@tellescope/react-components 1.205.0 → 1.206.0

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 (54) hide show
  1. package/lib/cjs/Forms/form_responses.d.ts +6 -2
  2. package/lib/cjs/Forms/form_responses.d.ts.map +1 -1
  3. package/lib/cjs/Forms/form_responses.js +8 -7
  4. package/lib/cjs/Forms/form_responses.js.map +1 -1
  5. package/lib/cjs/Forms/forms.d.ts +4 -1
  6. package/lib/cjs/Forms/forms.d.ts.map +1 -1
  7. package/lib/cjs/Forms/forms.js +6 -6
  8. package/lib/cjs/Forms/forms.js.map +1 -1
  9. package/lib/cjs/Forms/inputs.d.ts +8 -3
  10. package/lib/cjs/Forms/inputs.d.ts.map +1 -1
  11. package/lib/cjs/Forms/inputs.js +51 -34
  12. package/lib/cjs/Forms/inputs.js.map +1 -1
  13. package/lib/cjs/displays.d.ts +2 -0
  14. package/lib/cjs/displays.d.ts.map +1 -1
  15. package/lib/cjs/displays.js.map +1 -1
  16. package/lib/cjs/layout.d.ts +2 -1
  17. package/lib/cjs/layout.d.ts.map +1 -1
  18. package/lib/cjs/layout.js +2 -2
  19. package/lib/cjs/layout.js.map +1 -1
  20. package/lib/esm/CMS/components.d.ts +1 -0
  21. package/lib/esm/CMS/components.d.ts.map +1 -1
  22. package/lib/esm/Forms/form_responses.d.ts +7 -2
  23. package/lib/esm/Forms/form_responses.d.ts.map +1 -1
  24. package/lib/esm/Forms/form_responses.js +8 -7
  25. package/lib/esm/Forms/form_responses.js.map +1 -1
  26. package/lib/esm/Forms/forms.d.ts +7 -4
  27. package/lib/esm/Forms/forms.d.ts.map +1 -1
  28. package/lib/esm/Forms/forms.js +6 -6
  29. package/lib/esm/Forms/forms.js.map +1 -1
  30. package/lib/esm/Forms/hooks.d.ts +1 -0
  31. package/lib/esm/Forms/hooks.d.ts.map +1 -1
  32. package/lib/esm/Forms/inputs.d.ts +9 -4
  33. package/lib/esm/Forms/inputs.d.ts.map +1 -1
  34. package/lib/esm/Forms/inputs.js +51 -34
  35. package/lib/esm/Forms/inputs.js.map +1 -1
  36. package/lib/esm/controls.d.ts +2 -2
  37. package/lib/esm/displays.d.ts +2 -0
  38. package/lib/esm/displays.d.ts.map +1 -1
  39. package/lib/esm/displays.js.map +1 -1
  40. package/lib/esm/inputs.d.ts +1 -1
  41. package/lib/esm/inputs.native.d.ts +1 -0
  42. package/lib/esm/inputs.native.d.ts.map +1 -1
  43. package/lib/esm/layout.d.ts +2 -1
  44. package/lib/esm/layout.d.ts.map +1 -1
  45. package/lib/esm/layout.js +2 -2
  46. package/lib/esm/layout.js.map +1 -1
  47. package/lib/esm/state.d.ts +52 -52
  48. package/lib/tsconfig.tsbuildinfo +1 -1
  49. package/package.json +9 -9
  50. package/src/Forms/form_responses.tsx +9 -8
  51. package/src/Forms/forms.tsx +9 -1
  52. package/src/Forms/inputs.tsx +38 -5
  53. package/src/displays.tsx +2 -0
  54. package/src/layout.tsx +3 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tellescope/react-components",
3
- "version": "1.205.0",
3
+ "version": "1.206.0",
4
4
  "description": "",
5
5
  "main": "./lib/cjs/index.js",
6
6
  "module": "./lib/esm/index.js",
