@tipp/ui 2.9.0 → 2.10.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.
Files changed (198) hide show
  1. package/dist/app/index.js +17 -17
  2. package/dist/app/platform/edit-coaching-time.js +17 -17
  3. package/dist/app/platform/edit-service-type.js +17 -17
  4. package/dist/app/platform/goal-manage-card-edit.js +17 -17
  5. package/dist/app/platform/on-offline-radio-card.js +17 -17
  6. package/dist/app/platform/reservation-card.js +17 -17
  7. package/dist/app/platform/session-card.js +17 -17
  8. package/dist/app/roleplay/chart/session-chart.cjs +351 -0
  9. package/dist/app/roleplay/chart/session-chart.cjs.map +1 -0
  10. package/dist/app/roleplay/chart/session-chart.d.cts +16 -0
  11. package/dist/app/roleplay/chart/session-chart.d.ts +16 -0
  12. package/dist/app/roleplay/chart/session-chart.js +14 -0
  13. package/dist/app/roleplay/chart/session-chart.js.map +1 -0
  14. package/dist/app/roleplay/index.cjs +5715 -0
  15. package/dist/app/roleplay/index.cjs.map +1 -0
  16. package/dist/app/roleplay/index.d.cts +4 -0
  17. package/dist/app/roleplay/index.d.ts +4 -0
  18. package/dist/app/roleplay/index.js +182 -0
  19. package/dist/app/roleplay/index.js.map +1 -0
  20. package/dist/app/roleplay/parts/analysis-section.cjs +2178 -0
  21. package/dist/app/roleplay/parts/analysis-section.cjs.map +1 -0
  22. package/dist/app/roleplay/parts/analysis-section.d.cts +17 -0
  23. package/dist/app/roleplay/parts/analysis-section.d.ts +17 -0
  24. package/dist/app/roleplay/parts/analysis-section.js +97 -0
  25. package/dist/app/roleplay/parts/analysis-section.js.map +1 -0
  26. package/dist/app/roleplay/parts/coaching-panel.cjs +2191 -0
  27. package/dist/app/roleplay/parts/coaching-panel.cjs.map +1 -0
  28. package/dist/app/roleplay/parts/coaching-panel.d.cts +8 -0
  29. package/dist/app/roleplay/parts/coaching-panel.d.ts +8 -0
  30. package/dist/app/roleplay/parts/coaching-panel.js +95 -0
  31. package/dist/app/roleplay/parts/coaching-panel.js.map +1 -0
  32. package/dist/app/roleplay/parts/content.cjs +4687 -0
  33. package/dist/app/roleplay/parts/content.cjs.map +1 -0
  34. package/dist/app/roleplay/parts/content.d.cts +15 -0
  35. package/dist/app/roleplay/parts/content.d.ts +15 -0
  36. package/dist/app/roleplay/parts/content.js +174 -0
  37. package/dist/app/roleplay/parts/content.js.map +1 -0
  38. package/dist/app/roleplay/parts/header.cjs +2300 -0
  39. package/dist/app/roleplay/parts/header.cjs.map +1 -0
  40. package/dist/app/roleplay/parts/header.d.cts +13 -0
  41. package/dist/app/roleplay/parts/header.d.ts +13 -0
  42. package/dist/app/roleplay/parts/header.js +96 -0
  43. package/dist/app/roleplay/parts/header.js.map +1 -0
  44. package/dist/app/roleplay/parts/score-summary.cjs +2276 -0
  45. package/dist/app/roleplay/parts/score-summary.cjs.map +1 -0
  46. package/dist/app/roleplay/parts/score-summary.d.cts +12 -0
  47. package/dist/app/roleplay/parts/score-summary.d.ts +12 -0
  48. package/dist/app/roleplay/parts/score-summary.js +96 -0
  49. package/dist/app/roleplay/parts/score-summary.js.map +1 -0
  50. package/dist/app/roleplay/parts/score-trend-section.cjs +3687 -0
  51. package/dist/app/roleplay/parts/score-trend-section.cjs.map +1 -0
  52. package/dist/app/roleplay/parts/score-trend-section.d.cts +14 -0
  53. package/dist/app/roleplay/parts/score-trend-section.d.ts +14 -0
  54. package/dist/app/roleplay/parts/score-trend-section.js +167 -0
  55. package/dist/app/roleplay/parts/score-trend-section.js.map +1 -0
  56. package/dist/app/roleplay/parts/script-transcript.cjs +2288 -0
  57. package/dist/app/roleplay/parts/script-transcript.cjs.map +1 -0
  58. package/dist/app/roleplay/parts/script-transcript.d.cts +15 -0
  59. package/dist/app/roleplay/parts/script-transcript.d.ts +15 -0
  60. package/dist/app/roleplay/parts/script-transcript.js +96 -0
  61. package/dist/app/roleplay/parts/script-transcript.js.map +1 -0
  62. package/dist/app/roleplay/parts/section-nav.cjs +2433 -0
  63. package/dist/app/roleplay/parts/section-nav.cjs.map +1 -0
  64. package/dist/app/roleplay/parts/section-nav.d.cts +15 -0
  65. package/dist/app/roleplay/parts/section-nav.d.ts +15 -0
  66. package/dist/app/roleplay/parts/section-nav.js +96 -0
  67. package/dist/app/roleplay/parts/section-nav.js.map +1 -0
  68. package/dist/app/roleplay/parts/session-replay-dialog.cjs +2598 -0
  69. package/dist/app/roleplay/parts/session-replay-dialog.cjs.map +1 -0
  70. package/dist/app/roleplay/parts/session-replay-dialog.d.cts +14 -0
  71. package/dist/app/roleplay/parts/session-replay-dialog.d.ts +14 -0
  72. package/dist/app/roleplay/parts/session-replay-dialog.js +97 -0
  73. package/dist/app/roleplay/parts/session-replay-dialog.js.map +1 -0
  74. package/dist/app/roleplay/parts/step-detail.cjs +2311 -0
  75. package/dist/app/roleplay/parts/step-detail.cjs.map +1 -0
  76. package/dist/app/roleplay/parts/step-detail.d.cts +9 -0
  77. package/dist/app/roleplay/parts/step-detail.d.ts +9 -0
  78. package/dist/app/roleplay/parts/step-detail.js +96 -0
  79. package/dist/app/roleplay/parts/step-detail.js.map +1 -0
  80. package/dist/app/roleplay/parts/step-radar.cjs +463 -0
  81. package/dist/app/roleplay/parts/step-radar.cjs.map +1 -0
  82. package/dist/app/roleplay/parts/step-radar.d.cts +8 -0
  83. package/dist/app/roleplay/parts/step-radar.d.ts +8 -0
  84. package/dist/app/roleplay/parts/step-radar.js +14 -0
  85. package/dist/app/roleplay/parts/step-radar.js.map +1 -0
  86. package/dist/app/roleplay/parts/step-summary.cjs +2651 -0
  87. package/dist/app/roleplay/parts/step-summary.cjs.map +1 -0
  88. package/dist/app/roleplay/parts/step-summary.d.cts +8 -0
  89. package/dist/app/roleplay/parts/step-summary.d.ts +8 -0
  90. package/dist/app/roleplay/parts/step-summary.js +101 -0
  91. package/dist/app/roleplay/parts/step-summary.js.map +1 -0
  92. package/dist/app/roleplay/rp-session-detail.cjs +5712 -0
  93. package/dist/app/roleplay/rp-session-detail.cjs.map +1 -0
  94. package/dist/app/roleplay/rp-session-detail.d.cts +17 -0
  95. package/dist/app/roleplay/rp-session-detail.d.ts +17 -0
  96. package/dist/app/roleplay/rp-session-detail.js +179 -0
  97. package/dist/app/roleplay/rp-session-detail.js.map +1 -0
  98. package/dist/app/roleplay/types.cjs +19 -0
  99. package/dist/app/roleplay/types.cjs.map +1 -0
  100. package/dist/app/roleplay/types.d.cts +42 -0
  101. package/dist/app/roleplay/types.d.ts +42 -0
  102. package/dist/app/roleplay/types.js +2 -0
  103. package/dist/app/roleplay/types.js.map +1 -0
  104. package/dist/app/roleplay/utils/report-parse.cjs +285 -0
  105. package/dist/app/roleplay/utils/report-parse.cjs.map +1 -0
  106. package/dist/app/roleplay/utils/report-parse.d.cts +57 -0
  107. package/dist/app/roleplay/utils/report-parse.d.ts +57 -0
  108. package/dist/app/roleplay/utils/report-parse.js +8 -0
  109. package/dist/app/roleplay/utils/report-parse.js.map +1 -0
  110. package/dist/app/roleplay/utils/report-parse.test.cjs +491 -0
  111. package/dist/app/roleplay/utils/report-parse.test.cjs.map +1 -0
  112. package/dist/app/roleplay/utils/report-parse.test.d.cts +2 -0
  113. package/dist/app/roleplay/utils/report-parse.test.d.ts +2 -0
  114. package/dist/app/roleplay/utils/report-parse.test.js +237 -0
  115. package/dist/app/roleplay/utils/report-parse.test.js.map +1 -0
  116. package/dist/app/roleplay/utils/session-utils.cjs +204 -0
  117. package/dist/app/roleplay/utils/session-utils.cjs.map +1 -0
  118. package/dist/app/roleplay/utils/session-utils.d.cts +38 -0
  119. package/dist/app/roleplay/utils/session-utils.d.ts +38 -0
  120. package/dist/app/roleplay/utils/session-utils.js +46 -0
  121. package/dist/app/roleplay/utils/session-utils.js.map +1 -0
  122. package/dist/chunk-32WIS4L7.js +131 -0
  123. package/dist/chunk-32WIS4L7.js.map +1 -0
  124. package/dist/chunk-3UGBMKSQ.js +166 -0
  125. package/dist/chunk-3UGBMKSQ.js.map +1 -0
  126. package/dist/chunk-4YAA25AV.js +161 -0
  127. package/dist/chunk-4YAA25AV.js.map +1 -0
  128. package/dist/chunk-5QIT4URV.js +87 -0
  129. package/dist/chunk-5QIT4URV.js.map +1 -0
  130. package/dist/chunk-6YIKOYBQ.js +185 -0
  131. package/dist/chunk-6YIKOYBQ.js.map +1 -0
  132. package/dist/chunk-7MXY3D3Z.js +84 -0
  133. package/dist/chunk-7MXY3D3Z.js.map +1 -0
  134. package/dist/chunk-EBFQFOUQ.js +138 -0
  135. package/dist/chunk-EBFQFOUQ.js.map +1 -0
  136. package/dist/chunk-EHDUKUML.js +183 -0
  137. package/dist/chunk-EHDUKUML.js.map +1 -0
  138. package/dist/{chunk-NEJCZABQ.js → chunk-FJEDSUGU.js} +7 -7
  139. package/dist/chunk-GA6W62DO.js +101 -0
  140. package/dist/chunk-GA6W62DO.js.map +1 -0
  141. package/dist/chunk-KJPBBBVK.js +142 -0
  142. package/dist/chunk-KJPBBBVK.js.map +1 -0
  143. package/dist/{chunk-TQTCT7DC.js → chunk-LRNO4W2P.js} +5 -5
  144. package/dist/{chunk-6DWUGXSY.js → chunk-N242VJOP.js} +2 -2
  145. package/dist/chunk-NKW6BO5R.js +264 -0
  146. package/dist/chunk-NKW6BO5R.js.map +1 -0
  147. package/dist/{chunk-R5UDNKV2.js → chunk-O332K3SW.js} +2 -2
  148. package/dist/chunk-OUP3VFXG.js +1 -0
  149. package/dist/chunk-OUP3VFXG.js.map +1 -0
  150. package/dist/chunk-QMAINJ4G.js +190 -0
  151. package/dist/chunk-QMAINJ4G.js.map +1 -0
  152. package/dist/{chunk-KLJVIEFW.js → chunk-SOKGYD5B.js} +7 -7
  153. package/dist/chunk-TFJJKM3W.js +261 -0
  154. package/dist/chunk-TFJJKM3W.js.map +1 -0
  155. package/dist/{chunk-KQ3ME6XY.js → chunk-U2EAXN3Y.js} +4 -4
  156. package/dist/chunk-UXAEOCOH.js +150 -0
  157. package/dist/chunk-UXAEOCOH.js.map +1 -0
  158. package/dist/chunk-YHP75Y5K.js +242 -0
  159. package/dist/chunk-YHP75Y5K.js.map +1 -0
  160. package/dist/chunk-ZE36DFOC.js +142 -0
  161. package/dist/chunk-ZE36DFOC.js.map +1 -0
  162. package/dist/index.css +76 -0
  163. package/dist/index.js +32 -32
  164. package/dist/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/ReviewQuestion/index.js +5 -5
  165. package/dist/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/ReviewQuestion/review-question-body.js +2 -2
  166. package/dist/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/index.js +7 -7
  167. package/dist/molecules/curriculumV2/CurriculumContents/curriculum-review.js +8 -8
  168. package/dist/molecules/curriculumV2/CurriculumContents/index.js +9 -9
  169. package/dist/molecules/curriculumV2/index.js +11 -11
  170. package/dist/molecules/dynamic-form-editor.js +2 -2
  171. package/dist/molecules/index.js +29 -29
  172. package/package.json +28 -2
  173. package/src/app/roleplay/chart/session-chart.tsx +185 -0
  174. package/src/app/roleplay/index.ts +8 -0
  175. package/src/app/roleplay/parts/analysis-section.tsx +98 -0
  176. package/src/app/roleplay/parts/coaching-panel.tsx +101 -0
  177. package/src/app/roleplay/parts/content.tsx +146 -0
  178. package/src/app/roleplay/parts/header.tsx +168 -0
  179. package/src/app/roleplay/parts/score-summary.tsx +158 -0
  180. package/src/app/roleplay/parts/score-trend-section.tsx +265 -0
  181. package/src/app/roleplay/parts/script-transcript.tsx +190 -0
  182. package/src/app/roleplay/parts/section-nav.tsx +299 -0
  183. package/src/app/roleplay/parts/session-replay-dialog.tsx +168 -0
  184. package/src/app/roleplay/parts/step-detail.tsx +173 -0
  185. package/src/app/roleplay/parts/step-radar.tsx +80 -0
  186. package/src/app/roleplay/parts/step-summary.tsx +149 -0
  187. package/src/app/roleplay/rp-session-detail.tsx +176 -0
  188. package/src/app/roleplay/types.ts +61 -0
  189. package/src/app/roleplay/utils/report-parse.test.ts +268 -0
  190. package/src/app/roleplay/utils/report-parse.ts +443 -0
  191. package/src/app/roleplay/utils/session-utils.ts +215 -0
  192. package/src/constrant/trainingLog.dummy.json +1 -0
  193. /package/dist/{chunk-NEJCZABQ.js.map → chunk-FJEDSUGU.js.map} +0 -0
  194. /package/dist/{chunk-TQTCT7DC.js.map → chunk-LRNO4W2P.js.map} +0 -0
  195. /package/dist/{chunk-6DWUGXSY.js.map → chunk-N242VJOP.js.map} +0 -0
  196. /package/dist/{chunk-R5UDNKV2.js.map → chunk-O332K3SW.js.map} +0 -0
  197. /package/dist/{chunk-KLJVIEFW.js.map → chunk-SOKGYD5B.js.map} +0 -0
  198. /package/dist/{chunk-KQ3ME6XY.js.map → chunk-U2EAXN3Y.js.map} +0 -0
