@contractspec/example.learning-journey-ui-coaching 1.57.0 → 1.58.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.
Files changed (87) hide show
  1. package/.turbo/turbo-build.log +58 -59
  2. package/.turbo/turbo-prebuild.log +1 -0
  3. package/CHANGELOG.md +18 -0
  4. package/dist/CoachingMiniApp.d.ts +4 -14
  5. package/dist/CoachingMiniApp.d.ts.map +1 -1
  6. package/dist/CoachingMiniApp.js +1056 -59
  7. package/dist/browser/CoachingMiniApp.js +1059 -0
  8. package/dist/browser/components/EngagementMeter.js +143 -0
  9. package/dist/browser/components/TipCard.js +89 -0
  10. package/dist/browser/components/TipFeed.js +90 -0
  11. package/dist/browser/components/index.js +320 -0
  12. package/dist/browser/docs/index.js +22 -0
  13. package/dist/browser/docs/learning-journey-ui-coaching.docblock.js +22 -0
  14. package/dist/browser/example.js +32 -0
  15. package/dist/browser/index.js +1118 -0
  16. package/dist/browser/views/Overview.js +303 -0
  17. package/dist/browser/views/Progress.js +344 -0
  18. package/dist/browser/views/Steps.js +159 -0
  19. package/dist/browser/views/Timeline.js +266 -0
  20. package/dist/browser/views/index.js +980 -0
  21. package/dist/components/EngagementMeter.d.ts +6 -15
  22. package/dist/components/EngagementMeter.d.ts.map +1 -1
  23. package/dist/components/EngagementMeter.js +143 -107
  24. package/dist/components/TipCard.d.ts +8 -18
  25. package/dist/components/TipCard.d.ts.map +1 -1
  26. package/dist/components/TipCard.js +86 -72
  27. package/dist/components/TipFeed.d.ts +7 -13
  28. package/dist/components/TipFeed.d.ts.map +1 -1
  29. package/dist/components/TipFeed.js +87 -62
  30. package/dist/components/index.d.ts +4 -4
  31. package/dist/components/index.d.ts.map +1 -0
  32. package/dist/components/index.js +320 -4
  33. package/dist/docs/index.d.ts +2 -1
  34. package/dist/docs/index.d.ts.map +1 -0
  35. package/dist/docs/index.js +23 -1
  36. package/dist/docs/learning-journey-ui-coaching.docblock.d.ts +2 -1
  37. package/dist/docs/learning-journey-ui-coaching.docblock.d.ts.map +1 -0
  38. package/dist/docs/learning-journey-ui-coaching.docblock.js +21 -18
  39. package/dist/example.d.ts +2 -6
  40. package/dist/example.d.ts.map +1 -1
  41. package/dist/example.js +31 -39
  42. package/dist/index.d.ts +6 -12
  43. package/dist/index.d.ts.map +1 -0
  44. package/dist/index.js +1119 -14
  45. package/dist/node/CoachingMiniApp.js +1059 -0
  46. package/dist/node/components/EngagementMeter.js +143 -0
  47. package/dist/node/components/TipCard.js +89 -0
  48. package/dist/node/components/TipFeed.js +90 -0
  49. package/dist/node/components/index.js +320 -0
  50. package/dist/node/docs/index.js +22 -0
  51. package/dist/node/docs/learning-journey-ui-coaching.docblock.js +22 -0
  52. package/dist/node/example.js +32 -0
  53. package/dist/node/index.js +1118 -0
  54. package/dist/node/views/Overview.js +303 -0
  55. package/dist/node/views/Progress.js +344 -0
  56. package/dist/node/views/Steps.js +159 -0
  57. package/dist/node/views/Timeline.js +266 -0
  58. package/dist/node/views/index.js +980 -0
  59. package/dist/views/Overview.d.ts +4 -13
  60. package/dist/views/Overview.d.ts.map +1 -1
  61. package/dist/views/Overview.js +301 -148
  62. package/dist/views/Progress.d.ts +3 -10
  63. package/dist/views/Progress.d.ts.map +1 -1
  64. package/dist/views/Progress.js +342 -112
  65. package/dist/views/Steps.d.ts +2 -11
  66. package/dist/views/Steps.d.ts.map +1 -1
  67. package/dist/views/Steps.js +157 -66
  68. package/dist/views/Timeline.d.ts +2 -10
  69. package/dist/views/Timeline.d.ts.map +1 -1
  70. package/dist/views/Timeline.js +264 -110
  71. package/dist/views/index.d.ts +5 -5
  72. package/dist/views/index.d.ts.map +1 -0
  73. package/dist/views/index.js +980 -5
  74. package/package.json +154 -38
  75. package/tsdown.config.js +1 -2
  76. package/.turbo/turbo-build$colon$bundle.log +0 -62
  77. package/dist/CoachingMiniApp.js.map +0 -1
  78. package/dist/components/EngagementMeter.js.map +0 -1
  79. package/dist/components/TipCard.js.map +0 -1
  80. package/dist/components/TipFeed.js.map +0 -1
  81. package/dist/docs/learning-journey-ui-coaching.docblock.js.map +0 -1
  82. package/dist/example.js.map +0 -1
  83. package/dist/views/Overview.js.map +0 -1
  84. package/dist/views/Progress.js.map +0 -1
  85. package/dist/views/Steps.js.map +0 -1
  86. package/dist/views/Timeline.js.map +0 -1
  87. package/tsconfig.tsbuildinfo +0 -1
