@empoweredvote/ev-ui 0.8.1 → 0.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +88 -5
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +88 -5
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -103,7 +103,9 @@ function RadarChartCore({
|
|
|
103
103
|
onReplaceTopic = () => {
|
|
104
104
|
},
|
|
105
105
|
size = 400,
|
|
106
|
+
labelFontSize = 13,
|
|
106
107
|
padding = 80,
|
|
108
|
+
labelOffset = 32,
|
|
107
109
|
tightFit = false,
|
|
108
110
|
activeSpoke = null,
|
|
109
111
|
writeIns = {}
|
|
@@ -177,9 +179,25 @@ function RadarChartCore({
|
|
|
177
179
|
acc[shortTitle] = userAdj > 10 || cmpAdj > 10;
|
|
178
180
|
return acc;
|
|
179
181
|
}, {});
|
|
180
|
-
const
|
|
181
|
-
|
|
182
|
-
|
|
182
|
+
const labelMeta = spokes.map(([shortTitle], i) => {
|
|
183
|
+
const angle = 2 * Math.PI * i / numSpokes;
|
|
184
|
+
const lines = wrapLabel(shortTitle, 12);
|
|
185
|
+
const longestLineLen = lines.reduce((m, ln) => ln.length > m ? ln.length : m, 0);
|
|
186
|
+
const estimatedWidth = longestLineLen * labelFontSize * 0.55;
|
|
187
|
+
const sinA = Math.sin(angle);
|
|
188
|
+
const side = sinA < -0.1 ? "left" : sinA > 0.1 ? "right" : "center";
|
|
189
|
+
return { estimatedWidth, side };
|
|
190
|
+
});
|
|
191
|
+
const leftLabelWidths = labelMeta.filter((m) => m.side === "left").map((m) => m.estimatedWidth);
|
|
192
|
+
const rightLabelWidths = labelMeta.filter((m) => m.side === "right").map((m) => m.estimatedWidth);
|
|
193
|
+
const minPadding = 40;
|
|
194
|
+
const maxPadding = padding * 2;
|
|
195
|
+
const rawLeft = Math.min(Math.max(leftLabelWidths.length ? Math.max(...leftLabelWidths) + labelOffset : 0, minPadding), maxPadding);
|
|
196
|
+
const rawRight = Math.min(Math.max(rightLabelWidths.length ? Math.max(...rightLabelWidths) + labelOffset : 0, minPadding), maxPadding);
|
|
197
|
+
const sidePadding = Math.max(rawLeft, rawRight);
|
|
198
|
+
const verticalPadding = padding;
|
|
199
|
+
let tightTop = -verticalPadding;
|
|
200
|
+
let tightHeight = size + verticalPadding * 2;
|
|
183
201
|
if (tightFit && numSpokes > 0) {
|
|
184
202
|
let yMin = Infinity, yMax = -Infinity;
|
|
185
203
|
for (let i = 0; i < numSpokes; i++) {
|
|
@@ -189,8 +207,9 @@ function RadarChartCore({
|
|
|
189
207
|
if (y < yMin) yMin = y;
|
|
190
208
|
if (y > yMax) yMax = y;
|
|
191
209
|
}
|
|
192
|
-
|
|
193
|
-
|
|
210
|
+
const labelMargin = labelOffset + labelFontSize * 2.5;
|
|
211
|
+
tightTop = yMin - labelMargin;
|
|
212
|
+
tightHeight = yMax + labelMargin - tightTop;
|
|
194
213
|
}
|
|
195
214
|
const guidePolygons = [];
|
|
196
215
|
for (let level = 1; level <= 5; level++) {
|
|
@@ -255,6 +274,39 @@ function RadarChartCore({
|
|
|
255
274
|
}
|
|
256
275
|
));
|
|
257
276
|
}),
|
|
277
|
+
spokes.map(([shortTitle], i) => {
|
|
278
|
+
const angle = 2 * Math.PI * i / numSpokes;
|
|
279
|
+
const cosA = Math.cos(angle);
|
|
280
|
+
const isBottom = cosA < -0.5;
|
|
281
|
+
const isTop = cosA > 0.5;
|
|
282
|
+
const lines = wrapLabel(shortTitle, 12);
|
|
283
|
+
const longestLine = lines.reduce((m, ln) => ln.length > m ? ln.length : m, 0);
|
|
284
|
+
const lineHeight = labelFontSize * 1.2;
|
|
285
|
+
const dynamicOffset = lines.length > 1 ? labelOffset + 6 : labelOffset;
|
|
286
|
+
const offset2 = radius + dynamicOffset;
|
|
287
|
+
const labelX = centerX + offset2 * Math.sin(angle);
|
|
288
|
+
let labelY = centerY - offset2 * Math.cos(angle);
|
|
289
|
+
if (isTop && lines.length > 1) labelY -= (lines.length - 1) * lineHeight;
|
|
290
|
+
const isActive = shortTitle === activeSpoke;
|
|
291
|
+
const isUnansweredLabel = !!unansweredSpokes[shortTitle];
|
|
292
|
+
const fSize = isActive ? labelFontSize * 1.2 : labelFontSize;
|
|
293
|
+
return /* @__PURE__ */ import_react.default.createElement(
|
|
294
|
+
"text",
|
|
295
|
+
{
|
|
296
|
+
key: `label-${shortTitle}`,
|
|
297
|
+
x: labelX,
|
|
298
|
+
y: labelY,
|
|
299
|
+
textAnchor: "middle",
|
|
300
|
+
dominantBaseline: isBottom ? "hanging" : "auto",
|
|
301
|
+
onClick: () => onReplaceTopic(shortTitle),
|
|
302
|
+
fill: isActive ? "#E85D26" : isUnansweredLabel ? "#9ca3af" : "#555",
|
|
303
|
+
fontWeight: isActive ? "bold" : "normal",
|
|
304
|
+
style: { cursor: "pointer", userSelect: "none", fontSize: fSize, fontFamily: "sans-serif" }
|
|
305
|
+
},
|
|
306
|
+
isUnansweredLabel && /* @__PURE__ */ import_react.default.createElement("title", null, "No stance on file for this topic."),
|
|
307
|
+
lines.map((ln, idx) => /* @__PURE__ */ import_react.default.createElement("tspan", { key: idx, x: labelX, dy: idx === 0 ? "0" : `${lineHeight}` }, ln))
|
|
308
|
+
);
|
|
309
|
+
}),
|
|
258
310
|
countChanged ? /* @__PURE__ */ import_react.default.createElement(
|
|
259
311
|
"polygon",
|
|
260
312
|
{
|
|
@@ -387,6 +439,37 @@ function RadarChartCore({
|
|
|
387
439
|
})()
|
|
388
440
|
);
|
|
389
441
|
}
|
|
442
|
+
function wrapLabel(label, maxChars = 12) {
|
|
443
|
+
const str = String(label);
|
|
444
|
+
let rawWords;
|
|
445
|
+
if (str.includes("/")) {
|
|
446
|
+
rawWords = str.split("/").reduce((acc, segment, idx, arr) => {
|
|
447
|
+
const part = idx < arr.length - 1 ? segment + "/" : segment;
|
|
448
|
+
if (part.trim()) acc.push(part.trim());
|
|
449
|
+
return acc;
|
|
450
|
+
}, []);
|
|
451
|
+
} else {
|
|
452
|
+
rawWords = str.split(/\s+/);
|
|
453
|
+
}
|
|
454
|
+
const lines = [];
|
|
455
|
+
let line = "";
|
|
456
|
+
for (const word of rawWords) {
|
|
457
|
+
if (line === "") {
|
|
458
|
+
line = word;
|
|
459
|
+
} else if ((line + " " + word).length <= maxChars) {
|
|
460
|
+
line += " " + word;
|
|
461
|
+
} else {
|
|
462
|
+
lines.push(line);
|
|
463
|
+
line = word;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
if (line) lines.push(line);
|
|
467
|
+
if (lines.length > 2) {
|
|
468
|
+
const overflow = lines.splice(2).join(" ");
|
|
469
|
+
lines[1] = lines[1] + " " + overflow;
|
|
470
|
+
}
|
|
471
|
+
return lines;
|
|
472
|
+
}
|
|
390
473
|
|
|
391
474
|
// src/Header.jsx
|
|
392
475
|
var import_react3 = __toESM(require("react"));
|