Merge branch 'main' of github.com:formbricks/formbricks into patch/add-overflow-to-survey

This commit is contained in:
Johannes
2023-06-12 13:57:47 +02:00
26 changed files with 636 additions and 339 deletions

View File

@@ -14,6 +14,7 @@ Fixes # (issue)
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] Chore (refactoring code, technical debt, workflow improvements)
- [ ] Enhancement (small improvements)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] This change adds a new database migration

View File

@@ -18,7 +18,6 @@ export default function FormbricksClient({ session }) {
formbricks.init({
environmentId: process.env.NEXT_PUBLIC_FORMBRICKS_ENVIRONMENT_ID || "",
apiHost: process.env.NEXT_PUBLIC_FORMBRICKS_API_HOST || "",
logLevel: "debug",
});
formbricks.setUserId(session.user.id);
formbricks.setEmail(session.user.email);

View File

@@ -0,0 +1,39 @@
import React from "react";
import LogicEditor from "@/app/environments/[environmentId]/surveys/[surveyId]/edit/LogicEditor";
import UpdateQuestionId from "./UpdateQuestionId";
import { Question } from "@formbricks/types/questions";
import { Survey } from "@formbricks/types/surveys";
interface AdvancedSettingsProps {
question: Question;
questionIdx: number;
localSurvey: Survey;
updateQuestion: (questionIdx: number, updatedAttributes: any) => void;
}
export default function AdvancedSettings({
question,
questionIdx,
localSurvey,
updateQuestion,
}: AdvancedSettingsProps) {
return (
<div>
<div className="mb-4">
<LogicEditor
question={question}
updateQuestion={updateQuestion}
localSurvey={localSurvey}
questionIdx={questionIdx}
/>
</div>
<UpdateQuestionId
question={question}
questionIdx={questionIdx}
localSurvey={localSurvey}
updateQuestion={updateQuestion}
/>
</div>
);
}

View File

@@ -1,7 +1,7 @@
import type { MultipleChoiceMultiQuestion } from "@formbricks/types/questions";
import { Survey } from "@formbricks/types/surveys";
import { Button, Input, Label } from "@formbricks/ui";
import { TrashIcon } from "@heroicons/react/24/solid";
import { PlusIcon, TrashIcon } from "@heroicons/react/24/solid";
import { createId } from "@paralleldrive/cuid2";
import { cn } from "@formbricks/lib/cn";
import { useEffect, useRef, useState } from "react";
@@ -18,10 +18,10 @@ export default function MultipleChoiceMultiForm({
question,
questionIdx,
updateQuestion,
lastQuestion,
}: OpenQuestionFormProps): JSX.Element {
const lastChoiceRef = useRef<HTMLInputElement>(null);
const [isNew, setIsNew] = useState(true);
const [showSubheader, setShowSubheader] = useState(!!question.subheader);
const questionRef = useRef<HTMLInputElement>(null);
const updateChoice = (choiceIdx: number, updatedAttributes: any) => {
@@ -36,14 +36,19 @@ export default function MultipleChoiceMultiForm({
updateQuestion(questionIdx, { choices: newChoices });
};
const addChoice = () => {
const addChoice = (choiceIdx?: number) => {
setIsNew(false); // This question is no longer new.
let newChoices = !question.choices ? [] : question.choices;
const otherChoice = newChoices.find((choice) => choice.id === "other");
if (otherChoice) {
newChoices = newChoices.filter((choice) => choice.id !== "other");
}
newChoices.push({ id: createId(), label: "" });
const newChoice = { id: createId(), label: "" };
if (choiceIdx !== undefined) {
newChoices.splice(choiceIdx + 1, 0, newChoice);
} else {
newChoices.push(newChoice);
}
if (otherChoice) {
newChoices.push(otherChoice);
}
@@ -105,15 +110,32 @@ export default function MultipleChoiceMultiForm({
</div>
<div className="mt-3">
<Label htmlFor="subheader">Description</Label>
<div className="mt-2">
<Input
id="subheader"
name="subheader"
value={question.subheader}
onChange={(e) => updateQuestion(questionIdx, { subheader: e.target.value })}
/>
</div>
{showSubheader && (
<>
<Label htmlFor="subheader">Description</Label>
<div className="mt-2 inline-flex w-full items-center">
<Input
id="subheader"
name="subheader"
value={question.subheader}
onChange={(e) => updateQuestion(questionIdx, { subheader: e.target.value })}
/>
<TrashIcon
className="ml-2 h-4 w-4 cursor-pointer text-slate-400 hover:text-slate-500"
onClick={() => {
setShowSubheader(false);
updateQuestion(questionIdx, { subheader: "" });
}}
/>
</div>
</>
)}
{!showSubheader && (
<Button size="sm" variant="minimal" type="button" onClick={() => setShowSubheader(true)}>
<PlusIcon className="mr-1 h-4 w-4" />
Add Description
</Button>
)}
</div>
<div className="mt-3">
@@ -137,36 +159,25 @@ export default function MultipleChoiceMultiForm({
onClick={() => deleteChoice(choiceIdx)}
/>
)}
{choice.id !== "other" && (
<PlusIcon
className="ml-2 h-4 w-4 cursor-pointer text-slate-400 hover:text-slate-500"
onClick={() => addChoice(choiceIdx)}
/>
)}
</div>
))}
<div className="flex items-center space-x-2">
<Button variant="secondary" size="sm" type="button" onClick={() => addChoice()}>
Add Option
</Button>
{question.choices.filter((c) => c.id === "other").length === 0 && (
<>
<p>or</p>
<Button size="sm" variant="minimal" type="button" onClick={() => addOther()}>
Add &quot;Other&quot; with specify
Add &quot;Other&quot;
</Button>
</>
)}
</div>
</div>
</div>
<div className="mt-3">
<Label htmlFor="buttonLabel">Button Label</Label>
<div className="mt-2">
<Input
id="buttonLabel"
name="buttonLabel"
value={question.buttonLabel}
placeholder={lastQuestion ? "Finish" : "Next"}
onChange={(e) => updateQuestion(questionIdx, { buttonLabel: e.target.value })}
/>
</div>
</div>
</form>
);
}

View File

@@ -1,7 +1,7 @@
import type { MultipleChoiceSingleQuestion } from "@formbricks/types/questions";
import { Survey } from "@formbricks/types/surveys";
import { Button, Input, Label } from "@formbricks/ui";
import { TrashIcon } from "@heroicons/react/24/solid";
import { TrashIcon, PlusIcon } from "@heroicons/react/24/solid";
import { createId } from "@paralleldrive/cuid2";
import { cn } from "@formbricks/lib/cn";
import { useEffect, useRef, useState } from "react";
@@ -18,10 +18,10 @@ export default function MultipleChoiceSingleForm({
question,
questionIdx,
updateQuestion,
lastQuestion,
}: OpenQuestionFormProps): JSX.Element {
const lastChoiceRef = useRef<HTMLInputElement>(null);
const [isNew, setIsNew] = useState(true);
const [showSubheader, setShowSubheader] = useState(!!question.subheader);
const questionRef = useRef<HTMLInputElement>(null);
const updateChoice = (choiceIdx: number, updatedAttributes: any) => {
@@ -36,14 +36,19 @@ export default function MultipleChoiceSingleForm({
updateQuestion(questionIdx, { choices: newChoices });
};
const addChoice = () => {
const addChoice = (choiceIdx?: number) => {
setIsNew(false); // This question is no longer new.
let newChoices = !question.choices ? [] : question.choices;
const otherChoice = newChoices.find((choice) => choice.id === "other");
if (otherChoice) {
newChoices = newChoices.filter((choice) => choice.id !== "other");
}
newChoices.push({ id: createId(), label: "" });
const newChoice = { id: createId(), label: "" };
if (choiceIdx !== undefined) {
newChoices.splice(choiceIdx + 1, 0, newChoice);
} else {
newChoices.push(newChoice);
}
if (otherChoice) {
newChoices.push(otherChoice);
}
@@ -105,15 +110,32 @@ export default function MultipleChoiceSingleForm({
</div>
<div className="mt-3">
<Label htmlFor="subheader">Description</Label>
<div className="mt-2">
<Input
id="subheader"
name="subheader"
value={question.subheader}
onChange={(e) => updateQuestion(questionIdx, { subheader: e.target.value })}
/>
</div>
{showSubheader && (
<>
<Label htmlFor="subheader">Description</Label>
<div className="mt-2 inline-flex w-full items-center">
<Input
id="subheader"
name="subheader"
value={question.subheader}
onChange={(e) => updateQuestion(questionIdx, { subheader: e.target.value })}
/>
<TrashIcon
className="ml-2 h-4 w-4 cursor-pointer text-slate-400 hover:text-slate-500"
onClick={() => {
setShowSubheader(false);
updateQuestion(questionIdx, { subheader: "" });
}}
/>
</div>
</>
)}
{!showSubheader && (
<Button size="sm" variant="minimal" type="button" onClick={() => setShowSubheader(true)}>
<PlusIcon className="mr-1 h-4 w-4" />
Add Description
</Button>
)}
</div>
<div className="mt-3">
@@ -137,36 +159,23 @@ export default function MultipleChoiceSingleForm({
onClick={() => deleteChoice(choiceIdx)}
/>
)}
{choice.id !== "other" && (
<PlusIcon
className="ml-2 h-4 w-4 cursor-pointer text-slate-400 hover:text-slate-500"
onClick={() => addChoice(choiceIdx)}
/>
)}
</div>
))}
<div className="flex items-center space-x-2">
<Button variant="secondary" size="sm" type="button" onClick={() => addChoice()}>
Add Option
</Button>
{question.choices.filter((c) => c.id === "other").length === 0 && (
<>
<p>or</p>
<Button size="sm" variant="minimal" type="button" onClick={() => addOther()}>
Add &quot;Other&quot; with specify
</Button>
</>
<Button size="sm" variant="minimal" type="button" onClick={() => addOther()}>
Add &quot;Other&quot;
</Button>
)}
</div>
</div>
</div>
<div className="mt-3">
<Label htmlFor="buttonLabel">Button Label</Label>
<div className="mt-2">
<Input
id="buttonLabel"
name="buttonLabel"
value={question.buttonLabel}
placeholder={lastQuestion ? "Finish" : "Next"}
onChange={(e) => updateQuestion(questionIdx, { buttonLabel: e.target.value })}
/>
</div>
</div>
</form>
);
}

View File

@@ -1,6 +1,8 @@
import type { NPSQuestion } from "@formbricks/types/questions";
import { Survey } from "@formbricks/types/surveys";
import { Input, Label } from "@formbricks/ui";
import { Button, Input, Label } from "@formbricks/ui";
import { TrashIcon, PlusIcon } from "@heroicons/react/24/solid";
import { useState } from "react";
interface NPSQuestionFormProps {
localSurvey: Survey;
@@ -16,6 +18,8 @@ export default function NPSQuestionForm({
updateQuestion,
lastQuestion,
}: NPSQuestionFormProps): JSX.Element {
const [showSubheader, setShowSubheader] = useState(!!question.subheader);
return (
<form>
<div className="mt-3">
@@ -32,15 +36,32 @@ export default function NPSQuestionForm({
</div>
<div className="mt-3">
<Label htmlFor="subheader">Description</Label>
<div className="mt-2">
<Input
id="subheader"
name="subheader"
value={question.subheader}
onChange={(e) => updateQuestion(questionIdx, { subheader: e.target.value })}
/>
</div>
{showSubheader && (
<>
<Label htmlFor="subheader">Description</Label>
<div className="mt-2 inline-flex w-full items-center">
<Input
id="subheader"
name="subheader"
value={question.subheader}
onChange={(e) => updateQuestion(questionIdx, { subheader: e.target.value })}
/>
<TrashIcon
className="ml-2 h-4 w-4 cursor-pointer text-slate-400 hover:text-slate-500"
onClick={() => {
setShowSubheader(false);
updateQuestion(questionIdx, { subheader: "" });
}}
/>
</div>
</>
)}
{!showSubheader && (
<Button size="sm" variant="minimal" type="button" onClick={() => setShowSubheader(true)}>
<PlusIcon className="mr-1 h-4 w-4" />
Add Description
</Button>
)}
</div>
<div className="mt-3 flex justify-between">

View File

@@ -1,6 +1,8 @@
import type { OpenTextQuestion } from "@formbricks/types/questions";
import { Survey } from "@formbricks/types/surveys";
import { Input, Label } from "@formbricks/ui";
import { Button, Input, Label } from "@formbricks/ui";
import { TrashIcon, PlusIcon } from "@heroicons/react/24/solid";
import { useState } from "react";
interface OpenQuestionFormProps {
localSurvey: Survey;
@@ -14,8 +16,9 @@ export default function OpenQuestionForm({
question,
questionIdx,
updateQuestion,
lastQuestion,
}: OpenQuestionFormProps): JSX.Element {
const [showSubheader, setShowSubheader] = useState(!!question.subheader);
return (
<form>
<div className="mt-3">
@@ -32,15 +35,32 @@ export default function OpenQuestionForm({
</div>
<div className="mt-3">
<Label htmlFor="subheader">Description</Label>
<div className="mt-2">
<Input
id="subheader"
name="subheader"
value={question.subheader}
onChange={(e) => updateQuestion(questionIdx, { subheader: e.target.value })}
/>
</div>
{showSubheader && (
<>
<Label htmlFor="subheader">Description</Label>
<div className="mt-2 inline-flex w-full items-center">
<Input
id="subheader"
name="subheader"
value={question.subheader}
onChange={(e) => updateQuestion(questionIdx, { subheader: e.target.value })}
/>
<TrashIcon
className="ml-2 h-4 w-4 cursor-pointer text-slate-400 hover:text-slate-500"
onClick={() => {
setShowSubheader(false);
updateQuestion(questionIdx, { subheader: "" });
}}
/>
</div>
</>
)}
{!showSubheader && (
<Button size="sm" variant="minimal" type="button" onClick={() => setShowSubheader(true)}>
<PlusIcon className="mr-1 h-4 w-4" />
Add Description
</Button>
)}
</div>
<div className="mt-3">
@@ -54,19 +74,6 @@ export default function OpenQuestionForm({
/>
</div>
</div>
<div className="mt-3">
<Label htmlFor="buttonLabel">Button Label</Label>
<div className="mt-2">
<Input
id="buttonLabel"
name="buttonLabel"
value={question.buttonLabel}
placeholder={lastQuestion ? "Finish" : "Next"}
onChange={(e) => updateQuestion(questionIdx, { buttonLabel: e.target.value })}
/>
</div>
</div>
</form>
);
}

View File

@@ -1,11 +1,10 @@
"use client";
import LogicEditor from "@/app/environments/[environmentId]/surveys/[surveyId]/edit/LogicEditor";
import { getQuestionTypeName } from "@/lib/questions";
import { cn } from "@formbricks/lib/cn";
import type { Question } from "@formbricks/types/questions";
import type { Survey } from "@formbricks/types/surveys";
import { Label, Switch } from "@formbricks/ui";
import { Input, Label, Switch } from "@formbricks/ui";
import {
ChatBubbleBottomCenterTextIcon,
ChevronDownIcon,
@@ -24,9 +23,9 @@ import MultipleChoiceMultiForm from "./MultipleChoiceMultiForm";
import MultipleChoiceSingleForm from "./MultipleChoiceSingleForm";
import NPSQuestionForm from "./NPSQuestionForm";
import OpenQuestionForm from "./OpenQuestionForm";
import QuestionDropdown from "./QuestionDropdown";
import QuestionDropdown from "./QuestionMenu";
import RatingQuestionForm from "./RatingQuestionForm";
import UpdateQuestionId from "./UpdateQuestionId";
import AdvancedSettings from "@/app/environments/[environmentId]/surveys/[surveyId]/edit/AdvancedSettings";
interface QuestionCardProps {
localSurvey: Survey;
@@ -54,7 +53,7 @@ export default function QuestionCard({
lastQuestion,
}: QuestionCardProps) {
const open = activeQuestionId === question.id;
const [openAdvanced, setOpenAdvanced] = useState(false);
const [openAdvanced, setOpenAdvanced] = useState(question.logic && question.logic.length > 0);
return (
<Draggable draggableId={question.id} index={questionIdx}>
{(provided) => (
@@ -116,19 +115,6 @@ export default function QuestionCard({
</div>
<div className="flex items-center space-x-2">
{open && (
<div className="flex items-center space-x-2">
<Label htmlFor="required-toggle">Required</Label>
<Switch
id="required-toggle"
checked={question.required}
onClick={(e) => {
e.stopPropagation();
updateQuestion(questionIdx, { required: !question.required });
}}
/>
</div>
)}
<QuestionDropdown
questionIdx={questionIdx}
lastQuestion={lastQuestion}
@@ -189,15 +175,9 @@ export default function QuestionCard({
lastQuestion={lastQuestion}
/>
) : null}
<div className="mt-4 border-t border-slate-200">
<LogicEditor
question={question}
updateQuestion={updateQuestion}
localSurvey={localSurvey}
questionIdx={questionIdx}
/>
<div className="mt-4">
<Collapsible.Root open={openAdvanced} onOpenChange={setOpenAdvanced} className="mt-5">
<Collapsible.CollapsibleTrigger className="flex items-center text-xs text-slate-700 ">
<Collapsible.CollapsibleTrigger className="flex items-center text-xs text-slate-700">
{openAdvanced ? (
<ChevronDownIcon className="mr-1 h-4 w-3" />
) : (
@@ -206,19 +186,48 @@ export default function QuestionCard({
{openAdvanced ? "Hide Advanced Settings" : "Show Advanced Settings"}
</Collapsible.CollapsibleTrigger>
<Collapsible.CollapsibleContent className="space-y-2">
<div className="mt-3">
<UpdateQuestionId
question={question}
questionIdx={questionIdx}
localSurvey={localSurvey}
updateQuestion={updateQuestion}
/>
</div>
<Collapsible.CollapsibleContent className="space-y-4">
{question.type !== "nps" && question.type !== "rating" && question.type !== "cta" ? (
<div className="mt-4">
<Label htmlFor="buttonLabel">Button Label</Label>
<div className="mt-2">
<Input
id="buttonLabel"
name="buttonLabel"
value={question.buttonLabel}
placeholder={lastQuestion ? "Finish" : "Next"}
onChange={(e) => updateQuestion(questionIdx, { buttonLabel: e.target.value })}
/>
</div>
</div>
) : null}
<AdvancedSettings
question={question}
questionIdx={questionIdx}
localSurvey={localSurvey}
updateQuestion={updateQuestion}
/>
</Collapsible.CollapsibleContent>
</Collapsible.Root>
</div>
</Collapsible.CollapsibleContent>
{open && (
<div className="m-4 mt-0 border-t border-slate-200">
<div className="m-4 mr-0 flex items-center justify-end space-x-2">
<Label htmlFor="required-toggle">Required</Label>
<Switch
id="required-toggle"
checked={question.required}
onClick={(e) => {
e.stopPropagation();
updateQuestion(questionIdx, { required: !question.required });
}}
/>
</div>
</div>
)}
</Collapsible.Root>
</div>
)}

View File

@@ -1,71 +0,0 @@
"use client";
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@formbricks/ui";
import {
EllipsisHorizontalIcon,
ArrowUpIcon,
ArrowDownIcon,
TrashIcon,
DocumentDuplicateIcon,
} from "@heroicons/react/24/solid";
interface QuestionDropdownProps {
questionIdx: number;
lastQuestion: boolean;
duplicateQuestion: (questionIdx: number) => void;
deleteQuestion: (questionIdx: number) => void;
moveQuestion: (questionIdx: number, up: boolean) => void;
}
export default function QuestionDropdown({
questionIdx,
lastQuestion,
duplicateQuestion,
deleteQuestion,
moveQuestion,
}: QuestionDropdownProps) {
return (
<DropdownMenu>
<DropdownMenuTrigger>
<EllipsisHorizontalIcon className="h-5 w-5 text-slate-600 focus:outline-none active:outline-none" />
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem
className="justify-between"
onClick={(e) => {
e.stopPropagation();
moveQuestion(questionIdx, true);
}}
disabled={questionIdx == 0}>
Move up <ArrowUpIcon className="ml-3 h-4" />
</DropdownMenuItem>
<DropdownMenuItem
className="justify-between"
onClick={(e) => {
e.stopPropagation();
moveQuestion(questionIdx, false);
}}
disabled={lastQuestion}>
Move down
<ArrowDownIcon className="h-4" />
</DropdownMenuItem>
<DropdownMenuItem
className="justify-between"
onClick={(e) => {
e.stopPropagation();
duplicateQuestion(questionIdx);
}}>
Duplicate <DocumentDuplicateIcon className="ml-3 h-4" />
</DropdownMenuItem>
<DropdownMenuItem
className="justify-between"
onClick={(e) => {
e.stopPropagation();
deleteQuestion(questionIdx);
}}>
Delete <TrashIcon className="ml-3 h-4" />
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}

View File

@@ -0,0 +1,60 @@
"use client";
import { ArrowUpIcon, ArrowDownIcon, TrashIcon, DocumentDuplicateIcon } from "@heroicons/react/24/solid";
interface QuestionDropdownProps {
questionIdx: number;
lastQuestion: boolean;
duplicateQuestion: (questionIdx: number) => void;
deleteQuestion: (questionIdx: number) => void;
moveQuestion: (questionIdx: number, up: boolean) => void;
}
export default function QuestionActions({
questionIdx,
lastQuestion,
duplicateQuestion,
deleteQuestion,
moveQuestion,
}: QuestionDropdownProps) {
return (
<div className="flex space-x-4">
<ArrowUpIcon
className={`h-4 cursor-pointer text-slate-500 hover:text-slate-600 ${
questionIdx === 0 ? "opacity-50" : ""
}`}
onClick={(e) => {
if (questionIdx !== 0) {
e.stopPropagation();
moveQuestion(questionIdx, true);
}
}}
/>
<ArrowDownIcon
className={`h-4 cursor-pointer text-slate-500 hover:text-slate-600 ${
lastQuestion ? "opacity-50" : ""
}`}
onClick={(e) => {
if (!lastQuestion) {
e.stopPropagation();
moveQuestion(questionIdx, false);
}
}}
/>
<DocumentDuplicateIcon
className="h-4 cursor-pointer text-slate-500 hover:text-slate-600"
onClick={(e) => {
e.stopPropagation();
duplicateQuestion(questionIdx);
}}
/>
<TrashIcon
className="h-4 cursor-pointer text-slate-500 hover:text-slate-600"
onClick={(e) => {
e.stopPropagation();
deleteQuestion(questionIdx);
}}
/>
</div>
);
}

View File

@@ -1,8 +1,10 @@
import type { RatingQuestion } from "@formbricks/types/questions";
import type { Survey } from "@formbricks/types/surveys";
import { Input, Label } from "@formbricks/ui";
import { Button, Input, Label } from "@formbricks/ui";
import { FaceSmileIcon, HashtagIcon, StarIcon } from "@heroicons/react/24/outline";
import Dropdown from "./RatingTypeDropdown";
import { TrashIcon, PlusIcon } from "@heroicons/react/24/solid";
import { useState } from "react";
interface RatingQuestionFormProps {
localSurvey: Survey;
@@ -18,6 +20,8 @@ export default function RatingQuestionForm({
updateQuestion,
lastQuestion,
}: RatingQuestionFormProps) {
const [showSubheader, setShowSubheader] = useState(!!question.subheader);
return (
<form>
<div className="mt-3">
@@ -34,15 +38,32 @@ export default function RatingQuestionForm({
</div>
<div className="mt-3">
<Label htmlFor="subheader">Description</Label>
<div className="mt-2">
<Input
id="subheader"
name="subheader"
value={question.subheader}
onChange={(e) => updateQuestion(questionIdx, { subheader: e.target.value })}
/>
</div>
{showSubheader && (
<>
<Label htmlFor="subheader">Description</Label>
<div className="mt-2 inline-flex w-full items-center">
<Input
id="subheader"
name="subheader"
value={question.subheader}
onChange={(e) => updateQuestion(questionIdx, { subheader: e.target.value })}
/>
<TrashIcon
className="ml-2 h-4 w-4 cursor-pointer text-slate-400 hover:text-slate-500"
onClick={() => {
setShowSubheader(false);
updateQuestion(questionIdx, { subheader: "" });
}}
/>
</div>
</>
)}
{!showSubheader && (
<Button size="sm" variant="minimal" type="button" onClick={() => setShowSubheader(true)}>
<PlusIcon className="mr-1 h-4 w-4" />
Add Description
</Button>
)}
</div>
<div className="mt-3 flex justify-between gap-8">

View File

@@ -22,7 +22,7 @@ export default function UpdateQuestionId({ localSurvey, question, questionIdx, u
return (
<div>
<Label className="block" htmlFor="questionId">
<Label htmlFor="questionId">
Question ID
</Label>
<div className="mt-2 inline-flex w-full">

View File

@@ -146,6 +146,7 @@ export default function SummaryMetadata({ surveyId, environmentId }) {
<SurveyStatusDropdown surveyId={surveyId} environmentId={environmentId} />
) : null}
<Button
variant="darkCTA"
className="h-full w-full px-3 lg:px-6"
href={`/environments/${environmentId}/surveys/${surveyId}/edit`}>
<PencilSquareIcon className="mr-2 h-5 w-5 text-white" />

View File

@@ -203,7 +203,7 @@ export default function LinkSurvey({ survey }: LinkSurveyProps) {
loadingElement && "animate-pulse opacity-60",
"flex h-full flex-1 items-center overflow-y-auto bg-white"
)}>
<ContentWrapper className="w-full md:max-w-lg">
<ContentWrapper className="h-full w-full md:max-w-lg">
{isPreview && (
<div className="absolute left-0 top-0 flex w-full items-center justify-between bg-slate-600 p-2 px-4 text-center text-sm text-white shadow-sm">
<div className="w-20"></div>

View File

@@ -34,6 +34,7 @@ export default function OpenTextQuestion({
<Subheader subheader={question.subheader} questionId={question.id} />
<div className="mt-4">
<textarea
autoFocus
rows={3}
name={question.id}
id={question.id}

View File

@@ -125,7 +125,9 @@ export const sendResponseFinishedEmail = async (
const personEmail = person?.attributes?.find((a) => a.attributeClass?.name === "email")?.value;
await sendEmail({
to: email,
subject: `A response for ${survey.name} was completed ✅`,
subject: personEmail
? `${personEmail} just completed your ${survey.name} survey ✅`
: `A response for ${survey.name} was completed ✅`,
replyTo: personEmail || process.env.MAIL_FROM,
html: withEmailTemplate(`<h1>Survey completed</h1>Someone just completed your survey "${survey.name}"<br/>
@@ -134,8 +136,6 @@ export const sendResponseFinishedEmail = async (
${getQuestionResponseMapping(survey, response)
.map((question) => `<p><strong>${question.question}</strong></p><p>${question.answer}</p>`)
.join("")}
<hr/>

View File

@@ -24,6 +24,8 @@ export const questionTypes: QuestionType[] = [
description: "A single line of text",
icon: ChatBubbleBottomCenterTextIcon,
preset: {
headline: "Who let the dogs out?",
subheader: "Who? Who? Who?",
placeholder: "Type your answer here...",
},
},

View File

@@ -1,9 +1,10 @@
{
"name": "@formbricks/api",
"version": "1.0.0",
"version": "0.1.0",
"description": "A Typescript API-wrapper for managing the Formbricks Client API.",
"license": "MIT",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"sideEffects": false,
"files": [

View File

@@ -1,8 +1,7 @@
{
"name": "@formbricks/database",
"private": true,
"version": "1.0.0",
"license": "MIT",
"version": "0.1.0",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",

View File

@@ -1,9 +1,10 @@
{
"name": "@formbricks/errors",
"description": "A helper package containing general error classes for Formbricks",
"private": true,
"version": "1.0.0",
"license": "MIT",
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"sideEffects": false,
"files": [
@@ -14,8 +15,8 @@
"dev": "tsup --watch",
"lint": "eslint ./src --fix",
"clean": "rimraf .turbo node_modules dist"
},
"devDependencies": {
},
"devDependencies": {
"@formbricks/tsconfig": "workspace:*",
"eslint": "^8.41.0",
"eslint-config-formbricks": "workspace:*",

View File

@@ -13,7 +13,7 @@
setTimeout(function () {
window.formbricks = window.js;
window.formbricks.init({
environmentId: "clham12520003yz4zeng786vq",
environmentId: "clhkhwyc60003yz5rpgsgrebq",
apiHost: "http://localhost:3000",
logLevel: "debug",
});

View File

@@ -1,6 +1,7 @@
{
"name": "@formbricks/js",
"version": "0.1.19",
"license": "MIT",
"version": "0.1.20",
"description": "Formbricks-js allows you to connect your app to Formbricks, display surveys and trigger events.",
"keywords": [
"Formbricks",
@@ -22,10 +23,7 @@
},
"scripts": {
"clean": "rimraf .turbo node_modules dist",
"dev": "microbundle watch --css inline",
"start": "cross-env NODE_OPTIONS=--openssl-legacy-provider preact watch",
"build:widget": "microbundle --css inline",
"build:lib": "microbundle build -i src/component.tsx",
"dev": "microbundle --css inline",
"lint": "eslint '{src,tests}/**/*.{ts,tsx}'",
"test": "jest",
"build": "microbundle --css inline"
@@ -44,22 +42,19 @@
]
},
"author": "Formbricks <hola@formbricks.com>",
"license": "MIT",
"dependencies": {
"@formbricks/api": "workspace:*",
"@formbricks/errors": "workspace:*"
},
"dependencies": {},
"devDependencies": {
"@formbricks/api": "workspace:*",
"@formbricks/types": "workspace:*",
"@types/enzyme": "^3.10.13",
"@types/jest": "^29.5.2",
"@typescript-eslint/eslint-plugin": "^5.59.8",
"@typescript-eslint/parser": "^5.59.8",
"@typescript-eslint/eslint-plugin": "^5.59.9",
"@typescript-eslint/parser": "^5.59.9",
"autoprefixer": "^10.4.14",
"cross-env": "^7.0.3",
"enzyme": "^3.11.0",
"enzyme-adapter-preact-pure": "^4.1.0",
"eslint": "^8.41.0",
"eslint": "^8.42.0",
"eslint-config-formbricks": "workspace:*",
"eslint-config-preact": "^1.3.0",
"jest": "^29.5.0",
@@ -68,10 +63,10 @@
"postcss": "^8.4.24",
"preact": "10.15.1",
"preact-cli": "^3.4.5",
"preact-render-to-string": "^6.0.3",
"preact-render-to-string": "^6.1.0",
"rimraf": "^5.0.1",
"tailwindcss": "^3.3.2",
"typescript": "^5.0.4"
"typescript": "^5.1.3"
},
"jest": {
"preset": "jest-preset-preact",

View File

@@ -1,4 +1,4 @@
import { EnvironmentId, FormbricksAPI } from "@formbricks/api";
import { FormbricksAPI, EnvironmentId } from "@formbricks/api";
import { Config } from "./config";
export const getApi = (): FormbricksAPI => {

View File

@@ -19,6 +19,10 @@ export const renderWidget = (survey: Survey) => {
}
surveyRunning = true;
if (survey.delay) {
logger.debug(`Delaying survey by ${survey.delay} seconds.`);
}
setTimeout(() => {
render(
h(App, { config: config.get(), survey, closeSurvey, errorHandler: errorHandler.handle }),

View File

@@ -5,7 +5,6 @@
"version": "0.0.0",
"main": "./index.ts",
"types": "./index.ts",
"license": "MIT",
"scripts": {
"clean": "rimraf .turbo node_modules .next",
"lint": "eslint . --ext .ts,.js,.tsx,.jsx",

366
pnpm-lock.yaml generated
View File

@@ -468,7 +468,7 @@ importers:
version: 8.41.0
eslint-config-next:
specifier: ^13.4.4
version: 13.4.4(eslint@8.41.0)
version: 13.4.4(eslint@8.41.0)(typescript@5.1.3)
eslint-config-prettier:
specifier: ^8.8.0
version: 8.8.0(eslint@8.41.0)
@@ -484,14 +484,10 @@ importers:
version: 5.0.1
packages/js:
dependencies:
devDependencies:
'@formbricks/api':
specifier: workspace:*
version: link:../api
'@formbricks/errors':
specifier: workspace:*
version: link:../errors
devDependencies:
'@formbricks/types':
specifier: workspace:*
version: link:../types
@@ -502,11 +498,11 @@ importers:
specifier: ^29.5.2
version: 29.5.2
'@typescript-eslint/eslint-plugin':
specifier: ^5.59.8
version: 5.59.8(@typescript-eslint/parser@5.59.8)(eslint@8.41.0)(typescript@5.0.4)
specifier: ^5.59.9
version: 5.59.9(@typescript-eslint/parser@5.59.9)(eslint@8.42.0)(typescript@5.1.3)
'@typescript-eslint/parser':
specifier: ^5.59.8
version: 5.59.8(eslint@8.41.0)(typescript@5.0.4)
specifier: ^5.59.9
version: 5.59.9(eslint@8.42.0)(typescript@5.1.3)
autoprefixer:
specifier: ^10.4.14
version: 10.4.14(postcss@8.4.24)
@@ -520,20 +516,20 @@ importers:
specifier: ^4.1.0
version: 4.1.0(enzyme@3.11.0)(preact@10.15.1)
eslint:
specifier: ^8.41.0
version: 8.41.0
specifier: ^8.42.0
version: 8.42.0
eslint-config-formbricks:
specifier: workspace:*
version: link:../eslint-config-formbricks
eslint-config-preact:
specifier: ^1.3.0
version: 1.3.0(@typescript-eslint/eslint-plugin@5.59.8)(eslint@8.41.0)(jest@29.5.0)(typescript@5.0.4)
version: 1.3.0(@typescript-eslint/eslint-plugin@5.59.9)(eslint@8.42.0)(jest@29.5.0)(typescript@5.1.3)
jest:
specifier: ^29.5.0
version: 29.5.0
jest-preset-preact:
specifier: ^4.0.5
version: 4.0.5(jest@29.5.0)(preact-render-to-string@6.0.3)(preact@10.15.1)
version: 4.0.5(jest@29.5.0)(preact-render-to-string@6.1.0)(preact@10.15.1)
microbundle:
specifier: ^0.15.1
version: 0.15.1
@@ -545,10 +541,10 @@ importers:
version: 10.15.1
preact-cli:
specifier: ^3.4.5
version: 3.4.5(eslint@8.41.0)(preact-render-to-string@6.0.3)(preact@10.15.1)
version: 3.4.5(eslint@8.42.0)(preact-render-to-string@6.1.0)(preact@10.15.1)
preact-render-to-string:
specifier: ^6.0.3
version: 6.0.3(preact@10.15.1)
specifier: ^6.1.0
version: 6.1.0(preact@10.15.1)
rimraf:
specifier: ^5.0.1
version: 5.0.1
@@ -556,8 +552,8 @@ importers:
specifier: ^3.3.2
version: 3.3.2
typescript:
specifier: ^5.0.4
version: 5.0.4
specifier: ^5.1.3
version: 5.1.3
packages/lib:
devDependencies:
@@ -890,7 +886,7 @@ packages:
- supports-color
dev: true
/@babel/eslint-parser@7.19.1(@babel/core@7.20.12)(eslint@8.41.0):
/@babel/eslint-parser@7.19.1(@babel/core@7.20.12)(eslint@8.42.0):
resolution: {integrity: sha512-AqNf2QWt1rtu2/1rLswy6CDP7H9Oh3mMhk177Y67Rg8d7RD9WfOLLv8CGn6tisFvS2htm86yIe1yLF6I1UDaGQ==}
engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0}
peerDependencies:
@@ -899,7 +895,7 @@ packages:
dependencies:
'@babel/core': 7.20.12
'@nicolo-ribaudo/eslint-scope-5-internals': 5.1.1-v1
eslint: 8.41.0
eslint: 8.42.0
eslint-visitor-keys: 2.1.0
semver: 6.3.0
dev: true
@@ -2703,6 +2699,16 @@ packages:
eslint: 8.41.0
eslint-visitor-keys: 3.4.1
/@eslint-community/eslint-utils@4.2.0(eslint@8.42.0):
resolution: {integrity: sha512-gB8T4H4DEfX2IV9zGDJPOBgP1e/DbfCPDTtEqUMckpvzS1OYtva8JdFYBqMwYk7xAQ429WGF/UPqn8uQ//h2vQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
dependencies:
eslint: 8.42.0
eslint-visitor-keys: 3.4.1
dev: true
/@eslint-community/regexpp@4.4.0:
resolution: {integrity: sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ==}
engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
@@ -2749,6 +2755,11 @@ packages:
resolution: {integrity: sha512-LxcyMGxwmTh2lY9FwHPGWOHmYFCZvbrFCBZL4FzSSsxsRPuhrYUg/49/0KDfW8tnIEaEHtfmn6+NPN+1DqaNmA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
/@eslint/js@8.42.0:
resolution: {integrity: sha512-6SWlXpWU5AvId8Ac7zjzmIOqMOba/JWY8XZ4A7q7Gn1Vlfg/SFFIlrtHXt9nPn4op9ZPAkl91Jao+QQv3r/ukw==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dev: true
/@floating-ui/core@0.7.3:
resolution: {integrity: sha512-buc8BXHmG9l82+OQXOFU3Kr2XQx9ys01U/Q9HMIrZ300iLc8HLMgh7dcCqgYzAzf4BkoQvDcXf5Y+CuEZ5JBYg==}
dev: false
@@ -2826,6 +2837,17 @@ packages:
react: 18.2.0
dev: false
/@humanwhocodes/config-array@0.11.10:
resolution: {integrity: sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==}
engines: {node: '>=10.10.0'}
dependencies:
'@humanwhocodes/object-schema': 1.2.1
debug: 4.3.4
minimatch: 3.1.2
transitivePeerDependencies:
- supports-color
dev: true
/@humanwhocodes/config-array@0.11.8:
resolution: {integrity: sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==}
engines: {node: '>=10.10.0'}
@@ -5490,7 +5512,7 @@ packages:
tailwindcss: '>=3.0.0 || >= 3.0.0-alpha.1'
dependencies:
mini-svg-data-uri: 1.4.4
tailwindcss: 3.3.1(postcss@8.4.22)
tailwindcss: 3.3.1(postcss@8.4.21)
dev: true
/@tailwindcss/forms@0.5.3(tailwindcss@3.3.2):
@@ -6001,8 +6023,8 @@ packages:
'@types/yargs-parser': 21.0.0
dev: true
/@typescript-eslint/eslint-plugin@5.59.8(@typescript-eslint/parser@5.59.8)(eslint@8.41.0)(typescript@5.0.4):
resolution: {integrity: sha512-JDMOmhXteJ4WVKOiHXGCoB96ADWg9q7efPWHRViT/f09bA8XOMLAVHHju3l0MkZnG1izaWXYmgvQcUjTRcpShQ==}
/@typescript-eslint/eslint-plugin@5.59.9(@typescript-eslint/parser@5.59.9)(eslint@8.42.0)(typescript@5.1.3):
resolution: {integrity: sha512-4uQIBq1ffXd2YvF7MAvehWKW3zVv/w+mSfRAu+8cKbfj3nwzyqJLNcZJpQ/WZ1HLbJDiowwmQ6NO+63nCA+fqA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
'@typescript-eslint/parser': ^5.0.0
@@ -6013,30 +6035,30 @@ packages:
optional: true
dependencies:
'@eslint-community/regexpp': 4.4.0
'@typescript-eslint/parser': 5.59.8(eslint@8.41.0)(typescript@5.0.4)
'@typescript-eslint/scope-manager': 5.59.8
'@typescript-eslint/type-utils': 5.59.8(eslint@8.41.0)(typescript@5.0.4)
'@typescript-eslint/utils': 5.59.8(eslint@8.41.0)(typescript@5.0.4)
'@typescript-eslint/parser': 5.59.9(eslint@8.42.0)(typescript@5.1.3)
'@typescript-eslint/scope-manager': 5.59.9
'@typescript-eslint/type-utils': 5.59.9(eslint@8.42.0)(typescript@5.1.3)
'@typescript-eslint/utils': 5.59.9(eslint@8.42.0)(typescript@5.1.3)
debug: 4.3.4
eslint: 8.41.0
eslint: 8.42.0
grapheme-splitter: 1.0.4
ignore: 5.2.1
natural-compare-lite: 1.4.0
semver: 7.3.8
tsutils: 3.21.0(typescript@5.0.4)
typescript: 5.0.4
tsutils: 3.21.0(typescript@5.1.3)
typescript: 5.1.3
transitivePeerDependencies:
- supports-color
dev: true
/@typescript-eslint/experimental-utils@5.54.0(eslint@8.41.0)(typescript@5.0.4):
/@typescript-eslint/experimental-utils@5.54.0(eslint@8.42.0)(typescript@5.1.3):
resolution: {integrity: sha512-rRYECOTh5V3iWsrOzXi7h1jp3Bi9OkJHrb3wECi3DVqMGTilo9wAYmCbT+6cGdrzUY3MWcAa2mESM6FMik6tVw==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
dependencies:
'@typescript-eslint/utils': 5.54.0(eslint@8.41.0)(typescript@5.0.4)
eslint: 8.41.0
'@typescript-eslint/utils': 5.54.0(eslint@8.42.0)(typescript@5.1.3)
eslint: 8.42.0
transitivePeerDependencies:
- supports-color
- typescript
@@ -6062,7 +6084,7 @@ packages:
- supports-color
dev: false
/@typescript-eslint/parser@5.59.8(eslint@8.41.0)(typescript@5.0.4):
/@typescript-eslint/parser@5.59.8(eslint@8.41.0)(typescript@5.1.3):
resolution: {integrity: sha512-AnR19RjJcpjoeGojmwZtCwBX/RidqDZtzcbG3xHrmz0aHHoOcbWnpDllenRDmDvsV0RQ6+tbb09/kyc+UT9Orw==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
@@ -6074,12 +6096,33 @@ packages:
dependencies:
'@typescript-eslint/scope-manager': 5.59.8
'@typescript-eslint/types': 5.59.8
'@typescript-eslint/typescript-estree': 5.59.8(typescript@5.0.4)
'@typescript-eslint/typescript-estree': 5.59.8(typescript@5.1.3)
debug: 4.3.4
eslint: 8.41.0
typescript: 5.0.4
typescript: 5.1.3
transitivePeerDependencies:
- supports-color
dev: false
/@typescript-eslint/parser@5.59.9(eslint@8.42.0)(typescript@5.1.3):
resolution: {integrity: sha512-FsPkRvBtcLQ/eVK1ivDiNYBjn3TGJdXy2fhXX+rc7czWl4ARwnpArwbihSOHI2Peg9WbtGHrbThfBUkZZGTtvQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
typescript: '*'
peerDependenciesMeta:
typescript:
optional: true
dependencies:
'@typescript-eslint/scope-manager': 5.59.9
'@typescript-eslint/types': 5.59.9
'@typescript-eslint/typescript-estree': 5.59.9(typescript@5.1.3)
debug: 4.3.4
eslint: 8.42.0
typescript: 5.1.3
transitivePeerDependencies:
- supports-color
dev: true
/@typescript-eslint/scope-manager@5.54.0:
resolution: {integrity: sha512-VTPYNZ7vaWtYna9M4oD42zENOBrb+ZYyCNdFs949GcN8Miwn37b8b7eMj+EZaq7VK9fx0Jd+JhmkhjFhvnovhg==}
@@ -6103,9 +6146,18 @@ packages:
dependencies:
'@typescript-eslint/types': 5.59.8
'@typescript-eslint/visitor-keys': 5.59.8
dev: false
/@typescript-eslint/type-utils@5.59.8(eslint@8.41.0)(typescript@5.0.4):
resolution: {integrity: sha512-+5M518uEIHFBy3FnyqZUF3BMP+AXnYn4oyH8RF012+e7/msMY98FhGL5SrN29NQ9xDgvqCgYnsOiKp1VjZ/fpA==}
/@typescript-eslint/scope-manager@5.59.9:
resolution: {integrity: sha512-8RA+E+w78z1+2dzvK/tGZ2cpGigBZ58VMEHDZtpE1v+LLjzrYGc8mMaTONSxKyEkz3IuXFM0IqYiGHlCsmlZxQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dependencies:
'@typescript-eslint/types': 5.59.9
'@typescript-eslint/visitor-keys': 5.59.9
dev: true
/@typescript-eslint/type-utils@5.59.9(eslint@8.42.0)(typescript@5.1.3):
resolution: {integrity: sha512-ksEsT0/mEHg9e3qZu98AlSrONAQtrSTljL3ow9CGej8eRo7pe+yaC/mvTjptp23Xo/xIf2mLZKC6KPv4Sji26Q==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: '*'
@@ -6114,12 +6166,12 @@ packages:
typescript:
optional: true
dependencies:
'@typescript-eslint/typescript-estree': 5.59.8(typescript@5.0.4)
'@typescript-eslint/utils': 5.59.8(eslint@8.41.0)(typescript@5.0.4)
'@typescript-eslint/typescript-estree': 5.59.9(typescript@5.1.3)
'@typescript-eslint/utils': 5.59.9(eslint@8.42.0)(typescript@5.1.3)
debug: 4.3.4
eslint: 8.41.0
tsutils: 3.21.0(typescript@5.0.4)
typescript: 5.0.4
eslint: 8.42.0
tsutils: 3.21.0(typescript@5.1.3)
typescript: 5.1.3
transitivePeerDependencies:
- supports-color
dev: true
@@ -6137,8 +6189,14 @@ packages:
/@typescript-eslint/types@5.59.8:
resolution: {integrity: sha512-+uWuOhBTj/L6awoWIg0BlWy0u9TyFpCHrAuQ5bNfxDaZ1Ppb3mx6tUigc74LHcbHpOHuOTOJrBoAnhdHdaea1w==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dev: false
/@typescript-eslint/typescript-estree@5.54.0(typescript@5.0.4):
/@typescript-eslint/types@5.59.9:
resolution: {integrity: sha512-uW8H5NRgTVneSVTfiCVffBb8AbwWSKg7qcA4Ot3JI3MPCJGsB4Db4BhvAODIIYE5mNj7Q+VJkK7JxmRhk2Lyjw==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dev: true
/@typescript-eslint/typescript-estree@5.54.0(typescript@5.1.3):
resolution: {integrity: sha512-X2rJG97Wj/VRo5YxJ8Qx26Zqf0RRKsVHd4sav8NElhbZzhpBI8jU54i6hfo9eheumj4oO4dcRN1B/zIVEqR/MQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
@@ -6153,8 +6211,8 @@ packages:
globby: 11.1.0
is-glob: 4.0.3
semver: 7.3.8
tsutils: 3.21.0(typescript@5.0.4)
typescript: 5.0.4
tsutils: 3.21.0(typescript@5.1.3)
typescript: 5.1.3
transitivePeerDependencies:
- supports-color
dev: true
@@ -6180,7 +6238,7 @@ packages:
- supports-color
dev: false
/@typescript-eslint/typescript-estree@5.59.8(typescript@5.0.4):
/@typescript-eslint/typescript-estree@5.59.8(typescript@5.1.3):
resolution: {integrity: sha512-Jy/lPSDJGNow14vYu6IrW790p7HIf/SOV1Bb6lZ7NUkLc2iB2Z9elESmsaUtLw8kVqogSbtLH9tut5GCX1RLDg==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
@@ -6195,12 +6253,34 @@ packages:
globby: 11.1.0
is-glob: 4.0.3
semver: 7.3.8
tsutils: 3.21.0(typescript@5.0.4)
typescript: 5.0.4
tsutils: 3.21.0(typescript@5.1.3)
typescript: 5.1.3
transitivePeerDependencies:
- supports-color
dev: false
/@typescript-eslint/utils@5.54.0(eslint@8.41.0)(typescript@5.0.4):
/@typescript-eslint/typescript-estree@5.59.9(typescript@5.1.3):
resolution: {integrity: sha512-pmM0/VQ7kUhd1QyIxgS+aRvMgw+ZljB3eDb+jYyp6d2bC0mQWLzUDF+DLwCTkQ3tlNyVsvZRXjFyV0LkU/aXjA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
typescript: '*'
peerDependenciesMeta:
typescript:
optional: true
dependencies:
'@typescript-eslint/types': 5.59.9
'@typescript-eslint/visitor-keys': 5.59.9
debug: 4.3.4
globby: 11.1.0
is-glob: 4.0.3
semver: 7.3.8
tsutils: 3.21.0(typescript@5.1.3)
typescript: 5.1.3
transitivePeerDependencies:
- supports-color
dev: true
/@typescript-eslint/utils@5.54.0(eslint@8.42.0)(typescript@5.1.3):
resolution: {integrity: sha512-cuwm8D/Z/7AuyAeJ+T0r4WZmlnlxQ8wt7C7fLpFlKMR+dY6QO79Cq1WpJhvZbMA4ZeZGHiRWnht7ZJ8qkdAunw==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
@@ -6210,29 +6290,29 @@ packages:
'@types/semver': 7.3.13
'@typescript-eslint/scope-manager': 5.54.0
'@typescript-eslint/types': 5.54.0
'@typescript-eslint/typescript-estree': 5.54.0(typescript@5.0.4)
eslint: 8.41.0
'@typescript-eslint/typescript-estree': 5.54.0(typescript@5.1.3)
eslint: 8.42.0
eslint-scope: 5.1.1
eslint-utils: 3.0.0(eslint@8.41.0)
eslint-utils: 3.0.0(eslint@8.42.0)
semver: 7.3.8
transitivePeerDependencies:
- supports-color
- typescript
dev: true
/@typescript-eslint/utils@5.59.8(eslint@8.41.0)(typescript@5.0.4):
resolution: {integrity: sha512-Tr65630KysnNn9f9G7ROF3w1b5/7f6QVCJ+WK9nhIocWmx9F+TmCAcglF26Vm7z8KCTwoKcNEBZrhlklla3CKg==}
/@typescript-eslint/utils@5.59.9(eslint@8.42.0)(typescript@5.1.3):
resolution: {integrity: sha512-1PuMYsju/38I5Ggblaeb98TOoUvjhRvLpLa1DoTOFaLWqaXl/1iQ1eGurTXgBY58NUdtfTXKP5xBq7q9NDaLKg==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
dependencies:
'@eslint-community/eslint-utils': 4.2.0(eslint@8.41.0)
'@eslint-community/eslint-utils': 4.2.0(eslint@8.42.0)
'@types/json-schema': 7.0.11
'@types/semver': 7.3.13
'@typescript-eslint/scope-manager': 5.59.8
'@typescript-eslint/types': 5.59.8
'@typescript-eslint/typescript-estree': 5.59.8(typescript@5.0.4)
eslint: 8.41.0
'@typescript-eslint/scope-manager': 5.59.9
'@typescript-eslint/types': 5.59.9
'@typescript-eslint/typescript-estree': 5.59.9(typescript@5.1.3)
eslint: 8.42.0
eslint-scope: 5.1.1
semver: 7.3.8
transitivePeerDependencies:
@@ -6262,6 +6342,15 @@ packages:
dependencies:
'@typescript-eslint/types': 5.59.8
eslint-visitor-keys: 3.4.1
dev: false
/@typescript-eslint/visitor-keys@5.59.9:
resolution: {integrity: sha512-bT7s0td97KMaLwpEBckbzj/YohnvXtqbe2XgqNvTl6RJVakY5mvENOTPvw5u66nljfZxthESpDozs86U+oLY8Q==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dependencies:
'@typescript-eslint/types': 5.59.9
eslint-visitor-keys: 3.4.1
dev: true
/@webassemblyjs/ast@1.11.1:
resolution: {integrity: sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==}
@@ -9957,7 +10046,7 @@ packages:
- supports-color
dev: false
/eslint-config-next@13.4.4(eslint@8.41.0):
/eslint-config-next@13.4.4(eslint@8.41.0)(typescript@5.1.3):
resolution: {integrity: sha512-z/PMbm6L0iC/fwISULxe8IVy4DtNqZk2wQY711o35klenq70O6ns82A8yuMVCFjHC0DIyB2lyugesRtuk9u8dQ==}
peerDependencies:
eslint: ^7.23.0 || ^8.0.0
@@ -9968,7 +10057,7 @@ packages:
dependencies:
'@next/eslint-plugin-next': 13.4.4
'@rushstack/eslint-patch': 1.2.0
'@typescript-eslint/parser': 5.59.8(eslint@8.41.0)(typescript@5.0.4)
'@typescript-eslint/parser': 5.59.8(eslint@8.41.0)(typescript@5.1.3)
eslint: 8.41.0
eslint-import-resolver-node: 0.3.6
eslint-import-resolver-typescript: 3.5.2(eslint-plugin-import@2.26.0)(eslint@8.41.0)
@@ -9976,26 +10065,27 @@ packages:
eslint-plugin-jsx-a11y: 6.6.1(eslint@8.41.0)
eslint-plugin-react: 7.32.2(eslint@8.41.0)
eslint-plugin-react-hooks: 4.6.0(eslint@8.41.0)
typescript: 5.1.3
transitivePeerDependencies:
- eslint-import-resolver-webpack
- supports-color
dev: false
/eslint-config-preact@1.3.0(@typescript-eslint/eslint-plugin@5.59.8)(eslint@8.41.0)(jest@29.5.0)(typescript@5.0.4):
/eslint-config-preact@1.3.0(@typescript-eslint/eslint-plugin@5.59.9)(eslint@8.42.0)(jest@29.5.0)(typescript@5.1.3):
resolution: {integrity: sha512-yHYXg5qNzEJd3D/30AmsIW0W8MuY858KpApXp7xxBF08IYUljSKCOqMx+dVucXHQnAm7+11wOnMkgVHIBAechw==}
peerDependencies:
eslint: 6.x || 7.x || 8.x
dependencies:
'@babel/core': 7.20.12
'@babel/eslint-parser': 7.19.1(@babel/core@7.20.12)(eslint@8.41.0)
'@babel/eslint-parser': 7.19.1(@babel/core@7.20.12)(eslint@8.42.0)
'@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.20.12)
'@babel/plugin-syntax-decorators': 7.19.0(@babel/core@7.20.12)
'@babel/plugin-syntax-jsx': 7.18.6(@babel/core@7.20.12)
eslint: 8.41.0
eslint-plugin-compat: 4.1.2(eslint@8.41.0)
eslint-plugin-jest: 25.7.0(@typescript-eslint/eslint-plugin@5.59.8)(eslint@8.41.0)(jest@29.5.0)(typescript@5.0.4)
eslint-plugin-react: 7.32.2(eslint@8.41.0)
eslint-plugin-react-hooks: 4.6.0(eslint@8.41.0)
eslint: 8.42.0
eslint-plugin-compat: 4.1.2(eslint@8.42.0)
eslint-plugin-jest: 25.7.0(@typescript-eslint/eslint-plugin@5.59.9)(eslint@8.42.0)(jest@29.5.0)(typescript@5.1.3)
eslint-plugin-react: 7.32.2(eslint@8.42.0)
eslint-plugin-react-hooks: 4.6.0(eslint@8.42.0)
transitivePeerDependencies:
- '@typescript-eslint/eslint-plugin'
- jest
@@ -10071,7 +10161,7 @@ packages:
eslint-import-resolver-webpack:
optional: true
dependencies:
'@typescript-eslint/parser': 5.59.8(eslint@8.41.0)(typescript@5.0.4)
'@typescript-eslint/parser': 5.59.8(eslint@8.41.0)(typescript@5.1.3)
debug: 3.2.7
eslint: 8.41.0
eslint-import-resolver-node: 0.3.6
@@ -10080,7 +10170,7 @@ packages:
- supports-color
dev: false
/eslint-plugin-compat@4.1.2(eslint@8.41.0):
/eslint-plugin-compat@4.1.2(eslint@8.42.0):
resolution: {integrity: sha512-DNrQgDi5L4mAL4FdFboKBlSRg6MWfd75eA7K91lMjtP5ryN+O11qT2FDn7Z6zqy6sZ4sJawUR5V75qzB6l0CBg==}
engines: {node: '>=16.x'}
peerDependencies:
@@ -10090,7 +10180,7 @@ packages:
ast-metadata-inferer: 0.7.0
browserslist: 4.21.5
caniuse-lite: 1.0.30001466
eslint: 8.41.0
eslint: 8.42.0
find-up: 5.0.0
lodash.memoize: 4.1.2
semver: 7.3.8
@@ -10106,7 +10196,7 @@ packages:
'@typescript-eslint/parser':
optional: true
dependencies:
'@typescript-eslint/parser': 5.59.8(eslint@8.41.0)(typescript@5.0.4)
'@typescript-eslint/parser': 5.59.8(eslint@8.41.0)(typescript@5.1.3)
array-includes: 3.1.6
array.prototype.flat: 1.3.1
debug: 2.6.9
@@ -10127,7 +10217,7 @@ packages:
- supports-color
dev: false
/eslint-plugin-jest@25.7.0(@typescript-eslint/eslint-plugin@5.59.8)(eslint@8.41.0)(jest@29.5.0)(typescript@5.0.4):
/eslint-plugin-jest@25.7.0(@typescript-eslint/eslint-plugin@5.59.9)(eslint@8.42.0)(jest@29.5.0)(typescript@5.1.3):
resolution: {integrity: sha512-PWLUEXeeF7C9QGKqvdSbzLOiLTx+bno7/HC9eefePfEb257QFHg7ye3dh80AZVkaa/RQsBB1Q/ORQvg2X7F0NQ==}
engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
peerDependencies:
@@ -10140,9 +10230,9 @@ packages:
jest:
optional: true
dependencies:
'@typescript-eslint/eslint-plugin': 5.59.8(@typescript-eslint/parser@5.59.8)(eslint@8.41.0)(typescript@5.0.4)
'@typescript-eslint/experimental-utils': 5.54.0(eslint@8.41.0)(typescript@5.0.4)
eslint: 8.41.0
'@typescript-eslint/eslint-plugin': 5.59.9(@typescript-eslint/parser@5.59.9)(eslint@8.42.0)(typescript@5.1.3)
'@typescript-eslint/experimental-utils': 5.54.0(eslint@8.42.0)(typescript@5.1.3)
eslint: 8.42.0
jest: 29.5.0
transitivePeerDependencies:
- supports-color
@@ -10178,6 +10268,16 @@ packages:
eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0
dependencies:
eslint: 8.41.0
dev: false
/eslint-plugin-react-hooks@4.6.0(eslint@8.42.0):
resolution: {integrity: sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==}
engines: {node: '>=10'}
peerDependencies:
eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0
dependencies:
eslint: 8.42.0
dev: true
/eslint-plugin-react@7.32.2(eslint@8.41.0):
resolution: {integrity: sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==}
@@ -10201,6 +10301,31 @@ packages:
resolve: 2.0.0-next.4
semver: 6.3.0
string.prototype.matchall: 4.0.8
dev: false
/eslint-plugin-react@7.32.2(eslint@8.42.0):
resolution: {integrity: sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==}
engines: {node: '>=4'}
peerDependencies:
eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8
dependencies:
array-includes: 3.1.6
array.prototype.flatmap: 1.3.1
array.prototype.tosorted: 1.1.1
doctrine: 2.1.0
eslint: 8.42.0
estraverse: 5.3.0
jsx-ast-utils: 3.3.3
minimatch: 3.1.2
object.entries: 1.1.6
object.fromentries: 2.0.6
object.hasown: 1.1.2
object.values: 1.1.6
prop-types: 15.8.1
resolve: 2.0.0-next.4
semver: 6.3.0
string.prototype.matchall: 4.0.8
dev: true
/eslint-plugin-turbo@1.8.8(eslint@8.41.0):
resolution: {integrity: sha512-zqyTIvveOY4YU5jviDWw9GXHd4RiKmfEgwsjBrV/a965w0PpDwJgEUoSMB/C/dU310Sv9mF3DSdEjxjJLaw6rA==}
@@ -10240,13 +10365,13 @@ packages:
esrecurse: 4.3.0
estraverse: 5.3.0
/eslint-utils@3.0.0(eslint@8.41.0):
/eslint-utils@3.0.0(eslint@8.42.0):
resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==}
engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0}
peerDependencies:
eslint: '>=5'
dependencies:
eslint: 8.41.0
eslint: 8.42.0
eslint-visitor-keys: 2.1.0
dev: true
@@ -10360,6 +10485,54 @@ packages:
transitivePeerDependencies:
- supports-color
/eslint@8.42.0:
resolution: {integrity: sha512-ulg9Ms6E1WPf67PHaEY4/6E2tEn5/f7FXGzr3t9cBMugOmf1INYvuUwwh1aXQN4MfJ6a5K2iNwP3w4AColvI9A==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
hasBin: true
dependencies:
'@eslint-community/eslint-utils': 4.2.0(eslint@8.42.0)
'@eslint-community/regexpp': 4.4.0
'@eslint/eslintrc': 2.0.3
'@eslint/js': 8.42.0
'@humanwhocodes/config-array': 0.11.10
'@humanwhocodes/module-importer': 1.0.1
'@nodelib/fs.walk': 1.2.8
ajv: 6.12.6
chalk: 4.1.2
cross-spawn: 7.0.3
debug: 4.3.4
doctrine: 3.0.0
escape-string-regexp: 4.0.0
eslint-scope: 7.2.0
eslint-visitor-keys: 3.4.1
espree: 9.5.2
esquery: 1.5.0
esutils: 2.0.3
fast-deep-equal: 3.1.3
file-entry-cache: 6.0.1
find-up: 5.0.0
glob-parent: 6.0.2
globals: 13.19.0
graphemer: 1.4.0
ignore: 5.2.1
import-fresh: 3.3.0
imurmurhash: 0.1.4
is-glob: 4.0.3
is-path-inside: 3.0.3
js-yaml: 4.1.0
json-stable-stringify-without-jsonify: 1.0.1
levn: 0.4.1
lodash.merge: 4.6.2
minimatch: 3.1.2
natural-compare: 1.4.0
optionator: 0.9.1
strip-ansi: 6.0.1
strip-json-comments: 3.1.1
text-table: 0.2.0
transitivePeerDependencies:
- supports-color
dev: true
/esm@3.2.25:
resolution: {integrity: sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==}
engines: {node: '>=6'}
@@ -10862,7 +11035,7 @@ packages:
resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==}
dev: true
/fork-ts-checker-webpack-plugin@4.1.6(eslint@8.41.0)(typescript@4.6.4)(webpack@4.46.0):
/fork-ts-checker-webpack-plugin@4.1.6(eslint@8.42.0)(typescript@4.6.4)(webpack@4.46.0):
resolution: {integrity: sha512-DUxuQaKoqfNne8iikd14SAkh5uw4+8vNifp6gmA73yYNS6ywLIWSLD/n/mBzHQRpW3J7rbATEakmiA8JvkTyZw==}
engines: {node: '>=6.11.5', yarn: '>=1.0.0'}
peerDependencies:
@@ -10878,7 +11051,7 @@ packages:
dependencies:
'@babel/code-frame': 7.18.6
chalk: 2.4.2
eslint: 8.41.0
eslint: 8.42.0
micromatch: 3.1.10
minimatch: 3.1.2
semver: 5.7.1
@@ -12798,7 +12971,7 @@ packages:
jest-resolve: 29.5.0
dev: true
/jest-preset-preact@4.0.5(jest@29.5.0)(preact-render-to-string@6.0.3)(preact@10.15.1):
/jest-preset-preact@4.0.5(jest@29.5.0)(preact-render-to-string@6.1.0)(preact@10.15.1):
resolution: {integrity: sha512-MnU7mfpnwopJkdx0WoEyRmrNDIvRN+w6sOur0zEhaRYYMo0gJM7UdZHWTV8k6uo0+ypY+m0kQW6kMukUx4v8JQ==}
peerDependencies:
jest: 26.x || 27.x
@@ -12816,7 +12989,7 @@ packages:
jest: 29.5.0
jest-watch-typeahead: 0.6.5(jest@29.5.0)
preact: 10.15.1
preact-render-to-string: 6.0.3(preact@10.15.1)
preact-render-to-string: 6.1.0(preact@10.15.1)
transitivePeerDependencies:
- encoding
- supports-color
@@ -16688,7 +16861,7 @@ packages:
- debug
dev: false
/preact-cli@3.4.5(eslint@8.41.0)(preact-render-to-string@6.0.3)(preact@10.15.1):
/preact-cli@3.4.5(eslint@8.42.0)(preact-render-to-string@6.1.0)(preact@10.15.1):
resolution: {integrity: sha512-pLTawiXDy4rEct5ul0mDCP92GB6NK/QFhpoR+iHZJqgkeyE25qEXPf1/tJhAiijphDL5kxGvsT4qA6SrpQ5BsQ==}
engines: {node: '>=12'}
hasBin: true
@@ -16736,7 +16909,7 @@ packages:
envinfo: 7.8.1
esm: 3.2.25
file-loader: 6.2.0(webpack@4.46.0)
fork-ts-checker-webpack-plugin: 4.1.6(eslint@8.41.0)(typescript@4.6.4)(webpack@4.46.0)
fork-ts-checker-webpack-plugin: 4.1.6(eslint@8.42.0)(typescript@4.6.4)(webpack@4.46.0)
get-port: 5.1.1
gittar: 0.1.1
glob: 8.1.0
@@ -16756,7 +16929,7 @@ packages:
postcss-load-config: 3.1.4(postcss@8.4.24)
postcss-loader: 4.3.0(postcss@8.4.24)(webpack@4.46.0)
preact: 10.15.1
preact-render-to-string: 6.0.3(preact@10.15.1)
preact-render-to-string: 6.1.0(preact@10.15.1)
progress-bar-webpack-plugin: 2.1.0(webpack@4.46.0)
promise-polyfill: 8.3.0
prompts: 2.4.2
@@ -16812,8 +16985,8 @@ packages:
pretty-format: 3.8.0
dev: false
/preact-render-to-string@6.0.3(preact@10.15.1):
resolution: {integrity: sha512-UUP+EtmLw5ns0fT9C7+CTdLawm1wLmlrZ6WKzJ4Jwhb4EBu4vy5ufIZKlrfvWNnPl1JFoJzZwzfKs97H4N0Vug==}
/preact-render-to-string@6.1.0(preact@10.15.1):
resolution: {integrity: sha512-/AsKU4Q4R8r4aKwwNQrkQQNUVEDmTeZr6IwesDffobFRPcTk4dSQrfo1VOcXjtlcUss6QYEe7JShUGbQIhaw+A==}
peerDependencies:
preact: '>=10'
dependencies:
@@ -19818,6 +19991,16 @@ packages:
dependencies:
tslib: 1.14.1
typescript: 5.0.4
dev: false
/tsutils@3.21.0(typescript@5.1.3):
resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==}
engines: {node: '>= 6'}
peerDependencies:
typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta'
dependencies:
tslib: 1.14.1
typescript: 5.1.3
/tsx@3.12.6:
resolution: {integrity: sha512-q93WgS3lBdHlPgS0h1i+87Pt6n9K/qULIMNYZo07nSeu2z5QE2CellcAZfofVXBo2tQg9av2ZcRMQ2S2i5oadQ==}
@@ -20018,6 +20201,11 @@ packages:
engines: {node: '>=12.20'}
hasBin: true
/typescript@5.1.3:
resolution: {integrity: sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==}
engines: {node: '>=14.17'}
hasBin: true
/uc.micro@1.0.6:
resolution: {integrity: sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==}
dev: false