@tellescope/react-components 1.250.2 → 1.252.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 (42) hide show
  1. package/lib/cjs/CMS/ContentViewer.js +3 -3
  2. package/lib/cjs/Community/community.js +1 -1
  3. package/lib/cjs/Forms/form_responses.js +3 -3
  4. package/lib/cjs/Forms/form_responses.js.map +1 -1
  5. package/lib/cjs/Forms/forms.d.ts.map +1 -1
  6. package/lib/cjs/Forms/forms.js +4 -2
  7. package/lib/cjs/Forms/forms.js.map +1 -1
  8. package/lib/cjs/Forms/forms.v2.js +2 -2
  9. package/lib/cjs/Forms/hooks.d.ts.map +1 -1
  10. package/lib/cjs/Forms/hooks.js +22 -20
  11. package/lib/cjs/Forms/hooks.js.map +1 -1
  12. package/lib/cjs/Forms/inputs.d.ts.map +1 -1
  13. package/lib/cjs/Forms/inputs.js +7 -1
  14. package/lib/cjs/Forms/inputs.js.map +1 -1
  15. package/lib/cjs/displays.js +1 -1
  16. package/lib/cjs/displays.js.map +1 -1
  17. package/lib/esm/CMS/ContentViewer.js +4 -4
  18. package/lib/esm/Community/community.js +2 -2
  19. package/lib/esm/Forms/form_responses.js +4 -4
  20. package/lib/esm/Forms/form_responses.js.map +1 -1
  21. package/lib/esm/Forms/forms.d.ts.map +1 -1
  22. package/lib/esm/Forms/forms.js +5 -3
  23. package/lib/esm/Forms/forms.js.map +1 -1
  24. package/lib/esm/Forms/forms.v2.js +3 -3
  25. package/lib/esm/Forms/hooks.d.ts.map +1 -1
  26. package/lib/esm/Forms/hooks.js +22 -20
  27. package/lib/esm/Forms/hooks.js.map +1 -1
  28. package/lib/esm/Forms/inputs.d.ts.map +1 -1
  29. package/lib/esm/Forms/inputs.js +7 -1
  30. package/lib/esm/Forms/inputs.js.map +1 -1
  31. package/lib/esm/displays.js +2 -2
  32. package/lib/esm/displays.js.map +1 -1
  33. package/lib/tsconfig.tsbuildinfo +1 -1
  34. package/package.json +9 -9
  35. package/src/CMS/ContentViewer.tsx +4 -4
  36. package/src/Community/community.tsx +2 -2
  37. package/src/Forms/form_responses.tsx +4 -4
  38. package/src/Forms/forms.tsx +5 -3
  39. package/src/Forms/forms.v2.tsx +3 -3
  40. package/src/Forms/hooks.tsx +3 -1
  41. package/src/Forms/inputs.tsx +6 -1
  42. package/src/displays.tsx +2 -2
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tellescope/react-components",
3
- "version": "1.250.2",
3
+ "version": "1.252.0",
4
4
  "description": "",
5
5
  "main": "./lib/cjs/index.js",
6
6
  "module": "./lib/esm/index.js",
@@ -51,13 +51,13 @@
51
51
  "@reduxjs/toolkit": "1.9.0",
52
52
  "@stripe/react-stripe-js": "2.9.0",
53
53
  "@stripe/stripe-js": "1.52.1",
54
- "@tellescope/constants": "1.250.2",
55
- "@tellescope/sdk": "1.250.2",
56
- "@tellescope/types-client": "1.250.2",
57
- "@tellescope/types-models": "1.250.2",
58
- "@tellescope/types-utilities": "1.250.2",
59
- "@tellescope/utilities": "1.250.2",
60
- "@tellescope/validation": "1.250.2",
54
+ "@tellescope/constants": "1.252.0",
55
+ "@tellescope/sdk": "1.252.0",
56
+ "@tellescope/types-client": "1.252.0",
57
+ "@tellescope/types-models": "1.252.0",
58
+ "@tellescope/types-utilities": "1.252.0",
59
+ "@tellescope/utilities": "1.252.0",
60
+ "@tellescope/validation": "1.252.0",
61
61
  "@twilio/video-processors": "3.2.0",
