@burdenoff/microfe-technospam 2026.1102.1 → 2026.1102.3

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 (133) hide show
  1. package/dist/generated/wspace-types.d.ts +7468 -141
  2. package/dist/generated/wspace-types.d.ts.map +1 -1
  3. package/dist/node_modules/@codemirror/autocomplete/dist/index.js +527 -0
  4. package/dist/node_modules/@codemirror/autocomplete/dist/index.js.map +1 -0
  5. package/dist/node_modules/@codemirror/commands/dist/index.js +1108 -0
  6. package/dist/node_modules/@codemirror/commands/dist/index.js.map +1 -0
  7. package/dist/node_modules/@codemirror/lang-go/dist/index.js +206 -0
  8. package/dist/node_modules/@codemirror/lang-go/dist/index.js.map +1 -0
  9. package/dist/node_modules/@codemirror/lang-javascript/dist/index.js +321 -0
  10. package/dist/node_modules/@codemirror/lang-javascript/dist/index.js.map +1 -0
  11. package/dist/node_modules/@codemirror/lang-python/dist/index.js +265 -0
  12. package/dist/node_modules/@codemirror/lang-python/dist/index.js.map +1 -0
  13. package/dist/node_modules/@codemirror/language/dist/index.js +957 -0
  14. package/dist/node_modules/@codemirror/language/dist/index.js.map +1 -0
  15. package/dist/node_modules/@codemirror/legacy-modes/mode/ruby.js +164 -0
  16. package/dist/node_modules/@codemirror/legacy-modes/mode/ruby.js.map +1 -0
  17. package/dist/node_modules/@codemirror/legacy-modes/mode/shell.js +109 -0
  18. package/dist/node_modules/@codemirror/legacy-modes/mode/shell.js.map +1 -0
  19. package/dist/node_modules/@codemirror/state/dist/index.js +1739 -0
  20. package/dist/node_modules/@codemirror/state/dist/index.js.map +1 -0
  21. package/dist/node_modules/@codemirror/streamparser/dist/index.js +70 -0
  22. package/dist/node_modules/@codemirror/streamparser/dist/index.js.map +1 -0
  23. package/dist/node_modules/@codemirror/view/dist/index.js +5427 -0
  24. package/dist/node_modules/@codemirror/view/dist/index.js.map +1 -0
  25. package/dist/node_modules/@lezer/common/dist/index.js +896 -0
  26. package/dist/node_modules/@lezer/common/dist/index.js.map +1 -0
  27. package/dist/node_modules/@lezer/go/dist/index.js +215 -0
  28. package/dist/node_modules/@lezer/go/dist/index.js.map +1 -0
  29. package/dist/node_modules/@lezer/highlight/dist/index.js +395 -0
  30. package/dist/node_modules/@lezer/highlight/dist/index.js.map +1 -0
  31. package/dist/node_modules/@lezer/javascript/dist/index.js +437 -0
  32. package/dist/node_modules/@lezer/javascript/dist/index.js.map +1 -0
  33. package/dist/node_modules/@lezer/lr/dist/index.js +842 -0
  34. package/dist/node_modules/@lezer/lr/dist/index.js.map +1 -0
  35. package/dist/node_modules/@lezer/python/dist/index.js +352 -0
  36. package/dist/node_modules/@lezer/python/dist/index.js.map +1 -0
  37. package/dist/node_modules/@marijn/find-cluster-break/src/index.js +66 -0
  38. package/dist/node_modules/@marijn/find-cluster-break/src/index.js.map +1 -0
  39. package/dist/node_modules/style-mod/src/style-mod.js +74 -0
  40. package/dist/node_modules/style-mod/src/style-mod.js.map +1 -0
  41. package/dist/node_modules/w3c-keyname/index.js +90 -0
  42. package/dist/node_modules/w3c-keyname/index.js.map +1 -0
  43. package/dist/stories/fixtures/technospamFixtures.d.ts.map +1 -1
  44. package/dist/stories/journeys/Problems.stories.d.ts.map +1 -1
  45. package/dist/technospam/TechnoSpamRoot.d.ts.map +1 -1
  46. package/dist/technospam/TechnoSpamRoot.js +187 -178
  47. package/dist/technospam/TechnoSpamRoot.js.map +1 -1
  48. package/dist/technospam/api/technospamApi.d.ts +39 -0
  49. package/dist/technospam/api/technospamApi.d.ts.map +1 -1
  50. package/dist/technospam/api/technospamApi.js +184 -150
  51. package/dist/technospam/api/technospamApi.js.map +1 -1
  52. package/dist/technospam/components/MediaCover.js +2 -2
  53. package/dist/technospam/components/MediaCover.js.map +1 -1
  54. package/dist/technospam/components/MobileSectionTabs.d.ts +9 -0
  55. package/dist/technospam/components/MobileSectionTabs.d.ts.map +1 -0
  56. package/dist/technospam/components/MobileSectionTabs.js +43 -0
  57. package/dist/technospam/components/MobileSectionTabs.js.map +1 -0
  58. package/dist/technospam/components/PageLayout.d.ts +7 -1
  59. package/dist/technospam/components/PageLayout.d.ts.map +1 -1
  60. package/dist/technospam/components/PageLayout.js +40 -28
  61. package/dist/technospam/components/PageLayout.js.map +1 -1
  62. package/dist/technospam/components/SubmissionViews.d.ts +6 -2
  63. package/dist/technospam/components/SubmissionViews.d.ts.map +1 -1
  64. package/dist/technospam/components/SubmissionViews.js +6 -5
  65. package/dist/technospam/components/SubmissionViews.js.map +1 -1
  66. package/dist/technospam/components/TechnoSpamErrorBoundary.d.ts +6 -0
  67. package/dist/technospam/components/TechnoSpamErrorBoundary.d.ts.map +1 -1
  68. package/dist/technospam/components/TechnoSpamErrorBoundary.js +2 -2
  69. package/dist/technospam/components/TechnoSpamErrorBoundary.js.map +1 -1
  70. package/dist/technospam/components/editor/CodeEditor.d.ts +26 -0
  71. package/dist/technospam/components/editor/CodeEditor.d.ts.map +1 -0
  72. package/dist/technospam/components/editor/CodeEditor.js +102 -0
  73. package/dist/technospam/components/editor/CodeEditor.js.map +1 -0
  74. package/dist/technospam/components/editor/RunOutputPanel.d.ts +14 -0
  75. package/dist/technospam/components/editor/RunOutputPanel.d.ts.map +1 -0
  76. package/dist/technospam/components/editor/RunOutputPanel.js +127 -0
  77. package/dist/technospam/components/editor/RunOutputPanel.js.map +1 -0
  78. package/dist/technospam/components/editor/editorLanguages.d.ts +11 -0
  79. package/dist/technospam/components/editor/editorLanguages.d.ts.map +1 -0
  80. package/dist/technospam/components/editor/editorLanguages.js +30 -0
  81. package/dist/technospam/components/editor/editorLanguages.js.map +1 -0
  82. package/dist/technospam/components/editor/editorTheme.d.ts +11 -0
  83. package/dist/technospam/components/editor/editorTheme.d.ts.map +1 -0
  84. package/dist/technospam/components/editor/editorTheme.js +120 -0
  85. package/dist/technospam/components/editor/editorTheme.js.map +1 -0
  86. package/dist/technospam/components/lesson/SaveCourseOffline.js +6 -6
  87. package/dist/technospam/hooks/usePhoneLayout.d.ts +18 -0
  88. package/dist/technospam/hooks/usePhoneLayout.d.ts.map +1 -0
  89. package/dist/technospam/hooks/usePhoneLayout.js +14 -0
  90. package/dist/technospam/hooks/usePhoneLayout.js.map +1 -0
  91. package/dist/technospam/hooks/useSolutionRunner.d.ts +35 -0
  92. package/dist/technospam/hooks/useSolutionRunner.d.ts.map +1 -0
  93. package/dist/technospam/hooks/useSolutionRunner.js +66 -0
  94. package/dist/technospam/hooks/useSolutionRunner.js.map +1 -0
  95. package/dist/technospam/hooks/useTechnoSpamAnalytics.d.ts +1 -1
  96. package/dist/technospam/hooks/useTechnoSpamAnalytics.d.ts.map +1 -1
  97. package/dist/technospam/hooks/useTechnoSpamAnalytics.js.map +1 -1
  98. package/dist/technospam/pages/AdminAdminDashboardPagePage.js +1 -1
  99. package/dist/technospam/pages/AdminAdminDashboardPagePage.js.map +1 -1
  100. package/dist/technospam/pages/ApplicationsProblemDetailsPagePage.d.ts.map +1 -1
  101. package/dist/technospam/pages/ApplicationsProblemDetailsPagePage.js +416 -263
  102. package/dist/technospam/pages/ApplicationsProblemDetailsPagePage.js.map +1 -1
  103. package/dist/technospam/pages/ApplicationsProblemsPagePage.d.ts.map +1 -1
  104. package/dist/technospam/pages/ApplicationsProblemsPagePage.js +89 -87
  105. package/dist/technospam/pages/ApplicationsProblemsPagePage.js.map +1 -1
  106. package/dist/technospam/pages/CoursesCourseDetailsPagePage.js +3 -3
  107. package/dist/technospam/pages/CoursesCourseDetailsPagePage.js.map +1 -1
  108. package/dist/technospam/pages/CoursesCoursesPagePage.d.ts.map +1 -1
  109. package/dist/technospam/pages/CoursesCoursesPagePage.js +117 -81
  110. package/dist/technospam/pages/CoursesCoursesPagePage.js.map +1 -1
  111. package/dist/technospam/pages/CoursesMyLearningPagePage.js +1 -1
  112. package/dist/technospam/pages/CoursesMyLearningPagePage.js.map +1 -1
  113. package/dist/technospam/pages/DashboardDashboardPagePage.d.ts.map +1 -1
  114. package/dist/technospam/pages/DashboardDashboardPagePage.js +21 -17
  115. package/dist/technospam/pages/DashboardDashboardPagePage.js.map +1 -1
  116. package/dist/technospam/pages/HackathonsHackathonDetailsPagePage.js +3 -3
  117. package/dist/technospam/pages/HackathonsHackathonDetailsPagePage.js.map +1 -1
  118. package/dist/technospam/pages/MentorshipMentorProfilePagePage.js +4 -4
  119. package/dist/technospam/pages/MentorshipMentorProfilePagePage.js.map +1 -1
  120. package/dist/technospam/pages/MentorshipMentorsPagePage.d.ts.map +1 -1
  121. package/dist/technospam/pages/MentorshipMentorsPagePage.js +6 -4
  122. package/dist/technospam/pages/MentorshipMentorsPagePage.js.map +1 -1
  123. package/dist/technospam/pages/MentorshipSessionsPagePage.js +1 -1
  124. package/dist/technospam/pages/MentorshipSessionsPagePage.js.map +1 -1
  125. package/dist/technospam/types/index.d.ts +7 -0
  126. package/dist/technospam/types/index.d.ts.map +1 -1
  127. package/dist/technospam/utils/mobileTabs.d.ts +45 -0
  128. package/dist/technospam/utils/mobileTabs.d.ts.map +1 -0
  129. package/dist/technospam/utils/mobileTabs.js +70 -0
  130. package/dist/technospam/utils/mobileTabs.js.map +1 -0
  131. package/dist/test/matchMedia.d.ts +6 -0
  132. package/dist/test/matchMedia.d.ts.map +1 -0
  133. package/package.json +16 -6
