@aehrc/smart-forms-renderer 1.2.0 → 1.2.2

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 (135) hide show
  1. package/lib/components/FormComponents/ItemParts/FadingCheckIcon.d.ts +7 -0
  2. package/lib/components/FormComponents/ItemParts/FadingCheckIcon.js +26 -0
  3. package/lib/components/FormComponents/ItemParts/FadingCheckIcon.js.map +1 -0
  4. package/lib/components/FormComponents/ItemParts/ItemLabelText.d.ts +8 -0
  5. package/lib/components/FormComponents/ItemParts/ItemLabelText.js +63 -0
  6. package/lib/components/FormComponents/ItemParts/ItemLabelText.js.map +1 -0
  7. package/lib/components/FormComponents/ItemParts/ItemLabelWrapper.d.ts +8 -0
  8. package/lib/components/FormComponents/ItemParts/ItemLabelWrapper.js +53 -0
  9. package/lib/components/FormComponents/ItemParts/ItemLabelWrapper.js.map +1 -0
  10. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceAutocompleteItem.js +4 -3
  11. package/lib/components/FormComponents/OpenChoiceItems/OpenChoiceAutocompleteItem.js.map +1 -1
  12. package/lib/components/FormComponents/RepeatGroup/DeleteItemButton.d.ts +10 -0
  13. package/lib/components/FormComponents/RepeatGroup/DeleteItemButton.js +30 -0
  14. package/lib/components/FormComponents/RepeatGroup/DeleteItemButton.js.map +1 -0
  15. package/lib/components/FormComponents/SingleItem/SingleItem.js +15 -2
  16. package/lib/components/FormComponents/SingleItem/SingleItem.js.map +1 -1
  17. package/lib/components/FormComponents/SingleItem/SingleNestedItems.js +8 -8
  18. package/lib/components/FormComponents/SingleItem/SingleNestedItems.js.map +1 -1
  19. package/lib/components/Iconify/Iconify.d.ts +10 -0
  20. package/lib/components/Iconify/Iconify.js +26 -0
  21. package/lib/components/Iconify/Iconify.js.map +1 -0
  22. package/lib/components/Renderer/FormBodyPage.d.ts +9 -0
  23. package/lib/components/Renderer/FormBodyPage.js +43 -0
  24. package/lib/components/Renderer/FormBodyPage.js.map +1 -0
  25. package/lib/components/Renderer/FormTitle.d.ts +7 -0
  26. package/lib/components/Renderer/FormTitle.js +30 -0
  27. package/lib/components/Renderer/FormTitle.js.map +1 -0
  28. package/lib/components/Renderer/FormTopLevelPage.d.ts +9 -0
  29. package/lib/components/Renderer/FormTopLevelPage.js +29 -0
  30. package/lib/components/Renderer/FormTopLevelPage.js.map +1 -0
  31. package/lib/components/Tabs/FormBodyTabListWrapper.js +1 -1
  32. package/lib/components/Tabs/FormBodyTabListWrapper.js.map +1 -1
  33. package/lib/hooks/useBooleanCalculatedExpression.d.ts +12 -0
  34. package/lib/hooks/useBooleanCalculatedExpression.js +53 -0
  35. package/lib/hooks/useBooleanCalculatedExpression.js.map +1 -0
  36. package/lib/hooks/useDecimalCalculatedExpression.d.ts +13 -0
  37. package/lib/hooks/useDecimalCalculatedExpression.js +59 -0
  38. package/lib/hooks/useDecimalCalculatedExpression.js.map +1 -0
  39. package/lib/hooks/useIntegerCalculatedExpression.d.ts +12 -0
  40. package/lib/hooks/useIntegerCalculatedExpression.js +56 -0
  41. package/lib/hooks/useIntegerCalculatedExpression.js.map +1 -0
  42. package/lib/hooks/useQuantityCalculatedExpression.d.ts +14 -0
  43. package/lib/hooks/useQuantityCalculatedExpression.js +107 -0
  44. package/lib/hooks/useQuantityCalculatedExpression.js.map +1 -0
  45. package/lib/hooks/useStringCalculatedExpression.d.ts +12 -0
  46. package/lib/hooks/useStringCalculatedExpression.js +58 -0
  47. package/lib/hooks/useStringCalculatedExpression.js.map +1 -0
  48. package/lib/stores/rendererConfigStore.d.ts +1 -1
  49. package/lib/stories/storybookWrappers/InitialiseFormWrapperForStorybook.d.ts +3 -2
  50. package/lib/stories/storybookWrappers/InitialiseFormWrapperForStorybook.js +27 -6
  51. package/lib/stories/storybookWrappers/InitialiseFormWrapperForStorybook.js.map +1 -1
  52. package/lib/stories/storybookWrappers/index.js +1 -1
  53. package/lib/theme/Theme.d.ts +44 -0
  54. package/lib/theme/Theme.js +43 -0
  55. package/lib/theme/Theme.js.map +1 -0
  56. package/lib/theme/customGlobalStyles.d.ts +2 -0
  57. package/lib/theme/customGlobalStyles.js +61 -0
  58. package/lib/theme/customGlobalStyles.js.map +1 -0
  59. package/lib/theme/overrides/Accordion.d.ts +14 -0
  60. package/lib/theme/overrides/Accordion.js +32 -0
  61. package/lib/theme/overrides/Accordion.js.map +1 -0
  62. package/lib/theme/overrides/Autocomplete.d.ts +10 -0
  63. package/lib/theme/overrides/Autocomplete.js +28 -0
  64. package/lib/theme/overrides/Autocomplete.js.map +1 -0
  65. package/lib/theme/overrides/Button.d.ts +33 -0
  66. package/lib/theme/overrides/Button.js +52 -0
  67. package/lib/theme/overrides/Button.js.map +1 -0
  68. package/lib/theme/overrides/Card.d.ts +35 -0
  69. package/lib/theme/overrides/Card.js +49 -0
  70. package/lib/theme/overrides/Card.js.map +1 -0
  71. package/lib/theme/overrides/Input.d.ts +64 -0
  72. package/lib/theme/overrides/Input.js +81 -0
  73. package/lib/theme/overrides/Input.js.map +1 -0
  74. package/lib/theme/overrides/Overrides.d.ts +3 -0
  75. package/lib/theme/overrides/Overrides.js +29 -0
  76. package/lib/theme/overrides/Overrides.js.map +1 -0
  77. package/lib/theme/overrides/Paper.d.ts +12 -0
  78. package/lib/theme/overrides/Paper.js +31 -0
  79. package/lib/theme/overrides/Paper.js.map +1 -0
  80. package/lib/theme/overrides/SpeedDial.d.ts +16 -0
  81. package/lib/theme/overrides/SpeedDial.js +34 -0
  82. package/lib/theme/overrides/SpeedDial.js.map +1 -0
  83. package/lib/theme/overrides/Table.d.ts +12 -0
  84. package/lib/theme/overrides/Table.js +30 -0
  85. package/lib/theme/overrides/Table.js.map +1 -0
  86. package/lib/theme/palette.d.ts +27 -0
  87. package/lib/theme/palette.js +63 -0
  88. package/lib/theme/palette.js.map +1 -0
  89. package/lib/theme/shadows.d.ts +2 -0
  90. package/lib/theme/shadows.js +52 -0
  91. package/lib/theme/shadows.js.map +1 -0
  92. package/lib/utils/calculatedExpression.js +11 -0
  93. package/lib/utils/calculatedExpression.js.map +1 -1
  94. package/lib/utils/dayjsExtend.d.ts +1 -0
  95. package/lib/utils/dayjsExtend.js +22 -0
  96. package/lib/utils/dayjsExtend.js.map +1 -0
  97. package/lib/utils/initialise.js +8 -1
  98. package/lib/utils/initialise.js.map +1 -1
  99. package/lib/utils/itemControl.d.ts +103 -0
  100. package/lib/utils/itemControl.js +350 -0
  101. package/lib/utils/itemControl.js.map +1 -0
  102. package/lib/utils/mapItem.d.ts +1 -1
  103. package/lib/utils/mapItem.js +2 -0
  104. package/lib/utils/mapItem.js.map +1 -1
  105. package/lib/utils/qrItem.d.ts +13 -0
  106. package/lib/utils/qrItem.js +76 -0
  107. package/lib/utils/qrItem.js.map +1 -1
  108. package/lib/utils/questionnaireStoreUtils/addAdditionalVariables.d.ts +2 -0
  109. package/lib/utils/questionnaireStoreUtils/addAdditionalVariables.js +43 -0
  110. package/lib/utils/questionnaireStoreUtils/addAdditionalVariables.js.map +1 -0
  111. package/lib/utils/questionnaireStoreUtils/createQuestionaireModel.d.ts +3 -0
  112. package/lib/utils/questionnaireStoreUtils/createQuestionaireModel.js +101 -0
  113. package/lib/utils/questionnaireStoreUtils/createQuestionaireModel.js.map +1 -0
  114. package/lib/utils/questionnaireStoreUtils/extractOtherExtensions.js +4 -2
  115. package/lib/utils/questionnaireStoreUtils/extractOtherExtensions.js.map +1 -1
  116. package/lib/utils/validateQuestionnaire.d.ts +66 -0
  117. package/lib/utils/validateQuestionnaire.js +559 -0
  118. package/lib/utils/validateQuestionnaire.js.map +1 -0
  119. package/package.json +1 -1
  120. package/src/components/FormComponents/OpenChoiceItems/OpenChoiceAutocompleteItem.tsx +4 -3
  121. package/src/components/FormComponents/SingleItem/SingleItem.tsx +16 -2
  122. package/src/components/FormComponents/SingleItem/SingleNestedItems.tsx +8 -9
  123. package/src/components/Tabs/FormBodyTabListWrapper.tsx +1 -1
  124. package/src/stores/rendererConfigStore.ts +1 -1
  125. package/src/utils/calculatedExpression.ts +11 -0
  126. package/src/utils/initialise.ts +8 -1
  127. package/src/utils/mapItem.ts +3 -1
  128. package/src/utils/qrItem.ts +91 -0
  129. package/src/utils/questionnaireStoreUtils/extractOtherExtensions.ts +4 -2
  130. package/lib/interfaces/itemPath.interface.d.ts +0 -31
  131. package/lib/interfaces/itemPath.interface.js +0 -2
  132. package/lib/interfaces/itemPath.interface.js.map +0 -1
  133. package/lib/utils/itemPath.d.ts +0 -57
  134. package/lib/utils/itemPath.js +0 -75
  135. package/lib/utils/itemPath.js.map +0 -1
