@empoweredvote/ev-ui 0.6.2 → 0.6.4

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.mjs CHANGED
@@ -2390,7 +2390,7 @@ function CompassCardHorizontal({
2390
2390
  textTransform: "uppercase",
2391
2391
  padding: "6px 0",
2392
2392
  pointerEvents: "none"
2393
- } }, "Running Unopposed")),
2393
+ } }, typeof politician.running_unopposed === "string" ? politician.running_unopposed : "Running Unopposed")),
2394
2394
  /* @__PURE__ */ React10.createElement("div", { style: { flex: 1, minWidth: 0, padding: spacing[4], paddingLeft: spacing[3] } }, /* @__PURE__ */ React10.createElement(
2395
2395
  CompassCardHorizontalMeta,
2396
2396
  {
@@ -2740,7 +2740,7 @@ function CompassCardVertical({
2740
2740
  textTransform: "uppercase",
2741
2741
  padding: "6px 0",
2742
2742
  borderRadius: borderRadius.sm
2743
- } }, "Running Unopposed"),
2743
+ } }, typeof politician.running_unopposed === "string" ? politician.running_unopposed : "Running Unopposed"),
2744
2744
  /* @__PURE__ */ React11.createElement("div", { style: {
2745
2745
  flex: 1,
2746
2746
  padding: spacing[4],
@@ -2913,6 +2913,9 @@ var evContext = {
2913
2913
  if (current.authed.compass !== void 0) out.compass = current.authed.compass;
2914
2914
  if (current.authed.address !== void 0) out.address = current.authed.address;
2915
2915
  if (current.authed.verdicts !== void 0) out.verdicts = current.authed.verdicts;
2916
+ if (current.authed.promotionDismissed !== void 0) {
2917
+ out.promotionDismissed = current.authed.promotionDismissed;
2918
+ }
2916
2919
  return out;
2917
2920
  },
2918
2921
  /**
@@ -2937,6 +2940,9 @@ var evContext = {
2937
2940
  if (patch.compass !== void 0) allowed.compass = patch.compass;
2938
2941
  if (patch.address !== void 0) allowed.address = patch.address;
2939
2942
  if (patch.verdicts !== void 0) allowed.verdicts = patch.verdicts;
2943
+ if (patch.promotionDismissed !== void 0) {
2944
+ allowed.promotionDismissed = patch.promotionDismissed;
2945
+ }
2940
2946
  if (Object.keys(allowed).length === 0) return false;
2941
2947
  const current = await this.get() || {};
2942
2948
  const priorAuthed = current.authed && current.authed.userId === userId ? current.authed : null;
@@ -2945,10 +2951,17 @@ var evContext = {
2945
2951
  if (priorAuthed.compass !== void 0) nextAuthed.compass = priorAuthed.compass;
2946
2952
  if (priorAuthed.address !== void 0) nextAuthed.address = priorAuthed.address;
2947
2953
  if (priorAuthed.verdicts !== void 0) nextAuthed.verdicts = priorAuthed.verdicts;
2954
+ if (priorAuthed.promotionDismissed !== void 0) {
2955
+ nextAuthed.promotionDismissed = priorAuthed.promotionDismissed;
2956
+ }
2948
2957
  }
2949
2958
  if (allowed.compass !== void 0) nextAuthed.compass = allowed.compass;
2950
2959
  if (allowed.address !== void 0) nextAuthed.address = allowed.address;
2951
2960
  if (allowed.verdicts !== void 0) nextAuthed.verdicts = allowed.verdicts;
2961
+ if (allowed.promotionDismissed !== void 0 && allowed.promotionDismissed !== null && typeof allowed.promotionDismissed === "object") {
2962
+ const prior = priorAuthed && priorAuthed.promotionDismissed && typeof priorAuthed.promotionDismissed === "object" ? priorAuthed.promotionDismissed : {};
2963
+ nextAuthed.promotionDismissed = { ...prior, ...allowed.promotionDismissed };
2964
+ }
2952
2965
  return this.set({ ...current, authed: nextAuthed });
2953
2966
  },
2954
2967
  /**
@@ -5717,8 +5730,167 @@ function computeTierCoverage(topics) {
5717
5730
  return counts;
5718
5731
  }
5719
5732
 
5733
+ // src/useEvContextPromotion.js
5734
+ import { useEffect as useEffect9, useState as useState15, useCallback, useRef as useRef3 } from "react";
5735
+ function useEvContextPromotion({
5736
+ domain,
5737
+ isLoggedIn,
5738
+ userId,
5739
+ apiData,
5740
+ apiWriter,
5741
+ enabled = true
5742
+ }) {
5743
+ const [shouldPrompt, setShouldPrompt] = useState15(false);
5744
+ const [payload, setPayload] = useState15(null);
5745
+ const [status, setStatus] = useState15("idle");
5746
+ const [error, setError] = useState15(null);
5747
+ const apiDataRef = useRef3(apiData);
5748
+ apiDataRef.current = apiData;
5749
+ const userIdRef = useRef3(userId);
5750
+ userIdRef.current = userId;
5751
+ const isLoggedInRef = useRef3(isLoggedIn);
5752
+ isLoggedInRef.current = isLoggedIn;
5753
+ const enabledRef = useRef3(enabled);
5754
+ enabledRef.current = enabled;
5755
+ const domainRef = useRef3(domain);
5756
+ domainRef.current = domain;
5757
+ const apiWriterRef = useRef3(apiWriter);
5758
+ apiWriterRef.current = apiWriter;
5759
+ const detect = useCallback(async () => {
5760
+ const _enabled = enabledRef.current;
5761
+ const _isLoggedIn = isLoggedInRef.current;
5762
+ const _userId = userIdRef.current;
5763
+ const _apiData = apiDataRef.current;
5764
+ const _domain = domainRef.current;
5765
+ if (!_enabled || !_isLoggedIn || !_userId) {
5766
+ setShouldPrompt(false);
5767
+ setPayload(null);
5768
+ return;
5769
+ }
5770
+ if (!isApiEmpty(_domain, _apiData)) {
5771
+ setShouldPrompt(false);
5772
+ setPayload(null);
5773
+ return;
5774
+ }
5775
+ try {
5776
+ const slice = await evContext.getAuthedSlice(_userId);
5777
+ if (slice && slice.promotionDismissed && slice.promotionDismissed[_domain] === true) {
5778
+ setShouldPrompt(false);
5779
+ setPayload(null);
5780
+ return;
5781
+ }
5782
+ } catch {
5783
+ }
5784
+ let guest = null;
5785
+ try {
5786
+ guest = await evContext.get();
5787
+ } catch {
5788
+ guest = null;
5789
+ }
5790
+ if (isGuestPopulated(_domain, guest)) {
5791
+ setShouldPrompt(true);
5792
+ setPayload(guest[_domain]);
5793
+ } else {
5794
+ setShouldPrompt(false);
5795
+ setPayload(null);
5796
+ }
5797
+ }, []);
5798
+ useEffect9(() => {
5799
+ detect();
5800
+ }, [detect, isLoggedIn, userId, apiData, enabled, domain]);
5801
+ useEffect9(() => {
5802
+ const unsub = evContext.subscribe(() => {
5803
+ detect();
5804
+ });
5805
+ return unsub;
5806
+ }, [detect]);
5807
+ const promote = useCallback(async () => {
5808
+ const _userId = userIdRef.current;
5809
+ const _domain = domainRef.current;
5810
+ const _writer = apiWriterRef.current;
5811
+ const _payload = payload;
5812
+ if (!_userId || !_payload || typeof _writer !== "function") return;
5813
+ setStatus("saving");
5814
+ setError(null);
5815
+ try {
5816
+ await _writer(_payload);
5817
+ try {
5818
+ await evContext.setAuthedSlice(_userId, { [_domain]: _payload });
5819
+ } catch {
5820
+ }
5821
+ try {
5822
+ await evContext.setAuthedSlice(_userId, {
5823
+ promotionDismissed: { [_domain]: false }
5824
+ });
5825
+ } catch {
5826
+ }
5827
+ setStatus("saved");
5828
+ setShouldPrompt(false);
5829
+ } catch (err) {
5830
+ setStatus("error");
5831
+ setError(err instanceof Error ? err : new Error(String(err)));
5832
+ }
5833
+ }, [payload]);
5834
+ const dismiss = useCallback(async () => {
5835
+ const _userId = userIdRef.current;
5836
+ const _domain = domainRef.current;
5837
+ if (!_userId) return;
5838
+ try {
5839
+ await evContext.setAuthedSlice(_userId, {
5840
+ promotionDismissed: { [_domain]: true }
5841
+ });
5842
+ } catch {
5843
+ }
5844
+ setShouldPrompt(false);
5845
+ }, []);
5846
+ return { shouldPrompt, payload, promote, dismiss, status, error };
5847
+ }
5848
+ function isApiEmpty(domain, apiData) {
5849
+ if (apiData === null || apiData === void 0) return true;
5850
+ if (domain === "compass") {
5851
+ if (typeof apiData !== "object") return false;
5852
+ if (Array.isArray(apiData)) return apiData.length === 0;
5853
+ if (apiData.answers && typeof apiData.answers === "object") {
5854
+ return Object.keys(apiData.answers).length === 0;
5855
+ }
5856
+ return Object.keys(apiData).length === 0;
5857
+ }
5858
+ if (domain === "address") {
5859
+ if (typeof apiData === "string") return apiData.trim().length === 0;
5860
+ if (typeof apiData !== "object") return false;
5861
+ const a = apiData;
5862
+ const hasAddr = typeof a.formatted === "string" && a.formatted.length > 0;
5863
+ const hasAddrAlt = typeof a.addr === "string" && a.addr.length > 0;
5864
+ const hasLat = typeof a.lat === "number" || typeof a.latitude === "number";
5865
+ return !(hasAddr || hasAddrAlt || hasLat);
5866
+ }
5867
+ if (domain === "verdicts") {
5868
+ if (typeof apiData !== "object") return false;
5869
+ if (Array.isArray(apiData)) return apiData.length === 0;
5870
+ return Object.keys(apiData).length === 0;
5871
+ }
5872
+ return false;
5873
+ }
5874
+ function isGuestPopulated(domain, fullEvContext) {
5875
+ if (!fullEvContext || typeof fullEvContext !== "object") return false;
5876
+ const slice = fullEvContext[domain];
5877
+ if (!slice || typeof slice !== "object") return false;
5878
+ if (domain === "compass") {
5879
+ const ans = slice.answers || slice.a;
5880
+ if (ans && typeof ans === "object") return Object.keys(ans).length > 0;
5881
+ return false;
5882
+ }
5883
+ if (domain === "address") {
5884
+ return typeof slice.formatted === "string" && slice.formatted.length > 0 || typeof slice.addr === "string" && slice.addr.length > 0;
5885
+ }
5886
+ if (domain === "verdicts") {
5887
+ return Object.keys(slice).length > 0;
5888
+ }
5889
+ return false;
5890
+ }
5891
+
5720
5892
  // src/StanceAccordion.jsx
5721
- import React29, { useState as useState15, useRef as useRef3, useCallback, useEffect as useEffect9 } from "react";
5893
+ import React29, { useState as useState16, useRef as useRef4, useCallback as useCallback2, useEffect as useEffect10 } from "react";
5722
5894
 
5723
5895
  // src/Favicon.jsx
5724
5896
  import React28 from "react";
@@ -5779,11 +5951,11 @@ function StanceAccordion({
5779
5951
  apiUrl = "https://api.empowered.vote"
5780
5952
  }) {
5781
5953
  var _a;
5782
- const [expandedTopicId, setExpandedTopicId] = useState15(null);
5783
- const [loadingId, setLoadingId] = useState15(null);
5784
- const [showAll, setShowAll] = useState15(false);
5785
- const contextCache = useRef3(/* @__PURE__ */ new Map());
5786
- const quotesCache = useRef3(null);
5954
+ const [expandedTopicId, setExpandedTopicId] = useState16(null);
5955
+ const [loadingId, setLoadingId] = useState16(null);
5956
+ const [showAll, setShowAll] = useState16(false);
5957
+ const contextCache = useRef4(/* @__PURE__ */ new Map());
5958
+ const quotesCache = useRef4(null);
5787
5959
  const polAnswerMap = {};
5788
5960
  if (polAnswers) {
5789
5961
  polAnswers.forEach((a) => {
@@ -5842,7 +6014,7 @@ function StanceAccordion({
5842
6014
  quotesCache.current = [];
5843
6015
  }
5844
6016
  }
5845
- const handleToggle = useCallback(
6017
+ const handleToggle = useCallback2(
5846
6018
  async (topicId) => {
5847
6019
  if (expandedTopicId === topicId) {
5848
6020
  setExpandedTopicId(null);
@@ -5859,7 +6031,7 @@ function StanceAccordion({
5859
6031
  },
5860
6032
  [expandedTopicId, politicianId, apiUrl]
5861
6033
  );
5862
- useEffect9(() => {
6034
+ useEffect10(() => {
5863
6035
  if (initialExpandedTopicId && topics && topics.length > 0) {
5864
6036
  handleToggle(String(initialExpandedTopicId));
5865
6037
  }
@@ -6136,6 +6308,7 @@ export {
6136
6308
  spacing,
6137
6309
  textStyles,
6138
6310
  tierColors,
6311
+ useEvContextPromotion,
6139
6312
  useMediaQuery,
6140
6313
  zIndex
6141
6314
  };