@@ -0,0 +1,261 @@
1
+ // src/app/roleplay/utils/report-parse.ts
2
+ var QUALITIES = ["\uCDA9\uC871", "\uBD80\uBD84\uCDA9\uC871", "\uBBF8\uD761"];
3
+ function isObject(v) {
4
+ return typeof v === "object" && v !== null && !Array.isArray(v);
5
+ }
6
+ function isUnknownArray(v) {
7
+ return Array.isArray(v);
8
+ }
9
+ function asString(v) {
10
+ if (typeof v !== "string") return null;
11
+ const t = v.trim();
12
+ return t.length > 0 ? t : null;
13
+ }
14
+ function asNumber(v) {
15
+ return typeof v === "number" && Number.isFinite(v) ? v : null;
16
+ }
17
+ function asQuality(v) {
18
+ var _a;
19
+ const t = asString(v);
20
+ if (t === null) return null;
21
+ return (_a = QUALITIES.find((q) => q === t)) != null ? _a : null;
22
+ }
23
+ function asGuidelineText(v) {
24
+ if (isUnknownArray(v)) {
25
+ const parts = v.map(asString).filter((s) => s !== null && s !== "-");
26
+ return parts.length > 0 ? parts.join("\n") : null;
27
+ }
28
+ const t = asString(v);
29
+ return t !== null && t !== "-" ? t : null;
30
+ }
31
+ function humanize(key) {
32
+ return key.split("_").filter((p) => p.length > 0).map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join(" ");
33
+ }
34
+ var STEP_SUFFIXES = [
35
+ "max_score",
36
+ "maxscore",
37
+ "max",
38
+ "score",
39
+ "basis",
40
+ "issue",
41
+ "improve",
42
+ "example",
43
+ "quality"
44
+ ];
45
+ function splitStepKey(key) {
46
+ for (const suffix of STEP_SUFFIXES) {
47
+ const tail = `_${suffix}`;
48
+ if (key.endsWith(tail) && key.length > tail.length) {
49
+ return { prefix: key.slice(0, -tail.length), suffix };
50
+ }
51
+ }
52
+ return null;
53
+ }
54
+ function readGuidelineEntries(guideline) {
55
+ if (!isObject(guideline) || !isUnknownArray(guideline.value)) return [];
56
+ const entries = guideline.value.map((v) => {
57
+ if (!isObject(v)) return { title: null, description: null, example: null };
58
+ const title = asString(v.title);
59
+ return {
60
+ title: title === "-" ? null : title,
61
+ description: asGuidelineText(v.description),
62
+ example: asGuidelineText(v.example)
63
+ };
64
+ });
65
+ if (entries.every((e) => e.title === null)) return [];
66
+ return entries;
67
+ }
68
+ function buildFieldsMap(itemObj) {
69
+ var _a;
70
+ const order = [];
71
+ const fields = /* @__PURE__ */ new Map();
72
+ for (const [key, value] of Object.entries(itemObj)) {
73
+ const split = splitStepKey(key);
74
+ if (!split) continue;
75
+ if (!fields.has(split.prefix)) {
76
+ fields.set(split.prefix, /* @__PURE__ */ new Map());
77
+ order.push(split.prefix);
78
+ }
79
+ (_a = fields.get(split.prefix)) == null ? void 0 : _a.set(split.suffix, value);
80
+ }
81
+ return { order, fields };
82
+ }
83
+ function buildStep(key, f, meta) {
84
+ var _a, _b, _c;
85
+ const qualityRaw = f.get("quality");
86
+ return {
87
+ key,
88
+ label: meta.label,
89
+ initial: meta.initial,
90
+ description: meta.description,
91
+ idealExample: meta.idealExample,
92
+ score: asNumber(f.get("score")),
93
+ // reportData 의 실제 만점이 우선, 없으면 displayMeta.maxValue 폴백.
94
+ maxScore: (_c = asNumber((_b = (_a = f.get("max_score")) != null ? _a : f.get("maxscore")) != null ? _b : f.get("max"))) != null ? _c : meta.maxScoreFallback,
95
+ quality: asQuality(qualityRaw),
96
+ qualityLabel: asString(qualityRaw),
97
+ basis: asString(f.get("basis")),
98
+ issue: asString(f.get("issue")),
99
+ improve: asString(f.get("improve")),
100
+ example: asString(f.get("example"))
101
+ };
102
+ }
103
+ function extractSteps(itemObj, guideline, displaySteps) {
104
+ const { order, fields } = buildFieldsMap(itemObj);
105
+ const entries = readGuidelineEntries(guideline);
106
+ if (displaySteps.length > 0) {
107
+ const useGuideline2 = entries.length === displaySteps.length;
108
+ return displaySteps.map((ds, i) => {
109
+ var _a, _b, _c;
110
+ const f = (_a = fields.get(ds.key)) != null ? _a : /* @__PURE__ */ new Map();
111
+ const entry = useGuideline2 ? entries[i] : null;
112
+ const dsDescription = ds.description.trim().length > 0 ? ds.description : null;
113
+ return buildStep(ds.key, f, {
114
+ label: ds.displayName,
115
+ initial: ds.initial.trim().length > 0 ? ds.initial : null,
116
+ description: (_b = dsDescription != null ? dsDescription : entry == null ? void 0 : entry.description) != null ? _b : null,
117
+ idealExample: (_c = entry == null ? void 0 : entry.example) != null ? _c : null,
118
+ maxScoreFallback: ds.maxValue > 0 ? ds.maxValue : null
119
+ });
120
+ });
121
+ }
122
+ const useGuideline = entries.length === order.length;
123
+ return order.map((prefix, i) => {
124
+ var _a, _b, _c, _d;
125
+ const f = (_a = fields.get(prefix)) != null ? _a : /* @__PURE__ */ new Map();
126
+ const entry = useGuideline ? entries[i] : null;
127
+ return buildStep(prefix, f, {
128
+ label: (_b = entry == null ? void 0 : entry.title) != null ? _b : humanize(prefix),
129
+ initial: null,
130
+ description: (_c = entry == null ? void 0 : entry.description) != null ? _c : null,
131
+ idealExample: (_d = entry == null ? void 0 : entry.example) != null ? _d : null,
132
+ maxScoreFallback: null
133
+ });
134
+ });
135
+ }
136
+ function readDisplayMeta(raw) {
137
+ var _a, _b, _c, _d, _e;
138
+ if (!isObject(raw)) return { title: null, description: null, steps: [] };
139
+ const steps = [];
140
+ if (isUnknownArray(raw.steps)) {
141
+ for (const s of raw.steps) {
142
+ if (!isObject(s)) continue;
143
+ const key = asString(s.key);
144
+ if (key === null) continue;
145
+ steps.push({
146
+ order: (_a = asNumber(s.order)) != null ? _a : steps.length,
147
+ key,
148
+ initial: (_b = asString(s.initial)) != null ? _b : "",
149
+ displayName: (_c = asString(s.displayName)) != null ? _c : humanize(key),
150
+ maxValue: (_d = asNumber(s.maxValue)) != null ? _d : 0,
151
+ description: (_e = asString(s.description)) != null ? _e : ""
152
+ });
153
+ }
154
+ steps.sort((a, b) => a.order - b.order);
155
+ }
156
+ return {
157
+ title: asString(raw.title),
158
+ description: asString(raw.description),
159
+ steps
160
+ };
161
+ }
162
+ function flattenNumberedPairs(obj, titleBase, detailBase) {
163
+ var _a;
164
+ const out = [];
165
+ for (let n = 1; ; n += 1) {
166
+ const title = asString(obj[`${titleBase}${n}`]);
167
+ if (title === null) break;
168
+ out.push({ title, detail: (_a = asString(obj[`${detailBase}${n}`])) != null ? _a : "" });
169
+ }
170
+ return out;
171
+ }
172
+ var ANALYSIS_PAIR_CANDIDATES = [
173
+ ["title", "detail"],
174
+ ["improvement_title", "improvement_action"],
175
+ ["issue_title", "issue_detail"]
176
+ ];
177
+ function flattenAnalysis(source) {
178
+ if (!isUnknownArray(source)) return [];
179
+ const out = [];
180
+ for (const obj of source) {
181
+ if (!isObject(obj)) continue;
182
+ for (const [titleBase, detailBase] of ANALYSIS_PAIR_CANDIDATES) {
183
+ const items = flattenNumberedPairs(obj, titleBase, detailBase);
184
+ if (items.length > 0) {
185
+ out.push(...items);
186
+ break;
187
+ }
188
+ }
189
+ }
190
+ return out;
191
+ }
192
+ function flattenSkills(source) {
193
+ var _a, _b;
194
+ if (!isUnknownArray(source)) return [];
195
+ const out = [];
196
+ for (const obj of source) {
197
+ if (!isObject(obj)) continue;
198
+ for (let n = 1; ; n += 1) {
199
+ const title = asString(obj[`skill${n}`]);
200
+ if (title === null) break;
201
+ out.push({
202
+ title,
203
+ description: (_a = asString(obj[`description${n}`])) != null ? _a : "",
204
+ example: (_b = asString(obj[`example${n}`])) != null ? _b : ""
205
+ });
206
+ }
207
+ }
208
+ return out;
209
+ }
210
+ function readDeduction(summary) {
211
+ if (!summary || !isObject(summary.deduction)) return null;
212
+ const score = asNumber(summary.deduction.score);
213
+ const basis = asString(summary.deduction.basis);
214
+ if (score === null || basis === null) return null;
215
+ return { score, basis };
216
+ }
217
+ function unwrapOutputText(reportData) {
218
+ if (!isObject(reportData)) return {};
219
+ return isObject(reportData.output_text) ? reportData.output_text : reportData;
220
+ }
221
+ function findItemsArray(root) {
222
+ for (const [key, value] of Object.entries(root)) {
223
+ if (!key.endsWith("_items") || !isUnknownArray(value)) continue;
224
+ const first = value[0];
225
+ if (isObject(first)) return first;
226
+ }
227
+ return null;
228
+ }
229
+ function parseReportData(reportData, guideline, displayMeta) {
230
+ var _a, _b, _c, _d;
231
+ const root = unwrapOutputText(reportData);
232
+ const meta = readDisplayMeta(displayMeta);
233
+ const summary = isObject(root.summary) ? root.summary : null;
234
+ const comprehensive = isObject(root.comprehensive_analysis) ? root.comprehensive_analysis : null;
235
+ const comment = (_b = (_a = asString(comprehensive == null ? void 0 : comprehensive.comment)) != null ? _a : asString(summary == null ? void 0 : summary.comment)) != null ? _b : asString(summary == null ? void 0 : summary.basis);
236
+ const strengths = flattenAnalysis(
237
+ (_c = comprehensive == null ? void 0 : comprehensive.strengths) != null ? _c : summary == null ? void 0 : summary.good_point
238
+ );
239
+ const improvements = flattenAnalysis(
240
+ (_d = comprehensive == null ? void 0 : comprehensive.improvements) != null ? _d : summary == null ? void 0 : summary.improvement
241
+ );
242
+ const itemObj = findItemsArray(root);
243
+ const steps = itemObj ? extractSteps(itemObj, guideline, meta.steps) : [];
244
+ return {
245
+ frameworkTitle: meta.title,
246
+ frameworkDescription: meta.description,
247
+ todayDate: asString(root.todayDate),
248
+ totalScore: asNumber(summary == null ? void 0 : summary.total_score),
249
+ comment,
250
+ deduction: readDeduction(summary),
251
+ strengths,
252
+ improvements,
253
+ steps,
254
+ skills: flattenSkills(root.skills)
255
+ };
256
+ }
257
+
258
+ export {
259
+ parseReportData
260
+ };
261
+ //# sourceMappingURL=chunk-TFJJKM3W.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/app/roleplay/utils/report-parse.ts"],"sourcesContent":["// 롤플레잉 평가 리포트(reportData) 제네릭 파서.\n//\n// 보고서 타입(reportType)은 계속 추가되며 그때마다 프론트를 수정할 수 없다.\n// 따라서 프레임워크명 분기 없이 reportData 의 \"키 패턴\"만으로 해석한다.\n//\n// 입력 형태(프레임워크 공통, outputSchema 실측):\n// reportData = { output_text: { todayDate, summary, {name}_items:[{...}], skills:[{...}],\n// comprehensive_analysis? }, ai_traininglog_id }\n// - {name}_items[0] 안에 모든 단계가 `${step}_score|_basis|_issue|_improve|_example|_quality` 평면 필드로 존재\n// - 단계 라벨은 guideline.value[i].title (길이 일치 가드, 없으면 키 humanize 폴백)\n\n/* ───────────────────────── 출력 타입 ───────────────────────── */\n\nconst QUALITIES = ['충족', '부분충족', '미흡'] as const;\nexport type RpQuality = (typeof QUALITIES)[number];\n\nexport interface RpReportStep {\n key: string; // 단계 prefix (예: 'own', 'nurturing_org')\n label: string; // displayMeta.steps.displayName → guideline 제목 → humanize 된 키\n initial: string | null; // displayMeta.steps.initial. 없으면 null → session-utils stepCode 휴리스틱 폴백\n description: string | null; // displayMeta.steps.description → guideline 단계 설명\n idealExample: string | null; // guideline 모범 예시(있을 때)\n score: number | null;\n maxScore: number | null; // 신버전 리포트만 제공(구버전은 null) → 있으면 score/maxScore 표시\n quality: RpQuality | null; // 표준 등급(충족/부분충족/미흡)일 때만. 색·정규화 비율 산출용\n qualityLabel: string | null; // 원문 등급 문자열 그대로(예: 'X 매우 미흡'). 표시용\n basis: string | null;\n issue: string | null;\n improve: string | null;\n example: string | null; // reportData 의 단계별 예시 스크립트\n}\n\nexport interface RpReportAnalysisItem {\n title: string;\n detail: string;\n}\n\nexport interface RpReportSkill {\n title: string;\n description: string;\n example: string;\n}\n\nexport interface RpReport {\n frameworkTitle: string | null; // displayMeta.title — 프레임워크 제목(지표와 별개). 없으면 null\n frameworkDescription: string | null; // displayMeta.description — 프레임워크 설명문. 없으면 null\n todayDate: string | null;\n totalScore: number | null;\n comment: string | null;\n deduction: { score: number; basis: string } | null;\n strengths: RpReportAnalysisItem[];\n improvements: RpReportAnalysisItem[];\n steps: RpReportStep[];\n skills: RpReportSkill[];\n}\n\n/* ───────────────────────── displayMeta (framework 표시 메타) ───────────────────────── */\n\n// framework.displayMeta = { title?, description?, steps:[{order,key,initial,displayName,maxValue,description}] }\n// title/description은 프레임워크 자체(지표와 별개). steps는 지표별 표시 메타.\n// 없거나 형식 불일치면 폴백(기존 동작).\nexport interface RpDisplayMetaStep {\n order: number;\n key: string; // = outputSchema {prefix}_score 의 prefix\n initial: string;\n displayName: string;\n maxValue: number;\n description: string;\n}\n\nexport interface RpDisplayMeta {\n title?: string;\n description?: string;\n steps: RpDisplayMetaStep[];\n}\n\n/* ───────────────────────── 원시 헬퍼 ───────────────────────── */\n\nfunction isObject(v: unknown): v is Record<string, unknown> {\n return typeof v === 'object' && v !== null && !Array.isArray(v);\n}\n\n// Array.isArray 는 any[] 로 좁혀 unsafe 접근을 유발한다. unknown[] 로 좁히는 가드.\nfunction isUnknownArray(v: unknown): v is unknown[] {\n return Array.isArray(v);\n}\n\nfunction asString(v: unknown): string | null {\n if (typeof v !== 'string') return null;\n const t = v.trim();\n return t.length > 0 ? t : null;\n}\n\nfunction asNumber(v: unknown): number | null {\n return typeof v === 'number' && Number.isFinite(v) ? v : null;\n}\n\nfunction asQuality(v: unknown): RpQuality | null {\n const t = asString(v);\n if (t === null) return null;\n return QUALITIES.find((q) => q === t) ?? null;\n}\n\n// guideline 의 example 은 string | string[] 모두 가능. '-' 플레이스홀더는 무시.\nfunction asGuidelineText(v: unknown): string | null {\n if (isUnknownArray(v)) {\n const parts = v\n .map(asString)\n .filter((s): s is string => s !== null && s !== '-');\n return parts.length > 0 ? parts.join('\\n') : null;\n }\n const t = asString(v);\n return t !== null && t !== '-' ? t : null;\n}\n\nfunction humanize(key: string): string {\n return key\n .split('_')\n .filter((p) => p.length > 0)\n .map((p) => p.charAt(0).toUpperCase() + p.slice(1))\n .join(' ');\n}\n\n/* ───────────────────────── 단계 추출 ───────────────────────── */\n\n// ⚠ 순서 중요: 더 긴/구체 suffix를 먼저 둬야 한다.\n// 예) 'action_max_score' 는 '_score'보다 '_max_score' 가 먼저 매칭돼야\n// prefix='action_max'(오인) 가 아니라 prefix='action', suffix='max_score' 로 잡힌다.\nconst STEP_SUFFIXES = [\n 'max_score',\n 'maxscore',\n 'max',\n 'score',\n 'basis',\n 'issue',\n 'improve',\n 'example',\n 'quality',\n] as const;\ntype StepSuffix = (typeof STEP_SUFFIXES)[number];\n\nfunction splitStepKey(\n key: string\n): { prefix: string; suffix: StepSuffix } | null {\n for (const suffix of STEP_SUFFIXES) {\n const tail = `_${suffix}`;\n if (key.endsWith(tail) && key.length > tail.length) {\n return { prefix: key.slice(0, -tail.length), suffix };\n }\n }\n return null;\n}\n\ninterface GuidelineEntry {\n title: string | null;\n description: string | null;\n example: string | null;\n}\n\n// guideline = { value: [{title, example, description}], version }. 미작성/길이불일치면 빈 배열 취급(=폴백).\nfunction readGuidelineEntries(guideline: unknown): GuidelineEntry[] {\n if (!isObject(guideline) || !isUnknownArray(guideline.value)) return [];\n const entries: GuidelineEntry[] = guideline.value.map((v) => {\n if (!isObject(v)) return { title: null, description: null, example: null };\n const title = asString(v.title);\n return {\n title: title === '-' ? null : title,\n description: asGuidelineText(v.description),\n example: asGuidelineText(v.example),\n };\n });\n // 전부 플레이스홀더면 라벨 소스로 쓰지 않는다.\n if (entries.every((e) => e.title === null)) return [];\n return entries;\n}\n\n// reportData item 객체에서 prefix→(suffix→값) 맵과 첫 등장 순서(order)를 만든다.\nfunction buildFieldsMap(itemObj: Record<string, unknown>): {\n order: string[];\n fields: Map<string, Map<StepSuffix, unknown>>;\n} {\n const order: string[] = [];\n const fields = new Map<string, Map<StepSuffix, unknown>>();\n\n for (const [key, value] of Object.entries(itemObj)) {\n const split = splitStepKey(key);\n if (!split) continue;\n if (!fields.has(split.prefix)) {\n fields.set(split.prefix, new Map());\n order.push(split.prefix);\n }\n fields.get(split.prefix)?.set(split.suffix, value);\n }\n\n return { order, fields };\n}\n\n// 단일 단계(step) 조립. 라벨/이니셜/설명/만점은 호출부(displayMeta 또는 폴백)가 결정해 주입.\nfunction buildStep(\n key: string,\n f: Map<StepSuffix, unknown>,\n meta: {\n label: string;\n initial: string | null;\n description: string | null;\n idealExample: string | null;\n maxScoreFallback: number | null; // reportData 에 max 가 없을 때 쓸 만점(displayMeta.maxValue)\n }\n): RpReportStep {\n const qualityRaw = f.get('quality');\n return {\n key,\n label: meta.label,\n initial: meta.initial,\n description: meta.description,\n idealExample: meta.idealExample,\n score: asNumber(f.get('score')),\n // reportData 의 실제 만점이 우선, 없으면 displayMeta.maxValue 폴백.\n maxScore:\n asNumber(f.get('max_score') ?? f.get('maxscore') ?? f.get('max')) ??\n meta.maxScoreFallback,\n quality: asQuality(qualityRaw),\n qualityLabel: asString(qualityRaw),\n basis: asString(f.get('basis')),\n issue: asString(f.get('issue')),\n improve: asString(f.get('improve')),\n example: asString(f.get('example')),\n };\n}\n\nfunction extractSteps(\n itemObj: Record<string, unknown>,\n guideline: unknown,\n displaySteps: RpDisplayMetaStep[]\n): RpReportStep[] {\n const { order, fields } = buildFieldsMap(itemObj);\n const entries = readGuidelineEntries(guideline);\n\n // ── displayMeta.steps 우선: order 정렬된 steps 를 key 로 reportData 필드에 매칭.\n if (displaySteps.length > 0) {\n // guideline 의 단계 설명/모범예시 보강은 길이 일치 시에만 인덱스 매핑(기존 가드와 동일 정신).\n const useGuideline = entries.length === displaySteps.length;\n return displaySteps.map((ds, i) => {\n const f = fields.get(ds.key) ?? new Map<StepSuffix, unknown>();\n const entry = useGuideline ? entries[i] : null;\n // 지표 설명: displayMeta.steps.description 우선, 없으면 guideline.\n const dsDescription =\n ds.description.trim().length > 0 ? ds.description : null;\n return buildStep(ds.key, f, {\n label: ds.displayName,\n initial: ds.initial.trim().length > 0 ? ds.initial : null,\n description: dsDescription ?? entry?.description ?? null,\n idealExample: entry?.example ?? null,\n maxScoreFallback: ds.maxValue > 0 ? ds.maxValue : null,\n });\n });\n }\n\n // ── 폴백: reportData 키 등장 순서 + guideline 길이일치 인덱스 매칭 + humanize.\n const useGuideline = entries.length === order.length;\n return order.map((prefix, i) => {\n const f = fields.get(prefix) ?? new Map<StepSuffix, unknown>();\n const entry = useGuideline ? entries[i] : null;\n return buildStep(prefix, f, {\n label: entry?.title ?? humanize(prefix),\n initial: null,\n description: entry?.description ?? null,\n idealExample: entry?.example ?? null,\n maxScoreFallback: null,\n });\n });\n}\n\n// framework.displayMeta(unknown) 를 견고하게 정규화.\n// title/description(프레임워크 자체)과 steps(지표 배열)는 독립 — steps 가 비어도 title/description 은 살린다.\nfunction readDisplayMeta(raw: unknown): {\n title: string | null;\n description: string | null;\n steps: RpDisplayMetaStep[];\n} {\n if (!isObject(raw)) return { title: null, description: null, steps: [] };\n\n const steps: RpDisplayMetaStep[] = [];\n if (isUnknownArray(raw.steps)) {\n for (const s of raw.steps) {\n if (!isObject(s)) continue;\n const key = asString(s.key);\n if (key === null) continue; // key 없는 항목은 매칭 불가 → 제외\n steps.push({\n order: asNumber(s.order) ?? steps.length,\n key,\n initial: asString(s.initial) ?? '',\n displayName: asString(s.displayName) ?? humanize(key),\n maxValue: asNumber(s.maxValue) ?? 0,\n description: asString(s.description) ?? '',\n });\n }\n steps.sort((a, b) => a.order - b.order);\n }\n\n return {\n title: asString(raw.title),\n description: asString(raw.description),\n steps,\n };\n}\n\n/* ───────────────────────── 강점/개선점 (numbered-pair 평탄화) ───────────────────────── */\n\n// 객체에서 `${titleBase}${n}` / `${detailBase}${n}` 쌍을 n=1.. 순으로 수집.\nfunction flattenNumberedPairs(\n obj: Record<string, unknown>,\n titleBase: string,\n detailBase: string\n): RpReportAnalysisItem[] {\n const out: RpReportAnalysisItem[] = [];\n for (let n = 1; ; n += 1) {\n const title = asString(obj[`${titleBase}${n}`]);\n if (title === null) break;\n out.push({ title, detail: asString(obj[`${detailBase}${n}`]) ?? '' });\n }\n return out;\n}\n\n// 후보 (titleBase, detailBase) 쌍을 순서대로 시도, 첫 매치를 사용. (구·신 스키마 모두 대응)\nconst ANALYSIS_PAIR_CANDIDATES: readonly (readonly [string, string])[] = [\n ['title', 'detail'],\n ['improvement_title', 'improvement_action'],\n ['issue_title', 'issue_detail'],\n];\n\nfunction flattenAnalysis(source: unknown): RpReportAnalysisItem[] {\n if (!isUnknownArray(source)) return [];\n const out: RpReportAnalysisItem[] = [];\n for (const obj of source) {\n if (!isObject(obj)) continue;\n for (const [titleBase, detailBase] of ANALYSIS_PAIR_CANDIDATES) {\n const items = flattenNumberedPairs(obj, titleBase, detailBase);\n if (items.length > 0) {\n out.push(...items);\n break;\n }\n }\n }\n return out;\n}\n\n/* ───────────────────────── skills 평탄화 ───────────────────────── */\n\nfunction flattenSkills(source: unknown): RpReportSkill[] {\n if (!isUnknownArray(source)) return [];\n const out: RpReportSkill[] = [];\n for (const obj of source) {\n if (!isObject(obj)) continue;\n for (let n = 1; ; n += 1) {\n const title = asString(obj[`skill${n}`]);\n if (title === null) break;\n out.push({\n title,\n description: asString(obj[`description${n}`]) ?? '',\n example: asString(obj[`example${n}`]) ?? '',\n });\n }\n }\n return out;\n}\n\n/* ───────────────────────── 종합/감점 ───────────────────────── */\n\nfunction readDeduction(\n summary: Record<string, unknown> | null\n): { score: number; basis: string } | null {\n if (!summary || !isObject(summary.deduction)) return null;\n const score = asNumber(summary.deduction.score);\n const basis = asString(summary.deduction.basis);\n if (score === null || basis === null) return null;\n return { score, basis };\n}\n\n/* ───────────────────────── 메인 파서 ───────────────────────── */\n\n// airflow 가 output_text 를 dict 로 정규화해 저장하므로(ai_traininglog_request_clova.py),\n// 래퍼는 객체. 래퍼가 없으면(일부 프레임워크) reportData 자체를 루트로 사용.\nfunction unwrapOutputText(reportData: unknown): Record<string, unknown> {\n if (!isObject(reportData)) return {};\n return isObject(reportData.output_text) ? reportData.output_text : reportData;\n}\n\nfunction findItemsArray(\n root: Record<string, unknown>\n): Record<string, unknown> | null {\n for (const [key, value] of Object.entries(root)) {\n if (!key.endsWith('_items') || !isUnknownArray(value)) continue;\n const first = value[0];\n if (isObject(first)) return first;\n }\n return null;\n}\n\nexport function parseReportData(\n reportData: unknown,\n guideline: unknown,\n displayMeta?: unknown\n): RpReport {\n const root = unwrapOutputText(reportData);\n const meta = readDisplayMeta(displayMeta);\n\n const summary = isObject(root.summary) ? root.summary : null;\n const comprehensive = isObject(root.comprehensive_analysis)\n ? root.comprehensive_analysis\n : null;\n\n // 종합 코멘트: 신(comprehensive_analysis) → 구(summary) 순.\n const comment =\n asString(comprehensive?.comment) ??\n asString(summary?.comment) ??\n asString(summary?.basis);\n\n // 강점: comprehensive_analysis.strengths(신) → summary.good_point(구)\n const strengths = flattenAnalysis(\n comprehensive?.strengths ?? summary?.good_point\n );\n // 개선점: comprehensive_analysis.improvements(신) → summary.improvement(구)\n const improvements = flattenAnalysis(\n comprehensive?.improvements ?? summary?.improvement\n );\n\n const itemObj = findItemsArray(root);\n const steps = itemObj ? extractSteps(itemObj, guideline, meta.steps) : [];\n\n return {\n frameworkTitle: meta.title,\n frameworkDescription: meta.description,\n todayDate: asString(root.todayDate),\n totalScore: asNumber(summary?.total_score),\n comment,\n deduction: readDeduction(summary),\n strengths,\n improvements,\n steps,\n skills: flattenSkills(root.skills),\n };\n}\n"],"mappings":"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","names":["useGuideline"]}
@@ -1,3 +1,6 @@
1
+ import {
2
+ review_question_text_default
3
+ } from "./chunk-WLKK5L3P.js";
1
4
  import {
2
5
  review_question_radio_default
3
6
  } from "./chunk-CGLDFUOY.js";
