@burdenoff/microfe-buildmyiq 2026.825.1 → 2026.828.1
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/dist/buildmyiq/components/TutorPanel.d.ts +13 -1
- package/dist/buildmyiq/components/TutorPanel.d.ts.map +1 -1
- package/dist/buildmyiq/components/TutorPanel.js +86 -71
- package/dist/buildmyiq/components/TutorPanel.js.map +1 -1
- package/dist/buildmyiq/hooks/useBuildmyiqApi.d.ts +34 -1
- package/dist/buildmyiq/hooks/useBuildmyiqApi.d.ts.map +1 -1
- package/dist/buildmyiq/hooks/useBuildmyiqApi.js +160 -123
- package/dist/buildmyiq/hooks/useBuildmyiqApi.js.map +1 -1
- package/dist/buildmyiq/pages/catalog/CourseDetailPage.d.ts.map +1 -1
- package/dist/buildmyiq/pages/catalog/CourseDetailPage.js +251 -209
- package/dist/buildmyiq/pages/catalog/CourseDetailPage.js.map +1 -1
- package/dist/buildmyiq/pages/learning/LessonPlayerPage.d.ts.map +1 -1
- package/dist/buildmyiq/pages/learning/LessonPlayerPage.js +135 -126
- package/dist/buildmyiq/pages/learning/LessonPlayerPage.js.map +1 -1
- package/dist/buildmyiq/pages/learning/MyLearningPage.d.ts.map +1 -1
- package/dist/buildmyiq/pages/learning/MyLearningPage.js +271 -137
- package/dist/buildmyiq/pages/learning/MyLearningPage.js.map +1 -1
- package/dist/buildmyiq/pages/submissions/SubmissionsPage.d.ts.map +1 -1
- package/dist/buildmyiq/pages/submissions/SubmissionsPage.js +293 -254
- package/dist/buildmyiq/pages/submissions/SubmissionsPage.js.map +1 -1
- package/package.json +1 -1
- package/dist/generated/global-operations.d.ts +0 -2
- package/dist/generated/global-operations.d.ts.map +0 -1
- package/dist/generated/wspace-operations.d.ts +0 -2
- package/dist/generated/wspace-operations.d.ts.map +0 -1
|
@@ -7,11 +7,23 @@
|
|
|
7
7
|
* (see `TutorService.retrieveGrounding` in wspace-buildmyiq-svc) — never an
|
|
8
8
|
* ungrounded chat completion. Continues the learner's own session for this
|
|
9
9
|
* lesson (multi-turn) via `useBuiMyTutorSessions` / `useBuiTutorAsk`.
|
|
10
|
+
*
|
|
11
|
+
* Each assistant turn carries the `groundingLessonIds` the answer was actually
|
|
12
|
+
* derived from; they are rendered as source chips so the learner can see which
|
|
13
|
+
* lesson content backs the answer instead of taking it on trust. Ids the caller
|
|
14
|
+
* cannot name are shown as-is rather than guessed at or hidden.
|
|
10
15
|
*/
|
|
11
16
|
interface TutorPanelProps {
|
|
12
17
|
lessonId: string;
|
|
13
18
|
lessonTitle: string;
|
|
19
|
+
/**
|
|
20
|
+
* Titles for the lessons the tutor may ground an answer in, keyed by lesson
|
|
21
|
+
* id — supplied by the host page, which has already loaded the course. Only
|
|
22
|
+
* used to LABEL the ids the server returned; a missing entry falls back to
|
|
23
|
+
* the raw id, never to an invented title.
|
|
24
|
+
*/
|
|
25
|
+
lessonTitlesById?: ReadonlyMap<string, string>;
|
|
14
26
|
}
|
|
15
|
-
export declare function TutorPanel({ lessonId, lessonTitle }: TutorPanelProps): import("react").JSX.Element;
|
|
27
|
+
export declare function TutorPanel({ lessonId, lessonTitle, lessonTitlesById }: TutorPanelProps): import("react").JSX.Element;
|
|
16
28
|
export {};
|
|
17
29
|
//# sourceMappingURL=TutorPanel.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TutorPanel.d.ts","sourceRoot":"","sources":["../../../src/buildmyiq/components/TutorPanel.tsx"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"TutorPanel.d.ts","sourceRoot":"","sources":["../../../src/buildmyiq/components/TutorPanel.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAWH,UAAU,eAAe;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChD;AAmBD,wBAAgB,UAAU,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,gBAAgB,EAAE,EAAE,eAAe,+BAkKtF"}
|
|
@@ -1,142 +1,157 @@
|
|
|
1
1
|
import { useBuildmyiq as e } from "../context/BuildmyiqContext.js";
|
|
2
2
|
import "../context/index.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { useTr as t } from "../shared/hooks/useTr.js";
|
|
4
|
+
import { LoadingView as n } from "./StateViews.js";
|
|
5
|
+
import { useBuiMyTutorSessions as r, useBuiTutorAsk as i } from "../hooks/useBuildmyiqApi.js";
|
|
5
6
|
import "../hooks/index.js";
|
|
6
|
-
import { useEffect as
|
|
7
|
-
import { Bot as
|
|
8
|
-
import { jsx as
|
|
9
|
-
import { Button as
|
|
7
|
+
import { useEffect as a, useRef as o, useState as s } from "react";
|
|
8
|
+
import { BookOpen as c, Bot as l, Send as u, Sparkles as d } from "lucide-react";
|
|
9
|
+
import { jsx as f, jsxs as p } from "react/jsx-runtime";
|
|
10
|
+
import { Button as m, GlassCard as h, Textarea as g } from "@burdenoff/fe-libs/ui";
|
|
10
11
|
//#region src/buildmyiq/components/TutorPanel.tsx
|
|
11
|
-
function
|
|
12
|
+
function _(e) {
|
|
12
13
|
let t = e.trim();
|
|
13
14
|
return t ? t[0].toUpperCase() : "?";
|
|
14
15
|
}
|
|
15
|
-
var
|
|
16
|
+
var v = {
|
|
16
17
|
STRUGGLING: "Extra step-by-step help — based on your recent scores",
|
|
17
18
|
ON_TRACK: "Standard depth",
|
|
18
19
|
ADVANCED: "Deeper dive — based on your recent scores"
|
|
19
20
|
};
|
|
20
|
-
function
|
|
21
|
+
function y(e) {
|
|
21
22
|
if (!e) return "You";
|
|
22
23
|
let t = [e.firstName, e.lastName].filter(Boolean).join(" ").trim();
|
|
23
24
|
return e.name || t || e.username || e.email || "You";
|
|
24
25
|
}
|
|
25
|
-
function
|
|
26
|
-
let { currentUser:
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
top:
|
|
26
|
+
function b({ lessonId: b, lessonTitle: x, lessonTitlesById: S }) {
|
|
27
|
+
let { currentUser: C } = e(), w = t(), T = r(b), E = i(), [D, O] = s(void 0), [k, A] = s(""), [j, M] = s(null), N = o(null), P = T.data?.[0], F = D ? T.data?.find((e) => e.id === D)?.messages ?? [] : P?.messages ?? [];
|
|
28
|
+
a(() => {
|
|
29
|
+
N.current?.scrollTo({
|
|
30
|
+
top: N.current.scrollHeight,
|
|
30
31
|
behavior: "smooth"
|
|
31
32
|
});
|
|
32
|
-
}, [
|
|
33
|
-
let
|
|
34
|
-
let e =
|
|
33
|
+
}, [F.length]);
|
|
34
|
+
let I = y(C), L = (e) => e === b ? x : S?.get(e) ?? e, R = async () => {
|
|
35
|
+
let e = k.trim();
|
|
35
36
|
if (e) {
|
|
36
|
-
|
|
37
|
+
M(null), A("");
|
|
37
38
|
try {
|
|
38
|
-
|
|
39
|
-
lessonId:
|
|
39
|
+
O((await E.mutateAsync({
|
|
40
|
+
lessonId: b,
|
|
40
41
|
question: e,
|
|
41
|
-
sessionId:
|
|
42
|
+
sessionId: D ?? P?.id
|
|
42
43
|
})).session.id);
|
|
43
44
|
} catch (t) {
|
|
44
|
-
|
|
45
|
+
M(t instanceof Error ? t.message : "The AI tutor is temporarily unavailable."), A(e);
|
|
45
46
|
}
|
|
46
47
|
}
|
|
47
48
|
};
|
|
48
|
-
return /* @__PURE__ */
|
|
49
|
+
return /* @__PURE__ */ p(h, {
|
|
49
50
|
treatment: "plain",
|
|
50
51
|
className: "flex flex-col overflow-hidden p-0",
|
|
51
52
|
children: [
|
|
52
|
-
/* @__PURE__ */
|
|
53
|
+
/* @__PURE__ */ p("div", {
|
|
53
54
|
className: "flex items-center gap-2 border-b border-border-seam px-4 py-3",
|
|
54
|
-
children: [/* @__PURE__ */
|
|
55
|
+
children: [/* @__PURE__ */ f("span", {
|
|
55
56
|
className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-[var(--color-accent-soft)]",
|
|
56
|
-
children: /* @__PURE__ */
|
|
57
|
-
}), /* @__PURE__ */
|
|
57
|
+
children: /* @__PURE__ */ f(d, { className: "h-4 w-4 text-[var(--color-accent-teal)]" })
|
|
58
|
+
}), /* @__PURE__ */ p("div", {
|
|
58
59
|
className: "min-w-0",
|
|
59
|
-
children: [/* @__PURE__ */
|
|
60
|
+
children: [/* @__PURE__ */ f("p", {
|
|
60
61
|
className: "text-sm font-semibold text-text-primary",
|
|
61
62
|
children: "AI Tutor"
|
|
62
|
-
}), /* @__PURE__ */
|
|
63
|
+
}), /* @__PURE__ */ p("p", {
|
|
63
64
|
className: "truncate text-xs text-text-secondary",
|
|
64
65
|
children: [
|
|
65
66
|
"Grounded in “",
|
|
66
|
-
|
|
67
|
+
x,
|
|
67
68
|
"”"
|
|
68
69
|
]
|
|
69
70
|
})]
|
|
70
71
|
})]
|
|
71
72
|
}),
|
|
72
|
-
/* @__PURE__ */
|
|
73
|
-
ref:
|
|
73
|
+
/* @__PURE__ */ f("div", {
|
|
74
|
+
ref: N,
|
|
74
75
|
className: "max-h-96 min-h-40 flex-1 overflow-y-auto px-4 py-4",
|
|
75
|
-
children:
|
|
76
|
+
children: T.isLoading ? /* @__PURE__ */ f(n, { label: "Loading your tutor conversation…" }) : F.length === 0 ? /* @__PURE__ */ p("div", {
|
|
76
77
|
className: "flex flex-col items-center gap-2 py-6 text-center",
|
|
77
|
-
children: [/* @__PURE__ */
|
|
78
|
+
children: [/* @__PURE__ */ f(l, { className: "h-8 w-8 text-text-tertiary" }), /* @__PURE__ */ f("p", {
|
|
78
79
|
className: "text-sm text-text-secondary",
|
|
79
80
|
children: "Ask a question about this lesson — the tutor answers from the lesson content, with hints first."
|
|
80
81
|
})]
|
|
81
|
-
}) : /* @__PURE__ */
|
|
82
|
+
}) : /* @__PURE__ */ p("ul", {
|
|
82
83
|
className: "flex flex-col gap-4",
|
|
83
|
-
children: [
|
|
84
|
+
children: [F.map((e) => {
|
|
84
85
|
let t = e.role === "ASSISTANT";
|
|
85
|
-
return /* @__PURE__ */
|
|
86
|
+
return /* @__PURE__ */ p("li", {
|
|
86
87
|
className: "flex gap-3",
|
|
87
|
-
children: [/* @__PURE__ */
|
|
88
|
+
children: [/* @__PURE__ */ f("div", {
|
|
88
89
|
className: t ? "flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-[var(--color-accent-soft)]" : "flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-bg-sunken text-sm font-semibold text-text-secondary",
|
|
89
|
-
children: t ? /* @__PURE__ */
|
|
90
|
-
}), /* @__PURE__ */
|
|
90
|
+
children: t ? /* @__PURE__ */ f(l, { className: "h-4 w-4 text-[var(--color-accent-teal)]" }) : _(I)
|
|
91
|
+
}), /* @__PURE__ */ p("div", {
|
|
91
92
|
className: "min-w-0 flex-1",
|
|
92
|
-
children: [
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
93
|
+
children: [
|
|
94
|
+
/* @__PURE__ */ p("div", {
|
|
95
|
+
className: "flex flex-wrap items-baseline gap-x-2",
|
|
96
|
+
children: [/* @__PURE__ */ f("span", {
|
|
97
|
+
className: "text-sm font-semibold text-text-primary",
|
|
98
|
+
children: t ? "AI Tutor" : I
|
|
99
|
+
}), t && e.adaptiveLevel && /* @__PURE__ */ f("span", {
|
|
100
|
+
className: "text-xs text-text-tertiary",
|
|
101
|
+
children: v[e.adaptiveLevel]
|
|
102
|
+
})]
|
|
103
|
+
}),
|
|
104
|
+
/* @__PURE__ */ f("p", {
|
|
105
|
+
className: "mt-0.5 whitespace-pre-wrap break-words text-sm text-text-secondary",
|
|
106
|
+
children: e.content
|
|
107
|
+
}),
|
|
108
|
+
t && e.groundingLessonIds.length > 0 && /* @__PURE__ */ p("div", {
|
|
109
|
+
className: "mt-2 flex flex-wrap items-center gap-1.5",
|
|
110
|
+
children: [/* @__PURE__ */ p("span", {
|
|
111
|
+
className: "inline-flex items-center gap-1 text-xs text-text-tertiary",
|
|
112
|
+
children: [/* @__PURE__ */ f(c, { className: "h-3.5 w-3.5" }), w("buildmyiq.tutor.groundedIn", "Answered from")]
|
|
113
|
+
}), e.groundingLessonIds.map((e) => /* @__PURE__ */ f("span", {
|
|
114
|
+
title: e,
|
|
115
|
+
className: "max-w-[14rem] truncate rounded-full bg-bg-sunken px-2 py-0.5 text-xs text-text-secondary",
|
|
116
|
+
children: L(e)
|
|
117
|
+
}, e))]
|
|
118
|
+
})
|
|
119
|
+
]
|
|
105
120
|
})]
|
|
106
121
|
}, e.id);
|
|
107
|
-
}),
|
|
122
|
+
}), E.isPending && /* @__PURE__ */ p("li", {
|
|
108
123
|
className: "flex items-center gap-3",
|
|
109
|
-
children: [/* @__PURE__ */
|
|
124
|
+
children: [/* @__PURE__ */ f("span", {
|
|
110
125
|
className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-[var(--color-accent-soft)]",
|
|
111
|
-
children: /* @__PURE__ */
|
|
112
|
-
}), /* @__PURE__ */
|
|
126
|
+
children: /* @__PURE__ */ f(l, { className: "h-4 w-4 animate-pulse text-[var(--color-accent-teal)]" })
|
|
127
|
+
}), /* @__PURE__ */ f("span", {
|
|
113
128
|
className: "text-sm text-text-secondary",
|
|
114
129
|
children: "Thinking…"
|
|
115
130
|
})]
|
|
116
131
|
})]
|
|
117
132
|
})
|
|
118
133
|
}),
|
|
119
|
-
/* @__PURE__ */
|
|
134
|
+
/* @__PURE__ */ p("div", {
|
|
120
135
|
className: "border-t border-border-seam p-3",
|
|
121
|
-
children: [/* @__PURE__ */
|
|
122
|
-
value:
|
|
123
|
-
onChange: (e) =>
|
|
136
|
+
children: [/* @__PURE__ */ f(g, {
|
|
137
|
+
value: k,
|
|
138
|
+
onChange: (e) => A(e.target.value),
|
|
124
139
|
onKeyDown: (e) => {
|
|
125
|
-
e.key === "Enter" && !e.shiftKey && (e.preventDefault(),
|
|
140
|
+
e.key === "Enter" && !e.shiftKey && (e.preventDefault(), R());
|
|
126
141
|
},
|
|
127
142
|
placeholder: "Ask about this lesson…",
|
|
128
143
|
rows: 2,
|
|
129
|
-
disabled:
|
|
130
|
-
}), /* @__PURE__ */
|
|
144
|
+
disabled: E.isPending
|
|
145
|
+
}), /* @__PURE__ */ p("div", {
|
|
131
146
|
className: "mt-2 flex items-center justify-end gap-2",
|
|
132
|
-
children: [
|
|
147
|
+
children: [j && /* @__PURE__ */ f("span", {
|
|
133
148
|
className: "mr-auto text-xs text-status-error-text",
|
|
134
|
-
children:
|
|
135
|
-
}), /* @__PURE__ */
|
|
149
|
+
children: j
|
|
150
|
+
}), /* @__PURE__ */ p(m, {
|
|
136
151
|
size: "sm",
|
|
137
|
-
onClick:
|
|
138
|
-
disabled: !
|
|
139
|
-
children: [/* @__PURE__ */ u
|
|
152
|
+
onClick: R,
|
|
153
|
+
disabled: !k.trim() || E.isPending,
|
|
154
|
+
children: [/* @__PURE__ */ f(u, { className: "mr-1.5 h-4 w-4" }), E.isPending ? "Asking…" : "Ask"]
|
|
140
155
|
})]
|
|
141
156
|
})]
|
|
142
157
|
})
|
|
@@ -144,6 +159,6 @@ function v({ lessonId: v, lessonTitle: y }) {
|
|
|
144
159
|
});
|
|
145
160
|
}
|
|
146
161
|
//#endregion
|
|
147
|
-
export {
|
|
162
|
+
export { b as TutorPanel };
|
|
148
163
|
|
|
149
164
|
//# sourceMappingURL=TutorPanel.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TutorPanel.js","names":[],"sources":["../../../src/buildmyiq/components/TutorPanel.tsx"],"sourcesContent":["/**\n * TutorPanel — the 24/7 AI tutor chat for a lesson (BOFF-4426).\n * @module buildmyiq/components/TutorPanel\n *\n * Grounded Q&A: every assistant answer comes from `buiTutorAsk`, which\n * retrieves the actual lesson content server-side before calling the model\n * (see `TutorService.retrieveGrounding` in wspace-buildmyiq-svc) — never an\n * ungrounded chat completion. Continues the learner's own session for this\n * lesson (multi-turn) via `useBuiMyTutorSessions` / `useBuiTutorAsk`.\n */\n\nimport { useEffect, useRef, useState } from 'react';\nimport { Bot, Send, Sparkles } from 'lucide-react';\nimport { Button, GlassCard, Textarea } from '@burdenoff/fe-libs/ui';\nimport { LoadingView } from './StateViews';\nimport { useBuiMyTutorSessions, useBuiTutorAsk } from '../hooks';\nimport { useBuildmyiq } from '../context';\nimport type { BuiTutorAdaptiveLevel, BuiTutorMessage } from '../types';\n\ninterface TutorPanelProps {\n lessonId: string;\n lessonTitle: string;\n}\n\nfunction initialFor(label: string): string {\n const trimmed = label.trim();\n return trimmed ? trimmed[0]!.toUpperCase() : '?';\n}\n\nconst ADAPTIVE_LABEL: Record<BuiTutorAdaptiveLevel, string> = {\n STRUGGLING: 'Extra step-by-step help — based on your recent scores',\n ON_TRACK: 'Standard depth',\n ADVANCED: 'Deeper dive — based on your recent scores',\n};\n\nfunction displayName(user: ReturnType<typeof useBuildmyiq>['currentUser']): string {\n if (!user) return 'You';\n const full = [user.firstName, user.lastName].filter(Boolean).join(' ').trim();\n return user.name || full || user.username || user.email || 'You';\n}\n\nexport function TutorPanel({ lessonId, lessonTitle }: TutorPanelProps) {\n const { currentUser } = useBuildmyiq();\n const sessionsQuery = useBuiMyTutorSessions(lessonId);\n const ask = useBuiTutorAsk();\n\n const [sessionId, setSessionId] = useState<string | undefined>(undefined);\n const [draft, setDraft] = useState('');\n const [error, setError] = useState<string | null>(null);\n const scrollRef = useRef<HTMLDivElement>(null);\n\n // Resume the learner's most recently active session for this lesson, if any.\n const existingSession = sessionsQuery.data?.[0];\n const messages: BuiTutorMessage[] = sessionId\n ? (sessionsQuery.data?.find((s) => s.id === sessionId)?.messages ?? [])\n : (existingSession?.messages ?? []);\n\n useEffect(() => {\n scrollRef.current?.scrollTo({ top: scrollRef.current.scrollHeight, behavior: 'smooth' });\n }, [messages.length]);\n\n const selfName = displayName(currentUser);\n\n const handleAsk = async () => {\n const question = draft.trim();\n if (!question) return;\n setError(null);\n setDraft('');\n try {\n const result = await ask.mutateAsync({\n lessonId,\n question,\n sessionId: sessionId ?? existingSession?.id,\n });\n setSessionId(result.session.id);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'The AI tutor is temporarily unavailable.');\n setDraft(question);\n }\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n void handleAsk();\n }\n };\n\n return (\n <GlassCard treatment=\"plain\" className=\"flex flex-col overflow-hidden p-0\">\n <div className=\"flex items-center gap-2 border-b border-border-seam px-4 py-3\">\n <span className=\"flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-[var(--color-accent-soft)]\">\n <Sparkles className=\"h-4 w-4 text-[var(--color-accent-teal)]\" />\n </span>\n <div className=\"min-w-0\">\n <p className=\"text-sm font-semibold text-text-primary\">AI Tutor</p>\n <p className=\"truncate text-xs text-text-secondary\">Grounded in “{lessonTitle}”</p>\n </div>\n </div>\n\n <div ref={scrollRef} className=\"max-h-96 min-h-40 flex-1 overflow-y-auto px-4 py-4\">\n {sessionsQuery.isLoading ? (\n <LoadingView label=\"Loading your tutor conversation…\" />\n ) : messages.length === 0 ? (\n <div className=\"flex flex-col items-center gap-2 py-6 text-center\">\n <Bot className=\"h-8 w-8 text-text-tertiary\" />\n <p className=\"text-sm text-text-secondary\">\n Ask a question about this lesson — the tutor answers from the lesson content, with\n hints first.\n </p>\n </div>\n ) : (\n <ul className=\"flex flex-col gap-4\">\n {messages.map((message) => {\n const isAssistant = message.role === 'ASSISTANT';\n return (\n <li key={message.id} className=\"flex gap-3\">\n <div\n className={\n isAssistant\n ? 'flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-[var(--color-accent-soft)]'\n : 'flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-bg-sunken text-sm font-semibold text-text-secondary'\n }\n >\n {isAssistant ? (\n <Bot className=\"h-4 w-4 text-[var(--color-accent-teal)]\" />\n ) : (\n initialFor(selfName)\n )}\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-baseline gap-x-2\">\n <span className=\"text-sm font-semibold text-text-primary\">\n {isAssistant ? 'AI Tutor' : selfName}\n </span>\n {isAssistant && message.adaptiveLevel && (\n <span className=\"text-xs text-text-tertiary\">\n {ADAPTIVE_LABEL[message.adaptiveLevel]}\n </span>\n )}\n </div>\n <p className=\"mt-0.5 whitespace-pre-wrap break-words text-sm text-text-secondary\">\n {message.content}\n </p>\n </div>\n </li>\n );\n })}\n {ask.isPending && (\n <li className=\"flex items-center gap-3\">\n <span className=\"flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-[var(--color-accent-soft)]\">\n <Bot className=\"h-4 w-4 animate-pulse text-[var(--color-accent-teal)]\" />\n </span>\n <span className=\"text-sm text-text-secondary\">Thinking…</span>\n </li>\n )}\n </ul>\n )}\n </div>\n\n <div className=\"border-t border-border-seam p-3\">\n <Textarea\n value={draft}\n onChange={(e) => setDraft(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder=\"Ask about this lesson…\"\n rows={2}\n disabled={ask.isPending}\n />\n <div className=\"mt-2 flex items-center justify-end gap-2\">\n {error && <span className=\"mr-auto text-xs text-status-error-text\">{error}</span>}\n <Button size=\"sm\" onClick={handleAsk} disabled={!draft.trim() || ask.isPending}>\n <Send className=\"mr-1.5 h-4 w-4\" />\n {ask.isPending ? 'Asking…' : 'Ask'}\n </Button>\n </div>\n </div>\n </GlassCard>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TutorPanel.js","names":[],"sources":["../../../src/buildmyiq/components/TutorPanel.tsx"],"sourcesContent":["/**\n * TutorPanel — the 24/7 AI tutor chat for a lesson (BOFF-4426).\n * @module buildmyiq/components/TutorPanel\n *\n * Grounded Q&A: every assistant answer comes from `buiTutorAsk`, which\n * retrieves the actual lesson content server-side before calling the model\n * (see `TutorService.retrieveGrounding` in wspace-buildmyiq-svc) — never an\n * ungrounded chat completion. Continues the learner's own session for this\n * lesson (multi-turn) via `useBuiMyTutorSessions` / `useBuiTutorAsk`.\n *\n * Each assistant turn carries the `groundingLessonIds` the answer was actually\n * derived from; they are rendered as source chips so the learner can see which\n * lesson content backs the answer instead of taking it on trust. Ids the caller\n * cannot name are shown as-is rather than guessed at or hidden.\n */\n\nimport { useEffect, useRef, useState } from 'react';\nimport { Bot, BookOpen, Send, Sparkles } from 'lucide-react';\nimport { Button, GlassCard, Textarea } from '@burdenoff/fe-libs/ui';\nimport { LoadingView } from './StateViews';\nimport { useBuiMyTutorSessions, useBuiTutorAsk } from '../hooks';\nimport { useBuildmyiq } from '../context';\nimport { useTr } from '../shared/hooks/useTr';\nimport type { BuiTutorAdaptiveLevel, BuiTutorMessage } from '../types';\n\ninterface TutorPanelProps {\n lessonId: string;\n lessonTitle: string;\n /**\n * Titles for the lessons the tutor may ground an answer in, keyed by lesson\n * id — supplied by the host page, which has already loaded the course. Only\n * used to LABEL the ids the server returned; a missing entry falls back to\n * the raw id, never to an invented title.\n */\n lessonTitlesById?: ReadonlyMap<string, string>;\n}\n\nfunction initialFor(label: string): string {\n const trimmed = label.trim();\n return trimmed ? trimmed[0]!.toUpperCase() : '?';\n}\n\nconst ADAPTIVE_LABEL: Record<BuiTutorAdaptiveLevel, string> = {\n STRUGGLING: 'Extra step-by-step help — based on your recent scores',\n ON_TRACK: 'Standard depth',\n ADVANCED: 'Deeper dive — based on your recent scores',\n};\n\nfunction displayName(user: ReturnType<typeof useBuildmyiq>['currentUser']): string {\n if (!user) return 'You';\n const full = [user.firstName, user.lastName].filter(Boolean).join(' ').trim();\n return user.name || full || user.username || user.email || 'You';\n}\n\nexport function TutorPanel({ lessonId, lessonTitle, lessonTitlesById }: TutorPanelProps) {\n const { currentUser } = useBuildmyiq();\n const tr = useTr();\n const sessionsQuery = useBuiMyTutorSessions(lessonId);\n const ask = useBuiTutorAsk();\n\n const [sessionId, setSessionId] = useState<string | undefined>(undefined);\n const [draft, setDraft] = useState('');\n const [error, setError] = useState<string | null>(null);\n const scrollRef = useRef<HTMLDivElement>(null);\n\n // Resume the learner's most recently active session for this lesson, if any.\n const existingSession = sessionsQuery.data?.[0];\n const messages: BuiTutorMessage[] = sessionId\n ? (sessionsQuery.data?.find((s) => s.id === sessionId)?.messages ?? [])\n : (existingSession?.messages ?? []);\n\n useEffect(() => {\n scrollRef.current?.scrollTo({ top: scrollRef.current.scrollHeight, behavior: 'smooth' });\n }, [messages.length]);\n\n const selfName = displayName(currentUser);\n\n /** Label a grounding lesson id; an id we can't name is shown verbatim. */\n const groundingLabel = (id: string): string => {\n if (id === lessonId) return lessonTitle;\n return lessonTitlesById?.get(id) ?? id;\n };\n\n const handleAsk = async () => {\n const question = draft.trim();\n if (!question) return;\n setError(null);\n setDraft('');\n try {\n const result = await ask.mutateAsync({\n lessonId,\n question,\n sessionId: sessionId ?? existingSession?.id,\n });\n setSessionId(result.session.id);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'The AI tutor is temporarily unavailable.');\n setDraft(question);\n }\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n void handleAsk();\n }\n };\n\n return (\n <GlassCard treatment=\"plain\" className=\"flex flex-col overflow-hidden p-0\">\n <div className=\"flex items-center gap-2 border-b border-border-seam px-4 py-3\">\n <span className=\"flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-[var(--color-accent-soft)]\">\n <Sparkles className=\"h-4 w-4 text-[var(--color-accent-teal)]\" />\n </span>\n <div className=\"min-w-0\">\n <p className=\"text-sm font-semibold text-text-primary\">AI Tutor</p>\n <p className=\"truncate text-xs text-text-secondary\">Grounded in “{lessonTitle}”</p>\n </div>\n </div>\n\n <div ref={scrollRef} className=\"max-h-96 min-h-40 flex-1 overflow-y-auto px-4 py-4\">\n {sessionsQuery.isLoading ? (\n <LoadingView label=\"Loading your tutor conversation…\" />\n ) : messages.length === 0 ? (\n <div className=\"flex flex-col items-center gap-2 py-6 text-center\">\n <Bot className=\"h-8 w-8 text-text-tertiary\" />\n <p className=\"text-sm text-text-secondary\">\n Ask a question about this lesson — the tutor answers from the lesson content, with\n hints first.\n </p>\n </div>\n ) : (\n <ul className=\"flex flex-col gap-4\">\n {messages.map((message) => {\n const isAssistant = message.role === 'ASSISTANT';\n return (\n <li key={message.id} className=\"flex gap-3\">\n <div\n className={\n isAssistant\n ? 'flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-[var(--color-accent-soft)]'\n : 'flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-bg-sunken text-sm font-semibold text-text-secondary'\n }\n >\n {isAssistant ? (\n <Bot className=\"h-4 w-4 text-[var(--color-accent-teal)]\" />\n ) : (\n initialFor(selfName)\n )}\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex flex-wrap items-baseline gap-x-2\">\n <span className=\"text-sm font-semibold text-text-primary\">\n {isAssistant ? 'AI Tutor' : selfName}\n </span>\n {isAssistant && message.adaptiveLevel && (\n <span className=\"text-xs text-text-tertiary\">\n {ADAPTIVE_LABEL[message.adaptiveLevel]}\n </span>\n )}\n </div>\n <p className=\"mt-0.5 whitespace-pre-wrap break-words text-sm text-text-secondary\">\n {message.content}\n </p>\n {isAssistant && message.groundingLessonIds.length > 0 && (\n <div className=\"mt-2 flex flex-wrap items-center gap-1.5\">\n <span className=\"inline-flex items-center gap-1 text-xs text-text-tertiary\">\n <BookOpen className=\"h-3.5 w-3.5\" />\n {tr('buildmyiq.tutor.groundedIn', 'Answered from')}\n </span>\n {message.groundingLessonIds.map((groundingId) => (\n <span\n key={groundingId}\n title={groundingId}\n className=\"max-w-[14rem] truncate rounded-full bg-bg-sunken px-2 py-0.5 text-xs text-text-secondary\"\n >\n {groundingLabel(groundingId)}\n </span>\n ))}\n </div>\n )}\n </div>\n </li>\n );\n })}\n {ask.isPending && (\n <li className=\"flex items-center gap-3\">\n <span className=\"flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-[var(--color-accent-soft)]\">\n <Bot className=\"h-4 w-4 animate-pulse text-[var(--color-accent-teal)]\" />\n </span>\n <span className=\"text-sm text-text-secondary\">Thinking…</span>\n </li>\n )}\n </ul>\n )}\n </div>\n\n <div className=\"border-t border-border-seam p-3\">\n <Textarea\n value={draft}\n onChange={(e) => setDraft(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder=\"Ask about this lesson…\"\n rows={2}\n disabled={ask.isPending}\n />\n <div className=\"mt-2 flex items-center justify-end gap-2\">\n {error && <span className=\"mr-auto text-xs text-status-error-text\">{error}</span>}\n <Button size=\"sm\" onClick={handleAsk} disabled={!draft.trim() || ask.isPending}>\n <Send className=\"mr-1.5 h-4 w-4\" />\n {ask.isPending ? 'Asking…' : 'Ask'}\n </Button>\n </div>\n </div>\n </GlassCard>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BuiConnection, BuiCourse, BuiCourseLevel, BuiCourseStatus, BuiModule, BuiLesson, BuiAssessment, BuiAssessmentStatus, BuiQuestion, BuiSubmission, BuiSubmissionStatus, BuiEnrollment, BuiEnrollmentStatus, BuiCohort, BuiCohortStatus, BuiSkill, BuiSkillCategory, BuiSkillStandard, BuiCertification, BuiSkillMappingSuggestion, BuiCertificate, BuiLessonProgress, BuiCreateCourseInput, BuiUpdateCourseInput, BuiCreateModuleInput, BuiCreateLessonInput, BuiCreateAssessmentInput, BuiCreateQuestionInput, BuiCreateSkillInput, BuiCreateCohortInput, BuiEnrollInput, BuiRecordLessonProgressInput, BuiSubmitAssessmentInput, BuiGradeSubmissionInput, BuiIssueCertificateInput, BuiTutorAskInput, BuiTutorAskPayload, BuiTutorSession, BuiGradeSuggestion, BuiCourseOutlineSuggestion, BuiApplyCourseOutlineInput, BuiAdminCopilotAnswer, BuiAdminCopilotTurnInput, BuiAiSuggestionOutcome, BuiLtiPlatform, BuiRegisterLtiPlatformInput } from '../types';
|
|
1
|
+
import { BuiConnection, BuiCourse, BuiCourseLevel, BuiCourseStatus, BuiModule, BuiLesson, BuiAssessment, BuiAssessmentStatus, BuiQuestion, BuiSubmission, BuiSubmissionStatus, BuiEnrollment, BuiEnrollmentStatus, BuiCohort, BuiCohortStatus, BuiSkill, BuiSkillCategory, BuiSkillStandard, BuiCertification, BuiSkillMappingSuggestion, BuiCertificate, BuiLessonProgress, BuiCreateCourseInput, BuiUpdateCourseInput, BuiCreateModuleInput, BuiCreateLessonInput, BuiCreateAssessmentInput, BuiCreateQuestionInput, BuiCreateSkillInput, BuiCreateCohortInput, BuiEnrollInput, BuiRecordLessonProgressInput, BuiSubmitAssessmentInput, BuiGradeSubmissionInput, BuiIssueCertificateInput, BuiTutorAskInput, BuiTutorAskPayload, BuiTutorSession, BuiGradeSuggestion, BuiNextLessonSuggestion, BuiCourseOutlineSuggestion, BuiApplyCourseOutlineInput, BuiAdminCopilotAnswer, BuiAdminCopilotTurnInput, BuiAiSuggestionOutcome, BuiLtiPlatform, BuiRegisterLtiPlatformInput } from '../types';
|
|
2
2
|
export interface UseBuiCoursesArgs {
|
|
3
3
|
level?: BuiCourseLevel;
|
|
4
4
|
status?: BuiCourseStatus;
|
|
@@ -107,6 +107,16 @@ export declare const useBuiGradeSubmission: () => import('@tanstack/react-query'
|
|
|
107
107
|
id: string;
|
|
108
108
|
input: BuiGradeSubmissionInput;
|
|
109
109
|
}, unknown>;
|
|
110
|
+
/**
|
|
111
|
+
* Deterministically grades a submission whose assessment is made up ENTIRELY of
|
|
112
|
+
* objective questions (SINGLE_CHOICE / MULTIPLE_CHOICE / TRUE_FALSE) by
|
|
113
|
+
* comparing the learner's answers against each question's answer key — no LLM
|
|
114
|
+
* and no human judgement involved. Unlike `useBuiSuggestGrade` this DOES write
|
|
115
|
+
* the submission. The svc throws when the assessment contains any
|
|
116
|
+
* SHORT_ANSWER / ESSAY / CODE question; callers gate the action on the
|
|
117
|
+
* assessment's question types and surface the error honestly if it still fails.
|
|
118
|
+
*/
|
|
119
|
+
export declare const useBuiAutoScoreSubmission: () => import('@tanstack/react-query').UseMutationResult<BuiSubmission, Error, string, unknown>;
|
|
110
120
|
export interface UseBuiEnrollmentsArgs {
|
|
111
121
|
courseId?: string;
|
|
112
122
|
status?: BuiEnrollmentStatus;
|
|
@@ -123,6 +133,14 @@ export declare const useBuiEnrollments: (args?: UseBuiEnrollmentsArgs) => import
|
|
|
123
133
|
/** The signed-in learner's own enrollments (self-scoped, no learnerId arg). */
|
|
124
134
|
export declare const useBuiMyEnrollments: (args?: UseBuiEnrollmentsArgs) => import('@tanstack/react-query').UseQueryResult<NoInfer<BuiConnection<BuiEnrollment>>, Error>;
|
|
125
135
|
export declare const useBuiEnrollment: (id: string | undefined) => import('@tanstack/react-query').UseQueryResult<NoInfer<BuiEnrollment | null>, Error>;
|
|
136
|
+
/**
|
|
137
|
+
* The signed-in learner's OWN enrollment by id, with its full lesson-progress
|
|
138
|
+
* history. Self-scoped (`buiMyEnrollment`) — the resolver owner-filters by the
|
|
139
|
+
* authenticated actor and returns null for someone else's enrollment, so this
|
|
140
|
+
* is the read a learner-facing surface must use; `useBuiEnrollment` above is
|
|
141
|
+
* the workspace-scoped instructor/admin equivalent.
|
|
142
|
+
*/
|
|
143
|
+
export declare const useBuiMyEnrollment: (id: string | undefined) => import('@tanstack/react-query').UseQueryResult<NoInfer<BuiEnrollment | null>, Error>;
|
|
126
144
|
export declare const useBuiEnroll: () => import('@tanstack/react-query').UseMutationResult<BuiEnrollment, Error, BuiEnrollInput, unknown>;
|
|
127
145
|
export declare const useBuiTransitionEnrollment: () => import('@tanstack/react-query').UseMutationResult<BuiEnrollment, Error, {
|
|
128
146
|
id: string;
|
|
@@ -174,6 +192,21 @@ export declare const useBuiReviewGradeSuggestion: () => import('@tanstack/react-
|
|
|
174
192
|
id: string;
|
|
175
193
|
outcome: BuiAiSuggestionOutcome;
|
|
176
194
|
}, unknown>;
|
|
195
|
+
/**
|
|
196
|
+
* Proposes the lesson the learner should take next in one of their own
|
|
197
|
+
* enrollments — a deterministic curriculum-order "resume where you left off"
|
|
198
|
+
* walk plus a pacing hint derived from their recent graded scores (not an LLM
|
|
199
|
+
* call). It persists an auditable suggestion record but NEVER writes
|
|
200
|
+
* `BuiLessonProgress` / `BuiEnrollment`, so acting on it is entirely the
|
|
201
|
+
* learner's choice. Type-B self-scoped: `enrollmentId` is a client arg but the
|
|
202
|
+
* resolver owner-filters by the authenticated actor.
|
|
203
|
+
*/
|
|
204
|
+
export declare const useBuiSuggestNextLesson: () => import('@tanstack/react-query').UseMutationResult<BuiNextLessonSuggestion, Error, string, unknown>;
|
|
205
|
+
/** Records whether the learner accepted or dismissed a next-lesson suggestion. */
|
|
206
|
+
export declare const useBuiReviewNextLessonSuggestion: () => import('@tanstack/react-query').UseMutationResult<BuiNextLessonSuggestion, Error, {
|
|
207
|
+
id: string;
|
|
208
|
+
outcome: BuiAiSuggestionOutcome;
|
|
209
|
+
}, unknown>;
|
|
177
210
|
/**
|
|
178
211
|
* AI-drafted course outline from a topic — an EPHEMERAL suggestion (not
|
|
179
212
|
* persisted server-side); the instructor reviews/edits it before
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useBuildmyiqApi.d.ts","sourceRoot":"","sources":["../../../src/buildmyiq/hooks/useBuildmyiqApi.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH,OAAO,KAAK,EACV,aAAa,EACb,SAAS,EACT,cAAc,EACd,eAAe,EACf,SAAS,EACT,SAAS,EACT,aAAa,EACb,mBAAmB,EACnB,WAAW,EACX,aAAa,EACb,mBAAmB,EACnB,aAAa,EACb,mBAAmB,EACnB,SAAS,EACT,eAAe,EACf,QAAQ,EACR,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,yBAAyB,EACzB,cAAc,EACd,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,oBAAoB,EACpB,wBAAwB,EACxB,sBAAsB,EACtB,mBAAmB,EACnB,oBAAoB,EACpB,cAAc,EACd,4BAA4B,EAC5B,wBAAwB,EACxB,uBAAuB,EACvB,wBAAwB,EACxB,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,kBAAkB,EAClB,0BAA0B,EAC1B,0BAA0B,EAC1B,qBAAqB,EACrB,wBAAwB,EACxB,sBAAsB,EACtB,cAAc,EACd,2BAA2B,EAE5B,MAAM,UAAU,CAAC;AAkPlB,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,eAAO,MAAM,aAAa,GAAI,OAAM,iBAAsB;;iBAoCT,SAAS,EAAE;iBACX,SAAS,EAAE;;;;;;;;;;;;;;;;;;;;;;UAM3D,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,IAAI,MAAM,GAAG,SAAS,qFAgBlD,CAAC;AAEF,eAAO,MAAM,kBAAkB,0GAgB9B,CAAC;AAEF,eAAO,MAAM,kBAAkB;QAII,MAAM;WAAS,oBAAoB;WAerE,CAAC;AAEF,eAAO,MAAM,mBAAmB,4FAmB/B,CAAC;AAEF,eAAO,MAAM,mBAAmB,0FAiB/B,CAAC;AAMF,eAAO,MAAM,aAAa,GAAI,UAAU,MAAM,GAAG,SAAS;;;;;;;;;;YAkBzD,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,UAAU,MAAM,GAAG,SAAS,EAAE,WAAW,MAAM,gFAgB5E,CAAC;AAEF,eAAO,MAAM,kBAAkB,0GAmB9B,CAAC;AAEF,eAAO,MAAM,kBAAkB,0GAoB9B,CAAC;AAMF,eAAO,MAAM,iBAAiB,GAAI,UAAU,MAAM,GAAG,SAAS,EAAE,SAAS,mBAAmB;eA8BzC,WAAW,EAAE;;;;;;;;;;;;;;YAI/D,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,IAAI,MAAM,GAAG,SAAS,yFAgBtD,CAAC;AAEF,eAAO,MAAM,sBAAsB,kHAgBlC,CAAC;AAEF,eAAO,MAAM,uBAAuB,gGAmBnC,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB;QAID,MAAM;cAAY,MAAM;WAa1D,CAAC;AAEF,eAAO,MAAM,oBAAoB,8GAgBhC,CAAC;AAMF,MAAM,WAAW,qBAAqB;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,eAAO,MAAM,iBAAiB,GAAI,OAAM,qBAA0B,iGAoBjE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAAI,OAAM,qBAA0B,iGAoBnE,CAAC;AAEF,kGAAkG;AAClG,eAAO,MAAM,gBAAgB,GAAI,IAAI,MAAM,GAAG,SAAS,yFAgBtD,CAAC;AAEF,eAAO,MAAM,sBAAsB,kHAgBlC,CAAC;AAEF,eAAO,MAAM,qBAAqB;QAIC,MAAM;WAAS,uBAAuB;WAYxE,CAAC;AAMF,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAAI,OAAM,qBAA0B,iGAoBjE,CAAC;AAEF,+EAA+E;AAC/E,eAAO,MAAM,mBAAmB,GAAI,OAAM,qBAA0B,iGAoBnE,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,IAAI,MAAM,GAAG,SAAS,yFAgBtD,CAAC;AAEF,eAAO,MAAM,YAAY,wGAgBxB,CAAC;AAEF,eAAO,MAAM,0BAA0B;QAIJ,MAAM;YAAU,mBAAmB;WAerE,CAAC;AAEF,eAAO,MAAM,0BAA0B,0HAmBtC,CAAC;AAMF,eAAO,MAAM,aAAa,GAAI,WAAW,MAAM,EAAE,SAAS,eAAe,gFAexE,CAAC;AAEF,eAAO,MAAM,kBAAkB,0GAgB9B,CAAC;AAMF,eAAO,MAAM,YAAY,GAAI,WAAW,gBAAgB,+EAevD,CAAC;AAEF,eAAO,MAAM,iBAAiB,wGAgB7B,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAC/B,SAAS,gBAAgB,CAAC,QAAQ,CAAC,EACnC,WAAW,gBAAgB,EAC3B,iBAAc,uFAiBf,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAI,OAAO,gBAAgB,CAAC,MAAM,CAAC,EAAE,iBAAc,uFAgBnF,CAAC;AAEF,eAAO,MAAM,0BAA0B,GAAI,MAAM,MAAM,EAAE,cAAc,MAAM,EAAE,iBAAc,gGAoB5F,CAAC;AAMF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,GAAI,WAAW,MAAM,EAAE,iBAAc,qFAgBnE,CAAC;AAEF,gFAAgF;AAChF,eAAO,MAAM,oBAAoB,GAAI,WAAW,MAAM,EAAE,iBAAc,qFAgBrE,CAAC;AAEF,eAAO,MAAM,sBAAsB,mHAgBlC,CAAC;AAEF,eAAO,MAAM,uBAAuB,iGAgBnC,CAAC;AAMF;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,GAAI,UAAU,MAAM,GAAG,SAAS,sFAgBjE,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,cAAc,+GAqB1B,CAAC;AAeF;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,qGAc9B,CAAC;AAEF,2GAA2G;AAC3G,eAAO,MAAM,2BAA2B;QAGL,MAAM;aAAW,sBAAsB;WAWzE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,0BAA0B;WAI1B,MAAM;oBACG,MAAM,GAAG,IAAI;kBACf,MAAM,GAAG,IAAI;WAehC,CAAC;AAEF,2FAA2F;AAC3F,eAAO,MAAM,wBAAwB,gHAgBpC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,qBAAqB;cAGO,MAAM;aAAW,wBAAwB,EAAE;WAanF,CAAC;AAWF,eAAO,MAAM,kBAAkB,wFAa9B,CAAC;AAEF,eAAO,MAAM,yBAAyB,sHAgBrC,CAAC;AAEF,eAAO,MAAM,2BAA2B,0FAcvC,CAAC"}
|
|
1
|
+
{"version":3,"file":"useBuildmyiqApi.d.ts","sourceRoot":"","sources":["../../../src/buildmyiq/hooks/useBuildmyiqApi.ts"],"names":[],"mappings":"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"}
|