@@ -19,12 +19,11 @@ import React, { useMemo } from 'react';
19
19
  import type { QuestionnaireItem, QuestionnaireResponseItem } from 'fhir/r4';
20
20
  import { getQrItemsIndex, mapQItemsIndex } from '../../../utils/mapItem';
21
21
  import GroupItemSwitcher from '../GroupItem/GroupItemSwitcher';
22
- import { createEmptyQrGroup, updateQrItemsInGroup } from '../../../utils/qrItem';
22
+ import { createEmptyRepeatNestedItems, updateQrNestedItems } from '../../../utils/qrItem';
23
23
  import type {
24
24
  PropsWithParentIsReadOnlyAttribute,
25
25
  PropsWithQrItemChangeHandler
26
26
  } from '../../../interfaces/renderProps.interface';
27
- import type { QrRepeatGroup } from '../../../interfaces/repeatGroup.interface';
28
27
  import Box from '@mui/material/Box';
29
28
 
30
29
  interface SingleNestedItemsProps
@@ -41,27 +40,27 @@ function SingleNestedItems(props: SingleNestedItemsProps) {
41
40
  const qItemsIndexMap: Record<string, number> = useMemo(() => mapQItemsIndex(qItem), [qItem]);
42
41
 
43
42
  const qItems = qItem.item;
44
- const qrGroup = qrItem && qrItem.item ? qrItem : createEmptyQrGroup(qItem);
45
- const qrItems = qrGroup.item;
43
+ const qrGroup = qrItem && qrItem.answer ? qrItem : createEmptyRepeatNestedItems(qItem);
44
+ const qrAnswers = qrGroup.answer;
46
45
 
47
46
  // Event Handlers
48
47
  function handleQrItemChange(newQrItem: QuestionnaireResponseItem) {
49
48
  const updatedQrGroup: QuestionnaireResponseItem = { ...qrGroup };
50
- updateQrItemsInGroup(newQrItem, null, updatedQrGroup, qItemsIndexMap);
49
+ updateQrNestedItems(newQrItem, updatedQrGroup, qItemsIndexMap);
51
50
  onQrItemChange(updatedQrGroup);
52
51
  }
53
52
 
54
- function handleQrRepeatGroupChange(qrRepeatGroup: QrRepeatGroup) {
53
+ function handleQrRepeatGroupChange() {
55
54
  const updatedQrGroup: QuestionnaireResponseItem = { ...qrGroup };
56
- updateQrItemsInGroup(null, qrRepeatGroup, updatedQrGroup, qItemsIndexMap);
55
+ updateQrNestedItems(null, updatedQrGroup, qItemsIndexMap);
57
56
  onQrItemChange(updatedQrGroup);
58
57
  }
59
58
 
60
- if (!qItems || !qrItems) {
59
+ if (!qItems || !qrAnswers) {
61
60
  return <>Unable to load group, something has gone terribly wrong.</>;
62
61
  }
63
62
 
64
- const qrItemsByIndex = getQrItemsIndex(qItems, qrItems, qItemsIndexMap);
63
+ const qrItemsByIndex = getQrItemsIndex(qItems, qrAnswers[0]?.item, qItemsIndexMap);
65
64
 
66
65
  // TODO - Add support for horizontal "row" layout
67
66
  return (
@@ -45,7 +45,7 @@ const FormBodyTabListWrapper = memo(function FormBodyTabListWrapper(
45
45
  return (
46
46
  <Card sx={{ p: 0.75, mb: 2 }}>
47
47
  <Box sx={{ flexGrow: 1 }}>
48
- <aside aria-label="Questionaire tab items">
48
+ <aside aria-label="Form sections">
49
49
  <PrimarySelectableList
50
50
  dense
51
51
  disablePadding
@@ -74,7 +74,7 @@ import type { Breakpoints } from '@mui/material';
74
74
  * @property disableTabButtons - If `true`, hides navigation buttons for tabs.
75
75
  * - Default: `false`
76
76
  *
77
- * @property disableHeadingFocusOnTabSwitch - If `true`, the first heading will be focused when switching tabs.
77
+ * @property disableHeadingFocusOnTabSwitch - If `true`, disables automatic focus on the first heading when switching tabs.
78
78
  * - Default: `false`
79
79
  *
80
80
  * @property readOnlyVisualStyle - If `true`, item.readOnly will result in form fields having MUI disabled property and styles (recommended from usability perspective). If `false`, item.readOnly will result in form fields having HTML readonly property (less stable, but recommended from accessibility perspective).
@@ -705,6 +705,17 @@ function parseValueToAnswer(
705
705
  if (matchingAnswer) {
706
706
  return matchingAnswer;
707
707
  }
708
+ //If no matching answer is found, then we return the value as it is
709
+ else {
710
+ // if it is an object so that Calculated Expressions can retain the selected choice option.
711
+ if (typeof value === 'object') {
712
+ return { valueCoding: value };
713
+ }
714
+ // if it is a string from the choice field, return as it is
715
+ else if (typeof value === 'string') {
716
+ return { valueString: value };
717
+ }
718
+ }
708
719
  }
709
720
  }
710
721
 
@@ -168,7 +168,14 @@ function readInitialValuesRecursive(
168
168
  text: qItem.text
169
169
  };
170
170
  }
171
- qrItem.item = initialValues;
171
+
172
+ if (qItem.item && qItem.type !== 'group') {
173
+ qrItem.answer?.forEach((answer) => {
174
+ answer.item = initialValues.map((obj) => ({ ...obj }));
175
+ });
176
+ } else {
177
+ qrItem.item = initialValues.map((obj) => ({ ...obj }));
178
+ }
172
179
  }
173
180
 
174
181
  return qrItem ? [qrItem] : null;
@@ -30,12 +30,14 @@ import { isRepeatItemAndNotCheckbox } from './qItem';
30
30
  */
31
31
  export function getQrItemsIndex(
32
32
  qItems: QuestionnaireItem[],
33
- qrItems: QuestionnaireResponseItem[],
33
+ qrItems: QuestionnaireResponseItem[] | undefined,
34
34
  qItemsIndexMap: Record<string, number>
35
35
  ): (QuestionnaireResponseItem | QuestionnaireResponseItem[] | undefined)[] {
36
36
  // Generate a <linkId, QrItem OR QrItems> dictionary
37
37
  const qrItemsCollected: Record<string, QuestionnaireResponseItem | QuestionnaireResponseItem[]> =
38
38
  {};
39
+
40
+ if (!qrItems) return [];
39
41
  for (const qrItem of qrItems) {
40
42
  const linkId = qrItem.linkId;
41
43
 
@@ -67,6 +67,20 @@ export function createEmptyQrGroup(qItem: QuestionnaireItem): QuestionnaireRespo
67
67
  };
68
68
  }
69
69
 
70
+ /**
71
+ * Create an empty repeat qrItem from a given repeat qItem
72
+ *
73
+ * @author Clinton Gillespie
74
+ */
75
+ export function createEmptyRepeatNestedItems(qItem: QuestionnaireItem): QuestionnaireResponseItem {
76
+ return {
77
+ linkId: qItem.linkId,
78
+ text: qItem.text,
79
+ answer: [],
80
+ item: []
81
+ };
82
+ }
83
+
70
84
  /**
71
85
  * Create an empty qrItem from a given qItem, optionally with an answer key
72
86
  *
@@ -221,3 +235,80 @@ export function updateQrItemsInGroup(
221
235
  }
222
236
  }
223
237
  }
238
+
239
+ /**
240
+ * Updates the QuestionnaireResponseItem group by adding/removing a new/modified child QuestionnaireResponseItem into/from a qrGroup
241
+ * Specifically handles nested repeat items where each item has an answer array rather than nested items
242
+ *
243
+ * @author Sean Fong
244
+ */
245
+ export function updateQrNestedItems(
246
+ newQrItem: QuestionnaireResponseItem | null,
247
+ questionnaireResponseOrQrItem: QuestionnaireResponseItem,
248
+ qItemsIndexMap: Record<string, number>
249
+ ): void {
250
+ if (!newQrItem) return;
251
+ if (!questionnaireResponseOrQrItem.answer) {
252
+ questionnaireResponseOrQrItem.answer = [];
253
+ }
254
+
255
+ let qrAnswerItems = questionnaireResponseOrQrItem.answer;
256
+ if (!qrAnswerItems) {
257
+ qrAnswerItems = [];
258
+ }
259
+
260
+ if (newQrItem && newQrItem.linkId in qItemsIndexMap) {
261
+ if (qrAnswerItems.length === 0) {
262
+ // Only add if the item has answers (nested items use answer array, not item array)
263
+ if (newQrItem.answer?.length) {
264
+ qrAnswerItems.push({ item: [newQrItem] });
265
+ }
266
+ return;
267
+ }
268
+ }
269
+
270
+ // Find the index where newQrItem should be inserted based on qItemsIndexMap
271
+ const newItemSequenceIndex = qItemsIndexMap[newQrItem.linkId];
272
+
273
+ // Find the last answer object (group) that exists
274
+ const lastAnswerGroup = qrAnswerItems[qrAnswerItems.length - 1];
275
+
276
+ // If no answer group exists yet, create one
277
+ if (!lastAnswerGroup) {
278
+ const newGroup = {
279
+ item: [newQrItem]
280
+ };
281
+ qrAnswerItems.push(newGroup);
282
+ return;
283
+ }
284
+
285
+ // If the last answer group doesn't have an item array, create one
286
+ if (!lastAnswerGroup.item) {
287
+ lastAnswerGroup.item = [newQrItem];
288
+ return;
289
+ }
290
+
291
+ // Check if newQrItem already exists in the last group's item array
292
+ const existingItemIndex = lastAnswerGroup.item.findIndex(
293
+ (item) => item.linkId === newQrItem.linkId
294
+ );
295
+
296
+ if (existingItemIndex !== -1) {
297
+ // Item exists - overwrite it
298
+ lastAnswerGroup.item[existingItemIndex] = newQrItem;
299
+ } else {
300
+ // Item doesn't exist - find correct position to insert based on sequence
301
+ let insertIndex = lastAnswerGroup.item.length;
302
+
303
+ for (let i = 0; i < lastAnswerGroup.item.length; i++) {
304
+ const currentItemSequenceIndex = qItemsIndexMap[lastAnswerGroup.item[i].linkId];
305
+ if (newItemSequenceIndex < currentItemSequenceIndex) {
306
+ insertIndex = i;
307
+ break;
308
+ }
309
+ }
310
+ // Insert at the correct position
311
+ lastAnswerGroup.item.splice(insertIndex, 0, newQrItem);
312
+ return;
313
+ }
314
+ }
@@ -54,6 +54,7 @@ import type { InitialExpression } from '../../interfaces/initialExpression.inter
54
54
  import { addBindingParametersToValueSetUrl, getBindingParameters } from '../parameterisedValueSets';
55
55
  import type { AnswerOptionsToggleExpression } from '../../interfaces/answerOptionsToggleExpression.interface';
56
56
  import { getItemTerminologyServerToUse } from '../preferredTerminologyServer';
57
+ import { isSpecificItemControl } from '../extensions';
57
58
 
58
59
  interface ReturnParamsRecursive {
59
60
  variables: Variables;
@@ -282,9 +283,10 @@ async function extractExtensionsFromItemRecursive(
282
283
 
283
284
  // Only continue to process if answerValueSetUrl is not a reference, because we have already processed it earlier
284
285
  if (!initialValueSetUrl.startsWith('#')) {
285
- // Get valueSet promise to be resolved
286
+ // Get valueSet promise to be resolved if it is not an autocomplete item, or it hasn't been added before
287
+ // We exclude autocomplete items here because they usually contain large valueSets that cannot be expanded fully
286
288
  // Note: this entry uses valueSetUrlWithParams as the key
287
- if (!valueSetPromises[initialValueSetUrl]) {
289
+ if (!isSpecificItemControl(item, 'autocomplete') && !valueSetPromises[initialValueSetUrl]) {
288
290
  valueSetPromises[valueSetUrlWithParams] = {
289
291
  promise: getValueSetPromise(valueSetUrlWithParams, terminologyServerUrl)
290
292
  };
@@ -1,31 +0,0 @@
1
- /**
2
- * Represents a single step in the path to an item within a nested QuestionnaireResponse.
3
- * Each step is identified by its `linkId`, and optionally a `repeatIndex` if the item
4
- * occurs within a repeating group.
5
- */
6
- export interface ItemPathSegment {
7
- /** The `linkId` of the QuestionnaireResponseItem at this path segment. */
8
- linkId: string;
9
- /**
10
- * The index of the repeated item if this segment occurs within a repeating group.
11
- * Omitted if the item is not part of a repeating group.
12
- */
13
- repeatIndex?: number;
14
- }
15
- /**
16
- * Represents a full path from the root of a QuestionnaireResponse to a deeply nested item.
17
- * Each segment corresponds to one level of the item hierarchy.
18
- *
19
- * Example:
20
- * [
21
- * { linkId: 'sectionA' },
22
- * { linkId: 'groupB', repeatIndex: 1 },
23
- * { linkId: 'questionC' }
24
- * ]
25
- *
26
- * This path navigates through `sectionA`, into the second instance of `groupB`,
27
- * and finally to `questionC`.
28
- *
29
- * @author Sean Fong
30
- */
31
- export type ItemPath = ItemPathSegment[];
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=itemPath.interface.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"itemPath.interface.js","sourceRoot":"","sources":["../../src/interfaces/itemPath.interface.ts"],"names":[],"mappings":""}
@@ -1,57 +0,0 @@
1
- import type { ItemPath } from '../interfaces/itemPath.interface';
2
- /**
3
- * Creates an `ItemPath` containing a single segment for the given `linkId`.
4
- * This is useful when you want to construct a path to a specific item without referencing its ancestry,
5
- * such as when working with top-level items or when only the item's identity is relevant.
6
- *
7
- * @param linkId - The `linkId` of the item.
8
- * @param repeatIndex - (Optional) If the item is part of a repeating group, specify its index.
9
- * @returns An `ItemPath` containing one segment.
10
- *
11
- * @example
12
- * ```ts
13
- * const path = createSingleItemPath('question-1');
14
- * // Output: [{ linkId: 'question-1' }]
15
- *
16
- * const pathWithRepeat = createSingleItemPath('question-1', 2);
17
- * // Output: [{ linkId: 'question-1', repeatIndex: 2 }]
18
- * ```
19
- */
20
- export declare function createSingleItemPath(linkId: string, repeatIndex?: number): ItemPath;
21
- /**
22
- * Creates a new `ItemPath` by extending the given path with a new segment for the provided `linkId`.
23
- * This version does NOT include a `repeatIndex`. If repeat handling is needed,
24
- * use `appendRepeatIndexToLastSegment` after extending.
25
- *
26
- * @param currentPath - The existing item path.
27
- * @param linkId - The `linkId` to use in the new path segment.
28
- * @returns A new `ItemPath` with the added segment.
29
- */
30
- export declare function extendItemPath(currentPath: linkId: string): ItemPath;
31
- /**
32
- * Returns a new `ItemPath` with a `repeatIndex` applied to the last segment.
33
- * Useful for denoting which repetition of a group is being accessed.
34
- *
35
- * @param path - The item path to modify.
36
- * @param repeatIndex - The index to assign to the final segment.
37
- * @returns A new `ItemPath` with the last segment modified to include `repeatIndex`.
38
- *
39
- * @example
40
- * const basePath = [{ linkId: 'groupA' }, { linkId: 'groupB' }];
41
- * appendRepeatIndexToLastSegment(basePath, 2);
42
- * // → [{ linkId: 'groupA' }, { linkId: 'groupB', repeatIndex: 2 }]
43
- */
44
- export declare function appendRepeatIndexToLastSegment(path: repeatIndex: number): ItemPath;
45
- /**
46
- * Converts an `ItemPath` to a FHIRPath-compatible string.
47
- *
48
- * For example, the path:
49
- * [
50
- * { linkId: 'groupA' },
51
- * { linkId: 'repeatingGroup', repeatIndex: 1 },
52
- * { linkId: 'questionB' }
53
- * ]
54
- *
55
- * Returns: "item.where(linkId='groupA').item.where(linkId='repeatingGroup')[1].item.where(linkId='questionB')"
56
- */
57
- export declare function itemPathToFhirPathString(path: ItemPath): string;
@@ -1,75 +0,0 @@
1
- /**
2
- * Creates an `ItemPath` containing a single segment for the given `linkId`.
3
- * This is useful when you want to construct a path to a specific item without referencing its ancestry,
4
- * such as when working with top-level items or when only the item's identity is relevant.
5
- *
6
- * @param linkId - The `linkId` of the item.
7
- * @param repeatIndex - (Optional) If the item is part of a repeating group, specify its index.
8
- * @returns An `ItemPath` containing one segment.
9
- *
10
- * @example
11
- * ```ts
12
- * const path = createSingleItemPath('question-1');
13
- * // Output: [{ linkId: 'question-1' }]
14
- *
15
- * const pathWithRepeat = createSingleItemPath('question-1', 2);
16
- * // Output: [{ linkId: 'question-1', repeatIndex: 2 }]
17
- * ```
18
- */
19
- export function createSingleItemPath(linkId, repeatIndex) {
20
- return repeatIndex !== undefined ? [{ linkId, repeatIndex }] : [{ linkId }];
21
- }
22
- /**
23
- * Creates a new `ItemPath` by extending the given path with a new segment for the provided `linkId`.
24
- * This version does NOT include a `repeatIndex`. If repeat handling is needed,
25
- * use `appendRepeatIndexToLastSegment` after extending.
26
- *
27
- * @param currentPath - The existing item path.
28
- * @param linkId - The `linkId` to use in the new path segment.
29
- * @returns A new `ItemPath` with the added segment.
30
- */
31
- export function extendItemPath(currentPath, linkId) {
32
- return [...currentPath, { linkId }];
33
- }
34
- /**
35
- * Returns a new `ItemPath` with a `repeatIndex` applied to the last segment.
36
- * Useful for denoting which repetition of a group is being accessed.
37
- *
38
- * @param path - The item path to modify.
39
- * @param repeatIndex - The index to assign to the final segment.
40
- * @returns A new `ItemPath` with the last segment modified to include `repeatIndex`.
41
- *
42
- * @example
43
- * const basePath = [{ linkId: 'groupA' }, { linkId: 'groupB' }];
44
- * appendRepeatIndexToLastSegment(basePath, 2);
45
- * // → [{ linkId: 'groupA' }, { linkId: 'groupB', repeatIndex: 2 }]
46
- */
47
- export function appendRepeatIndexToLastSegment(path, repeatIndex) {
48
- if (path.length === 0)
49
- return [];
50
- const newPath = [...path];
51
- newPath[path.length - 1] = Object.assign(Object.assign({}, newPath[path.length - 1]), { repeatIndex });
52
- return newPath;
53
- }
54
- /**
55
- * Converts an `ItemPath` to a FHIRPath-compatible string.
56
- *
57
- * For example, the path:
58
- * [
59
- * { linkId: 'groupA' },
60
- * { linkId: 'repeatingGroup', repeatIndex: 1 },
61
- * { linkId: 'questionB' }
62
- * ]
63
- *
64
- * Returns: "item.where(linkId='groupA').item.where(linkId='repeatingGroup')[1].item.where(linkId='questionB')"
65
- */
66
- export function itemPathToFhirPathString(path) {
67
- return path
68
- .map((segment, index) => {
69
- const base = `where(linkId='${segment.linkId}')`;
70
- const repeat = segment.repeatIndex !== undefined ? `[${segment.repeatIndex}]` : '';
71
- return (index === 0 ? 'item.' : '') + base + repeat;
72
- })
73
- .join('.item.');
74
- }
75
- //# sourceMappingURL=itemPath.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"itemPath.js","sourceRoot":"","sources":["../../src/utils/itemPath.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAc,EAAE,WAAoB;IACvE,OAAO,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;AAC9E,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAAC,WAAqB,EAAE,MAAc;IAClE,OAAO,CAAC,GAAG,WAAW,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;AACtC,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,8BAA8B,CAAC,IAAc,EAAE,WAAmB;IAChF,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEjC,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;IAC1B,OAAO,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,mCAAQ,OAAO,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,KAAE,WAAW,GAAE,CAAC;IACxE,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,wBAAwB,CAAC,IAAc;IACrD,OAAO,IAAI;SACR,GAAG,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE;QACtB,MAAM,IAAI,GAAG,iBAAiB,OAAO,CAAC,MAAM,IAAI,CAAC;QACjD,MAAM,MAAM,GAAG,OAAO,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;QACnF,OAAO,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI,GAAG,MAAM,CAAC;IACtD,CAAC,CAAC;SACD,IAAI,CAAC,QAAQ,CAAC,CAAC;AACpB,CAAC"}