From d84cc9758b3512c5661293d60af0769f49a16e5a Mon Sep 17 00:00:00 2001 From: Kasper Baun Date: Wed, 22 May 2024 13:17:39 +0200 Subject: [PATCH 1/8] fix: change default view to intro instead of settings --- packages/designer/src/Hooks/useDocument.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/designer/src/Hooks/useDocument.ts b/packages/designer/src/Hooks/useDocument.ts index da3109a..c883538 100644 --- a/packages/designer/src/Hooks/useDocument.ts +++ b/packages/designer/src/Hooks/useDocument.ts @@ -73,7 +73,7 @@ export const useDocument = (entityName: string, attributeName: string, designerL } }, [quickformpayload, old, formData, column.logicalName]); - const view = quickformpayload.__designer?.activeView ?? "settings"; + const view = quickformpayload.__designer?.activeView ?? "intro"; const activeQuestion = quickformpayload.__designer?.activeQuestion; const activeSlide = quickformpayload.__designer?.activeSlide; const setActiveSlide = (slide?: string) => updateQuickFormPayload(old => { if (!old.__designer) { old.__designer = {} }; old.__designer.activeSlide = slide; return { ...old }; }); From 301143fbc9e0f1a381a0f884b68c615c5a2da4a4 Mon Sep 17 00:00:00 2001 From: Kasper Baun Date: Wed, 22 May 2024 13:23:24 +0200 Subject: [PATCH 2/8] fix: defined path where designer project should resolve its react types from --- packages/designer/tsconfig.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/designer/tsconfig.json b/packages/designer/tsconfig.json index 2bbf14f..5686dac 100644 --- a/packages/designer/tsconfig.json +++ b/packages/designer/tsconfig.json @@ -15,10 +15,14 @@ "jsx": "preserve", "baseUrl": "./src", "paths": { + "react": [ + "./../../../node_modules/@types/react" + ], }, "rootDirs": [ "src" ], "experimentalDecorators": true }, "exclude": [ "node_modules" ], - "include": [ "**/*.ts", "**/*.tsx" ] + "include": [ "**/*.ts", "**/*.tsx" ], + } From b94ff1e9813768fe270982c5b34ef5d48cc06374 Mon Sep 17 00:00:00 2001 From: Kasper Baun Date: Tue, 28 May 2024 07:02:52 +0200 Subject: [PATCH 3/8] fix: updated griffel - added QuickFormContainer --- package-lock.json | 46 ++++++------ packages/core/package.json | 2 +- packages/core/src/components/QuickForm.tsx | 1 + packages/playground/src/App.tsx | 38 ++++++---- .../container/QuickFormContainer.tsx | 74 +++++++++++++++++++ 5 files changed, 123 insertions(+), 38 deletions(-) create mode 100644 packages/playground/src/components/container/QuickFormContainer.tsx diff --git a/package-lock.json b/package-lock.json index c344a5e..85c17c4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4309,13 +4309,13 @@ } }, "node_modules/@griffel/core": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/@griffel/core/-/core-1.15.2.tgz", - "integrity": "sha512-RlsIXoSS3gaYykUgxFpwKAs/DV9cRUKp3CW1kt3iPAtsDTWn/o+8bT1jvBws/tMM2GBu/Uc0EkaIzUPqD7uA+Q==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/@griffel/core/-/core-1.17.0.tgz", + "integrity": "sha512-OhLMYQ9zXVpKh3DULgK0Olsm1Xw5cvQuL7BV3UCWoJttAWGfrdIvSMxGCJ2FpWVyS/OBWoG4BTYh3oHTgxBWCQ==", "peer": true, "dependencies": { "@emotion/hash": "^0.9.0", - "@griffel/style-types": "^1.0.3", + "@griffel/style-types": "^1.2.0", "csstype": "^3.1.3", "rtl-css-js": "^1.16.1", "stylis": "^4.2.0", @@ -4323,12 +4323,12 @@ } }, "node_modules/@griffel/react": { - "version": "1.5.20", - "resolved": "https://registry.npmjs.org/@griffel/react/-/react-1.5.20.tgz", - "integrity": "sha512-1P2yaPctENFSCwyPIYXBmgpNH68c0lc/jwSzPij1QATHDK1AASKuSeq6hW108I67RKjhRyHCcALshdZ3GcQXSg==", + "version": "1.5.23", + "resolved": "https://registry.npmjs.org/@griffel/react/-/react-1.5.23.tgz", + "integrity": "sha512-pOOh+h+2JibSVlRfN6rzIigkPm6HONxMHEN3IWLB3gVU7OKEQHt/EOK+1ZePMzaMILZaaFDvuwCaKCkEq6QQ/Q==", "peer": true, "dependencies": { - "@griffel/core": "^1.15.2", + "@griffel/core": "^1.17.0", "tslib": "^2.1.0" }, "peerDependencies": { @@ -4336,9 +4336,9 @@ } }, "node_modules/@griffel/style-types": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@griffel/style-types/-/style-types-1.0.3.tgz", - "integrity": "sha512-AzbbYV/EobNIBtfMtyu2edFin895gjVxtu1nsRhTETUAIb0/LCZoue3Jd/kFLuPwe95rv5WRUBiQpVwJsrrFcw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@griffel/style-types/-/style-types-1.2.0.tgz", + "integrity": "sha512-x166MNw0vWe5l5qhinfNT4eyWOaP48iFzPyFOfIB0/BVidKTWsEe5PmqRJDDtrJFS3VHhd/tE0oM6tkEMh2tsg==", "peer": true, "dependencies": { "csstype": "^3.1.3" @@ -17020,7 +17020,7 @@ "react-icons": "^4.11.0" }, "peerDependencies": { - "@griffel/react": "1.5.20", + "@griffel/react": "1.5.23", "@opentelemetry/api": "^1.8.0" } }, @@ -20296,13 +20296,13 @@ } }, "@griffel/core": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/@griffel/core/-/core-1.15.2.tgz", - "integrity": "sha512-RlsIXoSS3gaYykUgxFpwKAs/DV9cRUKp3CW1kt3iPAtsDTWn/o+8bT1jvBws/tMM2GBu/Uc0EkaIzUPqD7uA+Q==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/@griffel/core/-/core-1.17.0.tgz", + "integrity": "sha512-OhLMYQ9zXVpKh3DULgK0Olsm1Xw5cvQuL7BV3UCWoJttAWGfrdIvSMxGCJ2FpWVyS/OBWoG4BTYh3oHTgxBWCQ==", "peer": true, "requires": { "@emotion/hash": "^0.9.0", - "@griffel/style-types": "^1.0.3", + "@griffel/style-types": "^1.2.0", "csstype": "^3.1.3", "rtl-css-js": "^1.16.1", "stylis": "^4.2.0", @@ -20310,19 +20310,19 @@ } }, "@griffel/react": { - "version": "1.5.20", - "resolved": "https://registry.npmjs.org/@griffel/react/-/react-1.5.20.tgz", - "integrity": "sha512-1P2yaPctENFSCwyPIYXBmgpNH68c0lc/jwSzPij1QATHDK1AASKuSeq6hW108I67RKjhRyHCcALshdZ3GcQXSg==", + "version": "1.5.23", + "resolved": "https://registry.npmjs.org/@griffel/react/-/react-1.5.23.tgz", + "integrity": "sha512-pOOh+h+2JibSVlRfN6rzIigkPm6HONxMHEN3IWLB3gVU7OKEQHt/EOK+1ZePMzaMILZaaFDvuwCaKCkEq6QQ/Q==", "peer": true, "requires": { - "@griffel/core": "^1.15.2", + "@griffel/core": "^1.17.0", "tslib": "^2.1.0" } }, "@griffel/style-types": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@griffel/style-types/-/style-types-1.0.3.tgz", - "integrity": "sha512-AzbbYV/EobNIBtfMtyu2edFin895gjVxtu1nsRhTETUAIb0/LCZoue3Jd/kFLuPwe95rv5WRUBiQpVwJsrrFcw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@griffel/style-types/-/style-types-1.2.0.tgz", + "integrity": "sha512-x166MNw0vWe5l5qhinfNT4eyWOaP48iFzPyFOfIB0/BVidKTWsEe5PmqRJDDtrJFS3VHhd/tE0oM6tkEMh2tsg==", "peer": true, "requires": { "csstype": "^3.1.3" diff --git a/packages/core/package.json b/packages/core/package.json index 4e57b5f..70e1a08 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -7,7 +7,7 @@ "react-dom": "^18.2.0" }, "peerDependencies": { - "@griffel/react": "1.5.20", + "@griffel/react": "1.5.23", "@opentelemetry/api": "^1.8.0" }, "devDependencies": { diff --git a/packages/core/src/components/QuickForm.tsx b/packages/core/src/components/QuickForm.tsx index 40f4ddf..5718e46 100644 --- a/packages/core/src/components/QuickForm.tsx +++ b/packages/core/src/components/QuickForm.tsx @@ -2,6 +2,7 @@ import React from 'react'; import { useQuickForm } from "../state/QuickFormContext"; import { Ending, Submit, Intro, SlideRenderer } from "./index"; +import "./question/input-types/index"; export const QuickForm: React.FC = () => { const { state, setIntroVisited } = useQuickForm(); diff --git a/packages/playground/src/App.tsx b/packages/playground/src/App.tsx index f9edaa0..7e0afad 100644 --- a/packages/playground/src/App.tsx +++ b/packages/playground/src/App.tsx @@ -7,6 +7,16 @@ import "./components/buttons-input/ButtonsInput"; import "./components/checkbox-input/CheckboxInput"; import "./components/radio-input/RadioInput"; import "./components/slider-input/SliderInput"; +import { QuickFormContainer } from './components/container/QuickFormContainer'; + +const containerStyling: React.CSSProperties = { + width: '100%', + minHeight: '1200px', + padding: '10px', + display: 'flex', + justifyContent: 'center', + alignItems: 'center', +} export const App = () => { return ( @@ -16,20 +26,20 @@ export const App = () => { payload={{}} asContainer={true} > - -
- -
+ + +
+ +
+
); -}; - -const containerStyling: React.CSSProperties = { - width: '100%', - minHeight: '1200px', - padding: '10px', - display: 'flex', - justifyContent: 'center', - alignItems: 'center', -} \ No newline at end of file +}; \ No newline at end of file diff --git a/packages/playground/src/components/container/QuickFormContainer.tsx b/packages/playground/src/components/container/QuickFormContainer.tsx new file mode 100644 index 0000000..a6de368 --- /dev/null +++ b/packages/playground/src/components/container/QuickFormContainer.tsx @@ -0,0 +1,74 @@ +import { ErrorPopup, quickformtokens, useQuickForm } from "@eavfw/quickform-core"; +import { makeStyles, shorthands, mergeClasses } from "@griffel/react"; +import React, { PropsWithChildren } from "react"; +// import { Outfit } from "next/font/google"; +// const outfit = Outfit({ subsets: ["latin"] }); + + +const useStyles = makeStyles({ + root: { + display: 'flex', + flexDirection: "column", + justifyContent: "center", + alignItems: 'center', + width: "100%", + minWidth: "800px", + maxWidth: "1080px", + height: 'fit-content', + ...shorthands.padding("20px", "20px", "20px", "20px"), + ...shorthands.margin("20px", "0px"), + ...shorthands.borderRadius("20px"), + // borderRadius: '20px', + boxShadow: 'rgba(100, 100, 111, 0.2) 0px 7px 29px 0px', + } +}) + +type QuickFormContainerProps = { + title: string, + subtitle: string, +} + +export const QuickFormContainer: React.FC> = ({ children, subtitle, title }) => { + + const styles = useStyles(); + const { state: { errorMsg }, cssVariables } = useQuickForm(); + return ( +
+ + + +
+ {children} +
+
+ + ) +} + +const Headline: React.FC<{ text: string, fontWeight: number, color: string, lineHeight: number }> = ({ text, fontWeight, color, lineHeight }) => { + return ( +

+ {text} +

+ ) +} \ No newline at end of file From e37b030ecf00105718f53e49a4e262cb44a0eb8d Mon Sep 17 00:00:00 2001 From: Kasper Baun Date: Thu, 30 May 2024 08:35:57 +0200 Subject: [PATCH 4/8] fix: corrects a color issue on "Tryk Enter" text next to slideButton - removes some redundant code --- packages/core/src/components/button/Button.tsx | 2 +- .../core/src/services/defaults/DefaultInputTypeResolver.ts | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/core/src/components/button/Button.tsx b/packages/core/src/components/button/Button.tsx index 02806e7..f886565 100644 --- a/packages/core/src/components/button/Button.tsx +++ b/packages/core/src/components/button/Button.tsx @@ -72,7 +72,7 @@ export const Button: React.FC> = ({ childre {!disabled && !isOnMobile && showPressEnter && ( - + <>Tryk Enter ↵ )} diff --git a/packages/core/src/services/defaults/DefaultInputTypeResolver.ts b/packages/core/src/services/defaults/DefaultInputTypeResolver.ts index e7189b5..92a8751 100644 --- a/packages/core/src/services/defaults/DefaultInputTypeResolver.ts +++ b/packages/core/src/services/defaults/DefaultInputTypeResolver.ts @@ -18,10 +18,8 @@ const parseInputProperties = (questionJsonModel: QuestionJsonModel): InputProper .filter(([key]) => !['text', 'paragraph', 'placeholder'].includes(key)) .map(([key, schema]) => [key, questionJsonModel[key as keyof QuestionJsonModel] ?? getDefaultValue(schema)])) as InputPropertiesTypes; } - //This will always return {} , do we know what we are doing here? KBA? - const inputTypePropertiesMap: { [key: string]: () => InputPropertiesTypes } = {}; - return inputType in inputTypePropertiesMap ? inputTypePropertiesMap[inputType]() : {}; + return {}; }; registerQuickFormService("inputTypePropertiesTransformer", parseInputProperties); From b03bacac16e19eb275e15d22042f126ec0aeec61 Mon Sep 17 00:00:00 2001 From: Kasper Baun Date: Thu, 30 May 2024 08:36:49 +0200 Subject: [PATCH 5/8] fix: removes 2 second wait on phonevalidation that was used to demo async functionality --- packages/core/src/services/defaults/DefaultInputValidator.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/services/defaults/DefaultInputValidator.ts b/packages/core/src/services/defaults/DefaultInputValidator.ts index e9c3bb3..c4b4597 100644 --- a/packages/core/src/services/defaults/DefaultInputValidator.ts +++ b/packages/core/src/services/defaults/DefaultInputValidator.ts @@ -38,7 +38,7 @@ const validateEmail = (output: any): ValidationResult => { const validatePhone = async (output: any): Promise => { // Wait for 2 seconds to demo - await new Promise(resolve => setTimeout(resolve, 2000)); + // await new Promise(resolve => setTimeout(resolve, 2000)); const phoneRegex = /^[0-9]{8,}$/; const valid = typeof output === 'string' && phoneRegex.test(output); From 8b1f8b910b801e6d9a76923231cd65f13b8d5425 Mon Sep 17 00:00:00 2001 From: Kasper Baun Date: Thu, 30 May 2024 09:11:49 +0200 Subject: [PATCH 6/8] feat: adds the option to define icons and buttonText pr. slide. Also fixes a bug on multilinetext where focus on inputcontrol did not set the question to active --- .../src/components/icons/IconResolver.tsx | 11 +++--- .../baseinput/BaseInputComponent.tsx | 12 +++--- .../input-types/multiline/MultilineInput.tsx | 16 +++++--- .../slide-renderer/SlideRenderer.tsx | 37 ++++++++++++------- packages/core/src/model/SlideModel.ts | 3 ++ .../core/src/model/json-definitions/Layout.ts | 5 ++- .../defaults/DefaultModelTransformer.ts | 11 ++++-- packages/playground/src/App.tsx | 2 +- .../allInputControlsMultipleSlidesTest.json | 8 +++- 9 files changed, 68 insertions(+), 37 deletions(-) diff --git a/packages/core/src/components/icons/IconResolver.tsx b/packages/core/src/components/icons/IconResolver.tsx index 6eb6f34..a2203b0 100644 --- a/packages/core/src/components/icons/IconResolver.tsx +++ b/packages/core/src/components/icons/IconResolver.tsx @@ -2,17 +2,18 @@ import { EmailIcon } from "./EmailIcon"; import { TelephoneIcon } from "./TelephoneIcon"; import { UserIcon } from "./UserIcon"; import { IconProps } from "./iconProps"; +import { Checkmark } from '../icons/Checkmark'; export type IconType = "Email" | "Phone" | "User"; export type IconResolverProps = { type: IconType, } & IconProps -export const IconResolver: React.FC = ({ type, color, className, size }) => { +export const IconResolver: React.FC = ({ type, color, className, size, style }): JSX.Element => { switch (type) { - case "Email": return - case "Phone": return - case "User": return - default: return + case "Email": return + case "Phone": return + case "User": return + default: return ; } } \ No newline at end of file diff --git a/packages/core/src/components/question/input-types/baseinput/BaseInputComponent.tsx b/packages/core/src/components/question/input-types/baseinput/BaseInputComponent.tsx index 22bf772..9e7d25e 100644 --- a/packages/core/src/components/question/input-types/baseinput/BaseInputComponent.tsx +++ b/packages/core/src/components/question/input-types/baseinput/BaseInputComponent.tsx @@ -82,7 +82,7 @@ export const BaseInputComponent: React.FC = ({ question span.addEvent("BaseInputComponent:render"); } - + const resize = () => { const input = ref.current; @@ -104,7 +104,7 @@ export const BaseInputComponent: React.FC = ({ question } const handleChange = (event: ChangeEvent) => { - console.log("BaseInputComponent:handleChange", event.target.value); + console.log("BaseInputComponent:handleChange", event.target.value); if (span) { span.addEvent("BaseInputComponent:handleChange", { 'value': event.target.value }); } @@ -119,9 +119,9 @@ export const BaseInputComponent: React.FC = ({ question } /** - * The input control is responsible of setting it self focus when becoming active. - * - We should also listen to input controls being focused and if not active, trigger a reducer that its set active. - * Ultimatly removing active from other questions. This happens right now when an answer is given (intermediate or not), so not critical. + * The input control is responsible of setting itself focused when becoming active. + * - We should also listen to inputcontrols being focused and if not active, trigger a reducer that sets it to active. Ultimately removing active from other questions. + * This happens right now when an answer is given (intermediate or not), so not critical. */ useEffect(() => { if (questionModel.isActive) @@ -132,7 +132,7 @@ export const BaseInputComponent: React.FC = ({ question * While a base input component is active we should answer the question upon enter. */ useHandleEnterKeypress("baseinput", !questionModel.isActive, () => { - answerQuestion(questionModel.logicalName, text,false); + answerQuestion(questionModel.logicalName, text, false); }); return ( diff --git a/packages/core/src/components/question/input-types/multiline/MultilineInput.tsx b/packages/core/src/components/question/input-types/multiline/MultilineInput.tsx index d9258bf..030d2a4 100644 --- a/packages/core/src/components/question/input-types/multiline/MultilineInput.tsx +++ b/packages/core/src/components/question/input-types/multiline/MultilineInput.tsx @@ -43,9 +43,10 @@ const useInputTextStyles = makeStyles({ export const MultilineInput: InputComponentType = ({ questionModel }) => { const styles = useInputTextStyles(); - const { isFirstQuestionInCurrentSlide, answerQuestion } = useQuickForm(); + const { isFirstQuestionInCurrentSlide, answerQuestion, state } = useQuickForm(); const { placeholder, output } = questionModel; const [text, setText] = useState(output || ''); + const ref = useRef(null); const handleChange = (event: ChangeEvent) => { const newValue = event.target.value.replace(/\r?\n/g, '\n'); // Normalize newline characters @@ -53,12 +54,15 @@ export const MultilineInput: InputComponentType = ({ questi answerQuestion(questionModel.logicalName, newValue, true); }; - const ref = useRef(null); + /** + * The input control is responsible of setting itself focused when becoming active. + * - We should also listen to inputcontrols being focused and if not active, trigger a reducer that sets it to active. Ultimately removing active from other questions. + * This happens right now when an answer is given (intermediate or not), so not critical. + */ useEffect(() => { - if (ref.current && isFirstQuestionInCurrentSlide(questionModel.logicalName)) { - ref.current.focus(); - } - }, [ref, isFirstQuestionInCurrentSlide, questionModel.logicalName]); + if (questionModel.isActive || ref.current && isFirstQuestionInCurrentSlide(questionModel.logicalName)) + ref.current?.focus(); + }, [ref, isFirstQuestionInCurrentSlide, questionModel.logicalName, questionModel.isActive]); return (