@oneblink/apps-react 2.10.0-beta.1 → 2.10.0-beta.3

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 (90) hide show
  1. package/dist/components/renderer/AutocompleteDropdown.d.ts +3 -2
  2. package/dist/components/renderer/AutocompleteDropdown.js +12 -5
  3. package/dist/components/renderer/AutocompleteDropdown.js.map +1 -1
  4. package/dist/components/renderer/OneBlinkFormElements.js +49 -36
  5. package/dist/components/renderer/OneBlinkFormElements.js.map +1 -1
  6. package/dist/form-elements/FormElementABN.d.ts +3 -3
  7. package/dist/form-elements/FormElementABN.js +1 -2
  8. package/dist/form-elements/FormElementABN.js.map +1 -1
  9. package/dist/form-elements/FormElementAutocomplete.d.ts +2 -2
  10. package/dist/form-elements/FormElementAutocomplete.js +4 -4
  11. package/dist/form-elements/FormElementAutocomplete.js.map +1 -1
  12. package/dist/form-elements/FormElementBSB.d.ts +3 -3
  13. package/dist/form-elements/FormElementBSB.js +1 -3
  14. package/dist/form-elements/FormElementBSB.js.map +1 -1
  15. package/dist/form-elements/FormElementBarcodeScanner.d.ts +3 -3
  16. package/dist/form-elements/FormElementBarcodeScanner.js +1 -2
  17. package/dist/form-elements/FormElementBarcodeScanner.js.map +1 -1
  18. package/dist/form-elements/FormElementBoolean.d.ts +3 -3
  19. package/dist/form-elements/FormElementBoolean.js +1 -3
  20. package/dist/form-elements/FormElementBoolean.js.map +1 -1
  21. package/dist/form-elements/FormElementCamera.d.ts +3 -3
  22. package/dist/form-elements/FormElementCamera.js +1 -2
  23. package/dist/form-elements/FormElementCamera.js.map +1 -1
  24. package/dist/form-elements/FormElementCheckBoxes.js +3 -1
  25. package/dist/form-elements/FormElementCheckBoxes.js.map +1 -1
  26. package/dist/form-elements/FormElementCivicaStreetName.d.ts +3 -3
  27. package/dist/form-elements/FormElementCivicaStreetName.js +2 -2
  28. package/dist/form-elements/FormElementCivicaStreetName.js.map +1 -1
  29. package/dist/form-elements/FormElementCompliance.d.ts +3 -3
  30. package/dist/form-elements/FormElementCompliance.js +3 -5
  31. package/dist/form-elements/FormElementCompliance.js.map +1 -1
  32. package/dist/form-elements/FormElementDate.d.ts +3 -3
  33. package/dist/form-elements/FormElementDate.js +1 -3
  34. package/dist/form-elements/FormElementDate.js.map +1 -1
  35. package/dist/form-elements/FormElementDateTime.d.ts +3 -3
  36. package/dist/form-elements/FormElementDateTime.js +1 -3
  37. package/dist/form-elements/FormElementDateTime.js.map +1 -1
  38. package/dist/form-elements/FormElementEmail.d.ts +3 -3
  39. package/dist/form-elements/FormElementEmail.js +1 -3
  40. package/dist/form-elements/FormElementEmail.js.map +1 -1
  41. package/dist/form-elements/FormElementFiles.d.ts +3 -3
  42. package/dist/form-elements/FormElementFiles.js +2 -2
  43. package/dist/form-elements/FormElementFiles.js.map +1 -1
  44. package/dist/form-elements/FormElementGeoscapeAddress.d.ts +3 -3
  45. package/dist/form-elements/FormElementGeoscapeAddress.js +2 -2
  46. package/dist/form-elements/FormElementGeoscapeAddress.js.map +1 -1
  47. package/dist/form-elements/FormElementLocation.d.ts +3 -3
  48. package/dist/form-elements/FormElementLocation.js +1 -2
  49. package/dist/form-elements/FormElementLocation.js.map +1 -1
  50. package/dist/form-elements/FormElementNumber.d.ts +3 -3
  51. package/dist/form-elements/FormElementNumber.js +1 -3
  52. package/dist/form-elements/FormElementNumber.js.map +1 -1
  53. package/dist/form-elements/FormElementPointAddress.d.ts +3 -3
  54. package/dist/form-elements/FormElementPointAddress.js +2 -2
  55. package/dist/form-elements/FormElementPointAddress.js.map +1 -1
  56. package/dist/form-elements/FormElementRadio.d.ts +3 -3
  57. package/dist/form-elements/FormElementRadio.js +1 -3
  58. package/dist/form-elements/FormElementRadio.js.map +1 -1
  59. package/dist/form-elements/FormElementRepeatableSet.d.ts +3 -3
  60. package/dist/form-elements/FormElementRepeatableSet.js +18 -12
  61. package/dist/form-elements/FormElementRepeatableSet.js.map +1 -1
  62. package/dist/form-elements/FormElementSection.js +10 -12
  63. package/dist/form-elements/FormElementSection.js.map +1 -1
  64. package/dist/form-elements/FormElementSelect.d.ts +3 -3
  65. package/dist/form-elements/FormElementSelect.js +1 -3
  66. package/dist/form-elements/FormElementSelect.js.map +1 -1
  67. package/dist/form-elements/FormElementSignature.d.ts +3 -2
  68. package/dist/form-elements/FormElementSignature.js +1 -3
  69. package/dist/form-elements/FormElementSignature.js.map +1 -1
  70. package/dist/form-elements/FormElementTelephone.d.ts +3 -3
  71. package/dist/form-elements/FormElementTelephone.js +1 -3
  72. package/dist/form-elements/FormElementTelephone.js.map +1 -1
  73. package/dist/form-elements/FormElementText.d.ts +3 -3
  74. package/dist/form-elements/FormElementText.js +1 -3
  75. package/dist/form-elements/FormElementText.js.map +1 -1
  76. package/dist/form-elements/FormElementTextarea.d.ts +3 -3
  77. package/dist/form-elements/FormElementTextarea.js +1 -3
  78. package/dist/form-elements/FormElementTextarea.js.map +1 -1
  79. package/dist/form-elements/FormElementTime.d.ts +3 -3
  80. package/dist/form-elements/FormElementTime.js +1 -3
  81. package/dist/form-elements/FormElementTime.js.map +1 -1
  82. package/dist/hooks/attachments/useAttachments.d.ts +2 -3
  83. package/dist/hooks/attachments/useAttachments.js +1 -4
  84. package/dist/hooks/attachments/useAttachments.js.map +1 -1
  85. package/dist/hooks/useValidationClass.d.ts +9 -0
  86. package/dist/hooks/useValidationClass.js +18 -0
  87. package/dist/hooks/useValidationClass.js.map +1 -0
  88. package/dist/types/form.d.ts +4 -0
  89. package/dist/types/form.js.map +1 -1
  90. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"FormElementABN.js","sourceRoot":"","sources":["../../src/form-elements/FormElementABN.tsx"],"names":[],"mappings":"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","sourcesContent":["import * as React from 'react'\nimport clsx from 'clsx'\nimport InputMask from 'react-input-mask'\nimport { parseString } from 'xml2js'\nimport CopyToClipboardButton from '../components/renderer/CopyToClipboardButton'\nimport useBooleanState from '../hooks/useBooleanState'\nimport LookupButton from '../components/renderer/LookupButton'\nimport { FormTypes, MiscTypes } from '@oneblink/types'\nimport FormElementLabelContainer from '../components/renderer/FormElementLabelContainer'\nimport { FormElementValueChangeHandler } from '../types/form'\nimport useAbnLookupAuthenticationGuid from '../hooks/useAbnLookupAuthenticationGuid'\nimport { abnService } from '@oneblink/sdk-core'\ntype Props = {\n id: string\n element: FormTypes.ABNElement\n value: MiscTypes.ABNRecord | undefined\n onChange: FormElementValueChangeHandler<MiscTypes.ABNRecord>\n displayValidationMessage: boolean\n validationMessage: string | undefined\n}\n\nfunction FormElementABN({\n id,\n element,\n value,\n onChange,\n validationMessage,\n displayValidationMessage,\n}: Props) {\n const abnLookupAuthenticationGuid = useAbnLookupAuthenticationGuid()\n const [label, setLabel] = React.useState(\n value ? abnService.getABNNumberFromABNRecord(value) || '' : '',\n )\n const [isFocused, setIsFocused, removeFocus] = useBooleanState(false)\n const [isDirty, setIsDirty] = useBooleanState(false)\n const [{ isLoading, error }, setState] = React.useState<{\n isLoading: boolean\n error: Error | null\n }>({\n isLoading: false,\n error: null,\n })\n\n React.useEffect(() => {\n const searchString = label.replace(/[^\\d]/g, '')\n const isSearchStringValid =\n searchString.length === 11 || (searchString.length === 9 && !isFocused)\n\n const currentABNNumber = value\n ? abnService.getABNNumberFromABNRecord(value)\n : ''\n if (!isSearchStringValid || currentABNNumber === searchString) {\n return\n }\n\n setState({\n isLoading: true,\n error: null,\n })\n\n const abortController = new AbortController()\n const fetchRecord = async () => {\n try {\n const urlSearchParams = new URLSearchParams()\n urlSearchParams.append('searchString', searchString)\n urlSearchParams.append('includeHistoricalDetails', 'N')\n if (abnLookupAuthenticationGuid) {\n urlSearchParams.append(\n 'authenticationGuid',\n abnLookupAuthenticationGuid,\n )\n }\n\n const url =\n searchString.length === 11\n ? 'https://abr.business.gov.au/abrxmlsearch/AbrXmlSearch.asmx/SearchByABNv202001'\n : 'https://abr.business.gov.au/abrxmlsearch/AbrXmlSearch.asmx/SearchByASICv201408'\n const response = await fetch(`${url}?${urlSearchParams.toString()}`, {\n mode: 'cors',\n signal: abortController.signal,\n })\n const text = await response.text()\n if (!response.ok) {\n throw new Error(text)\n }\n\n const result = await new Promise<{\n ABRPayloadSearchResults: {\n response: {\n businessEntity201408?: MiscTypes.ABNRecord\n businessEntity202001: MiscTypes.ABNRecord\n exception?: {\n exceptionDescription: string\n exceptionCode: string\n }\n }\n }\n }>((resolve, reject) => {\n parseString(\n text,\n {\n explicitArray: false,\n },\n (err, result) => {\n if (err) {\n reject(err)\n } else {\n resolve(result)\n }\n },\n )\n })\n if (result.ABRPayloadSearchResults.response.exception) {\n throw new Error(\n result.ABRPayloadSearchResults.response.exception.exceptionDescription,\n )\n }\n\n if (result.ABRPayloadSearchResults.response.businessEntity201408) {\n result.ABRPayloadSearchResults.response.businessEntity202001 =\n result.ABRPayloadSearchResults.response.businessEntity201408\n }\n\n if (\n !Array.isArray(\n result.ABRPayloadSearchResults.response.businessEntity202001\n .businessName,\n )\n ) {\n result.ABRPayloadSearchResults.response.businessEntity202001.businessName =\n [\n result.ABRPayloadSearchResults.response.businessEntity202001\n .businessName,\n ]\n }\n\n if (!abortController.signal.aborted) {\n onChange(\n element,\n result.ABRPayloadSearchResults.response.businessEntity202001,\n )\n setState({\n isLoading: false,\n error: null,\n })\n }\n } catch (err) {\n if (!abortController.signal.aborted) {\n setState({\n isLoading: false,\n error: err as Error,\n })\n }\n }\n }\n\n fetchRecord()\n\n return () => {\n abortController.abort()\n }\n }, [abnLookupAuthenticationGuid, element, isFocused, label, onChange, value])\n\n // Ensure the label is set if the value is set outside of this component\n React.useEffect(() => {\n if (value) {\n const newLabel = abnService.getABNNumberFromABNRecord(value)\n if (!newLabel) {\n // Record in value had no ABN Number. This should never happen\n return\n }\n if (label !== newLabel) {\n setLabel(\n newLabel.split('').reduce((memo, character, index) => {\n switch (index) {\n case 2:\n case 5:\n case 8: {\n return `${memo} ${character}`\n }\n default: {\n return `${memo}${character}`\n }\n }\n }, ''),\n )\n }\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [value])\n\n return (\n <div className=\"cypress-abn-element\">\n <FormElementLabelContainer\n className=\"ob-abn\"\n id={id}\n element={element}\n required={element.required}\n >\n <div className=\"field has-addons\">\n <div\n className={clsx('control is-expanded', {\n 'is-loading': isLoading,\n })}\n >\n <InputMask\n mask={isFocused || value ? '99 999 999 999' : '999 999 999'}\n // @ts-expect-error \"react-input-mask\" types do not match code\n maskChar=\" \"\n type=\"text\"\n id={id}\n name={element.name}\n className=\"input ob-input cypress-abn-control\"\n placeholder={element.placeholderValue}\n value={label}\n onChange={(e) => {\n setLabel(e.target.value)\n if (value) {\n onChange(element, undefined)\n }\n }}\n required={element.required}\n disabled={element.readOnly}\n onBlur={() => {\n setIsDirty()\n removeFocus()\n }}\n onFocus={setIsFocused}\n />\n </div>\n {value && (\n <div className=\"control ob-abn__record-control\">\n <a className=\"button is-static ob-abn__record-button\">\n {abnService.displayBusinessNameFromABNRecord(value)}\n </a>\n </div>\n )}\n {!!element.readOnly && !!value && (\n <div className=\"control\">\n <CopyToClipboardButton\n className=\"button is-input-addon copy-button cypress-copy-to-clipboard-button\"\n text={label}\n />\n </div>\n )}\n <LookupButton\n isInputButton\n value={value}\n validationMessage={validationMessage}\n />\n </div>\n {(((isDirty || displayValidationMessage) &&\n !!validationMessage &&\n !isLoading) ||\n error) && (\n <div role=\"alert\" className=\"has-margin-top-8\">\n <div className=\"has-text-danger ob-error__text cypress-validation-message\">\n {error?.message || validationMessage}\n </div>\n </div>\n )}\n </FormElementLabelContainer>\n </div>\n )\n}\n\nexport default React.memo(FormElementABN)\n"]}
