@empoweredvote/ev-ui 0.7.1 → 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/README.md +111 -111
- package/dist/index.js +523 -575
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +189 -241
- package/dist/index.mjs.map +1 -1
- package/package.json +47 -45
- package/src/tailwind-preset.js +81 -81
- package/src/tokens.js +415 -415
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
// src/RadarChartCore.jsx
|
|
2
|
-
import React from "react";
|
|
2
|
+
import React, { useState, useRef, useEffect } from "react";
|
|
3
3
|
import { animated, useSpring } from "@react-spring/web";
|
|
4
|
-
import { useRef, useEffect } from "react";
|
|
5
4
|
function RadarChartCore({
|
|
6
5
|
topics,
|
|
7
6
|
data,
|
|
@@ -13,14 +12,17 @@ function RadarChartCore({
|
|
|
13
12
|
onReplaceTopic = () => {
|
|
14
13
|
},
|
|
15
14
|
size = 400,
|
|
16
|
-
labelFontSize = 18,
|
|
17
15
|
padding = 80,
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
tightFit = false,
|
|
17
|
+
activeSpoke = null,
|
|
18
|
+
writeIns = {}
|
|
20
19
|
}) {
|
|
20
|
+
var _a;
|
|
21
21
|
const radius = size / 2 - 40;
|
|
22
|
+
const extRadius = radius * 1.15;
|
|
22
23
|
const centerX = size / 2;
|
|
23
24
|
const centerY = size / 2;
|
|
25
|
+
const [tooltip, setTooltip] = useState(null);
|
|
24
26
|
const spokes = Object.entries(data);
|
|
25
27
|
const numSpokes = Math.max(spokes.length, 1);
|
|
26
28
|
const prevCountRef = useRef(numSpokes);
|
|
@@ -28,42 +30,40 @@ function RadarChartCore({
|
|
|
28
30
|
useEffect(() => {
|
|
29
31
|
prevCountRef.current = numSpokes;
|
|
30
32
|
}, [numSpokes]);
|
|
31
|
-
|
|
32
|
-
var
|
|
33
|
+
function calcAdjusted(value, shortTitle) {
|
|
34
|
+
var _a2;
|
|
35
|
+
if (!value || Number(value) === 0) return 0;
|
|
33
36
|
const topic = topics.find((t) => t.short_title === shortTitle);
|
|
34
|
-
const max = ((
|
|
35
|
-
const pct =
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
const max = ((_a2 = topic == null ? void 0 : topic.stances) == null ? void 0 : _a2.length) || 10;
|
|
38
|
+
const pct = Number(value) / max * 10;
|
|
39
|
+
return invertedSpokes[shortTitle] ? (max + 1) * 10 / max - pct : pct;
|
|
40
|
+
}
|
|
41
|
+
const pointsArr = spokes.map(([shortTitle, value], index) => {
|
|
42
|
+
const adjusted = calcAdjusted(value, shortTitle);
|
|
38
43
|
const r = adjusted / 10 * radius;
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
return [x, y];
|
|
44
|
+
const angle = 2 * Math.PI * index / numSpokes;
|
|
45
|
+
return [centerX + r * Math.sin(angle), centerY - r * Math.cos(angle)];
|
|
42
46
|
});
|
|
43
47
|
const targetPoints = pointsArr.map((p) => p.join(",")).join(" ");
|
|
44
|
-
const
|
|
48
|
+
const springBase = {
|
|
45
49
|
to: { points: targetPoints },
|
|
46
50
|
immediate: countChanged,
|
|
47
|
-
reset: countChanged,
|
|
48
51
|
config: { tension: 300, friction: 30 }
|
|
49
|
-
}
|
|
52
|
+
};
|
|
53
|
+
if (countChanged) springBase.from = { points: targetPoints };
|
|
54
|
+
const spring = useSpring(springBase);
|
|
50
55
|
const hasCompareData = Object.keys(compareData).length > 0;
|
|
51
56
|
const centerPoints = spokes.map(() => `${centerX},${centerY}`).join(" ");
|
|
52
57
|
let comparePoints = null;
|
|
53
58
|
let compareCoords = null;
|
|
54
59
|
if (hasCompareData) {
|
|
55
60
|
const ccoords = spokes.map(([shortTitle], index) => {
|
|
56
|
-
var
|
|
57
|
-
const value = (
|
|
58
|
-
const
|
|
59
|
-
const max = ((_b = topic == null ? void 0 : topic.stances) == null ? void 0 : _b.length) || 10;
|
|
60
|
-
const pct = Math.min(value / max * 10, 10);
|
|
61
|
-
const angle = 2 * Math.PI * index / numSpokes;
|
|
62
|
-
const adjusted = value === 0 ? 0 : invertedSpokes[shortTitle] ? 11 - pct : pct;
|
|
61
|
+
var _a2;
|
|
62
|
+
const value = (_a2 = compareData[shortTitle]) != null ? _a2 : 0;
|
|
63
|
+
const adjusted = calcAdjusted(value, shortTitle);
|
|
63
64
|
const r = adjusted / 10 * radius;
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
return [x, y];
|
|
65
|
+
const angle = 2 * Math.PI * index / numSpokes;
|
|
66
|
+
return [centerX + r * Math.sin(angle), centerY - r * Math.cos(angle)];
|
|
67
67
|
});
|
|
68
68
|
compareCoords = ccoords;
|
|
69
69
|
comparePoints = ccoords.map((p) => p.join(",")).join(" ");
|
|
@@ -73,61 +73,33 @@ function RadarChartCore({
|
|
|
73
73
|
useEffect(() => {
|
|
74
74
|
hadCompareDataRef.current = hasCompareData;
|
|
75
75
|
}, [hasCompareData]);
|
|
76
|
-
const
|
|
76
|
+
const compareSpringBase = {
|
|
77
77
|
to: { points: comparePoints || centerPoints || `${centerX},${centerY}` },
|
|
78
78
|
immediate: countChanged || compareJustAppeared,
|
|
79
|
-
reset: countChanged || compareJustAppeared,
|
|
80
79
|
config: { tension: 300, friction: 30 }
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
const
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const side = sinA < -0.1 ? "left" : sinA > 0.1 ? "right" : "center";
|
|
94
|
-
return { estimatedWidth, side };
|
|
95
|
-
});
|
|
96
|
-
const leftLabelWidths = labelMeta.filter((m) => m.side === "left").map((m) => m.estimatedWidth);
|
|
97
|
-
const rightLabelWidths = labelMeta.filter((m) => m.side === "right").map((m) => m.estimatedWidth);
|
|
98
|
-
const minPadding = 40;
|
|
99
|
-
const maxPadding = padding * 2;
|
|
100
|
-
const rawLeftPadding = Math.min(
|
|
101
|
-
Math.max(
|
|
102
|
-
leftLabelWidths.length ? Math.max(...leftLabelWidths) + labelOffset : 0,
|
|
103
|
-
minPadding
|
|
104
|
-
),
|
|
105
|
-
maxPadding
|
|
106
|
-
);
|
|
107
|
-
const rawRightPadding = Math.min(
|
|
108
|
-
Math.max(
|
|
109
|
-
rightLabelWidths.length ? Math.max(...rightLabelWidths) + labelOffset : 0,
|
|
110
|
-
minPadding
|
|
111
|
-
),
|
|
112
|
-
maxPadding
|
|
113
|
-
);
|
|
114
|
-
const symmetricPadding = Math.max(rawLeftPadding, rawRightPadding);
|
|
115
|
-
const leftPadding = symmetricPadding;
|
|
116
|
-
const rightPadding = symmetricPadding;
|
|
117
|
-
const verticalPadding = padding;
|
|
118
|
-
let tightTop = -verticalPadding;
|
|
119
|
-
let tightHeight = size + verticalPadding * 2;
|
|
80
|
+
};
|
|
81
|
+
if (countChanged || compareJustAppeared) compareSpringBase.from = compareSpringBase.to;
|
|
82
|
+
const compareSpring = useSpring(compareSpringBase);
|
|
83
|
+
const spokeExtension = spokes.reduce((acc, [shortTitle]) => {
|
|
84
|
+
const userAdj = calcAdjusted(data[shortTitle], shortTitle);
|
|
85
|
+
const cmpAdj = hasCompareData && compareData[shortTitle] ? calcAdjusted(compareData[shortTitle], shortTitle) : 0;
|
|
86
|
+
acc[shortTitle] = userAdj > 10 || cmpAdj > 10;
|
|
87
|
+
return acc;
|
|
88
|
+
}, {});
|
|
89
|
+
const sidePadding = 20;
|
|
90
|
+
let tightTop = -sidePadding;
|
|
91
|
+
let tightHeight = size + sidePadding * 2;
|
|
120
92
|
if (tightFit && numSpokes > 0) {
|
|
121
93
|
let yMin = Infinity, yMax = -Infinity;
|
|
122
94
|
for (let i = 0; i < numSpokes; i++) {
|
|
123
95
|
const angle = 2 * Math.PI * i / numSpokes;
|
|
124
|
-
const
|
|
96
|
+
const effectiveR = spokeExtension[(_a = spokes[i]) == null ? void 0 : _a[0]] ? extRadius : radius;
|
|
97
|
+
const y = centerY - effectiveR * Math.cos(angle);
|
|
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++) {
|
|
@@ -135,101 +107,76 @@ function RadarChartCore({
|
|
|
135
107
|
const ring = [];
|
|
136
108
|
for (let i = 0; i < numSpokes; i++) {
|
|
137
109
|
const angle = 2 * Math.PI * i / numSpokes;
|
|
138
|
-
|
|
139
|
-
const y = centerY - radius * scale * Math.cos(angle);
|
|
140
|
-
ring.push(`${x},${y}`);
|
|
110
|
+
ring.push(`${centerX + radius * scale * Math.sin(angle)},${centerY - radius * scale * Math.cos(angle)}`);
|
|
141
111
|
}
|
|
142
112
|
guidePolygons.push(
|
|
143
113
|
/* @__PURE__ */ React.createElement("polygon", { key: level, points: ring.join(" "), fill: "none", stroke: "#ccc" })
|
|
144
114
|
);
|
|
145
115
|
}
|
|
116
|
+
const getStanceText = (shortTitle, value) => {
|
|
117
|
+
if (writeIns[shortTitle]) return writeIns[shortTitle];
|
|
118
|
+
const topic = topics.find((t) => t.short_title === shortTitle);
|
|
119
|
+
const stances = (topic == null ? void 0 : topic.stances) || [];
|
|
120
|
+
const idx = Math.round(Number(value)) - 1;
|
|
121
|
+
if (idx >= 0 && idx < stances.length) {
|
|
122
|
+
return stances[idx].text || shortTitle;
|
|
123
|
+
}
|
|
124
|
+
return shortTitle;
|
|
125
|
+
};
|
|
146
126
|
return /* @__PURE__ */ React.createElement(
|
|
147
127
|
"svg",
|
|
148
128
|
{
|
|
149
129
|
className: "w-full h-auto max-h-full",
|
|
150
|
-
viewBox: `-${
|
|
151
|
-
preserveAspectRatio: "xMidYMid meet"
|
|
130
|
+
viewBox: `-${sidePadding} ${tightTop} ${size + sidePadding * 2} ${tightHeight}`,
|
|
131
|
+
preserveAspectRatio: "xMidYMid meet",
|
|
132
|
+
onMouseLeave: () => setTooltip(null)
|
|
152
133
|
},
|
|
153
134
|
guidePolygons,
|
|
154
135
|
spokes.map(([shortTitle], i) => {
|
|
155
136
|
const angle = 2 * Math.PI * i / numSpokes;
|
|
156
|
-
const
|
|
157
|
-
const
|
|
137
|
+
const endX = centerX + radius * Math.sin(angle);
|
|
138
|
+
const endY = centerY - radius * Math.cos(angle);
|
|
158
139
|
const isUnanswered = !!unansweredSpokes[shortTitle];
|
|
159
|
-
|
|
140
|
+
const needsExt = spokeExtension[shortTitle];
|
|
141
|
+
const extX = centerX + extRadius * Math.sin(angle);
|
|
142
|
+
const extY = centerY - extRadius * Math.cos(angle);
|
|
143
|
+
return /* @__PURE__ */ React.createElement("g", { key: `spoke-${shortTitle}` }, /* @__PURE__ */ React.createElement(
|
|
160
144
|
"line",
|
|
161
145
|
{
|
|
162
|
-
key: `line-${shortTitle}`,
|
|
163
146
|
x1: centerX,
|
|
164
147
|
y1: centerY,
|
|
165
|
-
x2:
|
|
166
|
-
y2:
|
|
167
|
-
stroke: isUnanswered ? "#9ca3af" : "
|
|
148
|
+
x2: endX,
|
|
149
|
+
y2: endY,
|
|
150
|
+
stroke: isUnanswered ? "#9ca3af" : "#aaa",
|
|
168
151
|
strokeDasharray: isUnanswered ? "4 3" : void 0,
|
|
169
152
|
opacity: isUnanswered ? 0.6 : 1
|
|
170
153
|
}
|
|
171
|
-
)
|
|
172
|
-
|
|
173
|
-
spokes.map(([shortTitle], i) => {
|
|
174
|
-
const angle = 2 * Math.PI * i / numSpokes;
|
|
175
|
-
const anchor = angle > Math.PI ? "end" : angle < Math.PI && angle > 0 ? "start" : "middle";
|
|
176
|
-
const cosA = Math.cos(angle);
|
|
177
|
-
const isTop = cosA > 0.5;
|
|
178
|
-
const isBottom = cosA < -0.5;
|
|
179
|
-
const baseFSize = labelFontSize;
|
|
180
|
-
const lines = wrapLabel(shortTitle, 12);
|
|
181
|
-
const longestLine = lines.reduce(
|
|
182
|
-
(max, ln) => ln.length > max ? ln.length : max,
|
|
183
|
-
0
|
|
184
|
-
);
|
|
185
|
-
const fSize = adaptiveFontSize(longestLine, baseFSize);
|
|
186
|
-
const lineHeight = fSize * 1.1;
|
|
187
|
-
const dynamicLabelOffset = lines.length > 1 ? labelOffset + 8 : labelOffset;
|
|
188
|
-
const offset2 = radius + dynamicLabelOffset;
|
|
189
|
-
const labelX = centerX + offset2 * Math.sin(angle);
|
|
190
|
-
let labelY = centerY - offset2 * Math.cos(angle);
|
|
191
|
-
if (isTop && lines.length > 1) {
|
|
192
|
-
labelY -= (lines.length - 1) * lineHeight;
|
|
193
|
-
}
|
|
194
|
-
const isUnansweredLabel = !!unansweredSpokes[shortTitle];
|
|
195
|
-
return /* @__PURE__ */ React.createElement(
|
|
196
|
-
"text",
|
|
154
|
+
), needsExt && /* @__PURE__ */ React.createElement(
|
|
155
|
+
"line",
|
|
197
156
|
{
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
},
|
|
208
|
-
isUnansweredLabel && /* @__PURE__ */ React.createElement("title", null, "No stance on file for this topic."),
|
|
209
|
-
lines.map((ln, idx) => /* @__PURE__ */ React.createElement("tspan", { key: idx, x: labelX, dy: idx === 0 ? "0" : `${lineHeight}` }, ln))
|
|
210
|
-
);
|
|
157
|
+
x1: endX,
|
|
158
|
+
y1: endY,
|
|
159
|
+
x2: extX,
|
|
160
|
+
y2: extY,
|
|
161
|
+
stroke: "#aaa",
|
|
162
|
+
strokeDasharray: "4 4",
|
|
163
|
+
opacity: 0.4
|
|
164
|
+
}
|
|
165
|
+
));
|
|
211
166
|
}),
|
|
212
167
|
countChanged ? /* @__PURE__ */ React.createElement(
|
|
213
168
|
"polygon",
|
|
214
169
|
{
|
|
215
170
|
key: "user-static",
|
|
216
171
|
points: targetPoints,
|
|
217
|
-
style: {
|
|
218
|
-
fill: "rgba(124, 107, 158, 0.4)",
|
|
219
|
-
stroke: "#7C6B9E",
|
|
220
|
-
strokeWidth: 3
|
|
221
|
-
}
|
|
172
|
+
style: { fill: "rgba(124, 107, 158, 0.4)", stroke: "#7C6B9E", strokeWidth: 3 }
|
|
222
173
|
}
|
|
223
174
|
) : /* @__PURE__ */ React.createElement(
|
|
224
175
|
animated.polygon,
|
|
225
176
|
{
|
|
226
177
|
key: "user-animated",
|
|
227
178
|
points: spring.points,
|
|
228
|
-
style: {
|
|
229
|
-
fill: "rgba(124, 107, 158, 0.4)",
|
|
230
|
-
stroke: "#7C6B9E",
|
|
231
|
-
strokeWidth: 3
|
|
232
|
-
}
|
|
179
|
+
style: { fill: "rgba(124, 107, 158, 0.4)", stroke: "#7C6B9E", strokeWidth: 3 }
|
|
233
180
|
}
|
|
234
181
|
),
|
|
235
182
|
pointsArr.map(([cx, cy], i) => {
|
|
@@ -247,7 +194,10 @@ function RadarChartCore({
|
|
|
247
194
|
r: matches ? 8 : 7,
|
|
248
195
|
fill: matches ? "#fed12e" : "#7C6B9E",
|
|
249
196
|
stroke: "#FFFFFF",
|
|
250
|
-
strokeWidth: 3
|
|
197
|
+
strokeWidth: 3,
|
|
198
|
+
style: { cursor: "default" },
|
|
199
|
+
onMouseEnter: () => setTooltip({ x: cx, y: cy, text: getStanceText(shortTitle, userVal) }),
|
|
200
|
+
onMouseLeave: () => setTooltip(null)
|
|
251
201
|
}
|
|
252
202
|
);
|
|
253
203
|
}),
|
|
@@ -256,22 +206,14 @@ function RadarChartCore({
|
|
|
256
206
|
{
|
|
257
207
|
key: "compare-static",
|
|
258
208
|
points: comparePoints,
|
|
259
|
-
style: {
|
|
260
|
-
fill: "rgba(90, 154, 110, 0.3)",
|
|
261
|
-
stroke: "#5A9A6E",
|
|
262
|
-
strokeWidth: 2
|
|
263
|
-
}
|
|
209
|
+
style: { fill: "rgba(90, 154, 110, 0.3)", stroke: "#5A9A6E", strokeWidth: 2 }
|
|
264
210
|
}
|
|
265
211
|
) : /* @__PURE__ */ React.createElement(
|
|
266
212
|
animated.polygon,
|
|
267
213
|
{
|
|
268
214
|
key: "compare-animated",
|
|
269
215
|
points: compareSpring.points,
|
|
270
|
-
style: {
|
|
271
|
-
fill: "rgba(90, 154, 110, 0.3)",
|
|
272
|
-
stroke: "#5A9A6E",
|
|
273
|
-
strokeWidth: 2
|
|
274
|
-
}
|
|
216
|
+
style: { fill: "rgba(90, 154, 110, 0.3)", stroke: "#5A9A6E", strokeWidth: 2 }
|
|
275
217
|
}
|
|
276
218
|
) : null,
|
|
277
219
|
hasCompareData && compareCoords && compareCoords.map(([cx, cy], i) => {
|
|
@@ -279,7 +221,7 @@ function RadarChartCore({
|
|
|
279
221
|
const userVal = spokes[i][1];
|
|
280
222
|
const compareVal = compareData[shortTitle];
|
|
281
223
|
if (!compareVal || Number(compareVal) === 0) return null;
|
|
282
|
-
const matches = userVal !== 0 && compareVal
|
|
224
|
+
const matches = userVal !== 0 && compareVal != null && Number(userVal) === Number(compareVal);
|
|
283
225
|
return /* @__PURE__ */ React.createElement(
|
|
284
226
|
"circle",
|
|
285
227
|
{
|
|
@@ -289,14 +231,17 @@ function RadarChartCore({
|
|
|
289
231
|
r: matches ? 8 : 7,
|
|
290
232
|
fill: matches ? "#fed12e" : "#5A9A6E",
|
|
291
233
|
stroke: "#FFFFFF",
|
|
292
|
-
strokeWidth: 3
|
|
234
|
+
strokeWidth: 3,
|
|
235
|
+
style: { cursor: "default" },
|
|
236
|
+
onMouseEnter: () => setTooltip({ x: cx, y: cy, text: getStanceText(shortTitle, compareVal) }),
|
|
237
|
+
onMouseLeave: () => setTooltip(null)
|
|
293
238
|
}
|
|
294
239
|
);
|
|
295
240
|
}),
|
|
296
241
|
spokes.map(([shortTitle], i) => {
|
|
297
242
|
const angle = 2 * Math.PI * i / numSpokes;
|
|
298
|
-
const
|
|
299
|
-
const
|
|
243
|
+
const endX = centerX + (spokeExtension[shortTitle] ? extRadius : radius) * Math.sin(angle);
|
|
244
|
+
const endY = centerY - (spokeExtension[shortTitle] ? extRadius : radius) * Math.cos(angle);
|
|
300
245
|
const isUnansweredHitbox = !!unansweredSpokes[shortTitle];
|
|
301
246
|
return /* @__PURE__ */ React.createElement(
|
|
302
247
|
"line",
|
|
@@ -304,54 +249,56 @@ function RadarChartCore({
|
|
|
304
249
|
key: `hitbox-${shortTitle}`,
|
|
305
250
|
x1: centerX,
|
|
306
251
|
y1: centerY,
|
|
307
|
-
x2:
|
|
308
|
-
y2:
|
|
252
|
+
x2: endX,
|
|
253
|
+
y2: endY,
|
|
309
254
|
stroke: "transparent",
|
|
310
255
|
strokeWidth: 14,
|
|
311
256
|
onClick: () => isUnansweredHitbox ? onReplaceTopic(shortTitle) : onToggleInversion(shortTitle),
|
|
312
257
|
style: { cursor: "pointer" }
|
|
313
258
|
}
|
|
314
259
|
);
|
|
315
|
-
})
|
|
260
|
+
}),
|
|
261
|
+
tooltip && (() => {
|
|
262
|
+
const tipW = 190;
|
|
263
|
+
const tipH = 70;
|
|
264
|
+
const svgW = size + sidePadding * 2;
|
|
265
|
+
const tx = tooltip.x + sidePadding + 12 > svgW - tipW ? tooltip.x - tipW - 12 : tooltip.x + 12;
|
|
266
|
+
const ty = tooltip.y - 10;
|
|
267
|
+
return /* @__PURE__ */ React.createElement(
|
|
268
|
+
"foreignObject",
|
|
269
|
+
{
|
|
270
|
+
x: tx,
|
|
271
|
+
y: ty,
|
|
272
|
+
width: tipW,
|
|
273
|
+
height: tipH,
|
|
274
|
+
style: { overflow: "visible", pointerEvents: "none" }
|
|
275
|
+
},
|
|
276
|
+
/* @__PURE__ */ React.createElement(
|
|
277
|
+
"div",
|
|
278
|
+
{
|
|
279
|
+
xmlns: "http://www.w3.org/1999/xhtml",
|
|
280
|
+
style: {
|
|
281
|
+
background: "white",
|
|
282
|
+
border: "1px solid #d1d5db",
|
|
283
|
+
borderRadius: 6,
|
|
284
|
+
padding: "6px 10px",
|
|
285
|
+
fontSize: 11,
|
|
286
|
+
lineHeight: 1.4,
|
|
287
|
+
color: "#111",
|
|
288
|
+
boxShadow: "0 2px 8px rgba(0,0,0,0.12)",
|
|
289
|
+
width: tipW + "px",
|
|
290
|
+
wordWrap: "break-word"
|
|
291
|
+
}
|
|
292
|
+
},
|
|
293
|
+
tooltip.text
|
|
294
|
+
)
|
|
295
|
+
);
|
|
296
|
+
})()
|
|
316
297
|
);
|
|
317
298
|
}
|
|
318
|
-
function adaptiveFontSize(longestLineLen, baseFSize) {
|
|
319
|
-
return Math.max(baseFSize, 10);
|
|
320
|
-
}
|
|
321
|
-
function wrapLabel(label, maxChars = 12) {
|
|
322
|
-
const str = String(label);
|
|
323
|
-
let rawWords;
|
|
324
|
-
if (str.includes("/")) {
|
|
325
|
-
rawWords = str.split("/").reduce((acc, segment, idx, arr) => {
|
|
326
|
-
const part = idx < arr.length - 1 ? segment + "/" : segment;
|
|
327
|
-
if (part.trim()) acc.push(part.trim());
|
|
328
|
-
return acc;
|
|
329
|
-
}, []);
|
|
330
|
-
} else {
|
|
331
|
-
rawWords = str.split(/\s+/);
|
|
332
|
-
}
|
|
333
|
-
const lines = [];
|
|
334
|
-
let line = "";
|
|
335
|
-
for (const word of rawWords) {
|
|
336
|
-
if (line === "") {
|
|
337
|
-
line = word;
|
|
338
|
-
} else if ((line + " " + word).length <= maxChars) {
|
|
339
|
-
line += " " + word;
|
|
340
|
-
} else {
|
|
341
|
-
lines.push(line);
|
|
342
|
-
line = word;
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
if (line) lines.push(line);
|
|
346
|
-
if (lines.length > 2) {
|
|
347
|
-
const overflow = lines.splice(2).join(" ");
|
|
348
|
-
lines[1] = lines[1] + " " + overflow;
|
|
349
|
-
}
|
|
350
|
-
return lines;
|
|
351
|
-
}
|
|
352
299
|
|
|
353
300
|
// src/Header.jsx
|
|
354
|
-
import React2, { useState as
|
|
301
|
+
import React2, { useState as useState3, useRef as useRef2, useEffect as useEffect3 } from "react";
|
|
355
302
|
|
|
356
303
|
// src/tokens.js
|
|
357
304
|
var colorScales = {
|
|
@@ -747,9 +694,9 @@ var breakpoints = {
|
|
|
747
694
|
};
|
|
748
695
|
|
|
749
696
|
// src/useMediaQuery.js
|
|
750
|
-
import { useState, useEffect as useEffect2 } from "react";
|
|
697
|
+
import { useState as useState2, useEffect as useEffect2 } from "react";
|
|
751
698
|
function useMediaQuery(query) {
|
|
752
|
-
const [matches, setMatches] =
|
|
699
|
+
const [matches, setMatches] = useState2(() => {
|
|
753
700
|
if (typeof window === "undefined") return false;
|
|
754
701
|
return window.matchMedia(query).matches;
|
|
755
702
|
});
|
|
@@ -768,6 +715,7 @@ function useMediaQuery(query) {
|
|
|
768
715
|
function Header({
|
|
769
716
|
logoSrc,
|
|
770
717
|
logoAlt = "Empowered Vote",
|
|
718
|
+
logoHref = "https://login.empowered.vote/profile",
|
|
771
719
|
navItems = [],
|
|
772
720
|
ctaButton,
|
|
773
721
|
secondaryAction,
|
|
@@ -776,9 +724,9 @@ function Header({
|
|
|
776
724
|
profileMenu,
|
|
777
725
|
style = {}
|
|
778
726
|
}) {
|
|
779
|
-
const [mobileMenuOpen, setMobileMenuOpen] =
|
|
780
|
-
const [openDropdown, setOpenDropdown] =
|
|
781
|
-
const [profileOpen, setProfileOpen] =
|
|
727
|
+
const [mobileMenuOpen, setMobileMenuOpen] = useState3(false);
|
|
728
|
+
const [openDropdown, setOpenDropdown] = useState3(null);
|
|
729
|
+
const [profileOpen, setProfileOpen] = useState3(false);
|
|
782
730
|
const isMobile = useMediaQuery("(max-width: 768px)");
|
|
783
731
|
const profileRef = useRef2(null);
|
|
784
732
|
useEffect3(() => {
|
|
@@ -1051,8 +999,8 @@ function Header({
|
|
|
1051
999
|
return /* @__PURE__ */ React2.createElement("header", { style: styles2.header }, /* @__PURE__ */ React2.createElement("div", { style: styles2.container }, /* @__PURE__ */ React2.createElement(
|
|
1052
1000
|
"a",
|
|
1053
1001
|
{
|
|
1054
|
-
href:
|
|
1055
|
-
onClick: (e) => handleNavClick(e,
|
|
1002
|
+
href: logoHref,
|
|
1003
|
+
onClick: (e) => handleNavClick(e, logoHref),
|
|
1056
1004
|
style: { display: "flex", alignItems: "center" }
|
|
1057
1005
|
},
|
|
1058
1006
|
logoSrc ? /* @__PURE__ */ React2.createElement("img", { src: logoSrc, alt: logoAlt, style: styles2.logo }) : /* @__PURE__ */ React2.createElement(
|
|
@@ -1692,7 +1640,7 @@ function FilterSidebar({
|
|
|
1692
1640
|
}
|
|
1693
1641
|
|
|
1694
1642
|
// src/PoliticianCard.jsx
|
|
1695
|
-
import React6, { useState as
|
|
1643
|
+
import React6, { useState as useState4, useEffect as useEffect4 } from "react";
|
|
1696
1644
|
function PoliticianCard({
|
|
1697
1645
|
id,
|
|
1698
1646
|
imageSrc,
|
|
@@ -1887,7 +1835,7 @@ function PoliticianCard({
|
|
|
1887
1835
|
}
|
|
1888
1836
|
)
|
|
1889
1837
|
);
|
|
1890
|
-
const [imgError, setImgError] =
|
|
1838
|
+
const [imgError, setImgError] = useState4(false);
|
|
1891
1839
|
useEffect4(() => {
|
|
1892
1840
|
setImgError(false);
|
|
1893
1841
|
}, [imageSrc]);
|
|
@@ -1954,7 +1902,7 @@ function PoliticianCard({
|
|
|
1954
1902
|
}
|
|
1955
1903
|
|
|
1956
1904
|
// src/CompassCardHorizontal.jsx
|
|
1957
|
-
import React11, { useState as
|
|
1905
|
+
import React11, { useState as useState6, useEffect as useEffect5 } from "react";
|
|
1958
1906
|
|
|
1959
1907
|
// src/PlaceholderRadar.jsx
|
|
1960
1908
|
import React7 from "react";
|
|
@@ -2037,7 +1985,7 @@ function PlaceholderRadar({ size = 250, name = "" }) {
|
|
|
2037
1985
|
import React10 from "react";
|
|
2038
1986
|
|
|
2039
1987
|
// src/IconOverlay.jsx
|
|
2040
|
-
import React9, { useState as
|
|
1988
|
+
import React9, { useState as useState5 } from "react";
|
|
2041
1989
|
import {
|
|
2042
1990
|
useFloating,
|
|
2043
1991
|
useHover,
|
|
@@ -2126,7 +2074,7 @@ function BranchIcon({ size = 16, color = "currentColor", branch }) {
|
|
|
2126
2074
|
|
|
2127
2075
|
// src/IconOverlay.jsx
|
|
2128
2076
|
function IconWithTooltip({ IconComponent, color, tooltip, size = 14, extraProps = {}, onClick }) {
|
|
2129
|
-
const [isOpen, setIsOpen] =
|
|
2077
|
+
const [isOpen, setIsOpen] = useState5(false);
|
|
2130
2078
|
const { refs, floatingStyles, context } = useFloating({
|
|
2131
2079
|
open: isOpen,
|
|
2132
2080
|
onOpenChange: setIsOpen,
|
|
@@ -2316,10 +2264,10 @@ function CompassCardHorizontal({
|
|
|
2316
2264
|
onClick
|
|
2317
2265
|
}) {
|
|
2318
2266
|
var _a;
|
|
2319
|
-
const [hovered, setHovered] =
|
|
2320
|
-
const [focused, setFocused] =
|
|
2321
|
-
const [imgError, setImgError] =
|
|
2322
|
-
const [emptyCtaHovered, setEmptyCtaHovered] =
|
|
2267
|
+
const [hovered, setHovered] = useState6(false);
|
|
2268
|
+
const [focused, setFocused] = useState6(false);
|
|
2269
|
+
const [imgError, setImgError] = useState6(false);
|
|
2270
|
+
const [emptyCtaHovered, setEmptyCtaHovered] = useState6(false);
|
|
2323
2271
|
useEffect5(() => {
|
|
2324
2272
|
setImgError(false);
|
|
2325
2273
|
}, [politician == null ? void 0 : politician.photo_origin_url]);
|
|
@@ -2569,7 +2517,7 @@ function CompassCardHorizontal({
|
|
|
2569
2517
|
}
|
|
2570
2518
|
|
|
2571
2519
|
// src/CompassCardVertical.jsx
|
|
2572
|
-
import React12, { useState as
|
|
2520
|
+
import React12, { useState as useState7, useEffect as useEffect6 } from "react";
|
|
2573
2521
|
var RADAR_SIZE2 = 400;
|
|
2574
2522
|
function CompassCardVertical({
|
|
2575
2523
|
politician,
|
|
@@ -2583,10 +2531,10 @@ function CompassCardVertical({
|
|
|
2583
2531
|
onClick
|
|
2584
2532
|
}) {
|
|
2585
2533
|
var _a;
|
|
2586
|
-
const [hovered, setHovered] =
|
|
2587
|
-
const [focused, setFocused] =
|
|
2588
|
-
const [imgError, setImgError] =
|
|
2589
|
-
const [emptyCtaHovered, setEmptyCtaHovered] =
|
|
2534
|
+
const [hovered, setHovered] = useState7(false);
|
|
2535
|
+
const [focused, setFocused] = useState7(false);
|
|
2536
|
+
const [imgError, setImgError] = useState7(false);
|
|
2537
|
+
const [emptyCtaHovered, setEmptyCtaHovered] = useState7(false);
|
|
2590
2538
|
useEffect6(() => {
|
|
2591
2539
|
setImgError(false);
|
|
2592
2540
|
}, [politician == null ? void 0 : politician.photo_origin_url]);
|
|
@@ -2921,7 +2869,7 @@ function CompassCardVertical({
|
|
|
2921
2869
|
}
|
|
2922
2870
|
|
|
2923
2871
|
// src/CompassKey.jsx
|
|
2924
|
-
import React13, { useEffect as useEffect7, useState as
|
|
2872
|
+
import React13, { useEffect as useEffect7, useState as useState8 } from "react";
|
|
2925
2873
|
|
|
2926
2874
|
// src/evContext.js
|
|
2927
2875
|
var DEFAULT_BROKER_URL = "https://ev-context.empowered.vote/";
|
|
@@ -3166,8 +3114,8 @@ var evContext = {
|
|
|
3166
3114
|
|
|
3167
3115
|
// src/CompassKey.jsx
|
|
3168
3116
|
function CompassKey({ compact = false } = {}) {
|
|
3169
|
-
const [dismissed, setDismissed] =
|
|
3170
|
-
const [loaded, setLoaded] =
|
|
3117
|
+
const [dismissed, setDismissed] = useState8(false);
|
|
3118
|
+
const [loaded, setLoaded] = useState8(false);
|
|
3171
3119
|
useEffect7(() => {
|
|
3172
3120
|
let cancelled = false;
|
|
3173
3121
|
evContext.get().then((shared) => {
|
|
@@ -3294,7 +3242,7 @@ function CompassKey({ compact = false } = {}) {
|
|
|
3294
3242
|
}
|
|
3295
3243
|
|
|
3296
3244
|
// src/CategorySection.jsx
|
|
3297
|
-
import React14, { useState as
|
|
3245
|
+
import React14, { useState as useState9 } from "react";
|
|
3298
3246
|
function CategorySection({
|
|
3299
3247
|
title,
|
|
3300
3248
|
infoTooltip,
|
|
@@ -3304,7 +3252,7 @@ function CategorySection({
|
|
|
3304
3252
|
tier
|
|
3305
3253
|
}) {
|
|
3306
3254
|
var _a, _b;
|
|
3307
|
-
const [showTooltip, setShowTooltip] =
|
|
3255
|
+
const [showTooltip, setShowTooltip] = useState9(false);
|
|
3308
3256
|
const tierStyle = tier ? tierColors[tier] : null;
|
|
3309
3257
|
const styles2 = {
|
|
3310
3258
|
section: {
|
|
@@ -3465,7 +3413,7 @@ function SubGroupSection({ title, websiteUrl, children, gridTemplateColumns, gap
|
|
|
3465
3413
|
}
|
|
3466
3414
|
|
|
3467
3415
|
// src/GovernmentBodySection.jsx
|
|
3468
|
-
import React16, { useState as
|
|
3416
|
+
import React16, { useState as useState10 } from "react";
|
|
3469
3417
|
function GovernmentBodySection({
|
|
3470
3418
|
title,
|
|
3471
3419
|
websiteUrl,
|
|
@@ -3474,7 +3422,7 @@ function GovernmentBodySection({
|
|
|
3474
3422
|
children
|
|
3475
3423
|
}) {
|
|
3476
3424
|
var _a;
|
|
3477
|
-
const [expanded, setExpanded] =
|
|
3425
|
+
const [expanded, setExpanded] = useState10(defaultExpanded);
|
|
3478
3426
|
const tierStyle = tier ? tierColors[tier] : null;
|
|
3479
3427
|
const accentColor = (_a = tierStyle == null ? void 0 : tierStyle.accent) != null ? _a : colors.borderMedium;
|
|
3480
3428
|
const styles2 = {
|
|
@@ -3803,7 +3751,7 @@ function IssueTags({
|
|
|
3803
3751
|
}
|
|
3804
3752
|
|
|
3805
3753
|
// src/CommitteeTable.jsx
|
|
3806
|
-
import React19, { useState as
|
|
3754
|
+
import React19, { useState as useState11 } from "react";
|
|
3807
3755
|
var ROLE_ORDER = {
|
|
3808
3756
|
"chair": 0,
|
|
3809
3757
|
"co-chair": 1,
|
|
@@ -3830,7 +3778,7 @@ function CommitteeTable({
|
|
|
3830
3778
|
maxVisible = 6,
|
|
3831
3779
|
style = {}
|
|
3832
3780
|
}) {
|
|
3833
|
-
const [showAll, setShowAll] =
|
|
3781
|
+
const [showAll, setShowAll] = useState11(false);
|
|
3834
3782
|
if (committees.length === 0) {
|
|
3835
3783
|
return null;
|
|
3836
3784
|
}
|
|
@@ -3934,7 +3882,7 @@ function CommitteeTable({
|
|
|
3934
3882
|
}
|
|
3935
3883
|
|
|
3936
3884
|
// src/PoliticianProfile.jsx
|
|
3937
|
-
import React22, { useState as
|
|
3885
|
+
import React22, { useState as useState12, useEffect as useEffect8 } from "react";
|
|
3938
3886
|
|
|
3939
3887
|
// src/LegislativeInlineSummary.jsx
|
|
3940
3888
|
import React20 from "react";
|
|
@@ -4377,7 +4325,7 @@ function PoliticianProfile({
|
|
|
4377
4325
|
return pol.photo_origin_url;
|
|
4378
4326
|
})();
|
|
4379
4327
|
const initials = [pol.first_name, pol.last_name].filter(Boolean).map((n) => n[0]).join("");
|
|
4380
|
-
const [imgError, setImgError] =
|
|
4328
|
+
const [imgError, setImgError] = useState12(false);
|
|
4381
4329
|
useEffect8(() => {
|
|
4382
4330
|
setImgError(false);
|
|
4383
4331
|
}, [profileImageUrl]);
|
|
@@ -4787,7 +4735,7 @@ function PoliticianProfile({
|
|
|
4787
4735
|
}
|
|
4788
4736
|
|
|
4789
4737
|
// src/LegislativeRecord.jsx
|
|
4790
|
-
import React23, { useState as
|
|
4738
|
+
import React23, { useState as useState13 } from "react";
|
|
4791
4739
|
var DEFAULT_LIMIT = 25;
|
|
4792
4740
|
function normalizeText(str) {
|
|
4793
4741
|
if (!str) return "";
|
|
@@ -4966,7 +4914,7 @@ function Spinner() {
|
|
|
4966
4914
|
} }), /* @__PURE__ */ React23.createElement("style", null, `@keyframes ev-spin { to { transform: rotate(360deg); } }`));
|
|
4967
4915
|
}
|
|
4968
4916
|
function CommitteesSection({ committees, leadership }) {
|
|
4969
|
-
const [showAll, setShowAll] =
|
|
4917
|
+
const [showAll, setShowAll] = useState13(false);
|
|
4970
4918
|
const visible = showAll ? committees : committees.slice(0, DEFAULT_LIMIT);
|
|
4971
4919
|
return /* @__PURE__ */ React23.createElement("div", { style: { marginBottom: spacing[8] } }, /* @__PURE__ */ React23.createElement(SectionHeader, { title: "Committees & Leadership" }), leadership && leadership.length > 0 && /* @__PURE__ */ React23.createElement("div", { style: { display: "flex", flexWrap: "wrap", gap: spacing[2], marginBottom: spacing[4] } }, leadership.map((role, i) => /* @__PURE__ */ React23.createElement("div", { key: i, style: {
|
|
4972
4920
|
display: "inline-flex",
|
|
@@ -5006,8 +4954,8 @@ function CommitteesSection({ committees, leadership }) {
|
|
|
5006
4954
|
}
|
|
5007
4955
|
function LegislationSection({ bills, isMobile }) {
|
|
5008
4956
|
const years = getYears(bills, "introduced_at");
|
|
5009
|
-
const [yearFilter, setYearFilter] =
|
|
5010
|
-
const [showAll, setShowAll] =
|
|
4957
|
+
const [yearFilter, setYearFilter] = useState13("All");
|
|
4958
|
+
const [showAll, setShowAll] = useState13(false);
|
|
5011
4959
|
const handleYearChange = (y) => {
|
|
5012
4960
|
setYearFilter(y);
|
|
5013
4961
|
setShowAll(false);
|
|
@@ -5068,8 +5016,8 @@ function LegislationSection({ bills, isMobile }) {
|
|
|
5068
5016
|
}
|
|
5069
5017
|
function VotingSection({ votes, isMobile }) {
|
|
5070
5018
|
const years = getYears(votes, "vote_date");
|
|
5071
|
-
const [yearFilter, setYearFilter] =
|
|
5072
|
-
const [showAll, setShowAll] =
|
|
5019
|
+
const [yearFilter, setYearFilter] = useState13("All");
|
|
5020
|
+
const [showAll, setShowAll] = useState13(false);
|
|
5073
5021
|
const handleYearChange = (y) => {
|
|
5074
5022
|
setYearFilter(y);
|
|
5075
5023
|
setShowAll(false);
|
|
@@ -5281,7 +5229,7 @@ function JudicialRecordDetail({ politician = {}, judicialRecord, onBack }) {
|
|
|
5281
5229
|
}
|
|
5282
5230
|
|
|
5283
5231
|
// src/AuthForm.jsx
|
|
5284
|
-
import React25, { useState as
|
|
5232
|
+
import React25, { useState as useState14 } from "react";
|
|
5285
5233
|
function AuthForm({
|
|
5286
5234
|
logoSrc = "/EVLogo.svg",
|
|
5287
5235
|
appName = "Empowered Vote",
|
|
@@ -5292,11 +5240,11 @@ function AuthForm({
|
|
|
5292
5240
|
error = null,
|
|
5293
5241
|
submitting = false
|
|
5294
5242
|
}) {
|
|
5295
|
-
const [username, setUsername] =
|
|
5296
|
-
const [password, setPassword] =
|
|
5297
|
-
const [confirmPassword, setConfirmPassword] =
|
|
5298
|
-
const [showPasswords, setShowPasswords] =
|
|
5299
|
-
const [passwordMismatch, setPasswordMismatch] =
|
|
5243
|
+
const [username, setUsername] = useState14("");
|
|
5244
|
+
const [password, setPassword] = useState14("");
|
|
5245
|
+
const [confirmPassword, setConfirmPassword] = useState14("");
|
|
5246
|
+
const [showPasswords, setShowPasswords] = useState14(false);
|
|
5247
|
+
const [passwordMismatch, setPasswordMismatch] = useState14(false);
|
|
5300
5248
|
const isLogin = mode === "login";
|
|
5301
5249
|
const handleSubmit = (e) => {
|
|
5302
5250
|
e.preventDefault();
|
|
@@ -5744,7 +5692,7 @@ function TopicTierBadge({
|
|
|
5744
5692
|
}
|
|
5745
5693
|
|
|
5746
5694
|
// src/CompassCoverageCallout.jsx
|
|
5747
|
-
import React27, { useState as
|
|
5695
|
+
import React27, { useState as useState15 } from "react";
|
|
5748
5696
|
var TIER_LABELS = {
|
|
5749
5697
|
federal: "federal",
|
|
5750
5698
|
state: "state",
|
|
@@ -5757,7 +5705,7 @@ function CompassCoverageCallout({
|
|
|
5757
5705
|
compassUrl,
|
|
5758
5706
|
onDismiss
|
|
5759
5707
|
}) {
|
|
5760
|
-
const [dismissed, setDismissed] =
|
|
5708
|
+
const [dismissed, setDismissed] = useState15(false);
|
|
5761
5709
|
if (dismissed) return null;
|
|
5762
5710
|
const tierLabel = TIER_LABELS[tier] || tier;
|
|
5763
5711
|
const tierStyle = tierColors[tier] || tierColors.federal;
|
|
@@ -5897,7 +5845,7 @@ function computeTierCoverage(topics) {
|
|
|
5897
5845
|
}
|
|
5898
5846
|
|
|
5899
5847
|
// src/useEvContextPromotion.js
|
|
5900
|
-
import { useEffect as useEffect9, useState as
|
|
5848
|
+
import { useEffect as useEffect9, useState as useState16, useCallback, useRef as useRef3 } from "react";
|
|
5901
5849
|
function useEvContextPromotion({
|
|
5902
5850
|
domain,
|
|
5903
5851
|
isLoggedIn,
|
|
@@ -5906,10 +5854,10 @@ function useEvContextPromotion({
|
|
|
5906
5854
|
apiWriter,
|
|
5907
5855
|
enabled = true
|
|
5908
5856
|
}) {
|
|
5909
|
-
const [shouldPrompt, setShouldPrompt] =
|
|
5910
|
-
const [payload, setPayload] =
|
|
5911
|
-
const [status, setStatus] =
|
|
5912
|
-
const [error, setError] =
|
|
5857
|
+
const [shouldPrompt, setShouldPrompt] = useState16(false);
|
|
5858
|
+
const [payload, setPayload] = useState16(null);
|
|
5859
|
+
const [status, setStatus] = useState16("idle");
|
|
5860
|
+
const [error, setError] = useState16(null);
|
|
5913
5861
|
const apiDataRef = useRef3(apiData);
|
|
5914
5862
|
apiDataRef.current = apiData;
|
|
5915
5863
|
const userIdRef = useRef3(userId);
|
|
@@ -6056,7 +6004,7 @@ function isGuestPopulated(domain, fullEvContext) {
|
|
|
6056
6004
|
}
|
|
6057
6005
|
|
|
6058
6006
|
// src/StanceAccordion.jsx
|
|
6059
|
-
import React30, { useState as
|
|
6007
|
+
import React30, { useState as useState17, useRef as useRef4, useCallback as useCallback2, useEffect as useEffect10 } from "react";
|
|
6060
6008
|
|
|
6061
6009
|
// src/Favicon.jsx
|
|
6062
6010
|
import React29 from "react";
|
|
@@ -6117,9 +6065,9 @@ function StanceAccordion({
|
|
|
6117
6065
|
apiUrl = "https://api.empowered.vote"
|
|
6118
6066
|
}) {
|
|
6119
6067
|
var _a;
|
|
6120
|
-
const [expandedTopicId, setExpandedTopicId] =
|
|
6121
|
-
const [loadingId, setLoadingId] =
|
|
6122
|
-
const [showAll, setShowAll] =
|
|
6068
|
+
const [expandedTopicId, setExpandedTopicId] = useState17(null);
|
|
6069
|
+
const [loadingId, setLoadingId] = useState17(null);
|
|
6070
|
+
const [showAll, setShowAll] = useState17(false);
|
|
6123
6071
|
const contextCache = useRef4(/* @__PURE__ */ new Map());
|
|
6124
6072
|
const quotesCache = useRef4(null);
|
|
6125
6073
|
const polAnswerMap = {};
|