@@ -7,9 +10,6 @@ import {
7
10
  import {
8
11
  ReviewQuestionSatisfisText
9
12
  } from "./chunk-ZGTGEBQX.js";
10
- import {
11
- review_question_text_default
12
- } from "./chunk-WLKK5L3P.js";
13
13
 
14
14
  // src/molecules/curriculumV2/CurriculumContents/CurriculumReviewSteps/ReviewQuestion/review-question-body.tsx
15
15
  import { jsx } from "react/jsx-runtime";
@@ -66,4 +66,4 @@ var review_question_body_default = ReviewQuestionBody;
66
66
  export {
67
67
  review_question_body_default
68
68
  };
69
- //# sourceMappingURL=chunk-KQ3ME6XY.js.map
69
+ //# sourceMappingURL=chunk-U2EAXN3Y.js.map
@@ -0,0 +1,150 @@
1
+ import {
2
+ EchartDefaultProps
3
+ } from "./chunk-WSWSAPSS.js";
4
+ import {
5
+ __objRest,
6
+ __spreadProps,
7
+ __spreadValues
8
+ } from "./chunk-CRTRMMJ7.js";
9
+
10
+ // src/app/roleplay/chart/session-chart.tsx
11
+ import { useEffect, useMemo, useRef, useState } from "react";
12
+ import { useResizeDetector } from "react-resize-detector";
13
+ import * as echarts from "echarts/core";
14
+ import * as ReactEChartsCoreNs from "echarts-for-react/lib/core";
15
+ import { LineChart, RadarChart } from "echarts/charts";
16
+ import { SVGRenderer } from "echarts/renderers";
17
+ import {
18
+ AxisPointerComponent,
19
+ AriaComponent,
20
+ TooltipComponent,
21
+ GridComponent,
22
+ LegendComponent,
23
+ PolarComponent,
24
+ RadarComponent
25
+ } from "echarts/components";
26
+ import { jsx } from "react/jsx-runtime";
27
+ function unwrapDefault(mod) {
28
+ let current = mod;
29
+ while (current !== null && typeof current === "object" && "default" in current) {
30
+ current = current.default;
31
+ }
32
+ return current;
33
+ }
34
+ function isComponentType(value) {
35
+ return typeof value === "function";
36
+ }
37
+ var unwrappedChart = unwrapDefault(ReactEChartsCoreNs);
38
+ var ReactEChartsCore = isComponentType(unwrappedChart) ? unwrappedChart : ReactEChartsCoreNs.default;
39
+ echarts.use([
40
+ SVGRenderer,
41
+ LineChart,
42
+ RadarChart,
43
+ TooltipComponent,
44
+ GridComponent,
45
+ LegendComponent,
46
+ AriaComponent,
47
+ AxisPointerComponent,
48
+ PolarComponent,
49
+ RadarComponent
50
+ ]);
51
+ function deepMerge(base, override) {
52
+ if (!override) return base;
53
+ if (typeof base !== "object" || !base || Array.isArray(base) || typeof override !== "object" || Array.isArray(override)) {
54
+ return override;
55
+ }
56
+ const out = __spreadValues({}, base);
57
+ for (const [k, v] of Object.entries(override)) {
58
+ out[k] = k in out ? deepMerge(out[k], v) : v;
59
+ }
60
+ return out;
61
+ }
62
+ function Chart(_a) {
63
+ var _b = _a, {
64
+ option: optionProp
65
+ } = _b, rest = __objRest(_b, [
66
+ "option"
67
+ ]);
68
+ const { width, height, ref } = useResizeDetector({
69
+ handleHeight: true,
70
+ refreshMode: "debounce",
71
+ refreshRate: 100
72
+ });
73
+ const [mounted, setMounted] = useState(false);
74
+ useEffect(() => {
75
+ setMounted(true);
76
+ }, []);
77
+ const option = useMemo(() => {
78
+ const baseOption = {
79
+ textStyle: { fontFamily: "var(--default-font-family, 'Noto Sans KR')" },
80
+ tooltip: { textStyle: { fontSize: 13 } },
81
+ // ds-allow: chart-lib
82
+ animation: false
83
+ };
84
+ return deepMerge(baseOption, optionProp);
85
+ }, [optionProp]);
86
+ return /* @__PURE__ */ jsx("div", { ref, style: { width: "100%", height: "100%" }, children: mounted ? /* @__PURE__ */ jsx(
87
+ ReactEChartsCore,
88
+ __spreadProps(__spreadValues(__spreadProps(__spreadValues({}, EchartDefaultProps), {
89
+ echarts,
90
+ opts: { renderer: "svg" },
91
+ style: { height, width }
92
+ }), rest), {
93
+ option
94
+ })
95
+ ) : null });
96
+ }
97
+ function normalizeColor(value, fallback) {
98
+ const v = value.trim();
99
+ if (!v) return fallback;
100
+ if (/^#|^rgb|^hsl/i.test(v)) return v;
101
+ try {
102
+ const canvas = document.createElement("canvas");
103
+ const ctx = canvas.getContext("2d");
104
+ if (!ctx) return fallback;
105
+ ctx.fillStyle = "#000";
106
+ ctx.fillStyle = v;
107
+ const out = ctx.fillStyle;
108
+ return /color\(|^$/i.test(out) ? fallback : out;
109
+ } catch (e) {
110
+ return fallback;
111
+ }
112
+ }
113
+ function useTokenColors(vars) {
114
+ const probeRef = useRef(null);
115
+ const fallbacks = useMemo(() => {
116
+ const f = {};
117
+ for (const k of Object.keys(vars)) f[k] = vars[k][1];
118
+ return f;
119
+ }, [vars]);
120
+ const [resolved, setResolved] = useState(fallbacks);
121
+ const key = JSON.stringify(vars);
122
+ const varsRef = useRef(vars);
123
+ varsRef.current = vars;
124
+ useEffect(() => {
125
+ const el = probeRef.current;
126
+ if (!el) return;
127
+ const cs = getComputedStyle(el);
128
+ const next = {};
129
+ for (const k of Object.keys(varsRef.current)) {
130
+ const [cssVar, fallback] = varsRef.current[k];
131
+ next[k] = normalizeColor(cs.getPropertyValue(cssVar), fallback);
132
+ }
133
+ setResolved(next);
134
+ }, [key]);
135
+ const probe = /* @__PURE__ */ jsx(
136
+ "span",
137
+ {
138
+ "aria-hidden": true,
139
+ ref: probeRef,
140
+ style: { position: "absolute", width: 0, height: 0, overflow: "hidden" }
141
+ }
142
+ );
143
+ return { colors: resolved, probe };
144
+ }
145
+
146
+ export {
147
+ Chart,
148
+ useTokenColors
149
+ };
150
+ //# sourceMappingURL=chunk-UXAEOCOH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/app/roleplay/chart/session-chart.tsx"],"sourcesContent":["'use client';\n\n// echarts 기반 Chart 래퍼 + 토큰 색 해석 훅.\n// echarts 본체/echarts-for-react/react-resize-detector 는 @tipp/ui 의 optional peerDependency.\n// 이 모듈은 subpath(@tipp/ui/roleplay)로만 노출되어 메인 번들에서 격리된다.\n// SSR 안전: echarts/ResizeObserver 는 클라이언트 전용이라 마운트 이후에만 렌더한다.\n\nimport React, { useEffect, useMemo, useRef, useState } from 'react';\nimport { useResizeDetector } from 'react-resize-detector';\nimport type { EChartsOption } from 'echarts';\nimport * as echarts from 'echarts/core';\nimport * as ReactEChartsCoreNs from 'echarts-for-react/lib/core';\nimport { LineChart, RadarChart } from 'echarts/charts';\nimport { SVGRenderer } from 'echarts/renderers';\nimport {\n AxisPointerComponent,\n AriaComponent,\n TooltipComponent,\n GridComponent,\n LegendComponent,\n PolarComponent,\n RadarComponent,\n} from 'echarts/components';\nimport { EchartDefaultProps } from '../../../charts';\n\n// CJS/ESM interop 정규화.\n// echarts-for-react/lib/core 는 CJS(exports.default = 클래스)이고 @tipp/ui 는 strict ESM(\"type\":\"module\")\n// 이라, 번들러/런타임에 따라 실제 컴포넌트가 default 로 0~2 겹 감싸진다. 특히 webpack 이 __esModule 를\n// 무시하면 module.exports 를 한 번 더 감싸 ReactEChartsCoreNs.default.default 에 클래스가 들어가고,\n// 그대로 렌더하면 React 가 \"Element type is invalid (got: object)\" 로 던진다.\n// 함수(클래스/함수형 컴포넌트)가 나올 때까지 default 를 풀어 정규화한다.\ntype EChartsComponentType = typeof ReactEChartsCoreNs.default;\n\nfunction unwrapDefault(mod: unknown): unknown {\n let current = mod;\n while (current !== null && typeof current === 'object' && 'default' in current) {\n current = current.default;\n }\n return current;\n}\n\nfunction isComponentType(value: unknown): value is EChartsComponentType {\n return typeof value === 'function';\n}\n\nconst unwrappedChart = unwrapDefault(ReactEChartsCoreNs);\nconst ReactEChartsCore: EChartsComponentType = isComponentType(unwrappedChart)\n ? unwrappedChart\n : ReactEChartsCoreNs.default;\n\necharts.use([\n SVGRenderer,\n LineChart,\n RadarChart,\n TooltipComponent,\n GridComponent,\n LegendComponent,\n AriaComponent,\n AxisPointerComponent,\n PolarComponent,\n RadarComponent,\n]);\n\n// base/option 깊은 병합 (배열은 option 우선)\nfunction deepMerge<T>(base: T, override: unknown): T {\n if (!override) return base;\n if (\n typeof base !== 'object' ||\n !base ||\n Array.isArray(base) ||\n typeof override !== 'object' ||\n Array.isArray(override)\n ) {\n return override as T;\n }\n const out: Record<string, unknown> = { ...(base as Record<string, unknown>) };\n for (const [k, v] of Object.entries(override as Record<string, unknown>)) {\n out[k] = k in out ? deepMerge(out[k], v) : v;\n }\n return out as T;\n}\n\nexport type ChartProps = Omit<\n React.ComponentProps<typeof ReactEChartsCore>,\n 'option' | 'echarts'\n> & {\n option: EChartsOption;\n};\n\nexport function Chart({\n option: optionProp,\n ...rest\n}: ChartProps): React.ReactElement {\n const { width, height, ref } = useResizeDetector({\n handleHeight: true,\n refreshMode: 'debounce',\n refreshRate: 100,\n });\n const [mounted, setMounted] = useState(false);\n useEffect(() => {\n setMounted(true);\n }, []);\n\n const option = useMemo(() => {\n const baseOption: EChartsOption = {\n textStyle: { fontFamily: \"var(--default-font-family, 'Noto Sans KR')\" },\n tooltip: { textStyle: { fontSize: 13 } }, // ds-allow: chart-lib\n animation: false,\n };\n return deepMerge(baseOption, optionProp);\n }, [optionProp]);\n\n return (\n <div ref={ref} style={{ width: '100%', height: '100%' }}>\n {mounted ? (\n <ReactEChartsCore\n {...EchartDefaultProps}\n echarts={echarts}\n opts={{ renderer: 'svg' }}\n style={{ height, width }}\n {...rest}\n option={option}\n />\n ) : null}\n </div>\n );\n}\n\n// 임의의 CSS 색 문자열을 echarts(zrender)가 파싱 가능한 rgb(a)로 정규화한다.\nfunction normalizeColor(value: string, fallback: string): string {\n const v = value.trim();\n if (!v) return fallback;\n if (/^#|^rgb|^hsl/i.test(v)) return v;\n try {\n const canvas = document.createElement('canvas');\n const ctx = canvas.getContext('2d');\n if (!ctx) return fallback;\n ctx.fillStyle = '#000';\n ctx.fillStyle = v;\n const out = ctx.fillStyle;\n return /color\\(|^$/i.test(out) ? fallback : out;\n } catch {\n return fallback;\n }\n}\n\n// @tipp/ui 토큰(CSS 변수)을 echarts 가 먹을 수 있는 실제 색 문자열로 해석하는 훅.\nexport function useTokenColors<K extends string>(\n vars: Record<K, [cssVar: string, fallback: string]>\n): {\n colors: Record<K, string>;\n probe: React.ReactNode;\n} {\n const probeRef = useRef<HTMLSpanElement | null>(null);\n const fallbacks = useMemo(() => {\n const f = {} as Record<K, string>;\n for (const k of Object.keys(vars) as K[]) f[k] = vars[k][1];\n return f;\n }, [vars]);\n const [resolved, setResolved] = useState<Record<K, string>>(fallbacks);\n const key = JSON.stringify(vars);\n // vars 객체는 매 렌더 새 참조라 deps에 직접 넣을 수 없어 ref로 최신값을 참조하고,\n // 실제 변경 추적은 직렬화한 key 로 한다.\n const varsRef = useRef(vars);\n varsRef.current = vars;\n useEffect(() => {\n const el = probeRef.current;\n if (!el) return;\n const cs = getComputedStyle(el);\n const next = {} as Record<K, string>;\n for (const k of Object.keys(varsRef.current) as K[]) {\n const [cssVar, fallback] = varsRef.current[k];\n next[k] = normalizeColor(cs.getPropertyValue(cssVar), fallback);\n }\n setResolved(next);\n }, [key]);\n const probe = (\n <span\n aria-hidden\n ref={probeRef}\n style={{ position: 'absolute', width: 0, height: 0, overflow: 'hidden' }}\n />\n );\n return { colors: resolved, probe };\n}\n"],"mappings":"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","names":[]}