@opengovsg/confetti 0.0.4 → 0.0.6

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.
@@ -1,7 +1,7 @@
1
1
  :root {
2
2
  --confetti-font-scale: 16px;
3
3
  /* Define CSS Variables with defaults */
4
- --confetti-box-padding: 20px 24px;
4
+ --confetti-box-padding: 24px;
5
5
  --confetti-max-width: 300px;
6
6
  --confetti-z-index: 2147483647;
7
7
  --confetti-border-color: #e4e4e7;
@@ -80,7 +80,7 @@
80
80
  .confetti {
81
81
  font-family: var(--confetti-font-family);
82
82
  overflow: hidden;
83
- padding: 24px;
83
+ padding: var(--confetti-box-padding);
84
84
  border-radius: var(--confetti-border-radius);
85
85
  border: 1px solid var(--confetti-border-color);
86
86
  display: flex;
@@ -179,6 +179,45 @@
179
179
  }
180
180
  }
181
181
 
182
+ .cf-response-choices-tag {
183
+ flex-direction: row;
184
+ flex-wrap: wrap;
185
+ gap: 8px;
186
+ }
187
+
188
+ .cf-tag-input {
189
+ display: none;
190
+
191
+ &[data-visible='true'] {
192
+ display: inline;
193
+ }
194
+ }
195
+
196
+ .cf-tag {
197
+ border-radius: 8px;
198
+ padding: 6px 12px;
199
+ font-weight: 500;
200
+ font-size: 0.875em;
201
+ transition:
202
+ background 200ms ease-out,
203
+ border-color 200ms ease-out;
204
+
205
+ &[data-selected='true'] {
206
+ background: var(--confetti-indicator-active-bg-color);
207
+ border-color: var(--confetti-indicator-active-bg-color);
208
+ color: var(--confetti-indicator-active-dot-color);
209
+ }
210
+
211
+ &[data-focus-visible='true'] {
212
+ outline: 2px solid var(--confetti-outline-color);
213
+ outline-offset: 2px;
214
+ }
215
+
216
+ &:active {
217
+ scale: 0.96;
218
+ }
219
+ }
220
+
182
221
  .cf-radio,
183
222
  .cf-checkbox {
184
223
  cursor: pointer;
@@ -255,6 +294,7 @@
255
294
  position: relative;
256
295
  width: 18px;
257
296
  height: 18px;
297
+ flex-shrink: 0;
258
298
  box-sizing: border-box;
259
299
  border-radius: 50%;
260
300
  transition: color 200ms ease-out;
@@ -335,6 +375,11 @@
335
375
  font-weight: 500;
336
376
  }
337
377
 
