diff --git a/.vscode/settings.json b/.vscode/settings.json
index f2b1e2a..43a153a 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -19,11 +19,13 @@
"arraybuffer",
"authorised",
"clientside",
+ "commonmeta",
"dont",
"firstseen",
"jwalelset",
"languagedetector",
"localisation",
+ "metaname",
"middot",
"motd",
"multiline",
@@ -34,6 +36,7 @@
"singleline",
"submenu",
"testid",
+ "timeago",
"totalin",
"totalout",
"tsdoc",
diff --git a/craco.config.js b/craco.config.js
index b3383f1..76218fe 100644
--- a/craco.config.js
+++ b/craco.config.js
@@ -1,4 +1,6 @@
const CracoLessPlugin = require("craco-less");
+const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer");
+const WebpackBar = require("webpackbar");
module.exports = {
style: {
@@ -32,5 +34,14 @@
// TODO: run this for production builds, and add a separate command for it.
eslint: {
enable: false
- }
+ },
+
+ webpack: {
+ plugins: [
+ new WebpackBar({ profile: true }),
+ ...(process.env.NODE_ENV === "development" || process.env.FORCE_ANALYZE
+ ? [new BundleAnalyzerPlugin({ openAnalyzer: false })]
+ : []),
+ ],
+ },
};
diff --git a/package.json b/package.json
index aed7805..7477ebc 100644
--- a/package.json
+++ b/package.json
@@ -34,6 +34,7 @@
"react-i18next": "^11.8.6",
"react-redux": "^7.2.2",
"react-router-dom": "^5.2.0",
+ "react-timeago": "^5.2.0",
"react-world-flags": "^1.4.0",
"redux": "^4.0.5",
"semver": "^7.3.4",
@@ -46,6 +47,8 @@
"scripts": {
"start": "craco start",
"build": "craco build",
+ "optimise": "gzip -kr build/static",
+ "full-build": "npm run build; npm run optimise",
"test": "craco test"
},
"eslintConfig": {
@@ -74,6 +77,7 @@
"@types/react-dom": "^17.0.0",
"@types/react-redux": "^7.1.16",
"@types/react-router-dom": "^5.1.7",
+ "@types/react-timeago": "^4.1.2",
"@types/semver": "^7.3.4",
"@types/uuid": "^8.3.0",
"@types/webpack-env": "^1.16.0",
@@ -89,7 +93,9 @@
"react-scripts": "4.0.2",
"redux-devtools-extension": "^2.13.8",
"typescript": "^4.1.5",
- "utility-types": "^3.10.0"
+ "utility-types": "^3.10.0",
+ "webpack-bundle-analyzer": "^4.4.0",
+ "webpackbar": "^5.0.0-3"
},
"stylelint": {
"extends": "stylelint-config-recommended",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 9c1b819..b47f8e6 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -18,6 +18,7 @@
react-i18next: 11.8.6_i18next@19.8.7+react@17.0.1
react-redux: 7.2.2_380dc38591053d98779d1f25fc7202b9
react-router-dom: 5.2.0_react@17.0.1
+ react-timeago: 5.2.0_react@17.0.1
react-world-flags: 1.4.0_react@17.0.1
redux: 4.0.5
semver: 7.3.4
@@ -37,6 +38,7 @@
'@types/react-dom': 17.0.1
'@types/react-redux': 7.1.16
'@types/react-router-dom': 5.1.7
+ '@types/react-timeago': 4.1.2
'@types/semver': 7.3.4
'@types/uuid': 8.3.0
'@types/webpack-env': 1.16.0
@@ -53,6 +55,8 @@
redux-devtools-extension: 2.13.8_redux@4.0.5
typescript: 4.1.5
utility-types: 3.10.0
+ webpack-bundle-analyzer: 4.4.0
+ webpackbar: 5.0.0-3
lockfileVersion: 5.2
packages:
/@ant-design/colors/6.0.0:
@@ -226,7 +230,7 @@
integrity: sha512-zYoZC1uvebBFmj1wFAlXwt35JLEgecefATtKp20xalwEK8vHAixLBXTGxNrVGEmTT+gzOThUgr8UEdgtalc1BQ==
/@babel/helper-module-imports/7.12.13:
dependencies:
- '@babel/types': 7.12.13
+ '@babel/types': 7.12.17
dev: true
resolution:
integrity: sha512-NGmfvRp9Rqxy0uHSSVP+SRIW1q31a7Ji10cLBcqSDUngGentY4FRiHOFZFE1CLU5eiL0oE8reH7Tg1y99TDM/g==
@@ -1344,6 +1348,14 @@
dev: true
resolution:
integrity: sha512-oKrdZTld2im1z8bDwTOQvUbxKwE+854zc16qWZQlcTqMN00pWxHQ4ZeOq0yDMnisOpRykH2/5Qqcrk/OlbAjiQ==
+ /@babel/types/7.12.17:
+ dependencies:
+ '@babel/helper-validator-identifier': 7.12.11
+ lodash: 4.17.21
+ to-fast-properties: 2.0.0
+ dev: true
+ resolution:
+ integrity: sha512-tNMDjcv/4DIcHxErTgwB9q2ZcYyN0sUfgGKUK/mm1FJK7Wz+KstoEekxrl/tBiNDgLK1HGi+sppj1An/1DR4fQ==
/@bcoe/v8-coverage/0.2.3:
dev: true
resolution:
@@ -1721,6 +1733,10 @@
optional: true
resolution:
integrity: sha512-br5Qwvh8D2OQqSXpd1g/xqXKnK0r+Jz6qVKBbWmpUcrbGOxUrf39V5oZ1876084CGn18uMdR5uvPqBv9UqtBjQ==
+ /@polka/url/1.0.0-next.11:
+ dev: true
+ resolution:
+ integrity: sha512-3NsZsJIA/22P3QUyrEDNA2D133H4j224twJrdipXN38dpnIOzAbUDtOwkcJ5pXmn75w7LSQDjA4tO9dm1XlqlA==
/@rollup/plugin-node-resolve/7.1.3_rollup@1.32.1:
dependencies:
'@rollup/pluginutils': 3.1.0_rollup@1.32.1
@@ -2138,6 +2154,12 @@
dev: true
resolution:
integrity: sha512-ofHbZMlp0Y2baOHgsWBQ4K3AttxY61bDMkwTiBOkPg7U6C/3UwwB5WaIx28JmSVi/eX3uFEMRo61BV22fDQIvg==
+ /@types/react-timeago/4.1.2:
+ dependencies:
+ '@types/react': 17.0.2
+ dev: true
+ resolution:
+ integrity: sha512-gkhU3rH7aZgeRybbm9ie9wHOM9i1I5YhUoto/uqY/DAbeRZuLU8ugl6E97jp65XCl9QTij32Vs7BAX2E/MqOAw==
/@types/react/17.0.2:
dependencies:
'@types/prop-types': 15.7.3
@@ -2539,6 +2561,12 @@
node: '>=0.4.0'
resolution:
integrity: sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
+ /acorn-walk/8.0.2:
+ dev: true
+ engines:
+ node: '>=0.4.0'
+ resolution:
+ integrity: sha512-+bpA9MJsHdZ4bgfDcpk0ozQyhhVct7rzOmO0s1IIr0AGGgKBljss8n2zp11rRP2wid5VGeh04CgeKzgat5/25A==
/acorn/6.4.2:
dev: true
engines:
@@ -2553,6 +2581,13 @@
hasBin: true
resolution:
integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
+ /acorn/8.0.5:
+ dev: true
+ engines:
+ node: '>=0.4.0'
+ hasBin: true
+ resolution:
+ integrity: sha512-v+DieK/HJkJOpFBETDJioequtc3PfxsWMaxIdIwujtF7FEV/MAyDQLlm6/zPvr7Mix07mLh6ccVwIsloceodlg==
/address/1.1.2:
dev: true
engines:
@@ -3683,6 +3718,10 @@
dev: true
resolution:
integrity: sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==
+ /ci-info/3.1.1:
+ dev: true
+ resolution:
+ integrity: sha512-kdRWLBIJwdsYJWYJFtAFFYxybguqeF91qpZaggjG5Nf8QKdizFG2hjqvaTXbxFIcYbSaD74KpAXv6BSm17DHEQ==
/cipher-base/1.0.4:
dependencies:
inherits: 2.0.4
@@ -3829,6 +3868,12 @@
node: '>= 6'
resolution:
integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==
+ /commander/6.2.1:
+ dev: true
+ engines:
+ node: '>= 6'
+ resolution:
+ integrity: sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==
/common-tags/1.8.0:
dev: true
engines:
@@ -3900,6 +3945,10 @@
node: '>=0.8'
resolution:
integrity: sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==
+ /consola/2.15.3:
+ dev: true
+ resolution:
+ integrity: sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==
/console-browserify/1.2.0:
dev: true
resolution:
@@ -5549,6 +5598,14 @@
dev: true
resolution:
integrity: sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==
+ /figures/3.2.0:
+ dependencies:
+ escape-string-regexp: 1.0.5
+ dev: true
+ engines:
+ node: '>=8'
+ resolution:
+ integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==
/file-entry-cache/6.0.0:
dependencies:
flat-cache: 3.0.4
@@ -6014,6 +6071,14 @@
node: '>=6'
resolution:
integrity: sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA==
+ /gzip-size/6.0.0:
+ dependencies:
+ duplexer: 0.1.2
+ dev: true
+ engines:
+ node: '>=10'
+ resolution:
+ integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==
/handle-thing/2.0.1:
dev: true
resolution:
@@ -7861,6 +7926,10 @@
/lodash/4.17.20:
resolution:
integrity: sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==
+ /lodash/4.17.21:
+ dev: true
+ resolution:
+ integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
/loglevel/1.7.1:
dev: true
engines:
@@ -8073,6 +8142,13 @@
hasBin: true
resolution:
integrity: sha512-ft3WayFSFUVBuJj7BMLKAQcSlItKtfjsKDDsii3rqFDAZ7t11zRe8ASw/GlmivGwVUYtwkQrxiGGpL6gFvB0ag==
+ /mime/2.5.2:
+ dev: true
+ engines:
+ node: '>=4.0.0'
+ hasBin: true
+ resolution:
+ integrity: sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==
/mimic-fn/2.1.0:
dev: true
engines:
@@ -8622,6 +8698,11 @@
node: '>=8'
resolution:
integrity: sha512-Pxv+fKRsd/Ozflgn2Gjev1HZveJJeKR6hKKmdaImJMuEZ6htAvCTbcMABJo+qevlAelTLCrEK3YTKZ9fVTcSPw==
+ /opener/1.5.2:
+ dev: true
+ hasBin: true
+ resolution:
+ integrity: sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==
/opn/5.5.0:
dependencies:
is-wsl: 1.1.0
@@ -9816,6 +9897,12 @@
node: '>= 10'
resolution:
integrity: sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==
+ /pretty-time/1.1.0:
+ dev: true
+ engines:
+ node: '>=4'
+ resolution:
+ integrity: sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==
/process-nextick-args/2.0.1:
dev: true
resolution:
@@ -10754,6 +10841,14 @@
optional: true
resolution:
integrity: sha512-okaWNaGDGtnXyM2CLMUl8gYZnAubgxEulC40FYjsxn5bbj+G/mDINdy24wHz4Vypb/LWtIe8rdBU78k/74v8Mw==
+ /react-timeago/5.2.0_react@17.0.1:
+ dependencies:
+ react: 17.0.1
+ dev: false
+ peerDependencies:
+ react: ^16.0.0
+ resolution:
+ integrity: sha512-wCEEDGQHMdFh/PLp+Hj5vk9ZoC4KjQ5u0u6+KrrY9rny5LqJ2gZvNNEAS4mhSZDV1i7JLgQI5VQTAux7f+vj2w==
/react-world-flags/1.4.0_react@17.0.1:
dependencies:
react: 17.0.1
@@ -11580,6 +11675,16 @@
dev: true
resolution:
integrity: sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=
+ /sirv/1.0.11:
+ dependencies:
+ '@polka/url': 1.0.0-next.11
+ mime: 2.5.2
+ totalist: 1.1.0
+ dev: true
+ engines:
+ node: '>= 10'
+ resolution:
+ integrity: sha512-SR36i3/LSWja7AJNRBz4fF/Xjpn7lQFI30tZ434dIy+bitLYSP+ZEenHg36i23V2SGEz+kqjksg0uOGZ5LPiqg==
/sisteransi/1.0.5:
dev: true
resolution:
@@ -11840,6 +11945,12 @@
node: '>= 0.6'
resolution:
integrity: sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=
+ /std-env/2.3.0:
+ dependencies:
+ ci-info: 3.1.1
+ dev: true
+ resolution:
+ integrity: sha512-4qT5B45+Kjef2Z6pE0BkskzsH0GO7GrND0wGlTM1ioUe3v0dGYx9ZJH0Aro/YyA8fqQ5EyIKDRjZojJYMFTflw==
/stealthy-require/1.1.1:
dev: true
engines:
@@ -12349,6 +12460,12 @@
node: '>=0.6'
resolution:
integrity: sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==
+ /totalist/1.1.0:
+ dev: true
+ engines:
+ node: '>=6'
+ resolution:
+ integrity: sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g==
/tough-cookie/2.5.0:
dependencies:
psl: 1.8.0
@@ -12850,6 +12967,23 @@
node: '>=10.4'
resolution:
integrity: sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==
+ /webpack-bundle-analyzer/4.4.0:
+ dependencies:
+ acorn: 8.0.5
+ acorn-walk: 8.0.2
+ chalk: 4.1.0
+ commander: 6.2.1
+ gzip-size: 6.0.0
+ lodash: 4.17.21
+ opener: 1.5.2
+ sirv: 1.0.11
+ ws: 7.4.3
+ dev: true
+ engines:
+ node: '>= 10.13.0'
+ hasBin: true
+ resolution:
+ integrity: sha512-9DhNa+aXpqdHk8LkLPTBU/dMfl84Y+WE2+KnfI6rSpNRNVKa0VGLjPd2pjFubDeqnWmulFggxmWBxhfJXZnR0g==
/webpack-dev-middleware/3.7.3_webpack@4.44.2:
dependencies:
memory-fs: 0.4.1
@@ -12988,6 +13122,23 @@
optional: true
resolution:
integrity: sha512-6KJVGlCxYdISyurpQ0IPTklv+DULv05rs2hseIXer6D7KrUicRDLFb4IUM1S6LUAKypPM/nSiVSuv8jHu1m3/Q==
+ /webpackbar/5.0.0-3:
+ dependencies:
+ ansi-escapes: 4.3.1
+ chalk: 4.1.0
+ consola: 2.15.3
+ figures: 3.2.0
+ pretty-time: 1.1.0
+ std-env: 2.3.0
+ text-table: 0.2.0
+ wrap-ansi: 7.0.0
+ dev: true
+ engines:
+ node: '>=10'
+ peerDependencies:
+ webpack: 3 || 4 || 5
+ resolution:
+ integrity: sha512-viW6KCYjMb0NPoDrw2jAmLXU2dEOhRrtku28KmOfeE1vxbfwCYuTbTaMhnkrCZLFAFyY9Q49Z/jzYO80Dw5b8g==
/websocket-as-promised/2.0.1:
dependencies:
chnl: 1.2.0
@@ -13253,6 +13404,16 @@
node: '>=8'
resolution:
integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==
+ /wrap-ansi/7.0.0:
+ dependencies:
+ ansi-styles: 4.3.0
+ string-width: 4.2.0
+ strip-ansi: 6.0.0
+ dev: true
+ engines:
+ node: '>=10'
+ resolution:
+ integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
/wrappy/1.0.2:
dev: true
resolution:
@@ -13387,6 +13548,7 @@
'@types/react-dom': ^17.0.0
'@types/react-redux': ^7.1.16
'@types/react-router-dom': ^5.1.7
+ '@types/react-timeago': ^4.1.2
'@types/semver': ^7.3.4
'@types/uuid': ^8.3.0
'@types/webpack-env': ^1.16.0
@@ -13415,6 +13577,7 @@
react-refresh: ^0.9.0
react-router-dom: ^5.2.0
react-scripts: 4.0.2
+ react-timeago: ^5.2.0
react-world-flags: ^1.4.0
redux: ^4.0.5
redux-devtools-extension: ^2.13.8
@@ -13425,4 +13588,6 @@
utility-types: ^3.10.0
uuid: ^8.3.2
web-vitals: ^1.1.0
+ webpack-bundle-analyzer: ^4.4.0
+ webpackbar: ^5.0.0-3
websocket-as-promised: ^2.0.1
diff --git a/public/locales/en.json b/public/locales/en.json
index d4ab497..353e6ba 100644
--- a/public/locales/en.json
+++ b/public/locales/en.json
@@ -55,6 +55,13 @@
"copy": "Copy to clipboard",
"copied": "Copied!",
+ "pageNotFound": {
+ "resultTitle": "Page not found",
+ "buttonGoBack": "Go back"
+ },
+
+ "contextualAddressUnknown": "Unknown",
+
"typeahead": {
"emptyLabel": "No matches found.",
"paginationText": "Display additional results..."
@@ -199,6 +206,24 @@
"walletOverviewAddWallets": "Add wallets...",
"transactionsCardTitle": "Transactions",
+ "transactionItemID": "Transaction ID: {{id}}",
+ "transactionItemFrom": "<0>From:0> <1 />",
+ "transactionItemTo": "<0>To:0> <1 />",
+ "transactionItemName": "<0>Name:0> <1 />",
+ "transactionItemARecord": "<0>A record:0> <1 />",
+ "transactionItemARecordRemoved": "(removed)",
+ "transactionTypes": {
+ "transferred": "Transferred",
+ "sent": "Sent",
+ "received": "Received",
+ "mined": "Mined",
+ "name_a_record": "Updated name",
+ "name_transferred": "Moved name",
+ "name_sent": "Sent name",
+ "name_received": "Received name",
+ "name_purchased": "Purchased name",
+ "unknown": "Unknown"
+ },
"blockValueCardTitle": "Block Value",
"blockValueBaseValue": "Base value (<1>1>)",
diff --git a/src/components/ContextualAddress.less b/src/components/ContextualAddress.less
new file mode 100644
index 0000000..7b86b40
--- /dev/null
+++ b/src/components/ContextualAddress.less
@@ -0,0 +1,12 @@
+@import (reference) "../App.less";
+
+.contextual-address {
+ .address-metaname, .address-name, .address-raw-metaname, .address-original,
+ .address-wallet, .address-address {
+ white-space: nowrap;
+ }
+
+ .address-original {
+ opacity: 0.8;
+ }
+}
diff --git a/src/components/ContextualAddress.tsx b/src/components/ContextualAddress.tsx
new file mode 100644
index 0000000..260941b
--- /dev/null
+++ b/src/components/ContextualAddress.tsx
@@ -0,0 +1,93 @@
+import React from "react";
+import { Tooltip } from "antd";
+
+import { useTranslation } from "react-i18next";
+import { Link } from "react-router-dom";
+
+import { KristAddress } from "../krist/api/types";
+import { Wallet } from "../krist/wallets/Wallet";
+import { parseCommonMeta, CommonMeta } from "../utils/commonmeta";
+
+import { KristName } from "./KristName";
+
+import "./ContextualAddress.less";
+
+interface Props {
+ address: KristAddress | string | null;
+ wallet?: Wallet;
+ metadata?: string;
+ source?: boolean;
+ hideNameAddress?: boolean;
+}
+
+interface AddressMetanameProps {
+ address: string;
+ commonMeta: CommonMeta;
+ source: boolean;
+ hideNameAddress: boolean;
+}
+
+export function AddressMetaname({ address, commonMeta, source, hideNameAddress }: AddressMetanameProps): JSX.Element {
+ const rawMetaname = (source ? commonMeta?.return : commonMeta?.recipient) || undefined;
+ const metaname = (source ? commonMeta?.returnMetaname : commonMeta?.metaname) || undefined;
+ const name = (source ? commonMeta?.returnName : commonMeta?.name) || undefined;
+
+ // TODO: support custom suffixes
+ const nameWithoutSuffix = name ? name.replace(/\.kst$/, "") : undefined;
+
+ return name
+ ? <>
+ {/* Display the name/metaname (e.g. foo@bar.kst) */}
+ {metaname && <>{metaname}@>}
+