@public-ui/sample-react 1.7.11 → 1.7.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (92) hide show
  1. package/dist/104.js +1 -1
  2. package/dist/1296.js +1 -1
  3. package/dist/1461.js +1 -1
  4. package/dist/1684.js +1 -1
  5. package/dist/1720.js +1 -1
  6. package/dist/1888.js +1 -1
  7. package/dist/{616.js → 2104.js} +2 -2
  8. package/dist/2120.js +1 -1
  9. package/dist/2240.js +1 -1
  10. package/dist/2444.js +1 -1
  11. package/dist/2628.js +1 -1
  12. package/dist/2740.js +1 -1
  13. package/dist/2764.js +1 -1
  14. package/dist/2782.js +1 -1
  15. package/dist/2812.js +1 -1
  16. package/dist/3200.js +1 -1
  17. package/dist/3204.js +1 -1
  18. package/dist/352.js +1 -1
  19. package/dist/3564.js +1 -1
  20. package/dist/3920.js +1 -1
  21. package/dist/4064.js +1 -1
  22. package/dist/4136.js +1 -1
  23. package/dist/4184.js +1 -1
  24. package/dist/4544.js +1 -1
  25. package/dist/4728.js +1 -1
  26. package/dist/4915.js +1 -1
  27. package/dist/4988.js +1 -1
  28. package/dist/5060.js +2 -0
  29. package/dist/5376.js +1 -1
  30. package/dist/5456.js +1 -1
  31. package/dist/5615.js +1 -1
  32. package/dist/5628.js +1 -1
  33. package/dist/5744.js +1 -1
  34. package/dist/5768.js +1 -1
  35. package/dist/5839.js +1 -1
  36. package/dist/5956.js +1 -1
  37. package/dist/5972.js +1 -1
  38. package/dist/6040.js +1 -1
  39. package/dist/6272.js +1 -1
  40. package/dist/7192.js +1 -1
  41. package/dist/7312.js +1 -1
  42. package/dist/7344.js +1 -1
  43. package/dist/736.js +1 -1
  44. package/dist/7496.js +1 -1
  45. package/dist/7508.js +1 -1
  46. package/dist/7596.js +1 -1
  47. package/dist/7712.js +1 -1
  48. package/dist/7808.js +1 -1
  49. package/dist/8188.js +1 -1
  50. package/dist/8232.js +1 -1
  51. package/dist/8248.js +1 -1
  52. package/dist/828.js +1 -1
  53. package/dist/8476.js +1 -1
  54. package/dist/8524.js +1 -1
  55. package/dist/8696.js +2 -0
  56. package/dist/9088.js +1 -1
  57. package/dist/9404.js +1 -1
  58. package/dist/9424.js +1 -1
  59. package/dist/9496.js +1 -1
  60. package/dist/9544.js +1 -1
  61. package/dist/9680.js +1 -1
  62. package/dist/9844.js +2 -0
  63. package/dist/9888.js +1 -1
  64. package/dist/9984.js +1 -1
  65. package/dist/index.html +1 -1
  66. package/dist/main.css +1 -1
  67. package/dist/main.js +1 -1
  68. package/dist/main.js.LICENSE.txt +2 -4
  69. package/package.json +13 -15
  70. package/public/index.html +1 -1
  71. package/src/App.tsx +26 -23
  72. package/src/components/SampleDescription.tsx +23 -0
  73. package/src/components/input-text/hide-errors.tsx +25 -0
  74. package/src/components/input-text/partials/cases.tsx +1 -4
  75. package/src/components/input-text/routes.ts +2 -0
  76. package/src/components/tabs/basic.tsx +24 -7
  77. package/src/scenarios/appointment-form/AppointmentForm.tsx +13 -7
  78. package/src/scenarios/appointment-form/AvailableAppointmentsForm.tsx +7 -10
  79. package/src/scenarios/appointment-form/DistrictForm.tsx +4 -9
  80. package/src/scenarios/appointment-form/PersonalInformationForm.tsx +29 -6
  81. package/src/scenarios/appointment-form/formUtils.ts +8 -0
  82. package/src/scenarios/routes.ts +3 -1
  83. package/src/scenarios/static-form.tsx +74 -0
  84. package/src/shares/HideMenusContext.ts +3 -0
  85. package/dist/4236.js +0 -2
  86. package/dist/4900.js +0 -2
  87. package/dist/5384.js +0 -2
  88. package/src/scenarios/appointment-form/ErrorList.tsx +0 -35
  89. /package/dist/{4236.js.LICENSE.txt → 2104.js.LICENSE.txt} +0 -0
  90. /package/dist/{4900.js.LICENSE.txt → 5060.js.LICENSE.txt} +0 -0
  91. /package/dist/{5384.js.LICENSE.txt → 8696.js.LICENSE.txt} +0 -0
  92. /package/dist/{616.js.LICENSE.txt → 9844.js.LICENSE.txt} +0 -0