@@ -0,0 +1,30 @@
1
+ import { StreamLanguage as e } from "../../../node_modules/@codemirror/language/dist/index.js";
2
+ import { javascript as t } from "../../../node_modules/@codemirror/lang-javascript/dist/index.js";
3
+ import { python as n } from "../../../node_modules/@codemirror/lang-python/dist/index.js";
4
+ import { go as r } from "../../../node_modules/@codemirror/lang-go/dist/index.js";
5
+ import { ruby as i } from "../../../node_modules/@codemirror/legacy-modes/mode/ruby.js";
6
+ import { shell as a } from "../../../node_modules/@codemirror/legacy-modes/mode/shell.js";
7
+ //#region src/technospam/components/editor/editorLanguages.ts
8
+ function o(o) {
9
+ switch (o.trim().toLowerCase()) {
10
+ case "javascript":
11
+ case "js":
12
+ case "node": return t();
13
+ case "typescript":
14
+ case "ts": return t({ typescript: !0 });
15
+ case "python":
16
+ case "py": return n();
17
+ case "go":
18
+ case "golang": return r();
19
+ case "ruby":
20
+ case "rb": return e.define(i);
21
+ case "bash":
22
+ case "sh":
23
+ case "shell": return e.define(a);
24
+ default: return [];
25
+ }
26
+ }
27
+ //#endregion
28
+ export { o as languageExtension };
29
+
30
+ //# sourceMappingURL=editorLanguages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editorLanguages.js","names":[],"sources":["../../../../src/technospam/components/editor/editorLanguages.ts"],"sourcesContent":["import type { Extension } from '@codemirror/state';\nimport { StreamLanguage } from '@codemirror/language';\nimport { javascript } from '@codemirror/lang-javascript';\nimport { python } from '@codemirror/lang-python';\nimport { go } from '@codemirror/lang-go';\nimport { ruby } from '@codemirror/legacy-modes/mode/ruby';\nimport { shell } from '@codemirror/legacy-modes/mode/shell';\n\n/**\n * Syntax support for every language slug the grading sandbox runs\n * (wspace-technospam-svc `SUPPORTED_LANGUAGES`). Unknown slugs get plain-text\n * editing — line numbers, brackets and history still work.\n */\nexport function languageExtension(language: string): Extension {\n switch (language.trim().toLowerCase()) {\n case 'javascript':\n case 'js':\n case 'node':\n return javascript();\n case 'typescript':\n case 'ts':\n return javascript({ typescript: true });\n case 'python':\n case 'py':\n return python();\n case 'go':\n case 'golang':\n return go();\n case 'ruby':\n case 'rb':\n return StreamLanguage.define(ruby);\n case 'bash':\n case 'sh':\n case 'shell':\n return StreamLanguage.define(shell);\n default:\n return [];\n }\n}\n\n/** Whether `languageExtension` highlights this slug (used by tests and the editor label). */\nexport function hasSyntaxSupport(language: string): boolean {\n const ext = languageExtension(language);\n return !(Array.isArray(ext) && ext.length === 0);\n}\n"],"mappings":";;;;;;;AAaA,SAAgB,EAAkB,GAA6B;AAC7D,SAAQ,EAAS,MAAM,CAAC,aAAa,EAArC;EACE,KAAK;EACL,KAAK;EACL,KAAK,OACH,QAAO,GAAY;EACrB,KAAK;EACL,KAAK,KACH,QAAO,EAAW,EAAE,YAAY,IAAM,CAAC;EACzC,KAAK;EACL,KAAK,KACH,QAAO,GAAQ;EACjB,KAAK;EACL,KAAK,SACH,QAAO,GAAI;EACb,KAAK;EACL,KAAK,KACH,QAAO,EAAe,OAAO,EAAK;EACpC,KAAK;EACL,KAAK;EACL,KAAK,QACH,QAAO,EAAe,OAAO,EAAM;EACrC,QACE,QAAO,EAAE"}
@@ -0,0 +1,11 @@
1
+ import { HighlightStyle } from '@codemirror/language';
2
+
3
+ /**
4
+ * Syntax colours are Tailwind utility classes over the platform's semantic
5
+ * tokens (never raw colours), so the editor follows the active brand and
6
+ * light/dark theme like the rest of the app.
7
+ */
8
+ export declare const technospamHighlightStyle: HighlightStyle;
9
+ /** Editor chrome: inherits the surrounding panel and uses semantic token variables. */
10
+ export declare const technospamEditorTheme: import('@codemirror/state').Extension;
11
+ //# sourceMappingURL=editorTheme.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editorTheme.d.ts","sourceRoot":"","sources":["../../../../src/technospam/components/editor/editorTheme.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGtD;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,gBAyBnC,CAAC;AAEH,uFAAuF;AACvF,eAAO,MAAM,qBAAqB,uCA+BhC,CAAC"}
@@ -0,0 +1,120 @@
1
+ import { EditorView as e } from "../../../node_modules/@codemirror/view/dist/index.js";
2
+ import { tags as t } from "../../../node_modules/@lezer/highlight/dist/index.js";
3
+ import { HighlightStyle as n } from "../../../node_modules/@codemirror/language/dist/index.js";
4
+ //#region src/technospam/components/editor/editorTheme.ts
5
+ var r = n.define([
6
+ {
7
+ tag: [
8
+ t.keyword,
9
+ t.controlKeyword,
10
+ t.moduleKeyword,
11
+ t.operatorKeyword
12
+ ],
13
+ class: "text-accent-purple"
14
+ },
15
+ {
16
+ tag: [t.definitionKeyword, t.modifier],
17
+ class: "text-accent-purple"
18
+ },
19
+ {
20
+ tag: [
21
+ t.string,
22
+ t.special(t.string),
23
+ t.regexp
24
+ ],
25
+ class: "text-status-success-text"
26
+ },
27
+ {
28
+ tag: [
29
+ t.number,
30
+ t.bool,
31
+ t.null,
32
+ t.atom
33
+ ],
34
+ class: "text-status-warning-text"
35
+ },
36
+ {
37
+ tag: [
38
+ t.comment,
39
+ t.lineComment,
40
+ t.blockComment,
41
+ t.docComment
42
+ ],
43
+ class: "italic text-text-secondary"
44
+ },
45
+ {
46
+ tag: [
47
+ t.function(t.variableName),
48
+ t.function(t.propertyName),
49
+ t.definition(t.function(t.variableName))
50
+ ],
51
+ class: "text-accent-primary"
52
+ },
53
+ {
54
+ tag: [
55
+ t.typeName,
56
+ t.className,
57
+ t.namespace
58
+ ],
59
+ class: "text-accent-teal"
60
+ },
61
+ {
62
+ tag: [t.propertyName, t.attributeName],
63
+ class: "text-accent-indigo"
64
+ },
65
+ {
66
+ tag: [t.self, t.special(t.variableName)],
67
+ class: "text-accent-purple"
68
+ },
69
+ {
70
+ tag: [
71
+ t.operator,
72
+ t.punctuation,
73
+ t.bracket
74
+ ],
75
+ class: "text-text-secondary"
76
+ },
77
+ {
78
+ tag: t.invalid,
79
+ class: "text-status-error-text"
80
+ }
81
+ ]), i = e.theme({
82
+ "&": {
83
+ backgroundColor: "inherit",
84
+ color: "var(--color-text-primary)",
85
+ fontSize: "12px",
86
+ height: "100%"
87
+ },
88
+ "&.cm-focused": { outline: "none" },
89
+ ".cm-scroller": {
90
+ fontFamily: "inherit",
91
+ lineHeight: "1.65"
92
+ },
93
+ ".cm-content": {
94
+ caretColor: "var(--color-text-primary)",
95
+ padding: "12px 0"
96
+ },
97
+ ".cm-cursor, .cm-dropCursor": { borderLeftColor: "var(--color-text-primary)" },
98
+ ".cm-gutters": {
99
+ backgroundColor: "inherit",
100
+ color: "var(--color-text-muted)",
101
+ border: "none",
102
+ borderRight: "1px solid var(--color-border-subtle)"
103
+ },
104
+ ".cm-lineNumbers .cm-gutterElement": { padding: "0 10px 0 12px" },
105
+ ".cm-activeLine": { backgroundColor: "var(--color-bg-surface)" },
106
+ ".cm-activeLineGutter": {
107
+ backgroundColor: "var(--color-bg-surface)",
108
+ color: "var(--color-text-primary)"
109
+ },
110
+ ".cm-selectionBackground, &.cm-focused .cm-selectionBackground, ::selection": { backgroundColor: "var(--color-bg-accent)" },
111
+ ".cm-matchingBracket": {
112
+ backgroundColor: "var(--color-bg-accent)",
113
+ outline: "1px solid var(--color-border-strong)"
114
+ },
115
+ ".cm-placeholder": { color: "var(--color-text-placeholder)" }
116
+ });
117
+ //#endregion
118
+ export { i as technospamEditorTheme, r as technospamHighlightStyle };
119
+
120
+ //# sourceMappingURL=editorTheme.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editorTheme.js","names":[],"sources":["../../../../src/technospam/components/editor/editorTheme.ts"],"sourcesContent":["import { EditorView } from '@codemirror/view';\nimport { HighlightStyle } from '@codemirror/language';\nimport { tags as t } from '@lezer/highlight';\n\n/**\n * Syntax colours are Tailwind utility classes over the platform's semantic\n * tokens (never raw colours), so the editor follows the active brand and\n * light/dark theme like the rest of the app.\n */\nexport const technospamHighlightStyle = HighlightStyle.define([\n {\n tag: [t.keyword, t.controlKeyword, t.moduleKeyword, t.operatorKeyword],\n class: 'text-accent-purple',\n },\n { tag: [t.definitionKeyword, t.modifier], class: 'text-accent-purple' },\n { tag: [t.string, t.special(t.string), t.regexp], class: 'text-status-success-text' },\n { tag: [t.number, t.bool, t.null, t.atom], class: 'text-status-warning-text' },\n {\n tag: [t.comment, t.lineComment, t.blockComment, t.docComment],\n class: 'italic text-text-secondary',\n },\n {\n tag: [\n t.function(t.variableName),\n t.function(t.propertyName),\n t.definition(t.function(t.variableName)),\n ],\n class: 'text-accent-primary',\n },\n { tag: [t.typeName, t.className, t.namespace], class: 'text-accent-teal' },\n { tag: [t.propertyName, t.attributeName], class: 'text-accent-indigo' },\n { tag: [t.self, t.special(t.variableName)], class: 'text-accent-purple' },\n { tag: [t.operator, t.punctuation, t.bracket], class: 'text-text-secondary' },\n { tag: t.invalid, class: 'text-status-error-text' },\n]);\n\n/** Editor chrome: inherits the surrounding panel and uses semantic token variables. */\nexport const technospamEditorTheme = EditorView.theme({\n '&': {\n backgroundColor: 'inherit',\n color: 'var(--color-text-primary)',\n fontSize: '12px',\n height: '100%',\n },\n '&.cm-focused': { outline: 'none' },\n '.cm-scroller': { fontFamily: 'inherit', lineHeight: '1.65' },\n '.cm-content': { caretColor: 'var(--color-text-primary)', padding: '12px 0' },\n '.cm-cursor, .cm-dropCursor': { borderLeftColor: 'var(--color-text-primary)' },\n '.cm-gutters': {\n backgroundColor: 'inherit',\n color: 'var(--color-text-muted)',\n border: 'none',\n borderRight: '1px solid var(--color-border-subtle)',\n },\n '.cm-lineNumbers .cm-gutterElement': { padding: '0 10px 0 12px' },\n '.cm-activeLine': { backgroundColor: 'var(--color-bg-surface)' },\n '.cm-activeLineGutter': {\n backgroundColor: 'var(--color-bg-surface)',\n color: 'var(--color-text-primary)',\n },\n '.cm-selectionBackground, &.cm-focused .cm-selectionBackground, ::selection': {\n backgroundColor: 'var(--color-bg-accent)',\n },\n '.cm-matchingBracket': {\n backgroundColor: 'var(--color-bg-accent)',\n outline: '1px solid var(--color-border-strong)',\n },\n '.cm-placeholder': { color: 'var(--color-text-placeholder)' },\n});\n"],"mappings":";;;;AASA,IAAa,IAA2B,EAAe,OAAO;CAC5D;EACE,KAAK;GAAC,EAAE;GAAS,EAAE;GAAgB,EAAE;GAAe,EAAE;GAAgB;EACtE,OAAO;EACR;CACD;EAAE,KAAK,CAAC,EAAE,mBAAmB,EAAE,SAAS;EAAE,OAAO;EAAsB;CACvE;EAAE,KAAK;GAAC,EAAE;GAAQ,EAAE,QAAQ,EAAE,OAAO;GAAE,EAAE;GAAO;EAAE,OAAO;EAA4B;CACrF;EAAE,KAAK;GAAC,EAAE;GAAQ,EAAE;GAAM,EAAE;GAAM,EAAE;GAAK;EAAE,OAAO;EAA4B;CAC9E;EACE,KAAK;GAAC,EAAE;GAAS,EAAE;GAAa,EAAE;GAAc,EAAE;GAAW;EAC7D,OAAO;EACR;CACD;EACE,KAAK;GACH,EAAE,SAAS,EAAE,aAAa;GAC1B,EAAE,SAAS,EAAE,aAAa;GAC1B,EAAE,WAAW,EAAE,SAAS,EAAE,aAAa,CAAC;GACzC;EACD,OAAO;EACR;CACD;EAAE,KAAK;GAAC,EAAE;GAAU,EAAE;GAAW,EAAE;GAAU;EAAE,OAAO;EAAoB;CAC1E;EAAE,KAAK,CAAC,EAAE,cAAc,EAAE,cAAc;EAAE,OAAO;EAAsB;CACvE;EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,CAAC;EAAE,OAAO;EAAsB;CACzE;EAAE,KAAK;GAAC,EAAE;GAAU,EAAE;GAAa,EAAE;GAAQ;EAAE,OAAO;EAAuB;CAC7E;EAAE,KAAK,EAAE;EAAS,OAAO;EAA0B;CACpD,CAAC,EAGW,IAAwB,EAAW,MAAM;CACpD,KAAK;EACH,iBAAiB;EACjB,OAAO;EACP,UAAU;EACV,QAAQ;EACT;CACD,gBAAgB,EAAE,SAAS,QAAQ;CACnC,gBAAgB;EAAE,YAAY;EAAW,YAAY;EAAQ;CAC7D,eAAe;EAAE,YAAY;EAA6B,SAAS;EAAU;CAC7E,8BAA8B,EAAE,iBAAiB,6BAA6B;CAC9E,eAAe;EACb,iBAAiB;EACjB,OAAO;EACP,QAAQ;EACR,aAAa;EACd;CACD,qCAAqC,EAAE,SAAS,iBAAiB;CACjE,kBAAkB,EAAE,iBAAiB,2BAA2B;CAChE,wBAAwB;EACtB,iBAAiB;EACjB,OAAO;EACR;CACD,8EAA8E,EAC5E,iBAAiB,0BAClB;CACD,uBAAuB;EACrB,iBAAiB;EACjB,SAAS;EACV;CACD,mBAAmB,EAAE,OAAO,iCAAiC;CAC9D,CAAC"}
@@ -5,11 +5,11 @@ import { useOnlineStatus as a } from "../../hooks/useOfflineLessons.js";
5
5
  import { useMemo as o, useState as s } from "react";
