diff --git a/app/cypress/support/component.js b/app/cypress/support/component.js
index 03b30c0a..9be6f32d 100644
--- a/app/cypress/support/component.js
+++ b/app/cypress/support/component.js
@@ -14,10 +14,17 @@
// ***********************************************************
import './commands'
-import 'semantic-ui-offline/semantic.min.css';
-import {MemoryRouter, Route, Routes} from "react-router-dom";
+// Component tests mount real components, so they need the same styles the app loads.
+import '../../src/index.css';
+import '../../src/themes/fonts.css';
+import '../../src/themes/tokens.css';
+import '@mantine/core/styles.css';
+// react-router v7 ships these directly; `react-router-dom` is not installed.
+import {MemoryRouter, Route, Routes} from "react-router";
import {QueryProvider} from "../../src/hooks/customHooks";
import {TagsProvider} from "../../src/Tags";
+import {MantineProvider} from "@mantine/core";
+import {cssVariablesResolver, mantineTheme} from "../../src/themes/mantine";
import React from "react";
Cypress.on('uncaught:exception', (err, runnable) => {
@@ -31,8 +38,14 @@ Cypress.on('uncaught:exception', (err, runnable) => {
Cypress.Commands.add('mountWithRouter', (component, options) => {
options = options || {};
const initialEntries = options?.initialEntries || ['/'];
+ /*
+ * MantineProvider, configured exactly as ThemeProvider configures it. Every component
+ * in src/components/ui renders Mantine internals and throws without it -- the same
+ * thing that had to be added to test-utils.js for jest.
+ */
return cy.mount(
+
@@ -41,6 +54,7 @@ Cypress.Commands.add('mountWithRouter', (component, options) => {
+
,
options
);
diff --git a/app/package-lock.json b/app/package-lock.json
index 541073c2..40aafcc6 100644
--- a/app/package-lock.json
+++ b/app/package-lock.json
@@ -33,10 +33,7 @@
"react-qr-code": "^2.2.0",
"react-router": "^7.18.2",
"react-scripts": "5.0.1",
- "react-semantic-toasts-2": "^0.6.7",
"react-stl-viewer": "^2.5.0",
- "semantic-ui-offline": "^2.5.1",
- "semantic-ui-react": "^2.1.5",
"three": "^0.185",
"web-vitals": "^5.3.0"
},
@@ -3799,36 +3796,6 @@
"integrity": "sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==",
"license": "MIT"
},
- "node_modules/@fluentui/react-component-event-listener": {
- "version": "0.63.1",
- "resolved": "https://registry.npmjs.org/@fluentui/react-component-event-listener/-/react-component-event-listener-0.63.1.tgz",
- "integrity": "sha512-gSMdOh6tI3IJKZFqxfQwbTpskpME0CvxdxGM2tdglmf6ZPVDi0L4+KKIm+2dN8nzb8Ya1A8ZT+Ddq0KmZtwVQg==",
- "dependencies": {
- "@babel/runtime": "^7.10.4"
- },
- "peerDependencies": {
- "react": "^16.8.0 || ^17 || ^18",
- "react-dom": "^16.8.0 || ^17 || ^18"
- }
- },
- "node_modules/@fluentui/react-component-ref": {
- "version": "0.63.1",
- "resolved": "https://registry.npmjs.org/@fluentui/react-component-ref/-/react-component-ref-0.63.1.tgz",
- "integrity": "sha512-8MkXX4+R3i80msdbD4rFpEB4WWq2UDvGwG386g3ckIWbekdvN9z2kWAd9OXhRGqB7QeOsoAGWocp6gAMCivRlw==",
- "dependencies": {
- "@babel/runtime": "^7.10.4",
- "react-is": "^16.6.3"
- },
- "peerDependencies": {
- "react": "^16.8.0 || ^17 || ^18",
- "react-dom": "^16.8.0 || ^17 || ^18"
- }
- },
- "node_modules/@fluentui/react-component-ref/node_modules/react-is": {
- "version": "16.13.1",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
- "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
- },
"node_modules/@humanwhocodes/config-array": {
"version": "0.11.8",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz",
@@ -4905,16 +4872,6 @@
"url": "https://opencollective.com/webpack"
}
},
- "node_modules/@popperjs/core": {
- "version": "2.11.6",
- "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz",
- "integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==",
- "peer": true,
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/popperjs"
- }
- },
"node_modules/@react-three/fiber": {
"version": "8.16.5",
"resolved": "https://registry.npmjs.org/@react-three/fiber/-/fiber-8.16.5.tgz",
@@ -5153,19 +5110,6 @@
"resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz",
"integrity": "sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg=="
},
- "node_modules/@semantic-ui-react/event-stack": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/@semantic-ui-react/event-stack/-/event-stack-3.1.3.tgz",
- "integrity": "sha512-FdTmJyWvJaYinHrKRsMLDrz4tTMGdFfds299Qory53hBugiDvGC0tEJf+cHsi5igDwWb/CLOgOiChInHwq8URQ==",
- "dependencies": {
- "exenv": "^1.2.2",
- "prop-types": "^15.6.2"
- },
- "peerDependencies": {
- "react": "^16.0.0 || ^17.0.0 || ^18.0.0",
- "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0"
- }
- },
"node_modules/@sinclair/typebox": {
"version": "0.24.51",
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz",
@@ -7937,14 +7881,6 @@
"wrap-ansi": "^7.0.0"
}
},
- "node_modules/clsx": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
- "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==",
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/co": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
@@ -10453,11 +10389,6 @@
"node": ">=4"
}
},
- "node_modules/exenv": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz",
- "integrity": "sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw=="
- },
"node_modules/exit": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
@@ -14520,11 +14451,6 @@
"url": "https://github.com/chalk/supports-color?sponsor=1"
}
},
- "node_modules/jquery": {
- "version": "3.7.1",
- "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz",
- "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg=="
- },
"node_modules/js-sdsl": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz",
@@ -14706,11 +14632,6 @@
"integrity": "sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA==",
"license": "ISC"
},
- "node_modules/keyboard-key": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/keyboard-key/-/keyboard-key-1.1.0.tgz",
- "integrity": "sha512-qkBzPTi3rlAKvX7k0/ub44sqOfXeLc/jcnGGmj5c7BJpU8eDrEVPyhCvNYAaoubbsLm9uGWwQJO1ytQK1a9/dQ=="
- },
"node_modules/kind-of": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
@@ -14934,11 +14855,6 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz",
"integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q=="
},
- "node_modules/lodash-es": {
- "version": "4.18.1",
- "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.18.1.tgz",
- "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A=="
- },
"node_modules/lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
@@ -17592,7 +17508,6 @@
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
- "peer": true,
"dependencies": {
"loose-envify": "^1.4.0",
"object-assign": "^4.1.1",
@@ -18016,11 +17931,6 @@
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz",
"integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg=="
},
- "node_modules/react-fast-compare": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz",
- "integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA=="
- },
"node_modules/react-hotkeys-hook": {
"version": "5.3.3",
"resolved": "https://registry.npmjs.org/react-hotkeys-hook/-/react-hotkeys-hook-5.3.3.tgz",
@@ -18045,20 +17955,6 @@
"react-dom": "^0.14 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
- "node_modules/react-popper": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.3.0.tgz",
- "integrity": "sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==",
- "dependencies": {
- "react-fast-compare": "^3.0.1",
- "warning": "^4.0.2"
- },
- "peerDependencies": {
- "@popperjs/core": "^2.0.0",
- "react": "^16.8.0 || ^17 || ^18",
- "react-dom": "^16.8.0 || ^17 || ^18"
- }
- },
"node_modules/react-qr-code": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/react-qr-code/-/react-qr-code-2.2.0.tgz",
@@ -18252,16 +18148,6 @@
}
}
},
- "node_modules/react-semantic-toasts-2": {
- "version": "0.6.7",
- "resolved": "https://registry.npmjs.org/react-semantic-toasts-2/-/react-semantic-toasts-2-0.6.7.tgz",
- "integrity": "sha512-Mwcwu6DbozO8XOteOOXmicNywLwskX7XV98sG2cSZ02G/RIM2uRUZvx65nqIFp67CSe+tBU1wKVWvNascZQR/w==",
- "peerDependencies": {
- "prop-types": "^15.7.2",
- "react": "16.x.x || 17.x.x || 18.x.x",
- "semantic-ui-react": "*"
- }
- },
"node_modules/react-stl-viewer": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/react-stl-viewer/-/react-stl-viewer-2.5.0.tgz",
@@ -18978,39 +18864,6 @@
"node": ">=10"
}
},
- "node_modules/semantic-ui-offline": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/semantic-ui-offline/-/semantic-ui-offline-2.5.1.tgz",
- "integrity": "sha512-uwykZ0AF8rbKSsm6GIbQtAwLCKUexqKVX4qbbB1hvYNvOqhYdWqWMbTfrb3JLHYb19g9m6CEV6n+077AoVTUNg==",
- "dependencies": {
- "jquery": "^3.7.1"
- }
- },
- "node_modules/semantic-ui-react": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/semantic-ui-react/-/semantic-ui-react-2.1.5.tgz",
- "integrity": "sha512-nIqmmUNpFHfovEb+RI2w3E2/maZQutd8UIWyRjf1SLse+XF51hI559xbz/sLN3O6RpLjr/echLOOXwKCirPy3Q==",
- "peer": true,
- "dependencies": {
- "@babel/runtime": "^7.10.5",
- "@fluentui/react-component-event-listener": "~0.63.0",
- "@fluentui/react-component-ref": "~0.63.0",
- "@popperjs/core": "^2.6.0",
- "@semantic-ui-react/event-stack": "^3.1.3",
- "clsx": "^1.1.1",
- "keyboard-key": "^1.1.0",
- "lodash": "^4.17.21",
- "lodash-es": "^4.17.21",
- "prop-types": "^15.7.2",
- "react-is": "^16.8.6 || ^17.0.0 || ^18.0.0",
- "react-popper": "^2.3.0",
- "shallowequal": "^1.1.0"
- },
- "peerDependencies": {
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
- "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
- }
- },
"node_modules/semver": {
"version": "7.5.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
@@ -19210,11 +19063,6 @@
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
},
- "node_modules/shallowequal": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz",
- "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ=="
- },
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -20872,14 +20720,6 @@
"makeerror": "1.0.12"
}
},
- "node_modules/warning": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
- "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
- "dependencies": {
- "loose-envify": "^1.0.0"
- }
- },
"node_modules/watchpack": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz",
@@ -24434,30 +24274,6 @@
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.12.tgz",
"integrity": "sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww=="
},
- "@fluentui/react-component-event-listener": {
- "version": "0.63.1",
- "resolved": "https://registry.npmjs.org/@fluentui/react-component-event-listener/-/react-component-event-listener-0.63.1.tgz",
- "integrity": "sha512-gSMdOh6tI3IJKZFqxfQwbTpskpME0CvxdxGM2tdglmf6ZPVDi0L4+KKIm+2dN8nzb8Ya1A8ZT+Ddq0KmZtwVQg==",
- "requires": {
- "@babel/runtime": "^7.10.4"
- }
- },
- "@fluentui/react-component-ref": {
- "version": "0.63.1",
- "resolved": "https://registry.npmjs.org/@fluentui/react-component-ref/-/react-component-ref-0.63.1.tgz",
- "integrity": "sha512-8MkXX4+R3i80msdbD4rFpEB4WWq2UDvGwG386g3ckIWbekdvN9z2kWAd9OXhRGqB7QeOsoAGWocp6gAMCivRlw==",
- "requires": {
- "@babel/runtime": "^7.10.4",
- "react-is": "^16.6.3"
- },
- "dependencies": {
- "react-is": {
- "version": "16.13.1",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
- "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
- }
- }
- },
"@humanwhocodes/config-array": {
"version": "0.11.8",
"resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz",
@@ -25238,12 +25054,6 @@
}
}
},
- "@popperjs/core": {
- "version": "2.11.6",
- "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz",
- "integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==",
- "peer": true
- },
"@react-three/fiber": {
"version": "8.16.5",
"resolved": "https://registry.npmjs.org/@react-three/fiber/-/fiber-8.16.5.tgz",
@@ -25394,15 +25204,6 @@
"resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz",
"integrity": "sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg=="
},
- "@semantic-ui-react/event-stack": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/@semantic-ui-react/event-stack/-/event-stack-3.1.3.tgz",
- "integrity": "sha512-FdTmJyWvJaYinHrKRsMLDrz4tTMGdFfds299Qory53hBugiDvGC0tEJf+cHsi5igDwWb/CLOgOiChInHwq8URQ==",
- "requires": {
- "exenv": "^1.2.2",
- "prop-types": "^15.6.2"
- }
- },
"@sinclair/typebox": {
"version": "0.24.51",
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz",
@@ -27424,11 +27225,6 @@
"wrap-ansi": "^7.0.0"
}
},
- "clsx": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
- "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg=="
- },
"co": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
@@ -29229,11 +29025,6 @@
"pify": "^2.2.0"
}
},
- "exenv": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz",
- "integrity": "sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw=="
- },
"exit": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
@@ -32124,11 +31915,6 @@
}
}
},
- "jquery": {
- "version": "3.7.1",
- "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz",
- "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg=="
- },
"js-sdsl": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz",
@@ -32266,11 +32052,6 @@
"resolved": "https://registry.npmjs.org/kdbush/-/kdbush-4.0.2.tgz",
"integrity": "sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA=="
},
- "keyboard-key": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/keyboard-key/-/keyboard-key-1.1.0.tgz",
- "integrity": "sha512-qkBzPTi3rlAKvX7k0/ub44sqOfXeLc/jcnGGmj5c7BJpU8eDrEVPyhCvNYAaoubbsLm9uGWwQJO1ytQK1a9/dQ=="
- },
"kind-of": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
@@ -32428,11 +32209,6 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz",
"integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q=="
},
- "lodash-es": {
- "version": "4.18.1",
- "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.18.1.tgz",
- "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A=="
- },
"lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
@@ -34132,7 +33908,6 @@
"version": "15.8.1",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
- "peer": true,
"requires": {
"loose-envify": "^1.4.0",
"object-assign": "^4.1.1",
@@ -34443,11 +34218,6 @@
"resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz",
"integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg=="
},
- "react-fast-compare": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz",
- "integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA=="
- },
"react-hotkeys-hook": {
"version": "5.3.3",
"resolved": "https://registry.npmjs.org/react-hotkeys-hook/-/react-hotkeys-hook-5.3.3.tgz",
@@ -34465,15 +34235,6 @@
"integrity": "sha512-y8O2yHHj3w0aE9XO8d2BCcUOOdQTRSVq+WIuMlLVucAm5XNjJAy+BoOJiuQMldVYVOKTMyvVNfnbl2Oqp+YxGw==",
"requires": {}
},
- "react-popper": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-2.3.0.tgz",
- "integrity": "sha512-e1hj8lL3uM+sgSR4Lxzn5h1GxBlpa4CQz0XLF8kx4MDrDRWY0Ena4c97PUeSX9i5W3UAfDP0z0FXCTQkoXUl3Q==",
- "requires": {
- "react-fast-compare": "^3.0.1",
- "warning": "^4.0.2"
- }
- },
"react-qr-code": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/react-qr-code/-/react-qr-code-2.2.0.tgz",
@@ -34600,12 +34361,6 @@
"workbox-webpack-plugin": "^6.4.1"
}
},
- "react-semantic-toasts-2": {
- "version": "0.6.7",
- "resolved": "https://registry.npmjs.org/react-semantic-toasts-2/-/react-semantic-toasts-2-0.6.7.tgz",
- "integrity": "sha512-Mwcwu6DbozO8XOteOOXmicNywLwskX7XV98sG2cSZ02G/RIM2uRUZvx65nqIFp67CSe+tBU1wKVWvNascZQR/w==",
- "requires": {}
- },
"react-stl-viewer": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/react-stl-viewer/-/react-stl-viewer-2.5.0.tgz",
@@ -35081,35 +34836,6 @@
"node-forge": "^1"
}
},
- "semantic-ui-offline": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/semantic-ui-offline/-/semantic-ui-offline-2.5.1.tgz",
- "integrity": "sha512-uwykZ0AF8rbKSsm6GIbQtAwLCKUexqKVX4qbbB1hvYNvOqhYdWqWMbTfrb3JLHYb19g9m6CEV6n+077AoVTUNg==",
- "requires": {
- "jquery": "^3.7.1"
- }
- },
- "semantic-ui-react": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/semantic-ui-react/-/semantic-ui-react-2.1.5.tgz",
- "integrity": "sha512-nIqmmUNpFHfovEb+RI2w3E2/maZQutd8UIWyRjf1SLse+XF51hI559xbz/sLN3O6RpLjr/echLOOXwKCirPy3Q==",
- "peer": true,
- "requires": {
- "@babel/runtime": "^7.10.5",
- "@fluentui/react-component-event-listener": "~0.63.0",
- "@fluentui/react-component-ref": "~0.63.0",
- "@popperjs/core": "^2.6.0",
- "@semantic-ui-react/event-stack": "^3.1.3",
- "clsx": "^1.1.1",
- "keyboard-key": "^1.1.0",
- "lodash": "^4.17.21",
- "lodash-es": "^4.17.21",
- "prop-types": "^15.7.2",
- "react-is": "^16.8.6 || ^17.0.0 || ^18.0.0",
- "react-popper": "^2.3.0",
- "shallowequal": "^1.1.0"
- }
- },
"semver": {
"version": "7.5.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
@@ -35282,11 +35008,6 @@
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
},
- "shallowequal": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz",
- "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ=="
- },
"shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
@@ -36437,14 +36158,6 @@
"makeerror": "1.0.12"
}
},
- "warning": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
- "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
- "requires": {
- "loose-envify": "^1.0.0"
- }
- },
"watchpack": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz",
diff --git a/app/package.json b/app/package.json
index 2ed3275e..13b0fa90 100644
--- a/app/package.json
+++ b/app/package.json
@@ -28,10 +28,7 @@
"react-qr-code": "^2.2.0",
"react-router": "^7.18.2",
"react-scripts": "5.0.1",
- "react-semantic-toasts-2": "^0.6.7",
"react-stl-viewer": "^2.5.0",
- "semantic-ui-offline": "^2.5.1",
- "semantic-ui-react": "^2.1.5",
"three": "^0.185",
"web-vitals": "^5.3.0"
},
diff --git a/app/src/components/Download.cy.js b/app/src/components/Download.cy.js
index 39195b35..cb03ca71 100644
--- a/app/src/components/Download.cy.js
+++ b/app/src/components/Download.cy.js
@@ -1,6 +1,5 @@
import React from 'react';
import {ArchiveDownloadForm, ChannelDownloadForm, EditRSSDownloadForm} from './Download';
-import 'semantic-ui-offline/semantic.min.css';
describe('', () => {
beforeEach(() => {
diff --git a/app/src/components/collections/BatchReorganizeModal.test.js b/app/src/components/collections/BatchReorganizeModal.test.js
index f434eae4..0945e77f 100644
--- a/app/src/components/collections/BatchReorganizeModal.test.js
+++ b/app/src/components/collections/BatchReorganizeModal.test.js
@@ -11,10 +11,6 @@ jest.mock('../../api', () => ({
getBatchReorganizationStatus: jest.fn(),
}));
-// Mock react-semantic-toasts-2
-jest.mock('react-semantic-toasts-2', () => ({
- toast: jest.fn(),
-}));
// Mock the FileWorkerStatusContext
jest.mock('../../contexts/FileWorkerStatusContext', () => ({
diff --git a/app/src/components/collections/CollectionReorganizeModal.test.js b/app/src/components/collections/CollectionReorganizeModal.test.js
index 1e5aab9e..b34ab6f7 100644
--- a/app/src/components/collections/CollectionReorganizeModal.test.js
+++ b/app/src/components/collections/CollectionReorganizeModal.test.js
@@ -11,10 +11,6 @@ jest.mock('../../api', () => ({
getReorganizationStatus: jest.fn(),
}));
-// Mock react-semantic-toasts-2
-jest.mock('react-semantic-toasts-2', () => ({
- toast: jest.fn(),
-}));
// Mock the FileWorkerStatusContext - default mock returns inactive state
jest.mock('../../contexts/FileWorkerStatusContext', () => ({
diff --git a/app/src/components/collections/ConflictResolutionModal.test.js b/app/src/components/collections/ConflictResolutionModal.test.js
index 27a90054..2ecd200a 100644
--- a/app/src/components/collections/ConflictResolutionModal.test.js
+++ b/app/src/components/collections/ConflictResolutionModal.test.js
@@ -9,10 +9,6 @@ jest.mock('../../api', () => ({
deleteFileGroups: jest.fn(),
}));
-// Mock react-semantic-toasts-2
-jest.mock('react-semantic-toasts-2', () => ({
- toast: jest.fn(),
-}));
describe('ConflictResolutionModal', () => {
const mockConflicts = [
diff --git a/app/src/hooks/useSubsystemToggle.test.js b/app/src/hooks/useSubsystemToggle.test.js
index d08c241f..ec8c9be6 100644
--- a/app/src/hooks/useSubsystemToggle.test.js
+++ b/app/src/hooks/useSubsystemToggle.test.js
@@ -17,7 +17,6 @@ jest.mock('../api/controller', () => ({
getControllerStats: jest.fn().mockResolvedValue({}),
}));
-jest.mock('react-semantic-toasts-2', () => ({toast: jest.fn()}));
const controllerApi = require('../api/controller');
diff --git a/app/src/semantic-baseline.test.js b/app/src/semantic-baseline.test.js
index 92c20ab1..a55d7c3c 100644
--- a/app/src/semantic-baseline.test.js
+++ b/app/src/semantic-baseline.test.js
@@ -3,20 +3,20 @@ import path from 'path';
import baseline from './semantic-baseline.json';
/*
- * A ratchet for the Semantic UI removal.
+ * Semantic UI is gone, and this keeps it gone.
*
- * semantic-baseline.json lists every file that still imports Semantic UI (or the
- * Semantic-based toast library). This test fails if a file not on that list
- * starts importing them, and asks for the list to shrink when a file stops.
+ * It began as a ratchet: semantic-baseline.json listed the 75 files still importing
+ * Semantic UI, the list only shrank, and adding a file to it failed the build. The list
+ * reached zero, the three packages are uninstalled, and the baseline is now an empty
+ * array kept only so a reintroduction has to delete a file rather than edit one.
*
- * It replaces an ESLint rule deliberately: `no-restricted-imports` would either
- * print 75 warnings on every dev rebuild, or fail the build outright, and CI
- * already unsets CI= for the build step so warnings there guard nothing.
+ * The assertions below are cheap and each one caught something real during the migration,
+ * so they stay: an import would now fail to resolve, but a `className="ui button"` or a
+ * reach back through Theme.tsx would not, and neither would reinstalling a package.
*
- * The list has reached zero. The test stays as a guard rather than being deleted: it now
- * asserts that nothing imports Semantic UI, nothing calls its toast library, nothing leans
- * on its stylesheet, and no migrated file reaches back through Theme.tsx. It can go when
- * the packages themselves are uninstalled.
+ * It is a test rather than an ESLint rule deliberately: `no-restricted-imports` would
+ * either print dozens of warnings on every dev rebuild or fail the build outright, and CI
+ * unsets CI= for its build step, so warnings there guard nothing.
*/
const SRC = path.join(__dirname);
@@ -109,10 +109,26 @@ describe('Semantic UI removal', () => {
expect(leaks).toEqual([]);
});
- it('reports how much of the migration is left', () => {
- // Not an assertion so much as a progress readout in the test output.
- const remaining = importers().length;
- expect(remaining).toBeLessThanOrEqual(baseline.length);
- console.log(`Semantic UI: ${remaining} files remaining to migrate.`);
+ it('has no Semantic package installed', () => {
+ /*
+ * The three packages are uninstalled. An import of a missing module fails loudly,
+ * so this guards the quieter mistake: someone reinstalling one -- to "just use a
+ * Semantic component for this one thing" -- which would drag the whole library and
+ * its 300kB stylesheet back into the bundle.
+ */
+ const pkg = JSON.parse(
+ fs.readFileSync(path.join(SRC, '..', 'package.json'), 'utf8'));
+ const named = [...Object.keys(pkg.dependencies || {}),
+ ...Object.keys(pkg.devDependencies || {})]
+ .filter(name => /semantic/i.test(name));
+
+ expect(named).toEqual([]);
+ });
+
+ it('keeps the baseline empty', () => {
+ // The migration is finished; the file stays as an empty list so that putting a
+ // name back requires a deliberate edit.
+ expect(baseline).toEqual([]);
+ expect(importers()).toEqual([]);
});
});