@@ -2,8 +2,6 @@
2
2
  * KoliBri - The accessible HTML-Standard
3
3
  */
4
4
 
5
- /*!__STENCIL_STATIC_IMPORT_SWITCH__*/
6
-
7
5
  /**
8
6
  * @license React
9
7
  * react-dom.production.min.js
@@ -35,7 +33,7 @@
35
33
  */
36
34
 
37
35
  /**
38
- * @remix-run/router v1.15.0
36
+ * @remix-run/router v1.15.1
39
37
  *
40
38
  * Copyright (c) Remix Software Inc.
41
39
  *
@@ -46,7 +44,7 @@
46
44
  */
47
45
 
48
46
  /**
49
- * React Router v6.22.0
47
+ * React Router v6.22.1
50
48
  *
51
49
  * Copyright (c) Remix Software Inc.
52
50
  *
package/package.json CHANGED
@@ -1,22 +1,22 @@
1
1
  {
2
2
  "name": "@public-ui/sample-react",
3
- "version": "1.7.11",
3
+ "version": "1.7.13",
4
4
  "description": "This app contains samples for the KoliBri/Public UI",
5
5
  "license": "EUPL-1.2",
6
6
  "dependencies": {
7
7
  "@leanup/stack": "1.3.49",
8
8
  "@leanup/stack-react": "1.3.49",
9
9
  "@leanup/stack-webpack": "1.3.49",
10
- "@public-ui/components": "1.7.11",
11
- "@public-ui/react": "1.7.11",
12
- "@public-ui/themes": "1.7.11",
13
- "@types/node": "20.11.17",
14
- "@types/react": "18.2.55",
10
+ "@public-ui/components": "1.7.13",
11
+ "@public-ui/react": "1.7.13",
12
+ "@public-ui/themes": "1.7.13",
13
+ "@types/node": "20.11.19",
14
+ "@types/react": "18.2.57",
15
15
  "@types/react-dom": "18.2.19",
16
16
  "@unocss/preset-uno": "0.58.5",
17
17
  "@unocss/webpack": "0.58.5",
18
18
  "ajv": "8.12.0",
19
- "chromedriver": "121.0.0",
19
+ "chromedriver": "121.0.2",
20
20
  "cpy-cli": "5.0.0",
21
21
  "eslint-plugin-jsx-a11y": "6.8.0",
22
22
  "eslint-plugin-react": "7.33.2",
@@ -25,8 +25,8 @@
25
25
  "npm-run-all": "4.1.5",
26
26
  "react": "18.2.0",
27
27
  "react-dom": "18.2.0",
28
- "react-router": "6.22.0",
29
- "react-router-dom": "6.22.0",
28
+ "react-router": "6.22.1",
29
+ "react-router-dom": "6.22.1",
30
30
  "rimraf": "3.0.2",
31
31
  "ts-prune": "0.10.3",
32
32
  "typescript": "5.3.3",
@@ -48,16 +48,14 @@
48
48
  "webpack.config.js"
49
49
  ],
50
50
  "scripts": {
51
- "clean": "git clean -f -d -X",
52
- "clean:locks": "rimraf package-lock.json pnpm-lock.yaml && npm run clean",
53
51
  "build": "rimraf dist && cross-env NODE_ENV=production webpack",
52
+ "build:deps": "pnpm --filter @public-ui/sample-react^... build",
54
53
  "format": "prettier --check src",
55
54
  "lint": "eslint \"{src,tests}/**/*.{html,js,json,jsx,ts,tsx,gql,graphql}\"",