378
+ .cf-label-optional {
379
+ font-weight: 400;
380
+ color: var(--confetti-text-subtle-color);
381
+ }
382
+
338
383
  .cf-description {
339
384
  font-size: 0.875em;
340
385
  line-height: 20px;
package/build/index.d.ts CHANGED
@@ -1,169 +1,8 @@
1
+ import { a as MultiSelectQuestionProperties, c as StatementQuestionProperties, i as PublicGetSurveyOutput, l as TextQuestionProperties, n as ConfettiState, o as RatingQuestionProperties, r as Question, s as SingleSelectQuestionProperties, t as Answer } from "./types-qVyTr8wu.js";
1
2
  import * as react0 from "react";
2
3
  import { HTMLAttributes, PropsWithChildren } from "react";
3
- import { z } from "zod/v4/mini";
4
4
  import * as react_jsx_runtime3 from "react/jsx-runtime";
5
5
 
6
- //#region ../validators/src/questions/properties.d.ts
7
-
8
- declare const ratingQuestionSchema: z.ZodMiniObject<{
9
- type: z.ZodMiniLiteral<"rating">;
10
- scale: z.ZodMiniNumber<number>;
11
- labels: z.ZodMiniOptional<z.ZodMiniObject<{
12
- lower: z.ZodMiniOptional<z.ZodMiniPipe<z.ZodMiniString<string>, z.ZodMiniTransform<string | undefined, string>>>;
13
- upper: z.ZodMiniOptional<z.ZodMiniPipe<z.ZodMiniString<string>, z.ZodMiniTransform<string | undefined, string>>>;
14
- }, z.core.$strip>>;
15
- display: z.ZodMiniOptional<z.ZodMiniLiteral<"number" | "star" | "emoji" | "tiffany">>;
16
- }, z.core.$strip>;
17
- type RatingQuestion = z.infer<typeof ratingQuestionSchema>;
18
- declare const textQuestionSchema: z.ZodMiniObject<{
19
- type: z.ZodMiniLiteral<"open-ended">;
20
- max: z.ZodMiniNumber<number>;
21
- }, z.core.$strip>;
22
- type TextQuestion = z.infer<typeof textQuestionSchema>;
23
- declare const singleSelectQuestionSchema: z.ZodMiniObject<{
24
- type: z.ZodMiniLiteral<"single-select">;
25
- options: z.ZodMiniArray<z.ZodMiniObject<{
26
- value: z.ZodMiniString<string>;
27
- description: z.ZodMiniOptional<z.ZodMiniString<string>>;
28
- }, z.core.$strip>>;
29
- editable: z.ZodMiniNullable<z.ZodMiniObject<{
30
- label: z.ZodMiniString<string>;
31
- max: z.ZodMiniNumber<number>;
32
- description: z.ZodMiniOptional<z.ZodMiniString<string>>;
33
- }, z.core.$strip>>;
34
- }, z.core.$strip>;
35
- type SingleSelectQuestion = z.infer<typeof singleSelectQuestionSchema>;
36
- declare const multiSelectQuestionSchema: z.ZodMiniObject<{
37
- type: z.ZodMiniLiteral<"multi-select">;
38
- options: z.ZodMiniArray<z.ZodMiniObject<{
39
- value: z.ZodMiniString<string>;
40
- description: z.ZodMiniOptional<z.ZodMiniString<string>>;
41
- }, z.core.$strip>>;
42
- editable: z.ZodMiniNullable<z.ZodMiniObject<{
43
- label: z.ZodMiniString<string>;
44
- max: z.ZodMiniNumber<number>;
45
- description: z.ZodMiniOptional<z.ZodMiniString<string>>;
46
- }, z.core.$strip>>;
47
- max: z.ZodMiniOptional<z.ZodMiniNumber<number>>;
48
- }, z.core.$strip>;
49
- type MultiSelectQuestion = z.infer<typeof multiSelectQuestionSchema>;
50
- //#endregion
51
- //#region ../validators/src/survey.d.ts
52
- declare const publicGetSurveyOutputSchema: z.ZodMiniObject<{
53
- title: z.ZodMiniString<string>;
54
- description: z.ZodMiniNullable<z.ZodMiniString<string>>;
55
- questions: z.ZodMiniArray<z.ZodMiniObject<{
56
- id: z.ZodMiniString<string>;
57
- title: z.ZodMiniString<string>;
58
- description: z.ZodMiniNullable<z.ZodMiniString<string>>;
59
- position: z.ZodMiniNumber<number>;
60
- required: z.ZodMiniBoolean<boolean>;
61
- properties: z.ZodMiniDiscriminatedUnion<[z.ZodMiniObject<{
62
- type: z.ZodMiniLiteral<"rating">;
63
- scale: z.ZodMiniNumber<number>;
64
- labels: z.ZodMiniOptional<z.ZodMiniObject<{
65
- lower: z.ZodMiniOptional<z.ZodMiniPipe<z.ZodMiniString<string>, z.ZodMiniTransform<string | undefined, string>>>;
66
- upper: z.ZodMiniOptional<z.ZodMiniPipe<z.ZodMiniString<string>, z.ZodMiniTransform<string | undefined, string>>>;
67
- }, z.core.$strip>>;
68
- display: z.ZodMiniOptional<z.ZodMiniLiteral<"number" | "star" | "emoji" | "tiffany">>;
69
- }, z.core.$strip>, z.ZodMiniObject<{
70
- type: z.ZodMiniLiteral<"single-select">;
71
- options: z.ZodMiniArray<z.ZodMiniObject<{
72
- value: z.ZodMiniString<string>;
73
- description: z.ZodMiniOptional<z.ZodMiniString<string>>;
74
- }, z.core.$strip>>;
75
- editable: z.ZodMiniNullable<z.ZodMiniObject<{
76
- label: z.ZodMiniString<string>;
77
- max: z.ZodMiniNumber<number>;
78
- description: z.ZodMiniOptional<z.ZodMiniString<string>>;
79
- }, z.core.$strip>>;
80
- }, z.core.$strip>, z.ZodMiniObject<{
81
- type: z.ZodMiniLiteral<"open-ended">;
82
- max: z.ZodMiniNumber<number>;
83
- }, z.core.$strip>, z.ZodMiniObject<{
84
- type: z.ZodMiniLiteral<"multi-select">;
85
- options: z.ZodMiniArray<z.ZodMiniObject<{
86
- value: z.ZodMiniString<string>;
87
- description: z.ZodMiniOptional<z.ZodMiniString<string>>;
88
- }, z.core.$strip>>;
89
- editable: z.ZodMiniNullable<z.ZodMiniObject<{
90
- label: z.ZodMiniString<string>;
91
- max: z.ZodMiniNumber<number>;
92
- description: z.ZodMiniOptional<z.ZodMiniString<string>>;
93
- }, z.core.$strip>>;
94
- max: z.ZodMiniOptional<z.ZodMiniNumber<number>>;
95
- }, z.core.$strip>], "type">;
96
- routingLogic: z.ZodMiniDiscriminatedUnion<[z.ZodMiniObject<{
97
- type: z.ZodMiniLiteral<"always">;
98
- target: z.ZodMiniDiscriminatedUnion<[z.ZodMiniObject<{
99
- type: z.ZodMiniLiteral<"next">;
100
- }, z.core.$strip>, z.ZodMiniObject<{
101
- type: z.ZodMiniLiteral<"jump">;
102
- target: z.ZodMiniNumber<number>;
103
- }, z.core.$strip>, z.ZodMiniObject<{
104
- type: z.ZodMiniLiteral<"end">;
105
- }, z.core.$strip>], "type">;
106
- }, z.core.$strip>, z.ZodMiniObject<{
107
- type: z.ZodMiniLiteral<"switch">;
108
- cases: z.ZodMiniArray<z.ZodMiniObject<{
109
- type: z.ZodMiniLiteral<"binary-operator">;
110
- operator: z.ZodMiniUnion<readonly [z.ZodMiniLiteral<"equal">, z.ZodMiniLiteral<"not-equal">, z.ZodMiniLiteral<"greater">, z.ZodMiniLiteral<"greater-or-equal">, z.ZodMiniLiteral<"less">, z.ZodMiniLiteral<"less-or-equal">, z.ZodMiniLiteral<"contains">, z.ZodMiniLiteral<"not-contains">]>;
111
- value: z.ZodMiniObject<{
112
- type: z.ZodMiniLiteral<"value">;
113
- value: z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniNumber<number>]>;
114
- }, z.core.$strip>;
115
- target: z.ZodMiniDiscriminatedUnion<[z.ZodMiniObject<{
116
- type: z.ZodMiniLiteral<"next">;
117
- }, z.core.$strip>, z.ZodMiniObject<{
118
- type: z.ZodMiniLiteral<"jump">;
119
- target: z.ZodMiniNumber<number>;
120
- }, z.core.$strip>, z.ZodMiniObject<{
121
- type: z.ZodMiniLiteral<"end">;
122
- }, z.core.$strip>], "type">;
123
- }, z.core.$strip>>;
124
- default: z.ZodMiniDiscriminatedUnion<[z.ZodMiniObject<{
125
- type: z.ZodMiniLiteral<"next">;
126
- }, z.core.$strip>, z.ZodMiniObject<{
127
- type: z.ZodMiniLiteral<"jump">;
128
- target: z.ZodMiniNumber<number>;
129
- }, z.core.$strip>, z.ZodMiniObject<{
130
- type: z.ZodMiniLiteral<"end">;
131
- }, z.core.$strip>], "type">;
132
- }, z.core.$strip>], "type">;
133
- }, z.core.$strip>>;
134
- confirmation: z.ZodMiniObject<{
135
- title: z.ZodMiniString<string>;
136
- description: z.ZodMiniString<string>;
137
- buttonText: z.ZodMiniString<string>;
138
- }, z.core.$strip>;
139
- }, z.core.$strip>;
140
- type PublicGetSurveyOutput = z.infer<typeof publicGetSurveyOutputSchema>;
141
- //#endregion
142
- //#region src/core/types.d.ts
143
- type Question = {
144
- visible: boolean;
145
- error?: string;
146
- } & PublicGetSurveyOutput['questions'][number];
147
- type Answer = string | number | string[] | undefined;
148
- interface ConfettiState {
149
- questions: Question[];
150
- current: number;
151
- update: ({
152
- question,
153
- answer
154
- }: {
155
- question: number;
156
- answer: Answer;
157
- }) => {
158
- next?: number;
159
- error?: string;
160
- };
161
- submit: () => void;
162
- isCompleted: boolean;
163
- isSubmitted: boolean;
164
- errors: Record<Question['id'], string>;
165
- }
166
- //#endregion
167
6
  //#region src/core/ConfettiController.d.ts