@@ -0,0 +1,143 @@
1
+ // src/components/EngagementMeter.tsx
2
+ import { jsxDEV } from "react/jsx-dev-runtime";
3
+ "use client";
4
+ function EngagementMeter({
5
+ acknowledged,
6
+ actioned,
7
+ pending,
8
+ streak = 0
9
+ }) {
10
+ const total = acknowledged + actioned + pending;
11
+ const actionedPercent = total > 0 ? actioned / total * 100 : 0;
12
+ const acknowledgedPercent = total > 0 ? acknowledged / total * 100 : 0;
13
+ return /* @__PURE__ */ jsxDEV("div", {
14
+ className: "space-y-4",
15
+ children: [
16
+ /* @__PURE__ */ jsxDEV("div", {
17
+ className: "flex items-center justify-center",
18
+ children: /* @__PURE__ */ jsxDEV("div", {
19
+ className: "relative h-32 w-32",
20
+ children: [
21
+ /* @__PURE__ */ jsxDEV("svg", {
22
+ className: "h-full w-full -rotate-90",
23
+ viewBox: "0 0 100 100",
24
+ children: [
25
+ /* @__PURE__ */ jsxDEV("circle", {
26
+ cx: "50",
27
+ cy: "50",
28
+ r: "40",
29
+ fill: "none",
30
+ strokeWidth: "12",
31
+ className: "stroke-muted"
32
+ }, undefined, false, undefined, this),
33
+ /* @__PURE__ */ jsxDEV("circle", {
34
+ cx: "50",
35
+ cy: "50",
36
+ r: "40",
37
+ fill: "none",
38
+ strokeWidth: "12",
39
+ strokeLinecap: "round",
40
+ strokeDasharray: `${actionedPercent * 2.51} 251`,
41
+ className: "stroke-green-500 transition-all duration-500"
42
+ }, undefined, false, undefined, this),
43
+ /* @__PURE__ */ jsxDEV("circle", {
44
+ cx: "50",
45
+ cy: "50",
46
+ r: "40",
47
+ fill: "none",
48
+ strokeWidth: "12",
49
+ strokeLinecap: "round",
50
+ strokeDasharray: `${acknowledgedPercent * 2.51} 251`,
51
+ strokeDashoffset: `${-actionedPercent * 2.51}`,
52
+ className: "stroke-amber-500 transition-all duration-500"
53
+ }, undefined, false, undefined, this)
54
+ ]
55
+ }, undefined, true, undefined, this),
56
+ /* @__PURE__ */ jsxDEV("div", {
57
+ className: "absolute inset-0 flex flex-col items-center justify-center",
58
+ children: [
59
+ /* @__PURE__ */ jsxDEV("span", {
60
+ className: "text-2xl font-bold",
61
+ children: total
62
+ }, undefined, false, undefined, this),
63
+ /* @__PURE__ */ jsxDEV("span", {
64
+ className: "text-muted-foreground text-xs",
65
+ children: "tips"
66
+ }, undefined, false, undefined, this)
67
+ ]
68
+ }, undefined, true, undefined, this)
69
+ ]
70
+ }, undefined, true, undefined, this)
71
+ }, undefined, false, undefined, this),
72
+ /* @__PURE__ */ jsxDEV("div", {
73
+ className: "flex justify-center gap-4 text-sm",
74
+ children: [
75
+ /* @__PURE__ */ jsxDEV("div", {
76
+ className: "flex items-center gap-1.5",
77
+ children: [
78
+ /* @__PURE__ */ jsxDEV("div", {
79
+ className: "h-3 w-3 rounded-full bg-green-500"
80
+ }, undefined, false, undefined, this),
81
+ /* @__PURE__ */ jsxDEV("span", {
82
+ children: [
83
+ "Actioned (",
84
+ actioned,
85
+ ")"
86
+ ]
87
+ }, undefined, true, undefined, this)
88
+ ]
89
+ }, undefined, true, undefined, this),
90
+ /* @__PURE__ */ jsxDEV("div", {
91
+ className: "flex items-center gap-1.5",
92
+ children: [
93
+ /* @__PURE__ */ jsxDEV("div", {
94
+ className: "h-3 w-3 rounded-full bg-amber-500"
95
+ }, undefined, false, undefined, this),
96
+ /* @__PURE__ */ jsxDEV("span", {
97
+ children: [
98
+ "Acknowledged (",
99
+ acknowledged,
100
+ ")"
101
+ ]
102
+ }, undefined, true, undefined, this)
103
+ ]
104
+ }, undefined, true, undefined, this),
105
+ /* @__PURE__ */ jsxDEV("div", {
106
+ className: "flex items-center gap-1.5",
107
+ children: [
108
+ /* @__PURE__ */ jsxDEV("div", {
109
+ className: "bg-muted h-3 w-3 rounded-full"
110
+ }, undefined, false, undefined, this),
111
+ /* @__PURE__ */ jsxDEV("span", {
112
+ children: [
113
+ "Pending (",
114
+ pending,
115
+ ")"
116
+ ]
117
+ }, undefined, true, undefined, this)
118
+ ]
119
+ }, undefined, true, undefined, this)
120
+ ]
121
+ }, undefined, true, undefined, this),
122
+ streak > 0 && /* @__PURE__ */ jsxDEV("div", {
123
+ className: "flex items-center justify-center gap-2 rounded-lg bg-orange-500/10 px-4 py-2",
124
+ children: [
125
+ /* @__PURE__ */ jsxDEV("span", {
126
+ className: "text-xl",
127
+ children: "\uD83D\uDD25"
128
+ }, undefined, false, undefined, this),
129
+ /* @__PURE__ */ jsxDEV("span", {
130
+ className: "font-semibold text-orange-500",
131
+ children: [
132
+ streak,
133
+ " day engagement streak!"
134
+ ]
135
+ }, undefined, true, undefined, this)
136
+ ]
137
+ }, undefined, true, undefined, this)
138
+ ]
139
+ }, undefined, true, undefined, this);
140
+ }
141
+ export {
142
+ EngagementMeter
143
+ };
@@ -0,0 +1,89 @@
1
+ // src/components/TipCard.tsx
2
+ import { Button } from "@contractspec/lib.design-system";
3
+ import { Card, CardContent } from "@contractspec/lib.ui-kit-web/ui/card";
4
+ import { cn } from "@contractspec/lib.ui-kit-web/ui/utils";
5
+ import { jsxDEV } from "react/jsx-dev-runtime";
6
+ "use client";
7
+ var TIP_ICONS = {
8
+ cash_buffer_too_high: "\uD83D\uDCB0",
9
+ no_savings_goal: "\uD83C\uDFAF",
10
+ irregular_savings: "\uD83D\uDCC5",
11
+ noise_late_evening: "\uD83D\uDD07",
12
+ guest_frequency_high: "\uD83D\uDC65",
13
+ shared_space_conflicts: "\uD83C\uDFE0",
14
+ default: "\uD83D\uDCA1"
15
+ };
16
+ function TipCard({
17
+ step,
18
+ isCompleted,
19
+ isCurrent,
20
+ onComplete,
21
+ onDismiss
22
+ }) {
23
+ const tipId = step.metadata?.tipId ?? "default";
24
+ const icon = TIP_ICONS[tipId] ?? TIP_ICONS.default;
25
+ return /* @__PURE__ */ jsxDEV(Card, {
26
+ className: cn("transition-all", isCompleted && "opacity-60", isCurrent && "ring-2 ring-amber-500"),
27
+ children: /* @__PURE__ */ jsxDEV(CardContent, {
28
+ className: "p-4",
29
+ children: /* @__PURE__ */ jsxDEV("div", {
30
+ className: "flex gap-4",
31
+ children: [
32
+ /* @__PURE__ */ jsxDEV("div", {
33
+ className: cn("flex h-12 w-12 shrink-0 items-center justify-center rounded-xl text-2xl", isCompleted ? "bg-green-500/10" : isCurrent ? "bg-amber-500/10" : "bg-muted"),
34
+ children: isCompleted ? "✓" : icon
35
+ }, undefined, false, undefined, this),
36
+ /* @__PURE__ */ jsxDEV("div", {
37
+ className: "min-w-0 flex-1",
38
+ children: [
39
+ /* @__PURE__ */ jsxDEV("div", {
40
+ className: "flex items-start justify-between gap-2",
41
+ children: [
42
+ /* @__PURE__ */ jsxDEV("h4", {
43
+ className: "font-semibold",
44
+ children: step.title
45
+ }, undefined, false, undefined, this),
46
+ step.xpReward && /* @__PURE__ */ jsxDEV("span", {
47
+ className: cn("shrink-0 rounded-full px-2 py-0.5 text-xs font-semibold", isCompleted ? "bg-green-500/10 text-green-500" : "bg-amber-500/10 text-amber-500"),
48
+ children: [
49
+ "+",
50
+ step.xpReward,
51
+ " XP"
52
+ ]
53
+ }, undefined, true, undefined, this)
54
+ ]
55
+ }, undefined, true, undefined, this),
56
+ /* @__PURE__ */ jsxDEV("p", {
57
+ className: "text-muted-foreground mt-1 text-sm",
58
+ children: step.description
59
+ }, undefined, false, undefined, this),
60
+ !isCompleted && /* @__PURE__ */ jsxDEV("div", {
61
+ className: "mt-3 flex flex-wrap gap-2",
62
+ children: [
63
+ /* @__PURE__ */ jsxDEV(Button, {
64
+ size: "sm",
65
+ onClick: onComplete,
66
+ children: "Take Action"
67
+ }, undefined, false, undefined, this),
68
+ /* @__PURE__ */ jsxDEV(Button, {
69
+ variant: "outline",
70
+ size: "sm",
71
+ onClick: onDismiss,
72
+ children: "Dismiss"
73
+ }, undefined, false, undefined, this)
74
+ ]
75
+ }, undefined, true, undefined, this),
76
+ isCompleted && /* @__PURE__ */ jsxDEV("p", {
77
+ className: "mt-2 text-sm text-green-500",
78
+ children: "✓ Tip acknowledged"
79
+ }, undefined, false, undefined, this)
80
+ ]
81
+ }, undefined, true, undefined, this)
82
+ ]
83
+ }, undefined, true, undefined, this)
84
+ }, undefined, false, undefined, this)
85
+ }, undefined, false, undefined, this);
86
+ }
87
+ export {
88
+ TipCard
89
+ };
@@ -0,0 +1,90 @@
1
+ // src/components/TipFeed.tsx
2
+ import { cn } from "@contractspec/lib.ui-kit-web/ui/utils";
3
+ import { jsxDEV } from "react/jsx-dev-runtime";
4
+ "use client";
5
+ var TIP_ICONS = {
6
+ cash_buffer_too_high: "\uD83D\uDCB0",
7
+ no_savings_goal: "\uD83C\uDFAF",
8
+ irregular_savings: "\uD83D\uDCC5",
9
+ noise_late_evening: "\uD83D\uDD07",
10
+ guest_frequency_high: "\uD83D\uDC65",
11
+ shared_space_conflicts: "\uD83C\uDFE0",
12
+ default: "\uD83D\uDCA1"
13
+ };
14
+ function TipFeed({ items }) {
15
+ if (items.length === 0) {
16
+ return /* @__PURE__ */ jsxDEV("div", {
17
+ className: "text-muted-foreground py-8 text-center",
18
+ children: "No tips yet. Start engaging with coaching tips!"
19
+ }, undefined, false, undefined, this);
20
+ }
21
+ return /* @__PURE__ */ jsxDEV("div", {
22
+ className: "relative",
23
+ children: [
24
+ /* @__PURE__ */ jsxDEV("div", {
25
+ className: "bg-border absolute top-0 left-4 h-full w-0.5"
26
+ }, undefined, false, undefined, this),
27
+ /* @__PURE__ */ jsxDEV("div", {
28
+ className: "space-y-4",
29
+ children: items.map((item) => {
30
+ const tipId = item.step.metadata?.tipId ?? "default";
31
+ const icon = TIP_ICONS[tipId] ?? TIP_ICONS.default;
32
+ return /* @__PURE__ */ jsxDEV("div", {
33
+ className: "relative flex gap-4 pl-2",
34
+ children: [
35
+ /* @__PURE__ */ jsxDEV("div", {
36
+ className: cn("relative z-10 flex h-8 w-8 shrink-0 items-center justify-center rounded-full text-sm", item.isCompleted ? "bg-green-500 text-white" : "bg-muted text-muted-foreground"),
37
+ children: item.isCompleted ? "✓" : icon
38
+ }, undefined, false, undefined, this),
39
+ /* @__PURE__ */ jsxDEV("div", {
40
+ className: "bg-card flex-1 rounded-lg border p-3",
41
+ children: [
42
+ /* @__PURE__ */ jsxDEV("div", {
43
+ className: "flex items-start justify-between gap-2",
44
+ children: [
45
+ /* @__PURE__ */ jsxDEV("div", {
46
+ children: [
47
+ /* @__PURE__ */ jsxDEV("p", {
48
+ className: "font-medium",
49
+ children: item.step.title
50
+ }, undefined, false, undefined, this),
51
+ /* @__PURE__ */ jsxDEV("p", {
52
+ className: "text-muted-foreground mt-0.5 text-sm",
53
+ children: item.step.description
54
+ }, undefined, false, undefined, this)
55
+ ]
56
+ }, undefined, true, undefined, this),
57
+ item.step.xpReward && /* @__PURE__ */ jsxDEV("span", {
58
+ className: cn("shrink-0 text-xs font-medium", item.isCompleted ? "text-green-500" : "text-muted-foreground"),
59
+ children: [
60
+ "+",
61
+ item.step.xpReward,
62
+ " XP"
63
+ ]
64
+ }, undefined, true, undefined, this)
65
+ ]
66
+ }, undefined, true, undefined, this),
67
+ /* @__PURE__ */ jsxDEV("div", {
68
+ className: "text-muted-foreground mt-2 flex items-center gap-2 text-xs",
69
+ children: item.isCompleted ? /* @__PURE__ */ jsxDEV("span", {
70
+ className: "text-green-500",
71
+ children: [
72
+ "✓ Completed",
73
+ item.completedAt && ` • ${item.completedAt}`
74
+ ]
75
+ }, undefined, true, undefined, this) : /* @__PURE__ */ jsxDEV("span", {
76
+ children: "Pending action"
77
+ }, undefined, false, undefined, this)
78
+ }, undefined, false, undefined, this)
79
+ ]
80
+ }, undefined, true, undefined, this)
81
+ ]
82
+ }, item.step.id, true, undefined, this);
83
+ })
84
+ }, undefined, false, undefined, this)
85
+ ]
86
+ }, undefined, true, undefined, this);
87
+ }
88
+ export {
89
+ TipFeed
90
+ };
@@ -0,0 +1,320 @@
1
+ // src/components/TipCard.tsx
2
+ import { Button } from "@contractspec/lib.design-system";
3
+ import { Card, CardContent } from "@contractspec/lib.ui-kit-web/ui/card";
4
+ import { cn } from "@contractspec/lib.ui-kit-web/ui/utils";
5
+ import { jsxDEV } from "react/jsx-dev-runtime";
6
+ "use client";
7
+ var TIP_ICONS = {
8
+ cash_buffer_too_high: "\uD83D\uDCB0",
9
+ no_savings_goal: "\uD83C\uDFAF",
10
+ irregular_savings: "\uD83D\uDCC5",
11
+ noise_late_evening: "\uD83D\uDD07",
12
+ guest_frequency_high: "\uD83D\uDC65",
13
+ shared_space_conflicts: "\uD83C\uDFE0",
14
+ default: "\uD83D\uDCA1"
15
+ };
16
+ function TipCard({
17
+ step,
18
+ isCompleted,
19
+ isCurrent,
20
+ onComplete,
21
+ onDismiss
22
+ }) {
23
+ const tipId = step.metadata?.tipId ?? "default";
24
+ const icon = TIP_ICONS[tipId] ?? TIP_ICONS.default;
25
+ return /* @__PURE__ */ jsxDEV(Card, {
26
+ className: cn("transition-all", isCompleted && "opacity-60", isCurrent && "ring-2 ring-amber-500"),
27
+ children: /* @__PURE__ */ jsxDEV(CardContent, {
28
+ className: "p-4",
29
+ children: /* @__PURE__ */ jsxDEV("div", {
30
+ className: "flex gap-4",
31
+ children: [
32
+ /* @__PURE__ */ jsxDEV("div", {
33
+ className: cn("flex h-12 w-12 shrink-0 items-center justify-center rounded-xl text-2xl", isCompleted ? "bg-green-500/10" : isCurrent ? "bg-amber-500/10" : "bg-muted"),
34
+ children: isCompleted ? "✓" : icon
35
+ }, undefined, false, undefined, this),
36
+ /* @__PURE__ */ jsxDEV("div", {
37
+ className: "min-w-0 flex-1",
38
+ children: [
39
+ /* @__PURE__ */ jsxDEV("div", {
40
+ className: "flex items-start justify-between gap-2",
41
+ children: [
42
+ /* @__PURE__ */ jsxDEV("h4", {
43
+ className: "font-semibold",
44
+ children: step.title
45
+ }, undefined, false, undefined, this),
46
+ step.xpReward && /* @__PURE__ */ jsxDEV("span", {
47
+ className: cn("shrink-0 rounded-full px-2 py-0.5 text-xs font-semibold", isCompleted ? "bg-green-500/10 text-green-500" : "bg-amber-500/10 text-amber-500"),
48
+ children: [
49
+ "+",
50
+ step.xpReward,
51
+ " XP"
52
+ ]
53
+ }, undefined, true, undefined, this)
54
+ ]
55
+ }, undefined, true, undefined, this),
56
+ /* @__PURE__ */ jsxDEV("p", {
57
+ className: "text-muted-foreground mt-1 text-sm",
58
+ children: step.description
59
+ }, undefined, false, undefined, this),
60
+ !isCompleted && /* @__PURE__ */ jsxDEV("div", {
61
+ className: "mt-3 flex flex-wrap gap-2",
62
+ children: [
63
+ /* @__PURE__ */ jsxDEV(Button, {
64
+ size: "sm",
65
+ onClick: onComplete,
66
+ children: "Take Action"
67
+ }, undefined, false, undefined, this),
68
+ /* @__PURE__ */ jsxDEV(Button, {
69
+ variant: "outline",
70
+ size: "sm",
71
+ onClick: onDismiss,
72
+ children: "Dismiss"
73
+ }, undefined, false, undefined, this)
74
+ ]
75
+ }, undefined, true, undefined, this),
76
+ isCompleted && /* @__PURE__ */ jsxDEV("p", {
77
+ className: "mt-2 text-sm text-green-500",
78
+ children: "✓ Tip acknowledged"
79
+ }, undefined, false, undefined, this)
80
+ ]
81
+ }, undefined, true, undefined, this)
82
+ ]
83
+ }, undefined, true, undefined, this)
84
+ }, undefined, false, undefined, this)
85
+ }, undefined, false, undefined, this);
86
+ }
87
+
88
+ // src/components/EngagementMeter.tsx
89
+ import { jsxDEV as jsxDEV2 } from "react/jsx-dev-runtime";
90
+ "use client";
91
+ function EngagementMeter({
92
+ acknowledged,
93
+ actioned,
94
+ pending,
95
+ streak = 0
96
+ }) {
97
+ const total = acknowledged + actioned + pending;
98
+ const actionedPercent = total > 0 ? actioned / total * 100 : 0;
99
+ const acknowledgedPercent = total > 0 ? acknowledged / total * 100 : 0;
100
+ return /* @__PURE__ */ jsxDEV2("div", {
101
+ className: "space-y-4",
102
+ children: [
103
+ /* @__PURE__ */ jsxDEV2("div", {
104
+ className: "flex items-center justify-center",
105
+ children: /* @__PURE__ */ jsxDEV2("div", {
106
+ className: "relative h-32 w-32",
107
+ children: [
108
+ /* @__PURE__ */ jsxDEV2("svg", {
109
+ className: "h-full w-full -rotate-90",
110
+ viewBox: "0 0 100 100",
111
+ children: [
112
+ /* @__PURE__ */ jsxDEV2("circle", {
113
+ cx: "50",
114
+ cy: "50",
115
+ r: "40",
116
+ fill: "none",
117
+ strokeWidth: "12",
118
+ className: "stroke-muted"
119
+ }, undefined, false, undefined, this),
120
+ /* @__PURE__ */ jsxDEV2("circle", {
121
+ cx: "50",
122
+ cy: "50",
123
+ r: "40",
124
+ fill: "none",
125
+ strokeWidth: "12",
126
+ strokeLinecap: "round",
127
+ strokeDasharray: `${actionedPercent * 2.51} 251`,
128
+ className: "stroke-green-500 transition-all duration-500"
129
+ }, undefined, false, undefined, this),
130
+ /* @__PURE__ */ jsxDEV2("circle", {
131
+ cx: "50",
132
+ cy: "50",
133
+ r: "40",
134
+ fill: "none",
135
+ strokeWidth: "12",
136
+ strokeLinecap: "round",
137
+ strokeDasharray: `${acknowledgedPercent * 2.51} 251`,
138
+ strokeDashoffset: `${-actionedPercent * 2.51}`,
139
+ className: "stroke-amber-500 transition-all duration-500"
140
+ }, undefined, false, undefined, this)
141
+ ]
142
+ }, undefined, true, undefined, this),
143
+ /* @__PURE__ */ jsxDEV2("div", {
144
+ className: "absolute inset-0 flex flex-col items-center justify-center",
145
+ children: [
146
+ /* @__PURE__ */ jsxDEV2("span", {
147
+ className: "text-2xl font-bold",
148
+ children: total
149
+ }, undefined, false, undefined, this),
150
+ /* @__PURE__ */ jsxDEV2("span", {
151
+ className: "text-muted-foreground text-xs",
152
+ children: "tips"
153
+ }, undefined, false, undefined, this)
154
+ ]
155
+ }, undefined, true, undefined, this)
156
+ ]
157
+ }, undefined, true, undefined, this)
158
+ }, undefined, false, undefined, this),
159
+ /* @__PURE__ */ jsxDEV2("div", {
160
+ className: "flex justify-center gap-4 text-sm",
161
+ children: [
162
+ /* @__PURE__ */ jsxDEV2("div", {
163
+ className: "flex items-center gap-1.5",
164
+ children: [
165
+ /* @__PURE__ */ jsxDEV2("div", {
166
+ className: "h-3 w-3 rounded-full bg-green-500"
167
+ }, undefined, false, undefined, this),
168
+ /* @__PURE__ */ jsxDEV2("span", {
169
+ children: [
170
+ "Actioned (",
171
+ actioned,
172
+ ")"
173
+ ]
174
+ }, undefined, true, undefined, this)
175
+ ]
176
+ }, undefined, true, undefined, this),
177
+ /* @__PURE__ */ jsxDEV2("div", {
178
+ className: "flex items-center gap-1.5",
179
+ children: [
180
+ /* @__PURE__ */ jsxDEV2("div", {
181
+ className: "h-3 w-3 rounded-full bg-amber-500"
182
+ }, undefined, false, undefined, this),
183
+ /* @__PURE__ */ jsxDEV2("span", {
184
+ children: [
185
+ "Acknowledged (",
186
+ acknowledged,
187
+ ")"
188
+ ]
189
+ }, undefined, true, undefined, this)
190
+ ]
191
+ }, undefined, true, undefined, this),
192
+ /* @__PURE__ */ jsxDEV2("div", {
193
+ className: "flex items-center gap-1.5",
194
+ children: [
195
+ /* @__PURE__ */ jsxDEV2("div", {
196
+ className: "bg-muted h-3 w-3 rounded-full"
197
+ }, undefined, false, undefined, this),
198
+ /* @__PURE__ */ jsxDEV2("span", {
199
+ children: [
200
+ "Pending (",
201
+ pending,
202
+ ")"
203
+ ]
204
+ }, undefined, true, undefined, this)
205
+ ]
206
+ }, undefined, true, undefined, this)
207
+ ]
208
+ }, undefined, true, undefined, this),
209
+ streak > 0 && /* @__PURE__ */ jsxDEV2("div", {
210
+ className: "flex items-center justify-center gap-2 rounded-lg bg-orange-500/10 px-4 py-2",
211
+ children: [
212
+ /* @__PURE__ */ jsxDEV2("span", {
213
+ className: "text-xl",
214
+ children: "\uD83D\uDD25"
215
+ }, undefined, false, undefined, this),
216
+ /* @__PURE__ */ jsxDEV2("span", {
217
+ className: "font-semibold text-orange-500",
218
+ children: [
219
+ streak,
220
+ " day engagement streak!"
221
+ ]
222
+ }, undefined, true, undefined, this)
223
+ ]
224
+ }, undefined, true, undefined, this)
225
+ ]
226
+ }, undefined, true, undefined, this);
227
+ }
228
+
229
+ // src/components/TipFeed.tsx
230
+ import { cn as cn2 } from "@contractspec/lib.ui-kit-web/ui/utils";
231
+ import { jsxDEV as jsxDEV3 } from "react/jsx-dev-runtime";
232
+ "use client";
233
+ var TIP_ICONS2 = {
234
+ cash_buffer_too_high: "\uD83D\uDCB0",
235
+ no_savings_goal: "\uD83C\uDFAF",
236
+ irregular_savings: "\uD83D\uDCC5",
237
+ noise_late_evening: "\uD83D\uDD07",
238
+ guest_frequency_high: "\uD83D\uDC65",
239
+ shared_space_conflicts: "\uD83C\uDFE0",
240
+ default: "\uD83D\uDCA1"
241
+ };
242
+ function TipFeed({ items }) {
243
+ if (items.length === 0) {
244
+ return /* @__PURE__ */ jsxDEV3("div", {
245
+ className: "text-muted-foreground py-8 text-center",
246
+ children: "No tips yet. Start engaging with coaching tips!"
247
+ }, undefined, false, undefined, this);
248
+ }
249
+ return /* @__PURE__ */ jsxDEV3("div", {
250
+ className: "relative",
251
+ children: [
252
+ /* @__PURE__ */ jsxDEV3("div", {
253
+ className: "bg-border absolute top-0 left-4 h-full w-0.5"
254
+ }, undefined, false, undefined, this),
255
+ /* @__PURE__ */ jsxDEV3("div", {
256
+ className: "space-y-4",
257
+ children: items.map((item) => {
258
+ const tipId = item.step.metadata?.tipId ?? "default";
259
+ const icon = TIP_ICONS2[tipId] ?? TIP_ICONS2.default;
260
+ return /* @__PURE__ */ jsxDEV3("div", {
261
+ className: "relative flex gap-4 pl-2",
262
+ children: [
263
+ /* @__PURE__ */ jsxDEV3("div", {
264
+ className: cn2("relative z-10 flex h-8 w-8 shrink-0 items-center justify-center rounded-full text-sm", item.isCompleted ? "bg-green-500 text-white" : "bg-muted text-muted-foreground"),
265
+ children: item.isCompleted ? "✓" : icon
266
+ }, undefined, false, undefined, this),
267
+ /* @__PURE__ */ jsxDEV3("div", {
268
+ className: "bg-card flex-1 rounded-lg border p-3",
269
+ children: [
270
+ /* @__PURE__ */ jsxDEV3("div", {
271
+ className: "flex items-start justify-between gap-2",
272
+ children: [
273
+ /* @__PURE__ */ jsxDEV3("div", {
274
+ children: [
275
+ /* @__PURE__ */ jsxDEV3("p", {
276
+ className: "font-medium",
277
+ children: item.step.title
278
+ }, undefined, false, undefined, this),
279
+ /* @__PURE__ */ jsxDEV3("p", {
280
+ className: "text-muted-foreground mt-0.5 text-sm",
281
+ children: item.step.description
282
+ }, undefined, false, undefined, this)
283
+ ]
284
+ }, undefined, true, undefined, this),
285
+ item.step.xpReward && /* @__PURE__ */ jsxDEV3("span", {
286
+ className: cn2("shrink-0 text-xs font-medium", item.isCompleted ? "text-green-500" : "text-muted-foreground"),
287
+ children: [
288
+ "+",
289
+ item.step.xpReward,
290
+ " XP"
291
+ ]
292
+ }, undefined, true, undefined, this)
293
+ ]
294
+ }, undefined, true, undefined, this),
295
+ /* @__PURE__ */ jsxDEV3("div", {
296
+ className: "text-muted-foreground mt-2 flex items-center gap-2 text-xs",
297
+ children: item.isCompleted ? /* @__PURE__ */ jsxDEV3("span", {
298
+ className: "text-green-500",
299
+ children: [
300
+ "✓ Completed",
301
+ item.completedAt && ` • ${item.completedAt}`
302
+ ]
303
+ }, undefined, true, undefined, this) : /* @__PURE__ */ jsxDEV3("span", {
304
+ children: "Pending action"
305
+ }, undefined, false, undefined, this)
306
+ }, undefined, false, undefined, this)
307
+ ]
308
+ }, undefined, true, undefined, this)
309
+ ]
310
+ }, item.step.id, true, undefined, this);
311
+ })
312
+ }, undefined, false, undefined, this)
313
+ ]
314
+ }, undefined, true, undefined, this);
315
+ }
316
+ export {
317
+ TipFeed,
318
+ TipCard,
319
+ EngagementMeter
320
+ };
@@ -0,0 +1,22 @@
1
+ // src/docs/learning-journey-ui-coaching.docblock.ts
2
+ import { registerDocBlocks } from "@contractspec/lib.contracts/docs";
3
+ var blocks = [
4
+ {
5
+ id: "docs.examples.learning-journey-ui-coaching",
6
+ title: "Learning Journey UI — Coaching",
7
+ summary: "UI mini-app components for coaching: tips, engagement, progress.",
8
+ kind: "reference",
9
+ visibility: "public",
10
+ route: "/docs/examples/learning-journey-ui-coaching",
11
+ tags: ["learning", "ui", "coaching"],
12
+ body: `## Includes
13
+ - Coaching mini-app shell
14
+ - Views: overview, steps, progress, timeline
15
+ - Components: tip card, engagement meter, tip feed
16
+
17
+ ## Notes
18
+ - Compose using design system components.
19
+ - Keep accessibility and mobile-friendly tap targets.`
20
+ }
21
+ ];
22
+ registerDocBlocks(blocks);