diff --git a/apps/smart-forms-app/src/features/standalone/components/Standalone.tsx b/apps/smart-forms-app/src/features/standalone/components/Standalone.tsx index 4307b6a87..29abd59cb 100644 --- a/apps/smart-forms-app/src/features/standalone/components/Standalone.tsx +++ b/apps/smart-forms-app/src/features/standalone/components/Standalone.tsx @@ -21,11 +21,11 @@ import type { RendererPropsActions, RendererPropsState } from '../interfaces/standalone.interface.ts'; -import { SmartFormsRenderer } from '@aehrc/smart-forms-renderer'; import { rendererPropsList } from '../utils/standaloneList.ts'; import StandaloneQuestionnairePicker from './StandaloneQuestionnairePicker.tsx'; import StandalonePropsPicker from './StandalonePropsPicker.tsx'; import StandaloneResourceViewer from './StandaloneResourceViewer.tsx'; +import { InitialiseFormWrapperForStorybook } from '@aehrc/smart-forms-renderer'; const rendererPropsReducer = (state: RendererPropsState, action: RendererPropsActions) => { switch (action.type) { @@ -86,7 +86,7 @@ function Standalone() { resourcesShown={resourcesShown} onShowResources={() => setResourcesShown(!resourcesShown)} /> - =v12.0.0" + } + }, "node_modules/@juggle/resize-observer": { "version": "3.4.0", "license": "Apache-2.0" @@ -13188,6 +13203,12 @@ "@types/node": "*" } }, + "node_modules/@types/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==", + "dev": true + }, "node_modules/@types/lodash": { "version": "4.17.0", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.0.tgz", @@ -13233,6 +13254,16 @@ "@types/lodash": "*" } }, + "node_modules/@types/markdown-it": { + "version": "14.1.1", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-14.1.1.tgz", + "integrity": "sha512-4NpsnpYl2Gt1ljyBGrKMxFYAYvpqbnnkgP/i/g+NLpjEUa3obn1XJCur9YbEXKDAkaXqsR1LbDnGEJ0MmKFxfg==", + "dev": true, + "dependencies": { + "@types/linkify-it": "^5", + "@types/mdurl": "^2" + } + }, "node_modules/@types/mdast": { "version": "3.0.12", "license": "MIT", @@ -13240,6 +13271,12 @@ "@types/unist": "^2" } }, + "node_modules/@types/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==", + "dev": true + }, "node_modules/@types/mdx": { "version": "2.0.13", "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", @@ -14656,6 +14693,27 @@ "node": ">=6" } }, + "node_modules/ansi-escape-sequences": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-escape-sequences/-/ansi-escape-sequences-4.1.0.tgz", + "integrity": "sha512-dzW9kHxH011uBsidTXd14JXgzye/YLb2LzeKZ4bsgl/Knwx8AtbSFkkGxagdNOoh0DlqHCmfiEjWKBaqjOanVw==", + "dev": true, + "dependencies": { + "array-back": "^3.0.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/ansi-escape-sequences/node_modules/array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/ansi-escapes": { "version": "4.3.2", "dev": true, @@ -14699,6 +14757,12 @@ "node": ">=8" } }, + "node_modules/ansi-sequence-parser": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz", + "integrity": "sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==", + "dev": true + }, "node_modules/ansi-styles": { "version": "4.3.0", "license": "MIT", @@ -14785,6 +14849,15 @@ "deep-equal": "^2.0.5" } }, + "node_modules/array-back": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz", + "integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==", + "dev": true, + "engines": { + "node": ">=12.17" + } + }, "node_modules/array-buffer-byte-length": { "version": "1.0.1", "dev": true, @@ -16535,6 +16608,29 @@ "node": ">=10" } }, + "node_modules/cache-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cache-point/-/cache-point-2.0.0.tgz", + "integrity": "sha512-4gkeHlFpSKgm3vm2gJN5sPqfmijYRFYCQ6tv5cLw0xVmT6r1z1vd4FNnpuOREco3cBs1G709sZ72LdgddKvL5w==", + "dev": true, + "dependencies": { + "array-back": "^4.0.1", + "fs-then-native": "^2.0.0", + "mkdirp2": "^1.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cache-point/node_modules/array-back": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", + "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/cacheable-lookup": { "version": "5.0.4", "dev": true, @@ -16649,6 +16745,18 @@ "dev": true, "license": "Apache-2.0" }, + "node_modules/catharsis": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/catharsis/-/catharsis-0.9.0.tgz", + "integrity": "sha512-prMTQVpcns/tzFgFVkVp6ak6RykZyWb3gu8ckUpd6YkTlacOd3DXGJjIpD4Q6zJirizvaiAjSSHlOsA+6sNh2A==", + "dev": true, + "dependencies": { + "lodash": "^4.17.15" + }, + "engines": { + "node": ">= 10" + } + }, "node_modules/ccount": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", @@ -17070,6 +17178,19 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/collect-all": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/collect-all/-/collect-all-1.0.4.tgz", + "integrity": "sha512-RKZhRwJtJEP5FWul+gkSMEnaK6H3AGPTTWOiRimCcs+rc/OmQE3Yhy1Q7A7KsdkG3ZXVdZq68Y6ONSdvkeEcKA==", + "dev": true, + "dependencies": { + "stream-connect": "^1.0.2", + "stream-via": "^1.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/collect-v8-coverage": { "version": "1.0.2", "dev": true, @@ -17145,6 +17266,94 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/command-line-args": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", + "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", + "dev": true, + "dependencies": { + "array-back": "^3.1.0", + "find-replace": "^3.0.0", + "lodash.camelcase": "^4.3.0", + "typical": "^4.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/command-line-args/node_modules/array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/command-line-args/node_modules/typical": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", + "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/command-line-tool": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/command-line-tool/-/command-line-tool-0.8.0.tgz", + "integrity": "sha512-Xw18HVx/QzQV3Sc5k1vy3kgtOeGmsKIqwtFFoyjI4bbcpSgnw2CWVULvtakyw4s6fhyAdI6soQQhXc2OzJy62g==", + "dev": true, + "dependencies": { + "ansi-escape-sequences": "^4.0.0", + "array-back": "^2.0.0", + "command-line-args": "^5.0.0", + "command-line-usage": "^4.1.0", + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/command-line-tool/node_modules/array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "dependencies": { + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/command-line-usage": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-4.1.0.tgz", + "integrity": "sha512-MxS8Ad995KpdAC0Jopo/ovGIroV/m0KHwzKfXxKag6FHOkGsH8/lv5yjgablcRxCJJC0oJeUMuO/gmaq+Wq46g==", + "dev": true, + "dependencies": { + "ansi-escape-sequences": "^4.0.0", + "array-back": "^2.0.0", + "table-layout": "^0.4.2", + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/command-line-usage/node_modules/array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "dependencies": { + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/commander": { "version": "6.2.1", "dev": true, @@ -17158,6 +17367,15 @@ "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==" }, + "node_modules/common-sequence": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/common-sequence/-/common-sequence-2.0.2.tgz", + "integrity": "sha512-jAg09gkdkrDO9EWTdXfv80WWH3yeZl5oT69fGfedBNS9pXUKYInVJ1bJ+/ht2+Moeei48TmSbQDYMc8EOx9G0g==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/common-tags": { "version": "1.8.2", "dev": true, @@ -17256,6 +17474,24 @@ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" }, + "node_modules/config-master": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/config-master/-/config-master-3.1.0.tgz", + "integrity": "sha512-n7LBL1zBzYdTpF1mx5DNcZnZn05CWIdsdvtPL4MosvqbBUK3Rq6VWEtGUuF3Y0s9/CIhMejezqlSkP6TnCJ/9g==", + "dev": true, + "dependencies": { + "walk-back": "^2.0.1" + } + }, + "node_modules/config-master/node_modules/walk-back": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-2.0.1.tgz", + "integrity": "sha512-Nb6GvBR8UWX1D+Le+xUq0+Q1kFmRBIWVrfLnQAOmcpEzA9oAxwJ9gIr36t9TWYfzvWRvuMtjHiVsJYEkXWaTAQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/configstore": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/configstore/-/configstore-6.0.0.tgz", @@ -18858,6 +19094,29 @@ "node": ">=8" } }, + "node_modules/dmd": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/dmd/-/dmd-6.2.0.tgz", + "integrity": "sha512-uXWxLF1H7TkUAuoHK59/h/ts5cKavm2LnhrIgJWisip4BVzPoXavlwyoprFFn2CzcahKYgvkfaebS6oxzgflkg==", + "dev": true, + "dependencies": { + "array-back": "^6.2.2", + "cache-point": "^2.0.0", + "common-sequence": "^2.0.2", + "file-set": "^4.0.2", + "handlebars": "^4.7.7", + "marked": "^4.2.3", + "object-get": "^2.1.1", + "reduce-flatten": "^3.0.1", + "reduce-unique": "^2.0.1", + "reduce-without": "^1.0.1", + "test-value": "^3.0.0", + "walk-back": "^5.1.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/dnd-core": { "version": "16.0.1", "license": "MIT", @@ -18889,6 +19148,15 @@ "node": ">=6.0.0" } }, + "node_modules/docusaurus-plugin-typedoc": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/docusaurus-plugin-typedoc/-/docusaurus-plugin-typedoc-1.0.1.tgz", + "integrity": "sha512-q3e/XHmnMNdP361/0SMBbCQyr7oUwbSs5QMhu1BkEUvM45oKG7i1qxcKKabOefFDVDW9cmbBISWxB8XZGJAVFg==", + "dev": true, + "peerDependencies": { + "typedoc-plugin-markdown": ">=4.0.0" + } + }, "node_modules/dom-accessibility-api": { "version": "0.5.16", "dev": true, @@ -20516,6 +20784,48 @@ "webpack": "^4.0.0 || ^5.0.0" } }, + "node_modules/file-set": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/file-set/-/file-set-4.0.2.tgz", + "integrity": "sha512-fuxEgzk4L8waGXaAkd8cMr73Pm0FxOVkn8hztzUW7BAHhOGH90viQNXbiOsnecCWmfInqU6YmAMwxRMdKETceQ==", + "dev": true, + "dependencies": { + "array-back": "^5.0.0", + "glob": "^7.1.6" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/file-set/node_modules/array-back": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-5.0.0.tgz", + "integrity": "sha512-kgVWwJReZWmVuWOQKEOohXKJX+nD02JAZ54D1RRWlv8L0NebauKAaFxACKzB74RTclt1+WNz5KHaLRDAPZbDEw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/file-set/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/file-system-cache": { "version": "2.3.0", "dev": true, @@ -20716,6 +21026,27 @@ "node": ">=8" } }, + "node_modules/find-replace": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", + "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", + "dev": true, + "dependencies": { + "array-back": "^3.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/find-replace/node_modules/array-back": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", + "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/find-root": { "version": "1.1.0", "license": "MIT" @@ -21102,6 +21433,15 @@ "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==" }, + "node_modules/fs-then-native": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fs-then-native/-/fs-then-native-2.0.0.tgz", + "integrity": "sha512-X712jAOaWXkemQCAmWeg5rOT2i+KOpWz1Z/txk/cW0qlOu2oQ9H61vc5w3X/iyuUEfq/OyaFJ78/cZAQD1/bgA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "license": "ISC" @@ -24695,6 +25035,15 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/js2xmlparser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/js2xmlparser/-/js2xmlparser-4.0.2.tgz", + "integrity": "sha512-6n4D8gLlLf1n5mNLQPRfViYzu9RATblzPEtm1SthMX1Pjao0r9YI9nw7ZIfRxQMERS87mcswrg+r/OYrPRX6jA==", + "dev": true, + "dependencies": { + "xmlcreate": "^2.0.4" + } + }, "node_modules/jsbn": { "version": "0.1.1", "dev": true, @@ -24775,6 +25124,113 @@ "signal-exit": "^3.0.2" } }, + "node_modules/jsdoc": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/jsdoc/-/jsdoc-4.0.3.tgz", + "integrity": "sha512-Nu7Sf35kXJ1MWDZIMAuATRQTg1iIPdzh7tqJ6jjvaU/GfDf+qi5UV8zJR3Mo+/pYFvm8mzay4+6O5EWigaQBQw==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.15", + "@jsdoc/salty": "^0.2.1", + "@types/markdown-it": "^14.1.1", + "bluebird": "^3.7.2", + "catharsis": "^0.9.0", + "escape-string-regexp": "^2.0.0", + "js2xmlparser": "^4.0.2", + "klaw": "^3.0.0", + "markdown-it": "^14.1.0", + "markdown-it-anchor": "^8.6.7", + "marked": "^4.0.10", + "mkdirp": "^1.0.4", + "requizzle": "^0.2.3", + "strip-json-comments": "^3.1.0", + "underscore": "~1.13.2" + }, + "bin": { + "jsdoc": "jsdoc.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/jsdoc-api": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/jsdoc-api/-/jsdoc-api-8.0.0.tgz", + "integrity": "sha512-Rnhor0suB1Ds1abjmFkFfKeD+kSMRN9oHMTMZoJVUrmtCGDwXty+sWMA9sa4xbe4UyxuPjhC7tavZ40mDKK6QQ==", + "dev": true, + "dependencies": { + "array-back": "^6.2.2", + "cache-point": "^2.0.0", + "collect-all": "^1.0.4", + "file-set": "^4.0.2", + "fs-then-native": "^2.0.0", + "jsdoc": "^4.0.0", + "object-to-spawn-args": "^2.0.1", + "temp-path": "^1.0.0", + "walk-back": "^5.1.0" + }, + "engines": { + "node": ">=12.17" + } + }, + "node_modules/jsdoc-parse": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsdoc-parse/-/jsdoc-parse-6.2.1.tgz", + "integrity": "sha512-9viGRUUtWOk/G4V0+nQ6rfLucz5plxh5I74WbNSNm9h9NWugCDVX4jbG8hZP9QqKGpdTPDE+qJXzaYNos3wqTA==", + "dev": true, + "dependencies": { + "array-back": "^6.2.2", + "lodash.omit": "^4.5.0", + "reduce-extract": "^1.0.0", + "sort-array": "^4.1.5", + "test-value": "^3.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/jsdoc-to-markdown": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/jsdoc-to-markdown/-/jsdoc-to-markdown-8.0.1.tgz", + "integrity": "sha512-qJfNJhkq2C26UYoOdj8L1yheTJlk1veCsxwRejRmj07XZKCn7oSkuPErx6+JoNi8afCaUKdIM5oUu0uF2/T8iw==", + "dev": true, + "dependencies": { + "array-back": "^6.2.2", + "command-line-tool": "^0.8.0", + "config-master": "^3.1.0", + "dmd": "^6.2.0", + "jsdoc-api": "^8.0.0", + "jsdoc-parse": "^6.2.1", + "walk-back": "^5.1.0" + }, + "bin": { + "jsdoc2md": "bin/cli.js" + }, + "engines": { + "node": ">=12.17" + } + }, + "node_modules/jsdoc/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/jsdoc/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/jsdom": { "version": "20.0.3", "dev": true, @@ -24921,6 +25377,12 @@ "node": ">=6" } }, + "node_modules/jsonc-parser": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", + "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", + "dev": true + }, "node_modules/jsonfile": { "version": "2.4.0", "license": "MIT", @@ -25108,6 +25570,15 @@ "node": ">=0.10.0" } }, + "node_modules/klaw": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-3.0.0.tgz", + "integrity": "sha512-0Fo5oir+O9jnXu5EefYbVK+mHMBeEVEy2cmctR1O1NECcCkPRreJKrS6Qt/j3KC2C148Dfo9i3pCmCMsdqGr0g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.9" + } + }, "node_modules/kleur": { "version": "3.0.3", "license": "MIT", @@ -25209,6 +25680,15 @@ "version": "1.2.4", "license": "MIT" }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "dev": true, + "dependencies": { + "uc.micro": "^2.0.0" + } + }, "node_modules/listr2": { "version": "3.14.0", "dev": true, @@ -25275,6 +25755,12 @@ "version": "4.17.21", "license": "MIT" }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "dev": true + }, "node_modules/lodash.clamp": { "version": "4.0.3", "license": "MIT" @@ -25318,11 +25804,23 @@ "devOptional": true, "license": "MIT" }, + "node_modules/lodash.omit": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.omit/-/lodash.omit-4.5.0.tgz", + "integrity": "sha512-XeqSp49hNGmlkj2EJlfrQFIzQ6lXdNro9sddtQzcJY8QaoC2GO0DT7xaIokHeyM+mIT0mPMlPvkYzg2xCuHdZg==", + "dev": true + }, "node_modules/lodash.once": { "version": "4.1.1", "dev": true, "license": "MIT" }, + "node_modules/lodash.padend": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", + "integrity": "sha512-sOQs2aqGpbl27tmCS1QNZA09Uqp01ZzWfDUoD+xzTii0E7dSQfRKcRetFwa+uXaxaqL+TKm7CgD2JdKP7aZBSw==", + "dev": true + }, "node_modules/lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", @@ -25440,6 +25938,12 @@ "yallist": "^3.0.2" } }, + "node_modules/lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true + }, "node_modules/lz-string": { "version": "1.5.0", "dev": true, @@ -25502,6 +26006,39 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/markdown-it-anchor": { + "version": "8.6.7", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-8.6.7.tgz", + "integrity": "sha512-FlCHFwNnutLgVTflOYHPW2pPcl2AACqVzExlkGQNsi4CJgqOHN7YTgDd4LuhgN1BFO3TS0vLAruV1Td6dwWPJA==", + "dev": true, + "peerDependencies": { + "@types/markdown-it": "*", + "markdown-it": "*" + } + }, + "node_modules/markdown-it/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, "node_modules/markdown-table": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.3.tgz", @@ -25522,6 +26059,18 @@ "react": ">= 0.14.0" } }, + "node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "dev": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, "node_modules/material-ui-popup-state": { "version": "5.0.10", "license": "MIT", @@ -31551,6 +32100,12 @@ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "dev": true + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -34123,6 +34678,12 @@ "dev": true, "license": "MIT" }, + "node_modules/mkdirp2": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/mkdirp2/-/mkdirp2-1.0.5.tgz", + "integrity": "sha512-xOE9xbICroUDmG1ye2h4bZ8WBie9EGmACaco8K8cx6RlkJJrxGIqjGqztAI+NMhexXBcdGbSEzI6N3EJPevxZw==", + "dev": true + }, "node_modules/moment": { "version": "2.29.4", "license": "MIT", @@ -34391,6 +34952,12 @@ "node": ">=0.10.0" } }, + "node_modules/object-get": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object-get/-/object-get-2.1.1.tgz", + "integrity": "sha512-7n4IpLMzGGcLEMiQKsNR7vCe+N5E9LORFrtNUVy4sO3dj9a3HedZCxEL2T7QuLhcHN1NBuBsMOKaOsAYI9IIvg==", + "dev": true + }, "node_modules/object-inspect": { "version": "1.13.1", "license": "MIT", @@ -34420,6 +34987,15 @@ "node": ">= 0.4" } }, + "node_modules/object-to-spawn-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object-to-spawn-args/-/object-to-spawn-args-2.0.1.tgz", + "integrity": "sha512-6FuKFQ39cOID+BMZ3QaphcC8Y4cw6LXBLyIgPU+OhIYwviJamPAn+4mITapnSBQrejB+NNp+FMskhD8Cq+Ys3w==", + "dev": true, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/object.assign": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", @@ -36112,6 +36688,15 @@ "node": ">=6" } }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/pupa": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/pupa/-/pupa-3.1.0.tgz", @@ -37259,6 +37844,98 @@ "node": ">=8" } }, + "node_modules/reduce-extract": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/reduce-extract/-/reduce-extract-1.0.0.tgz", + "integrity": "sha512-QF8vjWx3wnRSL5uFMyCjDeDc5EBMiryoT9tz94VvgjKfzecHAVnqmXAwQDcr7X4JmLc2cjkjFGCVzhMqDjgR9g==", + "dev": true, + "dependencies": { + "test-value": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reduce-extract/node_modules/array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha512-1WxbZvrmyhkNoeYcizokbmh5oiOCIfyvGtcqbK3Ls1v1fKcquzxnQSceOx6tzq7jmai2kFLWIpGND2cLhH6TPw==", + "dev": true, + "dependencies": { + "typical": "^2.6.0" + }, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/reduce-extract/node_modules/test-value": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/test-value/-/test-value-1.1.0.tgz", + "integrity": "sha512-wrsbRo7qP+2Je8x8DsK8ovCGyxe3sYfQwOraIY/09A2gFXU9DYKiTF14W4ki/01AEh56kMzAmlj9CaHGDDUBJA==", + "dev": true, + "dependencies": { + "array-back": "^1.0.2", + "typical": "^2.4.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reduce-flatten": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-3.0.1.tgz", + "integrity": "sha512-bYo+97BmUUOzg09XwfkwALt4PQH1M5L0wzKerBt6WLm3Fhdd43mMS89HiT1B9pJIqko/6lWx3OnV4J9f2Kqp5Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/reduce-unique": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/reduce-unique/-/reduce-unique-2.0.1.tgz", + "integrity": "sha512-x4jH/8L1eyZGR785WY+ePtyMNhycl1N2XOLxhCbzZFaqF4AXjLzqSxa2UHgJ2ZVR/HHyPOvl1L7xRnW8ye5MdA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/reduce-without": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/reduce-without/-/reduce-without-1.0.1.tgz", + "integrity": "sha512-zQv5y/cf85sxvdrKPlfcRzlDn/OqKFThNimYmsS3flmkioKvkUGn2Qg9cJVoQiEvdxFGLE0MQER/9fZ9sUqdxg==", + "dev": true, + "dependencies": { + "test-value": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/reduce-without/node_modules/array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha512-1WxbZvrmyhkNoeYcizokbmh5oiOCIfyvGtcqbK3Ls1v1fKcquzxnQSceOx6tzq7jmai2kFLWIpGND2cLhH6TPw==", + "dev": true, + "dependencies": { + "typical": "^2.6.0" + }, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/reduce-without/node_modules/test-value": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/test-value/-/test-value-2.1.0.tgz", + "integrity": "sha512-+1epbAxtKeXttkGFMTX9H42oqzOTufR1ceCF+GYA5aOmvaPq9wd4PUS8329fn2RRLGNeUkgRLnVpycjx8DsO2w==", + "dev": true, + "dependencies": { + "array-back": "^1.0.3", + "typical": "^2.6.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/redux": { "version": "4.2.1", "license": "MIT", @@ -38831,6 +39508,15 @@ "version": "1.0.0", "license": "MIT" }, + "node_modules/requizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/requizzle/-/requizzle-0.2.4.tgz", + "integrity": "sha512-JRrFk1D4OQ4SqovXOgdav+K8EAhSB/LJZqCz8tbX0KObcdeM15Ss59ozWMBWmmINMagCwmqn4ZNryUGpBsl6Jw==", + "dev": true, + "dependencies": { + "lodash": "^4.17.21" + } + }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", @@ -39673,6 +40359,18 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/shiki": { + "version": "0.14.7", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.7.tgz", + "integrity": "sha512-dNPAPrxSc87ua2sKJ3H5dQ/6ZaY8RNnaAqK+t0eG7p0Soi2ydiqbGOTaZCqaYvA/uZYfS1LJnemt3Q+mSfcPCg==", + "dev": true, + "dependencies": { + "ansi-sequence-parser": "^1.1.0", + "jsonc-parser": "^3.2.0", + "vscode-oniguruma": "^1.7.0", + "vscode-textmate": "^8.0.0" + } + }, "node_modules/side-channel": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", @@ -39871,6 +40569,37 @@ "uuid": "dist/bin/uuid" } }, + "node_modules/sort-array": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/sort-array/-/sort-array-4.1.5.tgz", + "integrity": "sha512-Ya4peoS1fgFN42RN1REk2FgdNOeLIEMKFGJvs7VTP3OklF8+kl2SkpVliZ4tk/PurWsrWRsdNdU+tgyOBkB9sA==", + "dev": true, + "dependencies": { + "array-back": "^5.0.0", + "typical": "^6.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sort-array/node_modules/array-back": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-5.0.0.tgz", + "integrity": "sha512-kgVWwJReZWmVuWOQKEOohXKJX+nD02JAZ54D1RRWlv8L0NebauKAaFxACKzB74RTclt1+WNz5KHaLRDAPZbDEw==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/sort-array/node_modules/typical": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/typical/-/typical-6.0.1.tgz", + "integrity": "sha512-+g3NEp7fJLe9DPa1TArHm9QAA7YciZmWnfAqEaFrBihQ7epOv9i99rjtgb6Iz0wh3WuQDjsCTDfgRoGnmHN81A==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/sort-css-media-queries": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/sort-css-media-queries/-/sort-css-media-queries-2.2.0.tgz", @@ -40135,6 +40864,30 @@ "emitter-component": "^1.1.1" } }, + "node_modules/stream-connect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-connect/-/stream-connect-1.0.2.tgz", + "integrity": "sha512-68Kl+79cE0RGKemKkhxTSg8+6AGrqBt+cbZAXevg2iJ6Y3zX4JhA/sZeGzLpxW9cXhmqAcE7KnJCisUmIUfnFQ==", + "dev": true, + "dependencies": { + "array-back": "^1.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stream-connect/node_modules/array-back": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-1.0.4.tgz", + "integrity": "sha512-1WxbZvrmyhkNoeYcizokbmh5oiOCIfyvGtcqbK3Ls1v1fKcquzxnQSceOx6tzq7jmai2kFLWIpGND2cLhH6TPw==", + "dev": true, + "dependencies": { + "typical": "^2.6.0" + }, + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/stream-shift": { "version": "1.0.1", "dev": true, @@ -40144,6 +40897,15 @@ "version": "0.1.2", "license": "BSD-3-Clause" }, + "node_modules/stream-via": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/stream-via/-/stream-via-1.0.4.tgz", + "integrity": "sha512-DBp0lSvX5G9KGRDTkR/R+a29H+Wk2xItOF+MpZLLNDWbEV9tGPnqLPxHEYjmiz8xGtJHRIqmI+hCjmNzqoA4nQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/string_decoder": { "version": "1.1.1", "license": "MIT", @@ -40585,6 +41347,34 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/table-layout": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-0.4.5.tgz", + "integrity": "sha512-zTvf0mcggrGeTe/2jJ6ECkJHAQPIYEwDoqsiqBjI24mvRmQbInK5jq33fyypaCBxX08hMkfmdOqj6haT33EqWw==", + "dev": true, + "dependencies": { + "array-back": "^2.0.0", + "deep-extend": "~0.6.0", + "lodash.padend": "^4.6.1", + "typical": "^2.6.1", + "wordwrapjs": "^3.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/table-layout/node_modules/array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "dependencies": { + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/tapable": { "version": "2.2.1", "license": "MIT", @@ -40703,6 +41493,12 @@ "node": ">=8" } }, + "node_modules/temp-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/temp-path/-/temp-path-1.0.0.tgz", + "integrity": "sha512-TvmyH7kC6ZVTYkqCODjJIbgvu0FKiwQpZ4D1aknE7xpcDf/qEOB8KZEK5ef2pfbVoiBhNWs3yx4y+ESMtNYmlg==", + "dev": true + }, "node_modules/temp/node_modules/glob": { "version": "7.2.3", "dev": true, @@ -40898,6 +41694,31 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/test-value": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/test-value/-/test-value-3.0.0.tgz", + "integrity": "sha512-sVACdAWcZkSU9x7AOmJo5TqE+GyNJknHaHsMrR6ZnhjVlVN9Yx6FjHrsKZ3BjIpPCT68zYesPWkakrNupwfOTQ==", + "dev": true, + "dependencies": { + "array-back": "^2.0.0", + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/test-value/node_modules/array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "dev": true, + "dependencies": { + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/text-table": { "version": "0.2.0", "license": "MIT" @@ -41461,6 +42282,60 @@ "is-typedarray": "^1.0.0" } }, + "node_modules/typedoc": { + "version": "0.25.13", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.13.tgz", + "integrity": "sha512-pQqiwiJ+Z4pigfOnnysObszLiU3mVLWAExSPf+Mu06G/qsc3wzbuM56SZQvONhHLncLUhYzOVkjFFpFfL5AzhQ==", + "dev": true, + "dependencies": { + "lunr": "^2.3.9", + "marked": "^4.3.0", + "minimatch": "^9.0.3", + "shiki": "^0.14.7" + }, + "bin": { + "typedoc": "bin/typedoc" + }, + "engines": { + "node": ">= 16" + }, + "peerDependencies": { + "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x" + } + }, + "node_modules/typedoc-plugin-markdown": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.0.2.tgz", + "integrity": "sha512-4MV3M+0lsmIaXuDBzeqLYemZqwTQDWQow+o8zdT9hC7KFu06GaFo2uUEbkjE6pgZA9hnkOTtzRVd0R9YJWcH8A==", + "dev": true, + "peerDependencies": { + "typedoc": "0.25.x" + } + }, + "node_modules/typedoc/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/typedoc/node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/typescript": { "version": "5.2.2", "license": "Apache-2.0", @@ -41472,6 +42347,12 @@ "node": ">=14.17" } }, + "node_modules/typical": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", + "integrity": "sha512-ofhi8kjIje6npGozTip9Fr8iecmYfEbS06i0JnIg+rh51KakryWF4+jX8lLKZVhy6N+ID45WYSFCxPOdTWCzNg==", + "dev": true + }, "node_modules/ua-parser-js": { "version": "1.0.37", "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.37.tgz", @@ -41494,6 +42375,12 @@ "node": "*" } }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "dev": true + }, "node_modules/uglify-js": { "version": "3.17.4", "dev": true, @@ -41520,6 +42407,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/underscore": { + "version": "1.13.6", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.6.tgz", + "integrity": "sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==", + "dev": true + }, "node_modules/undici-types": { "version": "5.26.5", "license": "MIT" @@ -42472,6 +43365,18 @@ "fsevents": "~2.3.2" } }, + "node_modules/vscode-oniguruma": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", + "dev": true + }, + "node_modules/vscode-textmate": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", + "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", + "dev": true + }, "node_modules/w3c-xmlserializer": { "version": "4.0.0", "dev": true, @@ -42483,6 +43388,15 @@ "node": ">=14" } }, + "node_modules/walk-back": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/walk-back/-/walk-back-5.1.0.tgz", + "integrity": "sha512-Uhxps5yZcVNbLEAnb+xaEEMdgTXl9qAQDzKYejG2AZ7qPwRQ81lozY9ECDbjLPNWm7YsO1IK5rsP1KoQzXAcGA==", + "dev": true, + "engines": { + "node": ">=12.17" + } + }, "node_modules/walker": { "version": "1.0.8", "dev": true, @@ -43132,6 +44046,28 @@ "dev": true, "license": "MIT" }, + "node_modules/wordwrapjs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-3.0.0.tgz", + "integrity": "sha512-mO8XtqyPvykVCsrwj5MlOVWvSnCdT+C+QVbm6blradR7JExAhbkZ7hZ9A+9NUtwzSqrlUo9a67ws0EiILrvRpw==", + "dev": true, + "dependencies": { + "reduce-flatten": "^1.0.1", + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/wordwrapjs/node_modules/reduce-flatten": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-1.0.1.tgz", + "integrity": "sha512-j5WfFJfc9CoXv/WbwVLHq74i/hdTUpy+iNC534LxczMRP67vJeK3V9JOdnL0N1cIRbn9mYhE2yVjvvKXDxvNXQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/wrap-ansi": { "version": "7.0.0", "dev": true, @@ -43235,6 +44171,12 @@ "dev": true, "license": "MIT" }, + "node_modules/xmlcreate": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/xmlcreate/-/xmlcreate-2.0.4.tgz", + "integrity": "sha512-nquOebG4sngPmGPICTS5EnxqhKbCmz5Ox5hsszI2T6U5qdrJizBc+0ilYSEjTSzU0yZcmvppztXe/5Al5fUwdg==", + "dev": true + }, "node_modules/xmldoc": { "version": "0.4.0", "license": "MIT", @@ -43475,11 +44417,15 @@ "@types/react-beautiful-dnd": "^13.1.7", "@types/react-dom": ">=18.2.22", "chokidar": "^3.5.3", + "docusaurus-plugin-typedoc": "^1.0.1", "jest": "^29.7.0", "jest-environment-jsdom": "^29.7.0", + "jsdoc-to-markdown": "^8.0.1", "storybook": "^8.0.10", "ts-jest": "^29.1.1", "tslib": "^2.6.2", + "typedoc": "^0.25.13", + "typedoc-plugin-markdown": "^4.0.2", "typescript": "^5.2.2" }, "peerDependencies": { diff --git a/packages/smart-forms-renderer/README.md b/packages/smart-forms-renderer/README.md index 373553fe9..41e0bb5c2 100644 --- a/packages/smart-forms-renderer/README.md +++ b/packages/smart-forms-renderer/README.md @@ -34,12 +34,12 @@ Note: The SmartFormsRenderer component trades customisability for simplicity. If ### SmartFormsRenderer Props -| Name | Type | Description | Required? | -|-----------------------|-------------------------------|--------------------------------------------------------------------------------------------------------------|-----------| -| questionnaire | FHIR R4.Questionnaire | Questionnaire to be rendered | Required | -| questionnaireResponse | FHIR R4.QuestionnaireResponse | Pre-populated QuestionnaireResponse to be rendered | Optional | -| additionalVariables | Record | Key-value pair of [SDC variables](http://hl7.org/fhir/R4/extension-variable.html) | Optional | -| terminologyServerUrl | string | Terminology server url to fetch terminology | Optional | +| Name | Type | Description | Required? | +|-----------------------|-------------------------------|---------------------------------------------------------------------------------------------------------------------|-----------| +| questionnaire | FHIR R4.Questionnaire | Questionnaire to be rendered | Required | +| questionnaireResponse | FHIR R4.QuestionnaireResponse | Pre-populated QuestionnaireResponse to be rendered | Optional | +| additionalVariables | `Record` | Key-value pair of [SDC variables](http://hl7.org/fhir/R4/extension-variable.html) `Record` | Optional | +| terminologyServerUrl | string | Terminology server url to fetch terminology | Optional | The below props are not supported at the moment, but will be in the future. diff --git a/packages/smart-forms-renderer/src/components/Renderer/SmartFormsRenderer.tsx b/packages/smart-forms-renderer/src/components/Renderer/SmartFormsRenderer.tsx index 3d83f90f6..cb4db6b76 100644 --- a/packages/smart-forms-renderer/src/components/Renderer/SmartFormsRenderer.tsx +++ b/packages/smart-forms-renderer/src/components/Renderer/SmartFormsRenderer.tsx @@ -33,7 +33,7 @@ import type Client from 'fhirclient/lib/Client'; * * @property questionnaire - Input FHIR R4 Questionnaire to be rendered * @property questionnaireResponse - Pre-populated QuestionnaireResponse to be rendered (optional) - * @property additionalVariables - Additional key-value pair of SDC variables for testing (optional) + * @property additionalVariables - Additional key-value pair of SDC variables `Record` for testing (optional) * @property terminologyServerUrl - Terminology server url to fetch terminology. If not provided, the default terminology server will be used. (optional) * @property fhirClient - FHIRClient object to perform further FHIR calls. At the moment it's only used in answerExpressions (optional) * @property readOnly - Applies read-only mode to all items in the form @@ -53,7 +53,8 @@ export interface SmartFormsRendererProps { /** * A self-initialising wrapper around the BaseRenderer rendering engine. - * // FIXME add github link + * Will be deprecated in version 1.0.0. For alternative usage, see: + * - https://github.com/aehrc/smart-forms/blob/main/packages/smart-forms-renderer/src/stories/InitialiseFormWrapperForStorybook.tsx#L40-L51 * * @see {SmartFormsRendererProps} for props. * diff --git a/packages/smart-forms-renderer/src/hooks/useBuildForm.ts b/packages/smart-forms-renderer/src/hooks/useBuildForm.ts index fb9270f72..0ef7ce686 100644 --- a/packages/smart-forms-renderer/src/hooks/useBuildForm.ts +++ b/packages/smart-forms-renderer/src/hooks/useBuildForm.ts @@ -27,7 +27,7 @@ import type { Questionnaire, QuestionnaireResponse } from 'fhir/r4'; * @param questionnaireResponse - Pre-populated/draft/loaded QuestionnaireResponse to be rendered (optional) * @param readOnly - Applies read-only mode to all items in the form view * @param terminologyServerUrl - Terminology server url to fetch terminology. If not provided, the default terminology server will be used. (optional) - * @param additionalVariables - Additional key-value pair of SDC variables for testing (optional) + * @param additionalVariables - Additional key-value pair of SDC variables `Record` for testing (optional) * * @author Sean Fong */ diff --git a/packages/smart-forms-renderer/src/hooks/useInitialiseForm.ts b/packages/smart-forms-renderer/src/hooks/useInitialiseForm.ts index 23e4ca927..5833ec73a 100644 --- a/packages/smart-forms-renderer/src/hooks/useInitialiseForm.ts +++ b/packages/smart-forms-renderer/src/hooks/useInitialiseForm.ts @@ -31,7 +31,7 @@ import { initialiseFhirClient } from '../utils/manageForm'; * @param questionnaireResponse - Pre-populated/draft/loaded QuestionnaireResponse to be rendered (optional) * @param readOnly - Applies read-only mode to all items in the form view * @param terminologyServerUrl - Terminology server url to fetch terminology. If not provided, the default terminology server will be used. (optional) - * @param additionalVariables - Additional key-value pair of SDC variables for testing (optional) + * @param additionalVariables - Additional key-value pair of SDC variables `Record` for testing (optional) * @param fhirClient - FHIRClient object to perform further FHIR calls. At the moment it's only used in answerExpressions (optional) * * @see {buildForm} for more information. diff --git a/packages/smart-forms-renderer/src/index.ts b/packages/smart-forms-renderer/src/index.ts index edf37bef6..6f84c69be 100644 --- a/packages/smart-forms-renderer/src/index.ts +++ b/packages/smart-forms-renderer/src/index.ts @@ -51,3 +51,9 @@ export { // theme provider exports export { RendererThemeProvider } from './theme'; + +export { + InitialiseFormWrapperForStorybook, + BuildFormButtonTesterWrapperForStorybook, + PrePopWrapperForStorybook +} from './stories/StorybookWrappers'; diff --git a/packages/smart-forms-renderer/src/interfaces/enableWhen.interface.ts b/packages/smart-forms-renderer/src/interfaces/enableWhen.interface.ts index 6e5710df7..d044eb145 100644 --- a/packages/smart-forms-renderer/src/interfaces/enableWhen.interface.ts +++ b/packages/smart-forms-renderer/src/interfaces/enableWhen.interface.ts @@ -24,8 +24,8 @@ import type { /** * EnableWhenExpressions interface * - * @property singleExpressions - Key-value pair of non-repeat group enableWhen expressions - * @property repeatExpressions - Key-value pair of repeat group enableWhen expressions + * @property singleExpressions - Key-value pair of non-repeat group enableWhen expressions `Record` + * @property repeatExpressions - Key-value pair of repeat group enableWhen expressions `Record` */ export interface EnableWhenExpressions { singleExpressions: Record; @@ -46,8 +46,8 @@ export interface EnableWhenRepeatExpression { /** * EnableWhenItems interface * - * @property singleItems - Key-value pair of non-repeat group enableWhen items - * @property repeatItems - Key-value pair of repeat group enableWhen items + * @property singleItems - Key-value pair of non-repeat group enableWhen items `Record` + * @property repeatItems - Key-value pair of repeat group enableWhen items `Record` */ export interface EnableWhenItems { singleItems: Record; diff --git a/packages/smart-forms-renderer/src/interfaces/tab.interface.ts b/packages/smart-forms-renderer/src/interfaces/tab.interface.ts index aabdcc090..111466cf8 100644 --- a/packages/smart-forms-renderer/src/interfaces/tab.interface.ts +++ b/packages/smart-forms-renderer/src/interfaces/tab.interface.ts @@ -25,6 +25,6 @@ export type Tab = { tabIndex: number; isComplete: boolean; isHidden: boolean }; /** - * Key-value pair of tabs + * Key-value pair of tabs `Record` */ export type Tabs = Record; diff --git a/packages/smart-forms-renderer/src/interfaces/variables.interface.ts b/packages/smart-forms-renderer/src/interfaces/variables.interface.ts index 6ba33e60d..b46c19d6d 100644 --- a/packages/smart-forms-renderer/src/interfaces/variables.interface.ts +++ b/packages/smart-forms-renderer/src/interfaces/variables.interface.ts @@ -20,8 +20,8 @@ import type { Expression, FhirResource } from 'fhir/r4'; /** * Variables interface * - * @property fhirPathVariables - Key-value pair of FHIRPath variable expressions in a Questionnaire item - * @property xFhirQueryVariables - Key-value pair of x-fhir-query variables + * @property fhirPathVariables - Key-value pair of FHIRPath variable expressions in a Questionnaire item `Record` + * @property xFhirQueryVariables - Key-value pair of x-fhir-query variables `Record` */ export interface Variables { fhirPathVariables: Record; diff --git a/packages/smart-forms-renderer/src/stores/questionnaireResponseStore.ts b/packages/smart-forms-renderer/src/stores/questionnaireResponseStore.ts index ede316c1a..7f4e2308e 100644 --- a/packages/smart-forms-renderer/src/stores/questionnaireResponseStore.ts +++ b/packages/smart-forms-renderer/src/stores/questionnaireResponseStore.ts @@ -38,9 +38,9 @@ import { createQuestionnaireResponseItemMap } from '../utils/questionnaireRespon * * @property sourceResponse - The original response created when the form is first initialised i.e. empty, pre-populated, opened saved draft * @property updatableResponse - The current state of the response that is being updated via form fields - * @property updatableResponseItems - Key-value pair of updatableResponse items + * @property updatableResponseItems - Key-value pair of updatableResponse items `Record` * @property formChangesHistory - Array of form changes history in the form of deep-diff objects - * @property invalidItems - Key-value pair of invalid items based on defined value constraints in the questionnaire + * @property invalidItems - Key-value pair of invalid items based on defined value constraints in the questionnaire `Record` * @property responseIsValid - Whether there are any invalid items in the response * @method validateQuestionnaire - Used to validate the questionnaire response based on the questionnaire * @method buildSourceResponse - Used to build the source response when the form is first initialised @@ -90,16 +90,9 @@ export const questionnaireResponseStore = createStore { - const enableWhenIsActivated = questionnaireStore.getState().enableWhenIsActivated; - const enableWhenItems = questionnaireStore.getState().enableWhenItems; - const enableWhenExpressions = questionnaireStore.getState().enableWhenExpressions; - const updatedInvalidItems = validateQuestionnaire({ questionnaire, - questionnaireResponse: updatedResponse, - enableWhenIsActivated, - enableWhenItems, - enableWhenExpressions + questionnaireResponse: updatedResponse }); set(() => ({ @@ -108,47 +101,89 @@ export const questionnaireResponseStore = createStore { + const sourceQuestionnaire = questionnaireStore.getState().sourceQuestionnaire; + const initialInvalidItems = validateQuestionnaire({ + questionnaire: sourceQuestionnaire, + questionnaireResponse: questionnaireResponse + }); + set(() => ({ sourceResponse: questionnaireResponse, updatableResponse: questionnaireResponse, - updatableResponseItems: createQuestionnaireResponseItemMap(questionnaireResponse) + updatableResponseItems: createQuestionnaireResponseItemMap(questionnaireResponse), + invalidItems: initialInvalidItems, + responseIsValid: Object.keys(initialInvalidItems).length === 0 })); }, setUpdatableResponseAsPopulated: (populatedResponse: QuestionnaireResponse) => { + const sourceQuestionnaire = questionnaireStore.getState().sourceQuestionnaire; const formChanges = diff(get().updatableResponse, populatedResponse) ?? null; + const updatedInvalidItems = validateQuestionnaire({ + questionnaire: sourceQuestionnaire, + questionnaireResponse: populatedResponse + }); set(() => ({ updatableResponse: populatedResponse, updatableResponseItems: createQuestionnaireResponseItemMap(populatedResponse), - formChangesHistory: [...get().formChangesHistory, formChanges] + formChangesHistory: [...get().formChangesHistory, formChanges], + invalidItems: updatedInvalidItems, + responseIsValid: Object.keys(updatedInvalidItems).length === 0 })); }, updateResponse: (updatedResponse: QuestionnaireResponse) => { + const sourceQuestionnaire = questionnaireStore.getState().sourceQuestionnaire; const formChanges = diff(get().updatableResponse, updatedResponse) ?? null; + const updatedInvalidItems = validateQuestionnaire({ + questionnaire: sourceQuestionnaire, + questionnaireResponse: updatedResponse + }); set(() => ({ updatableResponse: updatedResponse, updatableResponseItems: createQuestionnaireResponseItemMap(updatedResponse), - formChangesHistory: [...get().formChangesHistory, formChanges] + formChangesHistory: [...get().formChangesHistory, formChanges], + invalidItems: updatedInvalidItems, + responseIsValid: Object.keys(updatedInvalidItems).length === 0 })); }, - setUpdatableResponseAsSaved: (savedResponse: QuestionnaireResponse) => + setUpdatableResponseAsSaved: (savedResponse: QuestionnaireResponse) => { + const sourceQuestionnaire = questionnaireStore.getState().sourceQuestionnaire; + const updatedInvalidItems = validateQuestionnaire({ + questionnaire: sourceQuestionnaire, + questionnaireResponse: savedResponse + }); + set(() => ({ sourceResponse: savedResponse, updatableResponse: savedResponse, updatableResponseItems: createQuestionnaireResponseItemMap(savedResponse), - formChangesHistory: [] - })), - setUpdatableResponseAsEmpty: (clearedResponse: QuestionnaireResponse) => + formChangesHistory: [], + invalidItems: updatedInvalidItems, + responseIsValid: Object.keys(updatedInvalidItems).length === 0 + })); + }, + setUpdatableResponseAsEmpty: (clearedResponse: QuestionnaireResponse) => { + const sourceQuestionnaire = questionnaireStore.getState().sourceQuestionnaire; + const updatedInvalidItems = validateQuestionnaire({ + questionnaire: sourceQuestionnaire, + questionnaireResponse: clearedResponse + }); + set(() => ({ updatableResponse: clearedResponse, updatableResponseItems: createQuestionnaireResponseItemMap(clearedResponse), - formChangesHistory: [] - })), + formChangesHistory: [], + invalidItems: updatedInvalidItems, + responseIsValid: Object.keys(updatedInvalidItems).length === 0 + })); + }, destroySourceResponse: () => set(() => ({ sourceResponse: cloneDeep(emptyResponse), updatableResponse: cloneDeep(emptyResponse), updatableResponseItems: createQuestionnaireResponseItemMap(cloneDeep(emptyResponse)), - formChangesHistory: [] + formChangesHistory: [], + invalidItems: {}, + responseIsValid: true })) }) ); diff --git a/packages/smart-forms-renderer/src/stores/questionnaireStore.ts b/packages/smart-forms-renderer/src/stores/questionnaireStore.ts index 4bdb754f3..7e4cb51ea 100644 --- a/packages/smart-forms-renderer/src/stores/questionnaireStore.ts +++ b/packages/smart-forms-renderer/src/stores/questionnaireStore.ts @@ -53,22 +53,22 @@ import { createQuestionnaireResponseItemMap } from '../utils/questionnaireRespon * Methods are usually used internally, using them from an external source is not recommended. * * @property sourceQuestionnaire - FHIR R4 Questionnaire to render - * @property itemTypes - Key-value pair of item types - * @property tabs - Key-value pair of tabs + * @property itemTypes - Key-value pair of item types `Record` + * @property tabs - Key-value pair of tabs `Record` * @property currentTabIndex - Index of the current tab * @property variables - Questionnaire variables object containing FHIRPath and x-fhir-query variables - * @property launchContexts - Key-value pair of launch contexts + * @property launchContexts - Key-value pair of launch contexts `Record` * @property enableWhenItems - EnableWhenItems object containing enableWhen items and their linked questions - * @property enableWhenLinkedQuestions - Key-value pair of linked questions to enableWhen items + * @property enableWhenLinkedQuestions - Key-value pair of linked questions to enableWhen items `Record` * @property enableWhenIsActivated - Flag to turn enableWhen checks on/off * @property enableWhenExpressions - EnableWhenExpressions object containing enableWhen expressions - * @property calculatedExpressions - Key-value pair of calculated expressions - * @property answerExpressions - Key-value pair of answer expressions - * @property processedValueSetCodings - Key-value pair of processed value set codings - * @property processedValueSetUrls - Key-value pair of contained value set urls - * @property cachedValueSetCodings - Key-value pair of cached value set codings - * @property fhirPathContext - Key-value pair of evaluated FHIRPath values - * @property populatedContext - Key-value pair of one-off pre-populated FHIRPath values + * @property calculatedExpressions - Key-value pair of calculated expressions `Record` + * @property answerExpressions - Key-value pair of answer expressions `Record` + * @property processedValueSetCodings - Key-value pair of processed value set codings `Record` + * @property processedValueSetUrls - Key-value pair of contained value set urls `Record` + * @property cachedValueSetCodings - Key-value pair of cached value set codings `Record` + * @property fhirPathContext - Key-value pair of evaluated FHIRPath values `Record` + * @property populatedContext - Key-value pair of one-off pre-populated FHIRPath values `Record` * @property focusedLinkId - LinkId of the currently focused item * @property readOnly - Flag to set the form to read-only mode * @method buildSourceQuestionnaire - Used to build the source questionnaire with the provided questionnaire and optionally questionnaire response, additional variables, terminology server url and readyOnly flag diff --git a/packages/smart-forms-renderer/src/stories/BuildFormButtonForStorybook.tsx b/packages/smart-forms-renderer/src/stories/StorybookWrappers/BuildFormButtonForStorybook.tsx similarity index 91% rename from packages/smart-forms-renderer/src/stories/BuildFormButtonForStorybook.tsx rename to packages/smart-forms-renderer/src/stories/StorybookWrappers/BuildFormButtonForStorybook.tsx index bb2e10d6a..d6c2bfe87 100644 --- a/packages/smart-forms-renderer/src/stories/BuildFormButtonForStorybook.tsx +++ b/packages/smart-forms-renderer/src/stories/StorybookWrappers/BuildFormButtonForStorybook.tsx @@ -19,12 +19,12 @@ import React from 'react'; import type { Questionnaire, QuestionnaireResponse } from 'fhir/r4'; import { Box, IconButton, Tooltip } from '@mui/material'; -import Iconify from '../components/Iconify/Iconify'; -import { buildForm } from '../utils'; +import Iconify from '../../components/Iconify/Iconify'; +import { buildForm } from '../../utils'; interface BuildFormButtonProps { questionnaire: Questionnaire; - questionnaireResponse: QuestionnaireResponse; + questionnaireResponse?: QuestionnaireResponse; } function BuildFormButtonForStorybook(props: BuildFormButtonProps) { diff --git a/packages/smart-forms-renderer/src/stories/BuildFormButtonTesterWrapper.tsx b/packages/smart-forms-renderer/src/stories/StorybookWrappers/BuildFormButtonTesterWrapperForStorybook.tsx similarity index 80% rename from packages/smart-forms-renderer/src/stories/BuildFormButtonTesterWrapper.tsx rename to packages/smart-forms-renderer/src/stories/StorybookWrappers/BuildFormButtonTesterWrapperForStorybook.tsx index 3333a39d6..7a68b7d1c 100644 --- a/packages/smart-forms-renderer/src/stories/BuildFormButtonTesterWrapper.tsx +++ b/packages/smart-forms-renderer/src/stories/StorybookWrappers/BuildFormButtonTesterWrapperForStorybook.tsx @@ -18,18 +18,20 @@ // @ts-ignore import React from 'react'; import type { Questionnaire, QuestionnaireResponse } from 'fhir/r4'; -import { BaseRenderer } from '../components'; +import { BaseRenderer } from '../../components'; import { QueryClientProvider } from '@tanstack/react-query'; -import { RendererThemeProvider } from '../theme'; -import { useBuildForm, useRendererQueryClient } from '../hooks'; +import { RendererThemeProvider } from '../../theme'; +import { useBuildForm, useRendererQueryClient } from '../../hooks'; import BuildFormButtonForStorybook from './BuildFormButtonForStorybook'; -interface BuildFormButtonTesterWrapperProps { +interface BuildFormButtonTesterWrapperForStorybookProps { questionnaire: Questionnaire; questionnaireResponse?: QuestionnaireResponse; } -function BuildFormButtonTesterWrapper(props: BuildFormButtonTesterWrapperProps) { +function BuildFormButtonTesterWrapperForStorybook( + props: BuildFormButtonTesterWrapperForStorybookProps +) { const { questionnaire, questionnaireResponse } = props; const queryClient = useRendererQueryClient(); @@ -55,4 +57,4 @@ function BuildFormButtonTesterWrapper(props: BuildFormButtonTesterWrapperProps) ); } -export default BuildFormButtonTesterWrapper; +export default BuildFormButtonTesterWrapperForStorybook; diff --git a/packages/smart-forms-renderer/src/stories/BuildFormWrapper.tsx b/packages/smart-forms-renderer/src/stories/StorybookWrappers/BuildFormWrapperForStorybook.tsx similarity index 77% rename from packages/smart-forms-renderer/src/stories/BuildFormWrapper.tsx rename to packages/smart-forms-renderer/src/stories/StorybookWrappers/BuildFormWrapperForStorybook.tsx index 257ec1c69..ddc6ea243 100644 --- a/packages/smart-forms-renderer/src/stories/BuildFormWrapper.tsx +++ b/packages/smart-forms-renderer/src/stories/StorybookWrappers/BuildFormWrapperForStorybook.tsx @@ -18,18 +18,18 @@ // @ts-ignore import React from 'react'; import type { Questionnaire, QuestionnaireResponse } from 'fhir/r4'; -import { BaseRenderer } from '../components'; +import { BaseRenderer } from '../../components'; import { QueryClientProvider } from '@tanstack/react-query'; -import RendererThemeProvider from '../theme/Theme'; -import { useBuildForm } from '../hooks'; -import useRendererQueryClient from '../hooks/useRendererQueryClient'; +import RendererThemeProvider from '../../theme/Theme'; +import { useBuildForm } from '../../hooks'; +import useRendererQueryClient from '../../hooks/useRendererQueryClient'; -interface BuildFormWrapperProps { +interface BuildFormWrapperForStorybookProps { questionnaire: Questionnaire; questionnaireResponse?: QuestionnaireResponse; } -function BuildFormWrapper(props: BuildFormWrapperProps) { +function BuildFormWrapperForStorybook(props: BuildFormWrapperForStorybookProps) { const { questionnaire, questionnaireResponse } = props; const queryClient = useRendererQueryClient(); @@ -48,4 +48,4 @@ function BuildFormWrapper(props: BuildFormWrapperProps) { ); } -export default BuildFormWrapper; +export default BuildFormWrapperForStorybook; diff --git a/packages/smart-forms-renderer/src/stories/FormValidationTesterWrapper.tsx b/packages/smart-forms-renderer/src/stories/StorybookWrappers/FormValidationTesterWrapperForStorybook.tsx similarity index 81% rename from packages/smart-forms-renderer/src/stories/FormValidationTesterWrapper.tsx rename to packages/smart-forms-renderer/src/stories/StorybookWrappers/FormValidationTesterWrapperForStorybook.tsx index 81ed8f029..39f869e30 100644 --- a/packages/smart-forms-renderer/src/stories/FormValidationTesterWrapper.tsx +++ b/packages/smart-forms-renderer/src/stories/StorybookWrappers/FormValidationTesterWrapperForStorybook.tsx @@ -18,19 +18,21 @@ // @ts-ignore import React from 'react'; import type { Questionnaire, QuestionnaireResponse } from 'fhir/r4'; -import { BaseRenderer } from '../components'; +import { BaseRenderer } from '../../components'; import { QueryClientProvider } from '@tanstack/react-query'; -import { RendererThemeProvider } from '../theme'; -import { useBuildForm, useRendererQueryClient } from '../hooks'; +import { RendererThemeProvider } from '../../theme'; +import { useBuildForm, useRendererQueryClient } from '../../hooks'; import { Grid } from '@mui/material'; import FormValidationViewerForStorybook from './FormValidationViewerForStorybook'; -interface FormValidationTesterWrapperProps { +interface FormValidationTesterWrapperForStorybookProps { questionnaire: Questionnaire; questionnaireResponse?: QuestionnaireResponse; } -function FormValidationTesterWrapper(props: FormValidationTesterWrapperProps) { +function FormValidationTesterWrapperForStorybook( + props: FormValidationTesterWrapperForStorybookProps +) { const { questionnaire, questionnaireResponse } = props; const isBuilding = useBuildForm(questionnaire, questionnaireResponse); @@ -59,4 +61,4 @@ function FormValidationTesterWrapper(props: FormValidationTesterWrapperProps) { ); } -export default FormValidationTesterWrapper; +export default FormValidationTesterWrapperForStorybook; diff --git a/packages/smart-forms-renderer/src/stories/FormValidationViewerForStorybook.tsx b/packages/smart-forms-renderer/src/stories/StorybookWrappers/FormValidationViewerForStorybook.tsx similarity index 94% rename from packages/smart-forms-renderer/src/stories/FormValidationViewerForStorybook.tsx rename to packages/smart-forms-renderer/src/stories/StorybookWrappers/FormValidationViewerForStorybook.tsx index 0a87f4390..929a9323b 100644 --- a/packages/smart-forms-renderer/src/stories/FormValidationViewerForStorybook.tsx +++ b/packages/smart-forms-renderer/src/stories/StorybookWrappers/FormValidationViewerForStorybook.tsx @@ -17,7 +17,7 @@ // @ts-ignore import React from 'react'; -import { useQuestionnaireResponseStore } from '../stores'; +import { useQuestionnaireResponseStore } from '../../stores'; function FormValidationViewerForStorybook() { const invalidItems = useQuestionnaireResponseStore.use.invalidItems(); diff --git a/packages/smart-forms-renderer/src/stories/InitialiseFormWrapperForStorybook.tsx b/packages/smart-forms-renderer/src/stories/StorybookWrappers/InitialiseFormWrapperForStorybook.tsx similarity index 82% rename from packages/smart-forms-renderer/src/stories/InitialiseFormWrapperForStorybook.tsx rename to packages/smart-forms-renderer/src/stories/StorybookWrappers/InitialiseFormWrapperForStorybook.tsx index 4c0e35ea6..196bd9557 100644 --- a/packages/smart-forms-renderer/src/stories/InitialiseFormWrapperForStorybook.tsx +++ b/packages/smart-forms-renderer/src/stories/StorybookWrappers/InitialiseFormWrapperForStorybook.tsx @@ -18,12 +18,12 @@ // @ts-ignore import React from 'react'; import type { Questionnaire, QuestionnaireResponse } from 'fhir/r4'; -import { BaseRenderer } from '../components'; +import { BaseRenderer } from '../../components'; import { QueryClientProvider } from '@tanstack/react-query'; -import RendererThemeProvider from '../theme/Theme'; -import useRendererQueryClient from '../hooks/useRendererQueryClient'; +import RendererThemeProvider from '../../theme/Theme'; +import useRendererQueryClient from '../../hooks/useRendererQueryClient'; import type Client from 'fhirclient/lib/Client'; -import useInitialiseForm from '../hooks/useInitialiseForm'; +import useInitialiseForm from '../../hooks/useInitialiseForm'; import Box from '@mui/material/Box'; import CircularProgress from '@mui/material/CircularProgress'; import Typography from '@mui/material/Typography'; @@ -47,6 +47,10 @@ interface InitialiseFormWrapperProps { * - Make your own initialiseFhirClient() call in a button click or other event handler. Alternatively, you can use the useInitialiseForm hook to initialise the form. * - The initialised FHIRClient is only used for further FHIR calls. It does not provide pre-population capabilities. * + * For button click usage examples of buildForm(), see: + * - https://github.com/aehrc/smart-forms/blob/main/packages/smart-forms-renderer/src/stories/BuildFormButtonTesterWrapper.tsx#L47 + * - https://github.com/aehrc/smart-forms/blob/main/packages/smart-forms-renderer/src/stories/BuildFormButtonForStorybook.tsx + * * @author Sean Fong */ function InitialiseFormWrapperForStorybook(props: InitialiseFormWrapperProps) { @@ -66,8 +70,7 @@ function InitialiseFormWrapperForStorybook(props: InitialiseFormWrapperProps) { * The useInitialiseForm hook provides initialisation logic for the form * Alternatively (and recommended to do so), you can initialise your form via a button click or other event handler. * - * // FIXME add github link - * @see BuildFormButtonTesterWrapper for button click usage examples. + * @see {@link https://github.com/aehrc/smart-forms/blob/main/packages/smart-forms-renderer/src/stories/BuildFormButtonForStorybook.tsx} for button click usage examples. */ const isInitialising = useInitialiseForm( questionnaire, diff --git a/packages/smart-forms-renderer/src/stories/PrePopButtonForStorybook.tsx b/packages/smart-forms-renderer/src/stories/StorybookWrappers/PrePopButtonForStorybook.tsx similarity index 88% rename from packages/smart-forms-renderer/src/stories/PrePopButtonForStorybook.tsx rename to packages/smart-forms-renderer/src/stories/StorybookWrappers/PrePopButtonForStorybook.tsx index 3ed4c4150..cc1cbef4e 100644 --- a/packages/smart-forms-renderer/src/stories/PrePopButtonForStorybook.tsx +++ b/packages/smart-forms-renderer/src/stories/StorybookWrappers/PrePopButtonForStorybook.tsx @@ -18,15 +18,15 @@ // @ts-ignore import React from 'react'; import { Box, CircularProgress, Fade, IconButton, Tooltip } from '@mui/material'; -import PlayCircleIcon from '@mui/icons-material/PlayCircle'; +import CloudDownloadIcon from '@mui/icons-material/CloudDownload'; import Typography from '@mui/material/Typography'; -interface PrePopButtonProps { +interface PrePopButtonForStorybookProps { isPopulating: boolean; onPopulate: () => void; } -function PrePopButtonForStorybook(props: PrePopButtonProps) { +function PrePopButtonForStorybook(props: PrePopButtonForStorybookProps) { const { isPopulating, onPopulate } = props; return ( @@ -37,7 +37,7 @@ function PrePopButtonForStorybook(props: PrePopButtonProps) { {isPopulating ? ( ) : ( - + )} diff --git a/packages/smart-forms-renderer/src/stories/PrePopWrapper.tsx b/packages/smart-forms-renderer/src/stories/StorybookWrappers/PrePopWrapperForStorybook.tsx similarity index 82% rename from packages/smart-forms-renderer/src/stories/PrePopWrapper.tsx rename to packages/smart-forms-renderer/src/stories/StorybookWrappers/PrePopWrapperForStorybook.tsx index 001488f64..c4018d82d 100644 --- a/packages/smart-forms-renderer/src/stories/PrePopWrapper.tsx +++ b/packages/smart-forms-renderer/src/stories/StorybookWrappers/PrePopWrapperForStorybook.tsx @@ -18,24 +18,24 @@ // @ts-ignore import React, { useState } from 'react'; import type { Patient, Practitioner, Questionnaire } from 'fhir/r4'; -import { BaseRenderer } from '../components'; +import { BaseRenderer } from '../../components'; import { QueryClientProvider } from '@tanstack/react-query'; -import { RendererThemeProvider } from '../theme'; -import { useBuildForm, useRendererQueryClient } from '../hooks'; +import { RendererThemeProvider } from '../../theme'; +import { useBuildForm, useRendererQueryClient } from '../../hooks'; import type Client from 'fhirclient/lib/Client'; -import { buildForm } from '../utils'; import PrePopButtonForStorybook from './PrePopButtonForStorybook'; import { populateQuestionnaire } from '@aehrc/sdc-populate'; import { fetchResourceCallback } from './populateCallbackForStorybook'; +import { buildForm } from '../../utils'; -interface PrePopWrapperProps { +interface PrePopWrapperForStorybookProps { questionnaire: Questionnaire; fhirClient: Client; patient: Patient; user: Practitioner; } -function PrePopWrapper(props: PrePopWrapperProps) { +function PrePopWrapperForStorybook(props: PrePopWrapperForStorybookProps) { const { questionnaire, fhirClient, patient, user } = props; const [isPopulating, setIsPopulating] = useState(false); @@ -64,8 +64,7 @@ function PrePopWrapper(props: PrePopWrapperProps) { const { populatedResponse } = populateResult; - // buildForm is used here because there is a really bizarre bug - using the store hooks directly doesn't update the baseRenderer - // could be the fact that it doesn't play well with storybook + // Call to buildForm to pre-populate the QR which repaints the entire BaseRenderer view await buildForm(questionnaire, populatedResponse); setIsPopulating(false); @@ -88,4 +87,4 @@ function PrePopWrapper(props: PrePopWrapperProps) { ); } -export default PrePopWrapper; +export default PrePopWrapperForStorybook; diff --git a/packages/smart-forms-renderer/src/stories/ValidateFormButtonForStorybook.tsx b/packages/smart-forms-renderer/src/stories/StorybookWrappers/ValidateFormButtonForStorybook.tsx similarity index 90% rename from packages/smart-forms-renderer/src/stories/ValidateFormButtonForStorybook.tsx rename to packages/smart-forms-renderer/src/stories/StorybookWrappers/ValidateFormButtonForStorybook.tsx index 2f22275f8..ed51e7ef6 100644 --- a/packages/smart-forms-renderer/src/stories/ValidateFormButtonForStorybook.tsx +++ b/packages/smart-forms-renderer/src/stories/StorybookWrappers/ValidateFormButtonForStorybook.tsx @@ -18,13 +18,13 @@ // @ts-ignore import React from 'react'; import { Box, IconButton, Tooltip } from '@mui/material'; -import Iconify from '../components/Iconify/Iconify'; +import Iconify from '../../components/Iconify/Iconify'; -interface ValidationFormButtonProps { +interface ValidationFormButtonForStorybookProps { onValidate: () => void; } -function ValidationFormButtonForStorybook(props: ValidationFormButtonProps) { +function ValidationFormButtonForStorybook(props: ValidationFormButtonForStorybookProps) { const { onValidate } = props; return ( diff --git a/packages/smart-forms-renderer/src/stories/StorybookWrappers/index.ts b/packages/smart-forms-renderer/src/stories/StorybookWrappers/index.ts new file mode 100644 index 000000000..0d9e9023e --- /dev/null +++ b/packages/smart-forms-renderer/src/stories/StorybookWrappers/index.ts @@ -0,0 +1,20 @@ +/* + * Copyright 2024 Commonwealth Scientific and Industrial Research + * Organisation (CSIRO) ABN 41 687 119 230. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { default as InitialiseFormWrapperForStorybook } from './InitialiseFormWrapperForStorybook'; +export { default as BuildFormButtonTesterWrapperForStorybook } from './BuildFormButtonTesterWrapperForStorybook'; +export { default as PrePopWrapperForStorybook } from './PrePopWrapperForStorybook'; diff --git a/packages/smart-forms-renderer/src/stories/populateCallbackForStorybook.ts b/packages/smart-forms-renderer/src/stories/StorybookWrappers/populateCallbackForStorybook.ts similarity index 96% rename from packages/smart-forms-renderer/src/stories/populateCallbackForStorybook.ts rename to packages/smart-forms-renderer/src/stories/StorybookWrappers/populateCallbackForStorybook.ts index 89d2e6dd9..5eeb26520 100644 --- a/packages/smart-forms-renderer/src/stories/populateCallbackForStorybook.ts +++ b/packages/smart-forms-renderer/src/stories/StorybookWrappers/populateCallbackForStorybook.ts @@ -20,7 +20,7 @@ import axios from 'axios'; const ABSOLUTE_URL_REGEX = /^(https?|ftp):\/\/[^\s/$.?#].[^\s]*$/; -export interface RequestConfig { +interface RequestConfig { clientEndpoint: string; authToken: string | null; } @@ -32,7 +32,7 @@ export const fetchResourceCallback: FetchResourceCallback = ( let { clientEndpoint } = requestConfig; const { authToken } = requestConfig; - const headers = { + const headers: any = { Accept: 'application/json;charset=utf-8' }; diff --git a/packages/smart-forms-renderer/src/stories/assets/questionnaires/QBuildFormButtonTester.ts b/packages/smart-forms-renderer/src/stories/assets/questionnaires/QBuildFormButtonTester.ts deleted file mode 100644 index 1351df670..000000000 --- a/packages/smart-forms-renderer/src/stories/assets/questionnaires/QBuildFormButtonTester.ts +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright 2024 Commonwealth Scientific and Industrial Research - * Organisation (CSIRO) ABN 41 687 119 230. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import type { Questionnaire, QuestionnaireResponse } from 'fhir/r4'; - -export const qBuildFormButtonTester: Questionnaire = { - resourceType: 'Questionnaire', - id: 'BuildFormButtonTester', - name: 'BuildFormButtonTester', - title: 'BuildForm Button Tester', - version: '0.1.0', - status: 'draft', - publisher: 'AEHRC CSIRO', - date: '2024-05-01', - url: 'https://smartforms.csiro.au/docs/tester/build-form-button', - item: [ - { - linkId: 'decimal', - type: 'decimal', - repeats: false, - text: 'Decimal Test' - }, - { - linkId: 'integer', - type: 'integer', - repeats: false, - text: 'Integer Test' - }, - { - linkId: 'string', - type: 'string', - repeats: false, - text: 'String Test' - }, - { - linkId: 'text', - type: 'text', - repeats: false, - text: 'Text Test' - }, - { - linkId: 'date', - type: 'date', - repeats: false, - text: 'Date Test' - }, - { - linkId: 'dateTime', - type: 'dateTime', - repeats: false, - text: 'DateTime Test' - }, - { - linkId: 'url', - type: 'url', - repeats: false, - text: 'URL Test' - }, - { - linkId: 'repeats-container', - type: 'group', - repeats: false, - text: '', - item: [ - { - linkId: 'repeats-string', - type: 'string', - repeats: true, - text: 'Repeats Test (String)' - } - ] - }, - { - linkId: 'repeats-group', - type: 'group', - repeats: true, - text: 'Repeats Group Test', - item: [ - { - linkId: 'repeats-group-boolean', - type: 'boolean', - repeats: false, - text: 'Boolean' - }, - { - linkId: 'repeats-group-integer', - type: 'integer', - repeats: false, - text: 'Integer' - }, - { - linkId: 'repeats-group-string', - type: 'string', - repeats: false, - text: 'String' - } - ] - } - ] -}; - -export const qrBuildFormTesterResponse: QuestionnaireResponse = { - resourceType: 'QuestionnaireResponse', - status: 'in-progress', - item: [ - { - linkId: 'decimal', - text: 'Decimal Test', - answer: [ - { - valueDecimal: 123.45 - } - ] - }, - { - linkId: 'integer', - text: 'Integer Test', - answer: [ - { - valueInteger: 123 - } - ] - }, - { - linkId: 'string', - text: 'String Test', - answer: [ - { - valueString: 'Sample String' - } - ] - }, - { - linkId: 'text', - text: 'Text Test', - answer: [ - { - valueString: 'Sample Text' - } - ] - }, - { - linkId: 'date', - text: 'Date Test', - answer: [ - { - valueDate: '2024-05-20' - } - ] - }, - { - linkId: 'dateTime', - text: 'DateTime Test', - answer: [ - { - valueDateTime: '2024-05-20T15:30:00Z' - } - ] - }, - { - linkId: 'url', - text: 'URL Test', - answer: [ - { - valueUri: 'https://example.com' - } - ] - }, - { - linkId: 'repeats-container', - text: '', - item: [ - { - linkId: 'repeats-string', - text: 'Repeats Test (String)', - answer: [ - { - valueString: 'First String' - }, - { - valueString: 'Second String' - } - ] - } - ] - }, - { - linkId: 'repeats-group', - text: 'Repeats Group Test', - item: [ - { - linkId: 'repeats-group-boolean', - text: 'Boolean', - answer: [ - { - valueBoolean: true - } - ] - }, - { - linkId: 'repeats-group-integer', - text: 'Integer', - answer: [ - { - valueInteger: 123 - } - ] - }, - { - linkId: 'repeats-group-string', - text: 'String', - answer: [ - { - valueString: 'Nested String 1' - } - ] - } - ] - }, - { - linkId: 'repeats-group', - text: 'Repeats Group Test', - item: [ - { - linkId: 'repeats-group-boolean', - text: 'Boolean', - answer: [ - { - valueBoolean: false - } - ] - }, - { - linkId: 'repeats-group-integer', - text: 'Integer', - answer: [ - { - valueInteger: 456 - } - ] - }, - { - linkId: 'repeats-group-string', - text: 'String', - answer: [ - { - valueString: 'Nested String 2' - } - ] - } - ] - } - ], - - questionnaire: 'https://smartforms.csiro.au/docs/tester/build-form-button' -}; diff --git a/packages/smart-forms-renderer/src/stories/assets/questionnaires/QButtonTester.ts b/packages/smart-forms-renderer/src/stories/assets/questionnaires/QButtonTester.ts new file mode 100644 index 000000000..8d541dfc9 --- /dev/null +++ b/packages/smart-forms-renderer/src/stories/assets/questionnaires/QButtonTester.ts @@ -0,0 +1,380 @@ +/* + * Copyright 2024 Commonwealth Scientific and Industrial Research + * Organisation (CSIRO) ABN 41 687 119 230. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { Questionnaire, QuestionnaireResponse } from 'fhir/r4'; + +export const qButtonTester: Questionnaire = { + resourceType: 'Questionnaire', + id: 'ButtonTester', + name: 'ButtonTester', + title: 'Button Tester', + version: '0.1.0', + status: 'draft', + publisher: 'AEHRC CSIRO', + date: '2024-05-01', + url: 'https://smartforms.csiro.au/docs/tester/button', + extension: [ + { + url: 'http://hl7.org/fhir/StructureDefinition/variable', + valueExpression: { + name: 'AllConditions', + language: 'application/x-fhir-query', + expression: 'Condition?patient={{%patient.id}}' + } + }, + { + url: 'http://hl7.org/fhir/StructureDefinition/variable', + valueExpression: { + name: 'DecimalObsBodyWeight', + language: 'application/x-fhir-query', + expression: 'Observation?code=29463-7&_count=1&_sort=-date&patient={{%patient.id}}' + } + }, + { + url: 'http://hl7.org/fhir/StructureDefinition/variable', + valueExpression: { + name: 'IntegerObsBloodPressure', + language: 'application/x-fhir-query', + expression: 'Observation?code=85354-9&_count=1&_sort=-date&patient={{%patient.id}}' + } + }, + { + url: 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-launchContext', + extension: [ + { + url: 'name', + valueCoding: { + system: 'http://hl7.org/fhir/uv/sdc/CodeSystem/launchContext', + code: 'patient' + } + }, + { + url: 'type', + valueCode: 'Patient' + }, + { + url: 'description', + valueString: 'The patient that is to be used to pre-populate the form' + } + ] + } + ], + item: [ + { + extension: [ + { + url: 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression', + valueExpression: { + language: 'text/fhirpath', + expression: '%DecimalObsBodyWeight.entry.resource.value.value' + } + } + ], + linkId: 'decimal', + type: 'decimal', + repeats: false, + text: 'Decimal Test' + }, + { + extension: [ + { + url: 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression', + valueExpression: { + language: 'text/fhirpath', + expression: + "%IntegerObsBloodPressure.entry.resource.component.where(code.coding.exists(code='8480-6')).value.value" + } + } + ], + linkId: 'integer', + type: 'integer', + repeats: false, + text: 'Integer Test' + }, + { + extension: [ + { + url: 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression', + valueExpression: { + language: 'text/fhirpath', + expression: "(%patient.name.where(use='official').select(family) | text).first()" + } + } + ], + linkId: 'string', + type: 'string', + repeats: false, + text: 'String Test' + }, + { + extension: [ + { + url: 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression', + valueExpression: { + language: 'text/fhirpath', + expression: + "%patient.address.where(use='home' and (type.empty() or type!='postal')).select(line.join(', '))" + } + } + ], + linkId: 'text', + type: 'text', + repeats: false, + text: 'Text Test' + }, + { + extension: [ + { + url: 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression', + valueExpression: { + language: 'text/fhirpath', + expression: '%patient.birthDate' + } + } + ], + linkId: 'date', + type: 'date', + repeats: false, + text: 'Date Test' + }, + { + extension: [ + { + url: 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression', + valueExpression: { + language: 'text/fhirpath', + expression: '%patient.birthDate' + } + } + ], + linkId: 'dateTime', + type: 'dateTime', + repeats: false, + text: 'DateTime Test' + }, + { + linkId: 'repeats-container', + type: 'group', + repeats: false, + text: '', + item: [ + { + extension: [ + { + url: 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression', + valueExpression: { + language: 'text/fhirpath', + expression: "%patient.telecom.where(system = 'phone' and use = 'home').value" + } + } + ], + linkId: 'repeats-string', + type: 'string', + repeats: true, + text: 'Repeats Test (String)' + } + ] + }, + { + extension: [ + { + url: 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-itemPopulationContext', + valueExpression: { + name: 'PostalAddressRepeat', + language: 'text/fhirpath', + expression: "%patient.address.where(type='postal')" + } + } + ], + linkId: 'repeats-group', + type: 'group', + repeats: true, + text: 'Repeats Group Test', + item: [ + { + extension: [ + { + url: 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression', + valueExpression: { + language: 'text/fhirpath', + expression: '%PostalAddressRepeat.city' + } + } + ], + linkId: 'repeats-group-string', + text: 'String', + type: 'string', + repeats: false + }, + { + extension: [ + { + url: 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-initialExpression', + valueExpression: { + language: 'text/fhirpath', + expression: '%PostalAddressRepeat.state' + } + } + ], + linkId: 'repeats-group-choice', + text: 'Choice', + type: 'choice', + repeats: false, + answerValueSet: + 'https://healthterminologies.gov.au/fhir/ValueSet/australian-states-territories-2' + } + ] + } + ] +}; + +export const qrButtonTesterResponse: QuestionnaireResponse = { + resourceType: 'QuestionnaireResponse', + status: 'in-progress', + item: [ + { + linkId: 'decimal', + text: 'Decimal Test', + answer: [ + { + valueDecimal: 123.45 + } + ] + }, + { + linkId: 'integer', + text: 'Integer Test', + answer: [ + { + valueInteger: 123 + } + ] + }, + { + linkId: 'string', + text: 'String Test', + answer: [ + { + valueString: 'Sample String' + } + ] + }, + { + linkId: 'text', + text: 'Text Test', + answer: [ + { + valueString: 'Sample Text' + } + ] + }, + { + linkId: 'date', + text: 'Date Test', + answer: [ + { + valueDate: '2024-05-20' + } + ] + }, + { + linkId: 'dateTime', + text: 'DateTime Test', + answer: [ + { + valueDateTime: '2024-05-20T15:30:00Z' + } + ] + }, + { + linkId: 'repeats-container', + text: '', + item: [ + { + linkId: 'repeats-string', + text: 'Repeats Test (String)', + answer: [ + { + valueString: 'First String' + }, + { + valueString: 'Second String' + } + ] + } + ] + }, + { + linkId: 'repeats-group', + text: 'Repeats Group Test', + item: [ + { + linkId: 'repeats-group-string', + text: 'String', + answer: [ + { + valueString: 'Nested String 1' + } + ] + }, + { + linkId: 'repeats-group-choice', + text: 'Choice', + answer: [ + { + valueCoding: { + system: + 'https://healthterminologies.gov.au/fhir/CodeSystem/australian-states-territories-1', + code: 'NSW' + } + } + ] + } + ] + }, + { + linkId: 'repeats-group', + text: 'Repeats Group Test', + item: [ + { + linkId: 'repeats-group-string', + text: 'String', + answer: [ + { + valueString: 'Nested String 2' + } + ] + }, + { + linkId: 'repeats-group-choice', + text: 'Choice', + answer: [ + { + valueCoding: { + system: + 'https://healthterminologies.gov.au/fhir/CodeSystem/australian-states-territories-1', + code: 'SA' + } + } + ] + } + ] + } + ], + + questionnaire: 'https://smartforms.csiro.au/docs/tester/button' +}; diff --git a/packages/smart-forms-renderer/src/stories/assets/questionnaires/QValidateFormButtonTester.ts b/packages/smart-forms-renderer/src/stories/assets/questionnaires/QValidateTester.ts similarity index 63% rename from packages/smart-forms-renderer/src/stories/assets/questionnaires/QValidateFormButtonTester.ts rename to packages/smart-forms-renderer/src/stories/assets/questionnaires/QValidateTester.ts index 46d999ffc..3ddfa651c 100644 --- a/packages/smart-forms-renderer/src/stories/assets/questionnaires/QValidateFormButtonTester.ts +++ b/packages/smart-forms-renderer/src/stories/assets/questionnaires/QValidateTester.ts @@ -15,18 +15,18 @@ * limitations under the License. */ -import type { Questionnaire, QuestionnaireResponse } from 'fhir/r4'; +import type { Questionnaire } from 'fhir/r4'; -export const qValidateFormButtonTester: Questionnaire = { +export const qValidateTester: Questionnaire = { resourceType: 'Questionnaire', - id: 'ValidateFormButtonTester', - name: 'ValidateFormButtonTester', - title: 'ValidateForm Button Tester', + id: 'ValidateTester', + name: 'ValidateTester', + title: 'Validate Tester', version: '0.1.0', status: 'draft', publisher: 'AEHRC CSIRO', date: '2024-05-01', - url: 'https://smartforms.csiro.au/docs/tester/validate-form-button', + url: 'https://smartforms.csiro.au/docs/tester/validate', item: [ { linkId: 'required', @@ -116,74 +116,3 @@ export const qValidateFormButtonTester: Questionnaire = { } ] }; - -export const qrValidateFormButtonTesterResponse: QuestionnaireResponse = { - resourceType: 'QuestionnaireResponse', - status: 'in-progress', - item: [ - { - linkId: 'required', - text: 'Required', - answer: [ - { - valueBoolean: true - } - ] - }, - { - linkId: 'maxlength', - text: 'Max Length (10)', - answer: [ - { - valueInteger: 10 - } - ] - }, - { - linkId: 'minlength', - text: 'Min Length (10)', - answer: [ - { - valueInteger: 9 - } - ] - }, - { - linkId: 'regex', - text: 'Regex (####)', - answer: [ - { - valueString: '32452' - } - ] - }, - { - linkId: 'maxvalue', - text: 'Max Value (<=65)', - answer: [ - { - valueInteger: 70 - } - ] - }, - { - linkId: 'minvalue', - text: 'Min Value (>=18)', - answer: [ - { - valueInteger: 15 - } - ] - }, - { - linkId: 'maxdecimalplaces', - text: 'Max Decimal Places (2)', - answer: [ - { - valueDecimal: 72.456 - } - ] - } - ], - questionnaire: 'https://smartforms.csiro.au/docs/tester/validate-form-button|0.1.0' -}; diff --git a/packages/smart-forms-renderer/src/stories/itemTypes/Attachment.stories.tsx b/packages/smart-forms-renderer/src/stories/itemTypes/Attachment.stories.tsx index 09d425b41..c86af0d4e 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/Attachment.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/Attachment.stories.tsx @@ -16,16 +16,16 @@ */ import type { Meta, StoryObj } from '@storybook/react'; -import BuildFormWrapper from '../BuildFormWrapper'; +import BuildFormWrapperForStorybook from '../StorybookWrappers/BuildFormWrapperForStorybook'; import { qAttachmentBasic } from '../assets/questionnaires'; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export const meta = { title: 'Component/ItemType/Attachment', - component: BuildFormWrapper, + component: BuildFormWrapperForStorybook, // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs tags: [] -} satisfies Meta; +} satisfies Meta; export default meta; type Story = StoryObj; diff --git a/packages/smart-forms-renderer/src/stories/itemTypes/Boolean.stories.tsx b/packages/smart-forms-renderer/src/stories/itemTypes/Boolean.stories.tsx index 5b9b3d026..06360ec01 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/Boolean.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/Boolean.stories.tsx @@ -21,15 +21,15 @@ import { qBooleanCalculation, qrBooleanBasicResponse } from '../assets/questionnaires'; -import BuildFormWrapper from '../BuildFormWrapper'; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export +import BuildFormWrapperForStorybook from '../StorybookWrappers/BuildFormWrapperForStorybook'; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export const meta = { title: 'Component/ItemType/Boolean', - component: BuildFormWrapper, + component: BuildFormWrapperForStorybook, // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs tags: [] -} satisfies Meta; +} satisfies Meta; export default meta; type Story = StoryObj; diff --git a/packages/smart-forms-renderer/src/stories/itemTypes/Choice.stories.tsx b/packages/smart-forms-renderer/src/stories/itemTypes/Choice.stories.tsx index 7b977a603..266597e00 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/Choice.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/Choice.stories.tsx @@ -16,7 +16,7 @@ */ import type { Meta, StoryObj } from '@storybook/react'; -import BuildFormWrapper from '../BuildFormWrapper'; +import BuildFormWrapperForStorybook from '../StorybookWrappers/BuildFormWrapperForStorybook'; import { qChoiceAnswerOptionBasic, qChoiceAnswerOptionCalculation, @@ -29,10 +29,10 @@ import { // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export const meta = { title: 'Component/ItemType/Choice', - component: BuildFormWrapper, + component: BuildFormWrapperForStorybook, // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs tags: [] -} satisfies Meta; +} satisfies Meta; export default meta; type Story = StoryObj; diff --git a/packages/smart-forms-renderer/src/stories/itemTypes/Date.stories.tsx b/packages/smart-forms-renderer/src/stories/itemTypes/Date.stories.tsx index 3772d7f76..f9094a6f2 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/Date.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/Date.stories.tsx @@ -16,16 +16,16 @@ */ import type { Meta, StoryObj } from '@storybook/react'; -import BuildFormWrapper from '../BuildFormWrapper'; +import BuildFormWrapperForStorybook from '../StorybookWrappers/BuildFormWrapperForStorybook'; import { qDateBasic, qrDateBasicResponse } from '../assets/questionnaires'; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export const meta = { title: 'Component/ItemType/Date', - component: BuildFormWrapper, + component: BuildFormWrapperForStorybook, // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs tags: [] -} satisfies Meta; +} satisfies Meta; export default meta; type Story = StoryObj; diff --git a/packages/smart-forms-renderer/src/stories/itemTypes/DateTime.stories.tsx b/packages/smart-forms-renderer/src/stories/itemTypes/DateTime.stories.tsx index f722df697..4afd69a7f 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/DateTime.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/DateTime.stories.tsx @@ -16,16 +16,16 @@ */ import type { Meta, StoryObj } from '@storybook/react'; -import BuildFormWrapper from '../BuildFormWrapper'; +import BuildFormWrapperForStorybook from '../StorybookWrappers/BuildFormWrapperForStorybook'; import { qDateTimeBasic, qrDateTimeBasicResponse } from '../assets/questionnaires'; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export const meta = { title: 'Component/ItemType/DateTime', - component: BuildFormWrapper, + component: BuildFormWrapperForStorybook, // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs tags: [] -} satisfies Meta; +} satisfies Meta; export default meta; type Story = StoryObj; diff --git a/packages/smart-forms-renderer/src/stories/itemTypes/Decimal.stories.tsx b/packages/smart-forms-renderer/src/stories/itemTypes/Decimal.stories.tsx index 01446ad28..f8ddf6efc 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/Decimal.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/Decimal.stories.tsx @@ -16,7 +16,7 @@ */ import type { Meta, StoryObj } from '@storybook/react'; -import BuildFormWrapper from '../BuildFormWrapper'; +import BuildFormWrapperForStorybook from '../StorybookWrappers/BuildFormWrapperForStorybook'; import { qCalculatedExpressionBMICalculator, qDecimalBasic, @@ -26,10 +26,10 @@ import { // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export const meta = { title: 'Component/ItemType/Decimal', - component: BuildFormWrapper, + component: BuildFormWrapperForStorybook, // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs tags: [] -} satisfies Meta; +} satisfies Meta; export default meta; type Story = StoryObj; diff --git a/packages/smart-forms-renderer/src/stories/itemTypes/Display.stories.tsx b/packages/smart-forms-renderer/src/stories/itemTypes/Display.stories.tsx index 88d0eb15f..b9460c7ad 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/Display.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/Display.stories.tsx @@ -16,16 +16,16 @@ */ import type { Meta, StoryObj } from '@storybook/react'; -import BuildFormWrapper from '../BuildFormWrapper'; +import BuildFormWrapperForStorybook from '../StorybookWrappers/BuildFormWrapperForStorybook'; import { qDisplayBasic, qDisplayCalculation } from '../assets/questionnaires/QDisplay'; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export const meta = { title: 'Component/ItemType/Display', - component: BuildFormWrapper, + component: BuildFormWrapperForStorybook, // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs tags: [] -} satisfies Meta; +} satisfies Meta; export default meta; type Story = StoryObj; diff --git a/packages/smart-forms-renderer/src/stories/itemTypes/Group.stories.tsx b/packages/smart-forms-renderer/src/stories/itemTypes/Group.stories.tsx index b4af01139..20dd5e04c 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/Group.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/Group.stories.tsx @@ -16,16 +16,16 @@ */ import type { Meta, StoryObj } from '@storybook/react'; -import BuildFormWrapper from '../BuildFormWrapper'; +import BuildFormWrapperForStorybook from '../StorybookWrappers/BuildFormWrapperForStorybook'; import { qGroupBasic } from '../assets/questionnaires/QGroup'; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export const meta = { title: 'Component/ItemType/Group', - component: BuildFormWrapper, + component: BuildFormWrapperForStorybook, // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs tags: [] -} satisfies Meta; +} satisfies Meta; export default meta; type Story = StoryObj; diff --git a/packages/smart-forms-renderer/src/stories/itemTypes/Integer.stories.tsx b/packages/smart-forms-renderer/src/stories/itemTypes/Integer.stories.tsx index d47714a2f..b568a639c 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/Integer.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/Integer.stories.tsx @@ -16,7 +16,7 @@ */ import type { Meta, StoryObj } from '@storybook/react'; -import BuildFormWrapper from '../BuildFormWrapper'; +import BuildFormWrapperForStorybook from '../StorybookWrappers/BuildFormWrapperForStorybook'; import { qIntegerBasic, qIntegerCalculation, @@ -26,10 +26,10 @@ import { // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export const meta = { title: 'Component/ItemType/Integer', - component: BuildFormWrapper, + component: BuildFormWrapperForStorybook, // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs tags: [] -} satisfies Meta; +} satisfies Meta; export default meta; type Story = StoryObj; diff --git a/packages/smart-forms-renderer/src/stories/itemTypes/OpenChoice.stories.tsx b/packages/smart-forms-renderer/src/stories/itemTypes/OpenChoice.stories.tsx index f6ee8f0d2..2bd663222 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/OpenChoice.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/OpenChoice.stories.tsx @@ -16,7 +16,7 @@ */ import type { Meta, StoryObj } from '@storybook/react'; -import BuildFormWrapper from '../BuildFormWrapper'; +import BuildFormWrapperForStorybook from '../StorybookWrappers/BuildFormWrapperForStorybook'; import { qOpenChoiceAnswerOptionBasic, qOpenChoiceAnswerValueSetBasic, @@ -27,10 +27,10 @@ import { // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export const meta = { title: 'Component/ItemType/OpenChoice', - component: BuildFormWrapper, + component: BuildFormWrapperForStorybook, // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs tags: [] -} satisfies Meta; +} satisfies Meta; export default meta; type Story = StoryObj; diff --git a/packages/smart-forms-renderer/src/stories/itemTypes/Quantity.stories.tsx b/packages/smart-forms-renderer/src/stories/itemTypes/Quantity.stories.tsx index 3a61af7d5..ae4e4326b 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/Quantity.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/Quantity.stories.tsx @@ -16,16 +16,16 @@ */ import type { Meta, StoryObj } from '@storybook/react'; -import BuildFormWrapper from '../BuildFormWrapper'; +import BuildFormWrapperForStorybook from '../StorybookWrappers/BuildFormWrapperForStorybook'; import { qQuantityBasic } from '../assets/questionnaires'; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export const meta = { title: 'Component/ItemType/Quantity', - component: BuildFormWrapper, + component: BuildFormWrapperForStorybook, // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs tags: [] -} satisfies Meta; +} satisfies Meta; export default meta; type Story = StoryObj; diff --git a/packages/smart-forms-renderer/src/stories/itemTypes/Reference.stories.tsx b/packages/smart-forms-renderer/src/stories/itemTypes/Reference.stories.tsx index cc6d65dcd..027641fac 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/Reference.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/Reference.stories.tsx @@ -16,16 +16,16 @@ */ import type { Meta, StoryObj } from '@storybook/react'; -import BuildFormWrapper from '../BuildFormWrapper'; +import BuildFormWrapperForStorybook from '../StorybookWrappers/BuildFormWrapperForStorybook'; import { qReferenceBasic } from '../assets/questionnaires'; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export const meta = { title: 'Component/ItemType/Reference', - component: BuildFormWrapper, + component: BuildFormWrapperForStorybook, // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs tags: [] -} satisfies Meta; +} satisfies Meta; export default meta; type Story = StoryObj; diff --git a/packages/smart-forms-renderer/src/stories/itemTypes/String.stories.tsx b/packages/smart-forms-renderer/src/stories/itemTypes/String.stories.tsx index 3d7ea64e4..f2d424c80 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/String.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/String.stories.tsx @@ -16,16 +16,16 @@ */ import type { Meta, StoryObj } from '@storybook/react'; -import BuildFormWrapper from '../BuildFormWrapper'; +import BuildFormWrapperForStorybook from '../StorybookWrappers/BuildFormWrapperForStorybook'; import { qrStringBasicResponse, qStringBasic, qStringCalculation } from '../assets/questionnaires'; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export const meta = { title: 'Component/ItemType/String', - component: BuildFormWrapper, + component: BuildFormWrapperForStorybook, // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs tags: [] -} satisfies Meta; +} satisfies Meta; export default meta; type Story = StoryObj; diff --git a/packages/smart-forms-renderer/src/stories/itemTypes/Text.stories.tsx b/packages/smart-forms-renderer/src/stories/itemTypes/Text.stories.tsx index 2685a427c..2df17e712 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/Text.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/Text.stories.tsx @@ -16,16 +16,16 @@ */ import type { Meta, StoryObj } from '@storybook/react'; -import BuildFormWrapper from '../BuildFormWrapper'; +import BuildFormWrapperForStorybook from '../StorybookWrappers/BuildFormWrapperForStorybook'; import { qrTextBasicResponse, qTextBasic, qTextCalculation } from '../assets/questionnaires'; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export const meta = { title: 'Component/ItemType/Text', - component: BuildFormWrapper, + component: BuildFormWrapperForStorybook, // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs tags: [] -} satisfies Meta; +} satisfies Meta; export default meta; type Story = StoryObj; diff --git a/packages/smart-forms-renderer/src/stories/itemTypes/Time.stories.tsx b/packages/smart-forms-renderer/src/stories/itemTypes/Time.stories.tsx index 457179d27..3f80ee44e 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/Time.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/Time.stories.tsx @@ -16,16 +16,16 @@ */ import type { Meta, StoryObj } from '@storybook/react'; -import BuildFormWrapper from '../BuildFormWrapper'; +import BuildFormWrapperForStorybook from '../StorybookWrappers/BuildFormWrapperForStorybook'; import { qTimeBasic } from '../assets/questionnaires'; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export const meta = { title: 'Component/ItemType/Time', - component: BuildFormWrapper, + component: BuildFormWrapperForStorybook, // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs tags: [] -} satisfies Meta; +} satisfies Meta; export default meta; type Story = StoryObj; diff --git a/packages/smart-forms-renderer/src/stories/itemTypes/Url.stories.tsx b/packages/smart-forms-renderer/src/stories/itemTypes/Url.stories.tsx index 9ade52b6e..244fcedc0 100644 --- a/packages/smart-forms-renderer/src/stories/itemTypes/Url.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/itemTypes/Url.stories.tsx @@ -16,16 +16,16 @@ */ import type { Meta, StoryObj } from '@storybook/react'; -import BuildFormWrapper from '../BuildFormWrapper'; +import BuildFormWrapperForStorybook from '../StorybookWrappers/BuildFormWrapperForStorybook'; import { qUrlBasic } from '../assets/questionnaires'; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export const meta = { title: 'Component/ItemType/Url', - component: BuildFormWrapper, + component: BuildFormWrapperForStorybook, // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs tags: [] -} satisfies Meta; +} satisfies Meta; export default meta; type Story = StoryObj; diff --git a/packages/smart-forms-renderer/src/stories/populateUtilsForStorybook.ts b/packages/smart-forms-renderer/src/stories/populateUtilsForStorybook.ts deleted file mode 100644 index 622c28dee..000000000 --- a/packages/smart-forms-renderer/src/stories/populateUtilsForStorybook.ts +++ /dev/null @@ -1,545 +0,0 @@ -/* - * Copyright 2024 Commonwealth Scientific and Industrial Research - * Organisation (CSIRO) ABN 41 687 119 230. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import type { - Coding, - Expression, - Extension, - FhirResource, - OperationOutcome, - Parameters, - ParametersParameter, - Patient, - Practitioner, - Questionnaire, - QuestionnaireResponse, - Reference -} from 'fhir/r4'; -import type { - InputParameters, - IssuesParameter, - OutputParameters, - ResponseParameter -} from '@aehrc/sdc-populate'; -import { isInputParameters, isOutputParameters, populate } from '@aehrc/sdc-populate'; -import type { RequestConfig } from './populateCallbackForStorybook'; -import { fetchResourceCallback } from './populateCallbackForStorybook'; - -export interface PopulateResult { - populated: QuestionnaireResponse; - hasWarnings: boolean; -} - -export async function populateQuestionnaire( - questionnaire: Questionnaire, - patient: Patient, - user: Practitioner, - requestConfig: RequestConfig -): Promise<{ - populateSuccess: boolean; - populateResult: PopulateResult | null; -}> { - const fhirPathContext: Record = {}; - - // Get launch contexts, source queries and questionnaire-level variables - const launchContexts = getLaunchContexts(questionnaire); - const sourceQueries = getSourceQueries(questionnaire); - const questionnaireLevelVariables = getQuestionnaireLevelXFhirQueryVariables(questionnaire); - - if ( - launchContexts.length === 0 && - sourceQueries.length === 0 && - questionnaireLevelVariables.length === 0 - ) { - return { - populateSuccess: false, - populateResult: null - }; - } - - // Define population input parameters from launch contexts, source queries and questionnaire-level variables - const inputParameters = createPopulateInputParameters( - questionnaire, - patient, - user, - launchContexts, - sourceQueries, - questionnaireLevelVariables, - fhirPathContext - ); - - if (!inputParameters) { - return { - populateSuccess: false, - populateResult: null - }; - } - - if (!isInputParameters(inputParameters)) { - return { - populateSuccess: false, - populateResult: null - }; - } - - // Perform population if parameters satisfies input parameters - const outputParameters = await requestPopulate(inputParameters, requestConfig); - - if (outputParameters.resourceType === 'OperationOutcome') { - return { - populateSuccess: false, - populateResult: null - }; - } - - const responseParameter = outputParameters.parameter.find( - (param) => param.name === 'response' - ) as ResponseParameter; - const issuesParameter = outputParameters.parameter.find((param) => param.name === 'issues') as - | IssuesParameter - | undefined; - - if (issuesParameter) { - for (const issue of issuesParameter.resource.issue) { - if (issue.details?.text) { - console.warn(issue.details.text); - } - } - return { - populateSuccess: true, - populateResult: { - populated: responseParameter.resource, - hasWarnings: true - } - }; - } - - return { - populateSuccess: true, - populateResult: { - populated: responseParameter.resource, - hasWarnings: false - } - }; -} - -async function requestPopulate( - inputParameters: InputParameters, - requestConfig: RequestConfig -): Promise { - const populatePromise = populate(inputParameters, fetchResourceCallback, requestConfig); - - try { - const promiseResult = await addTimeoutToPromise(populatePromise, 10000); - - if (promiseResult.timeout) { - return { - resourceType: 'OperationOutcome', - issue: [ - { - severity: 'error', - code: 'timeout', - details: { text: '$populate operation timed out.' } - } - ] - }; - } - - if (isOutputParameters(promiseResult)) { - return promiseResult; - } - - return { - resourceType: 'OperationOutcome', - issue: [ - { - severity: 'error', - code: 'invalid', - details: { - text: 'Output parameters do not match the specification.' - } - } - ] - }; - } catch (error) { - console.error('Error:', error); - return { - resourceType: 'OperationOutcome', - issue: [ - { - severity: 'error', - code: 'unknown', - details: { text: 'An unknown error occurred.' } - } - ] - }; - } -} - -async function addTimeoutToPromise(promise: Promise, timeoutMs: number) { - const timeoutPromise = new Promise((_, reject) => { - setTimeout(() => { - reject(new Error(`Promise timed out after ${timeoutMs} milliseconds`)); - }, timeoutMs); - }); - - // Use Promise.race to wait for either the original promise or the timeout promise - return Promise.race([promise, timeoutPromise]); -} - -function isLaunchContext(extension: Extension): extension is LaunchContext { - const hasLaunchContextName = - extension.url === - 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-launchContext' && - !!extension.extension?.find( - (ext) => - ext.url === 'name' && - (ext.valueId || - (ext.valueCoding && - (ext.valueCoding.code === 'patient' || - ext.valueCoding.code === 'encounter' || - ext.valueCoding.code === 'location' || - ext.valueCoding.code === 'user' || - ext.valueCoding.code === 'study' || - ext.valueCoding.code === 'sourceQueries'))) - ); - - const hasLaunchContextType = !!extension.extension?.find( - (ext) => - ext.url === 'type' && - ext.valueCode && - (ext.valueCode === 'Patient' || - ext.valueCode === 'Practitioner' || - ext.valueCode === 'Encounter') - ); - - return ( - extension.url === - 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-launchContext' && - hasLaunchContextName && - hasLaunchContextType - ); -} - -function getLaunchContexts(questionnaire: Questionnaire): LaunchContext[] { - if (questionnaire.extension && questionnaire.extension.length > 0) { - return questionnaire.extension.filter((extension) => - isLaunchContext(extension) - ) as LaunchContext[]; - } - - return []; -} - -function isSourceQuery(extension: Extension): extension is SourceQuery { - return ( - extension.url === - 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-sourceQueries' && - !!extension.valueReference - ); -} - -function getSourceQueries(questionnaire: Questionnaire): SourceQuery[] { - if (questionnaire.extension && questionnaire.extension.length > 0) { - return questionnaire.extension.filter((extension) => isSourceQuery(extension)) as SourceQuery[]; - } - - return []; -} - -function isXFhirQueryVariable( - extension: Extension -): extension is QuestionnaireLevelXFhirQueryVariable { - return ( - extension.url === 'http://hl7.org/fhir/StructureDefinition/variable' && - !!extension.valueExpression?.name && - extension.valueExpression?.language === 'application/x-fhir-query' && - !!extension.valueExpression?.expression - ); -} - -function getQuestionnaireLevelXFhirQueryVariables( - questionnaire: Questionnaire -): QuestionnaireLevelXFhirQueryVariable[] { - if (questionnaire.extension && questionnaire.extension.length > 0) { - return questionnaire.extension.filter((extension) => - isXFhirQueryVariable(extension) - ) as QuestionnaireLevelXFhirQueryVariable[]; - } - - return []; -} - -// PopulateInputParameter private functions -function createPopulateInputParameters( - questionnaire: Questionnaire, - patient: Patient, - user: Practitioner, - launchContexts: LaunchContext[], - sourceQueries: SourceQuery[], - questionnaireLevelVariables: QuestionnaireLevelXFhirQueryVariable[], - fhirPathContext: Record -): Parameters | null { - const patientSubject = createPatientSubject(questionnaire, patient); - if (!patientSubject) { - return null; - } - - const inputParameters: Parameters = { - resourceType: 'Parameters', - parameter: [ - { - name: 'questionnaire', - resource: questionnaire - }, - { - name: 'subject', - valueReference: patientSubject - } - ] - }; - - // canonical - if (questionnaire.url) { - inputParameters.parameter?.push(createCanonicalParam(questionnaire.url)); - } - - // contexts - const contexts: ParametersParameter[] = []; - // add launch contexts - if (launchContexts.length > 0) { - for (const launchContext of launchContexts) { - const launchContextParam = createLaunchContextParam( - launchContext, - patient, - user, - fhirPathContext - ); - if (launchContextParam) { - contexts.push(launchContextParam); - } - } - } - - // add source queries - if (sourceQueries.length > 0) { - for (let index = 0; index < sourceQueries.length; index++) { - const sourceQuery = sourceQueries[index]; - contexts.push(createSourceQueryParams(sourceQuery, index)); - } - } - - // add questionnaire-level variables - if (questionnaireLevelVariables.length > 0) { - for (const variable of questionnaireLevelVariables) { - contexts.push(createVariableParam(variable)); - } - } - - if (contexts.length > 0) { - inputParameters.parameter?.push(...contexts); - } - - // local - inputParameters.parameter?.push(createLocalParam()); - - return inputParameters; -} - -function createPatientSubject(questionnaire: Questionnaire, patient: Patient): Reference | null { - const subjectTypes = questionnaire.subjectType; - - // If subjectTypes array is not empty AND "Patient" is not in the array, we cannot create a Patient subject reference. - if (subjectTypes && subjectTypes.length > 0) { - const patientSubject = subjectTypes.find((subject) => subject === 'Patient'); - if (!patientSubject) { - return null; - } - } - - return { - type: 'Patient', - reference: 'Patient/' + patient.id - }; -} - -function createCanonicalParam(canonicalUrl: string): ParametersParameter { - return { - name: 'canonical', - valueString: canonicalUrl - }; -} - -// setting local parameter as false as we are calling $populate with an NPM package, not a server -// package doesn't contain any fhir resources to "know" the context from -function createLocalParam(): ParametersParameter { - return { - name: 'local', - valueBoolean: false - }; -} - -function createLaunchContextParam( - launchContext: LaunchContext, - patient: Patient, - user: Practitioner, - fhirPathContext: Record -): ParametersParameter | null { - const name = launchContext.extension[0].valueId ?? launchContext.extension[0].valueCoding?.code; - if (!name) { - return null; - } - - const resourceType = launchContext.extension[1].valueCode; - let resource: FhirResource | null; - if (name === 'patient' && resourceType === 'Patient') { - resource = patient; - } else if (name === 'user' && resourceType === 'Practitioner') { - resource = user; - } else { - return null; - } - - if (!resource) { - return null; - } - - // Update fhirPathContext with launchContext resources - fhirPathContext[name] = resource; - - return { - name: 'context', - part: [ - { - name: 'name', - valueString: name - }, - { - name: 'content', - resource: resource - } - ] - }; -} - -function createSourceQueryParams(sourceQuery: SourceQuery, index: number): ParametersParameter { - const reference = sourceQuery.valueReference.reference; - if (reference && reference.startsWith('#')) { - const containedReference = reference.slice(1); - return { - name: 'context', - part: [ - { - name: 'name', - valueString: containedReference - }, - { - name: 'content', - valueReference: sourceQuery.valueReference - } - ] - }; - } - - // if sourceQuery cannot be referenced to a contained bundle, return itself as a context - // this most likely shouldn't happen - return { - name: 'context', - part: [ - { - name: 'name', - valueString: `sourceQuery${index}` - }, - { - name: 'content', - valueReference: sourceQuery.valueReference - } - ] - }; -} - -function createVariableParam(variable: QuestionnaireLevelXFhirQueryVariable): ParametersParameter { - const query = variable.valueExpression.expression; - const resourceType = query.split('?')[0]; - - return { - name: 'context', - part: [ - { - name: 'name', - valueString: variable.valueExpression.name - }, - { - name: 'content', - valueReference: { reference: query, type: resourceType } - } - ] - }; -} - -// interfaces -interface LaunchContext extends Extension { - url: 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-launchContext'; - extension: LaunchContextExtensions; -} - -type LaunchContextExtensions = - | [LaunchContextName, LaunchContextType] - | [LaunchContextName, LaunchContextType, LaunchContextDescription]; - -type LaunchContextName = LaunchContextNameId | LaunchContextNameCoding; - -// for backwards compatibility with old questionnaires (though it is not conformant) -interface LaunchContextNameId extends Extension { - url: 'name'; - valueId: string; -} - -interface LaunchContextNameCoding extends Extension { - url: 'name'; - valueCoding: LaunchContextNameCodingValueCoding; -} - -interface LaunchContextNameCodingValueCoding extends Coding { - code: 'patient' | 'encounter' | 'location' | 'user' | 'study'; -} - -interface LaunchContextType extends Extension { - url: 'type'; - valueCode: string; -} - -interface LaunchContextDescription extends Extension { - url: 'description'; - valueString: string; -} - -interface SourceQuery extends Extension { - url: 'http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-questionnaire-sourceQueries'; - valueReference: Reference; -} - -interface QuestionnaireLevelXFhirQueryVariable extends Extension { - url: 'http://hl7.org/fhir/StructureDefinition/variable'; - valueExpression: XFhirQueryVariableExpression; -} - -interface XFhirQueryVariableExpression extends Expression { - name: string; - language: 'application/x-fhir-query'; - expression: string; -} diff --git a/packages/smart-forms-renderer/src/stories/sdc/AdvancedAdditionalDisplayContent.stories.tsx b/packages/smart-forms-renderer/src/stories/sdc/AdvancedAdditionalDisplayContent.stories.tsx index cb4e90315..a0824fafb 100644 --- a/packages/smart-forms-renderer/src/stories/sdc/AdvancedAdditionalDisplayContent.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/sdc/AdvancedAdditionalDisplayContent.stories.tsx @@ -16,16 +16,16 @@ */ import type { Meta, StoryObj } from '@storybook/react'; -import BuildFormWrapper from '../BuildFormWrapper'; +import BuildFormWrapperForStorybook from '../StorybookWrappers/BuildFormWrapperForStorybook'; import { qEntryFormat, qQuestionnaireUnit, qShortText } from '../assets/questionnaires'; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export const meta = { title: 'Component/SDC/8.1.3 Advanced Additional Display Content', - component: BuildFormWrapper, + component: BuildFormWrapperForStorybook, // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs tags: [] -} satisfies Meta; +} satisfies Meta; export default meta; type Story = StoryObj; diff --git a/packages/smart-forms-renderer/src/stories/sdc/AdvancedControlAppearance.stories.tsx b/packages/smart-forms-renderer/src/stories/sdc/AdvancedControlAppearance.stories.tsx index 1b1c31588..336a07c53 100644 --- a/packages/smart-forms-renderer/src/stories/sdc/AdvancedControlAppearance.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/sdc/AdvancedControlAppearance.stories.tsx @@ -16,16 +16,16 @@ */ import type { Meta, StoryObj } from '@storybook/react'; -import BuildFormWrapper from '../BuildFormWrapper'; +import BuildFormWrapperForStorybook from '../StorybookWrappers/BuildFormWrapperForStorybook'; import { qChoiceOrientation, qItemControl, qSliderStepValue } from '../assets/questionnaires'; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export const meta = { title: 'Component/SDC/8.1.2 Advanced Control Appearance', - component: BuildFormWrapper, + component: BuildFormWrapperForStorybook, // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs tags: [] -} satisfies Meta; +} satisfies Meta; export default meta; type Story = StoryObj; diff --git a/packages/smart-forms-renderer/src/stories/sdc/AdvancedOther.stories.tsx b/packages/smart-forms-renderer/src/stories/sdc/AdvancedOther.stories.tsx index 3eb303e50..c29cb2b06 100644 --- a/packages/smart-forms-renderer/src/stories/sdc/AdvancedOther.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/sdc/AdvancedOther.stories.tsx @@ -16,7 +16,7 @@ */ import type { Meta, StoryObj } from '@storybook/react'; -import BuildFormWrapper from '../BuildFormWrapper'; +import BuildFormWrapperForStorybook from '../StorybookWrappers/BuildFormWrapperForStorybook'; import { qReadOnly, qRepeatsAutocomplete, @@ -29,10 +29,10 @@ import { // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export const meta = { title: 'Component/SDC/8.1.4 Advanced Other', - component: BuildFormWrapper, + component: BuildFormWrapperForStorybook, // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs tags: [] -} satisfies Meta; +} satisfies Meta; export default meta; type Story = StoryObj; diff --git a/packages/smart-forms-renderer/src/stories/sdc/AdvancedTextAppearance.stories.tsx b/packages/smart-forms-renderer/src/stories/sdc/AdvancedTextAppearance.stories.tsx index b668d1e92..87df9cf3b 100644 --- a/packages/smart-forms-renderer/src/stories/sdc/AdvancedTextAppearance.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/sdc/AdvancedTextAppearance.stories.tsx @@ -16,7 +16,7 @@ */ import type { Meta, StoryObj } from '@storybook/react'; -import BuildFormWrapper from '../BuildFormWrapper'; +import BuildFormWrapperForStorybook from '../StorybookWrappers/BuildFormWrapperForStorybook'; import { qDisplayCategoryInstructions, qHidden, @@ -29,10 +29,10 @@ import { // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export const meta = { title: 'Component/SDC/8.1.1 Advanced Text Appearance', - component: BuildFormWrapper, + component: BuildFormWrapperForStorybook, // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs tags: [] -} satisfies Meta; +} satisfies Meta; export default meta; type Story = StoryObj; diff --git a/packages/smart-forms-renderer/src/stories/sdc/BehaviorCalculations.stories.tsx b/packages/smart-forms-renderer/src/stories/sdc/BehaviorCalculations.stories.tsx index 9fb341dc3..d0637482d 100644 --- a/packages/smart-forms-renderer/src/stories/sdc/BehaviorCalculations.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/sdc/BehaviorCalculations.stories.tsx @@ -16,7 +16,7 @@ */ import type { Meta, StoryObj } from '@storybook/react'; -import BuildFormWrapper from '../BuildFormWrapper'; +import BuildFormWrapperForStorybook from '../StorybookWrappers/BuildFormWrapperForStorybook'; import { qCalculatedExpressionBMICalculator, qCalculatedExpressionCvdRiskCalculator, @@ -28,10 +28,10 @@ import { // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export const meta = { title: 'Component/SDC/9.1.3 Form Behavior Calculations', - component: BuildFormWrapper, + component: BuildFormWrapperForStorybook, // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs tags: [] -} satisfies Meta; +} satisfies Meta; export default meta; type Story = StoryObj; diff --git a/packages/smart-forms-renderer/src/stories/sdc/BehaviorChoiceRestriction.stories.tsx b/packages/smart-forms-renderer/src/stories/sdc/BehaviorChoiceRestriction.stories.tsx index e151c8921..64c7e429c 100644 --- a/packages/smart-forms-renderer/src/stories/sdc/BehaviorChoiceRestriction.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/sdc/BehaviorChoiceRestriction.stories.tsx @@ -16,7 +16,7 @@ */ import type { Meta, StoryObj } from '@storybook/react'; -import BuildFormWrapper from '../BuildFormWrapper'; +import BuildFormWrapperForStorybook from '../StorybookWrappers/BuildFormWrapperForStorybook'; import { qAnswerExpression, qAnswerOption, @@ -29,10 +29,10 @@ import { // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export const meta = { title: 'Component/SDC/9.1.2 Form Behavior Choice Restriction', - component: BuildFormWrapper, + component: BuildFormWrapperForStorybook, // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs tags: [] -} satisfies Meta; +} satisfies Meta; export default meta; type Story = StoryObj; diff --git a/packages/smart-forms-renderer/src/stories/sdc/BehaviorOther.stories.tsx b/packages/smart-forms-renderer/src/stories/sdc/BehaviorOther.stories.tsx index 8c0058f8d..c80366794 100644 --- a/packages/smart-forms-renderer/src/stories/sdc/BehaviorOther.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/sdc/BehaviorOther.stories.tsx @@ -16,7 +16,7 @@ */ import type { Meta, StoryObj } from '@storybook/react'; -import BuildFormWrapper from '../BuildFormWrapper'; +import BuildFormWrapperForStorybook from '../StorybookWrappers/BuildFormWrapperForStorybook'; import { qEnableBehaviorAll, qEnableBehaviorAny, @@ -31,10 +31,10 @@ import { // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export const meta = { title: 'Component/SDC/9.1.4 Form Behavior Other Control', - component: BuildFormWrapper, + component: BuildFormWrapperForStorybook, // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs tags: [] -} satisfies Meta; +} satisfies Meta; export default meta; type Story = StoryObj; diff --git a/packages/smart-forms-renderer/src/stories/sdc/BehaviorValueConstraints.stories.tsx b/packages/smart-forms-renderer/src/stories/sdc/BehaviorValueConstraints.stories.tsx index acc5777f4..7e2167d22 100644 --- a/packages/smart-forms-renderer/src/stories/sdc/BehaviorValueConstraints.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/sdc/BehaviorValueConstraints.stories.tsx @@ -16,7 +16,7 @@ */ import type { Meta, StoryObj } from '@storybook/react'; -import BuildFormWrapper from '../BuildFormWrapper'; +import BuildFormWrapperForStorybook from '../StorybookWrappers/BuildFormWrapperForStorybook'; import { qMaxDecimalPlaces, qMaxLength, @@ -35,10 +35,10 @@ import { // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export const meta = { title: 'Component/SDC/9.1.1 Form Behavior Value Constraints', - component: BuildFormWrapper, + component: BuildFormWrapperForStorybook, // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs tags: [] -} satisfies Meta; +} satisfies Meta; export default meta; type Story = StoryObj; diff --git a/packages/smart-forms-renderer/src/stories/sdc/FormPopulation.stories.tsx b/packages/smart-forms-renderer/src/stories/sdc/FormPopulation.stories.tsx index 4f4a2341d..ef6c845e5 100644 --- a/packages/smart-forms-renderer/src/stories/sdc/FormPopulation.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/sdc/FormPopulation.stories.tsx @@ -16,7 +16,7 @@ */ import type { Meta, StoryObj } from '@storybook/react'; -import PrePopWrapper from '../PrePopWrapper'; +import PrePopWrapperForStorybook from '../StorybookWrappers/PrePopWrapperForStorybook'; import { qCalculatedExpressionBMICalculatorPrepop, qCalculatedExpressionCvdRiskCalculatorPrepop, @@ -32,10 +32,10 @@ import { pracPrimaryPeter } from '../assets/practitioners/PracPrimaryPeter'; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export const meta = { title: 'Component/SDC/12 Form Population', - component: PrePopWrapper, + component: PrePopWrapperForStorybook, // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs tags: [] -} satisfies Meta; +} satisfies Meta; export default meta; type Story = StoryObj; diff --git a/packages/smart-forms-renderer/src/stories/sdc/ItemControlDisplay.stories.tsx b/packages/smart-forms-renderer/src/stories/sdc/ItemControlDisplay.stories.tsx index a80bebe86..b254da7fa 100644 --- a/packages/smart-forms-renderer/src/stories/sdc/ItemControlDisplay.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/sdc/ItemControlDisplay.stories.tsx @@ -16,7 +16,7 @@ */ import type { Meta, StoryObj } from '@storybook/react'; -import BuildFormWrapper from '../BuildFormWrapper'; +import BuildFormWrapperForStorybook from '../StorybookWrappers/BuildFormWrapperForStorybook'; import { qItemControlDisplayContextDisplay, qItemControlDisplayFlyover, @@ -28,10 +28,10 @@ import { // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export const meta = { title: 'Component/SDC/8.1.2 Advanced Control Appearance - Item Control Display', - component: BuildFormWrapper, + component: BuildFormWrapperForStorybook, // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs tags: [] -} satisfies Meta; +} satisfies Meta; export default meta; type Story = StoryObj; diff --git a/packages/smart-forms-renderer/src/stories/sdc/ItemControlGroup.stories.tsx b/packages/smart-forms-renderer/src/stories/sdc/ItemControlGroup.stories.tsx index 1b443b548..3bde38b62 100644 --- a/packages/smart-forms-renderer/src/stories/sdc/ItemControlGroup.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/sdc/ItemControlGroup.stories.tsx @@ -16,7 +16,7 @@ */ import type { Meta, StoryObj } from '@storybook/react'; -import BuildFormWrapper from '../BuildFormWrapper'; +import BuildFormWrapperForStorybook from '../StorybookWrappers/BuildFormWrapperForStorybook'; import { qItemControlDisplayTabContainer, qItemControlGroupGridMultiRow, @@ -27,10 +27,10 @@ import { // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export const meta = { title: 'Component/SDC/8.1.2 Advanced Control Appearance - Item Control Group', - component: BuildFormWrapper, + component: BuildFormWrapperForStorybook, // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs tags: [] -} satisfies Meta; +} satisfies Meta; export default meta; type Story = StoryObj; diff --git a/packages/smart-forms-renderer/src/stories/sdc/ItemControlQuestion.stories.tsx b/packages/smart-forms-renderer/src/stories/sdc/ItemControlQuestion.stories.tsx index 4ea5e5f25..67872d524 100644 --- a/packages/smart-forms-renderer/src/stories/sdc/ItemControlQuestion.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/sdc/ItemControlQuestion.stories.tsx @@ -16,7 +16,7 @@ */ import type { Meta, StoryObj } from '@storybook/react'; -import BuildFormWrapper from '../BuildFormWrapper'; +import BuildFormWrapperForStorybook from '../StorybookWrappers/BuildFormWrapperForStorybook'; import { qChoiceCheckboxAnswerOption, qChoiceCheckboxAnswerValueSet, @@ -35,10 +35,10 @@ import { // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export const meta = { title: 'Component/SDC/8.1.2 Advanced Control Appearance - Item Control Question', - component: BuildFormWrapper, + component: BuildFormWrapperForStorybook, // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs tags: [] -} satisfies Meta; +} satisfies Meta; export default meta; type Story = StoryObj; diff --git a/packages/smart-forms-renderer/src/stories/testing/BuildFormTesterWrapper.stories.tsx b/packages/smart-forms-renderer/src/stories/testing/BuildFormButtonTesterWrapper.stories.tsx similarity index 75% rename from packages/smart-forms-renderer/src/stories/testing/BuildFormTesterWrapper.stories.tsx rename to packages/smart-forms-renderer/src/stories/testing/BuildFormButtonTesterWrapper.stories.tsx index 4696b29b6..698845632 100644 --- a/packages/smart-forms-renderer/src/stories/testing/BuildFormTesterWrapper.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/testing/BuildFormButtonTesterWrapper.stories.tsx @@ -16,19 +16,16 @@ */ import type { Meta, StoryObj } from '@storybook/react'; -import BuildFormButtonTesterWrapper from '../BuildFormButtonTesterWrapper'; -import { - qBuildFormButtonTester, - qrBuildFormTesterResponse -} from '../assets/questionnaires/QBuildFormButtonTester'; +import BuildFormButtonTesterWrapperForStorybook from '../StorybookWrappers/BuildFormButtonTesterWrapperForStorybook'; +import { qButtonTester, qrButtonTesterResponse } from '../assets/questionnaires/QButtonTester'; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export const meta = { title: 'Component/Testing/Build Form Button Tester', - component: BuildFormButtonTesterWrapper, + component: BuildFormButtonTesterWrapperForStorybook, // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs tags: [] -} satisfies Meta; +} satisfies Meta; export default meta; type Story = StoryObj; @@ -37,7 +34,7 @@ type Story = StoryObj; export const BuildFormButtonTester: Story = { args: { - questionnaire: qBuildFormButtonTester, - questionnaireResponse: qrBuildFormTesterResponse + questionnaire: qButtonTester, + questionnaireResponse: qrButtonTesterResponse } }; diff --git a/packages/smart-forms-renderer/src/stories/testing/PrePopButtonTesterWrapper.stories.tsx b/packages/smart-forms-renderer/src/stories/testing/PrePopButtonTesterWrapper.stories.tsx new file mode 100644 index 000000000..f09148e96 --- /dev/null +++ b/packages/smart-forms-renderer/src/stories/testing/PrePopButtonTesterWrapper.stories.tsx @@ -0,0 +1,45 @@ +/* + * Copyright 2024 Commonwealth Scientific and Industrial Research + * Organisation (CSIRO) ABN 41 687 119 230. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { Meta, StoryObj } from '@storybook/react'; +import PrePopWrapperForStorybook from '../StorybookWrappers/PrePopWrapperForStorybook'; +import { mockFhirClient } from '../assets/fhirClient/mockFhirClient'; +import { patSmartForm } from '../assets/patients/PatSmartForm'; +import { pracPrimaryPeter } from '../assets/practitioners/PracPrimaryPeter'; +import { qButtonTester } from '../assets/questionnaires/QButtonTester'; + +// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export +const meta = { + title: 'Component/Testing/Pre Pop Button Tester', + component: PrePopWrapperForStorybook, + // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs + tags: [] +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +// More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args + +export const PrePopButtonTester: Story = { + args: { + questionnaire: qButtonTester, + fhirClient: mockFhirClient, + patient: patSmartForm, + user: pracPrimaryPeter + } +}; diff --git a/packages/smart-forms-renderer/src/stories/testing/ValidateFormTesterWrapper.stories.tsx b/packages/smart-forms-renderer/src/stories/testing/ValidateFormTesterWrapper.stories.tsx index dad0f0675..864401b88 100644 --- a/packages/smart-forms-renderer/src/stories/testing/ValidateFormTesterWrapper.stories.tsx +++ b/packages/smart-forms-renderer/src/stories/testing/ValidateFormTesterWrapper.stories.tsx @@ -16,12 +16,12 @@ */ import type { Meta, StoryObj } from '@storybook/react'; -import ValidationFormTesterWrapper from '../FormValidationTesterWrapper'; -import { qValidateFormButtonTester } from '../assets/questionnaires/QValidateFormButtonTester'; +import ValidationFormTesterWrapper from '../StorybookWrappers/FormValidationTesterWrapperForStorybook'; +import { qValidateTester } from '../assets/questionnaires/QValidateTester'; // More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export const meta = { - title: 'Component/Testing/Validate Form Button Tester', + title: 'Component/Testing/Validate Tester', component: ValidationFormTesterWrapper, // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs tags: [] @@ -32,8 +32,8 @@ type Story = StoryObj; // More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args -export const ValidateFormButtonTester: Story = { +export const ValidateTester: Story = { args: { - questionnaire: qValidateFormButtonTester + questionnaire: qValidateTester } }; diff --git a/packages/smart-forms-renderer/src/utils/manageForm.ts b/packages/smart-forms-renderer/src/utils/manageForm.ts index 5af8c469b..d39f26218 100644 --- a/packages/smart-forms-renderer/src/utils/manageForm.ts +++ b/packages/smart-forms-renderer/src/utils/manageForm.ts @@ -14,7 +14,7 @@ import type Client from 'fhirclient/lib/Client'; * @param questionnaireResponse - Pre-populated/draft/loaded QuestionnaireResponse to be rendered (optional) * @param readOnly - Applies read-only mode to all items in the form view * @param terminologyServerUrl - Terminology server url to fetch terminology. If not provided, the default terminology server will be used. (optional) - * @param additionalVariables - Additional key-value pair of SDC variables for testing (optional) + * @param additionalVariables - Additional key-value pair of SDC variables `Record` for testing (optional) * * @author Sean Fong */ diff --git a/packages/smart-forms-renderer/src/utils/tabs.ts b/packages/smart-forms-renderer/src/utils/tabs.ts index ba11e6114..4aebef202 100644 --- a/packages/smart-forms-renderer/src/utils/tabs.ts +++ b/packages/smart-forms-renderer/src/utils/tabs.ts @@ -106,7 +106,7 @@ export function isTab(item: QuestionnaireItem) { } /** - * Create a key-value pair for all tabbed items in a qItem array + * Create a `Record` key-value pair for all tabbed items in a qItem array * * @author Sean Fong */ diff --git a/packages/smart-forms-renderer/src/utils/validateQuestionnaire.ts b/packages/smart-forms-renderer/src/utils/validateQuestionnaire.ts index ac4292e63..4b689a0e4 100644 --- a/packages/smart-forms-renderer/src/utils/validateQuestionnaire.ts +++ b/packages/smart-forms-renderer/src/utils/validateQuestionnaire.ts @@ -39,6 +39,7 @@ import { structuredDataCapture } from 'fhir-sdc-helpers'; import type { RegexValidation } from '../interfaces/regex.interface'; import { parseDecimalStringToFloat } from './parseInputs'; import dayjs from 'dayjs'; +import { questionnaireStore } from '../stores'; export enum ValidationResult { unknown = 'unknown', // Unknown validation result @@ -85,9 +86,6 @@ export enum ValidationResult { interface ValidateQuestionnaireParams { questionnaire: Questionnaire; questionnaireResponse: QuestionnaireResponse; - enableWhenIsActivated: boolean; - enableWhenItems: EnableWhenItems; - enableWhenExpressions: EnableWhenExpressions; } /** @@ -99,23 +97,20 @@ interface ValidateQuestionnaireParams { export function validateQuestionnaire( params: ValidateQuestionnaireParams ): Record { - const { - questionnaire, - questionnaireResponse, - enableWhenIsActivated, - enableWhenItems, - enableWhenExpressions - } = params; + const { questionnaire, questionnaireResponse } = params; - if ( - !questionnaire.item || - questionnaire.item.length === 0 || - !questionnaireResponse.item || - questionnaireResponse.item.length === 0 - ) { + const enableWhenIsActivated = questionnaireStore.getState().enableWhenIsActivated; + const enableWhenItems = questionnaireStore.getState().enableWhenItems; + const enableWhenExpressions = questionnaireStore.getState().enableWhenExpressions; + + if (!questionnaire.item || questionnaire.item.length === 0) { return {}; } + if (!questionnaireResponse.item || questionnaireResponse.item.length === 0) { + questionnaireResponse.item = []; + } + const qItemsIndexMap = mapQItemsIndex(questionnaire); const topLevelQRItemsByIndex = getQrItemsIndex( questionnaire.item,