168
7
  interface ConfettiControllerProps {
169
8
  children: (props: ConfettiState) => React.ReactElement;
@@ -290,12 +129,13 @@ declare const SurveyQuestionFactory: ({
290
129
  //#endregion
291
130
  //#region src/components/questions/Rating.d.ts
292
131
  interface RatingProps extends BaseFieldProps {
293
- properties: RatingQuestion;
132
+ properties: RatingQuestionProperties;
294
133
  classNames?: {
295
134
  question?: string;
296
135
  header?: string;
297
136
  title?: string;
298
137
  description?: string;
138
+ optionalLabel?: string;
299
139
  ratingSection?: string;
300
140
  ratingDisplay?: string;
301
141
  ratingText?: string;
@@ -324,11 +164,12 @@ declare const Rating: ({
324
164
  //#endregion
325
165
  //#region src/components/questions/FreeText.d.ts
326
166
  interface FreeTextProps extends BaseFieldProps {
327
- properties: TextQuestion;
167
+ properties: TextQuestionProperties;
328
168
  classNames?: {
329
169
  question?: string;
330
170
  header?: string;
331
171
  title?: string;
172
+ optionalLabel?: string;
332
173
  description?: string;
333
174
  textarea?: string;
334
175
  error?: string;
@@ -347,13 +188,14 @@ declare const FreeText: ({
347
188
  //#endregion
348
189
  //#region src/components/questions/SingleChoice.d.ts
349
190
  interface SingleChoiceProps extends BaseFieldProps {
350
- properties: SingleSelectQuestion;
191
+ properties: SingleSelectQuestionProperties;
351
192
  classNames?: {
352
193
  question?: string;
353
194
  header?: string;
354
195
  label?: string;
355
196
  title?: string;
356
197
  description?: string;
198
+ optionalLabel?: string;
357
199
  group?: string;
358
200
  radio?: string;
359
201
  indicator?: string;
@@ -376,16 +218,19 @@ declare const SingleChoice: ({
376
218
  //#endregion
377
219
  //#region src/components/questions/MultiChoice.d.ts
378
220
  interface MultiChoiceProps extends BaseFieldProps {
379
- properties: MultiSelectQuestion;
221
+ properties: MultiSelectQuestionProperties;
380
222
  classNames?: {
381
223
  question?: string;
382
224
  header?: string;
383
225
  label?: string;
384
226
  title?: string;
385
227
  description?: string;
228
+ optionalLabel?: string;
386
229
  choiceDescription?: string;
387
230
  group?: string;
388
231
  checkbox?: string;
232
+ tag?: string;
233
+ tagLabel?: string;
389
234
  indicator?: string;
390
235
  svg?: string;
391
236
  othersChoice?: string;
@@ -404,6 +249,24 @@ declare const MultiChoice: ({
404
249
  error
405
250
  }: MultiChoiceProps) => react_jsx_runtime3.JSX.Element;
406
251
  //#endregion
252
+ //#region src/components/questions/Statement.d.ts
253
+ interface StatementProps extends BaseFieldProps {
254
+ properties: StatementQuestionProperties;
255
+ classNames?: {
256
+ question?: string;
257
+ header?: string;
258
+ title?: string;
259
+ description?: string;
260
+ ctaButton?: string;
261
+ };
262
+ }
263
+ declare const Statement: ({
264
+ properties: _properties,
265
+ title,
266
+ description,
267
+ classNames
268
+ }: StatementProps) => react_jsx_runtime3.JSX.Element;
269
+ //#endregion
407
270
  //#region src/components/presentation/Flow.d.ts
408
271
  type ChildField = (_: {
409
272
  onChange: (answer: Answer) => void;
@@ -494,5 +357,5 @@ declare const useVisibleAfterScroll: ({
494
357
  isVisible: boolean;
495
358
  };
496
359
  //#endregion
497
- export { type Answer, Confetti, ConfettiContext, ConfettiController, type ConfettiControllerProps, type ConfettiProps, ConfettiProvider, type ConfettiProviderProps, type ConfettiState, Embed, EmbeddedConfetti, Flow, FreeText, type FreeTextProps, MultiChoice, type MultiChoiceProps, PopoverConfetti, PopoverContainer, type PopoverContainerProps, type Question, Rating, type RatingProps, SingleChoice, type SingleChoiceProps, StepperConfetti, SurveyQuestionFactory, type SurveyQuestionFactoryProps, ThankYouMessage, useConfetti, useVisibleAfterDelay, useVisibleAfterPageVisits, useVisibleAfterScroll, useVisibleAfterSessionPageVisits };
360
+ export { type Answer, Confetti, ConfettiContext, ConfettiController, type ConfettiControllerProps, type ConfettiProps, ConfettiProvider, type ConfettiProviderProps, type ConfettiState, Embed, EmbeddedConfetti, Flow, FreeText, type FreeTextProps, MultiChoice, type MultiChoiceProps, PopoverConfetti, PopoverContainer, type PopoverContainerProps, type Question, Rating, type RatingProps, SingleChoice, type SingleChoiceProps, Statement, type StatementProps, StepperConfetti, SurveyQuestionFactory, type SurveyQuestionFactoryProps, ThankYouMessage, useConfetti, useVisibleAfterDelay, useVisibleAfterPageVisits, useVisibleAfterScroll, useVisibleAfterSessionPageVisits };
498
361
  //# sourceMappingURL=index.d.ts.map
package/build/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { n as isVisible, t as evaluateCondition } from "./routing-DjtQKwsR.js";
1
2
  import { ErrorBoundary } from "react-error-boundary";
2
3
  import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
3
4
  import { useLocalStorage, useSessionStorage, useTimeout } from "usehooks-ts";
@@ -55,8 +56,16 @@ const alwaysConditionSchema = z.object({
55
56
  });
56
57
  const routingLogicSchema = z.discriminatedUnion("type", [alwaysConditionSchema, switchConditionSchema]);
57
58
 
59
+ //#endregion
60
+ //#region ../validators/src/url.ts
61
+ const urlSchema = z.string().check(z.trim(), z.url({
62
+ protocol: /^(https|mailto)/,
63
+ error: "Link must start with https:// or mailto:"
64
+ }));
65
+
58
66
  //#endregion
59
67
  //#region ../validators/src/questions/properties.ts
68
+ const buttonLabelSchema = z.optional(z.string().check(z.trim(), z.maxLength(50)));
60
69
  const optionSchema = z.object({
61
70
  value: z.string().check(z.trim(), z.minLength(1, { error: "Value is required" })),
62
71
  description: z.optional(z.string().check(z.trim()))
@@ -66,8 +75,9 @@ const editableSchema = z.nullable(z.object({
66
75
  max: z.number(),
67
76
  description: z.optional(z.string().check(z.trim()))
68
77
  }));
69
- const ratingQuestionSchema = z.object({
78
+ const ratingQuestionPropertiesSchema = z.object({
70
79
  type: z.literal("rating"),
80
+ buttonLabel: buttonLabelSchema,
71
81
  scale: z.number().check(z.minimum(2), z.maximum(10)),
72
82
  labels: z.optional(z.object({
73
83
  lower: z.optional(z.pipe(z.string().check(z.trim()), z.transform((val) => val === "" ? void 0 : val))),
@@ -80,26 +90,36 @@ const ratingQuestionSchema = z.object({
80
90
  "tiffany"
81
91
  ]))
82
92
  });
83
- const textQuestionSchema = z.object({
93
+ const textQuestionPropertiesSchema = z.object({
84
94
  type: z.literal("open-ended"),
95
+ buttonLabel: buttonLabelSchema,
85
96
  max: z.number()
86
97
  });
87
- const singleSelectQuestionSchema = z.object({
98
+ const singleSelectQuestionPropertiesSchema = z.object({
88
99
  type: z.literal("single-select"),
89
100
  options: z.array(optionSchema),
101
+ buttonLabel: buttonLabelSchema,
90
102
  editable: editableSchema
91
103
  });
92
- const multiSelectQuestionSchema = z.object({
104
+ const multiSelectQuestionPropertiesSchema = z.object({
93
105
  type: z.literal("multi-select"),
106
+ buttonLabel: buttonLabelSchema,
94
107
  options: z.array(optionSchema),
95
108
  editable: editableSchema,
96
- max: z.optional(z.number())
109
+ max: z.optional(z.number()),
110
+ display: z.optional(z.literal(["checkbox", "tag"]))
111
+ });
112
+ const statementQuestionPropertiesSchema = z.object({
113
+ type: z.literal("statement"),
114
+ buttonLabel: buttonLabelSchema,
115
+ buttonUrl: z.optional(urlSchema)
97
116
  });
98
117
  const questionPropertiesSchema = z.discriminatedUnion("type", [
99
- ratingQuestionSchema,
100
- singleSelectQuestionSchema,
101
- textQuestionSchema,
102
- multiSelectQuestionSchema
118
+ ratingQuestionPropertiesSchema,
119
+ singleSelectQuestionPropertiesSchema,
120
+ textQuestionPropertiesSchema,
121
+ multiSelectQuestionPropertiesSchema,
122
+ statementQuestionPropertiesSchema
103
123
  ]);
104
124
 
105
125
  //#endregion
@@ -121,6 +141,7 @@ const singleSelectAnswerSchemaFactory = ({ maxLength }, { required }) => {
121
141
  return required ? baseSchema : z.optional(baseSchema);
122
142
  };
123
143
  const multiSelectAnswerSchemaFactory = ({ maxSelected, maxLength }, { required }) => z.array(z.string().check(z.trim(), ...required ? [z.minLength(1, { error: "This field is required" })] : [], z.maxLength(maxLength ?? 1024, { error: ({ maximum }) => `Please enter less than ${maximum} characters` }), z.refine((val) => val !== CHECKBOX_OTHERS_VALUE, { error: "Please fill out the free text field" }))).check(...required ? [z.minLength(1, { error: "Please select at least one option" })] : [], z.maxLength(maxSelected ?? 1024, { error: ({ maximum }) => `Please select less than ${maximum} options` }));
144
+ const statementAnswerSchemaFactory = () => z.optional(z.string());
124
145
 
125
146
  //#endregion
126
147
  //#region ../validators/src/survey.ts
@@ -248,63 +269,6 @@ const useConfetti = () => {
248
269
  return context;
249
270
  };
250
271
 
251
- //#endregion
252
- //#region src/core/logic/route.ts
253
- const isVisible = ({ index, questions, answers }) => {
254
- if (index === 0) return true;
255
- for (let i = 0; i < index; i++) {
256
- const question = questions[i];
257
- const answer = question ? answers[question.id] : void 0;
258
- if (!question || !question.visible) continue;
259
- const logic = question.routingLogic;
260
- if (logic.type === "always") if (evaluateTarget({
261
- position: i,
262
- value: logic.target
263
- }) === index) return true;
264
- else continue;
265
- if ((answer === void 0 || answer === null) && question.required) continue;
266
- const cases = logic.cases;
267
- const match = answer !== null ? cases.find((condition) => evaluateCondition({
268
- answer,
269
- condition
270
- })) : void 0;
271
- if (!match) if (evaluateTarget({
272
- position: i,
273
- value: logic.default
274
- }) === index) return true;
275
- else continue;
276
- if (evaluateTarget({
277
- position: i,
278
- value: match.target
279
- }) === index) return true;
280
- else continue;
281
- }
282
- return false;
283
- };
284
- const evaluateTarget = ({ position, value }) => {
285
- switch (value.type) {
286
- case "next": return position + 1;
287
- case "jump": return value.target;
288
- case "end": return null;
289
- }
290
- };
291
- const evaluateCondition = ({ answer, condition }) => {
292
- const value = evaluateValue(condition.value);
293
- switch (condition.operator) {
294
- case "equal": return answer === value;
295
- case "not-equal": return answer !== value;
296
- case "greater": return typeof answer === "number" && typeof value === "number" && answer > value;
297
- case "greater-or-equal": return typeof answer === "number" && typeof value === "number" && answer >= value;
298
- case "less": return typeof answer === "number" && typeof value === "number" && answer < value;
299
- case "less-or-equal": return typeof answer === "number" && typeof value === "number" && answer <= value;
300
- case "contains": return Array.isArray(answer) && typeof value === "string" && answer.includes(value);
301
- case "not-contains": return Array.isArray(answer) && typeof value === "string" && !answer.includes(value);
302
- }
303
- };
304
- const evaluateValue = (node) => {
305
- return node.value;
306
- };
307
-
308
272
  //#endregion
309
273
  //#region src/core/logic/validate.ts
310
274
  const VALIDATOR_FACTORY_MAP = {
@@ -314,7 +278,8 @@ const VALIDATOR_FACTORY_MAP = {
314
278
  "multi-select": ({ editable, max }, meta) => multiSelectAnswerSchemaFactory({
315
279
  maxLength: editable?.max,
316
280
  maxSelected: max
317
- }, meta)
281
+ }, meta),
282
+ statement: (_properties, _meta) => statementAnswerSchemaFactory()
318
283
  };
319
284
  const getAnswerValidator = (properties, meta) => {
320
285
  const type = properties.type;
@@ -335,6 +300,10 @@ const getAnswerValidator = (properties, meta) => {
335
300
  const validator = VALIDATOR_FACTORY_MAP[type];
336
301
  return validator(properties, meta);
337
302
  }
303
+ case "statement": {
304
+ const validator = VALIDATOR_FACTORY_MAP[type];
305
+ return validator(properties, meta);
306
+ }
338
307
  default: throw new Error("Unsupported question type");
339
308
  }
340
309
  };
@@ -570,9 +539,12 @@ const FreeText = ({ id, title, description, properties, onChange, classNames, re
570
539
  children: [
571
540
  /* @__PURE__ */ jsxs("div", {
572
541
  className: clsx("cf-header", classNames?.header),
573
- children: [/* @__PURE__ */ jsx(Label, {
542
+ children: [/* @__PURE__ */ jsxs(Label, {
574
543
  className: clsx("cf-title", classNames?.title),
575
- children: title
544
+ children: [title, !required && /* @__PURE__ */ jsxs("span", {
545
+ className: clsx("cf-label-optional", classNames?.optionalLabel),
546
+ children: [" ", "(optional)"]
547
+ })]
576
548
  }), description && /* @__PURE__ */ jsx(Text, {
577
549
  slot: "description",
578
550
  className: clsx("cf-description", classNames?.description),
@@ -620,8 +592,18 @@ const MultiChoiceCheckbox = ({ children, classNames, description, ...props }) =>
620
592
  })] })
621
593
  });
622
594
  };
595
+ const MultiChoiceTag = ({ children, classNames, ...props }) => {
596
+ return /* @__PURE__ */ jsx(Checkbox, {
597
+ ...props,
598
+ children: /* @__PURE__ */ jsx("div", {
599
+ className: clsx("cf-tag-label", classNames?.tagLabel),
600
+ children
601
+ })
602
+ });
603
+ };
623
604
  const MultiChoice = ({ title, description, properties, classNames, onChange, id, required, error }) => {
624
605
  const hasEditable = !!properties.editable;
606
+ const display = properties.display ?? "checkbox";
625
607
  const [value, setValue] = useState([]);
626
608
  const [othersValue, setOthersValue] = useState("");
627
609
  const othersRef = useRef(null);
@@ -633,6 +615,7 @@ const MultiChoice = ({ title, description, properties, classNames, onChange, id,
633
615
  submissionValue$1[othersValueIndex] = othersValue || CHECKBOX_OTHERS_VALUE;
634
616
  return submissionValue$1;
635
617
  }, [othersValue, value]);
618
+ const isTag = display === "tag";
636
619
  useEffect(() => {
637
620
  onChange(submissionValue);
638
621
  }, [onChange, submissionValue]);
@@ -646,9 +629,12 @@ const MultiChoice = ({ title, description, properties, classNames, onChange, id,
646
629
  children: ({ state }) => /* @__PURE__ */ jsxs(Fragment, { children: [
647
630
  /* @__PURE__ */ jsxs("div", {
648
631
  className: clsx("cf-header", classNames?.header),
649
- children: [/* @__PURE__ */ jsx(Label, {
632
+ children: [/* @__PURE__ */ jsxs(Label, {
650
633
  className: clsx("cf-title", classNames?.title),
651
- children: title
634
+ children: [title, !required && /* @__PURE__ */ jsxs("span", {
635
+ className: clsx("cf-label-optional", classNames?.optionalLabel),
636
+ children: [" ", "(optional)"]
637
+ })]
652
638
  }), description && /* @__PURE__ */ jsx(Text, {
653
639
  slot: "description",
654
640
  className: clsx("cf-description", classNames?.description),
@@ -656,17 +642,43 @@ const MultiChoice = ({ title, description, properties, classNames, onChange, id,
656
642
  })]
657
643
  }),
658
644
  /* @__PURE__ */ jsxs("div", {
659
- className: clsx("cf-response-choices", classNames?.group),
660
- children: [properties.options.map((option, index) => /* @__PURE__ */ jsx(MultiChoiceCheckbox, {
661
- className: clsx("cf-choice cf-checkbox", classNames?.checkbox),
662
- value: option.value,
663
- classNames: {
664
- indicator: classNames?.indicator,
665
- svg: classNames?.svg
645
+ className: clsx("cf-response-choices", display === "tag" && "cf-response-choices-tag", classNames?.group),
646
+ children: [properties.options.map((option, index) => {
647
+ return /* @__PURE__ */ jsx(isTag ? MultiChoiceTag : MultiChoiceCheckbox, {
648
+ className: clsx("cf-choice", isTag && ["cf-tag", classNames?.tag], !isTag && ["cf-checkbox", classNames?.checkbox]),
649
+ value: option.value,
650
+ classNames: {
651
+ tag: classNames?.tag,
652
+ tagLabel: classNames?.tagLabel,
653
+ choiceDescription: classNames?.choiceDescription,
654
+ label: classNames?.label,
655
+ indicator: classNames?.indicator,
656
+ svg: classNames?.svg
657
+ },
658
+ children: option.value
659
+ }, index);
660
+ }), hasEditable && (isTag ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(MultiChoiceTag, {
661
+ inputRef: othersRef,
662
+ onChange: (isSelected) => {
663
+ console.log("hehe", isSelected);
664
+ if (!othersInputRef.current) return;
665
+ if (isSelected) requestAnimationFrame(() => {
666
+ if (!othersInputRef.current) return;
667
+ othersInputRef.current.focus();
668
+ });
666
669
  },
667
- description: option.description,
668
- children: option.value
669
- }, index)), hasEditable && /* @__PURE__ */ jsxs("div", {
670
+ className: clsx("cf-choice cf-tag", classNames?.tag),
671
+ value: CHECKBOX_OTHERS_VALUE,
672
+ children: properties.editable?.label
673
+ }), /* @__PURE__ */ jsx(Input, {
674
+ "data-visible": state.value.includes(CHECKBOX_OTHERS_VALUE) || void 0,
675
+ value: othersValue,
676
+ onChange: (e) => {
677
+ setOthersValue(e.target.value);
678
+ },
679
+ ref: othersInputRef,
680
+ className: clsx("cf-input cf-tag-input", classNames?.othersInput)
681
+ })] }) : /* @__PURE__ */ jsxs("div", {
670
682
  className: clsx("cf-choice cf-others-choice", classNames?.othersChoice),
671
683
  children: [/* @__PURE__ */ jsx(MultiChoiceCheckbox, {
672
684
  inputRef: othersRef,
@@ -697,7 +709,7 @@ const MultiChoice = ({ title, description, properties, classNames, onChange, id,
697
709
  },
698
710
  className: clsx("cf-input", classNames?.othersInput)
699
711
  })]
700
- })]
712
+ }))]
701
713
  }),
702
714
  /* @__PURE__ */ jsx(FieldError, {
703
715
  className: clsx("cf-error", classNames?.error),
@@ -1045,9 +1057,12 @@ const Rating = ({ properties, title, description, classNames, onChange, id, erro
1045
1057
  children: ({ state }) => /* @__PURE__ */ jsxs(Fragment, { children: [
1046
1058
  /* @__PURE__ */ jsxs("div", {
1047
1059
  className: clsx("cf-header", classNames?.header),
1048
- children: [/* @__PURE__ */ jsx(Label, {
1060
+ children: [/* @__PURE__ */ jsxs(Label, {
1049
1061
  className: clsx("cf-title", classNames?.title),
1050
- children: title
1062
+ children: [title, !required && /* @__PURE__ */ jsxs("span", {
1063
+ className: clsx("cf-label-optional", classNames?.optionalLabel),
1064
+ children: [" ", "(optional)"]
1065
+ })]
1051
1066
  }), description && /* @__PURE__ */ jsx(Text, {
1052
1067
  slot: "description",
1053
1068
  className: clsx("cf-description", classNames?.description),
@@ -1123,9 +1138,12 @@ const SingleChoice = ({ title, description, properties, classNames, onChange, id
1123
1138
  children: ({ state }) => /* @__PURE__ */ jsxs(Fragment, { children: [
1124
1139
  /* @__PURE__ */ jsxs("div", {
1125
1140
  className: clsx("cf-header", classNames?.header),
1126
- children: [/* @__PURE__ */ jsx(Label, {
1141
+ children: [/* @__PURE__ */ jsxs(Label, {
1127
1142
  className: clsx("cf-title", classNames?.title),
1128
- children: title
1143
+ children: [title, !required && /* @__PURE__ */ jsxs("span", {
1144
+ className: clsx("cf-label-optional", classNames?.optionalLabel),
1145
+ children: [" ", "(optional)"]
1146
+ })]
1129
1147
  }), description && /* @__PURE__ */ jsx(Text, {
1130
1148
  slot: "description",
1131
1149
  className: clsx("cf-description", classNames?.description),
@@ -1173,6 +1191,24 @@ const SingleChoice = ({ title, description, properties, classNames, onChange, id
1173
1191
  });
1174
1192
  };
1175
1193
 
1194
+ //#endregion
1195
+ //#region src/components/questions/Statement.tsx
1196
+ const Statement = ({ properties: _properties, title, description, classNames }) => {
1197
+ return /* @__PURE__ */ jsx("div", {
1198
+ className: clsx("cf-question", classNames?.question),
1199
+ children: /* @__PURE__ */ jsxs("div", {
1200
+ className: clsx("cf-header", classNames?.header),
1201
+ children: [title && /* @__PURE__ */ jsx("div", {
1202
+ className: clsx("cf-title", classNames?.title),
1203
+ children: title
1204
+ }), description && /* @__PURE__ */ jsx("div", {
1205
+ className: clsx("cf-description", classNames?.description),
1206
+ children: description
1207
+ })]
1208
+ })
1209
+ });
1210
+ };
1211
+
1176
1212
  //#endregion
1177
1213
  //#region src/components/questions/factory.tsx
1178
1214
  const SurveyQuestionFactory = ({ question, onChange, error }) => {
@@ -1201,6 +1237,12 @@ const SurveyQuestionFactory = ({ question, onChange, error }) => {
1201
1237
  onChange,
1202
1238
  error
1203
1239
  }, question.id);
1240
+ case "statement": return /* @__PURE__ */ jsx(Statement, {
1241
+ ...question,
1242
+ properties: question.properties,
1243
+ onChange,
1244
+ error
1245
+ }, question.id);
1204
1246
  }
1205
1247
  return /* @__PURE__ */ jsx("div", { children: "Unsupported question type" }, question.id);
1206
1248
  };
@@ -1221,6 +1263,7 @@ const SubmitButton = ({ onPress, isDisabled, children = "Submit" }) => {
1221
1263
  const getInitialState = (type) => {
1222
1264
  switch (type) {
1223
1265
  case "multi-select": return [];
1266
+ case "statement": return;
1224
1267
  default: return "";
1225
1268
  }
1226
1269
  };
@@ -1248,14 +1291,33 @@ const Flow = ({ onSubmit, children, question, isLastQuestion }) => {
1248
1291
  question.required,
1249
1292
  question.routingLogic
1250
1293
  ]);
1294
+ const buttonLabel = useMemo(() => {
1295
+ if (question.properties.buttonLabel) return question.properties.buttonLabel;
1296
+ return hasNextQuestion ? "Next" : "Submit";
1297
+ }, [hasNextQuestion, question.properties.buttonLabel]);
1298
+ const handleSubmitPressed = useCallback(() => {
1299
+ switch (question.properties.type) {
1300
+ case "statement":
1301
+ if (question.properties.buttonUrl && typeof window !== "undefined") {
1302
+ const validatedUrl = urlSchema.safeParse(question.properties.buttonUrl).data;
1303
+ if (validatedUrl) window.open(validatedUrl, "_blank");
1304
+ }
1305
+ return onSubmit(void 0);
1306
+ default: return onSubmit(answer);
1307
+ }
1308
+ }, [
1309
+ answer,
1310
+ onSubmit,
1311
+ question.properties
1312
+ ]);
1251
1313
  return /* @__PURE__ */ jsxs(Fragment, { children: [children({
1252
1314
  onChange: setAnswer,
1253
1315
  question,
1254
1316
  error
1255
1317
  }), /* @__PURE__ */ jsx(SubmitButton, {
1256
1318
  isDisabled: !!error,
1257
- onPress: () => onSubmit(answer),
1258
- children: hasNextQuestion ? "Next" : "Submit"
1319
+ onPress: handleSubmitPressed,
1320
+ children: buttonLabel
1259
1321
  })] });
1260
1322
  };
1261
1323
 
@@ -1407,5 +1469,5 @@ const useVisibleAfterScroll = ({ threshold }) => {
1407
1469
  };
1408
1470
 
1409
1471
  //#endregion
1410
- export { Confetti, ConfettiContext, ConfettiController, ConfettiProvider, Embed, EmbeddedConfetti, Flow, FreeText, MultiChoice, PopoverConfetti, PopoverContainer, Rating, SingleChoice, StepperConfetti, SurveyQuestionFactory, ThankYouMessage, useConfetti, useVisibleAfterDelay, useVisibleAfterPageVisits, useVisibleAfterScroll, useVisibleAfterSessionPageVisits };
1472
+ export { Confetti, ConfettiContext, ConfettiController, ConfettiProvider, Embed, EmbeddedConfetti, Flow, FreeText, MultiChoice, PopoverConfetti, PopoverContainer, Rating, SingleChoice, Statement, StepperConfetti, SurveyQuestionFactory, ThankYouMessage, useConfetti, useVisibleAfterDelay, useVisibleAfterPageVisits, useVisibleAfterScroll, useVisibleAfterSessionPageVisits };
1411
1473
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,14 @@
1
+ import { t as Answer, u as BinaryOperatorCondition } from "./types-qVyTr8wu.js";
2
+
3
+ //#region src/core/logic/routing.d.ts
4
+
5
+ declare const evaluateCondition: ({
6
+ answer,
7
+ condition
8
+ }: {
9
+ answer: Answer;
10
+ condition: BinaryOperatorCondition;
11
+ }) => boolean;
12
+ //#endregion
13
+ export { evaluateCondition as unstableInternalConfettiEvaluateCondition };
14
+ //# sourceMappingURL=internals.d.ts.map
@@ -0,0 +1,3 @@
1
+ import { t as evaluateCondition } from "./routing-DjtQKwsR.js";
2
+
3
+ export { evaluateCondition as unstableInternalConfettiEvaluateCondition };
@@ -0,0 +1,59 @@
1
+ //#region src/core/logic/routing.ts
2
+ const isVisible = ({ index, questions, answers }) => {
3
+ if (index === 0) return true;
4
+ for (let i = 0; i < index; i++) {
5
+ const question = questions[i];
6
+ const answer = question ? answers[question.id] : void 0;
7
+ if (!question || !question.visible) continue;
8
+ const logic = question.routingLogic;
9
+ if (logic.type === "always") if (evaluateTarget({
10
+ position: i,
11
+ value: logic.target
12
+ }) === index) return true;
13
+ else continue;
14
+ if ((answer === void 0 || answer === null) && question.required) continue;
15
+ const cases = logic.cases;
16
+ const match = answer !== null ? cases.find((condition) => evaluateCondition({
17
+ answer,
18
+ condition
19
+ })) : void 0;
20
+ if (!match) if (evaluateTarget({
21
+ position: i,
22
+ value: logic.default
23
+ }) === index) return true;
24
+ else continue;
25
+ if (evaluateTarget({
26
+ position: i,
27
+ value: match.target
28
+ }) === index) return true;
29
+ else continue;
30
+ }
31
+ return false;
32
+ };
33
+ const evaluateTarget = ({ position, value }) => {
34
+ switch (value.type) {
35
+ case "next": return position + 1;
36
+ case "jump": return value.target;
37
+ case "end": return null;
38
+ }
39
+ };
40
+ const evaluateCondition = ({ answer, condition }) => {
41
+ const value = evaluateValue(condition.value);
42
+ switch (condition.operator) {
43
+ case "equal": return answer === value;
44
+ case "not-equal": return answer !== value;
45
+ case "greater": return typeof answer === "number" && typeof value === "number" && answer > value;
46
+ case "greater-or-equal": return typeof answer === "number" && typeof value === "number" && answer >= value;
47
+ case "less": return typeof answer === "number" && typeof value === "number" && answer < value;
48
+ case "less-or-equal": return typeof answer === "number" && typeof value === "number" && answer <= value;
49
+ case "contains": return Array.isArray(answer) && typeof value === "string" && answer.includes(value);
50
+ case "not-contains": return Array.isArray(answer) && typeof value === "string" && !answer.includes(value);
51
+ }
52
+ };
53
+ const evaluateValue = (node) => {
54
+ return node.value;
55
+ };
56
+
57
+ //#endregion
58
+ export { isVisible as n, evaluateCondition as t };
59
+ //# sourceMappingURL=routing-DjtQKwsR.js.map
@@ -0,0 +1,204 @@
1
+ import { z } from "zod/v4/mini";
2
+
3
+ //#region ../validators/src/questions/routing.d.ts
4
+
5
+ declare const binaryOperatorConditionSchema: z.ZodMiniObject<{
6
+ type: z.ZodMiniLiteral<"binary-operator">;
7
+ operator: z.ZodMiniUnion<readonly [z.ZodMiniLiteral<"equal">, z.ZodMiniLiteral<"not-equal">, z.ZodMiniLiteral<"greater">, z.ZodMiniLiteral<"greater-or-equal">, z.ZodMiniLiteral<"less">, z.ZodMiniLiteral<"less-or-equal">, z.ZodMiniLiteral<"contains">, z.ZodMiniLiteral<"not-contains">]>;
8
+ value: z.ZodMiniObject<{
9
+ type: z.ZodMiniLiteral<"value">;
10
+ value: z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniNumber<number>]>;
11
+ }, z.core.$strip>;
12
+ target: z.ZodMiniDiscriminatedUnion<[z.ZodMiniObject<{
13
+ type: z.ZodMiniLiteral<"next">;
14
+ }, z.core.$strip>, z.ZodMiniObject<{
15
+ type: z.ZodMiniLiteral<"jump">;
16
+ target: z.ZodMiniNumber<number>;
17
+ }, z.core.$strip>, z.ZodMiniObject<{
18
+ type: z.ZodMiniLiteral<"end">;
19
+ }, z.core.$strip>], "type">;
20
+ }, z.core.$strip>;
21
+ type BinaryOperatorCondition = z.infer<typeof binaryOperatorConditionSchema>;
22
+ //#endregion
23
+ //#region ../validators/src/questions/properties.d.ts
24
+ declare const ratingQuestionPropertiesSchema: z.ZodMiniObject<{
25
+ type: z.ZodMiniLiteral<"rating">;
26
+ buttonLabel: z.ZodMiniOptional<z.ZodMiniString<string>>;
27
+ scale: z.ZodMiniNumber<number>;
28
+ labels: z.ZodMiniOptional<z.ZodMiniObject<{
29
+ lower: z.ZodMiniOptional<z.ZodMiniPipe<z.ZodMiniString<string>, z.ZodMiniTransform<string | undefined, string>>>;
30
+ upper: z.ZodMiniOptional<z.ZodMiniPipe<z.ZodMiniString<string>, z.ZodMiniTransform<string | undefined, string>>>;
31
+ }, z.core.$strip>>;
32
+ display: z.ZodMiniOptional<z.ZodMiniLiteral<"number" | "star" | "emoji" | "tiffany">>;
33
+ }, z.core.$strip>;
34
+ type RatingQuestionProperties = z.infer<typeof ratingQuestionPropertiesSchema>;
35
+ declare const textQuestionPropertiesSchema: z.ZodMiniObject<{
36
+ type: z.ZodMiniLiteral<"open-ended">;
37
+ buttonLabel: z.ZodMiniOptional<z.ZodMiniString<string>>;
38
+ max: z.ZodMiniNumber<number>;
39
+ }, z.core.$strip>;
40
+ type TextQuestionProperties = z.infer<typeof textQuestionPropertiesSchema>;
41
+ declare const singleSelectQuestionPropertiesSchema: z.ZodMiniObject<{
42
+ type: z.ZodMiniLiteral<"single-select">;
43
+ options: z.ZodMiniArray<z.ZodMiniObject<{
44
+ value: z.ZodMiniString<string>;
45
+ description: z.ZodMiniOptional<z.ZodMiniString<string>>;
46
+ }, z.core.$strip>>;
47
+ buttonLabel: z.ZodMiniOptional<z.ZodMiniString<string>>;
48
+ editable: z.ZodMiniNullable<z.ZodMiniObject<{
49
+ label: z.ZodMiniString<string>;
50
+ max: z.ZodMiniNumber<number>;
51
+ description: z.ZodMiniOptional<z.ZodMiniString<string>>;
52
+ }, z.core.$strip>>;
53
+ }, z.core.$strip>;
54
+ type SingleSelectQuestionProperties = z.infer<typeof singleSelectQuestionPropertiesSchema>;
55
+ declare const multiSelectQuestionPropertiesSchema: z.ZodMiniObject<{
56
+ type: z.ZodMiniLiteral<"multi-select">;
57
+ buttonLabel: z.ZodMiniOptional<z.ZodMiniString<string>>;
58
+ options: z.ZodMiniArray<z.ZodMiniObject<{
59
+ value: z.ZodMiniString<string>;
60
+ description: z.ZodMiniOptional<z.ZodMiniString<string>>;
61
+ }, z.core.$strip>>;
62
+ editable: z.ZodMiniNullable<z.ZodMiniObject<{
63
+ label: z.ZodMiniString<string>;
64
+ max: z.ZodMiniNumber<number>;
65
+ description: z.ZodMiniOptional<z.ZodMiniString<string>>;
66
+ }, z.core.$strip>>;
67
+ max: z.ZodMiniOptional<z.ZodMiniNumber<number>>;
68
+ display: z.ZodMiniOptional<z.ZodMiniLiteral<"checkbox" | "tag">>;
69
+ }, z.core.$strip>;
70
+ type MultiSelectQuestionProperties = z.infer<typeof multiSelectQuestionPropertiesSchema>;
71
+ declare const statementQuestionPropertiesSchema: z.ZodMiniObject<{
72
+ type: z.ZodMiniLiteral<"statement">;
73
+ buttonLabel: z.ZodMiniOptional<z.ZodMiniString<string>>;
74
+ buttonUrl: z.ZodMiniOptional<z.ZodMiniString<string>>;
75
+ }, z.core.$strip>;
76
+ type StatementQuestionProperties = z.infer<typeof statementQuestionPropertiesSchema>;
77
+ //#endregion
78
+ //#region ../validators/src/survey.d.ts
79
+ declare const publicGetSurveyOutputSchema: z.ZodMiniObject<{
80
+ title: z.ZodMiniString<string>;
81
+ description: z.ZodMiniNullable<z.ZodMiniString<string>>;
82
+ questions: z.ZodMiniArray<z.ZodMiniObject<{
83
+ id: z.ZodMiniString<string>;
84
+ title: z.ZodMiniString<string>;
85
+ description: z.ZodMiniNullable<z.ZodMiniString<string>>;
86
+ position: z.ZodMiniNumber<number>;
87
+ required: z.ZodMiniBoolean<boolean>;
88
+ properties: z.ZodMiniDiscriminatedUnion<[z.ZodMiniObject<{
89
+ type: z.ZodMiniLiteral<"rating">;
90
+ buttonLabel: z.ZodMiniOptional<z.ZodMiniString<string>>;
91
+ scale: z.ZodMiniNumber<number>;
92
+ labels: z.ZodMiniOptional<z.ZodMiniObject<{
93
+ lower: z.ZodMiniOptional<z.ZodMiniPipe<z.ZodMiniString<string>, z.ZodMiniTransform<string | undefined, string>>>;
94
+ upper: z.ZodMiniOptional<z.ZodMiniPipe<z.ZodMiniString<string>, z.ZodMiniTransform<string | undefined, string>>>;
95
+ }, z.core.$strip>>;
96
+ display: z.ZodMiniOptional<z.ZodMiniLiteral<"number" | "star" | "emoji" | "tiffany">>;
97
+ }, z.core.$strip>, z.ZodMiniObject<{
98
+ type: z.ZodMiniLiteral<"single-select">;
99
+ options: z.ZodMiniArray<z.ZodMiniObject<{
100
+ value: z.ZodMiniString<string>;
101
+ description: z.ZodMiniOptional<z.ZodMiniString<string>>;
102
+ }, z.core.$strip>>;
103
+ buttonLabel: z.ZodMiniOptional<z.ZodMiniString<string>>;
104
+ editable: z.ZodMiniNullable<z.ZodMiniObject<{
105
+ label: z.ZodMiniString<string>;
106
+ max: z.ZodMiniNumber<number>;
107
+ description: z.ZodMiniOptional<z.ZodMiniString<string>>;
108
+ }, z.core.$strip>>;
109
+ }, z.core.$strip>, z.ZodMiniObject<{
110
+ type: z.ZodMiniLiteral<"open-ended">;
111
+ buttonLabel: z.ZodMiniOptional<z.ZodMiniString<string>>;
112
+ max: z.ZodMiniNumber<number>;
113
+ }, z.core.$strip>, z.ZodMiniObject<{
114
+ type: z.ZodMiniLiteral<"multi-select">;
115
+ buttonLabel: z.ZodMiniOptional<z.ZodMiniString<string>>;
116
+ options: z.ZodMiniArray<z.ZodMiniObject<{
117
+ value: z.ZodMiniString<string>;
118
+ description: z.ZodMiniOptional<z.ZodMiniString<string>>;
119
+ }, z.core.$strip>>;
120
+ editable: z.ZodMiniNullable<z.ZodMiniObject<{
121
+ label: z.ZodMiniString<string>;
122
+ max: z.ZodMiniNumber<number>;
123
+ description: z.ZodMiniOptional<z.ZodMiniString<string>>;
124
+ }, z.core.$strip>>;
125
+ max: z.ZodMiniOptional<z.ZodMiniNumber<number>>;
126
+ display: z.ZodMiniOptional<z.ZodMiniLiteral<"checkbox" | "tag">>;
127
+ }, z.core.$strip>, z.ZodMiniObject<{
128
+ type: z.ZodMiniLiteral<"statement">;
129
+ buttonLabel: z.ZodMiniOptional<z.ZodMiniString<string>>;
130
+ buttonUrl: z.ZodMiniOptional<z.ZodMiniString<string>>;
131
+ }, z.core.$strip>], "type">;
132
+ routingLogic: z.ZodMiniDiscriminatedUnion<[z.ZodMiniObject<{
133
+ type: z.ZodMiniLiteral<"always">;
134
+ target: z.ZodMiniDiscriminatedUnion<[z.ZodMiniObject<{
135
+ type: z.ZodMiniLiteral<"next">;
136
+ }, z.core.$strip>, z.ZodMiniObject<{
137
+ type: z.ZodMiniLiteral<"jump">;
138
+ target: z.ZodMiniNumber<number>;
139
+ }, z.core.$strip>, z.ZodMiniObject<{
140
+ type: z.ZodMiniLiteral<"end">;
141
+ }, z.core.$strip>], "type">;
142
+ }, z.core.$strip>, z.ZodMiniObject<{
143
+ type: z.ZodMiniLiteral<"switch">;
144
+ cases: z.ZodMiniArray<z.ZodMiniObject<{
145
+ type: z.ZodMiniLiteral<"binary-operator">;
146
+ operator: z.ZodMiniUnion<readonly [z.ZodMiniLiteral<"equal">, z.ZodMiniLiteral<"not-equal">, z.ZodMiniLiteral<"greater">, z.ZodMiniLiteral<"greater-or-equal">, z.ZodMiniLiteral<"less">, z.ZodMiniLiteral<"less-or-equal">, z.ZodMiniLiteral<"contains">, z.ZodMiniLiteral<"not-contains">]>;
147
+ value: z.ZodMiniObject<{
148
+ type: z.ZodMiniLiteral<"value">;
149
+ value: z.ZodMiniUnion<readonly [z.ZodMiniString<string>, z.ZodMiniNumber<number>]>;
150
+ }, z.core.$strip>;
151
+ target: z.ZodMiniDiscriminatedUnion<[z.ZodMiniObject<{
152
+ type: z.ZodMiniLiteral<"next">;
153
+ }, z.core.$strip>, z.ZodMiniObject<{
154
+ type: z.ZodMiniLiteral<"jump">;
155
+ target: z.ZodMiniNumber<number>;
156
+ }, z.core.$strip>, z.ZodMiniObject<{
157
+ type: z.ZodMiniLiteral<"end">;
158
+ }, z.core.$strip>], "type">;
159
+ }, z.core.$strip>>;
160
+ default: z.ZodMiniDiscriminatedUnion<[z.ZodMiniObject<{
161
+ type: z.ZodMiniLiteral<"next">;
162
+ }, z.core.$strip>, z.ZodMiniObject<{
163
+ type: z.ZodMiniLiteral<"jump">;
164
+ target: z.ZodMiniNumber<number>;
165
+ }, z.core.$strip>, z.ZodMiniObject<{
166
+ type: z.ZodMiniLiteral<"end">;
167
+ }, z.core.$strip>], "type">;
168
+ }, z.core.$strip>], "type">;
169
+ }, z.core.$strip>>;
170
+ confirmation: z.ZodMiniObject<{
171
+ title: z.ZodMiniString<string>;
172
+ description: z.ZodMiniString<string>;
173
+ buttonText: z.ZodMiniString<string>;
174
+ }, z.core.$strip>;
175
+ }, z.core.$strip>;
176
+ type PublicGetSurveyOutput = z.infer<typeof publicGetSurveyOutputSchema>;
177
+ //#endregion
178
+ //#region src/core/types.d.ts
179
+ type Question = {
180
+ visible: boolean;
181
+ error?: string;
182
+ } & PublicGetSurveyOutput['questions'][number];
183
+ type Answer = string | number | string[] | undefined;
184
+ interface ConfettiState {
185
+ questions: Question[];
186
+ current: number;
187
+ update: ({
188
+ question,
189
+ answer
190
+ }: {
191
+ question: number;
192
+ answer: Answer;
193
+ }) => {
194
+ next?: number;
195
+ error?: string;
196
+ };
197
+ submit: () => void;
198
+ isCompleted: boolean;
199
+ isSubmitted: boolean;
200
+ errors: Record<Question['id'], string>;
201
+ }
202
+ //#endregion
203
+ export { MultiSelectQuestionProperties as a, StatementQuestionProperties as c, PublicGetSurveyOutput as i, TextQuestionProperties as l, ConfettiState as n, RatingQuestionProperties as o, Question as r, SingleSelectQuestionProperties as s, Answer as t, BinaryOperatorCondition as u };
204
+ //# sourceMappingURL=types-qVyTr8wu.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengovsg/confetti",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "sideEffects": false,
5
5
  "description": "Widgets for Confetti",
6
6
  "license": "SEE LICENSE IN LICENSE.md",
@@ -13,6 +13,11 @@
13
13
  "default": "./build/index.js",
14
14
  "types": "./build/index.d.ts"
15
15
  },
16
+ "./internals": {
17
+ "import": "./build/internals.js",
18
+ "default": "./build/internals.js",
19
+ "types": "./build/internals.d.ts"
20
+ },
16
21
  "./confetti.css": "./build/confetti.css"
17
22
  },
18
23
  "files": [
@@ -38,10 +43,10 @@
38
43
  "prettier": "^3.7.4",
39
44
  "tsdown": "0.19.0",
40
45
  "typescript": "^5.9.3",
41
- "@confetti/tsconfig": "0.0.0",
42
- "@confetti/validators": "0.0.0",
46
+ "@confetti/eslint-config": "0.0.0",
43
47
  "@confetti/prettier-config": "0.0.0",
44
- "@confetti/eslint-config": "0.0.0"
48
+ "@confetti/tsconfig": "0.0.0",
49
+ "@confetti/validators": "0.0.0"
45
50
  },
46
51
  "prettier": "@confetti/prettier-config",
47
52
  "scripts": {