mirror of
https://github.com/formbricks/formbricks.git
synced 2026-05-04 03:16:15 -05:00
Add new Consent Question Type (#342)
* feat: add consent to questionTypes and types * feat: add default values to consent question * feat: add consent question form * feat: add consent question to preview / link survey * fix: clean consent question html * feat: add consent question to js package * feat: add consent to summary list * fix build errors * fix: remove skip button, add button label input * feat: add checked logic option * fix: add accepted option * update consent form to match new advanced settings layout * remove console.log * hide accepted condition if consent is required * fix build errors * update consent question return values * remove console.log * renamed submitted to clicked in CTA logic, removed submitted condition for consent questions * remove logs display from demo; * remove logs display from demo; --------- Co-authored-by: Matthias Nannt <mail@matthiasnannt.com>
This commit is contained in:
@@ -1,29 +0,0 @@
|
||||
// @ts-nocheck
|
||||
import React, { useState, useEffect, useRef } from "react";
|
||||
import { Console, Hook, Unhook } from "console-feed";
|
||||
|
||||
const LogsContainer = () => {
|
||||
const [logs, setLogs] = useState([]);
|
||||
const messagesEndRef = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
const scrollToBottom = () => {
|
||||
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
||||
};
|
||||
|
||||
// run once!
|
||||
useEffect(() => {
|
||||
const hookedConsole = Hook(window.console, (log) => setLogs((currLogs) => [...currLogs, log]), false);
|
||||
return () => Unhook(hookedConsole);
|
||||
}, []);
|
||||
|
||||
useEffect(scrollToBottom, [logs]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Console logs={logs} variant="light" />
|
||||
<div ref={messagesEndRef} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export { LogsContainer };
|
||||
@@ -12,7 +12,6 @@
|
||||
"dependencies": {
|
||||
"@formbricks/js": "workspace:*",
|
||||
"@heroicons/react": "^2.0.17",
|
||||
"console-feed": "^3.5.0",
|
||||
"eslint-config-formbricks": "workspace:*",
|
||||
"next": "13.2.4",
|
||||
"react": "18.2.0",
|
||||
@@ -21,8 +20,8 @@
|
||||
"devDependencies": {
|
||||
"@tailwindcss/forms": "^0.5.3",
|
||||
"@types/node": "18.15.11",
|
||||
"@types/react-dom": "18.0.11",
|
||||
"@types/react": "18.0.33",
|
||||
"@types/react-dom": "18.0.11",
|
||||
"autoprefixer": "^10.4.14",
|
||||
"postcss": "^8.4.21",
|
||||
"rimraf": "^5.0.0",
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import fbsetup from "../../public/fb-setup.png";
|
||||
import formbricks from "@formbricks/js";
|
||||
import Image from "next/image";
|
||||
import { LogsContainer } from "../../components/ConsoleFeed";
|
||||
|
||||
export default function AppPage({}) {
|
||||
return (
|
||||
@@ -22,13 +21,13 @@ export default function AppPage({}) {
|
||||
</p>
|
||||
<Image src={fbsetup} alt="fb setup" className="mt-4 rounded" priority />
|
||||
</div>
|
||||
<div className="mt-4 rounded-lg border border-slate-300 bg-slate-100 p-6">
|
||||
{/* <div className="mt-4 rounded-lg border border-slate-300 bg-slate-100 p-6">
|
||||
<h3 className="text-lg font-semibold">Console</h3>
|
||||
<p className="text-slate-700">You can also open your browser console to logs:</p>
|
||||
<div className="max-h-[40vh] overflow-y-auto py-4">
|
||||
<LogsContainer />
|
||||
</div>
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
|
||||
<div className="md:grid md:grid-cols-3">
|
||||
|
||||
@@ -157,6 +157,10 @@ export default function PreviewSurvey({
|
||||
Array.isArray(logic.value) &&
|
||||
logic.value.some((v) => answerValue.includes(v))
|
||||
);
|
||||
case "accepted":
|
||||
return answerValue === "accepted";
|
||||
case "clicked":
|
||||
return answerValue === "clicked";
|
||||
case "submitted":
|
||||
if (typeof answerValue === "string") {
|
||||
return answerValue !== "dismissed" && answerValue !== "" && answerValue !== null;
|
||||
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
"use client";
|
||||
|
||||
import { md } from "@formbricks/lib/markdownIt";
|
||||
import type { ConsentQuestion } from "@formbricks/types/questions";
|
||||
import { Survey } from "@formbricks/types/surveys";
|
||||
import { Editor, Input, Label } from "@formbricks/ui";
|
||||
import { useState } from "react";
|
||||
|
||||
interface ConsentQuestionFormProps {
|
||||
localSurvey: Survey;
|
||||
question: ConsentQuestion;
|
||||
questionIdx: number;
|
||||
updateQuestion: (questionIdx: number, updatedAttributes: any) => void;
|
||||
}
|
||||
|
||||
export default function ConsentQuestionForm({
|
||||
question,
|
||||
questionIdx,
|
||||
updateQuestion,
|
||||
}: ConsentQuestionFormProps): JSX.Element {
|
||||
const [firstRender, setFirstRender] = useState(true);
|
||||
return (
|
||||
<form>
|
||||
<div className="mt-3">
|
||||
<Label htmlFor="headline">Question</Label>
|
||||
<div className="mt-2">
|
||||
<Input
|
||||
id="headline"
|
||||
name="headline"
|
||||
value={question.headline}
|
||||
onChange={(e) => updateQuestion(questionIdx, { headline: e.target.value })}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-3">
|
||||
<Label htmlFor="subheader">Description</Label>
|
||||
<div className="mt-2">
|
||||
<Editor
|
||||
getText={() =>
|
||||
md.render(
|
||||
question.html || "We would love to talk to you and learn more about how you use our product."
|
||||
)
|
||||
}
|
||||
setText={(value: string) => {
|
||||
updateQuestion(questionIdx, { html: value });
|
||||
}}
|
||||
excludedToolbarItems={["blockType"]}
|
||||
disableLists
|
||||
firstRender={firstRender}
|
||||
setFirstRender={setFirstRender}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-3">
|
||||
<Label htmlFor="label">Checkbox Label</Label>
|
||||
<Input
|
||||
id="label"
|
||||
name="label"
|
||||
className="mt-2"
|
||||
value={question.label}
|
||||
placeholder="I agree to the terms and conditions"
|
||||
onChange={(e) => updateQuestion(questionIdx, { label: e.target.value })}
|
||||
/>
|
||||
</div>
|
||||
{/* <div className="mt-3">
|
||||
<Label htmlFor="buttonLabel">Button Label</Label>
|
||||
<Input
|
||||
id="buttonLabel"
|
||||
name="buttonLabel"
|
||||
className="mt-2"
|
||||
value={question.buttonLabel}
|
||||
placeholder={lastQuestion ? "Finish" : "Next"}
|
||||
onChange={(e) => updateQuestion(questionIdx, { buttonLabel: e.target.value })}
|
||||
/>
|
||||
</div> */}
|
||||
</form>
|
||||
);
|
||||
}
|
||||
@@ -79,7 +79,8 @@ export default function LogicEditor({
|
||||
"submitted",
|
||||
"skipped",
|
||||
],
|
||||
cta: ["submitted", "skipped"],
|
||||
cta: ["clicked", "skipped"],
|
||||
consent: ["skipped", "accepted"],
|
||||
};
|
||||
const logicConditions: LogicConditions = {
|
||||
submitted: {
|
||||
@@ -92,6 +93,16 @@ export default function LogicEditor({
|
||||
values: null,
|
||||
unique: true,
|
||||
},
|
||||
accepted: {
|
||||
label: "is accepted",
|
||||
values: null,
|
||||
unique: true,
|
||||
},
|
||||
clicked: {
|
||||
label: "is clicked",
|
||||
values: null,
|
||||
unique: true,
|
||||
},
|
||||
equals: {
|
||||
label: "equals",
|
||||
values: questionValues,
|
||||
|
||||
@@ -7,6 +7,7 @@ import type { Survey } from "@formbricks/types/surveys";
|
||||
import { Input, Label, Switch } from "@formbricks/ui";
|
||||
import {
|
||||
ChatBubbleBottomCenterTextIcon,
|
||||
CheckIcon,
|
||||
ChevronDownIcon,
|
||||
ChevronRightIcon,
|
||||
CursorArrowRippleIcon,
|
||||
@@ -25,6 +26,7 @@ import NPSQuestionForm from "./NPSQuestionForm";
|
||||
import OpenQuestionForm from "./OpenQuestionForm";
|
||||
import QuestionDropdown from "./QuestionMenu";
|
||||
import RatingQuestionForm from "./RatingQuestionForm";
|
||||
import ConsentQuestionForm from "./ConsentQuestionForm";
|
||||
import AdvancedSettings from "@/app/environments/[environmentId]/surveys/[surveyId]/edit/AdvancedSettings";
|
||||
|
||||
interface QuestionCardProps {
|
||||
@@ -100,6 +102,8 @@ export default function QuestionCard({
|
||||
<CursorArrowRippleIcon />
|
||||
) : question.type === QuestionType.Rating ? (
|
||||
<StarIcon />
|
||||
) : question.type === "consent" ? (
|
||||
<CheckIcon />
|
||||
) : null}
|
||||
</div>
|
||||
<div>
|
||||
@@ -174,6 +178,13 @@ export default function QuestionCard({
|
||||
updateQuestion={updateQuestion}
|
||||
lastQuestion={lastQuestion}
|
||||
/>
|
||||
) : question.type === "consent" ? (
|
||||
<ConsentQuestionForm
|
||||
localSurvey={localSurvey}
|
||||
question={question}
|
||||
questionIdx={questionIdx}
|
||||
updateQuestion={updateQuestion}
|
||||
/>
|
||||
) : null}
|
||||
<div className="mt-4">
|
||||
<Collapsible.Root open={openAdvanced} onOpenChange={setOpenAdvanced} className="mt-5">
|
||||
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
import { ConsentQuestion } from "@formbricks/types/questions";
|
||||
import type { QuestionSummary } from "@formbricks/types/responses";
|
||||
import { ProgressBar } from "@formbricks/ui";
|
||||
import { InboxStackIcon } from "@heroicons/react/24/solid";
|
||||
import { useMemo } from "react";
|
||||
|
||||
interface ConsentSummaryProps {
|
||||
questionSummary: QuestionSummary<ConsentQuestion>;
|
||||
}
|
||||
|
||||
interface ChoiceResult {
|
||||
count: number;
|
||||
acceptedCount: number;
|
||||
acceptedPercentage: number;
|
||||
dismissedCount: number;
|
||||
dismissedPercentage: number;
|
||||
}
|
||||
|
||||
export default function ConsentSummary({ questionSummary }: ConsentSummaryProps) {
|
||||
const ctr: ChoiceResult = useMemo(() => {
|
||||
const total = questionSummary.responses.length;
|
||||
const clickedAbs = questionSummary.responses.filter((response) => response.value !== "skipped").length;
|
||||
|
||||
return {
|
||||
count: total,
|
||||
acceptedCount: clickedAbs,
|
||||
acceptedPercentage: clickedAbs / total,
|
||||
dismissedCount: total - clickedAbs,
|
||||
dismissedPercentage: 1 - clickedAbs / total,
|
||||
};
|
||||
}, [questionSummary]);
|
||||
|
||||
return (
|
||||
<div className=" rounded-lg border border-slate-200 bg-slate-50 shadow-sm">
|
||||
<div className="space-y-2 px-6 pb-5 pt-6">
|
||||
<div>
|
||||
<h3 className="pb-1 text-xl font-semibold text-slate-900">{questionSummary.question.headline}</h3>
|
||||
</div>
|
||||
<div className="flex space-x-2 font-semibold text-slate-600">
|
||||
<div className="rounded-lg bg-slate-100 p-2 text-sm">Consent</div>
|
||||
<div className=" flex items-center rounded-lg bg-slate-100 p-2 text-sm">
|
||||
<InboxStackIcon className="mr-2 h-4 w-4 " />
|
||||
{ctr.count} responses
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-5 rounded-b-lg bg-white px-6 pb-6 pt-4">
|
||||
<div>
|
||||
<div className="text flex justify-between px-2 pb-2">
|
||||
<div className="mr-8 flex space-x-1">
|
||||
<p className="font-semibold text-slate-700">Accepted</p>
|
||||
<div>
|
||||
<p className="rounded-lg bg-slate-100 px-2 text-slate-700">
|
||||
{Math.round(ctr.acceptedPercentage * 100)}%
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<p className="flex w-32 items-end justify-end text-slate-600">
|
||||
{ctr.acceptedCount} {ctr.acceptedCount === 1 ? "response" : "responses"}
|
||||
</p>
|
||||
</div>
|
||||
<ProgressBar barColor="bg-brand" progress={ctr.acceptedPercentage} />
|
||||
</div>
|
||||
<div>
|
||||
<div className="text flex justify-between px-2 pb-2">
|
||||
<div className="mr-8 flex space-x-1">
|
||||
<p className="font-semibold text-slate-700">Skipped</p>
|
||||
<div>
|
||||
<p className="rounded-lg bg-slate-100 px-2 text-slate-700">
|
||||
{Math.round(ctr.dismissedPercentage * 100)}%
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<p className="flex w-32 items-end justify-end text-slate-600">
|
||||
{ctr.dismissedCount} {ctr.dismissedCount === 1 ? "response" : "responses"}
|
||||
</p>
|
||||
</div>
|
||||
<ProgressBar barColor="bg-brand" progress={ctr.dismissedPercentage} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -252,7 +252,7 @@ export const templates: Template[] = [
|
||||
id: "mao94214zoo6c1at5rpuz7io",
|
||||
html: '<p class="fb-editor-paragraph" dir="ltr"><span>We\'d love to keep you as a customer. Happy to offer a 30% discount for the next year.</span></p>',
|
||||
type: QuestionType.CTA,
|
||||
logic: [{ condition: "submitted", destination: "end" }],
|
||||
logic: [{ condition: "clicked", destination: "end" }],
|
||||
headline: "Get 30% off for the next year!",
|
||||
required: true,
|
||||
buttonUrl: "https://formbricks.com",
|
||||
@@ -273,7 +273,7 @@ export const templates: Template[] = [
|
||||
id: "hdftsos1odzjllr7flj4m3j9",
|
||||
html: '<p class="fb-editor-paragraph" dir="ltr"><span>We aim to provide the best possible customer service. Please email our CEO and she will personally handle your issue.</span></p>',
|
||||
type: QuestionType.CTA,
|
||||
logic: [{ condition: "submitted", destination: "end" }],
|
||||
logic: [{ condition: "clicked", destination: "end" }],
|
||||
headline: "So sorry to hear 😔 Talk to our CEO directly!",
|
||||
required: true,
|
||||
buttonUrl: "mailto:ceo@company.com",
|
||||
@@ -409,7 +409,7 @@ export const templates: Template[] = [
|
||||
id: "x760wga1fhtr1i80cpssr7af",
|
||||
html: '<p class="fb-editor-paragraph" dir="ltr"><span>We\'re happy to offer you a 20% discount on a yearly plan.</span></p>',
|
||||
type: QuestionType.CTA,
|
||||
logic: [{ condition: "submitted", destination: "end" }],
|
||||
logic: [{ condition: "clicked", destination: "end" }],
|
||||
headline: "Sorry to hear! Get 20% off the first year.",
|
||||
required: true,
|
||||
buttonUrl: "https://formbricks.com/github",
|
||||
@@ -466,7 +466,7 @@ export const templates: Template[] = [
|
||||
id: createId(),
|
||||
html: '<p class="fb-editor-paragraph" dir="ltr"><span>This helps us a lot.</span></p>',
|
||||
type: QuestionType.CTA,
|
||||
logic: [{ condition: "submitted", destination: "end" }],
|
||||
logic: [{ condition: "clicked", destination: "end" }],
|
||||
headline: "Happy to hear 🙏 Please write a review for us!",
|
||||
required: true,
|
||||
buttonUrl: "https://formbricks.com/github",
|
||||
@@ -945,7 +945,7 @@ export const templates: Template[] = [
|
||||
html: '<p class="fb-editor-paragraph" dir="ltr"><span>We will fix this as soon as possible. Do you want to be notified when we did?</span></p>',
|
||||
type: QuestionType.CTA,
|
||||
logic: [
|
||||
{ condition: "submitted", destination: "end" },
|
||||
{ condition: "clicked", destination: "end" },
|
||||
{ condition: "skipped", destination: "end" },
|
||||
],
|
||||
headline: "Want to stay in the loop?",
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
import type { ConsentQuestion } from "@formbricks/types/questions";
|
||||
import Headline from "./Headline";
|
||||
import HtmlBody from "./HtmlBody";
|
||||
import { cn } from "@/../../packages/lib/cn";
|
||||
import { isLight } from "@/lib/utils";
|
||||
|
||||
interface ConsentQuestionProps {
|
||||
question: ConsentQuestion;
|
||||
onSubmit: (data: { [x: string]: any }) => void;
|
||||
lastQuestion: boolean;
|
||||
brandColor: string;
|
||||
}
|
||||
|
||||
export default function ConsentQuestion({
|
||||
question,
|
||||
onSubmit,
|
||||
lastQuestion,
|
||||
brandColor,
|
||||
}: ConsentQuestionProps) {
|
||||
return (
|
||||
<div>
|
||||
<Headline headline={question.headline} questionId={question.id} />
|
||||
<HtmlBody htmlString={question.html || ""} questionId={question.id} />
|
||||
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
|
||||
const checkbox = document.getElementById(question.id) as HTMLInputElement;
|
||||
onSubmit({ [question.id]: checkbox.checked ? "accepted" : "dismissed" });
|
||||
}}>
|
||||
<label className="relative z-10 mt-4 flex w-full cursor-pointer items-center rounded-md border border-gray-200 bg-slate-50 p-4 text-sm focus:outline-none">
|
||||
<input
|
||||
type="checkbox"
|
||||
id={question.id}
|
||||
name={question.id}
|
||||
value={question.label}
|
||||
className="h-4 w-4 border border-slate-300 focus:ring-0 focus:ring-offset-0"
|
||||
aria-labelledby={`${question.id}-label`}
|
||||
style={{ borderColor: brandColor, color: brandColor }}
|
||||
required={question.required}
|
||||
/>
|
||||
<span id={`${question.id}-label`} className="ml-3 font-medium">
|
||||
{question.label}
|
||||
</span>
|
||||
</label>
|
||||
|
||||
<div className="mt-4 flex w-full justify-end">
|
||||
<button
|
||||
type="submit"
|
||||
className={cn(
|
||||
"flex items-center rounded-md border border-transparent px-3 py-3 text-base font-medium leading-4 shadow-sm hover:opacity-90 focus:outline-none focus:ring-2 focus:ring-slate-500 focus:ring-offset-2",
|
||||
isLight(brandColor) ? "text-black" : "text-white"
|
||||
)}
|
||||
style={{ backgroundColor: brandColor }}>
|
||||
{question.buttonLabel || (lastQuestion ? "Finish" : "Next")}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import MultipleChoiceMultiQuestion from "./MultipleChoiceMultiQuestion";
|
||||
import NPSQuestion from "./NPSQuestion";
|
||||
import CTAQuestion from "./CTAQuestion";
|
||||
import RatingQuestion from "./RatingQuestion";
|
||||
import ConsentQuestion from "./ConsentQuestion";
|
||||
|
||||
interface QuestionConditionalProps {
|
||||
question: Question;
|
||||
@@ -61,5 +62,12 @@ export default function QuestionConditional({
|
||||
lastQuestion={lastQuestion}
|
||||
brandColor={brandColor}
|
||||
/>
|
||||
) : question.type === "consent" ? (
|
||||
<ConsentQuestion
|
||||
question={question}
|
||||
onSubmit={onSubmit}
|
||||
lastQuestion={lastQuestion}
|
||||
brandColor={brandColor}
|
||||
/>
|
||||
) : null;
|
||||
}
|
||||
|
||||
@@ -314,6 +314,10 @@ const evaluateCondition = (logic: Logic, answerValue: any): boolean => {
|
||||
Array.isArray(logic.value) &&
|
||||
logic.value.some((v) => answerValue.includes(v))
|
||||
);
|
||||
case "accepted":
|
||||
return answerValue === "accepted";
|
||||
case "clicked":
|
||||
return answerValue === "clicked";
|
||||
case "submitted":
|
||||
if (typeof answerValue === "string") {
|
||||
return answerValue !== "dismissed" && answerValue !== "" && answerValue !== null;
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
PresentationChartBarIcon,
|
||||
QueueListIcon,
|
||||
StarIcon,
|
||||
CheckIcon,
|
||||
} from "@heroicons/react/24/solid";
|
||||
import { createId } from "@paralleldrive/cuid2";
|
||||
import { replaceQuestionPresetPlaceholders } from "./templates";
|
||||
@@ -95,6 +96,17 @@ export const questionTypes: QuestionType[] = [
|
||||
upperLabel: "Very good",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "consent",
|
||||
label: "Consent",
|
||||
description: "Ask your users to accept something",
|
||||
icon: CheckIcon,
|
||||
preset: {
|
||||
headline: "Terms and Conditions",
|
||||
label: "I agree to the terms and conditions",
|
||||
dismissButtonLabel: "Skip",
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
export const universalQuestionPresets = {
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
import type { ConsentQuestion } from "../../../types/questions";
|
||||
import { h } from "preact";
|
||||
import Headline from "./Headline";
|
||||
import HtmlBody from "./HtmlBody";
|
||||
import SubmitButton from "./SubmitButton";
|
||||
|
||||
interface ConsentQuestionProps {
|
||||
question: ConsentQuestion;
|
||||
onSubmit: (data: { [x: string]: any }) => void;
|
||||
lastQuestion: boolean;
|
||||
brandColor: string;
|
||||
}
|
||||
|
||||
export default function ConsentQuestion({
|
||||
question,
|
||||
onSubmit,
|
||||
lastQuestion,
|
||||
brandColor,
|
||||
}: ConsentQuestionProps) {
|
||||
return (
|
||||
<div>
|
||||
<Headline headline={question.headline} questionId={question.id} />
|
||||
<HtmlBody htmlString={question.html || ""} questionId={question.id} />
|
||||
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
|
||||
const checkbox = document.getElementById(question.id) as HTMLInputElement;
|
||||
onSubmit({ [question.id]: checkbox.checked ? "accepted" : "dismissed" });
|
||||
}}>
|
||||
<label className="fb-relative fb-z-10 fb-mt-4 fb-flex fb-w-full fb-cursor-pointer fb-items-center fb-rounded-md fb-border fb-border-gray-200 fb-bg-slate-50 fb-p-4 fb-text-sm focus:fb-outline-none">
|
||||
<input
|
||||
type="checkbox"
|
||||
id={question.id}
|
||||
name={question.id}
|
||||
value={question.label}
|
||||
className="fb-h-4 fb-w-4 fb-border fb-border-slate-300 focus:fb-ring-0 focus:fb-ring-offset-0"
|
||||
aria-labelledby={`${question.id}-label`}
|
||||
style={{ borderColor: brandColor, color: brandColor }}
|
||||
required={question.required}
|
||||
/>
|
||||
<span id={`${question.id}-label`} className="fb-ml-3 fb-font-medium">
|
||||
{question.label}
|
||||
</span>
|
||||
</label>
|
||||
|
||||
<div className="fb-mt-4 fb-flex fb-w-full fb-justify-end">
|
||||
<SubmitButton
|
||||
brandColor={brandColor}
|
||||
question={question}
|
||||
lastQuestion={lastQuestion}
|
||||
onClick={() => {}}
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import MultipleChoiceMultiQuestion from "./MultipleChoiceMultiQuestion";
|
||||
import NPSQuestion from "./NPSQuestion";
|
||||
import CTAQuestion from "./CTAQuestion";
|
||||
import RatingQuestion from "./RatingQuestion";
|
||||
import ConsentQuestion from "./ConsentQuestion";
|
||||
|
||||
interface QuestionConditionalProps {
|
||||
question: Question;
|
||||
@@ -62,5 +63,12 @@ export default function QuestionConditional({
|
||||
lastQuestion={lastQuestion}
|
||||
brandColor={brandColor}
|
||||
/>
|
||||
) : question.type === "consent" ? (
|
||||
<ConsentQuestion
|
||||
question={question}
|
||||
onSubmit={onSubmit}
|
||||
lastQuestion={lastQuestion}
|
||||
brandColor={brandColor}
|
||||
/>
|
||||
) : null;
|
||||
}
|
||||
|
||||
@@ -121,6 +121,10 @@ export default function SurveyView({ config, survey, close, errorHandler }: Surv
|
||||
Array.isArray(logic.value) &&
|
||||
logic.value.some((v) => answerValue.includes(v))
|
||||
);
|
||||
case "accepted":
|
||||
return answerValue === "accepted";
|
||||
case "clicked":
|
||||
return answerValue === "clicked";
|
||||
case "submitted":
|
||||
if (typeof answerValue === "string") {
|
||||
return answerValue !== "dismissed" && answerValue !== "" && answerValue !== null;
|
||||
|
||||
@@ -19,7 +19,8 @@ export type Question =
|
||||
| MultipleChoiceMultiQuestion
|
||||
| NPSQuestion
|
||||
| CTAQuestion
|
||||
| RatingQuestion;
|
||||
| RatingQuestion
|
||||
| ConsentQuestion;
|
||||
|
||||
export interface IQuestion<T extends Logic> {
|
||||
id: string;
|
||||
@@ -68,9 +69,18 @@ export interface RatingQuestion extends IQuestion<RatingLogic> {
|
||||
upperLabel: string;
|
||||
}
|
||||
|
||||
export interface ConsentQuestion extends IQuestion<CTALogic> {
|
||||
type: "consent";
|
||||
html?: string;
|
||||
label: string;
|
||||
dismissButtonLabel?: string;
|
||||
}
|
||||
|
||||
export type LogicCondition =
|
||||
| "submitted"
|
||||
| "skipped"
|
||||
| "accepted"
|
||||
| "clicked"
|
||||
| "equals"
|
||||
| "notEquals"
|
||||
| "lessThan"
|
||||
@@ -112,7 +122,7 @@ export interface NPSLogic extends LogicBase {
|
||||
value?: number;
|
||||
}
|
||||
export interface CTALogic extends LogicBase {
|
||||
condition: "submitted" | "skipped" | undefined;
|
||||
condition: "clicked" | "skipped" | undefined;
|
||||
value?: undefined;
|
||||
}
|
||||
export interface RatingLogic extends LogicBase {
|
||||
@@ -128,10 +138,17 @@ export interface RatingLogic extends LogicBase {
|
||||
| undefined;
|
||||
value?: number | string;
|
||||
}
|
||||
|
||||
export interface ConsentLogic extends LogicBase {
|
||||
condition: "submitted" | "skipped" | "accepted" | undefined;
|
||||
value: undefined;
|
||||
}
|
||||
|
||||
export type Logic =
|
||||
| OpenTextLogic
|
||||
| MultipleChoiceSingleLogic
|
||||
| MultipleChoiceMultiLogic
|
||||
| NPSLogic
|
||||
| CTALogic
|
||||
| RatingLogic;
|
||||
| RatingLogic
|
||||
| ConsentLogic;
|
||||
|
||||
@@ -40,7 +40,7 @@ export const ZSurveyOpenTextLogic = ZSurveyLogicBase.extend({
|
||||
});
|
||||
|
||||
export const ZSurveyConsentLogic = ZSurveyLogicBase.extend({
|
||||
condition: z.enum(["submitted", "skipped", "accepted"]).optional(),
|
||||
condition: z.enum(["skipped", "accepted"]).optional(),
|
||||
value: z.undefined(),
|
||||
});
|
||||
|
||||
@@ -71,7 +71,8 @@ export const ZSurveyNPSLogic = ZSurveyLogicBase.extend({
|
||||
});
|
||||
|
||||
const ZSurveyCTALogic = ZSurveyLogicBase.extend({
|
||||
condition: z.enum(["submitted", "skipped"]).optional(),
|
||||
// "submitted" condition is legacy and should be removed later
|
||||
condition: z.enum(["clicked", "submitted", "skipped"]).optional(),
|
||||
value: z.undefined(),
|
||||
});
|
||||
|
||||
|
||||
Generated
+15
-221
@@ -32,9 +32,6 @@ importers:
|
||||
'@heroicons/react':
|
||||
specifier: ^2.0.17
|
||||
version: 2.0.18(react@18.2.0)
|
||||
console-feed:
|
||||
specifier: ^3.5.0
|
||||
version: 3.5.0(jquery@3.7.0)(react-dom@18.2.0)(react@18.2.0)
|
||||
eslint-config-formbricks:
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/eslint-config-formbricks
|
||||
@@ -912,6 +909,7 @@ packages:
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/highlight': 7.18.6
|
||||
dev: true
|
||||
|
||||
/@babel/compat-data@7.20.5:
|
||||
resolution: {integrity: sha512-KZXo2t10+/jxmkhNXc7pZTqRvSOIvVv/+lJwHS+B2rErwOyjuVRh60yVpb7liQ1U5t7lLJ1bz+t8tSypUZdm0g==}
|
||||
@@ -1077,6 +1075,7 @@ packages:
|
||||
engines: {node: '>=6.9.0'}
|
||||
dependencies:
|
||||
'@babel/types': 7.20.7
|
||||
dev: true
|
||||
|
||||
/@babel/helper-module-transforms@7.20.11:
|
||||
resolution: {integrity: sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg==}
|
||||
@@ -1158,10 +1157,12 @@ packages:
|
||||
/@babel/helper-string-parser@7.19.4:
|
||||
resolution: {integrity: sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dev: true
|
||||
|
||||
/@babel/helper-validator-identifier@7.19.1:
|
||||
resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
dev: true
|
||||
|
||||
/@babel/helper-validator-option@7.18.6:
|
||||
resolution: {integrity: sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==}
|
||||
@@ -1198,6 +1199,7 @@ packages:
|
||||
'@babel/helper-validator-identifier': 7.19.1
|
||||
chalk: 2.4.2
|
||||
js-tokens: 4.0.0
|
||||
dev: true
|
||||
|
||||
/@babel/parser@7.20.13:
|
||||
resolution: {integrity: sha512-gFDLKMfpiXCsjt4za2JA9oTMn70CeseCehb11kRZgvd7+F67Hih3OHOK24cRrWECJ/ljfPGac6ygXAs/C8kIvw==}
|
||||
@@ -2266,6 +2268,7 @@ packages:
|
||||
'@babel/helper-string-parser': 7.19.4
|
||||
'@babel/helper-validator-identifier': 7.19.1
|
||||
to-fast-properties: 2.0.0
|
||||
dev: true
|
||||
|
||||
/@bcoe/v8-coverage@0.2.3:
|
||||
resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==}
|
||||
@@ -2516,107 +2519,6 @@ packages:
|
||||
- search-insights
|
||||
dev: false
|
||||
|
||||
/@emotion/cache@10.0.29:
|
||||
resolution: {integrity: sha512-fU2VtSVlHiF27empSbxi1O2JFdNWZO+2NFHfwO0pxgTep6Xa3uGb+3pVKfLww2l/IBGLNEZl5Xf/++A4wAYDYQ==}
|
||||
dependencies:
|
||||
'@emotion/sheet': 0.9.4
|
||||
'@emotion/stylis': 0.8.5
|
||||
'@emotion/utils': 0.11.3
|
||||
'@emotion/weak-memoize': 0.2.5
|
||||
dev: false
|
||||
|
||||
/@emotion/core@10.3.1(react@18.2.0):
|
||||
resolution: {integrity: sha512-447aUEjPIm0MnE6QYIaFz9VQOHSXf4Iu6EWOIqq11EAPqinkSZmfymPTmlOE3QjLv846lH4JVZBUOtwGbuQoww==}
|
||||
peerDependencies:
|
||||
react: '>=16.3.0'
|
||||
dependencies:
|
||||
'@babel/runtime': 7.21.0
|
||||
'@emotion/cache': 10.0.29
|
||||
'@emotion/css': 10.0.27
|
||||
'@emotion/serialize': 0.11.16
|
||||
'@emotion/sheet': 0.9.4
|
||||
'@emotion/utils': 0.11.3
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@emotion/css@10.0.27:
|
||||
resolution: {integrity: sha512-6wZjsvYeBhyZQYNrGoR5yPMYbMBNEnanDrqmsqS1mzDm1cOTu12shvl2j4QHNS36UaTE0USIJawCH9C8oW34Zw==}
|
||||
dependencies:
|
||||
'@emotion/serialize': 0.11.16
|
||||
'@emotion/utils': 0.11.3
|
||||
babel-plugin-emotion: 10.2.2
|
||||
dev: false
|
||||
|
||||
/@emotion/hash@0.8.0:
|
||||
resolution: {integrity: sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==}
|
||||
dev: false
|
||||
|
||||
/@emotion/is-prop-valid@0.8.8:
|
||||
resolution: {integrity: sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==}
|
||||
dependencies:
|
||||
'@emotion/memoize': 0.7.4
|
||||
dev: false
|
||||
|
||||
/@emotion/memoize@0.7.4:
|
||||
resolution: {integrity: sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==}
|
||||
dev: false
|
||||
|
||||
/@emotion/serialize@0.11.16:
|
||||
resolution: {integrity: sha512-G3J4o8by0VRrO+PFeSc3js2myYNOXVJ3Ya+RGVxnshRYgsvErfAOglKAiy1Eo1vhzxqtUvjCyS5gtewzkmvSSg==}
|
||||
dependencies:
|
||||
'@emotion/hash': 0.8.0
|
||||
'@emotion/memoize': 0.7.4
|
||||
'@emotion/unitless': 0.7.5
|
||||
'@emotion/utils': 0.11.3
|
||||
csstype: 2.6.21
|
||||
dev: false
|
||||
|
||||
/@emotion/sheet@0.9.4:
|
||||
resolution: {integrity: sha512-zM9PFmgVSqBw4zL101Q0HrBVTGmpAxFZH/pYx/cjJT5advXguvcgjHFTCaIO3enL/xr89vK2bh0Mfyj9aa0ANA==}
|
||||
dev: false
|
||||
|
||||
/@emotion/styled-base@10.3.0(@emotion/core@10.3.1)(react@18.2.0):
|
||||
resolution: {integrity: sha512-PBRqsVKR7QRNkmfH78hTSSwHWcwDpecH9W6heujWAcyp2wdz/64PP73s7fWS1dIPm8/Exc8JAzYS8dEWXjv60w==}
|
||||
peerDependencies:
|
||||
'@emotion/core': ^10.0.28
|
||||
react: '>=16.3.0'
|
||||
dependencies:
|
||||
'@babel/runtime': 7.21.0
|
||||
'@emotion/core': 10.3.1(react@18.2.0)
|
||||
'@emotion/is-prop-valid': 0.8.8
|
||||
'@emotion/serialize': 0.11.16
|
||||
'@emotion/utils': 0.11.3
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@emotion/styled@10.3.0(@emotion/core@10.3.1)(react@18.2.0):
|
||||
resolution: {integrity: sha512-GgcUpXBBEU5ido+/p/mCT2/Xx+Oqmp9JzQRuC+a4lYM4i4LBBn/dWvc0rQ19N9ObA8/T4NWMrPNe79kMBDJqoQ==}
|
||||
peerDependencies:
|
||||
'@emotion/core': ^10.0.27
|
||||
react: '>=16.3.0'
|
||||
dependencies:
|
||||
'@emotion/core': 10.3.1(react@18.2.0)
|
||||
'@emotion/styled-base': 10.3.0(@emotion/core@10.3.1)(react@18.2.0)
|
||||
babel-plugin-emotion: 10.2.2
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@emotion/stylis@0.8.5:
|
||||
resolution: {integrity: sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==}
|
||||
dev: false
|
||||
|
||||
/@emotion/unitless@0.7.5:
|
||||
resolution: {integrity: sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==}
|
||||
dev: false
|
||||
|
||||
/@emotion/utils@0.11.3:
|
||||
resolution: {integrity: sha512-0o4l6pZC+hI88+bzuaX/6BgOvQVhbt2PfmxauVaYOGgbsAw14wdKyvMCZXnsnsHys94iadcF+RG/wZyx6+ZZBw==}
|
||||
dev: false
|
||||
|
||||
/@emotion/weak-memoize@0.2.5:
|
||||
resolution: {integrity: sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==}
|
||||
dev: false
|
||||
|
||||
/@esbuild-kit/cjs-loader@2.4.2:
|
||||
resolution: {integrity: sha512-BDXFbYOJzT/NBEtp71cvsrGPwGAMGRB/349rwKuoxNSiKjPraNNnlK6MIIabViCjqZugu6j+xeMDlEkWdHHJSg==}
|
||||
dependencies:
|
||||
@@ -6291,6 +6193,7 @@ packages:
|
||||
|
||||
/@types/parse-json@4.0.0:
|
||||
resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==}
|
||||
dev: true
|
||||
|
||||
/@types/prettier@2.7.2:
|
||||
resolution: {integrity: sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==}
|
||||
@@ -7672,21 +7575,6 @@ packages:
|
||||
webpack: 4.46.0
|
||||
dev: true
|
||||
|
||||
/babel-plugin-emotion@10.2.2:
|
||||
resolution: {integrity: sha512-SMSkGoqTbTyUTDeuVuPIWifPdUGkTk1Kf9BWRiXIOIcuyMfsdp2EjeiiFvOzX8NOBvEh/ypKYvUh2rkgAJMCLA==}
|
||||
dependencies:
|
||||
'@babel/helper-module-imports': 7.18.6
|
||||
'@emotion/hash': 0.8.0
|
||||
'@emotion/memoize': 0.7.4
|
||||
'@emotion/serialize': 0.11.16
|
||||
babel-plugin-macros: 2.8.0
|
||||
babel-plugin-syntax-jsx: 6.18.0
|
||||
convert-source-map: 1.9.0
|
||||
escape-string-regexp: 1.0.5
|
||||
find-root: 1.1.0
|
||||
source-map: 0.5.7
|
||||
dev: false
|
||||
|
||||
/babel-plugin-istanbul@6.1.1:
|
||||
resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -7720,14 +7608,6 @@ packages:
|
||||
'@types/babel__traverse': 7.18.3
|
||||
dev: true
|
||||
|
||||
/babel-plugin-macros@2.8.0:
|
||||
resolution: {integrity: sha512-SEP5kJpfGYqYKpBrj5XU3ahw5p5GOHJ0U5ssOSQ/WBVdwkD2Dzlce95exQTs3jOVWPPKLBN2rlEWkCK7dSmLvg==}
|
||||
dependencies:
|
||||
'@babel/runtime': 7.21.0
|
||||
cosmiconfig: 6.0.0
|
||||
resolve: 1.22.2
|
||||
dev: false
|
||||
|
||||
/babel-plugin-macros@3.1.0:
|
||||
resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==}
|
||||
engines: {node: '>=10', npm: '>=6'}
|
||||
@@ -7773,10 +7653,6 @@ packages:
|
||||
- supports-color
|
||||
dev: true
|
||||
|
||||
/babel-plugin-syntax-jsx@6.18.0:
|
||||
resolution: {integrity: sha512-qrPaCSo9c8RHNRHIotaufGbuOBN8rtdC4QrrFFc43vyWCCz7Kl7GL1PGaXtMGQZUXrkCjNEgxDfmAuAabr/rlw==}
|
||||
dev: false
|
||||
|
||||
/babel-plugin-transform-async-to-promises@0.8.18:
|
||||
resolution: {integrity: sha512-WpOrF76nUHijnNn10eBGOHZmXQC8JYRME9rOLxStOga7Av2VO53ehVFvVNImMksVtQuL2/7ZNxEgxnx7oo/3Hw==}
|
||||
dev: true
|
||||
@@ -8970,22 +8846,6 @@ packages:
|
||||
engines: {node: '>=4'}
|
||||
dev: true
|
||||
|
||||
/console-feed@3.5.0(jquery@3.7.0)(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-2N5b37yH0HeaqbBDsHBx0jEy3qvhTGA1dVdGyEM6C1NQhVmIX+ToU6Rt/uo86K0lLs4Lg1orC940YSn+Z3kk5g==}
|
||||
peerDependencies:
|
||||
react: ^15.x || ^16.x || ^17.x || ^18.x
|
||||
dependencies:
|
||||
'@emotion/core': 10.3.1(react@18.2.0)
|
||||
'@emotion/styled': 10.3.0(@emotion/core@10.3.1)(react@18.2.0)
|
||||
emotion-theming: 10.3.0(@emotion/core@10.3.1)(react@18.2.0)
|
||||
linkifyjs: 2.1.9(jquery@3.7.0)(react-dom@18.2.0)(react@18.2.0)
|
||||
react: 18.2.0
|
||||
react-inspector: 5.1.1(react@18.2.0)
|
||||
transitivePeerDependencies:
|
||||
- jquery
|
||||
- react-dom
|
||||
dev: false
|
||||
|
||||
/constants-browserify@1.0.0:
|
||||
resolution: {integrity: sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==}
|
||||
dev: true
|
||||
@@ -9004,6 +8864,7 @@ packages:
|
||||
|
||||
/convert-source-map@1.9.0:
|
||||
resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==}
|
||||
dev: true
|
||||
|
||||
/convert-source-map@2.0.0:
|
||||
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
|
||||
@@ -9089,17 +8950,6 @@ packages:
|
||||
parse-json: 4.0.0
|
||||
dev: true
|
||||
|
||||
/cosmiconfig@6.0.0:
|
||||
resolution: {integrity: sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==}
|
||||
engines: {node: '>=8'}
|
||||
dependencies:
|
||||
'@types/parse-json': 4.0.0
|
||||
import-fresh: 3.3.0
|
||||
parse-json: 5.2.0
|
||||
path-type: 4.0.0
|
||||
yaml: 1.10.2
|
||||
dev: false
|
||||
|
||||
/cosmiconfig@7.1.0:
|
||||
resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==}
|
||||
engines: {node: '>=10'}
|
||||
@@ -9507,10 +9357,6 @@ packages:
|
||||
cssom: 0.3.8
|
||||
dev: true
|
||||
|
||||
/csstype@2.6.21:
|
||||
resolution: {integrity: sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==}
|
||||
dev: false
|
||||
|
||||
/csstype@3.1.1:
|
||||
resolution: {integrity: sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==}
|
||||
|
||||
@@ -10065,19 +9911,6 @@ packages:
|
||||
engines: {node: '>= 4'}
|
||||
dev: true
|
||||
|
||||
/emotion-theming@10.3.0(@emotion/core@10.3.1)(react@18.2.0):
|
||||
resolution: {integrity: sha512-mXiD2Oj7N9b6+h/dC6oLf9hwxbtKHQjoIqtodEyL8CpkN4F3V4IK/BT4D0C7zSs4BBFOu4UlPJbvvBLa88SGEA==}
|
||||
peerDependencies:
|
||||
'@emotion/core': ^10.0.27
|
||||
react: '>=16.3.0'
|
||||
dependencies:
|
||||
'@babel/runtime': 7.21.0
|
||||
'@emotion/core': 10.3.1(react@18.2.0)
|
||||
'@emotion/weak-memoize': 0.2.5
|
||||
hoist-non-react-statics: 3.3.2
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/encodeurl@1.0.2:
|
||||
resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==}
|
||||
engines: {node: '>= 0.8'}
|
||||
@@ -10192,6 +10025,7 @@ packages:
|
||||
resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
|
||||
dependencies:
|
||||
is-arrayish: 0.2.1
|
||||
dev: true
|
||||
|
||||
/error-stack-parser@2.1.4:
|
||||
resolution: {integrity: sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==}
|
||||
@@ -11618,10 +11452,6 @@ packages:
|
||||
pkg-dir: 4.2.0
|
||||
dev: true
|
||||
|
||||
/find-root@1.1.0:
|
||||
resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==}
|
||||
dev: false
|
||||
|
||||
/find-up@3.0.0:
|
||||
resolution: {integrity: sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==}
|
||||
engines: {node: '>=6'}
|
||||
@@ -12861,6 +12691,7 @@ packages:
|
||||
|
||||
/is-arrayish@0.2.1:
|
||||
resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==}
|
||||
dev: true
|
||||
|
||||
/is-arrayish@0.3.2:
|
||||
resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==}
|
||||
@@ -12996,13 +12827,6 @@ packages:
|
||||
engines: {node: '>=8'}
|
||||
hasBin: true
|
||||
|
||||
/is-dom@1.1.0:
|
||||
resolution: {integrity: sha512-u82f6mvhYxRPKpw8V1N0W8ce1xXwOrQtgGcxl6UCL5zBmZu3is/18K0rR7uFCnMDuAsS/3W54mGL4vsaFUQlEQ==}
|
||||
dependencies:
|
||||
is-object: 1.0.2
|
||||
is-window: 1.0.2
|
||||
dev: false
|
||||
|
||||
/is-extendable@0.1.1:
|
||||
resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -13131,10 +12955,6 @@ packages:
|
||||
resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
/is-object@1.0.2:
|
||||
resolution: {integrity: sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==}
|
||||
dev: false
|
||||
|
||||
/is-path-cwd@2.2.0:
|
||||
resolution: {integrity: sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==}
|
||||
engines: {node: '>=6'}
|
||||
@@ -13262,10 +13082,6 @@ packages:
|
||||
dependencies:
|
||||
call-bind: 1.0.2
|
||||
|
||||
/is-window@1.0.2:
|
||||
resolution: {integrity: sha512-uj00kdXyZb9t9RcAUAwMZAnkBUwdYGhYlt7djMXhfyhUCzwNba50tIiBKR7q0l7tdoBtFVw/3JmLY6fI3rmZmg==}
|
||||
dev: false
|
||||
|
||||
/is-windows@1.0.2:
|
||||
resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -13940,10 +13756,6 @@ packages:
|
||||
engines: {node: '>=10'}
|
||||
dev: true
|
||||
|
||||
/jquery@3.7.0:
|
||||
resolution: {integrity: sha512-umpJ0/k8X0MvD1ds0P9SfowREz2LenHsQaxSohMZ5OMNEU2r0tf8pdeEFTHMFxWVxKNyU9rTtK3CWzUCTKJUeQ==}
|
||||
dev: false
|
||||
|
||||
/js-cookie@2.2.1:
|
||||
resolution: {integrity: sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==}
|
||||
dev: false
|
||||
@@ -14255,6 +14067,7 @@ packages:
|
||||
|
||||
/lines-and-columns@1.2.4:
|
||||
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
|
||||
dev: true
|
||||
|
||||
/linkify-it@4.0.1:
|
||||
resolution: {integrity: sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==}
|
||||
@@ -14262,18 +14075,6 @@ packages:
|
||||
uc.micro: 1.0.6
|
||||
dev: false
|
||||
|
||||
/linkifyjs@2.1.9(jquery@3.7.0)(react-dom@18.2.0)(react@18.2.0):
|
||||
resolution: {integrity: sha512-74ivurkK6WHvHFozVaGtQWV38FzBwSTGNmJolEgFp7QgR2bl6ArUWlvT4GcHKbPe1z3nWYi+VUdDZk16zDOVug==}
|
||||
peerDependencies:
|
||||
jquery: '>= 1.11.0'
|
||||
react: '>= 0.14.0'
|
||||
react-dom: '>= 0.14.0'
|
||||
dependencies:
|
||||
jquery: 3.7.0
|
||||
react: 18.2.0
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/listify@1.0.3:
|
||||
resolution: {integrity: sha512-083swF7iH7bx8666zdzBColpgEuy46HjN3r1isD4zV6Ix7FuHfb/2/WVnl4CH8hjuoWeFF7P5KkKNXUnJCFEJg==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -16481,6 +16282,7 @@ packages:
|
||||
error-ex: 1.3.2
|
||||
json-parse-even-better-errors: 2.3.1
|
||||
lines-and-columns: 1.2.4
|
||||
dev: true
|
||||
|
||||
/parse-passwd@1.0.0:
|
||||
resolution: {integrity: sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==}
|
||||
@@ -18105,17 +17907,6 @@ packages:
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/react-inspector@5.1.1(react@18.2.0):
|
||||
resolution: {integrity: sha512-GURDaYzoLbW8pMGXwYPDBIv6nqei4kK7LPRZ9q9HCZF54wqXz/dnylBp/kfE9XmekBhHvLDdcYeyIwSrvtOiWg==}
|
||||
peerDependencies:
|
||||
react: ^16.8.4 || ^17.0.0
|
||||
dependencies:
|
||||
'@babel/runtime': 7.21.0
|
||||
is-dom: 1.1.0
|
||||
prop-types: 15.8.1
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/react-is@16.13.1:
|
||||
resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==}
|
||||
|
||||
@@ -19407,6 +19198,7 @@ packages:
|
||||
/source-map@0.5.7:
|
||||
resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: true
|
||||
|
||||
/source-map@0.6.1:
|
||||
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
|
||||
@@ -20335,6 +20127,7 @@ packages:
|
||||
/to-fast-properties@2.0.0:
|
||||
resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
|
||||
engines: {node: '>=4'}
|
||||
dev: true
|
||||
|
||||
/to-object-path@0.3.0:
|
||||
resolution: {integrity: sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==}
|
||||
@@ -22024,6 +21817,7 @@ packages:
|
||||
/yaml@1.10.2:
|
||||
resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==}
|
||||
engines: {node: '>= 6'}
|
||||
dev: true
|
||||
|
||||
/yaml@2.1.3:
|
||||
resolution: {integrity: sha512-AacA8nRULjKMX2DvWvOAdBZMOfQlypSFkjcOcu9FalllIDJ1kvlREzcdIZmidQUqqeMv7jorHjq2HlLv/+c2lg==}
|
||||
|
||||
Reference in New Issue
Block a user