62
62
  "css-to-react-native": "3.0.0",
63
63
  "draft-js": "0.11.7",
@@ -85,7 +85,7 @@
85
85
  "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
86
86
  "react-native": "^0.65.0 || ^0.66.0 || ^0.67.0 || ^0.68.0 || ^0.71.0"
87
87
  },
88
- "gitHead": "595c21b2b46ee87643c2a5cb4183e7ecf2185293",
88
+ "gitHead": "00b42c82462699491547e2bded4aad41a5d57daa",
89
89
  "publishConfig": {
90
90
  "access": "public"
91
91
  }
@@ -1,6 +1,6 @@
1
1
  import React, { useEffect, useLayoutEffect, useRef, useState } from "react"
2
2
  import { ManagedContentRecord } from "@tellescope/types-client"
3
- import { remove_script_tags, sanitize_html_for_cms } from "@tellescope/utilities"
3
+ import { sanitize_user_html, sanitize_html_for_cms } from "@tellescope/utilities"
4
4
  import { Button, Grid, Typography } from "@mui/material"
5
5
  import { PDFBlockUI } from "./components"
6
6
  import { css } from "@emotion/css"
@@ -190,7 +190,7 @@ export const ArticleViewer = ({
190
190
  else if (article.htmlContent) {
191
191
  return (
192
192
  <div style={style} dangerouslySetInnerHTML={{
193
- __html: remove_script_tags(article.htmlContent)
193
+ __html: sanitize_user_html(article.htmlContent)
194
194
  }} />
195
195
  )
196
196
  } else {
@@ -224,7 +224,7 @@ export const ArticleViewer = ({
224
224
  margin-bottom: 0;
225
225
  }`}
226
226
  dangerouslySetInnerHTML={{
227
- __html: remove_script_tags(
227
+ __html: sanitize_user_html(
228
228
  block.info.html.replaceAll(/style="*"/g, '')
229
229
  )
230
230
  }}
@@ -306,7 +306,7 @@ export const html_for_article = (article: ManagedContentRecord, options?: { root
306
306
  `<h2>${block.info.text}</h2>`
307
307
  )
308
308
  : block.type === 'html' ? (
309
- `<div>${remove_script_tags(remove_script_tags(block.info.html))}</div>`
309
+ `<div>${sanitize_user_html(sanitize_user_html(block.info.html))}</div>`
310
310
  )
311
311
  : block.type === 'raw-html' ? (
312
312
  `<div>${sanitize_html_for_cms(block.info.html)}</div>`
@@ -28,7 +28,7 @@ import { Divider, Grid, LinearProgress, Paper, TextField, Typography } from "@mu
28
28
  import {
29
29
  usePostLiking,
30
30
  } from "./hooks"
31
- import { remove_script_tags, truncate_string, user_is_admin } from "@tellescope/utilities"
31
+ import { sanitize_user_html, truncate_string, user_is_admin } from "@tellescope/utilities"
32
32
 
33
33
  import LikeIcon from "@mui/icons-material/ThumbUp"
34
34
 
@@ -50,7 +50,7 @@ export const ResolvedContent = ({ textContent, htmlContent, style } : { textCont
50
50
  if (htmlContent) {
51
51
  return (
52
52
  <div style={style} dangerouslySetInnerHTML={{
53
- __html: remove_script_tags(htmlContent),
53
+ __html: sanitize_user_html(htmlContent),
54
54
  }} />
55
55
  )
56
56
  }
@@ -1,7 +1,7 @@
1
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
- import { form_response_value_to_string, formatted_date, getOrgnizationLogoURL, remove_script_tags, user_display_name } from "@tellescope/utilities"
4
+ import { form_response_value_to_string, formatted_date, getOrgnizationLogoURL, sanitize_user_html, user_display_name } from "@tellescope/utilities"
5
5
  import { DownloadFileIconButton, ImageProps, LabeledIconButton, SecureImage, useEndusers, useEnduserMedications, useEnduserObservations, 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"
@@ -161,7 +161,7 @@ export const ResponseAnswer = ({ formResponse, fieldId, isHTML, answer: a, print
161
161
  isHTML?: boolean,
162
162
  }) => (
163
163
  ((isHTML || a.type === 'Rich Text') && typeof a.value === 'string')
164
- ? <div dangerouslySetInnerHTML={{ __html: remove_script_tags(a.value) }} />
164
+ ? <div dangerouslySetInnerHTML={{ __html: sanitize_user_html(a.value) }} />
165
165
  : a.value
166
166
  ? (
167
167
  <Typography component="div">
@@ -461,7 +461,7 @@ export const FormResponseView = ({ showAnswerInline=true, logoURL, enduser, onCl
461
461
  && !(typeof r.answer.value === 'string' && r.answer.value.includes('{TELLESCOPE')) // hidden field for matching, not to display
462
462
  && (
463
463
  (r.answerIsHTML && typeof r.answer.value === 'string')
464
- ? <div dangerouslySetInnerHTML={{ __html: remove_script_tags(r.answer.value) }} />
464
+ ? <div dangerouslySetInnerHTML={{ __html: sanitize_user_html(r.answer.value) }} />
465
465
  : <ResponseAnswer fieldId={r.fieldId} formResponse={response} answer={r.answer} printing={printing} />
466
466
  )
467
467
  }
@@ -476,7 +476,7 @@ export const FormResponseView = ({ showAnswerInline=true, logoURL, enduser, onCl
476
476
  ): r.fieldHtmlDescription
477
477
  ? (
478
478
  <div dangerouslySetInnerHTML={{
479
- __html: r.fieldHtmlDescription
479
+ __html: sanitize_user_html(r.fieldHtmlDescription)
480
480
  }} />
481
481
  )
482
482
  : null
@@ -6,7 +6,7 @@ import { AddToDatabaseProps, AddressInput, AllergiesInput, AppointmentBookingInp
6
6
  import { PRIMARY_HEX } from "@tellescope/constants"
7
7
  import { FormResponse, FormField, Form, Enduser } from "@tellescope/types-client"
8
8
  import { FormResponseAnswerFileValue, OrganizationTheme, HistoricalDataSource } from "@tellescope/types-models"
9
- import { calculate_form_scoring, field_can_autosubmit, form_response_value_to_string, formatted_date, object_is_empty, objects_equivalent, read_local_storage, remove_script_tags, responses_satisfy_conditions, truncate_string } from "@tellescope/utilities"
9
+ import { calculate_form_scoring, field_can_autosubmit, form_response_value_to_string, formatted_date, object_is_empty, objects_equivalent, read_local_storage, sanitize_user_html, responses_satisfy_conditions, truncate_string } from "@tellescope/utilities"
10
10
  import { Divider } from "@mui/material"
11
11
 
12
12
  export const TellescopeFormContainer = ({ businessId, organizationIds, ...props } : {
@@ -798,7 +798,7 @@ export const ThanksMessage = ({
798
798
  {htmlThanksMessage
799
799
  ? (
800
800
  <div style={{ textAlign: 'center' }} dangerouslySetInnerHTML={{
801
- __html: remove_script_tags(htmlThanksMessage)
801
+ __html: sanitize_user_html(htmlThanksMessage)
802
802
  }} />
803
803
  ) : (
804
804
  <Typography style={{ marginTop: 25, alignSelf: 'center' }}>{thanksMessage || DEFAULT_THANKS_MESSAGE}</Typography>
@@ -1068,6 +1068,8 @@ const HistoricalDataSection = ({ sources, enduserId, onDataLoaded } : { sources:
1068
1068
  session.api.enduser_observations.getSome({
1069
1069
  filter: { enduserId, ...source.filter },
1070
1070
  limit: source.limit,
1071
+ sortBy: 'timestamp',
1072
+ sort: 'newFirst',
1071
1073
  })
1072
1074
  .then((obs: any[]) => { loadedObservations = obs; setObservations(obs) })
1073
1075
  )
@@ -1236,7 +1238,7 @@ export const Description = ({ field, color="primary", style, enduserId, onFieldC
1236
1238
  </Typography>
1237
1239
  ) : field.htmlDescription ? (
1238
1240
  <span dangerouslySetInnerHTML={{
1239
- __html: remove_script_tags(field.htmlDescription)
1241
+ __html: sanitize_user_html(field.htmlDescription)
1240
1242
  }} />
1241
1243
  ) : null
1242
1244
  )
@@ -6,7 +6,7 @@ import { AddToDatabaseProps, AddressInput, AllergiesInput, AppointmentBookingInp
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"
9
- import { calculate_form_scoring, field_can_autosubmit, form_response_value_to_string, formatted_date, object_is_empty, objects_equivalent, read_local_storage, remove_script_tags, responses_satisfy_conditions, truncate_string } from "@tellescope/utilities"
9
+ import { calculate_form_scoring, field_can_autosubmit, form_response_value_to_string, formatted_date, object_is_empty, objects_equivalent, read_local_storage, sanitize_user_html, responses_satisfy_conditions, truncate_string } from "@tellescope/utilities"
10
10
  import { Divider } from "@mui/material"
11
11
 
12
12
  export const TellescopeFormContainerV2 = ({ businessId, organizationIds, ...props } : {
@@ -836,7 +836,7 @@ export const ThanksMessage = ({
836
836
  {htmlThanksMessage
837
837
  ? (
838
838
  <div style={{ textAlign: 'center' }} dangerouslySetInnerHTML={{
839
- __html: remove_script_tags(htmlThanksMessage)
839
+ __html: sanitize_user_html(htmlThanksMessage)
840
840
  }} />
841
841
  ) : (
842
842
  <Typography style={{ marginTop: 25, alignSelf: 'center' }}>{thanksMessage || DEFAULT_THANKS_MESSAGE}</Typography>
@@ -1092,7 +1092,7 @@ export const Description = ({ field, color="primary", style } : { field: FormFie
1092
1092
 
1093
1093
  return (
1094
1094
  <span style={style} dangerouslySetInnerHTML={{
1095
- __html: remove_script_tags(field.htmlDescription)
1095
+ __html: sanitize_user_html(field.htmlDescription)
1096
1096
  }} />
1097
1097
  )
1098
1098
  }
@@ -1219,7 +1219,9 @@ export const useTellescopeForm = ({ dontAutoadvance, isPublicForm, form, urlLogi
1219
1219
  if (field.type === 'files' && value.answer.type === 'files' && Array.isArray(value.answer.value)) {
1220
1220
  existingCount = value.answer.value.filter(av => !file.blobs?.some(b => b.name === av.name)).length
1221
1221
  } else if (field.type === 'file' && value.answer.type === 'file' && value.answer.value?.secureName) {
1222
- existingCount = 1
1222
+ const existingFileName = value.answer.value.name
1223
+ const hasMatchingBlob = file.blobs?.some(b => b.name === existingFileName)
1224
+ existingCount = hasMatchingBlob ? 0 : 1
1223
1225
  }
1224
1226
 
1225
1227
  const totalCount = blobCount + existingCount
@@ -5060,8 +5060,13 @@ export const HiddenValueInput = ({ goToNextField, goToPreviousField, field, valu
5060
5060
  if (dontNavigate) return
5061
5061
  goToPreviousField?.()
5062
5062
  } else {
5063
- onChange(valueToSet, field.id)
5063
+ // Avoid redundant setResponses when value is already correct — prevents the effect
5064
+ // from cascading into every keystroke on sibling text fields in single-page forms.
5065
+ if (value !== valueToSet) {
5066
+ onChange(valueToSet, field.id)
5067
+ }
5064
5068
 
5069
+ if (isSinglePage) return
5065
5070
  if (dontNavigate) return
5066
5071
 
5067
5072
  // pass value that is set after above onChange
package/src/displays.tsx CHANGED
@@ -1,6 +1,6 @@
1
1
  import React, { useEffect, useRef, useState } from "react"
2
2
 
3
- import { user_display_name } from "@tellescope/utilities"
3
+ import { sanitize_user_html, user_display_name } from "@tellescope/utilities"
4
4
 
5
5
  import {
6
6
  useEndusers,
@@ -304,5 +304,5 @@ export const replace_links = (html: string) => {
304
304
  html = html.replace(linkTemplate, replacementHTML)
305
305
  }
306
306
 
307
- return <span dangerouslySetInnerHTML={{ __html: html }} />
307
+ return <span dangerouslySetInnerHTML={{ __html: sanitize_user_html(html) }} />
308
308
  }