1
+ {"version":3,"file":"FormElementABN.js","sourceRoot":"","sources":["../../src/form-elements/FormElementABN.tsx"],"names":[],"mappings":"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","sourcesContent":["import * as React from 'react'\nimport clsx from 'clsx'\nimport InputMask from 'react-input-mask'\nimport { parseString } from 'xml2js'\nimport CopyToClipboardButton from '../components/renderer/CopyToClipboardButton'\nimport useBooleanState from '../hooks/useBooleanState'\nimport LookupButton from '../components/renderer/LookupButton'\nimport { FormTypes, MiscTypes } from '@oneblink/types'\nimport FormElementLabelContainer from '../components/renderer/FormElementLabelContainer'\nimport { FormElementValueChangeHandler, IsDirtyProps } from '../types/form'\nimport useAbnLookupAuthenticationGuid from '../hooks/useAbnLookupAuthenticationGuid'\nimport { abnService } from '@oneblink/sdk-core'\ntype Props = {\n id: string\n element: FormTypes.ABNElement\n value: MiscTypes.ABNRecord | undefined\n onChange: FormElementValueChangeHandler<MiscTypes.ABNRecord>\n displayValidationMessage: boolean\n validationMessage: string | undefined\n} & IsDirtyProps\n\nfunction FormElementABN({\n id,\n element,\n value,\n onChange,\n validationMessage,\n displayValidationMessage,\n isDirty,\n setIsDirty,\n}: Props) {\n const abnLookupAuthenticationGuid = useAbnLookupAuthenticationGuid()\n const [label, setLabel] = React.useState(\n value ? abnService.getABNNumberFromABNRecord(value) || '' : '',\n )\n const [isFocused, setIsFocused, removeFocus] = useBooleanState(false)\n const [{ isLoading, error }, setState] = React.useState<{\n isLoading: boolean\n error: Error | null\n }>({\n isLoading: false,\n error: null,\n })\n\n React.useEffect(() => {\n const searchString = label.replace(/[^\\d]/g, '')\n const isSearchStringValid =\n searchString.length === 11 || (searchString.length === 9 && !isFocused)\n\n const currentABNNumber = value\n ? abnService.getABNNumberFromABNRecord(value)\n : ''\n if (!isSearchStringValid || currentABNNumber === searchString) {\n return\n }\n\n setState({\n isLoading: true,\n error: null,\n })\n\n const abortController = new AbortController()\n const fetchRecord = async () => {\n try {\n const urlSearchParams = new URLSearchParams()\n urlSearchParams.append('searchString', searchString)\n urlSearchParams.append('includeHistoricalDetails', 'N')\n if (abnLookupAuthenticationGuid) {\n urlSearchParams.append(\n 'authenticationGuid',\n abnLookupAuthenticationGuid,\n )\n }\n\n const url =\n searchString.length === 11\n ? 'https://abr.business.gov.au/abrxmlsearch/AbrXmlSearch.asmx/SearchByABNv202001'\n : 'https://abr.business.gov.au/abrxmlsearch/AbrXmlSearch.asmx/SearchByASICv201408'\n const response = await fetch(`${url}?${urlSearchParams.toString()}`, {\n mode: 'cors',\n signal: abortController.signal,\n })\n const text = await response.text()\n if (!response.ok) {\n throw new Error(text)\n }\n\n const result = await new Promise<{\n ABRPayloadSearchResults: {\n response: {\n businessEntity201408?: MiscTypes.ABNRecord\n businessEntity202001: MiscTypes.ABNRecord\n exception?: {\n exceptionDescription: string\n exceptionCode: string\n }\n }\n }\n }>((resolve, reject) => {\n parseString(\n text,\n {\n explicitArray: false,\n },\n (err, result) => {\n if (err) {\n reject(err)\n } else {\n resolve(result)\n }\n },\n )\n })\n if (result.ABRPayloadSearchResults.response.exception) {\n throw new Error(\n result.ABRPayloadSearchResults.response.exception.exceptionDescription,\n )\n }\n\n if (result.ABRPayloadSearchResults.response.businessEntity201408) {\n result.ABRPayloadSearchResults.response.businessEntity202001 =\n result.ABRPayloadSearchResults.response.businessEntity201408\n }\n\n if (\n !Array.isArray(\n result.ABRPayloadSearchResults.response.businessEntity202001\n .businessName,\n )\n ) {\n result.ABRPayloadSearchResults.response.businessEntity202001.businessName =\n [\n result.ABRPayloadSearchResults.response.businessEntity202001\n .businessName,\n ]\n }\n\n if (!abortController.signal.aborted) {\n onChange(\n element,\n result.ABRPayloadSearchResults.response.businessEntity202001,\n )\n setState({\n isLoading: false,\n error: null,\n })\n }\n } catch (err) {\n if (!abortController.signal.aborted) {\n setState({\n isLoading: false,\n error: err as Error,\n })\n }\n }\n }\n\n fetchRecord()\n\n return () => {\n abortController.abort()\n }\n }, [abnLookupAuthenticationGuid, element, isFocused, label, onChange, value])\n\n // Ensure the label is set if the value is set outside of this component\n React.useEffect(() => {\n if (value) {\n const newLabel = abnService.getABNNumberFromABNRecord(value)\n if (!newLabel) {\n // Record in value had no ABN Number. This should never happen\n return\n }\n if (label !== newLabel) {\n setLabel(\n newLabel.split('').reduce((memo, character, index) => {\n switch (index) {\n case 2:\n case 5:\n case 8: {\n return `${memo} ${character}`\n }\n default: {\n return `${memo}${character}`\n }\n }\n }, ''),\n )\n }\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [value])\n\n return (\n <div className=\"cypress-abn-element\">\n <FormElementLabelContainer\n className=\"ob-abn\"\n id={id}\n element={element}\n required={element.required}\n >\n <div className=\"field has-addons\">\n <div\n className={clsx('control is-expanded', {\n 'is-loading': isLoading,\n })}\n >\n <InputMask\n mask={isFocused || value ? '99 999 999 999' : '999 999 999'}\n // @ts-expect-error \"react-input-mask\" types do not match code\n maskChar=\" \"\n type=\"text\"\n id={id}\n name={element.name}\n className=\"input ob-input cypress-abn-control\"\n placeholder={element.placeholderValue}\n value={label}\n onChange={(e) => {\n setLabel(e.target.value)\n if (value) {\n onChange(element, undefined)\n }\n }}\n required={element.required}\n disabled={element.readOnly}\n onBlur={() => {\n setIsDirty()\n removeFocus()\n }}\n onFocus={setIsFocused}\n />\n </div>\n {value && (\n <div className=\"control ob-abn__record-control\">\n <a className=\"button is-static ob-abn__record-button\">\n {abnService.displayBusinessNameFromABNRecord(value)}\n </a>\n </div>\n )}\n {!!element.readOnly && !!value && (\n <div className=\"control\">\n <CopyToClipboardButton\n className=\"button is-input-addon copy-button cypress-copy-to-clipboard-button\"\n text={label}\n />\n </div>\n )}\n <LookupButton\n isInputButton\n value={value}\n validationMessage={validationMessage}\n />\n </div>\n {(((isDirty || displayValidationMessage) &&\n !!validationMessage &&\n !isLoading) ||\n error) && (\n <div role=\"alert\" className=\"has-margin-top-8\">\n <div className=\"has-text-danger ob-error__text cypress-validation-message\">\n {error?.message || validationMessage}\n </div>\n </div>\n )}\n </FormElementLabelContainer>\n </div>\n )\n}\n\nexport default React.memo(FormElementABN)\n"]}
@@ -1,13 +1,13 @@
1
1
  import * as React from 'react';
2
2
  import { FormTypes } from '@oneblink/types';
3
- import { FormElementValueChangeHandler, FormElementConditionallyShownElement } from '../types/form';
3
+ import { FormElementValueChangeHandler, FormElementConditionallyShownElement, IsDirtyProps } from '../types/form';
4
4
  declare type _BaseProps = {
5
5
  id: string;
6
6
  element: FormTypes.AutoCompleteElement;
7
7
  value: unknown | undefined;
8
8
  displayValidationMessage: boolean;
9
9
  validationMessage: string | undefined;
10
- };
10
+ } & IsDirtyProps;
11
11
  declare type _AutocompleteConditionallyShowOptionProps = {
12
12
  conditionallyShownOptionsElement: FormElementConditionallyShownElement | undefined;
13
13
  };
@@ -5,7 +5,7 @@ import FormElementOptions from '../components/renderer/FormElementOptions';
5
5
  import useFormElementOptions from '../hooks/useFormElementOptions';
6
6
  import AutocompleteDropdown from '../components/renderer/AutocompleteDropdown';
7
7
  import FormElementLabelContainer from '../components/renderer/FormElementLabelContainer';