55
+ "prepare:components-assets": "cpy \"node_modules/@public-ui/components/assets/**/*\" public/assets --dot",
56
+ "prepare:themes-assets": "cpy \"node_modules/@public-ui/themes/assets/**/*\" public/assets --dot",
56
57
  "serve": "cross-env NODE_ENV=development webpack serve --devtool=source-map",
57
58
  "start": "npm run serve -- --open",
58
- "unused": "ts-prune -e src",
59
- "postinstall": "npm-run-all postinstall:*",
60
- "postinstall:components-assets": "cpy \"node_modules/@public-ui/components/assets/**/*\" public/assets --dot",
61
- "postinstall:themes-assets": "cpy \"node_modules/@public-ui/themes/assets/**/*\" public/assets --dot"
59
+ "unused": "ts-prune -e src"
62
60
  }
63
61
  }
package/public/index.html CHANGED
@@ -18,7 +18,7 @@
18
18
  <link rel="stylesheet" href="assets/tabler-icons/tabler-icons.css" />
19
19
  <link rel="stylesheet" href="main.css" />
20
20
  <meta name="robots" content="noindex" />
21
- <meta name="kolibri" content="dev-mode=false" />
21
+ <meta name="kolibri" content="dev-mode=false;experimental-mode=true;" />
22
22
  </head>
23
23
  <body>
24
24
  <div id="app"></div>
package/src/App.tsx CHANGED
@@ -3,13 +3,14 @@ import { Navigate, Route, Routes, useSearchParams } from 'react-router-dom';
3
3
  import { Route as MyRoute, Routes as MyRoutes } from './shares/types';
4
4
 
5
5
  import { Option } from '@public-ui/components';
6
+ import PackageJson from '@public-ui/components/package.json';
6
7
  import { KolAlert, KolBadge } from '@public-ui/react';
8
+ import { HideMenusContext } from './shares/HideMenusContext';
9
+ import { useLocation } from 'react-router';
10
+ import { Sidebar } from './components/Sidebar';
7
11
  import { ROUTES } from './shares/routes';
8
- import { isDraftTheme, Theme, THEME_OPTIONS } from './shares/theme';
9
- import PackageJson from '@public-ui/components/package.json';
10
12
  import { getTheme, getThemeName, setStorage, setTheme } from './shares/store';
11
- import { Sidebar } from './components/Sidebar';
12
- import { useLocation } from 'react-router';
13
+ import { THEME_OPTIONS, Theme, isDraftTheme } from './shares/theme';
13
14
 
14
15
  import { BackPage } from './components/BackPage';
15
16
 
@@ -118,26 +119,28 @@ export const App: FC = () => {
118
119
  };
119
120
 