@@ -47,13 +47,13 @@
47
47
  "@reduxjs/toolkit": "^1.6.2",
48
48
  "@stripe/react-stripe-js": "^2.9.0",
49
49
  "@stripe/stripe-js": "^1.52.1",
50
- "@tellescope/constants": "^1.205.0",
51
- "@tellescope/sdk": "^1.205.0",
52
- "@tellescope/types-client": "^1.205.0",
53
- "@tellescope/types-models": "^1.205.0",
54
- "@tellescope/types-utilities": "^1.205.0",
55
- "@tellescope/utilities": "^1.205.0",
56
- "@tellescope/validation": "^1.205.0",
50
+ "@tellescope/constants": "^1.206.0",
51
+ "@tellescope/sdk": "^1.206.0",
52
+ "@tellescope/types-client": "^1.206.0",
53
+ "@tellescope/types-models": "^1.206.0",
54
+ "@tellescope/types-utilities": "^1.206.0",
55
+ "@tellescope/utilities": "^1.206.0",
56
+ "@tellescope/validation": "^1.206.0",
57
57
  "@typescript-eslint/eslint-plugin": "^4.33.0",
58
58
  "@typescript-eslint/parser": "^4.33.0",
59
59
  "css-to-react-native": "^3.0.0",
@@ -84,7 +84,7 @@
84
84
  "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0",
85
85
  "react-native": "^0.65.0 || ^0.66.0 || ^0.67.0 || ^0.68.0 || ^0.71.0"
86
86
  },
87
- "gitHead": "2207d17c9959fcef3194f08245f8890817739b4e",
87
+ "gitHead": "d806743ca9f51d8abb2464d25f4d093e3b58a55f",
88
88
  "publishConfig": {
89
89
  "access": "public"
90
90
  }
@@ -1,8 +1,8 @@
1
- import React from "react"
1
+ import React, { useEffect } from "react"
2
2
  import { Divider, Grid, Typography } from "@mui/material"
3
3
  import { Enduser, FormResponse } from "@tellescope/types-client"
4
4
  import { form_response_value_to_string, formatted_date, getOrgnizationLogoURL, remove_script_tags, user_display_name } from "@tellescope/utilities"
5
- import { DownloadFileIconButton, LabeledIconButton, SecureImage, useEndusers, useOrganization, useResolvedSession, useSession, useUsers, value_is_loaded } from "../index"
5
+ import { DownloadFileIconButton, ImageProps, LabeledIconButton, SecureImage, useEndusers, useOrganization, useResolvedSession, useSession, useUsers, value_is_loaded } from "../index"
6
6
  import CloseIcon from '@mui/icons-material/Close';
7
7
  import { DatabaseSelectResponse, FormResponseAnswerAddress, FormResponseValueAnswer } from "@tellescope/types-models"
8
8
  import { Image } from "../layout"