8
- const AutocompleteFilter = React.memo(function AutocompleteFilter({ id, element, value, onChange, conditionallyShownOptionsElement, validationMessage, displayValidationMessage, }) {
8
+ const AutocompleteFilter = React.memo(function AutocompleteFilter({ id, element, value, onChange, conditionallyShownOptionsElement, validationMessage, displayValidationMessage, isDirty, setIsDirty, }) {
9
9
  const [label, setLabel] = React.useState('');
10
10
  const onFilter = React.useCallback((option) => {
11
11
  // If the user has typed nothing in, display all options
@@ -42,9 +42,9 @@ const AutocompleteFilter = React.memo(function AutocompleteFilter({ id, element,
42
42
  return (React.createElement("div", { className: "cypress-autocomplete-filter-element" },
43
43
  React.createElement(FormElementLabelContainer, { className: "ob-autocomplete", element: element, id: id, required: element.required },
44
44
  React.createElement(FormElementOptions, { options: element.options, conditionallyShownOptionsElement: conditionallyShownOptionsElement },
45
- React.createElement(AutocompleteDropdown, { id: id, label: label, disabled: element.readOnly, placeholder: element.placeholderValue, required: element.required, value: value, validationMessage: validationMessage, displayValidationMessage: displayValidationMessage, onChangeValue: onChange, onChangeLabel: setLabel, onSearch: handleSearch, searchDebounceMs: 0, searchMinCharacters: 0 })))));
45
+ React.createElement(AutocompleteDropdown, { id: id, label: label, disabled: element.readOnly, placeholder: element.placeholderValue, required: element.required, value: value, validationMessage: validationMessage, displayValidationMessage: displayValidationMessage, onChangeValue: onChange, onChangeLabel: setLabel, onSearch: handleSearch, searchDebounceMs: 0, searchMinCharacters: 0, isDirty: isDirty, setIsDirty: setIsDirty })))));
46
46
  });
47
- const AutocompleteFetch = React.memo(function AutocompleteFetch({ id, element, value, onChange, validationMessage, displayValidationMessage, searchUrl, }) {
47
+ const AutocompleteFetch = React.memo(function AutocompleteFetch({ id, element, value, onChange, validationMessage, displayValidationMessage, searchUrl, isDirty, setIsDirty, }) {
48
48
  const [label, setLabel] = React.useState('');
49
49
  const handleSearch = React.useCallback(async (search, abortSignal) => {
50
50
  const headers = await generateHeaders();
@@ -70,7 +70,7 @@ const AutocompleteFetch = React.memo(function AutocompleteFetch({ id, element, v
70
70
  }, [value]);
71
71
  return (React.createElement("div", { className: "cypress-autocomplete-search-element" },
72
72
  React.createElement(FormElementLabelContainer, { className: "ob-autocomplete", element: element, id: id, required: element.required },
73
- React.createElement(AutocompleteDropdown, { id: id, label: label, disabled: element.readOnly, placeholder: element.placeholderValue, required: element.required, value: value, validationMessage: validationMessage, displayValidationMessage: displayValidationMessage, onChangeValue: onChange, onChangeLabel: setLabel, searchDebounceMs: 750, searchMinCharacters: 1, onSearch: handleSearch }))));
73
+ React.createElement(AutocompleteDropdown, { id: id, label: label, disabled: element.readOnly, placeholder: element.placeholderValue, required: element.required, value: value, validationMessage: validationMessage, displayValidationMessage: displayValidationMessage, onChangeValue: onChange, onChangeLabel: setLabel, searchDebounceMs: 750, searchMinCharacters: 1, onSearch: handleSearch, isDirty: isDirty, setIsDirty: setIsDirty }))));
74
74
  });
75
75
  function FormElementAutocomplete({ conditionallyShownOptionsElement, onChange, ...props }) {
76
76
  const handleChange = React.useCallback((newValue) => {
@@ -1 +1 @@
1
- {"version":3,"file":"FormElementAutocomplete.js","sourceRoot":"","sources":["../../src/form-elements/FormElementAutocomplete.tsx"],"names":[],"mappings":"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","sourcesContent":["import * as React from 'react'\nimport { formElementsService } from '@oneblink/sdk-core'\nimport { generateHeaders } from '@oneblink/apps/dist/services/fetch'\n\nimport FormElementOptions from '../components/renderer/FormElementOptions'\nimport useFormElementOptions from '../hooks/useFormElementOptions'\nimport AutocompleteDropdown from '../components/renderer/AutocompleteDropdown'\nimport FormElementLabelContainer from '../components/renderer/FormElementLabelContainer'\nimport { FormTypes } from '@oneblink/types'\nimport {\n FormElementValueChangeHandler,\n FormElementConditionallyShownElement,\n} from '../types/form'\n\ntype _BaseProps = {\n id: string\n element: FormTypes.AutoCompleteElement\n value: unknown | undefined\n displayValidationMessage: boolean\n validationMessage: string | undefined\n}\n\ntype _AutocompleteChangeHandlerProps = _BaseProps & {\n onChange: (newValue: unknown | undefined) => void\n}\n\ntype _AutocompleteConditionallyShowOptionProps = {\n conditionallyShownOptionsElement:\n | FormElementConditionallyShownElement\n | undefined\n}\n\ntype AutocompleteFilterProps = _AutocompleteChangeHandlerProps &\n _AutocompleteConditionallyShowOptionProps\n\ntype AutocompleteFetchProps = _AutocompleteChangeHandlerProps & {\n searchUrl: string\n}\n\ntype Props = _BaseProps &\n _AutocompleteConditionallyShowOptionProps & {\n onChange: FormElementValueChangeHandler<string>\n }\n\nconst AutocompleteFilter = React.memo(function AutocompleteFilter({\n id,\n element,\n value,\n onChange,\n conditionallyShownOptionsElement,\n validationMessage,\n displayValidationMessage,\n}: AutocompleteFilterProps) {\n const [label, setLabel] = React.useState('')\n\n const onFilter = React.useCallback(\n (option) => {\n // If the user has typed nothing in, display all options\n if (!label) {\n return true\n }\n\n const lowerCase = label.toLowerCase()\n\n return option.label.toLowerCase().includes(lowerCase)\n },\n [label],\n )\n\n const handleChange = React.useCallback(\n //useFormElementOptions expects the first arg to be the element\n (element: FormTypes.FormElement, newValue: unknown) => onChange(newValue),\n [onChange],\n )\n\n const filteredOptions = useFormElementOptions({\n element,\n value,\n onChange: handleChange,\n conditionallyShownOptionsElement,\n onFilter,\n })\n\n const handleSearch = React.useCallback(async () => {\n return filteredOptions\n }, [filteredOptions])\n\n // Ensure the label matches the value selected\n React.useEffect(() => {\n if (!Array.isArray(element.options)) {\n return\n }\n\n const option = element.options.find((option) => option.value === value)\n if (option && label !== option.label) {\n setLabel(option.label)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [element.options, value])\n\n return (\n <div className=\"cypress-autocomplete-filter-element\">\n <FormElementLabelContainer\n className=\"ob-autocomplete\"\n element={element}\n id={id}\n required={element.required}\n >\n <FormElementOptions\n options={element.options}\n conditionallyShownOptionsElement={conditionallyShownOptionsElement}\n >\n <AutocompleteDropdown\n id={id}\n label={label}\n disabled={element.readOnly}\n placeholder={element.placeholderValue}\n required={element.required}\n value={value}\n validationMessage={validationMessage}\n displayValidationMessage={displayValidationMessage}\n onChangeValue={onChange}\n onChangeLabel={setLabel}\n onSearch={handleSearch}\n searchDebounceMs={0}\n searchMinCharacters={0}\n />\n </FormElementOptions>\n </FormElementLabelContainer>\n </div>\n )\n})\n\nconst AutocompleteFetch = React.memo(function AutocompleteFetch({\n id,\n element,\n value,\n onChange,\n validationMessage,\n displayValidationMessage,\n searchUrl,\n}: AutocompleteFetchProps) {\n const [label, setLabel] = React.useState('')\n\n const handleSearch = React.useCallback(\n async (search, abortSignal) => {\n const headers = await generateHeaders()\n const url = new URL(searchUrl)\n url.searchParams.append('value', search)\n const response = await fetch(url.href, {\n headers,\n signal: abortSignal,\n })\n\n if (!response.ok) {\n const text = await response.text()\n throw new Error(text)\n }\n\n const data = await response.json()\n return formElementsService.parseFormElementOptionsSet(data)\n },\n [searchUrl],\n )\n\n // Ensure the label is set if the value is set outside of this component\n React.useEffect(() => {\n if (!label && typeof value === 'string') {\n setLabel(value)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [value])\n\n return (\n <div className=\"cypress-autocomplete-search-element\">\n <FormElementLabelContainer\n className=\"ob-autocomplete\"\n element={element}\n id={id}\n required={element.required}\n >\n <AutocompleteDropdown\n id={id}\n label={label}\n disabled={element.readOnly}\n placeholder={element.placeholderValue}\n required={element.required}\n value={value}\n validationMessage={validationMessage}\n displayValidationMessage={displayValidationMessage}\n onChangeValue={onChange}\n onChangeLabel={setLabel}\n searchDebounceMs={750}\n searchMinCharacters={1}\n onSearch={handleSearch}\n />\n </FormElementLabelContainer>\n </div>\n )\n})\n\nfunction FormElementAutocomplete({\n conditionallyShownOptionsElement,\n onChange,\n ...props\n}: Props) {\n const handleChange = React.useCallback(\n (newValue) => {\n onChange(props.element, newValue)\n },\n [onChange, props.element],\n )\n if (props.element.optionsType === 'SEARCH' && props.element.searchUrl) {\n return (\n <AutocompleteFetch\n {...props}\n onChange={handleChange}\n searchUrl={props.element.searchUrl}\n />\n )\n }\n\n return (\n <AutocompleteFilter\n {...props}\n onChange={handleChange}\n conditionallyShownOptionsElement={conditionallyShownOptionsElement}\n />\n )\n}\n\nexport default React.memo(FormElementAutocomplete)\n"]}
1
+ {"version":3,"file":"FormElementAutocomplete.js","sourceRoot":"","sources":["../../src/form-elements/FormElementAutocomplete.tsx"],"names":[],"mappings":"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","sourcesContent":["import * as React from 'react'\nimport { formElementsService } from '@oneblink/sdk-core'\nimport { generateHeaders } from '@oneblink/apps/dist/services/fetch'\n\nimport FormElementOptions from '../components/renderer/FormElementOptions'\nimport useFormElementOptions from '../hooks/useFormElementOptions'\nimport AutocompleteDropdown from '../components/renderer/AutocompleteDropdown'\nimport FormElementLabelContainer from '../components/renderer/FormElementLabelContainer'\nimport { FormTypes } from '@oneblink/types'\nimport {\n FormElementValueChangeHandler,\n FormElementConditionallyShownElement,\n IsDirtyProps,\n} from '../types/form'\n\ntype _BaseProps = {\n id: string\n element: FormTypes.AutoCompleteElement\n value: unknown | undefined\n displayValidationMessage: boolean\n validationMessage: string | undefined\n} & IsDirtyProps\n\ntype _AutocompleteChangeHandlerProps = _BaseProps & {\n onChange: (newValue: unknown | undefined) => void\n}\n\ntype _AutocompleteConditionallyShowOptionProps = {\n conditionallyShownOptionsElement:\n | FormElementConditionallyShownElement\n | undefined\n}\n\ntype AutocompleteFilterProps = _AutocompleteChangeHandlerProps &\n _AutocompleteConditionallyShowOptionProps\n\ntype AutocompleteFetchProps = _AutocompleteChangeHandlerProps & {\n searchUrl: string\n}\n\ntype Props = _BaseProps &\n _AutocompleteConditionallyShowOptionProps & {\n onChange: FormElementValueChangeHandler<string>\n }\n\nconst AutocompleteFilter = React.memo(function AutocompleteFilter({\n id,\n element,\n value,\n onChange,\n conditionallyShownOptionsElement,\n validationMessage,\n displayValidationMessage,\n isDirty,\n setIsDirty,\n}: AutocompleteFilterProps) {\n const [label, setLabel] = React.useState('')\n\n const onFilter = React.useCallback(\n (option) => {\n // If the user has typed nothing in, display all options\n if (!label) {\n return true\n }\n\n const lowerCase = label.toLowerCase()\n\n return option.label.toLowerCase().includes(lowerCase)\n },\n [label],\n )\n\n const handleChange = React.useCallback(\n //useFormElementOptions expects the first arg to be the element\n (element: FormTypes.FormElement, newValue: unknown) => onChange(newValue),\n [onChange],\n )\n\n const filteredOptions = useFormElementOptions({\n element,\n value,\n onChange: handleChange,\n conditionallyShownOptionsElement,\n onFilter,\n })\n\n const handleSearch = React.useCallback(async () => {\n return filteredOptions\n }, [filteredOptions])\n\n // Ensure the label matches the value selected\n React.useEffect(() => {\n if (!Array.isArray(element.options)) {\n return\n }\n\n const option = element.options.find((option) => option.value === value)\n if (option && label !== option.label) {\n setLabel(option.label)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [element.options, value])\n\n return (\n <div className=\"cypress-autocomplete-filter-element\">\n <FormElementLabelContainer\n className=\"ob-autocomplete\"\n element={element}\n id={id}\n required={element.required}\n >\n <FormElementOptions\n options={element.options}\n conditionallyShownOptionsElement={conditionallyShownOptionsElement}\n >\n <AutocompleteDropdown\n id={id}\n label={label}\n disabled={element.readOnly}\n placeholder={element.placeholderValue}\n required={element.required}\n value={value}\n validationMessage={validationMessage}\n displayValidationMessage={displayValidationMessage}\n onChangeValue={onChange}\n onChangeLabel={setLabel}\n onSearch={handleSearch}\n searchDebounceMs={0}\n searchMinCharacters={0}\n isDirty={isDirty}\n setIsDirty={setIsDirty}\n />\n </FormElementOptions>\n </FormElementLabelContainer>\n </div>\n )\n})\n\nconst AutocompleteFetch = React.memo(function AutocompleteFetch({\n id,\n element,\n value,\n onChange,\n validationMessage,\n displayValidationMessage,\n searchUrl,\n isDirty,\n setIsDirty,\n}: AutocompleteFetchProps) {\n const [label, setLabel] = React.useState('')\n\n const handleSearch = React.useCallback(\n async (search, abortSignal) => {\n const headers = await generateHeaders()\n const url = new URL(searchUrl)\n url.searchParams.append('value', search)\n const response = await fetch(url.href, {\n headers,\n signal: abortSignal,\n })\n\n if (!response.ok) {\n const text = await response.text()\n throw new Error(text)\n }\n\n const data = await response.json()\n return formElementsService.parseFormElementOptionsSet(data)\n },\n [searchUrl],\n )\n\n // Ensure the label is set if the value is set outside of this component\n React.useEffect(() => {\n if (!label && typeof value === 'string') {\n setLabel(value)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [value])\n\n return (\n <div className=\"cypress-autocomplete-search-element\">\n <FormElementLabelContainer\n className=\"ob-autocomplete\"\n element={element}\n id={id}\n required={element.required}\n >\n <AutocompleteDropdown\n id={id}\n label={label}\n disabled={element.readOnly}\n placeholder={element.placeholderValue}\n required={element.required}\n value={value}\n validationMessage={validationMessage}\n displayValidationMessage={displayValidationMessage}\n onChangeValue={onChange}\n onChangeLabel={setLabel}\n searchDebounceMs={750}\n searchMinCharacters={1}\n onSearch={handleSearch}\n isDirty={isDirty}\n setIsDirty={setIsDirty}\n />\n </FormElementLabelContainer>\n </div>\n )\n})\n\nfunction FormElementAutocomplete({\n conditionallyShownOptionsElement,\n onChange,\n ...props\n}: Props) {\n const handleChange = React.useCallback(\n (newValue) => {\n onChange(props.element, newValue)\n },\n [onChange, props.element],\n )\n if (props.element.optionsType === 'SEARCH' && props.element.searchUrl) {\n return (\n <AutocompleteFetch\n {...props}\n onChange={handleChange}\n searchUrl={props.element.searchUrl}\n />\n )\n }\n\n return (\n <AutocompleteFilter\n {...props}\n onChange={handleChange}\n conditionallyShownOptionsElement={conditionallyShownOptionsElement}\n />\n )\n}\n\nexport default React.memo(FormElementAutocomplete)\n"]}
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import { FormTypes } from '@oneblink/types';
3
- import { FormElementValueChangeHandler } from '../types/form';
3
+ import { FormElementValueChangeHandler, IsDirtyProps } from '../types/form';
4
4
  declare type Props = {
5
5
  id: string;
6
6
  formId: number;
@@ -12,7 +12,7 @@ declare type Props = {
12
12
  }>;
13
13
  displayValidationMessage: boolean;
14
14
  validationMessage: string | undefined;
15
- };
16
- declare function FormElementBSB({ id, formId, element, value, onChange, validationMessage, displayValidationMessage, }: Props): JSX.Element;
15
+ } & IsDirtyProps;
16
+ declare function FormElementBSB({ id, formId, element, value, onChange, validationMessage, displayValidationMessage, isDirty, setIsDirty, }: Props): JSX.Element;
17
17
  declare const _default: React.MemoExoticComponent<typeof FormElementBSB>;
18
18
  export default _default;
@@ -2,14 +2,12 @@ import * as React from 'react';
2
2
  import InputMask from 'react-input-mask';
3
3
  import clsx from 'clsx';
4
4
  import CopyToClipboardButton from '../components/renderer/CopyToClipboardButton';
5
- import useBooleanState from '../hooks/useBooleanState';
6
5
  import LookupButton from '../components/renderer/LookupButton';
7
6
  import FormElementLabelContainer from '../components/renderer/FormElementLabelContainer';
8
7
  import { formService } from '@oneblink/apps';
9
- function FormElementBSB({ id, formId, element, value, onChange, validationMessage, displayValidationMessage, }) {
8
+ function FormElementBSB({ id, formId, element, value, onChange, validationMessage, displayValidationMessage, isDirty, setIsDirty, }) {
10
9
  const [text, setText] = React.useState(typeof value === 'string' ? value : '');
11
10
  const isValidFormat = /\d{3}-\d{3}/.test(text);
12
- const [isDirty, setIsDirty] = useBooleanState(false);
13
11
  const [{ isLoading, errorMessage, bsbRecord }, setState] = React.useState({
14
12
  isLoading: false,
15
13
  errorMessage: null,
@@ -1 +1 @@
1
- {"version":3,"file":"FormElementBSB.js","sourceRoot":"","sources":["../../src/form-elements/FormElementBSB.tsx"],"names":[],"mappings":"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","sourcesContent":["import * as React from 'react'\nimport InputMask from 'react-input-mask'\nimport clsx from 'clsx'\nimport CopyToClipboardButton from '../components/renderer/CopyToClipboardButton'\nimport useBooleanState from '../hooks/useBooleanState'\nimport LookupButton from '../components/renderer/LookupButton'\nimport { FormTypes, MiscTypes } from '@oneblink/types'\nimport FormElementLabelContainer from '../components/renderer/FormElementLabelContainer'\nimport { FormElementValueChangeHandler } from '../types/form'\nimport { formService } from '@oneblink/apps'\n\ntype Props = {\n id: string\n formId: number\n element: FormTypes.BSBElement\n value: unknown\n onChange: FormElementValueChangeHandler<\n string | { isInvalid: boolean; isValidating: boolean }\n >\n displayValidationMessage: boolean\n validationMessage: string | undefined\n}\n\nfunction FormElementBSB({\n id,\n formId,\n element,\n value,\n onChange,\n validationMessage,\n displayValidationMessage,\n}: Props) {\n const [text, setText] = React.useState(typeof value === 'string' ? value : '')\n const isValidFormat = /\\d{3}-\\d{3}/.test(text)\n\n const [isDirty, setIsDirty] = useBooleanState(false)\n const [{ isLoading, errorMessage, bsbRecord }, setState] = React.useState<{\n isLoading: boolean\n errorMessage: string | null\n bsbRecord: MiscTypes.BSBRecord | null\n }>({\n isLoading: false,\n errorMessage: null,\n bsbRecord: null,\n })\n\n React.useEffect(() => {\n if (bsbRecord) {\n onChange(element, bsbRecord.bsb)\n }\n }, [bsbRecord, element, onChange, value])\n\n React.useEffect(() => {\n if (text === '') {\n return\n }\n\n if (!isValidFormat) {\n setState({\n isLoading: false,\n errorMessage: null,\n bsbRecord: null,\n })\n return\n }\n\n setState({\n isLoading: true,\n errorMessage: null,\n bsbRecord: null,\n })\n\n const abortController = new AbortController()\n const getBSBRecord = async () => {\n onChange(element, { isValidating: true, isInvalid: false })\n try {\n const bsbRecord = await formService.getBSBRecord(\n formId,\n text,\n abortController.signal,\n )\n if (!abortController.signal.aborted) {\n setState({\n isLoading: false,\n errorMessage: null,\n bsbRecord,\n })\n }\n } catch (error) {\n console.warn('Error validating BSB number', error)\n if (!abortController.signal.aborted) {\n onChange(element, { isInvalid: true, isValidating: false })\n setState({\n isLoading: false,\n errorMessage: `The BSB number \"${text}\" does not exist`,\n bsbRecord: null,\n })\n }\n }\n }\n\n getBSBRecord()\n\n return () => {\n abortController.abort()\n }\n }, [formId, isValidFormat, text, onChange, element])\n\n return (\n <div className=\"cypress-bsb-element\">\n <FormElementLabelContainer\n className=\"ob-bsb\"\n id={id}\n element={element}\n required={element.required}\n >\n <div className=\"field has-addons\">\n <div\n className={clsx('control is-expanded', {\n 'is-loading': isLoading,\n })}\n >\n <InputMask\n mask=\"999-999\"\n // @ts-expect-error \"react-input-mask\" types do not match code\n maskChar=\"x\"\n type=\"text\"\n placeholder={element.placeholderValue}\n id={id}\n name={element.name}\n className=\"input ob-input cypress-bsb-control\"\n value={text}\n onChange={(e) => {\n setText(e.target.value)\n }}\n required={element.required}\n disabled={element.readOnly}\n onBlur={() => {\n if (text === 'xxx-xxx') {\n onChange(element, undefined)\n }\n setIsDirty()\n }}\n />\n </div>\n {bsbRecord && (\n <div className=\"control ob-bsb__record-control\">\n <a className=\"button is-static ob-bsb__record-button\">\n {bsbRecord.financialInstitutionMnemonic} - {bsbRecord.name}\n </a>\n </div>\n )}\n {!!element.readOnly && !!value && (\n <div className=\"control\">\n <CopyToClipboardButton\n className=\"button is-input-addon copy-button cypress-copy-to-clipboard-button\"\n text={text}\n />\n </div>\n )}\n <LookupButton\n isInputButton\n value={value}\n validationMessage={validationMessage}\n />\n </div>\n {(((isDirty || displayValidationMessage) &&\n !!validationMessage &&\n !isLoading) ||\n errorMessage) && (\n <div role=\"alert\" className=\"has-margin-top-8\">\n <div className=\"has-text-danger ob-error__text cypress-validation-message\">\n {errorMessage || validationMessage}\n </div>\n </div>\n )}\n </FormElementLabelContainer>\n </div>\n )\n}\n\nexport default React.memo(FormElementBSB)\n"]}
1
+ {"version":3,"file":"FormElementBSB.js","sourceRoot":"","sources":["../../src/form-elements/FormElementBSB.tsx"],"names":[],"mappings":"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","sourcesContent":["import * as React from 'react'\nimport InputMask from 'react-input-mask'\nimport clsx from 'clsx'\nimport CopyToClipboardButton from '../components/renderer/CopyToClipboardButton'\nimport LookupButton from '../components/renderer/LookupButton'\nimport { FormTypes, MiscTypes } from '@oneblink/types'\nimport FormElementLabelContainer from '../components/renderer/FormElementLabelContainer'\nimport { FormElementValueChangeHandler, IsDirtyProps } from '../types/form'\nimport { formService } from '@oneblink/apps'\n\ntype Props = {\n id: string\n formId: number\n element: FormTypes.BSBElement\n value: unknown\n onChange: FormElementValueChangeHandler<\n string | { isInvalid: boolean; isValidating: boolean }\n >\n displayValidationMessage: boolean\n validationMessage: string | undefined\n} & IsDirtyProps\n\nfunction FormElementBSB({\n id,\n formId,\n element,\n value,\n onChange,\n validationMessage,\n displayValidationMessage,\n isDirty,\n setIsDirty,\n}: Props) {\n const [text, setText] = React.useState(typeof value === 'string' ? value : '')\n const isValidFormat = /\\d{3}-\\d{3}/.test(text)\n\n const [{ isLoading, errorMessage, bsbRecord }, setState] = React.useState<{\n isLoading: boolean\n errorMessage: string | null\n bsbRecord: MiscTypes.BSBRecord | null\n }>({\n isLoading: false,\n errorMessage: null,\n bsbRecord: null,\n })\n\n React.useEffect(() => {\n if (bsbRecord) {\n onChange(element, bsbRecord.bsb)\n }\n }, [bsbRecord, element, onChange, value])\n\n React.useEffect(() => {\n if (text === '') {\n return\n }\n\n if (!isValidFormat) {\n setState({\n isLoading: false,\n errorMessage: null,\n bsbRecord: null,\n })\n return\n }\n\n setState({\n isLoading: true,\n errorMessage: null,\n bsbRecord: null,\n })\n\n const abortController = new AbortController()\n const getBSBRecord = async () => {\n onChange(element, { isValidating: true, isInvalid: false })\n try {\n const bsbRecord = await formService.getBSBRecord(\n formId,\n text,\n abortController.signal,\n )\n if (!abortController.signal.aborted) {\n setState({\n isLoading: false,\n errorMessage: null,\n bsbRecord,\n })\n }\n } catch (error) {\n console.warn('Error validating BSB number', error)\n if (!abortController.signal.aborted) {\n onChange(element, { isInvalid: true, isValidating: false })\n setState({\n isLoading: false,\n errorMessage: `The BSB number \"${text}\" does not exist`,\n bsbRecord: null,\n })\n }\n }\n }\n\n getBSBRecord()\n\n return () => {\n abortController.abort()\n }\n }, [formId, isValidFormat, text, onChange, element])\n\n return (\n <div className=\"cypress-bsb-element\">\n <FormElementLabelContainer\n className=\"ob-bsb\"\n id={id}\n element={element}\n required={element.required}\n >\n <div className=\"field has-addons\">\n <div\n className={clsx('control is-expanded', {\n 'is-loading': isLoading,\n })}\n >\n <InputMask\n mask=\"999-999\"\n // @ts-expect-error \"react-input-mask\" types do not match code\n maskChar=\"x\"\n type=\"text\"\n placeholder={element.placeholderValue}\n id={id}\n name={element.name}\n className=\"input ob-input cypress-bsb-control\"\n value={text}\n onChange={(e) => {\n setText(e.target.value)\n }}\n required={element.required}\n disabled={element.readOnly}\n onBlur={() => {\n if (text === 'xxx-xxx') {\n onChange(element, undefined)\n }\n setIsDirty()\n }}\n />\n </div>\n {bsbRecord && (\n <div className=\"control ob-bsb__record-control\">\n <a className=\"button is-static ob-bsb__record-button\">\n {bsbRecord.financialInstitutionMnemonic} - {bsbRecord.name}\n </a>\n </div>\n )}\n {!!element.readOnly && !!value && (\n <div className=\"control\">\n <CopyToClipboardButton\n className=\"button is-input-addon copy-button cypress-copy-to-clipboard-button\"\n text={text}\n />\n </div>\n )}\n <LookupButton\n isInputButton\n value={value}\n validationMessage={validationMessage}\n />\n </div>\n {(((isDirty || displayValidationMessage) &&\n !!validationMessage &&\n !isLoading) ||\n errorMessage) && (\n <div role=\"alert\" className=\"has-margin-top-8\">\n <div className=\"has-text-danger ob-error__text cypress-validation-message\">\n {errorMessage || validationMessage}\n </div>\n </div>\n )}\n </FormElementLabelContainer>\n </div>\n )\n}\n\nexport default React.memo(FormElementBSB)\n"]}
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import { FormTypes } from '@oneblink/types';
3
- import { FormElementValueChangeHandler } from '../types/form';
3
+ import { FormElementValueChangeHandler, IsDirtyProps } from '../types/form';
4
4
  declare type Props = {
5
5
  id: string;
6
6
  element: FormTypes.BarcodeScannerElement;
@@ -8,7 +8,7 @@ declare type Props = {
8
8
  onChange: FormElementValueChangeHandler<string>;
9
9
  displayValidationMessage: boolean;
10
10
  validationMessage: string | undefined;
11
- };
12
- declare function FormElementBarcodeScanner({ id, element, value, onChange, validationMessage, displayValidationMessage, }: Props): JSX.Element;
11
+ } & IsDirtyProps;
12
+ declare function FormElementBarcodeScanner({ id, element, value, onChange, validationMessage, displayValidationMessage, isDirty, setIsDirty, }: Props): JSX.Element;
13
13
  declare const _default: React.MemoExoticComponent<typeof FormElementBarcodeScanner>;
14
14
  export default _default;
@@ -13,8 +13,7 @@ const MS_BETWEEN_IMAGE_PROCESSING = 10;
13
13
  const fadedSquareWidthInPixels = 200;
14
14
  const fadedSquareHeightInPixels = 150;
15
15
  const redLineHeightInPixels = 1;
16
- function FormElementBarcodeScanner({ id, element, value, onChange, validationMessage, displayValidationMessage, }) {
17
- const [isDirty, setIsDirty] = useBooleanState(false);
16
+ function FormElementBarcodeScanner({ id, element, value, onChange, validationMessage, displayValidationMessage, isDirty, setIsDirty, }) {
18
17
  const [isCameraOpen, startBarcodeScanner, stopBarcodeScanner] = useBooleanState(false);
19
18
  const [error, setError] = React.useState(null);
20
19
  const { onLookup } = useLookupNotification();
@@ -1 +1 @@
1
- {"version":3,"file":"FormElementBarcodeScanner.js","sourceRoot":"","sources":["../../src/form-elements/FormElementBarcodeScanner.tsx"],"names":[],"mappings":"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","sourcesContent":["import * as React from 'react'\nimport clsx from 'clsx'\nimport jsQR from 'jsqr'\n\nimport OnLoading from '../components/renderer/OnLoading'\nimport CopyToClipboardButton from '../components/renderer/CopyToClipboardButton'\nimport quaggaReader from '../services/barcode-readers/quagger.js'\nimport useBooleanState from '../hooks/useBooleanState'\nimport LookupButton from '../components/renderer/LookupButton'\nimport { FormTypes } from '@oneblink/types'\nimport FormElementLabelContainer from '../components/renderer/FormElementLabelContainer'\nimport { Sentry } from '@oneblink/apps'\nimport useLookupNotification from '../hooks/useLookupNotification'\nimport { FormElementValueChangeHandler } from '../types/form'\n\nconst MS_BETWEEN_IMAGE_PROCESSING = 10\nconst fadedSquareWidthInPixels = 200\nconst fadedSquareHeightInPixels = 150\nconst redLineHeightInPixels = 1\n\ntype Props = {\n id: string\n element: FormTypes.BarcodeScannerElement\n value: unknown | undefined\n onChange: FormElementValueChangeHandler<string>\n displayValidationMessage: boolean\n validationMessage: string | undefined\n}\n\nfunction FormElementBarcodeScanner({\n id,\n element,\n value,\n onChange,\n validationMessage,\n displayValidationMessage,\n}: Props) {\n const [isDirty, setIsDirty] = useBooleanState(false)\n const [isCameraOpen, startBarcodeScanner, stopBarcodeScanner] =\n useBooleanState(false)\n const [error, setError] = React.useState<Error | null>(null)\n\n const { onLookup } = useLookupNotification()\n const handleScan = React.useCallback(\n (newValue: string | undefined) => {\n setIsDirty()\n onChange(element, newValue)\n stopBarcodeScanner()\n onLookup(newValue)\n },\n [element, onChange, onLookup, setIsDirty, stopBarcodeScanner],\n )\n\n const openBarcodeScanner = React.useCallback(() => {\n if (window.cordova) {\n setError(null)\n // @ts-expect-error ???\n window.cordova.plugins.barcodeScanner.scan(\n // @ts-expect-error ???\n (result) => {\n if (!result.cancelled) {\n handleScan(result.text)\n }\n },\n // @ts-expect-error ???\n (error) => {\n setError(\n new Error(\n `An error has occurred: \"${error}\". Please click \"Cancel\" below to try again. If the problem persists, please contact support.`,\n ),\n )\n },\n {\n showFlipCameraButton: true,\n showTorchButton: true,\n },\n )\n } else {\n startBarcodeScanner()\n }\n }, [handleScan, startBarcodeScanner])\n\n const text = typeof value === 'string' ? value : ''\n return (\n <div className=\"cypress-barcode-scanner-element\">\n <FormElementLabelContainer\n className=\"ob-barcode-scanner\"\n element={element}\n id={id}\n required={element.required}\n >\n {error && (\n <figure className=\"ob-figure\">\n <div className=\"figure-content has-text-centered\">\n <div>\n <h4 className=\"title is-4\">Whoops...</h4>\n <p>{error.message}</p>\n </div>\n </div>\n </figure>\n )}\n\n {isCameraOpen ? (\n <BarcodeScanner\n element={element}\n onScan={handleScan}\n onClose={stopBarcodeScanner}\n />\n ) : (\n <div>\n <div className=\"field has-addons\">\n <div className=\"control is-expanded has-icons-right\">\n <input\n type=\"text\"\n placeholder={element.placeholderValue}\n id={id}\n name={element.name}\n className=\"input ob-input cypress-barcode-scanner-control has-margin-bottom-8\"\n value={text}\n onChange={(e) =>\n onChange(element, e.target.value || undefined)\n }\n required={element.required}\n disabled={element.readOnly}\n onBlur={setIsDirty}\n />\n <span className=\"ob-input-icon icon is-small is-right\">\n <i className=\"material-icons is-size-5\">document_scanner</i>\n </span>\n </div>\n {!!element.readOnly && !!value && (\n <div className=\"control\">\n <CopyToClipboardButton\n className=\"button is-input-addon copy-button cypress-copy-to-clipboard-button\"\n text={text}\n />\n </div>\n )}\n <LookupButton\n isInputButton\n value={value}\n validationMessage={validationMessage}\n />\n </div>\n\n <button\n type=\"button\"\n className=\"button ob-button ob-button__open is-primary cypress-start-scan-barcode-button\"\n disabled={element.readOnly}\n onClick={openBarcodeScanner}\n >\n Scan Barcode\n </button>\n </div>\n )}\n\n {(isDirty || displayValidationMessage) && !!validationMessage && (\n <div role=\"alert\" className=\"has-margin-top-8\">\n <div className=\"has-text-danger ob-error__text cypress-validation-message\">\n {validationMessage}\n </div>\n </div>\n )}\n </FormElementLabelContainer>\n </div>\n )\n}\n\nexport default React.memo(FormElementBarcodeScanner)\n\ntype BarcodeScannerProps = {\n element: FormTypes.BarcodeScannerElement\n onScan: (barcode: string | undefined) => void\n onClose: () => void\n}\n\nfunction BarcodeScanner({ element, onScan, onClose }: BarcodeScannerProps) {\n const videoElementRef = React.useRef<HTMLVideoElement>(null)\n const figureElementRef = React.useRef<HTMLDivElement>(null)\n\n const [{ isLoading = false, selectedDeviceId, error }, setState] =\n React.useState<{\n isLoading: boolean\n selectedDeviceId: string | undefined\n error: Error | undefined\n }>({\n isLoading: true,\n selectedDeviceId: undefined,\n error: undefined,\n })\n const [camera, setCamera] = React.useState<HTML5Camera | null>(null)\n\n const setError = React.useCallback((error: Error) => {\n setState({\n error,\n isLoading: false,\n selectedDeviceId: undefined,\n })\n }, [])\n\n // Create timeout using $timeout outside of the scan function so\n // so that we can cancel it when navigating away from screen\n const scanImageForBarcode = React.useCallback(\n (videoElement, waitInMS, options, checkStop) => {\n const restrictedBarcodeTypes = element.restrictedBarcodeTypes || []\n // Using $timeout here instead of $interval as we dont know\n // exactly how long each processing of the image will take.\n setTimeout(async () => {\n if (checkStop()) return\n const canvasElement = document.createElement('canvas')\n\n canvasElement.width = options.sourceWidth\n canvasElement.height = options.sourceHeight\n\n const canvasContext = canvasElement.getContext('2d')\n if (canvasContext) {\n canvasContext.drawImage(\n videoElement,\n options.sourceX,\n options.sourceY,\n canvasElement.width,\n canvasElement.height,\n 0,\n 0,\n canvasElement.width,\n canvasElement.height,\n )\n\n if (\n !element.restrictBarcodeTypes ||\n (element.restrictedBarcodeTypes || []).indexOf('qr_reader') > -1\n ) {\n const imageData = canvasContext.getImageData(\n 0,\n 0,\n canvasElement.width,\n canvasElement.height,\n )\n\n const code = jsQR(\n imageData.data,\n imageData.width,\n imageData.height,\n {\n inversionAttempts: 'dontInvert',\n },\n )\n\n if (code) {\n return onScan(code.data)\n }\n }\n }\n\n if (\n !element.restrictBarcodeTypes ||\n !(\n restrictedBarcodeTypes.length === 1 &&\n restrictedBarcodeTypes[0] === 'qr_reader'\n )\n ) {\n const base64Image = canvasElement.toDataURL('image/png')\n const quaggaResult = await quaggaReader(\n base64Image,\n restrictedBarcodeTypes,\n )\n if (quaggaResult) {\n return onScan(quaggaResult)\n }\n }\n\n if (checkStop()) return\n\n scanImageForBarcode(\n videoElement,\n MS_BETWEEN_IMAGE_PROCESSING,\n options,\n checkStop,\n )\n }, waitInMS)\n },\n [element.restrictBarcodeTypes, element.restrictedBarcodeTypes, onScan],\n )\n\n const switchCamera = React.useCallback(() => {\n if (!camera) {\n return\n }\n\n // We will just be rotating between the available camera.\n const nextDeviceIndex =\n camera.availableDevices.findIndex(\n (mediaDeviceInfo) => mediaDeviceInfo.deviceId === camera.activeDeviceId,\n ) + 1\n const nextDevice =\n camera.availableDevices[nextDeviceIndex] || camera.availableDevices[0]\n setState({\n error: undefined,\n isLoading: true,\n selectedDeviceId: nextDevice.deviceId,\n })\n }, [camera])\n\n React.useEffect(() => {\n if (!videoElementRef.current) {\n return\n }\n\n const newCamera = new HTML5Camera(videoElementRef.current)\n setCamera(newCamera)\n\n return () => {\n newCamera.close()\n }\n }, [])\n\n React.useEffect(() => {\n if (\n !camera ||\n error ||\n // If attempting to open the device that is currently open,\n // we will not attempt to open again.\n (selectedDeviceId && camera.activeDeviceId === selectedDeviceId)\n ) {\n return\n }\n\n let ignore = false\n\n ;(async () => {\n try {\n const videoElement = videoElementRef.current\n const figureElement = figureElementRef.current\n if (!videoElement || !figureElement) {\n return\n }\n\n console.log('Opening camera with:', selectedDeviceId || 'UNKNOWN')\n await camera.open(selectedDeviceId)\n\n if (ignore) {\n return\n }\n\n setState({\n error: undefined,\n isLoading: false,\n selectedDeviceId,\n })\n\n // @ts-expect-error ???\n const fadedSquareElement: HTMLDivElement =\n figureElement.getElementsByClassName('ob-barcode-scanner__square')[0]\n // @ts-expect-error ???\n const redLineElement: HTMLDivElement =\n figureElement.getElementsByClassName('ob-barcode-scanner__line')[0]\n console.log('videoElement Width pixels', videoElement.clientWidth)\n console.log('videoElement Height pixels', videoElement.clientHeight)\n console.log('videoElement Width', videoElement.videoWidth)\n console.log('videoElement Height', videoElement.videoHeight)\n\n // Faded Square needs its values set in pixels\n const fadedSquareLeftInPixels =\n (videoElement.clientWidth - fadedSquareWidthInPixels) / 2\n console.log('fadedSquareLeftInPixels', fadedSquareLeftInPixels)\n const fadedSquareTopInPixels =\n (videoElement.clientHeight - fadedSquareHeightInPixels) / 2\n console.log('fadedSquareTopInPixels', fadedSquareTopInPixels)\n\n fadedSquareElement.style.borderBottom = `${fadedSquareTopInPixels}px`\n fadedSquareElement.style.borderTop = `${fadedSquareTopInPixels}px`\n fadedSquareElement.style.borderLeft = `${fadedSquareLeftInPixels}px`\n fadedSquareElement.style.borderRight = `${fadedSquareLeftInPixels}px`\n fadedSquareElement.style.borderColor = 'rgba(0, 0, 0, 0.25)'\n fadedSquareElement.style.borderStyle = 'solid'\n\n redLineElement.style.height = `${redLineHeightInPixels}px`\n redLineElement.style.top = `${\n (videoElement.clientHeight - redLineHeightInPixels) / 2\n }px`\n redLineElement.style.left = `${fadedSquareLeftInPixels}px`\n redLineElement.style.right = `${fadedSquareLeftInPixels}px`\n\n // Need to calculate the actual width, which is not in pixels\n const ratio = videoElement.videoWidth / videoElement.clientWidth\n console.log('pixel to video Ratio', ratio)\n\n const left = ratio * fadedSquareLeftInPixels\n console.log('left in video measurement', left)\n const top = ratio * fadedSquareTopInPixels\n console.log('top in video measurement', top)\n\n const fadedSquareWidth = fadedSquareWidthInPixels * ratio\n console.log('red square in video measurement', fadedSquareWidth)\n\n // Wait a little before scanning the first image\n // to prevent image processing staring before\n // camera is ready.\n scanImageForBarcode(\n videoElement,\n 250,\n {\n sourceX: left,\n sourceY: top,\n sourceWidth: fadedSquareWidth,\n sourceHeight: fadedSquareWidth,\n },\n () => ignore,\n )\n } catch (error) {\n if (ignore) {\n return\n }\n console.warn('Error while attempting to open camera', error)\n Sentry.captureException(error)\n switch ((error as Error).name) {\n case 'NotSupportedError': {\n setError(\n new Error(\n 'Your browser does not support accessing your camera. Please click \"Cancel\" below and type in the barcode value manually.',\n ),\n )\n break\n }\n case 'NotAllowedError': {\n setError(\n new Error(\n 'Cannot scan for barcodes without granting the application access to the camera. Please click \"Cancel\" below to try again.',\n ),\n )\n break\n }\n default: {\n setError(\n new Error(\n 'An unknown error has occurred, please click \"Cancel\" below to try again. If the problem persists, please contact support.',\n ),\n )\n }\n }\n }\n })()\n\n return () => {\n ignore = true\n }\n }, [camera, error, scanImageForBarcode, selectedDeviceId, setError])\n\n return (\n <div>\n <figure className=\"ob-figure\" ref={figureElementRef}>\n <div className=\"figure-content has-text-centered\">\n {isLoading && <OnLoading small />}\n\n {!!error && (\n <div>\n <h4 className=\"title is-4\">Whoops...</h4>\n <p>{error.message}</p>\n </div>\n )}\n\n <div\n className={clsx('is-relative', {\n 'is-hidden': isLoading || error,\n })}\n >\n <div className=\"ob-barcode-scanner__square\"></div>\n <div className=\"ob-barcode-scanner__line\"></div>\n <video\n ref={videoElementRef}\n autoPlay\n playsInline\n className=\"ob-barcode-scanner__video\"\n />\n </div>\n </div>\n </figure>\n\n <div className=\"buttons ob-buttons\">\n <button\n type=\"button\"\n className=\"button ob-button ob-button__cancel is-light cypress-cancel-scan-barcode-button\"\n onClick={onClose}\n >\n Cancel\n </button>\n {(camera?.availableDevices.length || 1) > 1 && (\n <button\n type=\"button\"\n className=\"button ob-button ob-button__switch-camera is-primary cypress-switch-camera-button\"\n onClick={switchCamera}\n >\n Switch Camera\n </button>\n )}\n </div>\n </div>\n )\n}\n\nclass HTML5Camera {\n availableDevices: MediaDeviceInfo[]\n htmlVideoElement: HTMLVideoElement\n mediaStream: MediaStream | undefined\n\n constructor(htmlVideoElement: HTMLVideoElement) {\n this.htmlVideoElement = htmlVideoElement\n this.availableDevices = []\n this.mediaStream = undefined\n }\n\n get activeDeviceId(): string | undefined {\n if (this.mediaStream) {\n const [activeMediaStreamTrack] = this.mediaStream.getTracks()\n return activeMediaStreamTrack?.getSettings()?.deviceId\n }\n }\n\n async open(deviceId?: string) {\n if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {\n const error = new Error()\n error.name = 'NotSupportedError'\n throw error\n }\n\n this.close()\n\n const constraints = {\n video: {\n facingMode: deviceId ? undefined : 'environment',\n deviceId: deviceId ? { exact: deviceId } : undefined,\n },\n }\n const mediaStream = await navigator.mediaDevices.getUserMedia(constraints)\n this.mediaStream = mediaStream\n this.htmlVideoElement.srcObject = mediaStream\n\n if (!this.availableDevices.length) {\n const availableDevices = await navigator.mediaDevices.enumerateDevices()\n this.availableDevices = availableDevices.filter(\n (mediaDeviceInfo) =>\n mediaDeviceInfo.kind === 'videoinput' && !!mediaDeviceInfo.deviceId,\n )\n }\n\n await new Promise((resolve) =>\n this.htmlVideoElement.addEventListener('canplay', resolve, {\n once: true,\n }),\n )\n }\n\n close() {\n if (this.mediaStream) {\n this.mediaStream.getTracks().forEach((track) => {\n track.stop()\n })\n this.mediaStream = undefined\n }\n }\n}\n"]}
1
+ {"version":3,"file":"FormElementBarcodeScanner.js","sourceRoot":"","sources":["../../src/form-elements/FormElementBarcodeScanner.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,IAAI,MAAM,MAAM,CAAA;AAEvB,OAAO,SAAS,MAAM,kCAAkC,CAAA;AACxD,OAAO,qBAAqB,MAAM,8CAA8C,CAAA;AAChF,OAAO,YAAY,MAAM,wCAAwC,CAAA;AACjE,OAAO,eAAe,MAAM,0BAA0B,CAAA;AACtD,OAAO,YAAY,MAAM,qCAAqC,CAAA;AAE9D,OAAO,yBAAyB,MAAM,kDAAkD,CAAA;AACxF,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AACvC,OAAO,qBAAqB,MAAM,gCAAgC,CAAA;AAGlE,MAAM,2BAA2B,GAAG,EAAE,CAAA;AACtC,MAAM,wBAAwB,GAAG,GAAG,CAAA;AACpC,MAAM,yBAAyB,GAAG,GAAG,CAAA;AACrC,MAAM,qBAAqB,GAAG,CAAC,CAAA;AAW/B,SAAS,yBAAyB,CAAC,EACjC,EAAE,EACF,OAAO,EACP,KAAK,EACL,QAAQ,EACR,iBAAiB,EACjB,wBAAwB,EACxB,OAAO,EACP,UAAU,GACJ;IACN,MAAM,CAAC,YAAY,EAAE,mBAAmB,EAAE,kBAAkB,CAAC,GAC3D,eAAe,CAAC,KAAK,CAAC,CAAA;IACxB,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAe,IAAI,CAAC,CAAA;IAE5D,MAAM,EAAE,QAAQ,EAAE,GAAG,qBAAqB,EAAE,CAAA;IAC5C,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,CAClC,CAAC,QAA4B,EAAE,EAAE;QAC/B,UAAU,EAAE,CAAA;QACZ,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAA;QAC3B,kBAAkB,EAAE,CAAA;QACpB,QAAQ,CAAC,QAAQ,CAAC,CAAA;IACpB,CAAC,EACD,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,kBAAkB,CAAC,CAC9D,CAAA;IAED,MAAM,kBAAkB,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE;QAChD,IAAI,MAAM,CAAC,OAAO,EAAE;YAClB,QAAQ,CAAC,IAAI,CAAC,CAAA;YACd,uBAAuB;YACvB,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI;YACxC,uBAAuB;YACvB,CAAC,MAAM,EAAE,EAAE;gBACT,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE;oBACrB,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;iBACxB;YACH,CAAC;YACD,uBAAuB;YACvB,CAAC,KAAK,EAAE,EAAE;gBACR,QAAQ,CACN,IAAI,KAAK,CACP,2BAA2B,KAAK,+FAA+F,CAChI,CACF,CAAA;YACH,CAAC,EACD;gBACE,oBAAoB,EAAE,IAAI;gBAC1B,eAAe,EAAE,IAAI;aACtB,CACF,CAAA;SACF;aAAM;YACL,mBAAmB,EAAE,CAAA;SACtB;IACH,CAAC,EAAE,CAAC,UAAU,EAAE,mBAAmB,CAAC,CAAC,CAAA;IAErC,MAAM,IAAI,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;IACnD,OAAO,CACL,6BAAK,SAAS,EAAC,iCAAiC;QAC9C,oBAAC,yBAAyB,IACxB,SAAS,EAAC,oBAAoB,EAC9B,OAAO,EAAE,OAAO,EAChB,EAAE,EAAE,EAAE,EACN,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAEzB,KAAK,IAAI,CACR,gCAAQ,SAAS,EAAC,WAAW;gBAC3B,6BAAK,SAAS,EAAC,kCAAkC;oBAC/C;wBACE,4BAAI,SAAS,EAAC,YAAY,gBAAe;wBACzC,+BAAI,KAAK,CAAC,OAAO,CAAK,CAClB,CACF,CACC,CACV;YAEA,YAAY,CAAC,CAAC,CAAC,CACd,oBAAC,cAAc,IACb,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,UAAU,EAClB,OAAO,EAAE,kBAAkB,GAC3B,CACH,CAAC,CAAC,CAAC,CACF;gBACE,6BAAK,SAAS,EAAC,kBAAkB;oBAC/B,6BAAK,SAAS,EAAC,qCAAqC;wBAClD,+BACE,IAAI,EAAC,MAAM,EACX,WAAW,EAAE,OAAO,CAAC,gBAAgB,EACrC,EAAE,EAAE,EAAE,EACN,IAAI,EAAE,OAAO,CAAC,IAAI,EAClB,SAAS,EAAC,oEAAoE,EAC9E,KAAK,EAAE,IAAI,EACX,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CACd,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,IAAI,SAAS,CAAC,EAEhD,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAC1B,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAC1B,MAAM,EAAE,UAAU,GAClB;wBACF,8BAAM,SAAS,EAAC,sCAAsC;4BACpD,2BAAG,SAAS,EAAC,0BAA0B,uBAAqB,CACvD,CACH;oBACL,CAAC,CAAC,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC,KAAK,IAAI,CAChC,6BAAK,SAAS,EAAC,SAAS;wBACtB,oBAAC,qBAAqB,IACpB,SAAS,EAAC,oEAAoE,EAC9E,IAAI,EAAE,IAAI,GACV,CACE,CACP;oBACD,oBAAC,YAAY,IACX,aAAa,QACb,KAAK,EAAE,KAAK,EACZ,iBAAiB,EAAE,iBAAiB,GACpC,CACE;gBAEN,gCACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,+EAA+E,EACzF,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAC1B,OAAO,EAAE,kBAAkB,mBAGpB,CACL,CACP;YAEA,CAAC,OAAO,IAAI,wBAAwB,CAAC,IAAI,CAAC,CAAC,iBAAiB,IAAI,CAC/D,6BAAK,IAAI,EAAC,OAAO,EAAC,SAAS,EAAC,kBAAkB;gBAC5C,6BAAK,SAAS,EAAC,2DAA2D,IACvE,iBAAiB,CACd,CACF,CACP,CACyB,CACxB,CACP,CAAA;AACH,CAAC;AAED,eAAe,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAA;AAQpD,SAAS,cAAc,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAuB;IACvE,MAAM,eAAe,GAAG,KAAK,CAAC,MAAM,CAAmB,IAAI,CAAC,CAAA;IAC5D,MAAM,gBAAgB,GAAG,KAAK,CAAC,MAAM,CAAiB,IAAI,CAAC,CAAA;IAE3D,MAAM,CAAC,EAAE,SAAS,GAAG,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,EAAE,QAAQ,CAAC,GAC9D,KAAK,CAAC,QAAQ,CAIX;QACD,SAAS,EAAE,IAAI;QACf,gBAAgB,EAAE,SAAS;QAC3B,KAAK,EAAE,SAAS;KACjB,CAAC,CAAA;IACJ,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAqB,IAAI,CAAC,CAAA;IAEpE,MAAM,QAAQ,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC,KAAY,EAAE,EAAE;QAClD,QAAQ,CAAC;YACP,KAAK;YACL,SAAS,EAAE,KAAK;YAChB,gBAAgB,EAAE,SAAS;SAC5B,CAAC,CAAA;IACJ,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,gEAAgE;IAChE,4DAA4D;IAC5D,MAAM,mBAAmB,GAAG,KAAK,CAAC,WAAW,CAC3C,CAAC,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE;QAC7C,MAAM,sBAAsB,GAAG,OAAO,CAAC,sBAAsB,IAAI,EAAE,CAAA;QACnE,2DAA2D;QAC3D,2DAA2D;QAC3D,UAAU,CAAC,KAAK,IAAI,EAAE;YACpB,IAAI,SAAS,EAAE;gBAAE,OAAM;YACvB,MAAM,aAAa,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAA;YAEtD,aAAa,CAAC,KAAK,GAAG,OAAO,CAAC,WAAW,CAAA;YACzC,aAAa,CAAC,MAAM,GAAG,OAAO,CAAC,YAAY,CAAA;YAE3C,MAAM,aAAa,GAAG,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;YACpD,IAAI,aAAa,EAAE;gBACjB,aAAa,CAAC,SAAS,CACrB,YAAY,EACZ,OAAO,CAAC,OAAO,EACf,OAAO,CAAC,OAAO,EACf,aAAa,CAAC,KAAK,EACnB,aAAa,CAAC,MAAM,EACpB,CAAC,EACD,CAAC,EACD,aAAa,CAAC,KAAK,EACnB,aAAa,CAAC,MAAM,CACrB,CAAA;gBAED,IACE,CAAC,OAAO,CAAC,oBAAoB;oBAC7B,CAAC,OAAO,CAAC,sBAAsB,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,EAChE;oBACA,MAAM,SAAS,GAAG,aAAa,CAAC,YAAY,CAC1C,CAAC,EACD,CAAC,EACD,aAAa,CAAC,KAAK,EACnB,aAAa,CAAC,MAAM,CACrB,CAAA;oBAED,MAAM,IAAI,GAAG,IAAI,CACf,SAAS,CAAC,IAAI,EACd,SAAS,CAAC,KAAK,EACf,SAAS,CAAC,MAAM,EAChB;wBACE,iBAAiB,EAAE,YAAY;qBAChC,CACF,CAAA;oBAED,IAAI,IAAI,EAAE;wBACR,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;qBACzB;iBACF;aACF;YAED,IACE,CAAC,OAAO,CAAC,oBAAoB;gBAC7B,CAAC,CACC,sBAAsB,CAAC,MAAM,KAAK,CAAC;oBACnC,sBAAsB,CAAC,CAAC,CAAC,KAAK,WAAW,CAC1C,EACD;gBACA,MAAM,WAAW,GAAG,aAAa,CAAC,SAAS,CAAC,WAAW,CAAC,CAAA;gBACxD,MAAM,YAAY,GAAG,MAAM,YAAY,CACrC,WAAW,EACX,sBAAsB,CACvB,CAAA;gBACD,IAAI,YAAY,EAAE;oBAChB,OAAO,MAAM,CAAC,YAAY,CAAC,CAAA;iBAC5B;aACF;YAED,IAAI,SAAS,EAAE;gBAAE,OAAM;YAEvB,mBAAmB,CACjB,YAAY,EACZ,2BAA2B,EAC3B,OAAO,EACP,SAAS,CACV,CAAA;QACH,CAAC,EAAE,QAAQ,CAAC,CAAA;IACd,CAAC,EACD,CAAC,OAAO,CAAC,oBAAoB,EAAE,OAAO,CAAC,sBAAsB,EAAE,MAAM,CAAC,CACvE,CAAA;IAED,MAAM,YAAY,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,EAAE;QAC1C,IAAI,CAAC,MAAM,EAAE;YACX,OAAM;SACP;QAED,yDAAyD;QACzD,MAAM,eAAe,GACnB,MAAM,CAAC,gBAAgB,CAAC,SAAS,CAC/B,CAAC,eAAe,EAAE,EAAE,CAAC,eAAe,CAAC,QAAQ,KAAK,MAAM,CAAC,cAAc,CACxE,GAAG,CAAC,CAAA;QACP,MAAM,UAAU,GACd,MAAM,CAAC,gBAAgB,CAAC,eAAe,CAAC,IAAI,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAA;QACxE,QAAQ,CAAC;YACP,KAAK,EAAE,SAAS;YAChB,SAAS,EAAE,IAAI;YACf,gBAAgB,EAAE,UAAU,CAAC,QAAQ;SACtC,CAAC,CAAA;IACJ,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAA;IAEZ,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE;YAC5B,OAAM;SACP;QAED,MAAM,SAAS,GAAG,IAAI,WAAW,CAAC,eAAe,CAAC,OAAO,CAAC,CAAA;QAC1D,SAAS,CAAC,SAAS,CAAC,CAAA;QAEpB,OAAO,GAAG,EAAE;YACV,SAAS,CAAC,KAAK,EAAE,CAAA;QACnB,CAAC,CAAA;IACH,CAAC,EAAE,EAAE,CAAC,CAAA;IAEN,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,IACE,CAAC,MAAM;YACP,KAAK;YACL,2DAA2D;YAC3D,qCAAqC;YACrC,CAAC,gBAAgB,IAAI,MAAM,CAAC,cAAc,KAAK,gBAAgB,CAAC,EAChE;YACA,OAAM;SACP;QAED,IAAI,MAAM,GAAG,KAAK,CAEjB;QAAA,CAAC,KAAK,IAAI,EAAE;YACX,IAAI;gBACF,MAAM,YAAY,GAAG,eAAe,CAAC,OAAO,CAAA;gBAC5C,MAAM,aAAa,GAAG,gBAAgB,CAAC,OAAO,CAAA;gBAC9C,IAAI,CAAC,YAAY,IAAI,CAAC,aAAa,EAAE;oBACnC,OAAM;iBACP;gBAED,OAAO,CAAC,GAAG,CAAC,sBAAsB,EAAE,gBAAgB,IAAI,SAAS,CAAC,CAAA;gBAClE,MAAM,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAA;gBAEnC,IAAI,MAAM,EAAE;oBACV,OAAM;iBACP;gBAED,QAAQ,CAAC;oBACP,KAAK,EAAE,SAAS;oBAChB,SAAS,EAAE,KAAK;oBAChB,gBAAgB;iBACjB,CAAC,CAAA;gBAEF,uBAAuB;gBACvB,MAAM,kBAAkB,GACtB,aAAa,CAAC,sBAAsB,CAAC,4BAA4B,CAAC,CAAC,CAAC,CAAC,CAAA;gBACvE,uBAAuB;gBACvB,MAAM,cAAc,GAClB,aAAa,CAAC,sBAAsB,CAAC,0BAA0B,CAAC,CAAC,CAAC,CAAC,CAAA;gBACrE,OAAO,CAAC,GAAG,CAAC,2BAA2B,EAAE,YAAY,CAAC,WAAW,CAAC,CAAA;gBAClE,OAAO,CAAC,GAAG,CAAC,4BAA4B,EAAE,YAAY,CAAC,YAAY,CAAC,CAAA;gBACpE,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,YAAY,CAAC,UAAU,CAAC,CAAA;gBAC1D,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE,YAAY,CAAC,WAAW,CAAC,CAAA;gBAE5D,8CAA8C;gBAC9C,MAAM,uBAAuB,GAC3B,CAAC,YAAY,CAAC,WAAW,GAAG,wBAAwB,CAAC,GAAG,CAAC,CAAA;gBAC3D,OAAO,CAAC,GAAG,CAAC,yBAAyB,EAAE,uBAAuB,CAAC,CAAA;gBAC/D,MAAM,sBAAsB,GAC1B,CAAC,YAAY,CAAC,YAAY,GAAG,yBAAyB,CAAC,GAAG,CAAC,CAAA;gBAC7D,OAAO,CAAC,GAAG,CAAC,wBAAwB,EAAE,sBAAsB,CAAC,CAAA;gBAE7D,kBAAkB,CAAC,KAAK,CAAC,YAAY,GAAG,GAAG,sBAAsB,IAAI,CAAA;gBACrE,kBAAkB,CAAC,KAAK,CAAC,SAAS,GAAG,GAAG,sBAAsB,IAAI,CAAA;gBAClE,kBAAkB,CAAC,KAAK,CAAC,UAAU,GAAG,GAAG,uBAAuB,IAAI,CAAA;gBACpE,kBAAkB,CAAC,KAAK,CAAC,WAAW,GAAG,GAAG,uBAAuB,IAAI,CAAA;gBACrE,kBAAkB,CAAC,KAAK,CAAC,WAAW,GAAG,qBAAqB,CAAA;gBAC5D,kBAAkB,CAAC,KAAK,CAAC,WAAW,GAAG,OAAO,CAAA;gBAE9C,cAAc,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,qBAAqB,IAAI,CAAA;gBAC1D,cAAc,CAAC,KAAK,CAAC,GAAG,GAAG,GACzB,CAAC,YAAY,CAAC,YAAY,GAAG,qBAAqB,CAAC,GAAG,CACxD,IAAI,CAAA;gBACJ,cAAc,CAAC,KAAK,CAAC,IAAI,GAAG,GAAG,uBAAuB,IAAI,CAAA;gBAC1D,cAAc,CAAC,KAAK,CAAC,KAAK,GAAG,GAAG,uBAAuB,IAAI,CAAA;gBAE3D,6DAA6D;gBAC7D,MAAM,KAAK,GAAG,YAAY,CAAC,UAAU,GAAG,YAAY,CAAC,WAAW,CAAA;gBAChE,OAAO,CAAC,GAAG,CAAC,sBAAsB,EAAE,KAAK,CAAC,CAAA;gBAE1C,MAAM,IAAI,GAAG,KAAK,GAAG,uBAAuB,CAAA;gBAC5C,OAAO,CAAC,GAAG,CAAC,2BAA2B,EAAE,IAAI,CAAC,CAAA;gBAC9C,MAAM,GAAG,GAAG,KAAK,GAAG,sBAAsB,CAAA;gBAC1C,OAAO,CAAC,GAAG,CAAC,0BAA0B,EAAE,GAAG,CAAC,CAAA;gBAE5C,MAAM,gBAAgB,GAAG,wBAAwB,GAAG,KAAK,CAAA;gBACzD,OAAO,CAAC,GAAG,CAAC,iCAAiC,EAAE,gBAAgB,CAAC,CAAA;gBAEhE,gDAAgD;gBAChD,6CAA6C;gBAC7C,mBAAmB;gBACnB,mBAAmB,CACjB,YAAY,EACZ,GAAG,EACH;oBACE,OAAO,EAAE,IAAI;oBACb,OAAO,EAAE,GAAG;oBACZ,WAAW,EAAE,gBAAgB;oBAC7B,YAAY,EAAE,gBAAgB;iBAC/B,EACD,GAAG,EAAE,CAAC,MAAM,CACb,CAAA;aACF;YAAC,OAAO,KAAK,EAAE;gBACd,IAAI,MAAM,EAAE;oBACV,OAAM;iBACP;gBACD,OAAO,CAAC,IAAI,CAAC,uCAAuC,EAAE,KAAK,CAAC,CAAA;gBAC5D,MAAM,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAA;gBAC9B,QAAS,KAAe,CAAC,IAAI,EAAE;oBAC7B,KAAK,mBAAmB,CAAC,CAAC;wBACxB,QAAQ,CACN,IAAI,KAAK,CACP,0HAA0H,CAC3H,CACF,CAAA;wBACD,MAAK;qBACN;oBACD,KAAK,iBAAiB,CAAC,CAAC;wBACtB,QAAQ,CACN,IAAI,KAAK,CACP,2HAA2H,CAC5H,CACF,CAAA;wBACD,MAAK;qBACN;oBACD,OAAO,CAAC,CAAC;wBACP,QAAQ,CACN,IAAI,KAAK,CACP,2HAA2H,CAC5H,CACF,CAAA;qBACF;iBACF;aACF;QACH,CAAC,CAAC,EAAE,CAAA;QAEJ,OAAO,GAAG,EAAE;YACV,MAAM,GAAG,IAAI,CAAA;QACf,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,QAAQ,CAAC,CAAC,CAAA;IAEpE,OAAO,CACL;QACE,gCAAQ,SAAS,EAAC,WAAW,EAAC,GAAG,EAAE,gBAAgB;YACjD,6BAAK,SAAS,EAAC,kCAAkC;gBAC9C,SAAS,IAAI,oBAAC,SAAS,IAAC,KAAK,SAAG;gBAEhC,CAAC,CAAC,KAAK,IAAI,CACV;oBACE,4BAAI,SAAS,EAAC,YAAY,gBAAe;oBACzC,+BAAI,KAAK,CAAC,OAAO,CAAK,CAClB,CACP;gBAED,6BACE,SAAS,EAAE,IAAI,CAAC,aAAa,EAAE;wBAC7B,WAAW,EAAE,SAAS,IAAI,KAAK;qBAChC,CAAC;oBAEF,6BAAK,SAAS,EAAC,4BAA4B,GAAO;oBAClD,6BAAK,SAAS,EAAC,0BAA0B,GAAO;oBAChD,+BACE,GAAG,EAAE,eAAe,EACpB,QAAQ,QACR,WAAW,QACX,SAAS,EAAC,2BAA2B,GACrC,CACE,CACF,CACC;QAET,6BAAK,SAAS,EAAC,oBAAoB;YACjC,gCACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,gFAAgF,EAC1F,OAAO,EAAE,OAAO,aAGT;YACR,CAAC,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,gBAAgB,CAAC,MAAM,KAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAC7C,gCACE,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,mFAAmF,EAC7F,OAAO,EAAE,YAAY,oBAGd,CACV,CACG,CACF,CACP,CAAA;AACH,CAAC;AAED,MAAM,WAAW;IAKf,YAAY,gBAAkC;QAC5C,IAAI,CAAC,gBAAgB,GAAG,gBAAgB,CAAA;QACxC,IAAI,CAAC,gBAAgB,GAAG,EAAE,CAAA;QAC1B,IAAI,CAAC,WAAW,GAAG,SAAS,CAAA;IAC9B,CAAC;IAED,IAAI,cAAc;;QAChB,IAAI,IAAI,CAAC,WAAW,EAAE;YACpB,MAAM,CAAC,sBAAsB,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,CAAA;YAC7D,OAAO,MAAA,sBAAsB,aAAtB,sBAAsB,uBAAtB,sBAAsB,CAAE,WAAW,EAAE,0CAAE,QAAQ,CAAA;SACvD;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,QAAiB;QAC1B,IAAI,CAAC,SAAS,CAAC,YAAY,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,YAAY,EAAE;YACnE,MAAM,KAAK,GAAG,IAAI,KAAK,EAAE,CAAA;YACzB,KAAK,CAAC,IAAI,GAAG,mBAAmB,CAAA;YAChC,MAAM,KAAK,CAAA;SACZ;QAED,IAAI,CAAC,KAAK,EAAE,CAAA;QAEZ,MAAM,WAAW,GAAG;YAClB,KAAK,EAAE;gBACL,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa;gBAChD,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,SAAS;aACrD;SACF,CAAA;QACD,MAAM,WAAW,GAAG,MAAM,SAAS,CAAC,YAAY,CAAC,YAAY,CAAC,WAAW,CAAC,CAAA;QAC1E,IAAI,CAAC,WAAW,GAAG,WAAW,CAAA;QAC9B,IAAI,CAAC,gBAAgB,CAAC,SAAS,GAAG,WAAW,CAAA;QAE7C,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE;YACjC,MAAM,gBAAgB,GAAG,MAAM,SAAS,CAAC,YAAY,CAAC,gBAAgB,EAAE,CAAA;YACxE,IAAI,CAAC,gBAAgB,GAAG,gBAAgB,CAAC,MAAM,CAC7C,CAAC,eAAe,EAAE,EAAE,CAClB,eAAe,CAAC,IAAI,KAAK,YAAY,IAAI,CAAC,CAAC,eAAe,CAAC,QAAQ,CACtE,CAAA;SACF;QAED,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAC5B,IAAI,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,SAAS,EAAE,OAAO,EAAE;YACzD,IAAI,EAAE,IAAI;SACX,CAAC,CACH,CAAA;IACH,CAAC;IAED,KAAK;QACH,IAAI,IAAI,CAAC,WAAW,EAAE;YACpB,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;gBAC7C,KAAK,CAAC,IAAI,EAAE,CAAA;YACd,CAAC,CAAC,CAAA;YACF,IAAI,CAAC,WAAW,GAAG,SAAS,CAAA;SAC7B;IACH,CAAC;CACF","sourcesContent":["import * as React from 'react'\nimport clsx from 'clsx'\nimport jsQR from 'jsqr'\n\nimport OnLoading from '../components/renderer/OnLoading'\nimport CopyToClipboardButton from '../components/renderer/CopyToClipboardButton'\nimport quaggaReader from '../services/barcode-readers/quagger.js'\nimport useBooleanState from '../hooks/useBooleanState'\nimport LookupButton from '../components/renderer/LookupButton'\nimport { FormTypes } from '@oneblink/types'\nimport FormElementLabelContainer from '../components/renderer/FormElementLabelContainer'\nimport { Sentry } from '@oneblink/apps'\nimport useLookupNotification from '../hooks/useLookupNotification'\nimport { FormElementValueChangeHandler, IsDirtyProps } from '../types/form'\n\nconst MS_BETWEEN_IMAGE_PROCESSING = 10\nconst fadedSquareWidthInPixels = 200\nconst fadedSquareHeightInPixels = 150\nconst redLineHeightInPixels = 1\n\ntype Props = {\n id: string\n element: FormTypes.BarcodeScannerElement\n value: unknown | undefined\n onChange: FormElementValueChangeHandler<string>\n displayValidationMessage: boolean\n validationMessage: string | undefined\n} & IsDirtyProps\n\nfunction FormElementBarcodeScanner({\n id,\n element,\n value,\n onChange,\n validationMessage,\n displayValidationMessage,\n isDirty,\n setIsDirty,\n}: Props) {\n const [isCameraOpen, startBarcodeScanner, stopBarcodeScanner] =\n useBooleanState(false)\n const [error, setError] = React.useState<Error | null>(null)\n\n const { onLookup } = useLookupNotification()\n const handleScan = React.useCallback(\n (newValue: string | undefined) => {\n setIsDirty()\n onChange(element, newValue)\n stopBarcodeScanner()\n onLookup(newValue)\n },\n [element, onChange, onLookup, setIsDirty, stopBarcodeScanner],\n )\n\n const openBarcodeScanner = React.useCallback(() => {\n if (window.cordova) {\n setError(null)\n // @ts-expect-error ???\n window.cordova.plugins.barcodeScanner.scan(\n // @ts-expect-error ???\n (result) => {\n if (!result.cancelled) {\n handleScan(result.text)\n }\n },\n // @ts-expect-error ???\n (error) => {\n setError(\n new Error(\n `An error has occurred: \"${error}\". Please click \"Cancel\" below to try again. If the problem persists, please contact support.`,\n ),\n )\n },\n {\n showFlipCameraButton: true,\n showTorchButton: true,\n },\n )\n } else {\n startBarcodeScanner()\n }\n }, [handleScan, startBarcodeScanner])\n\n const text = typeof value === 'string' ? value : ''\n return (\n <div className=\"cypress-barcode-scanner-element\">\n <FormElementLabelContainer\n className=\"ob-barcode-scanner\"\n element={element}\n id={id}\n required={element.required}\n >\n {error && (\n <figure className=\"ob-figure\">\n <div className=\"figure-content has-text-centered\">\n <div>\n <h4 className=\"title is-4\">Whoops...</h4>\n <p>{error.message}</p>\n </div>\n </div>\n </figure>\n )}\n\n {isCameraOpen ? (\n <BarcodeScanner\n element={element}\n onScan={handleScan}\n onClose={stopBarcodeScanner}\n />\n ) : (\n <div>\n <div className=\"field has-addons\">\n <div className=\"control is-expanded has-icons-right\">\n <input\n type=\"text\"\n placeholder={element.placeholderValue}\n id={id}\n name={element.name}\n className=\"input ob-input cypress-barcode-scanner-control has-margin-bottom-8\"\n value={text}\n onChange={(e) =>\n onChange(element, e.target.value || undefined)\n }\n required={element.required}\n disabled={element.readOnly}\n onBlur={setIsDirty}\n />\n <span className=\"ob-input-icon icon is-small is-right\">\n <i className=\"material-icons is-size-5\">document_scanner</i>\n </span>\n </div>\n {!!element.readOnly && !!value && (\n <div className=\"control\">\n <CopyToClipboardButton\n className=\"button is-input-addon copy-button cypress-copy-to-clipboard-button\"\n text={text}\n />\n </div>\n )}\n <LookupButton\n isInputButton\n value={value}\n validationMessage={validationMessage}\n />\n </div>\n\n <button\n type=\"button\"\n className=\"button ob-button ob-button__open is-primary cypress-start-scan-barcode-button\"\n disabled={element.readOnly}\n onClick={openBarcodeScanner}\n >\n Scan Barcode\n </button>\n </div>\n )}\n\n {(isDirty || displayValidationMessage) && !!validationMessage && (\n <div role=\"alert\" className=\"has-margin-top-8\">\n <div className=\"has-text-danger ob-error__text cypress-validation-message\">\n {validationMessage}\n </div>\n </div>\n )}\n </FormElementLabelContainer>\n </div>\n )\n}\n\nexport default React.memo(FormElementBarcodeScanner)\n\ntype BarcodeScannerProps = {\n element: FormTypes.BarcodeScannerElement\n onScan: (barcode: string | undefined) => void\n onClose: () => void\n}\n\nfunction BarcodeScanner({ element, onScan, onClose }: BarcodeScannerProps) {\n const videoElementRef = React.useRef<HTMLVideoElement>(null)\n const figureElementRef = React.useRef<HTMLDivElement>(null)\n\n const [{ isLoading = false, selectedDeviceId, error }, setState] =\n React.useState<{\n isLoading: boolean\n selectedDeviceId: string | undefined\n error: Error | undefined\n }>({\n isLoading: true,\n selectedDeviceId: undefined,\n error: undefined,\n })\n const [camera, setCamera] = React.useState<HTML5Camera | null>(null)\n\n const setError = React.useCallback((error: Error) => {\n setState({\n error,\n isLoading: false,\n selectedDeviceId: undefined,\n })\n }, [])\n\n // Create timeout using $timeout outside of the scan function so\n // so that we can cancel it when navigating away from screen\n const scanImageForBarcode = React.useCallback(\n (videoElement, waitInMS, options, checkStop) => {\n const restrictedBarcodeTypes = element.restrictedBarcodeTypes || []\n // Using $timeout here instead of $interval as we dont know\n // exactly how long each processing of the image will take.\n setTimeout(async () => {\n if (checkStop()) return\n const canvasElement = document.createElement('canvas')\n\n canvasElement.width = options.sourceWidth\n canvasElement.height = options.sourceHeight\n\n const canvasContext = canvasElement.getContext('2d')\n if (canvasContext) {\n canvasContext.drawImage(\n videoElement,\n options.sourceX,\n options.sourceY,\n canvasElement.width,\n canvasElement.height,\n 0,\n 0,\n canvasElement.width,\n canvasElement.height,\n )\n\n if (\n !element.restrictBarcodeTypes ||\n (element.restrictedBarcodeTypes || []).indexOf('qr_reader') > -1\n ) {\n const imageData = canvasContext.getImageData(\n 0,\n 0,\n canvasElement.width,\n canvasElement.height,\n )\n\n const code = jsQR(\n imageData.data,\n imageData.width,\n imageData.height,\n {\n inversionAttempts: 'dontInvert',\n },\n )\n\n if (code) {\n return onScan(code.data)\n }\n }\n }\n\n if (\n !element.restrictBarcodeTypes ||\n !(\n restrictedBarcodeTypes.length === 1 &&\n restrictedBarcodeTypes[0] === 'qr_reader'\n )\n ) {\n const base64Image = canvasElement.toDataURL('image/png')\n const quaggaResult = await quaggaReader(\n base64Image,\n restrictedBarcodeTypes,\n )\n if (quaggaResult) {\n return onScan(quaggaResult)\n }\n }\n\n if (checkStop()) return\n\n scanImageForBarcode(\n videoElement,\n MS_BETWEEN_IMAGE_PROCESSING,\n options,\n checkStop,\n )\n }, waitInMS)\n },\n [element.restrictBarcodeTypes, element.restrictedBarcodeTypes, onScan],\n )\n\n const switchCamera = React.useCallback(() => {\n if (!camera) {\n return\n }\n\n // We will just be rotating between the available camera.\n const nextDeviceIndex =\n camera.availableDevices.findIndex(\n (mediaDeviceInfo) => mediaDeviceInfo.deviceId === camera.activeDeviceId,\n ) + 1\n const nextDevice =\n camera.availableDevices[nextDeviceIndex] || camera.availableDevices[0]\n setState({\n error: undefined,\n isLoading: true,\n selectedDeviceId: nextDevice.deviceId,\n })\n }, [camera])\n\n React.useEffect(() => {\n if (!videoElementRef.current) {\n return\n }\n\n const newCamera = new HTML5Camera(videoElementRef.current)\n setCamera(newCamera)\n\n return () => {\n newCamera.close()\n }\n }, [])\n\n React.useEffect(() => {\n if (\n !camera ||\n error ||\n // If attempting to open the device that is currently open,\n // we will not attempt to open again.\n (selectedDeviceId && camera.activeDeviceId === selectedDeviceId)\n ) {\n return\n }\n\n let ignore = false\n\n ;(async () => {\n try {\n const videoElement = videoElementRef.current\n const figureElement = figureElementRef.current\n if (!videoElement || !figureElement) {\n return\n }\n\n console.log('Opening camera with:', selectedDeviceId || 'UNKNOWN')\n await camera.open(selectedDeviceId)\n\n if (ignore) {\n return\n }\n\n setState({\n error: undefined,\n isLoading: false,\n selectedDeviceId,\n })\n\n // @ts-expect-error ???\n const fadedSquareElement: HTMLDivElement =\n figureElement.getElementsByClassName('ob-barcode-scanner__square')[0]\n // @ts-expect-error ???\n const redLineElement: HTMLDivElement =\n figureElement.getElementsByClassName('ob-barcode-scanner__line')[0]\n console.log('videoElement Width pixels', videoElement.clientWidth)\n console.log('videoElement Height pixels', videoElement.clientHeight)\n console.log('videoElement Width', videoElement.videoWidth)\n console.log('videoElement Height', videoElement.videoHeight)\n\n // Faded Square needs its values set in pixels\n const fadedSquareLeftInPixels =\n (videoElement.clientWidth - fadedSquareWidthInPixels) / 2\n console.log('fadedSquareLeftInPixels', fadedSquareLeftInPixels)\n const fadedSquareTopInPixels =\n (videoElement.clientHeight - fadedSquareHeightInPixels) / 2\n console.log('fadedSquareTopInPixels', fadedSquareTopInPixels)\n\n fadedSquareElement.style.borderBottom = `${fadedSquareTopInPixels}px`\n fadedSquareElement.style.borderTop = `${fadedSquareTopInPixels}px`\n fadedSquareElement.style.borderLeft = `${fadedSquareLeftInPixels}px`\n fadedSquareElement.style.borderRight = `${fadedSquareLeftInPixels}px`\n fadedSquareElement.style.borderColor = 'rgba(0, 0, 0, 0.25)'\n fadedSquareElement.style.borderStyle = 'solid'\n\n redLineElement.style.height = `${redLineHeightInPixels}px`\n redLineElement.style.top = `${\n (videoElement.clientHeight - redLineHeightInPixels) / 2\n }px`\n redLineElement.style.left = `${fadedSquareLeftInPixels}px`\n redLineElement.style.right = `${fadedSquareLeftInPixels}px`\n\n // Need to calculate the actual width, which is not in pixels\n const ratio = videoElement.videoWidth / videoElement.clientWidth\n console.log('pixel to video Ratio', ratio)\n\n const left = ratio * fadedSquareLeftInPixels\n console.log('left in video measurement', left)\n const top = ratio * fadedSquareTopInPixels\n console.log('top in video measurement', top)\n\n const fadedSquareWidth = fadedSquareWidthInPixels * ratio\n console.log('red square in video measurement', fadedSquareWidth)\n\n // Wait a little before scanning the first image\n // to prevent image processing staring before\n // camera is ready.\n scanImageForBarcode(\n videoElement,\n 250,\n {\n sourceX: left,\n sourceY: top,\n sourceWidth: fadedSquareWidth,\n sourceHeight: fadedSquareWidth,\n },\n () => ignore,\n )\n } catch (error) {\n if (ignore) {\n return\n }\n console.warn('Error while attempting to open camera', error)\n Sentry.captureException(error)\n switch ((error as Error).name) {\n case 'NotSupportedError': {\n setError(\n new Error(\n 'Your browser does not support accessing your camera. Please click \"Cancel\" below and type in the barcode value manually.',\n ),\n )\n break\n }\n case 'NotAllowedError': {\n setError(\n new Error(\n 'Cannot scan for barcodes without granting the application access to the camera. Please click \"Cancel\" below to try again.',\n ),\n )\n break\n }\n default: {\n setError(\n new Error(\n 'An unknown error has occurred, please click \"Cancel\" below to try again. If the problem persists, please contact support.',\n ),\n )\n }\n }\n }\n })()\n\n return () => {\n ignore = true\n }\n }, [camera, error, scanImageForBarcode, selectedDeviceId, setError])\n\n return (\n <div>\n <figure className=\"ob-figure\" ref={figureElementRef}>\n <div className=\"figure-content has-text-centered\">\n {isLoading && <OnLoading small />}\n\n {!!error && (\n <div>\n <h4 className=\"title is-4\">Whoops...</h4>\n <p>{error.message}</p>\n </div>\n )}\n\n <div\n className={clsx('is-relative', {\n 'is-hidden': isLoading || error,\n })}\n >\n <div className=\"ob-barcode-scanner__square\"></div>\n <div className=\"ob-barcode-scanner__line\"></div>\n <video\n ref={videoElementRef}\n autoPlay\n playsInline\n className=\"ob-barcode-scanner__video\"\n />\n </div>\n </div>\n </figure>\n\n <div className=\"buttons ob-buttons\">\n <button\n type=\"button\"\n className=\"button ob-button ob-button__cancel is-light cypress-cancel-scan-barcode-button\"\n onClick={onClose}\n >\n Cancel\n </button>\n {(camera?.availableDevices.length || 1) > 1 && (\n <button\n type=\"button\"\n className=\"button ob-button ob-button__switch-camera is-primary cypress-switch-camera-button\"\n onClick={switchCamera}\n >\n Switch Camera\n </button>\n )}\n </div>\n </div>\n )\n}\n\nclass HTML5Camera {\n availableDevices: MediaDeviceInfo[]\n htmlVideoElement: HTMLVideoElement\n mediaStream: MediaStream | undefined\n\n constructor(htmlVideoElement: HTMLVideoElement) {\n this.htmlVideoElement = htmlVideoElement\n this.availableDevices = []\n this.mediaStream = undefined\n }\n\n get activeDeviceId(): string | undefined {\n if (this.mediaStream) {\n const [activeMediaStreamTrack] = this.mediaStream.getTracks()\n return activeMediaStreamTrack?.getSettings()?.deviceId\n }\n }\n\n async open(deviceId?: string) {\n if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {\n const error = new Error()\n error.name = 'NotSupportedError'\n throw error\n }\n\n this.close()\n\n const constraints = {\n video: {\n facingMode: deviceId ? undefined : 'environment',\n deviceId: deviceId ? { exact: deviceId } : undefined,\n },\n }\n const mediaStream = await navigator.mediaDevices.getUserMedia(constraints)\n this.mediaStream = mediaStream\n this.htmlVideoElement.srcObject = mediaStream\n\n if (!this.availableDevices.length) {\n const availableDevices = await navigator.mediaDevices.enumerateDevices()\n this.availableDevices = availableDevices.filter(\n (mediaDeviceInfo) =>\n mediaDeviceInfo.kind === 'videoinput' && !!mediaDeviceInfo.deviceId,\n )\n }\n\n await new Promise((resolve) =>\n this.htmlVideoElement.addEventListener('canplay', resolve, {\n once: true,\n }),\n )\n }\n\n close() {\n if (this.mediaStream) {\n this.mediaStream.getTracks().forEach((track) => {\n track.stop()\n })\n this.mediaStream = undefined\n }\n }\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import { FormTypes } from '@oneblink/types';
3
- import { FormElementValueChangeHandler } from '../types/form';
3
+ import { FormElementValueChangeHandler, IsDirtyProps } from '../types/form';
4
4
  declare type Props = {
5
5
  id: string;
6
6
  element: FormTypes.BooleanElement;
@@ -8,7 +8,7 @@ declare type Props = {
8
8
  onChange: FormElementValueChangeHandler<boolean>;
9
9
  displayValidationMessage: boolean;
10
10
  validationMessage: string | undefined;
11
- };
12
- declare function FormElementBoolean({ id, element, value, onChange, validationMessage, displayValidationMessage, }: Props): JSX.Element;
11
+ } & IsDirtyProps;
12
+ declare function FormElementBoolean({ id, element, value, onChange, validationMessage, displayValidationMessage, isDirty, setIsDirty, }: Props): JSX.Element;
13
13
  declare const _default: React.MemoExoticComponent<typeof FormElementBoolean>;
14
14
  export default _default;
@@ -1,9 +1,7 @@
1
1
  import * as React from 'react';
2
- import useBooleanState from '../hooks/useBooleanState';
3
2
  import FormElementLabelContainer from '../components/renderer/FormElementLabelContainer';
4
3
  import { Switch } from '@mui/material';
5
- function FormElementBoolean({ id, element, value, onChange, validationMessage, displayValidationMessage, }) {
6
- const [isDirty, setIsDirty] = useBooleanState(false);
4
+ function FormElementBoolean({ id, element, value, onChange, validationMessage, displayValidationMessage, isDirty, setIsDirty, }) {
7
5
  return (React.createElement("div", { className: "cypress-boolean-element" },
8
6
  React.createElement(FormElementLabelContainer, { className: "ob-boolean", id: id, element: element, required: element.required, leading: React.createElement(Switch, { id: id, name: element.name, color: "primary", edge: "start", className: "ob-boolean__input cypress-boolean-control", classes: {
9
7
  checked: 'ob-boolean__input-checked',
@@ -1 +1 @@
1
- {"version":3,"file":"FormElementBoolean.js","sourceRoot":"","sources":["../../src/form-elements/FormElementBoolean.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,eAAe,MAAM,0BAA0B,CAAA;AAEtD,OAAO,yBAAyB,MAAM,kDAAkD,CAAA;AACxF,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAYtC,SAAS,kBAAkB,CAAC,EAC1B,EAAE,EACF,OAAO,EACP,KAAK,EACL,QAAQ,EACR,iBAAiB,EACjB,wBAAwB,GAClB;IACN,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,eAAe,CAAC,KAAK,CAAC,CAAA;IACpD,OAAO,CACL,6BAAK,SAAS,EAAC,yBAAyB;QACtC,oBAAC,yBAAyB,IACxB,SAAS,EAAC,YAAY,EACtB,EAAE,EAAE,EAAE,EACN,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAC1B,OAAO,EACL,oBAAC,MAAM,IACL,EAAE,EAAE,EAAE,EACN,IAAI,EAAE,OAAO,CAAC,IAAI,EAClB,KAAK,EAAC,SAAS,EACf,IAAI,EAAC,OAAO,EACZ,SAAS,EAAC,2CAA2C,EACrD,OAAO,EAAE;oBACP,OAAO,EAAE,2BAA2B;iBACrC,EACD,OAAO,EAAE,CAAC,CAAC,KAAK,EAChB,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAC1B,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE;oBACd,UAAU,EAAE,CAAA;oBACZ,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;gBACrC,CAAC,EACD,aAAa,SACb,IAGH,CAAC,OAAO,IAAI,wBAAwB,CAAC,IAAI,CAAC,CAAC,iBAAiB,IAAI,CAC/D,6BAAK,IAAI,EAAC,OAAO,EAAC,SAAS,EAAC,kBAAkB;YAC5C,6BAAK,SAAS,EAAC,2DAA2D,IACvE,iBAAiB,CACd,CACF,CACP,CACyB,CACxB,CACP,CAAA;AACH,CAAC;AAED,eAAe,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAA","sourcesContent":["import * as React from 'react'\nimport useBooleanState from '../hooks/useBooleanState'\nimport { FormTypes } from '@oneblink/types'\nimport FormElementLabelContainer from '../components/renderer/FormElementLabelContainer'\nimport { Switch } from '@mui/material'\nimport { FormElementValueChangeHandler } from '../types/form'\n\ntype Props = {\n id: string\n element: FormTypes.BooleanElement\n value: unknown\n onChange: FormElementValueChangeHandler<boolean>\n displayValidationMessage: boolean\n validationMessage: string | undefined\n}\n\nfunction FormElementBoolean({\n id,\n element,\n value,\n onChange,\n validationMessage,\n displayValidationMessage,\n}: Props) {\n const [isDirty, setIsDirty] = useBooleanState(false)\n return (\n <div className=\"cypress-boolean-element\">\n <FormElementLabelContainer\n className=\"ob-boolean\"\n id={id}\n element={element}\n required={element.required}\n leading={\n <Switch\n id={id}\n name={element.name}\n color=\"primary\"\n edge=\"start\"\n className=\"ob-boolean__input cypress-boolean-control\"\n classes={{\n checked: 'ob-boolean__input-checked',\n }}\n checked={!!value}\n disabled={element.readOnly}\n onChange={(e) => {\n setIsDirty()\n onChange(element, e.target.checked)\n }}\n disableRipple\n />\n }\n >\n {(isDirty || displayValidationMessage) && !!validationMessage && (\n <div role=\"alert\" className=\"has-margin-top-8\">\n <div className=\"has-text-danger ob-error__text cypress-validation-message\">\n {validationMessage}\n </div>\n </div>\n )}\n </FormElementLabelContainer>\n </div>\n )\n}\n\nexport default React.memo(FormElementBoolean)\n"]}
1
+ {"version":3,"file":"FormElementBoolean.js","sourceRoot":"","sources":["../../src/form-elements/FormElementBoolean.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,yBAAyB,MAAM,kDAAkD,CAAA;AACxF,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAYtC,SAAS,kBAAkB,CAAC,EAC1B,EAAE,EACF,OAAO,EACP,KAAK,EACL,QAAQ,EACR,iBAAiB,EACjB,wBAAwB,EACxB,OAAO,EACP,UAAU,GACJ;IACN,OAAO,CACL,6BAAK,SAAS,EAAC,yBAAyB;QACtC,oBAAC,yBAAyB,IACxB,SAAS,EAAC,YAAY,EACtB,EAAE,EAAE,EAAE,EACN,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAC1B,OAAO,EACL,oBAAC,MAAM,IACL,EAAE,EAAE,EAAE,EACN,IAAI,EAAE,OAAO,CAAC,IAAI,EAClB,KAAK,EAAC,SAAS,EACf,IAAI,EAAC,OAAO,EACZ,SAAS,EAAC,2CAA2C,EACrD,OAAO,EAAE;oBACP,OAAO,EAAE,2BAA2B;iBACrC,EACD,OAAO,EAAE,CAAC,CAAC,KAAK,EAChB,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAC1B,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE;oBACd,UAAU,EAAE,CAAA;oBACZ,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;gBACrC,CAAC,EACD,aAAa,SACb,IAGH,CAAC,OAAO,IAAI,wBAAwB,CAAC,IAAI,CAAC,CAAC,iBAAiB,IAAI,CAC/D,6BAAK,IAAI,EAAC,OAAO,EAAC,SAAS,EAAC,kBAAkB;YAC5C,6BAAK,SAAS,EAAC,2DAA2D,IACvE,iBAAiB,CACd,CACF,CACP,CACyB,CACxB,CACP,CAAA;AACH,CAAC;AAED,eAAe,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAA","sourcesContent":["import * as React from 'react'\nimport { FormTypes } from '@oneblink/types'\nimport FormElementLabelContainer from '../components/renderer/FormElementLabelContainer'\nimport { Switch } from '@mui/material'\nimport { FormElementValueChangeHandler, IsDirtyProps } from '../types/form'\n\ntype Props = {\n id: string\n element: FormTypes.BooleanElement\n value: unknown\n onChange: FormElementValueChangeHandler<boolean>\n displayValidationMessage: boolean\n validationMessage: string | undefined\n} & IsDirtyProps\n\nfunction FormElementBoolean({\n id,\n element,\n value,\n onChange,\n validationMessage,\n displayValidationMessage,\n isDirty,\n setIsDirty,\n}: Props) {\n return (\n <div className=\"cypress-boolean-element\">\n <FormElementLabelContainer\n className=\"ob-boolean\"\n id={id}\n element={element}\n required={element.required}\n leading={\n <Switch\n id={id}\n name={element.name}\n color=\"primary\"\n edge=\"start\"\n className=\"ob-boolean__input cypress-boolean-control\"\n classes={{\n checked: 'ob-boolean__input-checked',\n }}\n checked={!!value}\n disabled={element.readOnly}\n onChange={(e) => {\n setIsDirty()\n onChange(element, e.target.checked)\n }}\n disableRipple\n />\n }\n >\n {(isDirty || displayValidationMessage) && !!validationMessage && (\n <div role=\"alert\" className=\"has-margin-top-8\">\n <div className=\"has-text-danger ob-error__text cypress-validation-message\">\n {validationMessage}\n </div>\n </div>\n )}\n </FormElementLabelContainer>\n </div>\n )\n}\n\nexport default React.memo(FormElementBoolean)\n"]}
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { FormTypes } from '@oneblink/types';
3
3
  import { FormElementBinaryStorageValue } from '../types/attachments';
4
- import { FormElementValueChangeHandler } from '../types/form';
4
+ import { FormElementValueChangeHandler, IsDirtyProps } from '../types/form';
5
5
  declare type Props = {
6
6
  id: string;
7
7
  element: FormTypes.CameraElement;
@@ -9,7 +9,7 @@ declare type Props = {
9
9
  onChange: FormElementValueChangeHandler<FormElementBinaryStorageValue>;
10
10
  displayValidationMessage: boolean;
11
11
  validationMessage: string | undefined;
12
- };
13
- declare function FormElementCamera({ id, element, value, onChange, validationMessage, displayValidationMessage, }: Props): JSX.Element;
12
+ } & IsDirtyProps;
13
+ declare function FormElementCamera({ id, element, value, onChange, validationMessage, displayValidationMessage, isDirty, setIsDirty, }: Props): JSX.Element;
14
14
  declare const _default: React.MemoExoticComponent<typeof FormElementCamera>;
15
15
  export default _default;
@@ -12,11 +12,10 @@ import AttachmentStatus from '../components/renderer/attachments/AttachmentStatu
12
12
  import { canvasToBlob, urlToBlobAsync } from '../services/blob-utils';
13
13
  import ImagePreviewUnavailable from '../components/renderer/attachments/ImagePreviewUnavailable';
14
14
  import ProgressBar from '../components/renderer/attachments/ProgressBar';
15
- function FormElementCamera({ id, element, value, onChange, validationMessage, displayValidationMessage, }) {
15
+ function FormElementCamera({ id, element, value, onChange, validationMessage, displayValidationMessage, isDirty, setIsDirty, }) {
16
16
  const [{ cameraError, isLoading }, setState] = React.useState({
17
17
  isLoading: false,
18
18
  });
19
- const [isDirty, setIsDirty] = useBooleanState(false);
20
19
  const [isAnnotating, setIsAnnotating, clearIsAnnotating] = useBooleanState(false);
21
20
  const fileInputRef = React.useRef(null);
22
21
  const clearImage = React.useCallback(() => {