120
121
  return (
121
- <div className={!hideMenus ? 'app-container' : ''} data-theme={theme}>
122
- {!hideMenus && (
123
- <Sidebar
124
- version={PackageJson.version}
125
- theme={theme}
126
- sample={routerLocation.pathname}
127
- routes={ROUTES}
128
- routeList={ROUTE_LIST}
129
- onThemeChange={handleThemeChange}
130
- />
131
- )}
122
+ <HideMenusContext.Provider value={hideMenus}>
123
+ <div className={!hideMenus ? 'app-container' : ''} data-theme={theme}>
124
+ {!hideMenus && (
125
+ <Sidebar
126
+ version={PackageJson.version}
127
+ theme={theme}
128
+ sample={routerLocation.pathname}
129
+ routes={ROUTES}
130
+ routeList={ROUTE_LIST}
131
+ onThemeChange={handleThemeChange}
132
+ />
133
+ )}
132
134
 
133
- <div className="p-4" id="route-container">
134
- {!hideMenus && isDraftTheme(theme) && <KolBadge className="mb-3" _label="DRAFT" _color="#db5461" />}
135
- <Routes>
136
- {ROUTE_TREE}
137
- <Route path="*" element={<KolAlert _type="info">This code example has not been migrated yet - it&#39;s coming soon!</KolAlert>} />
138
- <Route path="back-page" element={<BackPage />} />
139
- </Routes>
135
+ <div className="p-4" id="route-container">
136
+ {!hideMenus && isDraftTheme(theme) && <KolBadge className="mb-3" _label="DRAFT" _color="#db5461" />}
137
+ <Routes>
138
+ {ROUTE_TREE}
139
+ <Route path="*" element={<KolAlert _type="info">This code example has not been migrated yet - it&#39;s coming soon!</KolAlert>} />
140
+ <Route path="back-page" element={<BackPage />} />
141
+ </Routes>
142
+ </div>
140
143
  </div>
141
- </div>
144
+ </HideMenusContext.Provider>
142
145
  );
143
146
  };
@@ -0,0 +1,23 @@
1
+ import type { FC, PropsWithChildren } from 'react';
2
+ import React, { useContext } from 'react';
3
+
4
+ import { KolIndentedText, KolLink } from '@public-ui/react';
5
+
6
+ import { HideMenusContext } from '../shares/HideMenusContext';
7
+
8
+ export const SampleDescription: FC<PropsWithChildren> = (props) => {
9
+ const hideMenus = useContext(HideMenusContext);
10
+
11
+ return hideMenus ? null : (
12
+ <div className="flex mb-sm">
13
+ <KolIndentedText>{props.children}</KolIndentedText>
14
+ <KolLink
15
+ _hideLabel
16
+ _href={`${location.href}?hideMenus`}
17
+ _label="Beispiel in neuem Tab öffnen"
18
+ _target="_blank"
19
+ className="mla flex-self-center"
20
+ ></KolLink>
21
+ </div>
22
+ );
23
+ };
@@ -0,0 +1,25 @@
1
+ import { KolAlert, KolCard, KolInputText } from '@public-ui/react';
2
+ import type { FC } from 'react';
3
+ import React from 'react';
4
+ import { SampleDescription } from '../SampleDescription';
5
+
6
+ export const InputTextHideErrors: FC = () => (
7
+ <div className="grid gap-4">
8
+ <SampleDescription>
9
+ This case shows the <code>_hideError</code> feature in the se. You can use the <code>_error</code> prop to show an error message.
10
+ </SampleDescription>
11
+ <KolCard _label="Normal input field with error" _level={0}>
12
+ <KolInputText _error="Error message" _label="Input with error" _touched />
13
+ </KolCard>
14
+ <KolCard _label="Input field with hidden error" _level={0}>
15
+ <fieldset className="grid md:grid-cols-2 gap-4">
16
+ <legend>Combined input field</legend>
17
+ <KolAlert className="col-span-2" _level={0} _type="error">
18
+ This is a combined error message
19
+ </KolAlert>
20
+ <KolInputText _error="This is a combined error message" _hideError _label="First input" _touched />
21
+ <KolInputText _error="This is a combined error message" _hideError _label="Second input with error" _touched />
22
+ </fieldset>
23
+ </KolCard>
24
+ </div>
25
+ );
@@ -14,7 +14,6 @@ export const InputTextCases = forwardRef<HTMLKolInputTextElement, Components.Kol
14
14
  _error={ERROR_MSG}
15
15
  _placeholder="Mit Icons"
16
16
  _icons={{
17
- left: 'codicon codicon-arrow-left',
18
17
  right: {
19
18
  icon: 'codicon codicon-arrow-right',
20
19
  style: {
@@ -28,13 +27,11 @@ export const InputTextCases = forwardRef<HTMLKolInputTextElement, Components.Kol
28
27
  onClick: console.log,
29
28
  onFocus: console.log,
30
29
  }}
31
- _hideLabel
32
30
  _required
33
31
  _type="search"
34
32
  _touched
35
- _label="Suche"
33
+ _label="Vorname (text)"
36
34
  />
37
- <KolInputText {...props} ref={ref} _placeholder="Placeholder" _label="Vorname (text)" _required />
38
35
  <KolInputText {...props} _placeholder="Placeholder" _label="Suche (search)" _type="search" />
39
36
  <KolInputText {...props} _placeholder="Placeholder" _error={ERROR_MSG} _touched _type="url" _label="URL (url)" />
40
37
  <KolInputText {...props} _placeholder="Placeholder" _type="tel" _label="Telefon (tel)" />
@@ -2,6 +2,7 @@ import { Routes } from '../../shares/types';
2
2
 
3
3
  import { InputTextBasic } from './basic';
4
4
  import { InputTextBlur } from './blur';
5
+ import { InputTextHideErrors } from './hide-errors';
5
6
  import { InputTextFocus } from './focus';
6
7
 
7
8
  export const INPUT_TEXT_ROUTES: Routes = {
@@ -9,5 +10,6 @@ export const INPUT_TEXT_ROUTES: Routes = {
9
10
  basic: InputTextBasic,
10
11
  blur: InputTextBlur,
11
12
  focus: InputTextFocus,
13
+ 'hide-errors': InputTextHideErrors,
12
14
  },
13
15
  };
@@ -1,4 +1,6 @@
1
- import React, { FC } from 'react';
1
+ import type { FC } from 'react';
2
+ import React from 'react';
3
+
2
4
  import { KolTabs } from '@public-ui/react';
3
5
 
4
6
  const tabs = [
@@ -20,11 +22,26 @@ const tabs = [
20
22
  _label: 'Letzter Tab',
21
23
  },
22
24
  ];
25
+
26
+ const tabsWithoutIcons = tabs.map((tab) => ({
27
+ ...tab,
28
+ _icons: undefined,
29
+ }));
30
+
23
31
  export const TabsBasic: FC = () => (
24
- <KolTabs _tabs={tabs}>
25
- <div slot="tab-0">Inhalte von Tab 1</div>
26
- <div slot="tab-1">Inhalte von Tab 2</div>
27
- <div slot="tab-2">Inhalte von Tab 3</div>
28
- <div slot="tab-3">Inhalte von Tab 4</div>
29
- </KolTabs>
32
+ <>
33
+ <KolTabs _tabs={tabsWithoutIcons} _label="Regular tabs">
34
+ <div slot="tab-0">Inhalte von Tab 1</div>
35
+ <div slot="tab-1">Inhalte von Tab 2</div>
36
+ <div slot="tab-2">Inhalte von Tab 3</div>
37
+ <div slot="tab-3">Inhalte von Tab 4</div>
38
+ </KolTabs>
39
+
40
+ <KolTabs _tabs={tabs} className="mt-4" _label="Tabs with icons">
41
+ <div slot="tab-0">Inhalte von Tab 1</div>
42
+ <div slot="tab-1">Inhalte von Tab 2</div>
43
+ <div slot="tab-2">Inhalte von Tab 3</div>
44
+ <div slot="tab-3">Inhalte von Tab 4</div>
45
+ </KolTabs>
46
+ </>
30
47
  );
@@ -1,9 +1,9 @@
1
- import React, { useEffect, useState } from 'react';
1
+ import React, { useEffect, useState, useRef } from 'react';
2
2
  import { KolTabs } from '@public-ui/react';
3
3
  import { DistrictForm } from './DistrictForm';
4
4
  import { Summary } from './Summary';
5
5
  import { PersonalInformationForm } from './PersonalInformationForm';
6
- import { Formik, FormikHelpers } from 'formik';
6
+ import { Formik, FormikHelpers, FormikProps } from 'formik';
7
7
  import * as Yup from 'yup';
8
8
  import { AvailableAppointmentsForm } from './AvailableAppointmentsForm';
9
9
  import { Iso8601 } from '@public-ui/components';
@@ -46,12 +46,12 @@ const districtSchema = {
46
46
  };
47
47
  const personalInformationSchema = {
48
48
  salutation: Yup.string().required('Bitte Anrede auswählen.'),
49
- name: Yup.string().required('Bitte Name eingeben.'),
49
+ name: Yup.string().required('Bitte Vor- und Zuname eingeben.'),
50
50
  company: Yup.string().when('salutation', {
51
51
  is: (salutation: string) => salutation === 'Firma',
52
- then: (schema) => schema.required('Bitte Firmenname angeben.'),
52
+ then: (schema) => schema.required('Bitte Firma angeben.'),
53
53
  }),
54
- email: Yup.string().required('Bitte E-Mail-Adresse eingeben.'),
54
+ email: Yup.string().required('Bitte E-Mail eingeben.'),
55
55
  };
56
56
  const availableAppointmentsSchema = {
57
57
  date: Yup.string().required('Bitte Datum eingeben.'),
@@ -64,6 +64,7 @@ const availableAppointmentsSchema = {
64
64
  export function AppointmentForm() {
65
65
  const [activeFormSection, setActiveFormSection] = useState(FormSection.DISTRICT);
66
66
  const [selectedTab, setSelectedTab] = useState(activeFormSection);
67
+ const formikRef = useRef<FormikProps<FormValues>>(null);
67
68
 
68
69
  const validationSchema = Yup.object().shape({
69
70
  ...(activeFormSection === FormSection.DISTRICT ? districtSchema : {}),
@@ -86,7 +87,7 @@ export function AppointmentForm() {
86
87
  };
87
88
 
88
89
  return (
89
- <Formik<FormValues> initialValues={initialValues} validationSchema={validationSchema} onSubmit={handleSubmit}>
90
+ <Formik<FormValues> innerRef={formikRef} initialValues={initialValues} validationSchema={validationSchema} onSubmit={handleSubmit}>
90
91
  <KolTabs
91
92
  _tabs={[
92
93
  {
@@ -107,7 +108,12 @@ export function AppointmentForm() {
107
108
  ]}
108
109
  _label="Formular-Navigation"
109
110
  _selected={selectedTab}
110
- _on={{ onSelect: (_event, selectedTab) => setActiveFormSection(selectedTab) }}
111
+ _on={{
112
+ onSelect: (_event, selectedTab) => {
113
+ setActiveFormSection(selectedTab);
114
+ formikRef.current?.setErrors({});
115
+ },
116
+ }}
111
117
  >
112
118
  <div>
113
119
  <DistrictForm />
@@ -1,16 +1,17 @@
1
1
  import React, { useEffect, useState } from 'react';
2
2
  import { KolButton, KolForm, KolHeading, KolInputDate, KolInputRadio, KolSpin } from '@public-ui/react';
3
3
  import { FormValues } from './AppointmentForm';
4
- import { ErrorList } from './ErrorList';
5
4
  import { Field, FieldProps, useFormikContext } from 'formik';
6
5
  import { fetchAvailableTimes } from './appointmentService';
7
6
  import { Option } from '@public-ui/components/src';
7
+ import { createErrorList } from './formUtils';
8
8
 
9
9
  export function AvailableAppointmentsForm() {
10
10
  const form = useFormikContext<FormValues>();
11
11
 
12
12
  const [sectionSubmitted, setSectionSubmitted] = useState(false);
13
13
  const [availableTimes, setAvailableTimes] = useState<Option<string>[] | null>(null);
14
+ const errorList = createErrorList(form.errors);
14
15
 
15
16
  useEffect(() => {
16
17
  let ignoreResponse = false;
@@ -36,14 +37,8 @@ export function AvailableAppointmentsForm() {
36
37
  return (
37
38
  <div className="p-2">
38
39
  <KolHeading _level={2} _label="Wählen Sie einen Termin aus"></KolHeading>
39
-
40
- {sectionSubmitted && Object.keys(form.errors).length ? (
41
- <div className="mt-2">
42
- <ErrorList errors={form.errors} />
43
- </div>
44
- ) : null}
45
-
46
40
  <KolForm
41
+ _errorList={sectionSubmitted ? errorList : []}
47
42
  _on={{
48
43
  onSubmit: () => {
49
44
  void form.submitForm();
@@ -81,7 +76,7 @@ export function AvailableAppointmentsForm() {
81
76
  <Field name="time">
82
77
  {({ field }: FieldProps<FormValues['time']>) => (
83
78
  <KolInputRadio
84
- id="field-date"
79
+ id="field-time"
85
80
  _label="Zeit"
86
81
  _orientation="horizontal"
87
82
  _options={availableTimes}
@@ -92,10 +87,12 @@ export function AvailableAppointmentsForm() {
92
87
  _on={{
93
88
  onChange: (event: Event, value: unknown): void => {
94
89
  if (event.target) {
95
- void form.setFieldTouched('time', true);
96
90
  void form.setFieldValue('time', value, true);
97
91
  }
98
92
  },
93
+ onBlur: () => {
94
+ void form.setFieldTouched('time', true);
95
+ },
99
96
  }}
100
97
  />
101
98
  )}
@@ -2,7 +2,7 @@ import React, { useState } from 'react';
2
2
  import { KolButton, KolForm, KolHeading, KolSelect } from '@public-ui/react';
3
3
  import { Field, FieldProps, useFormikContext } from 'formik';
4
4
  import { FormValues } from './AppointmentForm';
5
- import { ErrorListPropType } from '@public-ui/components';
5
+ import { createErrorList } from './formUtils';
6
6
 
7
7
  const LOCATION_OPTIONS = [
8
8
  {
@@ -32,13 +32,6 @@ export function DistrictForm() {
32
32
  const [sectionSubmitted, setSectionSubmitted] = useState(false);
33
33
  const errorList = createErrorList(form.errors);
34
34
 
35
- function createErrorList(formikErrors: Record<string, string>): ErrorListPropType[] {
36
- return Object.keys(formikErrors).map((fieldName) => ({
37
- message: formikErrors[fieldName],
38
- selector: `#field-${fieldName}`,
39
- }));
40
- }
41
-
42
35
  return (
43
36
  <div className="p-2">
44
37
  <KolHeading _level={2} _label="Wählen Sie einen Stadtteil aus"></KolHeading>
@@ -62,11 +55,13 @@ export function DistrictForm() {
62
55
  _touched={form.touched.district}
63
56
  _required
64
57
  _on={{
58
+ onBlur: () => {
59
+ void form.setFieldTouched('district', true);
60
+ },
65
61
  onChange: (event, values: unknown) => {
66
62
  // Select und Radio setzen den Wert immer initial.
67
63
  if (event.target) {
68
64
  const [value] = values as [FormValues['district']];
69
- void form.setFieldTouched('district', true);
70
65
  void form.setFieldValue('district', value, true);
71
66
  }
72
67
  },
@@ -2,6 +2,7 @@ import React, { useState } from 'react';
2
2
  import { KolButton, KolForm, KolHeading, KolInputEmail, KolInputText, KolSelect } from '@public-ui/react';
3
3
  import { Field, FieldProps, useFormikContext } from 'formik';
4
4
  import { FormValues } from './AppointmentForm';
5
+ import { createErrorList } from './formUtils';
5
6
 
6
7
  const SALUTATION_OPTIONS = [
7
8
  {
@@ -25,12 +26,13 @@ const SALUTATION_OPTIONS = [
25
26
  export function PersonalInformationForm() {
26
27
  const form = useFormikContext<FormValues>();
27
28
  const [sectionSubmitted, setSectionSubmitted] = useState(false);
29
+ const errorList = createErrorList(form.errors);
28
30
 
29
31
  return (
30
32
  <div className="p-2">
31
33
  <KolHeading _level={2} _label="Geben Sie Ihre Kontaktdaten ein"></KolHeading>
32
- <ul>{sectionSubmitted && Object.entries(form.errors).map(([field, error]) => <li key={field}>{error}</li>)}</ul>
33
34
  <KolForm
35
+ _errorList={sectionSubmitted ? errorList : []}
34
36
  _on={{
35
37
  onSubmit: () => {
36
38
  void form.submitForm();
@@ -41,6 +43,10 @@ export function PersonalInformationForm() {
41
43
  <Field name="salutation">
42
44
  {({ field }: FieldProps<FormValues['salutation']>) => (
43
45
  <KolSelect
46
+ onBlur={() => {
47
+ void form.setFieldTouched('salutation', true);
48
+ }}
49
+ id="field-salutation"
44
50
  _label="Anrede"
45
51
  _value={[field.value]}
46
52
  _error={form.errors.salutation || ''}
@@ -48,10 +54,12 @@ export function PersonalInformationForm() {
48
54
  _options={[{ label: 'Bitte wählen…', value: '' }, ...SALUTATION_OPTIONS]}
49
55
  _required
50
56
  _on={{
57
+ onBlur: () => {
58
+ void form.setFieldTouched('salutation', true);
59
+ },
51
60
  onChange: (event, values: unknown) => {
52
61
  if (event.target) {
53
62
  const [value] = values as [FormValues['salutation']];
54
- void form.setFieldTouched('salutation', true);
55
63
  void form.setFieldValue('salutation', value, true);
56
64
  }
57
65
  },
@@ -65,15 +73,18 @@ export function PersonalInformationForm() {
65
73
  {({ field }: FieldProps<FormValues['company']>) => (
66
74
  <div className="block mt-2">
67
75
  <KolInputText
76
+ id="field-company"
68
77
  _label="Firma"
69
78
  _value={field.value}
70
79
  _error={form.errors.company || ''}
71
80
  _touched={form.touched.company}
72
81
  _required
73
82
  _on={{
83
+ onBlur: () => {
84
+ void form.setFieldTouched('company', true);
85
+ },
74
86
  onChange: (event, value: unknown) => {
75
87
  if (event.target) {
76
- void form.setFieldTouched('company', true);
77
88
  void form.setFieldValue('company', value, true);
78
89
  }
79
90
  },
@@ -88,15 +99,18 @@ export function PersonalInformationForm() {
88
99
  {({ field }: FieldProps<FormValues['name']>) => (
89
100
  <div className="block mt-2">
90
101
  <KolInputText
102
+ id="field-name"
91
103
  _label="Vor- und Zuname"
92
104
  _value={field.value}
93
105
  _error={form.errors.name || ''}
94
106
  _touched={form.touched.name}
95
107
  _required
96
108
  _on={{
109
+ onBlur: () => {
110
+ void form.setFieldTouched('name', true);
111
+ },
97
112
  onChange: (event, value: unknown) => {
98
113
  if (event.target) {
99
- void form.setFieldTouched('name', true);
100
114
  void form.setFieldValue('name', value, true);
101
115
  }
102
116
  },
@@ -110,15 +124,21 @@ export function PersonalInformationForm() {
110
124
  {({ field }: FieldProps<FormValues['email']>) => (
111
125
  <div className="block mt-2">
112
126
  <KolInputEmail
127
+ onBlur={() => {
128
+ void form.setFieldTouched('email', true);
129
+ }}
130
+ id="field-email"
113
131
  _label="E-Mail"
114
132
  _value={field.value}
115
133
  _error={form.errors.email || ''}
116
134
  _touched={form.touched.email}
117
135
  _required
118
136
  _on={{
137
+ onBlur: () => {
138
+ void form.setFieldTouched('email', true);
139
+ },
119
140
  onChange: (event, value: unknown) => {
120
141
  if (event.target) {
121
- void form.setFieldTouched('email', true);
122
142
  void form.setFieldValue('email', value, true);
123
143
  }
124
144
  },
@@ -132,15 +152,18 @@ export function PersonalInformationForm() {
132
152
  {({ field }: FieldProps<FormValues['phone']>) => (
133
153
  <div className="block mt-2">
134
154
  <KolInputText
155
+ id="field-phone"
135
156
  _type="tel"
136
157
  _label="Telefonnumer"
137
158
  _value={field.value}
138
159
  _error={form.errors.phone || ''}
139
160
  _touched={form.touched.phone}
140
161
  _on={{
162
+ onBlur: () => {
163
+ void form.setFieldTouched('phone', true);
164
+ },
141
165
  onChange: (event, value: unknown) => {
142
166
  if (event.target) {
143
- void form.setFieldTouched('phone', true);
144
167
  void form.setFieldValue('phone', value, true);
145
168
  }
146
169
  },
@@ -0,0 +1,8 @@
1
+ import type { ErrorListPropType } from '@public-ui/components';
2
+
3
+ export function createErrorList(formikErrors: Record<string, string>): ErrorListPropType[] {
4
+ return Object.keys(formikErrors).map((fieldName) => ({
5
+ message: formikErrors[fieldName],
6
+ selector: `#field-${fieldName}`,
7
+ }));
8
+ }
@@ -1,12 +1,14 @@
1
1
  import { Routes } from '../shares/types';
2
- import { TerminComponent } from './complex-form/component';
3
2
  import { AppointmentForm } from './appointment-form/AppointmentForm';
3
+ import { TerminComponent } from './complex-form/component';
4
4
  import { CustomTooltipWidth } from './custom-tooltip-width';
5
+ import { StaticForm } from './static-form';
5
6
 
6
7
  export const SCENARIO_ROUTES: Routes = {
7
8
  scenarios: {
8
9
  'complex-form': TerminComponent,
9
10
  'appointment-form': AppointmentForm,
10
11
  'custom-tooltip-width': CustomTooltipWidth,
12
+ 'static-form': StaticForm,
11
13
  },
12
14
  };