6
6
  import { CloudDownload as c, CloudOff as l, Trash2 as u } from "lucide-react";
7
7
  import { jsx as d, jsxs as f } from "react/jsx-runtime";
8
- import { Button as p } from "@burdenoff/fe-libs/ui";
9
- import { useApolloClient as m } from "@apollo/client/react";
8
+ import { useApolloClient as p } from "@apollo/client/react";
9
+ import { Button as m } from "@burdenoff/fe-libs/ui";
10
10
  //#region src/technospam/components/lesson/SaveCourseOffline.tsx
11
11
  function h({ scope: h, courseId: g, lessons: _, enrollment: v }) {
12
- let y = m(), b = a(), x = _.filter((e) => !e.isLocked), [S, C] = s(0), w = o(() => i(h, g), [
12
+ let y = p(), b = a(), x = _.filter((e) => !e.isLocked), [S, C] = s(0), w = o(() => i(h, g), [
13
13
  h,
14
14
  g,
15
15
  S
@@ -31,7 +31,7 @@ function h({ scope: h, courseId: g, lessons: _, enrollment: v }) {
31
31
  children: [/* @__PURE__ */ f("span", {
32
32
  className: "inline-flex items-center gap-1 rounded-full bg-accent-primary/6 px-2.5 py-1 text-xs font-medium text-accent-primary",
33
33
  children: [/* @__PURE__ */ d(l, { size: 12 }), " Available offline"]
34
- }), /* @__PURE__ */ d(p, {
34
+ }), /* @__PURE__ */ d(m, {
35
35
  size: "sm",
36
36
  variant: "ghost",
37
37
  onClick: () => {
@@ -40,7 +40,7 @@ function h({ scope: h, courseId: g, lessons: _, enrollment: v }) {
40
40
  "aria-label": "Remove offline copy",
41
41
  children: /* @__PURE__ */ d(u, { size: 14 })
42
42
  })]
43
- }) : /* @__PURE__ */ f(p, {
43
+ }) : /* @__PURE__ */ f(m, {
44
44
  size: "sm",
45
45
  variant: "outline",
46
46
  onClick: () => void k(),
@@ -52,7 +52,7 @@ function h({ scope: h, courseId: g, lessons: _, enrollment: v }) {
52
52
  " Save for offline",
53
53
  D > 0 ? ` (${D}/${x.length})` : ""
54
54
  ]
55
- }) : /* @__PURE__ */ f(p, {
55
+ }) : /* @__PURE__ */ f(m, {
56
56
  size: "sm",
57
57
  variant: "outline",
58
58
  disabled: !0,
@@ -0,0 +1,18 @@
1
+ /** Below Tailwind's `sm` breakpoint (640px): the phone layouts apply. */
2
+ export declare const PHONE_MEDIA_QUERY = "(max-width: 639px)";
3
+ export interface PhoneLayout {
4
+ /** Viewport is phone-width (any platform). */
5
+ isPhone: boolean;
6
+ /**
7
+ * Installed app (Capacitor / standalone PWA) on a phone: the shell renders
8
+ * its bottom tab bar and native top bar instead of the desktop chrome.
9
+ */
10
+ nativeChrome: boolean;
11
+ }
12
+ /**
13
+ * The single source for "which phone layout am I in" across TechnoSpam pages,
14
+ * so the in-page section switcher, pull-to-refresh and phone-only defaults all
15
+ * agree with the shell's own tab-bar rule.
16
+ */
17
+ export declare function usePhoneLayout(): PhoneLayout;
18
+ //# sourceMappingURL=usePhoneLayout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usePhoneLayout.d.ts","sourceRoot":"","sources":["../../../src/technospam/hooks/usePhoneLayout.ts"],"names":[],"mappings":"AAGA,yEAAyE;AACzE,eAAO,MAAM,iBAAiB,uBAAuB,CAAC;AAEtD,MAAM,WAAW,WAAW;IAC1B,8CAA8C;IAC9C,OAAO,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,YAAY,EAAE,OAAO,CAAC;CACvB;AAED;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,WAAW,CAI5C"}
@@ -0,0 +1,14 @@
1
+ import { useMediaQuery as e } from "@burdenoff/fe-libs/shared/hooks";
2
+ import { useMobileTabBarVisible as t } from "@burdenoff/fe-libs/chrome/mobileTabBar/useMobileTabBarVisible";
3
+ //#region src/technospam/hooks/usePhoneLayout.ts
4
+ var n = "(max-width: 639px)";
5
+ function r() {
6
+ return {
7
+ isPhone: e(n),
8
+ nativeChrome: t()
9
+ };
10
+ }
11
+ //#endregion
12
+ export { r as usePhoneLayout };
13
+
14
+ //# sourceMappingURL=usePhoneLayout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usePhoneLayout.js","names":[],"sources":["../../../src/technospam/hooks/usePhoneLayout.ts"],"sourcesContent":["import { useMediaQuery } from '@burdenoff/fe-libs/shared/hooks';\nimport { useMobileTabBarVisible } from '@burdenoff/fe-libs/chrome/mobileTabBar/useMobileTabBarVisible';\n\n/** Below Tailwind's `sm` breakpoint (640px): the phone layouts apply. */\nexport const PHONE_MEDIA_QUERY = '(max-width: 639px)';\n\nexport interface PhoneLayout {\n /** Viewport is phone-width (any platform). */\n isPhone: boolean;\n /**\n * Installed app (Capacitor / standalone PWA) on a phone: the shell renders\n * its bottom tab bar and native top bar instead of the desktop chrome.\n */\n nativeChrome: boolean;\n}\n\n/**\n * The single source for \"which phone layout am I in\" across TechnoSpam pages,\n * so the in-page section switcher, pull-to-refresh and phone-only defaults all\n * agree with the shell's own tab-bar rule.\n */\nexport function usePhoneLayout(): PhoneLayout {\n const isPhone = useMediaQuery(PHONE_MEDIA_QUERY);\n const nativeChrome = useMobileTabBarVisible();\n return { isPhone, nativeChrome };\n}\n"],"mappings":";;;AAIA,IAAa,IAAoB;AAiBjC,SAAgB,IAA8B;AAG5C,QAAO;EAAE,SAFO,EAAc,EAAkB;EAE9B,cADG,GAAwB;EACb"}
@@ -0,0 +1,35 @@
1
+ import { TecSolutionRun } from '../api/technospamApi';
2
+
3
+ /**
4
+ * A cold code sandbox can take a few minutes to start. While the API answers
5
+ * WARMING the run is retried on this interval, giving up after the budget so
6
+ * the learner can retry by hand.
7
+ */
8
+ export declare const RUN_WARMING_RETRY_MS = 4000;
9
+ export declare const RUN_WARMING_BUDGET_MS: number;
10
+ export interface SolutionRunRequest {
11
+ problemId: string;
12
+ language: string;
13
+ code: string;
14
+ /** Custom stdin; omit to run the sample cases. */
15
+ stdin?: string | null;
16
+ }
17
+ export interface SolutionRunner {
18
+ /** The latest finished (or given-up) run. */
19
+ run: TecSolutionRun | null;
20
+ /** A request is in flight. */
21
+ running: boolean;
22
+ /** The sandbox is starting; the run is being retried automatically. */
23
+ warming: boolean;
24
+ /** Why the last run was refused (quota, bad input…), shown inline. */
25
+ error: string | null;
26
+ execute: (request: SolutionRunRequest) => void;
27
+ reset: () => void;
28
+ }
29
+ /**
30
+ * Drives `tecRunSolution` for the problem editor (BOFF-4078): sends the run,
31
+ * keeps retrying while the sandbox warms up, and exposes the result. Starting
32
+ * a new run cancels any pending warm-up retry.
33
+ */
34
+ export declare function useSolutionRunner(): SolutionRunner;
35
+ //# sourceMappingURL=useSolutionRunner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSolutionRunner.d.ts","sourceRoot":"","sources":["../../../src/technospam/hooks/useSolutionRunner.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG3E;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,OAAQ,CAAC;AAC1C,eAAO,MAAM,qBAAqB,QAAa,CAAC;AAEhD,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,kDAAkD;IAClD,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,6CAA6C;IAC7C,GAAG,EAAE,cAAc,GAAG,IAAI,CAAC;IAC3B,8BAA8B;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,uEAAuE;IACvE,OAAO,EAAE,OAAO,CAAC;IACjB,sEAAsE;IACtE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE,CAAC,OAAO,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAC/C,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,IAAI,cAAc,CA6GlD"}
@@ -0,0 +1,66 @@
1
+ import { userMessageFromError as e } from "../lib/errorMessage.js";
2
+ import { useRunSolution as t } from "../api/technospamApi.js";
3
+ import { useCallback as n, useEffect as r, useRef as i, useState as a } from "react";
4
+ //#region src/technospam/hooks/useSolutionRunner.ts
5
+ var o = 4e3;
6
+ function s() {
7
+ let [s] = t(), [c, l] = a(null), [u, d] = a(!1), [f, p] = a(!1), [m, h] = a(null), g = i(null), _ = i(null), v = i(0), y = () => {
8
+ g.current && clearTimeout(g.current), g.current = null;
9
+ };
10
+ r(() => () => {
11
+ y(), v.current += 1;
12
+ }, []);
13
+ let b = n((t, n) => {
14
+ let r = async () => {
15
+ d(!0);
16
+ try {
17
+ let i = await s({ variables: { input: {
18
+ problemId: t.problemId,
19
+ language: t.language,
20
+ code: t.code,
21
+ ...t.stdin == null ? {} : { stdin: t.stdin }
22
+ } } });
23
+ if (n !== v.current) return;
24
+ let a = i.data?.tecRunSolution;
25
+ if (!a) {
26
+ p(!1), _.current = null, l(null), h(e(i.error, "Your code could not be run. Please try again."));
27
+ return;
28
+ }
29
+ if (a.status === "WARMING") {
30
+ if (_.current ??= Date.now(), Date.now() - _.current < 24e4) {
31
+ p(!0), g.current = setTimeout(() => void r(), o);
32
+ return;
33
+ }
34
+ p(!1), _.current = null, l({
35
+ ...a,
36
+ status: "UNAVAILABLE"
37
+ });
38
+ return;
39
+ }
40
+ p(!1), _.current = null, l(a);
41
+ } catch (t) {
42
+ if (n !== v.current) return;
43
+ p(!1), _.current = null, l(null), h(e(t, "Your code could not be run. Please try again."));
44
+ } finally {
45
+ n === v.current && d(!1);
46
+ }
47
+ };
48
+ return r();
49
+ }, [s]);
50
+ return {
51
+ run: c,
52
+ running: u,
53
+ warming: f,
54
+ error: m,
55
+ execute: n((e) => {
56
+ y(), v.current += 1, _.current = null, h(null), b(e, v.current);
57
+ }, [b]),
58
+ reset: n(() => {
59
+ y(), v.current += 1, _.current = null, l(null), h(null), p(!1), d(!1);
60
+ }, [])
61
+ };
62
+ }
63
+ //#endregion
64
+ export { s as useSolutionRunner };
65
+
66
+ //# sourceMappingURL=useSolutionRunner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSolutionRunner.js","names":[],"sources":["../../../src/technospam/hooks/useSolutionRunner.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\nimport { useRunSolution, type TecSolutionRun } from '../api/technospamApi';\nimport { userMessageFromError } from '../lib/errorMessage';\n\n/**\n * A cold code sandbox can take a few minutes to start. While the API answers\n * WARMING the run is retried on this interval, giving up after the budget so\n * the learner can retry by hand.\n */\nexport const RUN_WARMING_RETRY_MS = 4_000;\nexport const RUN_WARMING_BUDGET_MS = 4 * 60_000;\n\nexport interface SolutionRunRequest {\n problemId: string;\n language: string;\n code: string;\n /** Custom stdin; omit to run the sample cases. */\n stdin?: string | null;\n}\n\nexport interface SolutionRunner {\n /** The latest finished (or given-up) run. */\n run: TecSolutionRun | null;\n /** A request is in flight. */\n running: boolean;\n /** The sandbox is starting; the run is being retried automatically. */\n warming: boolean;\n /** Why the last run was refused (quota, bad input…), shown inline. */\n error: string | null;\n execute: (request: SolutionRunRequest) => void;\n reset: () => void;\n}\n\n/**\n * Drives `tecRunSolution` for the problem editor (BOFF-4078): sends the run,\n * keeps retrying while the sandbox warms up, and exposes the result. Starting\n * a new run cancels any pending warm-up retry.\n */\nexport function useSolutionRunner(): SolutionRunner {\n const [runSolution] = useRunSolution();\n const [run, setRun] = useState<TecSolutionRun | null>(null);\n const [running, setRunning] = useState(false);\n const [warming, setWarming] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const timer = useRef<ReturnType<typeof setTimeout> | null>(null);\n const warmingSince = useRef<number | null>(null);\n /** Bumped per user-initiated run so a stale retry never overwrites a newer run. */\n const generation = useRef(0);\n\n const clearTimer = () => {\n if (timer.current) clearTimeout(timer.current);\n timer.current = null;\n };\n\n // On unmount, cancel any pending warm-up retry and invalidate the in-flight\n // request so a late WARMING answer cannot schedule another run after the\n // learner has left the page.\n useEffect(\n () => () => {\n clearTimer();\n generation.current += 1;\n },\n []\n );\n\n const attempt = useCallback(\n (request: SolutionRunRequest, gen: number): Promise<void> => {\n // A local recursive function keeps the warm-up retry inside one closure,\n // so the scheduled retry never references the hook binding itself.\n const go = async (): Promise<void> => {\n setRunning(true);\n try {\n const res = await runSolution({\n variables: {\n input: {\n problemId: request.problemId,\n language: request.language,\n code: request.code,\n ...(request.stdin != null ? { stdin: request.stdin } : {}),\n },\n },\n });\n if (gen !== generation.current) return;\n const result = res.data?.tecRunSolution;\n if (!result) {\n setWarming(false);\n warmingSince.current = null;\n setRun(null);\n setError(\n userMessageFromError(res.error, 'Your code could not be run. Please try again.')\n );\n return;\n }\n if (result.status === 'WARMING') {\n warmingSince.current ??= Date.now();\n if (Date.now() - warmingSince.current < RUN_WARMING_BUDGET_MS) {\n setWarming(true);\n timer.current = setTimeout(() => void go(), RUN_WARMING_RETRY_MS);\n return;\n }\n setWarming(false);\n warmingSince.current = null;\n setRun({ ...result, status: 'UNAVAILABLE' });\n return;\n }\n setWarming(false);\n warmingSince.current = null;\n setRun(result);\n } catch (err: unknown) {\n // Apollo reports GraphQL/network failures via res.error, but anything\n // unexpected must still end the warming state instead of spinning forever.\n if (gen !== generation.current) return;\n setWarming(false);\n warmingSince.current = null;\n setRun(null);\n setError(userMessageFromError(err, 'Your code could not be run. Please try again.'));\n } finally {\n if (gen === generation.current) setRunning(false);\n }\n };\n return go();\n },\n [runSolution]\n );\n\n const execute = useCallback(\n (request: SolutionRunRequest) => {\n clearTimer();\n generation.current += 1;\n warmingSince.current = null;\n setError(null);\n void attempt(request, generation.current);\n },\n [attempt]\n );\n\n const reset = useCallback(() => {\n clearTimer();\n generation.current += 1;\n warmingSince.current = null;\n setRun(null);\n setError(null);\n setWarming(false);\n setRunning(false);\n }, []);\n\n return { run, running, warming, error, execute, reset };\n}\n"],"mappings":";;;;AASA,IAAa,IAAuB;AA6BpC,SAAgB,IAAoC;CAClD,IAAM,CAAC,KAAe,GAAgB,EAChC,CAAC,GAAK,KAAU,EAAgC,KAAK,EACrD,CAAC,GAAS,KAAc,EAAS,GAAM,EACvC,CAAC,GAAS,KAAc,EAAS,GAAM,EACvC,CAAC,GAAO,KAAY,EAAwB,KAAK,EACjD,IAAQ,EAA6C,KAAK,EAC1D,IAAe,EAAsB,KAAK,EAE1C,IAAa,EAAO,EAAE,EAEtB,UAAmB;AAEvB,EADI,EAAM,WAAS,aAAa,EAAM,QAAQ,EAC9C,EAAM,UAAU;;AAMlB,eACc;AAEV,EADA,GAAY,EACZ,EAAW,WAAW;IAExB,EAAE,CACH;CAED,IAAM,IAAU,GACb,GAA6B,MAA+B;EAG3D,IAAM,IAAK,YAA2B;AACpC,KAAW,GAAK;AAChB,OAAI;IACF,IAAM,IAAM,MAAM,EAAY,EAC5B,WAAW,EACT,OAAO;KACL,WAAW,EAAQ;KACnB,UAAU,EAAQ;KAClB,MAAM,EAAQ;KACd,GAAI,EAAQ,SAAS,OAAkC,EAAE,GAA7B,EAAE,OAAO,EAAQ,OAAO;KACrD,EACF,EACF,CAAC;AACF,QAAI,MAAQ,EAAW,QAAS;IAChC,IAAM,IAAS,EAAI,MAAM;AACzB,QAAI,CAAC,GAAQ;AAIX,KAHA,EAAW,GAAM,EACjB,EAAa,UAAU,MACvB,EAAO,KAAK,EACZ,EACE,EAAqB,EAAI,OAAO,gDAAgD,CACjF;AACD;;AAEF,QAAI,EAAO,WAAW,WAAW;AAE/B,SADA,EAAa,YAAY,KAAK,KAAK,EAC/B,KAAK,KAAK,GAAG,EAAa,UAAA,MAAiC;AAE7D,MADA,EAAW,GAAK,EAChB,EAAM,UAAU,iBAAiB,KAAK,GAAI,EAAE,EAAqB;AACjE;;AAIF,KAFA,EAAW,GAAM,EACjB,EAAa,UAAU,MACvB,EAAO;MAAE,GAAG;MAAQ,QAAQ;MAAe,CAAC;AAC5C;;AAIF,IAFA,EAAW,GAAM,EACjB,EAAa,UAAU,MACvB,EAAO,EAAO;YACP,GAAc;AAGrB,QAAI,MAAQ,EAAW,QAAS;AAIhC,IAHA,EAAW,GAAM,EACjB,EAAa,UAAU,MACvB,EAAO,KAAK,EACZ,EAAS,EAAqB,GAAK,gDAAgD,CAAC;aAC5E;AACR,IAAI,MAAQ,EAAW,WAAS,EAAW,GAAM;;;AAGrD,SAAO,GAAI;IAEb,CAAC,EAAY,CACd;AAuBD,QAAO;EAAE;EAAK;EAAS;EAAS;EAAO,SArBvB,GACb,MAAgC;AAK1B,GAJL,GAAY,EACZ,EAAW,WAAW,GACtB,EAAa,UAAU,MACvB,EAAS,KAAK,EACT,EAAQ,GAAS,EAAW,QAAQ;KAE3C,CAAC,EAAQ,CACV;EAY+C,OAVlC,QAAkB;AAO9B,GANA,GAAY,EACZ,EAAW,WAAW,GACtB,EAAa,UAAU,MACvB,EAAO,KAAK,EACZ,EAAS,KAAK,EACd,EAAW,GAAM,EACjB,EAAW,GAAM;KAChB,EAAE,CAAC;EAEiD"}
@@ -13,7 +13,7 @@ export interface EntityEventPayload {
13
13
  entityId?: string;
14
14
  entityType?: string;
15
15
  }
16
- export type TechnoSpamEventName = 'technospam.page.viewed' | 'technospam.course.viewed' | 'technospam.course.enroll_clicked' | 'technospam.course.enrolled' | 'technospam.course.progress_updated' | 'technospam.course.certificate_claimed' | 'technospam.lesson.viewed' | 'technospam.lesson.completed' | 'technospam.problem.viewed' | 'technospam.problem.submit_clicked' | 'technospam.problem.submitted' | 'technospam.mentor.viewed' | 'technospam.mentor.book_clicked' | 'technospam.mentor.booked' | 'technospam.mentor.become_mentor_clicked' | 'technospam.mentor.became_mentor' | 'technospam.session.cancel_clicked' | 'technospam.session.cancelled' | 'technospam.session.complete_clicked' | 'technospam.session.completed' | 'technospam.hackathon.viewed' | 'technospam.hackathon.register_team_clicked' | 'technospam.hackathon.team_registered' | 'technospam.hackathon.submit_project_clicked' | 'technospam.hackathon.project_submitted' | 'technospam.search.performed';
16
+ export type TechnoSpamEventName = 'technospam.page.viewed' | 'technospam.course.viewed' | 'technospam.course.enroll_clicked' | 'technospam.course.enrolled' | 'technospam.course.progress_updated' | 'technospam.course.certificate_claimed' | 'technospam.lesson.viewed' | 'technospam.lesson.completed' | 'technospam.problem.viewed' | 'technospam.problem.run_clicked' | 'technospam.problem.submit_clicked' | 'technospam.problem.submitted' | 'technospam.mentor.viewed' | 'technospam.mentor.book_clicked' | 'technospam.mentor.booked' | 'technospam.mentor.become_mentor_clicked' | 'technospam.mentor.became_mentor' | 'technospam.session.cancel_clicked' | 'technospam.session.cancelled' | 'technospam.session.complete_clicked' | 'technospam.session.completed' | 'technospam.hackathon.viewed' | 'technospam.hackathon.register_team_clicked' | 'technospam.hackathon.team_registered' | 'technospam.hackathon.submit_project_clicked' | 'technospam.hackathon.project_submitted' | 'technospam.search.performed';
17
17
  export declare function useTechnoSpamAnalytics(): {
18
18
  emit: (name: TechnoSpamEventName, payload?: EntityEventPayload & Record<string, unknown>) => void;
19
19
  };
@@ -1 +1 @@
1
- {"version":3,"file":"useTechnoSpamAnalytics.d.ts","sourceRoot":"","sources":["../../../src/technospam/hooks/useTechnoSpamAnalytics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,MAAM,WAAW,kBAAkB;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,mBAAmB,GAC3B,wBAAwB,GACxB,0BAA0B,GAC1B,kCAAkC,GAClC,4BAA4B,GAC5B,oCAAoC,GACpC,uCAAuC,GACvC,0BAA0B,GAC1B,6BAA6B,GAC7B,2BAA2B,GAC3B,mCAAmC,GACnC,8BAA8B,GAC9B,0BAA0B,GAC1B,gCAAgC,GAChC,0BAA0B,GAC1B,yCAAyC,GACzC,iCAAiC,GACjC,mCAAmC,GACnC,8BAA8B,GAC9B,qCAAqC,GACrC,8BAA8B,GAC9B,6BAA6B,GAC7B,4CAA4C,GAC5C,sCAAsC,GACtC,6CAA6C,GAC7C,wCAAwC,GACxC,6BAA6B,CAAC;AAElC,wBAAgB,sBAAsB;iBAI3B,mBAAmB,YAAW,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;EAOpF"}
1
+ {"version":3,"file":"useTechnoSpamAnalytics.d.ts","sourceRoot":"","sources":["../../../src/technospam/hooks/useTechnoSpamAnalytics.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,MAAM,WAAW,kBAAkB;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,mBAAmB,GAC3B,wBAAwB,GACxB,0BAA0B,GAC1B,kCAAkC,GAClC,4BAA4B,GAC5B,oCAAoC,GACpC,uCAAuC,GACvC,0BAA0B,GAC1B,6BAA6B,GAC7B,2BAA2B,GAC3B,gCAAgC,GAChC,mCAAmC,GACnC,8BAA8B,GAC9B,0BAA0B,GAC1B,gCAAgC,GAChC,0BAA0B,GAC1B,yCAAyC,GACzC,iCAAiC,GACjC,mCAAmC,GACnC,8BAA8B,GAC9B,qCAAqC,GACrC,8BAA8B,GAC9B,6BAA6B,GAC7B,4CAA4C,GAC5C,sCAAsC,GACtC,6CAA6C,GAC7C,wCAAwC,GACxC,6BAA6B,CAAC;AAElC,wBAAgB,sBAAsB;iBAI3B,mBAAmB,YAAW,kBAAkB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;EAOpF"}
@@ -1 +1 @@
1
- {"version":3,"file":"useTechnoSpamAnalytics.js","names":[],"sources":["../../../src/technospam/hooks/useTechnoSpamAnalytics.ts"],"sourcesContent":["/**\n * TechnoSpam product analytics helper.\n *\n * Emits events on the shared event bus. The shell's RybbitSink forwards\n * allow-listed fact events to Rybbit Cloud; until TechnoSpam has a site ID,\n * events still flow to the bus and to backend audit / telemetry sinks.\n *\n * Pattern: emit an intent event before a mutation, then a fact event when the\n * server confirms the change.\n */\n\nimport { useCallback } from 'react';\nimport { useEventBus } from '@burdenoff/fe-libs/shared/events';\n\nexport interface EntityEventPayload {\n workspaceId?: string;\n entityId?: string;\n entityType?: string;\n}\n\nexport type TechnoSpamEventName =\n | 'technospam.page.viewed'\n | 'technospam.course.viewed'\n | 'technospam.course.enroll_clicked'\n | 'technospam.course.enrolled'\n | 'technospam.course.progress_updated'\n | 'technospam.course.certificate_claimed'\n | 'technospam.lesson.viewed'\n | 'technospam.lesson.completed'\n | 'technospam.problem.viewed'\n | 'technospam.problem.submit_clicked'\n | 'technospam.problem.submitted'\n | 'technospam.mentor.viewed'\n | 'technospam.mentor.book_clicked'\n | 'technospam.mentor.booked'\n | 'technospam.mentor.become_mentor_clicked'\n | 'technospam.mentor.became_mentor'\n | 'technospam.session.cancel_clicked'\n | 'technospam.session.cancelled'\n | 'technospam.session.complete_clicked'\n | 'technospam.session.completed'\n | 'technospam.hackathon.viewed'\n | 'technospam.hackathon.register_team_clicked'\n | 'technospam.hackathon.team_registered'\n | 'technospam.hackathon.submit_project_clicked'\n | 'technospam.hackathon.project_submitted'\n | 'technospam.search.performed';\n\nexport function useTechnoSpamAnalytics() {\n const bus = useEventBus();\n\n const emit = useCallback(\n (name: TechnoSpamEventName, payload: EntityEventPayload & Record<string, unknown> = {}) => {\n bus.emitCustom(name, payload, { component: 'microfe-technospam' });\n },\n [bus]\n );\n\n return { emit };\n}\n"],"mappings":";;;AAgDA,SAAgB,IAAyB;CACvC,IAAM,IAAM,GAAa;AASzB,QAAO,EAAE,MAPI,GACV,GAA2B,IAAwD,EAAE,KAAK;AACzF,IAAI,WAAW,GAAM,GAAS,EAAE,WAAW,sBAAsB,CAAC;IAEpE,CAAC,EAAI,CACN,EAEc"}
1
+ {"version":3,"file":"useTechnoSpamAnalytics.js","names":[],"sources":["../../../src/technospam/hooks/useTechnoSpamAnalytics.ts"],"sourcesContent":["/**\n * TechnoSpam product analytics helper.\n *\n * Emits events on the shared event bus. The shell's RybbitSink forwards\n * allow-listed fact events to Rybbit Cloud; until TechnoSpam has a site ID,\n * events still flow to the bus and to backend audit / telemetry sinks.\n *\n * Pattern: emit an intent event before a mutation, then a fact event when the\n * server confirms the change.\n */\n\nimport { useCallback } from 'react';\nimport { useEventBus } from '@burdenoff/fe-libs/shared/events';\n\nexport interface EntityEventPayload {\n workspaceId?: string;\n entityId?: string;\n entityType?: string;\n}\n\nexport type TechnoSpamEventName =\n | 'technospam.page.viewed'\n | 'technospam.course.viewed'\n | 'technospam.course.enroll_clicked'\n | 'technospam.course.enrolled'\n | 'technospam.course.progress_updated'\n | 'technospam.course.certificate_claimed'\n | 'technospam.lesson.viewed'\n | 'technospam.lesson.completed'\n | 'technospam.problem.viewed'\n | 'technospam.problem.run_clicked'\n | 'technospam.problem.submit_clicked'\n | 'technospam.problem.submitted'\n | 'technospam.mentor.viewed'\n | 'technospam.mentor.book_clicked'\n | 'technospam.mentor.booked'\n | 'technospam.mentor.become_mentor_clicked'\n | 'technospam.mentor.became_mentor'\n | 'technospam.session.cancel_clicked'\n | 'technospam.session.cancelled'\n | 'technospam.session.complete_clicked'\n | 'technospam.session.completed'\n | 'technospam.hackathon.viewed'\n | 'technospam.hackathon.register_team_clicked'\n | 'technospam.hackathon.team_registered'\n | 'technospam.hackathon.submit_project_clicked'\n | 'technospam.hackathon.project_submitted'\n | 'technospam.search.performed';\n\nexport function useTechnoSpamAnalytics() {\n const bus = useEventBus();\n\n const emit = useCallback(\n (name: TechnoSpamEventName, payload: EntityEventPayload & Record<string, unknown> = {}) => {\n bus.emitCustom(name, payload, { component: 'microfe-technospam' });\n },\n [bus]\n );\n\n return { emit };\n}\n"],"mappings":";;;AAiDA,SAAgB,IAAyB;CACvC,IAAM,IAAM,GAAa;AASzB,QAAO,EAAE,MAPI,GACV,GAA2B,IAAwD,EAAE,KAAK;AACzF,IAAI,WAAW,GAAM,GAAS,EAAE,WAAW,sBAAsB,CAAC;IAEpE,CAAC,EAAI,CACN,EAEc"}
@@ -71,7 +71,7 @@ function $({ label: e, required: t, className: n, children: r }) {
71
71
  }
72
72
  function Ve({ seed: e, icon: n }) {
73
73
  return /* @__PURE__ */ q("span", {
74
- className: t("flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-gradient-to-br text-white shadow-sm", r(e)),
74
+ className: t("flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-gradient-to-br text-action-primary-text shadow-sm", r(e)),
75
75
  children: /* @__PURE__ */ q(n, {
76
76
  size: 18,
77
77
  strokeWidth: 2