@@ -64,6 +64,7 @@ export const ResponseAnswer = ({ formResponse, fieldId, isHTML, answer: a, print
64
64
  : (
65
65
  <SecureImage secureName={a.value.secureName} onImageClick={onImageClick}
66
66
  style={{ maxHeight: 400, maxWidth: 400 }}
67
+ crossOrigin="anonymous"
67
68
  />
68
69
  )
69
70
  }
@@ -181,7 +182,7 @@ export const ResponseAnswer = ({ formResponse, fieldId, isHTML, answer: a, print
181
182
  )
182
183
  )
183
184
 
184
- export const OrganizationLogo = () => {
185
+ export const OrganizationLogo = ({ crossOrigin } : { crossOrigin?: ImageProps['crossOrigin'] }) => {
185
186
  const [organizationLoading] = useOrganization()
186
187
 
187
188
  if (!value_is_loaded(organizationLoading)) return null
@@ -190,7 +191,7 @@ export const OrganizationLogo = () => {
190
191
  const logoURL = getOrgnizationLogoURL(organizationLoading.value)
191
192
 
192
193
  return (
193
- <Image
194
+ <Image crossOrigin={crossOrigin}
194
195
  src={logoURL}
195
196
  alt=""
196
197
  maxWidth={400}
@@ -199,12 +200,12 @@ export const OrganizationLogo = () => {
199
200
  )
200
201
  }
201
202
 
202
- export const ResolveOrganizationLogo = ({ logoURL } : { logoURL?: string }) => {
203
+ export const ResolveOrganizationLogo = ({ logoURL, crossOrigin } : { logoURL?: string, crossOrigin?: ImageProps['crossOrigin'] }) => {
203
204
  const session = useResolvedSession()
204
205
 
205
206
  if (logoURL) {
206
207
  return (
207
- <Image
208
+ <Image crossOrigin={crossOrigin}
208
209
  src={logoURL}
209
210
  alt=""
210
211
  maxWidth={400}
@@ -215,7 +216,7 @@ export const ResolveOrganizationLogo = ({ logoURL } : { logoURL?: string }) => {
215
216
 
216
217
  if (session.type === 'enduser') return null
217
218
 
218
- return <OrganizationLogo />
219
+ return <OrganizationLogo crossOrigin={crossOrigin} />
219
220
  }
220
221
 
221
222
  interface FormResponse_T {
@@ -245,7 +246,7 @@ export const FormResponseView = ({ showAnswerInline=true, logoURL, enduser, onCl
245
246
  <div style={{ textAlign: 'center' }}>
246
247
  {!hideHeader &&
247
248
  <>
248
- <ResolveOrganizationLogo logoURL={logoURL} />
249
+ <ResolveOrganizationLogo logoURL={logoURL} crossOrigin="anonymous" />
249
250
 
250
251
  <h2 style={{
251
252
  fontSize: 20,
@@ -2,7 +2,7 @@ import React, { useCallback, useEffect, useMemo, useRef, useState } from "react"
2
2
  import { Button, CircularProgress, FileBlob, FileUploadHandler, Flex, LinearProgress, LoadingButton, Modal, Paper, Styled, Typography, form_display_text_for_language, useFileUpload, useFormResponses, useSession } from "../index"
3
3
  import { useListForFormFields, useOrganizationTheme, useTellescopeForm, WithOrganizationTheme, Response, FileResponse, NextFieldLogicOptions } from "./hooks"
4
4
  import { ChangeHandler, FormInputs } from "./types"
5
- import { AddressInput, AllergiesInput, AppointmentBookingInput, ChargeebeeInput, ConditionsInput, DatabaseSelectInput, DateInput, DateStringInput, DropdownInput, EmailInput, EmotiiInput, FileInput, FilesInput, HeightInput, HiddenValueInput, InsuranceInput, LanguageSelect, MedicationsInput, MultipleChoiceInput, NumberInput, PhoneInput, Progress, RankingInput, RatingInput, RedirectInput, RelatedContactsInput, RichTextInput, SignatureInput, StringInput, StringLongInput, StripeInput, TableInput, TimeInput, defaultButtonStyles } from "./inputs"
5
+ import { AddToDatabaseProps, AddressInput, AllergiesInput, AppointmentBookingInput, ChargeebeeInput, ConditionsInput, DatabaseSelectInput, DateInput, DateStringInput, DropdownInput, EmailInput, EmotiiInput, FileInput, FilesInput, HeightInput, HiddenValueInput, InsuranceInput, LanguageSelect, MedicationsInput, MultipleChoiceInput, NumberInput, PhoneInput, Progress, RankingInput, RatingInput, RedirectInput, RelatedContactsInput, RichTextInput, SignatureInput, StringInput, StringLongInput, StripeInput, TableInput, TimeInput, defaultButtonStyles } from "./inputs"
6
6
  import { PRIMARY_HEX } from "@tellescope/constants"
7
7
  import { FormResponse, FormField, Form, Enduser } from "@tellescope/types-client"
8
8
  import { FormResponseAnswerFileValue, OrganizationTheme } from "@tellescope/types-models"
@@ -137,6 +137,7 @@ export const QuestionForField = ({
137
137
  logicOptions,
138
138
  uploadingFiles, setUploadingFiles, handleFileUpload,
139
139
  groupFields,
140
+ AddToDatabase,
140
141
  } : {
141
142
  spacing?: number,
142
143
  form?: Form,
@@ -154,6 +155,7 @@ export const QuestionForField = ({
154
155
  uploadingFiles: { fieldId: string }[]
155
156
  setUploadingFiles: React.Dispatch<React.SetStateAction<{ fieldId: string }[]>>,
156
157
  groupFields?: FormField[],
158
+ AddToDatabase?: React.JSXElementConstructor<AddToDatabaseProps>,
157
159
  } & Pick<TellescopeFormProps, "rootResponseId" | "goToNextField" | "groupId" | "groupInstance" | "submit" | "formResponseId" | 'enduserId' | 'isPreviousDisabled' | 'goToPreviousField' | 'enduser' | 'handleDatabaseSelect' | 'onAddFile' | 'onFieldChange' | 'fields' | 'customInputs' | 'responses' | 'selectedFiles' | 'validateField'>) => {
158
160
  const String = customInputs?.['string'] ?? StringInput
159
161
  const StringLong = customInputs?.['stringLong'] ?? StringLongInput
@@ -325,6 +327,7 @@ export const QuestionForField = ({
325
327
  <DatabaseSelect field={field} disabled={value.disabled} value={value.answer.value as any} onChange={onFieldChange as ChangeHandler<'Database Select'>}
326
328
  onDatabaseSelect={handleDatabaseSelect}
327
329
  responses={responses} form={form}
330
+ AddToDatabase={AddToDatabase}
328
331
  />
329
332
  )
330
333
  : field.type === 'Medications' ? (
@@ -332,6 +335,7 @@ export const QuestionForField = ({
332
335
  )
333
336
  : field.type === 'Insurance' ? (
334
337
  <Insurance field={field} value={value.answer.value as any} form={form}
338
+ onDatabaseSelect={handleDatabaseSelect}
335
339
  enduser={enduser} responses={responses} // for filtering insurers by state
336
340
  onChange={(v, fieldId) => (onFieldChange as ChangeHandler<'Insurance'>)({
337
341
  ...v,
@@ -381,6 +385,7 @@ export const QuestionForField = ({
381
385
  questionGroupSize={field.options?.subFields?.length}
382
386
  uploadingFiles={uploadingFiles} setUploadingFiles={setUploadingFiles}
383
387
  handleFileUpload={handleFileUpload}
388
+ AddToDatabase={AddToDatabase}
384
389
  />
385
390
  </Flex>
386
391
  )
@@ -918,6 +923,7 @@ export const TellescopeSinglePageForm: React.JSXElementConstructor<TellescopeFor
918
923
  updatedAt?: Date,
919
924
  otherEnduserIds?: string[],
920
925
  onBulkErrors?: (errors: { enduserId: string, message: string }[]) => void,
926
+ AddToDatabase?: React.JSXElementConstructor<AddToDatabaseProps>,
921
927
  }> = ({
922
928
  customInputs,
923
929
  submitErrorMessage,
@@ -969,6 +975,7 @@ export const TellescopeSinglePageForm: React.JSXElementConstructor<TellescopeFor
969
975
  groupId,
970
976
  groupInstance,
971
977
  uploadingFiles, setUploadingFiles, handleFileUpload,
978
+ AddToDatabase,
972
979
  ...props
973
980
  }) => {
974
981
  const list = useListForFormFields(fields, responses, { form: props.form, gender: enduser?.gender })
@@ -1051,6 +1058,7 @@ export const TellescopeSinglePageForm: React.JSXElementConstructor<TellescopeFor
1051
1058
  groupId={groupId} groupInstance={groupInstance}
1052
1059
  uploadingFiles={uploadingFiles} setUploadingFiles={setUploadingFiles}
1053
1060
  handleFileUpload={handleFileUpload}
1061
+ AddToDatabase={AddToDatabase}
1054
1062
  />
1055
1063
  </Flex>
1056
1064
  </Flex>
@@ -532,10 +532,10 @@ export const NumberInput = ({ field, value, onChange, form, ...props }: FormInpu
532
532
  )
533
533
  }
534
534
 
535
- export const InsuranceInput = ({ field, value, onChange, form, responses, enduser, ...props }: FormInputProps<'Insurance'>) => {
535
+ export const InsuranceInput = ({ field, onDatabaseSelect, value, onChange, form, responses, enduser, ...props }: FormInputProps<'Insurance'>) => {
536
536
  const session = useResolvedSession()
537
537
 
538
- const [payers, setPayers] = useState<{ id: string, name: string, type?: string, state?: string }[]>([])
538
+ const [payers, setPayers] = useState<{ id: string, name: string, databaseRecord?: DatabaseRecord, type?: string, state?: string }[]>([])
539
539
  const [query, setQuery] = useState('')
540
540
 
541
541
  const addressQuestion = useMemo(() => responses?.find(r => {
@@ -567,6 +567,7 @@ export const InsuranceInput = ({ field, value, onChange, form, responses, enduse
567
567
  name: c.values.find(v => v.label?.trim()?.toLowerCase() === 'name')?.value?.toString() || '',
568
568
  state: c.values.find(v => v.label?.trim()?.toLowerCase() === 'state')?.value?.toString() || '',
569
569
  type: c.values.find(v => v.label?.trim()?.toLowerCase() === 'type')?.value?.toString() || '',
570
+ databaseRecord: c,
570
571
  }))
571
572
  .filter(c => !c.state || !state || (c.state === state))
572
573
  ))
@@ -613,6 +614,11 @@ export const InsuranceInput = ({ field, value, onChange, form, responses, enduse
613
614
  : (e, v) => {
614
615
  if (v) { setQuery(v) }
615
616
 
617
+ const databaseRecord = payers.find(p => p.name === v)?.databaseRecord
618
+ if (databaseRecord) {
619
+ onDatabaseSelect?.([databaseRecord])
620
+ }
621
+
616
622
  onChange({
617
623
  ...value,
618
624
  payerName: v || '',
@@ -1864,7 +1870,18 @@ const useDatabaseChoices = ({ databaseId='', field, otherAnswers } : { databaseI
1864
1870
  })
1865
1871
  }, [session, field, databaseId, renderCount])
1866
1872
 
1873
+ const addChoice = useCallback((record: DatabaseRecord) => {
1874
+ if (!choicesForDatabase[databaseId]) {
1875
+ choicesForDatabase[databaseId] = {
1876
+ done: false,
1877
+ records: [],
1878
+ }
1879
+ }
1880
+ choicesForDatabase[databaseId].records!.push(record)
1881
+ }, [choicesForDatabase, databaseId])
1882
+
1867
1883
  return {
1884
+ addChoice,
1868
1885
  doneLoading: choicesForDatabase[databaseId]?.done ?? false,
1869
1886
  choices: [
1870
1887
  ...choicesForDatabase[databaseId]?.records ?? [],
@@ -1915,11 +1932,17 @@ const get_other_answers = (_value?: DatabaseSelectResponse[], typing?: string) =
1915
1932
  return []
1916
1933
  }
1917
1934
 
1918
- export const DatabaseSelectInput = ({ field, value: _value, onChange, onDatabaseSelect, responses, size, disabled }: FormInputProps<'Database Select'> & {
1935
+ export interface AddToDatabaseProps {
1936
+ databaseId: string,
1937
+ onAdd: (record: DatabaseRecord) => void
1938
+ }
1939
+
1940
+ export const DatabaseSelectInput = ({ AddToDatabase, field, value: _value, onChange, onDatabaseSelect, responses, size, disabled }: FormInputProps<'Database Select'> & {
1919
1941
  responses: FormResponseValue[],
1942
+ AddToDatabase?: React.JSXElementConstructor<AddToDatabaseProps>,
1920
1943
  }) => {
1921
1944
  const [typing, setTyping] = useState('')
1922
- const { choices, doneLoading } = useDatabaseChoices({
1945
+ const { addChoice, choices, doneLoading } = useDatabaseChoices({
1923
1946
  databaseId: field.options?.databaseId,
1924
1947
  field,
1925
1948
  otherAnswers: get_other_answers(_value, field?.options?.other ? typing : undefined),
@@ -2010,6 +2033,7 @@ export const DatabaseSelectInput = ({ field, value: _value, onChange, onDatabase
2010
2033
 
2011
2034
  if (!doneLoading) return <LinearProgress />
2012
2035
  return (
2036
+ <>
2013
2037
  <Autocomplete id={field.id} freeSolo={false} size={size}
2014
2038
  componentsProps={{ popper: { sx: { wordBreak: "break-word" } } } }
2015
2039
  options={filteredChoices} multiple={true}
@@ -2022,7 +2046,11 @@ export const DatabaseSelectInput = ({ field, value: _value, onChange, onDatabase
2022
2046
  disabled={disabled}
2023
2047
  onChange={(_, v) => {
2024
2048
  if (v.length && onDatabaseSelect) {
2025
- onDatabaseSelect(v)
2049
+ onDatabaseSelect(
2050
+ field.options?.radio
2051
+ ? [v[v.length - 1]] // if radio, only last selected
2052
+ : v
2053
+ )
2026
2054
  }
2027
2055
  return onChange(
2028
2056
  (
@@ -2055,6 +2083,11 @@ export const DatabaseSelectInput = ({ field, value: _value, onChange, onDatabase
2055
2083
  ))
2056
2084
  }
2057
2085
  />
2086
+
2087
+ {AddToDatabase && field?.options?.allowAddToDatabase && (
2088
+ <AddToDatabase databaseId={field.options?.databaseId!} onAdd={addChoice} />
2089
+ )}
2090
+ </>
2058
2091
  )
2059
2092
  }
2060
2093
 
package/src/displays.tsx CHANGED
@@ -8,6 +8,7 @@ import {
8
8
  value_is_loaded,
9
9
  useUsers,
10
10
  convertHEIC,
11
+ ImageProps,
11
12
  } from "./index"
12
13
 
13
14
  import { Avatar, AvatarProps, Styled } from "./mui"
@@ -72,6 +73,7 @@ export const SecureImage = ({ secureName, placeholder, onImageClick, ...props }
72
73
  secureName: string,
73
74
  alt?: string,
74
75
  onImageClick?: (args: { src: string }) => void,
76
+ crossOrigin?: ImageProps['crossOrigin'],
75
77
  } & ImageDimensions & Styled) => {
76
78
  const loadedImage = useFileForSecureName({ secureName })
77
79
 
package/src/layout.tsx CHANGED
@@ -41,9 +41,10 @@ export interface ImageProps extends ImageDimensions, Styled {
41
41
  src: string,
42
42
  alt?: string,
43
43
  onClick?: () => void,
44
+ crossOrigin?: 'anonymous' | 'use-credentials',
44
45
  }
45
- export const Image = ({ src, alt, style, onClick, ...props }: ImageProps) => (
46
- <img src={src} alt={alt} onClick={onClick} style={{ cursor: !!onClick ? 'pointer' : undefined, ...props, ...style }} />
46
+ export const Image = ({ src, alt, style, onClick, crossOrigin, ...props }: ImageProps) => (
47
+ <img crossOrigin={crossOrigin} src={src} alt={alt} onClick={onClick} style={{ cursor: !!onClick ? 'pointer' : undefined, ...props, ...style }} />
47
48
  )
48
49
 
49
50
  export interface VideoProps extends Styled {