@empoweredvote/ev-ui 0.8.0 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +10 -108
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +10 -108
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -12,9 +12,7 @@ function RadarChartCore({
|
|
|
12
12
|
onReplaceTopic = () => {
|
|
13
13
|
},
|
|
14
14
|
size = 400,
|
|
15
|
-
labelFontSize = 18,
|
|
16
15
|
padding = 80,
|
|
17
|
-
labelOffset = 20,
|
|
18
16
|
tightFit = false,
|
|
19
17
|
activeSpoke = null,
|
|
20
18
|
writeIns = {}
|
|
@@ -82,40 +80,15 @@ function RadarChartCore({
|
|
|
82
80
|
};
|
|
83
81
|
if (countChanged || compareJustAppeared) compareSpringBase.from = compareSpringBase.to;
|
|
84
82
|
const compareSpring = useSpring(compareSpringBase);
|
|
85
|
-
const labelMeta = spokes.map(([shortTitle], i) => {
|
|
86
|
-
const angle = 2 * Math.PI * i / numSpokes;
|
|
87
|
-
const lines = wrapLabel(shortTitle, 12);
|
|
88
|
-
const longestLineLen = lines.reduce((m, ln) => ln.length > m ? ln.length : m, 0);
|
|
89
|
-
const fSize = adaptiveFontSize(longestLineLen, labelFontSize);
|
|
90
|
-
const estimatedWidth = longestLineLen * fSize * 0.6;
|
|
91
|
-
const sinA = Math.sin(angle);
|
|
92
|
-
const side = sinA < -0.1 ? "left" : sinA > 0.1 ? "right" : "center";
|
|
93
|
-
return { estimatedWidth, side };
|
|
94
|
-
});
|
|
95
|
-
const leftLabelWidths = labelMeta.filter((m) => m.side === "left").map((m) => m.estimatedWidth);
|
|
96
|
-
const rightLabelWidths = labelMeta.filter((m) => m.side === "right").map((m) => m.estimatedWidth);
|
|
97
|
-
const minPadding = 40;
|
|
98
|
-
const maxPadding = padding * 2;
|
|
99
|
-
const rawLeftPadding = Math.min(
|
|
100
|
-
Math.max(leftLabelWidths.length ? Math.max(...leftLabelWidths) + labelOffset : 0, minPadding),
|
|
101
|
-
maxPadding
|
|
102
|
-
);
|
|
103
|
-
const rawRightPadding = Math.min(
|
|
104
|
-
Math.max(rightLabelWidths.length ? Math.max(...rightLabelWidths) + labelOffset : 0, minPadding),
|
|
105
|
-
maxPadding
|
|
106
|
-
);
|
|
107
|
-
const symmetricPadding = Math.max(rawLeftPadding, rawRightPadding);
|
|
108
|
-
const leftPadding = symmetricPadding;
|
|
109
|
-
const rightPadding = symmetricPadding;
|
|
110
|
-
const verticalPadding = padding;
|
|
111
83
|
const spokeExtension = spokes.reduce((acc, [shortTitle]) => {
|
|
112
84
|
const userAdj = calcAdjusted(data[shortTitle], shortTitle);
|
|
113
85
|
const cmpAdj = hasCompareData && compareData[shortTitle] ? calcAdjusted(compareData[shortTitle], shortTitle) : 0;
|
|
114
86
|
acc[shortTitle] = userAdj > 10 || cmpAdj > 10;
|
|
115
87
|
return acc;
|
|
116
88
|
}, {});
|
|
117
|
-
|
|
118
|
-
let
|
|
89
|
+
const sidePadding = 20;
|
|
90
|
+
let tightTop = -sidePadding;
|
|
91
|
+
let tightHeight = size + sidePadding * 2;
|
|
119
92
|
if (tightFit && numSpokes > 0) {
|
|
120
93
|
let yMin = Infinity, yMax = -Infinity;
|
|
121
94
|
for (let i = 0; i < numSpokes; i++) {
|
|
@@ -125,9 +98,8 @@ function RadarChartCore({
|
|
|
125
98
|
if (y < yMin) yMin = y;
|
|
126
99
|
if (y > yMax) yMax = y;
|
|
127
100
|
}
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
tightHeight = yMax + labelMargin - tightTop;
|
|
101
|
+
tightTop = yMin - sidePadding;
|
|
102
|
+
tightHeight = yMax + sidePadding - tightTop;
|
|
131
103
|
}
|
|
132
104
|
const guidePolygons = [];
|
|
133
105
|
for (let level = 1; level <= 5; level++) {
|
|
@@ -155,7 +127,7 @@ function RadarChartCore({
|
|
|
155
127
|
"svg",
|
|
156
128
|
{
|
|
157
129
|
className: "w-full h-auto max-h-full",
|
|
158
|
-
viewBox: `-${
|
|
130
|
+
viewBox: `-${sidePadding} ${tightTop} ${size + sidePadding * 2} ${tightHeight}`,
|
|
159
131
|
preserveAspectRatio: "xMidYMid meet",
|
|
160
132
|
onMouseLeave: () => setTooltip(null)
|
|
161
133
|
},
|
|
@@ -175,7 +147,7 @@ function RadarChartCore({
|
|
|
175
147
|
y1: centerY,
|
|
176
148
|
x2: endX,
|
|
177
149
|
y2: endY,
|
|
178
|
-
stroke: isUnanswered ? "#9ca3af" : "
|
|
150
|
+
stroke: isUnanswered ? "#9ca3af" : "#aaa",
|
|
179
151
|
strokeDasharray: isUnanswered ? "4 3" : void 0,
|
|
180
152
|
opacity: isUnanswered ? 0.6 : 1
|
|
181
153
|
}
|
|
@@ -186,48 +158,12 @@ function RadarChartCore({
|
|
|
186
158
|
y1: endY,
|
|
187
159
|
x2: extX,
|
|
188
160
|
y2: extY,
|
|
189
|
-
stroke: "
|
|
161
|
+
stroke: "#aaa",
|
|
190
162
|
strokeDasharray: "4 4",
|
|
191
163
|
opacity: 0.4
|
|
192
164
|
}
|
|
193
165
|
));
|
|
194
166
|
}),
|
|
195
|
-
spokes.map(([shortTitle], i) => {
|
|
196
|
-
const angle = 2 * Math.PI * i / numSpokes;
|
|
197
|
-
const cosA = Math.cos(angle);
|
|
198
|
-
const isBottom = cosA < -0.5;
|
|
199
|
-
const isTop = cosA > 0.5;
|
|
200
|
-
const lines = wrapLabel(shortTitle, 12);
|
|
201
|
-
const longestLine = lines.reduce((m, ln) => ln.length > m ? ln.length : m, 0);
|
|
202
|
-
const fSize = adaptiveFontSize(longestLine, labelFontSize);
|
|
203
|
-
const lineHeight = fSize * 1.1;
|
|
204
|
-
const dynamicLabelOffset = lines.length > 1 ? labelOffset + 8 : labelOffset;
|
|
205
|
-
const offset2 = radius + dynamicLabelOffset;
|
|
206
|
-
const labelX = centerX + offset2 * Math.sin(angle);
|
|
207
|
-
let labelY = centerY - offset2 * Math.cos(angle);
|
|
208
|
-
if (isTop && lines.length > 1) labelY -= (lines.length - 1) * lineHeight;
|
|
209
|
-
const isActive = shortTitle === activeSpoke;
|
|
210
|
-
const isUnansweredLabel = !!unansweredSpokes[shortTitle];
|
|
211
|
-
const activeFSize = fSize * 1.5;
|
|
212
|
-
const displayFSize = isActive ? activeFSize : fSize;
|
|
213
|
-
return /* @__PURE__ */ React.createElement(
|
|
214
|
-
"text",
|
|
215
|
-
{
|
|
216
|
-
key: `label-${shortTitle}`,
|
|
217
|
-
x: labelX,
|
|
218
|
-
y: labelY,
|
|
219
|
-
textAnchor: "middle",
|
|
220
|
-
dominantBaseline: isBottom ? "hanging" : "auto",
|
|
221
|
-
onClick: () => onReplaceTopic(shortTitle),
|
|
222
|
-
className: "text-xl font-medium mb-1 md:text-base md:font-normal",
|
|
223
|
-
fill: isActive ? "#E85D26" : isUnansweredLabel ? "#9ca3af" : void 0,
|
|
224
|
-
fontWeight: isActive ? "bold" : void 0,
|
|
225
|
-
style: { cursor: "pointer", userSelect: "none", fontSize: displayFSize }
|
|
226
|
-
},
|
|
227
|
-
isUnansweredLabel && /* @__PURE__ */ React.createElement("title", null, "No stance on file for this topic."),
|
|
228
|
-
lines.map((ln, idx) => /* @__PURE__ */ React.createElement("tspan", { key: idx, x: labelX, dy: idx === 0 ? "0" : `${lineHeight}` }, ln))
|
|
229
|
-
);
|
|
230
|
-
}),
|
|
231
167
|
countChanged ? /* @__PURE__ */ React.createElement(
|
|
232
168
|
"polygon",
|
|
233
169
|
{
|
|
@@ -325,8 +261,8 @@ function RadarChartCore({
|
|
|
325
261
|
tooltip && (() => {
|
|
326
262
|
const tipW = 190;
|
|
327
263
|
const tipH = 70;
|
|
328
|
-
const svgW = size +
|
|
329
|
-
const tx = tooltip.x +
|
|
264
|
+
const svgW = size + sidePadding * 2;
|
|
265
|
+
const tx = tooltip.x + sidePadding + 12 > svgW - tipW ? tooltip.x - tipW - 12 : tooltip.x + 12;
|
|
330
266
|
const ty = tooltip.y - 10;
|
|
331
267
|
return /* @__PURE__ */ React.createElement(
|
|
332
268
|
"foreignObject",
|
|
@@ -360,40 +296,6 @@ function RadarChartCore({
|
|
|
360
296
|
})()
|
|
361
297
|
);
|
|
362
298
|
}
|
|
363
|
-
function adaptiveFontSize(longestLineLen, baseFSize) {
|
|
364
|
-
return Math.max(baseFSize, 10);
|
|
365
|
-
}
|
|
366
|
-
function wrapLabel(label, maxChars = 12) {
|
|
367
|
-
const str = String(label);
|
|
368
|
-
let rawWords;
|
|
369
|
-
if (str.includes("/")) {
|
|
370
|
-
rawWords = str.split("/").reduce((acc, segment, idx, arr) => {
|
|
371
|
-
const part = idx < arr.length - 1 ? segment + "/" : segment;
|
|
372
|
-
if (part.trim()) acc.push(part.trim());
|
|
373
|
-
return acc;
|
|
374
|
-
}, []);
|
|
375
|
-
} else {
|
|
376
|
-
rawWords = str.split(/\s+/);
|
|
377
|
-
}
|
|
378
|
-
const lines = [];
|
|
379
|
-
let line = "";
|
|
380
|
-
for (const word of rawWords) {
|
|
381
|
-
if (line === "") {
|
|
382
|
-
line = word;
|
|
383
|
-
} else if ((line + " " + word).length <= maxChars) {
|
|
384
|
-
line += " " + word;
|
|
385
|
-
} else {
|
|
386
|
-
lines.push(line);
|
|
387
|
-
line = word;
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
if (line) lines.push(line);
|
|
391
|
-
if (lines.length > 2) {
|
|
392
|
-
const overflow = lines.splice(2).join(" ");
|
|
393
|
-
lines[1] = lines[1] + " " + overflow;
|
|
394
|
-
}
|
|
395
|
-
return lines;
|
|
396
|
-
}
|
|
397
299
|
|
|
398
300
|
// src/Header.jsx
|
|
399
301
|
import React2, { useState as useState3, useRef as useRef2, useEffect as useEffect3 } from "react";
|