@opengovsg/confetti 0.1.1 → 0.1.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/README.md CHANGED
@@ -56,7 +56,7 @@ function App() {
56
56
  3. Add Confetti to your CSP headers:
57
57
 
58
58
  ```
59
- connect-src https://confetti.hack2026.gov.sg;
59
+ connect-src https://confetti.gov.sg;
60
60
  ```
61
61
 
62
62
  ## Template Components
package/build/index.js CHANGED
@@ -201,8 +201,9 @@ const ConfettiContext = createContext(null);
201
201
  const ConfettiProvider = ({ children, surveyId, publishableKey, respondent: respondentInput, metadata = {}, isSurveyVisible: isSurveyVisibleInput, apiBaseUrl }) => {
202
202
  const hasTrackedViewRef = useRef(false);
203
203
  const [survey, setSurvey] = useState();
204
- const [lastRespondedAt, setLastRespondedAt] = useState();
205
- const [lastDismissedAt, setLastDismissedAt] = useState();
204
+ const [isSettled, setIsSettled] = useState(false);
205
+ const [lastRespondedAt, setLastRespondedAt] = useState(null);
206
+ const [lastDismissedAt, setLastDismissedAt] = useState(null);
206
207
  const responseId = useMemo(() => crypto.randomUUID(), []);
207
208
  const [internalRespondentId, setInternalRespondentId] = useLocalStorage(`cfti:${surveyId}:respondent`, "");
208
209
  useEffect(() => {
@@ -215,30 +216,51 @@ const ConfettiProvider = ({ children, surveyId, publishableKey, respondent: resp
215
216
  if (apiBaseUrl) properties.prefixUrl = apiBaseUrl;
216
217
  return client.extend(properties);
217
218
  }, [apiBaseUrl, publishableKey]);
218
- useEffect(() => {
219
- client$1.get(`v1/cfti/${surveyId}`).json().then((data) => {
220
- const parseResult = publicGetSurveyOutputSchema.safeParse(data);
221
- if (!parseResult.success) return;
222
- setSurvey(parseResult.data);
223
- });
219
+ const fetchRespondentData = useCallback(async () => {
224
220
  if (!respondent) return;
225
- client$1.get(`v1/cfti/${surveyId}/respondent/${respondent}`).json().then((data) => {
226
- const parseResult = publicGetRespondentOutputSchema.safeParse(data);
227
- if (!parseResult.success) {
228
- setLastRespondedAt(null);
229
- setLastDismissedAt(null);
230
- return;
231
- }
232
- setLastRespondedAt(parseResult.data.lastRespondedAt ? new Date(parseResult.data.lastRespondedAt) : null);
233
- setLastDismissedAt(parseResult.data.lastDismissedAt ? new Date(parseResult.data.lastDismissedAt) : null);
234
- });
221
+ const respondentData = await client$1.get(`v1/cfti/${surveyId}/respondent/${respondent}`).json();
222
+ const respondentResult = publicGetRespondentOutputSchema.safeParse(respondentData);
223
+ if (!respondentResult.success) return;
224
+ setLastRespondedAt(respondentResult.data.lastRespondedAt ? new Date(respondentResult.data.lastRespondedAt) : null);
225
+ setLastDismissedAt(respondentResult.data.lastDismissedAt ? new Date(respondentResult.data.lastDismissedAt) : null);
235
226
  }, [
236
- apiBaseUrl,
237
227
  client$1,
238
- internalRespondentId,
239
228
  respondent,
240
229
  surveyId
241
230
  ]);
231
+ useEffect(() => {
232
+ if (typeof window === "undefined" || typeof document === "undefined") return;
233
+ const eventHandler = () => {
234
+ if (document.visibilityState === "visible") fetchRespondentData();
235
+ };
236
+ document.addEventListener("visibilitychange", eventHandler);
237
+ return () => {
238
+ document.removeEventListener("visibilitychange", eventHandler);
239
+ };
240
+ }, [fetchRespondentData]);
241
+ useEffect(() => {
242
+ const fetchData = async () => {
243
+ hasTrackedViewRef.current = false;
244
+ setIsSettled(false);
245
+ setSurvey(void 0);
246
+ setLastRespondedAt(null);
247
+ setLastDismissedAt(null);
248
+ try {
249
+ const surveyData = await client$1.get(`v1/cfti/${surveyId}`).json();
250
+ const parseResult = publicGetSurveyOutputSchema.safeParse(surveyData);
251
+ if (!parseResult.success) return;
252
+ setSurvey(parseResult.data);
253
+ await fetchRespondentData();
254
+ } catch {} finally {
255
+ setIsSettled(true);
256
+ }
257
+ };
258
+ fetchData();
259
+ }, [
260
+ client$1,
261
+ fetchRespondentData,
262
+ surveyId
263
+ ]);
242
264
  const submit = useCallback(async ({ answers }) => {
243
265
  await client$1.put(`v1/cfti/${surveyId}/response/${responseId}`, { json: {
244
266
  respondent,
@@ -261,21 +283,22 @@ const ConfettiProvider = ({ children, surveyId, publishableKey, respondent: resp
261
283
  surveyId
262
284
  ]);
263
285
  const isSurveyVisible = useMemo(() => {
286
+ if (!isSettled) return false;
264
287
  if (isSurveyVisibleInput === void 0) return true;
265
288
  if (typeof isSurveyVisibleInput === "boolean") return isSurveyVisibleInput;
266
- if (lastRespondedAt === void 0 || lastDismissedAt === void 0) return false;
267
289
  return isSurveyVisibleInput({
268
290
  lastRespondedAt,
269
291
  lastDismissedAt
270
292
  });
271
293
  }, [
294
+ isSettled,
272
295
  isSurveyVisibleInput,
273
296
  lastRespondedAt,
274
297
  lastDismissedAt
275
298
  ]);
276
299
  useEffect(() => {
277
300
  if (hasTrackedViewRef.current) return;
278
- if (isSurveyVisible) {
301
+ if (isSurveyVisible && survey && respondent) {
279
302
  hasTrackedViewRef.current = true;
280
303
  client$1.post(`v1/cfti/${surveyId}/respondent/${respondent}/event`, { json: { type: "view" } }).catch(() => {});
281
304
  }
@@ -283,6 +306,7 @@ const ConfettiProvider = ({ children, surveyId, publishableKey, respondent: resp
283
306
  client$1,
284
307
  isSurveyVisible,
285
308
  respondent,
309
+ survey,
286
310
  surveyId
287
311
  ]);
288
312
  if (!isSurveyVisible || !survey) return null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengovsg/confetti",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "sideEffects": false,
5
5
  "description": "Widgets for Confetti",
6
6
  "license": "SEE LICENSE IN LICENSE.md",
@@ -45,10 +45,10 @@
45
45
  "prettier": "^3.7.4",
46
46
  "tsdown": "0.19.0",
47
47
  "typescript": "^5.9.3",
48
+ "@confetti/eslint-config": "0.0.0",
48
49
  "@confetti/prettier-config": "0.0.0",
49
50
  "@confetti/tsconfig": "0.0.0",
50
- "@confetti/validators": "0.0.0",
51
- "@confetti/eslint-config": "0.0.0"
51
+ "@confetti/validators": "0.0.0"
52
52
  },
53
53
  "prettier": "@confetti/prettier-config",
54
54
  "scripts": {