From 28468e134c80ff0733a3c407bc1a0a8f8389e24e Mon Sep 17 00:00:00 2001 From: Tim Down <158919+timdown@users.noreply.github.com> Date: Wed, 9 Apr 2025 09:36:07 +0100 Subject: [PATCH 001/170] Merge pull request #24660 from overleaf/td-bs5-remove-react-bootstrap-0 Remove react-bootstrap 0.33.1 GitOrigin-RevId: c320a6b18c576afdc0fd49559915d3d2f3a7a1ef --- package-lock.json | 128 --- services/web/.storybook/preview.tsx | 38 +- .../utils/with-bootstrap-switcher.tsx | 20 - services/web/cypress/support/ct/window.ts | 1 - .../components/file-tree-context-menu.tsx | 19 - .../components/change-list/change-list.tsx | 5 +- .../change-list/dropdown/actions-dropdown.tsx | 22 +- .../dropdown/compare-version-dropdown.tsx | 1 - .../change-list/dropdown/history-dropdown.tsx | 1 - .../make-primary/confirmation-modal.tsx | 3 +- .../reconfirmation-info-prompt-text.tsx | 3 - .../dashboard/group-settings-button.tsx | 44 +- .../dashboard/leave-group-modal.tsx | 5 - .../dashboard/managed-group-subscriptions.tsx | 6 +- ...rsonal-subscription-recurly-sync-email.tsx | 3 - .../components/dashboard/row-link.tsx | 24 +- .../dashboard/states/active/active-new.tsx | 14 +- .../cancel-plan/downgrade-plan-button.tsx | 3 - .../cancel-plan/extend-trial-button.tsx | 3 - .../modals/cancel-ai-add-on-modal.tsx | 5 - .../modals/change-to-group-modal.tsx | 14 +- .../modals/confirm-change-plan-modal.tsx | 5 - .../modals/keep-current-plan-modal.tsx | 5 - .../bootstrap-3/dropdown-menu-with-ref.tsx | 71 -- .../dropdown-toggle-with-tooltip.tsx | 53 - .../bootstrap-3/form/form-control.tsx | 21 - .../bootstrap-3/toast-container.tsx | 14 - .../ui/components/bootstrap-3/toast.tsx | 51 - .../bootstrap-3/toggle-button-group.tsx | 99 -- .../bootstrap-version-switcher.tsx | 15 - .../ui/components/ol/icons/ol-tag-icon.tsx | 9 +- .../js/features/ui/components/ol/ol-badge.tsx | 37 +- .../ui/components/ol/ol-button-group.tsx | 27 +- .../ui/components/ol/ol-button-toolbar.tsx | 28 +- .../features/ui/components/ol/ol-button.tsx | 127 +-- .../js/features/ui/components/ol/ol-card.tsx | 13 +- .../ui/components/ol/ol-close-button.tsx | 22 +- .../js/features/ui/components/ol/ol-col.tsx | 70 +- .../components/ol/ol-dropdown-menu-item.tsx | 38 +- .../ui/components/ol/ol-form-checkbox.tsx | 135 +-- .../ui/components/ol/ol-form-control.tsx | 81 +- .../ui/components/ol/ol-form-feedback.tsx | 28 +- .../ui/components/ol/ol-form-group.tsx | 38 +- .../ui/components/ol/ol-form-label.tsx | 25 +- .../ui/components/ol/ol-form-select.tsx | 51 +- .../ui/components/ol/ol-form-switch.tsx | 48 +- .../ui/components/ol/ol-form-text.tsx | 31 +- .../js/features/ui/components/ol/ol-form.tsx | 41 +- .../ui/components/ol/ol-icon-button.tsx | 45 +- .../ui/components/ol/ol-list-group-item.tsx | 39 +- .../ui/components/ol/ol-list-group.tsx | 31 +- .../js/features/ui/components/ol/ol-modal.tsx | 126 +-- .../ui/components/ol/ol-notification.tsx | 40 +- .../features/ui/components/ol/ol-overlay.tsx | 58 +- .../ui/components/ol/ol-page-content-card.tsx | 14 +- .../features/ui/components/ol/ol-popover.tsx | 75 +- .../js/features/ui/components/ol/ol-row.tsx | 13 +- .../features/ui/components/ol/ol-spinner.tsx | 25 +- .../js/features/ui/components/ol/ol-table.tsx | 29 +- .../js/features/ui/components/ol/ol-tag.tsx | 31 +- .../ui/components/ol/ol-toast-container.tsx | 18 +- .../js/features/ui/components/ol/ol-toast.tsx | 35 +- .../components/ol/ol-toggle-button-group.tsx | 39 +- .../ui/components/ol/ol-toggle-button.tsx | 45 +- .../features/ui/components/ol/ol-tooltip.tsx | 45 +- .../frontend/js/features/utils/bootstrap-5.ts | 26 - .../js/shared/components/accessible-modal.tsx | 30 - .../frontend/js/shared/components/badge.tsx | 29 - .../js/shared/components/beta-badge-icon.tsx | 23 +- .../js/shared/components/beta-badge.tsx | 5 +- .../frontend/js/shared/components/close.tsx | 14 +- .../shared/components/controlled-dropdown.tsx | 58 -- .../shared/components/copy-to-clipboard.tsx | 8 +- .../generic-error-boundary-fallback.tsx | 27 +- .../frontend/js/shared/components/icon.tsx | 5 +- .../labs/labs-experiments-widget.tsx | 8 +- .../js/shared/components/loading-spinner.tsx | 13 +- .../js/shared/components/material-icon.tsx | 5 +- .../frontend/js/shared/components/select.tsx | 209 ++-- .../web/frontend/js/shared/components/tag.tsx | 56 - .../frontend/js/shared/components/tooltip.tsx | 57 -- .../js/shared/components/upgrade-benefits.jsx | 9 +- .../stories/contact-us-modal.stories.tsx | 60 +- .../web/frontend/stories/dropdown.stories.jsx | 45 - .../stories/feedback-badge.stories.tsx | 4 - .../frontend/stories/input-switch.stories.tsx | 7 +- .../stories/loading/loading.stories.tsx | 2 - .../web/frontend/stories/menu-bar.stories.tsx | 3 - .../unsaved-docs-locked-modal.stories.tsx | 7 - .../frontend/stories/pdf-preview.stories.jsx | 10 +- .../project-list/add-affiliation.stories.tsx | 3 - .../project-list/color-picker.stories.tsx | 3 - ...mpile-and-download-project-pdf.stories.tsx | 3 - .../current-plan-widget.stories.tsx | 3 - .../project-list/inr-banner.stories.tsx | 3 - .../new-project-button.stories.tsx | 3 - .../project-list/notifications.stories.tsx | 3 - .../project-list/project-list.stories.tsx | 3 - .../project-list/project-search.stories.tsx | 3 - .../project-list/survey-widget.stories.tsx | 3 - .../project-list/system-messages.stories.tsx | 3 - .../start-free-trial-button.stories.jsx | 4 - .../frontend/stories/style-guide.stories.jsx | 962 ------------------ .../group-invites/group-invites.stories.tsx | 2 - .../frontend/stories/ui/badge-bs3.stories.tsx | 59 -- ...adge-bs5.stories.tsx => badge.stories.tsx} | 5 +- .../frontend/stories/ui/button.stories.tsx | 7 +- .../stories/ui/dropdown-menu.stories.tsx | 5 +- .../ui/form/form-check-bs5.stories.tsx | 5 +- .../ui/form/form-input-bs5.stories.tsx | 5 +- .../ui/form/form-radio-bs5.stories.tsx | 5 +- .../ui/form/form-select-bs5.stories.tsx | 5 +- .../ui/form/form-textarea-bs5.stories.tsx | 5 +- .../stories/ui/icon-button.stories.tsx | 5 +- .../web/frontend/stories/ui/row.stories.tsx | 5 +- .../stories/ui/split-button.stories.tsx | 5 +- .../frontend/stories/ui/tag-bs3.stories.tsx | 70 -- .../{tag-bs5.stories.tsx => tag.stories.tsx} | 5 +- .../frontend/stories/ui/tooltip.stories.tsx | 19 +- .../stories/upgrade-prompt.stories.tsx | 5 - .../bootstrap-5/components/button.scss | 8 - .../bootstrap-5/pages/onboarding.scss | 4 - services/web/package.json | 3 - .../shared/accessible-modal.spec.tsx | 36 - .../components/shared/select.spec.tsx | 16 +- .../components/shared/tooltip.spec.tsx | 8 +- .../components/notifications.test.tsx | 13 +- .../components/project-list-title.tsx | 3 - .../project-tools-rename.test.tsx | 11 - .../components/share-project-modal.test.jsx | 5 - .../components/dashboard/pause-modal.test.tsx | 1 - .../dashboard/states/active/active.test.tsx | 12 +- .../group-invite/accepted-invite.test.tsx | 64 +- .../group-invite/group-invite.test.tsx | 181 ++-- .../web/test/frontend/helpers/bootstrap-3.ts | 5 - .../web/test/frontend/helpers/reset-meta.ts | 1 - 136 files changed, 428 insertions(+), 4132 deletions(-) delete mode 100644 services/web/.storybook/utils/with-bootstrap-switcher.tsx delete mode 100644 services/web/frontend/js/features/ui/components/bootstrap-3/dropdown-menu-with-ref.tsx delete mode 100644 services/web/frontend/js/features/ui/components/bootstrap-3/dropdown-toggle-with-tooltip.tsx delete mode 100644 services/web/frontend/js/features/ui/components/bootstrap-3/form/form-control.tsx delete mode 100644 services/web/frontend/js/features/ui/components/bootstrap-3/toast-container.tsx delete mode 100644 services/web/frontend/js/features/ui/components/bootstrap-3/toast.tsx delete mode 100644 services/web/frontend/js/features/ui/components/bootstrap-3/toggle-button-group.tsx delete mode 100644 services/web/frontend/js/features/ui/components/bootstrap-5/bootstrap-version-switcher.tsx delete mode 100644 services/web/frontend/js/features/utils/bootstrap-5.ts delete mode 100644 services/web/frontend/js/shared/components/accessible-modal.tsx delete mode 100644 services/web/frontend/js/shared/components/badge.tsx delete mode 100644 services/web/frontend/js/shared/components/controlled-dropdown.tsx delete mode 100644 services/web/frontend/js/shared/components/tag.tsx delete mode 100644 services/web/frontend/js/shared/components/tooltip.tsx delete mode 100644 services/web/frontend/stories/dropdown.stories.jsx delete mode 100644 services/web/frontend/stories/style-guide.stories.jsx delete mode 100644 services/web/frontend/stories/ui/badge-bs3.stories.tsx rename services/web/frontend/stories/ui/{badge-bs5.stories.tsx => badge.stories.tsx} (92%) delete mode 100644 services/web/frontend/stories/ui/tag-bs3.stories.tsx rename services/web/frontend/stories/ui/{tag-bs5.stories.tsx => tag.stories.tsx} (93%) delete mode 100644 services/web/test/frontend/components/shared/accessible-modal.spec.tsx delete mode 100644 services/web/test/frontend/helpers/bootstrap-3.ts diff --git a/package-lock.json b/package-lock.json index 5f0eb0baf1..bd3eb0b2e9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3267,27 +3267,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/runtime-corejs2": { - "version": "7.16.7", - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs2/-/runtime-corejs2-7.16.7.tgz", - "integrity": "sha512-ec0BM0J/9M5Cncha++AlgvvDlk+uM+m6f7K0t74ClcYzsE8LgX4RstRreksMSCI82o3LJS//UswmA0pUWkJpqg==", - "dev": true, - "dependencies": { - "core-js": "^2.6.5", - "regenerator-runtime": "^0.13.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/runtime-corejs2/node_modules/core-js": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", - "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", - "deprecated": "core-js@<3.4 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Please, upgrade your dependencies to the actual version of core-js.", - "dev": true, - "hasInstallScript": true - }, "node_modules/@babel/runtime-corejs3": { "version": "7.16.8", "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.16.8.tgz", @@ -12634,16 +12613,6 @@ "@types/react": "*" } }, - "node_modules/@types/react-overlays": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@types/react-overlays/-/react-overlays-1.1.3.tgz", - "integrity": "sha512-oOq5NWbyfNz2w2sKvjkHdvGQSMA+VDVfI5UOfGPR0wkik2welad1RDVnVgH15jKf58jrZNBa1Ee4SVBgCGFxCg==", - "dev": true, - "dependencies": { - "@types/react": "*", - "@types/react-transition-group": "*" - } - }, "node_modules/@types/react-redux": { "version": "7.1.33", "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.33.tgz", @@ -19802,15 +19771,6 @@ "utila": "~0.4" } }, - "node_modules/dom-helpers": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz", - "integrity": "sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.1.2" - } - }, "node_modules/dom-serializer": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", @@ -27577,12 +27537,6 @@ "node": ">=12.0.0" } }, - "node_modules/keycode": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/keycode/-/keycode-2.2.1.tgz", - "integrity": "sha512-Rdgz9Hl9Iv4QKi8b0OlCRQEzp4AgVxyCtz5S/+VIHezDmrDhkp2N2TqBWOLz0/gbeREXOOiI9/4b8BY9uw2vFg==", - "dev": true - }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -34620,30 +34574,6 @@ "react": ">=16.4.1" } }, - "node_modules/react-bootstrap": { - "version": "0.33.1", - "resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-0.33.1.tgz", - "integrity": "sha512-qWTRravSds87P8WC82tETy2yIso8qDqlIm0czsrduCaYAFtHuyLu0XDbUlfLXeRzqgwm5sRk2wRaTNoiVkk/YQ==", - "dev": true, - "dependencies": { - "@babel/runtime-corejs2": "^7.0.0", - "classnames": "^2.2.5", - "dom-helpers": "^3.2.0", - "invariant": "^2.2.4", - "keycode": "^2.2.0", - "prop-types": "^15.6.1", - "prop-types-extra": "^1.0.1", - "react-overlays": "^0.9.0", - "react-prop-types": "^0.4.0", - "react-transition-group": "^2.0.0", - "uncontrollable": "^7.0.2", - "warning": "^3.0.0" - }, - "peerDependencies": { - "react": ">=16.3.0", - "react-dom": ">=16.3.0" - } - }, "node_modules/react-chartjs-2": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-5.0.1.tgz", @@ -34849,36 +34779,6 @@ "uc.micro": "^1.0.1" } }, - "node_modules/react-overlays": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/react-overlays/-/react-overlays-0.9.3.tgz", - "integrity": "sha512-u2T7nOLnK+Hrntho4p0Nxh+BsJl0bl4Xuwj/Y0a56xywLMetgAfyjnDVrudLXsNcKGaspoC+t3C1V80W9QQTdQ==", - "dev": true, - "dependencies": { - "classnames": "^2.2.5", - "dom-helpers": "^3.2.1", - "prop-types": "^15.5.10", - "prop-types-extra": "^1.0.1", - "react-transition-group": "^2.2.1", - "warning": "^3.0.0" - }, - "peerDependencies": { - "react": ">=16.3.0", - "react-dom": ">=16.3.0" - } - }, - "node_modules/react-prop-types": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/react-prop-types/-/react-prop-types-0.4.0.tgz", - "integrity": "sha1-+ZsL+0AGkpya8gUefBQUpcdbk9A=", - "dev": true, - "dependencies": { - "warning": "^3.0.0" - }, - "peerDependencies": { - "react": ">=0.14.0" - } - }, "node_modules/react-proxy": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/react-proxy/-/react-proxy-1.1.8.tgz", @@ -34989,22 +34889,6 @@ "react-proxy": "^1.1.7" } }, - "node_modules/react-transition-group": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz", - "integrity": "sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg==", - "dev": true, - "dependencies": { - "dom-helpers": "^3.4.0", - "loose-envify": "^1.4.0", - "prop-types": "^15.6.2", - "react-lifecycles-compat": "^3.0.4" - }, - "peerDependencies": { - "react": ">=15.0.0", - "react-dom": ">=15.0.0" - } - }, "node_modules/reactcss": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/reactcss/-/reactcss-1.2.3.tgz", @@ -40502,15 +40386,6 @@ "node": ">=6.0.0" } }, - "node_modules/warning": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz", - "integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=", - "dev": true, - "dependencies": { - "loose-envify": "^1.0.0" - } - }, "node_modules/watchpack": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", @@ -44482,7 +44357,6 @@ "@types/react-dom": "^17.0.13", "@types/react-google-recaptcha": "^2.1.5", "@types/react-linkify": "^1.0.0", - "@types/react-overlays": "^1.1.3", "@types/recurly__recurly-js": "^4.22.0", "@types/sinon-chai": "^3.2.8", "@types/uuid": "^9.0.8", @@ -44570,7 +44444,6 @@ "prop-types": "^15.7.2", "qrcode": "^1.4.4", "react": "^17.0.2", - "react-bootstrap": "^0.33.1", "react-bootstrap-5": "npm:react-bootstrap@^2.10.5", "react-chartjs-2": "^5.0.1", "react-color": "^2.19.3", @@ -44581,7 +44454,6 @@ "react-google-recaptcha": "^3.1.0", "react-i18next": "^13.3.1", "react-linkify": "^1.0.0-alpha", - "react-overlays": "^0.9.3", "react-refresh": "^0.14.0", "react-resizable-panels": "^2.1.1", "resolve-url-loader": "^5.0.0", diff --git a/services/web/.storybook/preview.tsx b/services/web/.storybook/preview.tsx index ed67abc3c4..e3838a6f97 100644 --- a/services/web/.storybook/preview.tsx +++ b/services/web/.storybook/preview.tsx @@ -9,14 +9,10 @@ import i18n from 'i18next' import { initReactI18next } from 'react-i18next' // @ts-ignore import en from '../../../services/web/locales/en.json' -import { bootstrapVersionArg } from './utils/with-bootstrap-switcher' -function resetMeta(bootstrapVersion?: 3 | 5) { +function resetMeta() { window.metaAttributesCache = new Map() window.metaAttributesCache.set('ol-i18n', { currentLangCode: 'en' }) - if (bootstrapVersion) { - window.metaAttributesCache.set('ol-bootstrapVersion', bootstrapVersion) - } window.metaAttributesCache.set('ol-ExposedSettings', { adminEmail: 'placeholder@example.com', appName: 'Overleaf', @@ -126,8 +122,6 @@ const preview: Preview = { // render stories in iframes, to isolate modals inlineStories: false, }, - // Default to Bootstrap 5 styles - bootstrap5: true, }, globalTypes: { theme: { @@ -144,17 +138,9 @@ const preview: Preview = { }, }, loaders: [ - async ({ globals }) => { - const { theme } = globals - + async () => { return { - // NOTE: this uses `${theme}style.less` rather than `${theme}.less` - // so that webpack only bundles files ending with "style.less" - bootstrap3Style: await import( - `!!to-string-loader!css-loader!less-loader!../../../services/web/frontend/stylesheets/${theme}style.less` - ), - // Themes are applied differently in Bootstrap 5 code - bootstrap5Style: await import( + mainStyle: await import( // @ts-ignore `!!to-string-loader!css-loader!resolve-url-loader!sass-loader!../../../services/web/frontend/stylesheets/bootstrap-5/main-style.scss` ), @@ -163,15 +149,9 @@ const preview: Preview = { ], decorators: [ (Story, context) => { - const { bootstrap3Style, bootstrap5Style } = context.loaded - const bootstrapVersion = Number( - context.args[bootstrapVersionArg] || - (context.parameters.bootstrap5 === false ? 3 : 5) - ) as 3 | 5 - const activeStyle = - bootstrapVersion === 3 ? bootstrap3Style : bootstrap5Style + const { mainStyle } = context.loaded - resetMeta(bootstrapVersion) + resetMeta() return (
- {activeStyle && } - + {mainStyle && } +
) }, diff --git a/services/web/.storybook/utils/with-bootstrap-switcher.tsx b/services/web/.storybook/utils/with-bootstrap-switcher.tsx deleted file mode 100644 index 640338dbb0..0000000000 --- a/services/web/.storybook/utils/with-bootstrap-switcher.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import { Meta } from '@storybook/react' - -export const bootstrapVersionArg = 'bootstrapVersion' - -export const bsVersionDecorator: Meta = { - argTypes: { - [bootstrapVersionArg]: { - name: 'Bootstrap Version', - description: 'Bootstrap version for components', - control: { type: 'inline-radio' }, - options: ['3', '5'], - table: { - defaultValue: { summary: '5' }, - }, - }, - }, - args: { - [bootstrapVersionArg]: '5', - }, -} diff --git a/services/web/cypress/support/ct/window.ts b/services/web/cypress/support/ct/window.ts index 3f415cf3c5..ae2a194bc1 100644 --- a/services/web/cypress/support/ct/window.ts +++ b/services/web/cypress/support/ct/window.ts @@ -10,7 +10,6 @@ export function resetMeta() { hasLinkedProjectOutputFileFeature: true, hasLinkUrlFeature: true, }) - window.metaAttributesCache.set('ol-bootstrapVersion', 5) } // Populate meta for top-level access in modules on import diff --git a/services/web/frontend/js/features/file-tree/components/file-tree-context-menu.tsx b/services/web/frontend/js/features/file-tree/components/file-tree-context-menu.tsx index 5e66614dcd..957ed0cbdb 100644 --- a/services/web/frontend/js/features/file-tree/components/file-tree-context-menu.tsx +++ b/services/web/frontend/js/features/file-tree/components/file-tree-context-menu.tsx @@ -19,20 +19,11 @@ function FileTreeContextMenu() { toggleButtonRef.current = document.querySelector( '.entity-menu-toggle' ) as HTMLButtonElement | null - focusContextMenu() } }, [contextMenuCoords]) if (!contextMenuCoords || fileTreeReadOnly) return null - // A11y - Move the focus to the context menu when it opens - function focusContextMenu() { - const BS3contextMenu = document.querySelector( - '[aria-labelledby="dropdown-file-tree-context-menu"]' - ) as HTMLElement | null - BS3contextMenu?.focus() - } - function close() { setContextMenuCoords(null) if (toggleButtonRef.current) { @@ -79,14 +70,4 @@ function FileTreeContextMenu() { ) } -// fake component required as Dropdowns require a Toggle, even tho we don't want -// one for the context menu -const FakeDropDownToggle = React.forwardRef( - ({ bsRole }, ref) => { - return null - } -) - -FakeDropDownToggle.displayName = 'FakeDropDownToggle' - export default FileTreeContextMenu diff --git a/services/web/frontend/js/features/history/components/change-list/change-list.tsx b/services/web/frontend/js/features/history/components/change-list/change-list.tsx index cb0e93fae4..f072d24a57 100644 --- a/services/web/frontend/js/features/history/components/change-list/change-list.tsx +++ b/services/web/frontend/js/features/history/components/change-list/change-list.tsx @@ -11,10 +11,7 @@ function ChangeList() {
-
+
{labelsOnly ? : }
diff --git a/services/web/frontend/js/features/history/components/change-list/dropdown/actions-dropdown.tsx b/services/web/frontend/js/features/history/components/change-list/dropdown/actions-dropdown.tsx index 90f23cf746..9029260057 100644 --- a/services/web/frontend/js/features/history/components/change-list/dropdown/actions-dropdown.tsx +++ b/services/web/frontend/js/features/history/components/change-list/dropdown/actions-dropdown.tsx @@ -3,26 +3,20 @@ import { Dropdown, DropdownMenu, } from '@/features/ui/components/bootstrap-5/dropdown-menu' -import BS5DropdownToggleWithTooltip from '@/features/ui/components/bootstrap-5/dropdown-toggle-with-tooltip' +import DropdownToggleWithTooltip from '@/features/ui/components/bootstrap-5/dropdown-toggle-with-tooltip' type ActionDropdownProps = { id: string children: React.ReactNode - parentSelector?: string isOpened: boolean iconTag: ReactNode toolTipDescription: string setIsOpened: (isOpened: boolean) => void } -function BS5ActionsDropdown({ - id, - children, - isOpened, - iconTag, - setIsOpened, - toolTipDescription, -}: Omit) { +function ActionsDropdown(props: ActionDropdownProps) { + const { id, children, isOpened, iconTag, setIsOpened, toolTipDescription } = + props return ( setIsOpened(open)} > - {iconTag} - + {children} @@ -47,8 +41,4 @@ function BS5ActionsDropdown({ ) } -function ActionsDropdown(props: ActionDropdownProps) { - return -} - export default ActionsDropdown diff --git a/services/web/frontend/js/features/history/components/change-list/dropdown/compare-version-dropdown.tsx b/services/web/frontend/js/features/history/components/change-list/dropdown/compare-version-dropdown.tsx index 6cf2d54f1f..91f0bf991a 100644 --- a/services/web/frontend/js/features/history/components/change-list/dropdown/compare-version-dropdown.tsx +++ b/services/web/frontend/js/features/history/components/change-list/dropdown/compare-version-dropdown.tsx @@ -21,7 +21,6 @@ function CompareVersionDropdown({ id={id} isOpened={isOpened} setIsOpened={setIsOpened} - parentSelector="[data-history-version-list-container]" toolTipDescription={t('compare')} iconTag={ } - parentSelector="[data-history-version-list-container]" > {children} diff --git a/services/web/frontend/js/features/settings/components/emails/actions/make-primary/confirmation-modal.tsx b/services/web/frontend/js/features/settings/components/emails/actions/make-primary/confirmation-modal.tsx index cdc1b9d481..66f4da7c99 100644 --- a/services/web/frontend/js/features/settings/components/emails/actions/make-primary/confirmation-modal.tsx +++ b/services/web/frontend/js/features/settings/components/emails/actions/make-primary/confirmation-modal.tsx @@ -1,5 +1,4 @@ import { useTranslation, Trans } from 'react-i18next' -import AccessibleModal from '../../../../../../shared/components/accessible-modal' import { MergeAndOverride } from '../../../../../../../../types/utils' import OLButton from '@/features/ui/components/ol/ol-button' import OLModal, { @@ -11,7 +10,7 @@ import OLModal, { import { type UserEmailData } from '../../../../../../../../types/user-email' type ConfirmationModalProps = MergeAndOverride< - React.ComponentProps, + React.ComponentProps, { email: string isConfirmDisabled: boolean diff --git a/services/web/frontend/js/features/settings/components/emails/reconfirmation-info/reconfirmation-info-prompt-text.tsx b/services/web/frontend/js/features/settings/components/emails/reconfirmation-info/reconfirmation-info-prompt-text.tsx index 4dace050ef..898649504d 100644 --- a/services/web/frontend/js/features/settings/components/emails/reconfirmation-info/reconfirmation-info-prompt-text.tsx +++ b/services/web/frontend/js/features/settings/components/emails/reconfirmation-info/reconfirmation-info-prompt-text.tsx @@ -4,19 +4,16 @@ import { Institution } from '../../../../../../../types/institution' type ReconfirmationInfoPromptTextProps = { primary: boolean institutionName: Institution['name'] - icon?: React.ReactElement // BS3 only } function ReconfirmationInfoPromptText({ primary, institutionName, - icon, }: ReconfirmationInfoPromptTextProps) { const { t } = useTranslation() return ( <> - {icon}
+ ) } diff --git a/services/web/frontend/js/features/subscription/components/dashboard/leave-group-modal.tsx b/services/web/frontend/js/features/subscription/components/dashboard/leave-group-modal.tsx index d56b0c80b8..99a80da3f4 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/leave-group-modal.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/leave-group-modal.tsx @@ -71,11 +71,6 @@ export default function LeaveGroupModal() { disabled={inflight} isLoading={inflight} loadingLabel={t('processing_uppercase') + '…'} - bs3Props={{ - loading: inflight - ? t('processing_uppercase') + '…' - : t('leave_now'), - }} > {t('leave_now')} diff --git a/services/web/frontend/js/features/subscription/components/dashboard/managed-group-subscriptions.tsx b/services/web/frontend/js/features/subscription/components/dashboard/managed-group-subscriptions.tsx index 18b43bd7da..a79cac06ac 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/managed-group-subscriptions.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/managed-group-subscriptions.tsx @@ -7,8 +7,6 @@ import { Trans, useTranslation } from 'react-i18next' import { useSubscriptionDashboardContext } from '../../context/subscription-dashboard-context' import { RowLink } from './row-link' import { ManagedGroupSubscription } from '../../../../../../types/subscription/dashboard/subscription' -import { bsVersion } from '@/features/utils/bootstrap-5' -import classnames from 'classnames' function ManagedGroupAdministrator({ subscription, @@ -104,9 +102,7 @@ export default function ManagedGroupSubscriptions() { {managedGroupSubscriptions.map(subscription => { return (
-

- {t('group_management')} -

+

{t('group_management')}

diff --git a/services/web/frontend/js/features/subscription/components/dashboard/personal-subscription-recurly-sync-email.tsx b/services/web/frontend/js/features/subscription/components/dashboard/personal-subscription-recurly-sync-email.tsx index 1425609264..9c08e175d6 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/personal-subscription-recurly-sync-email.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/personal-subscription-recurly-sync-email.tsx @@ -51,9 +51,6 @@ function PersonalSubscriptionRecurlySyncEmail() { disabled={isLoading} isLoading={isLoading} loadingLabel={t('updating')} - bs3Props={{ - loading: isLoading ? t('updating') + '…' : t('update'), - }} > {t('update')} diff --git a/services/web/frontend/js/features/subscription/components/dashboard/row-link.tsx b/services/web/frontend/js/features/subscription/components/dashboard/row-link.tsx index fec6f03c53..42e331fdd0 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/row-link.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/row-link.tsx @@ -1,5 +1,4 @@ import MaterialIcon from '../../../../shared/components/material-icon' -import { isBootstrap5 } from '@/features/utils/bootstrap-5' type RowLinkProps = { href: string @@ -8,28 +7,7 @@ type RowLinkProps = { icon: string } -export function RowLink(props: RowLinkProps) { - return isBootstrap5() ? : -} - -function BS3RowLink({ href, heading, subtext, icon }: RowLinkProps) { - return ( - -
- -
-
-
{heading}
-
{subtext}
-
-
- -
-
- ) -} - -function BS5RowLink({ href, heading, subtext, icon }: RowLinkProps) { +export function RowLink({ href, heading, subtext, icon }: RowLinkProps) { return (
  • diff --git a/services/web/frontend/js/features/subscription/components/dashboard/states/active/active-new.tsx b/services/web/frontend/js/features/subscription/components/dashboard/states/active/active-new.tsx index 067888f918..8a60af4dad 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/states/active/active-new.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/states/active/active-new.tsx @@ -12,7 +12,6 @@ import { ChangeToGroupModal } from './change-plan/modals/change-to-group-modal' import { CancelAiAddOnModal } from '@/features/subscription/components/dashboard/states/active/change-plan/modals/cancel-ai-add-on-modal' import OLButton from '@/features/ui/components/ol/ol-button' import isInFreeTrial from '../../../../util/is-in-free-trial' -import { bsVersion } from '@/features/utils/bootstrap-5' import AddOns from '@/features/subscription/components/dashboard/states/active/add-ons' import { AI_ADD_ON_CODE, @@ -20,7 +19,6 @@ import { isStandaloneAiPlanCode, } from '@/features/subscription/data/add-on-codes' import getMeta from '@/utils/meta' -import classnames from 'classnames' import SubscriptionRemainder from '@/features/subscription/components/dashboard/states/active/subscription-remainder' import { sendMB } from '../../../../../../infrastructure/event-tracking' import PauseSubscriptionModal from '@/features/subscription/components/dashboard/pause-modal' @@ -100,9 +98,7 @@ export function ActiveSubscriptionNew({ /> )}
  • -

    - {t('billing')} -

    +

    {t('billing')}

    {subscription.plan.annual ? (


    -

    - {t('plan')} -

    -

    - {planName} -

    +

    {t('plan')}

    +

    {planName}

    {subscription.pendingPlan && subscription.pendingPlan.name !== subscription.plan.name && (

    {t('want_change_to_apply_before_plan_end')}

    diff --git a/services/web/frontend/js/features/subscription/components/dashboard/states/active/cancel-plan/downgrade-plan-button.tsx b/services/web/frontend/js/features/subscription/components/dashboard/states/active/cancel-plan/downgrade-plan-button.tsx index e0bc66ac63..c34e304e8b 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/states/active/cancel-plan/downgrade-plan-button.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/states/active/cancel-plan/downgrade-plan-button.tsx @@ -41,9 +41,6 @@ export default function DowngradePlanButton({ disabled={isButtonDisabled} isLoading={isLoading} loadingLabel={t('processing_uppercase') + '…'} - bs3Props={{ - loading: isLoading ? t('processing_uppercase') + '…' : buttonText, - }} > {buttonText} diff --git a/services/web/frontend/js/features/subscription/components/dashboard/states/active/cancel-plan/extend-trial-button.tsx b/services/web/frontend/js/features/subscription/components/dashboard/states/active/cancel-plan/extend-trial-button.tsx index d5b2e4d95c..e108e934a0 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/states/active/cancel-plan/extend-trial-button.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/states/active/cancel-plan/extend-trial-button.tsx @@ -34,9 +34,6 @@ export default function ExtendTrialButton({ disabled={isButtonDisabled} isLoading={isLoading} loadingLabel={t('processing_uppercase') + '…'} - bs3Props={{ - loading: isLoading ? t('processing_uppercase') + '…' : buttonText, - }} > {buttonText} diff --git a/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/cancel-ai-add-on-modal.tsx b/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/cancel-ai-add-on-modal.tsx index 87d63bc44e..41c006507a 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/cancel-ai-add-on-modal.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/cancel-ai-add-on-modal.tsx @@ -107,11 +107,6 @@ export function CancelAiAddOnModal() { isLoading={inflight} loadingLabel={t('processing_uppercase') + '…'} onClick={handleConfirmChange} - bs3Props={{ - loading: inflight - ? t('processing_uppercase') + '…' - : t('cancel_add_on'), - }} > {t('cancel_add_on')} diff --git a/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/change-to-group-modal.tsx b/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/change-to-group-modal.tsx index 010522a357..6ebfc3e7e3 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/change-to-group-modal.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/change-to-group-modal.tsx @@ -22,9 +22,7 @@ import OLFormCheckbox from '@/features/ui/components/ol/ol-form-checkbox' import { useContactUsModal } from '@/shared/hooks/use-contact-us-modal' import { UserProvider } from '@/shared/context/user-context' import OLButton from '@/features/ui/components/ol/ol-button' -import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' import OLNotification from '@/features/ui/components/ol/ol-notification' -import { bsVersion } from '@/features/utils/bootstrap-5' const educationalPercentDiscount = 40 @@ -79,8 +77,6 @@ function GroupPrice({ })} - } /> - {t('x_price_per_user', { @@ -221,10 +217,7 @@ export function ChangeToGroupModal() {
    {t('plan')} {groupPlans.plans.map(option => ( -
    +
    {t('upgrade_now')} diff --git a/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/confirm-change-plan-modal.tsx b/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/confirm-change-plan-modal.tsx index 0a9a5841eb..08cbf1743f 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/confirm-change-plan-modal.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/confirm-change-plan-modal.tsx @@ -112,11 +112,6 @@ export function ConfirmChangePlanModal() { isLoading={inflight} loadingLabel={t('processing_uppercase') + '…'} onClick={handleConfirmChange} - bs3Props={{ - loading: inflight - ? t('processing_uppercase') + '…' - : t('change_plan'), - }} > {t('change_plan')} diff --git a/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/keep-current-plan-modal.tsx b/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/keep-current-plan-modal.tsx index e6bbe4942f..793c570e25 100644 --- a/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/keep-current-plan-modal.tsx +++ b/services/web/frontend/js/features/subscription/components/dashboard/states/active/change-plan/modals/keep-current-plan-modal.tsx @@ -93,11 +93,6 @@ export function KeepCurrentPlanModal() { isLoading={inflight} loadingLabel={t('processing_uppercase') + '…'} onClick={confirmCancelPendingPlanChange} - bs3Props={{ - loading: inflight - ? t('processing_uppercase') + '…' - : t('revert_pending_plan_change'), - }} > {t('revert_pending_plan_change')} diff --git a/services/web/frontend/js/features/ui/components/bootstrap-3/dropdown-menu-with-ref.tsx b/services/web/frontend/js/features/ui/components/bootstrap-3/dropdown-menu-with-ref.tsx deleted file mode 100644 index 04807ad825..0000000000 --- a/services/web/frontend/js/features/ui/components/bootstrap-3/dropdown-menu-with-ref.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import { forwardRef, SyntheticEvent } from 'react' -import classnames from 'classnames' -import RootCloseWrapper from 'react-overlays/lib/RootCloseWrapper' -import { DropdownProps } from 'react-bootstrap' -import { MergeAndOverride } from '../../../../../../types/utils' - -type DropdownMenuWithRefProps = MergeAndOverride< - Pick, - { - children: React.ReactNode - bsRole: 'menu' - menuRef: React.MutableRefObject - className?: string - // The props below are passed by react-bootstrap - labelledBy?: string | undefined - rootCloseEvent?: 'click' | 'mousedown' | undefined - onClose?: (e: SyntheticEvent) => void - } -> - -const DropdownMenuWithRef = forwardRef< - HTMLUListElement, - DropdownMenuWithRefProps ->(function (props, ref) { - const { - children, - bsRole, - bsClass, - className, - open, - pullRight, - labelledBy, - menuRef, - onClose, - rootCloseEvent, - ...rest - } = props - - // expose the menu reference to both the `menuRef` and `ref callback` from react-bootstrap - const handleRefs = (node: HTMLUListElement) => { - if (typeof ref === 'function') { - ref(node) - } - menuRef.current = node - } - - // Implementation as suggested in - // https://react-bootstrap-v3.netlify.app/components/dropdowns/#btn-dropdowns-props-dropdown - return ( - -
      - {children} -
    -
    - ) -}) -DropdownMenuWithRef.displayName = 'DropdownMenuWithRef' - -export default DropdownMenuWithRef diff --git a/services/web/frontend/js/features/ui/components/bootstrap-3/dropdown-toggle-with-tooltip.tsx b/services/web/frontend/js/features/ui/components/bootstrap-3/dropdown-toggle-with-tooltip.tsx deleted file mode 100644 index 9f0dedf622..0000000000 --- a/services/web/frontend/js/features/ui/components/bootstrap-3/dropdown-toggle-with-tooltip.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { forwardRef } from 'react' -import Tooltip from '../../../../shared/components/tooltip' -import classnames from 'classnames' -import { DropdownProps } from 'react-bootstrap' -import { MergeAndOverride } from '../../../../../../types/utils' - -type CustomToggleProps = MergeAndOverride< - Pick, - { - children: React.ReactNode - isOpened: boolean - bsRole: 'toggle' - className?: string - tooltipProps: Omit, 'children'> - } -> - -const DropdownToggleWithTooltip = forwardRef< - HTMLButtonElement, - CustomToggleProps ->(function (props, ref) { - const { - tooltipProps, - isOpened, - children, - bsClass, - className, - open, - bsRole: _bsRole, - ...rest - } = props - - const button = ( - - ) - - return ( - <>{isOpened ? button : {button}} - ) -}) - -DropdownToggleWithTooltip.displayName = 'DropdownToggleWithTooltip' - -export default DropdownToggleWithTooltip diff --git a/services/web/frontend/js/features/ui/components/bootstrap-3/form/form-control.tsx b/services/web/frontend/js/features/ui/components/bootstrap-3/form/form-control.tsx deleted file mode 100644 index 1cd6c617e0..0000000000 --- a/services/web/frontend/js/features/ui/components/bootstrap-3/form/form-control.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { - FormControl as BS3FormControl, - FormControlProps as BS3FormControlProps, -} from 'react-bootstrap' - -type FormControlProps = BS3FormControlProps & { - prepend?: React.ReactNode - append?: React.ReactNode -} - -function FormControl({ prepend, append, ...props }: FormControlProps) { - return ( - <> - {prepend &&
    {prepend}
    } - - {append &&
    {append}
    } - - ) -} - -export default FormControl diff --git a/services/web/frontend/js/features/ui/components/bootstrap-3/toast-container.tsx b/services/web/frontend/js/features/ui/components/bootstrap-3/toast-container.tsx deleted file mode 100644 index 314de8ba77..0000000000 --- a/services/web/frontend/js/features/ui/components/bootstrap-3/toast-container.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import classNames from 'classnames' -import { FC, HTMLProps } from 'react' - -export const ToastContainer: FC> = ({ - children, - className, - ...props -}) => { - return ( -
    - {children} -
    - ) -} diff --git a/services/web/frontend/js/features/ui/components/bootstrap-3/toast.tsx b/services/web/frontend/js/features/ui/components/bootstrap-3/toast.tsx deleted file mode 100644 index 4c35ddf4b5..0000000000 --- a/services/web/frontend/js/features/ui/components/bootstrap-3/toast.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import classNames from 'classnames' -import { FC, useCallback, useEffect, useRef } from 'react' - -type ToastProps = { - onClose?: () => void - onExited?: () => void - autohide?: boolean - delay?: number - show: boolean - className?: string -} -export const Toast: FC = ({ - children, - delay = 5000, - onClose, - onExited, - autohide, - show, - className, -}) => { - const delayRef = useRef(delay) - const onCloseRef = useRef(onClose) - const onExitedRef = useRef(onExited) - const shouldAutoHide = Boolean(autohide && show) - - const handleTimeout = useCallback(() => { - if (shouldAutoHide) { - onCloseRef.current?.() - onExitedRef.current?.() - } - }, [shouldAutoHide]) - - useEffect(() => { - const timeout = window.setTimeout(handleTimeout, delayRef.current) - return () => window.clearTimeout(timeout) - }, [handleTimeout]) - - if (!show) { - return null - } - - return ( -
    - {children} -
    - ) -} diff --git a/services/web/frontend/js/features/ui/components/bootstrap-3/toggle-button-group.tsx b/services/web/frontend/js/features/ui/components/bootstrap-3/toggle-button-group.tsx deleted file mode 100644 index 2224e6160b..0000000000 --- a/services/web/frontend/js/features/ui/components/bootstrap-3/toggle-button-group.tsx +++ /dev/null @@ -1,99 +0,0 @@ -import { - Children, - cloneElement, - isValidElement, - useState, - useEffect, -} from 'react' -import { - ToggleButtonGroup as BS3ToggleButtonGroup, - ToggleButtonGroupProps as BS3ToggleButtonGroupProps, - ToggleButtonProps as BS3ToggleButtonProps, -} from 'react-bootstrap' - -function ToggleButtonGroup({ - children, - value, - defaultValue, - onChange, - ...props -}: BS3ToggleButtonGroupProps) { - const [selectedValue, setSelectedValue] = useState( - defaultValue || (props.type === 'checkbox' ? [] : null) - ) - const isControlled = value !== undefined - - useEffect(() => { - if (isControlled) { - if (props.type === 'radio') { - setSelectedValue(value) - } else { - if (Array.isArray(value)) { - setSelectedValue(Array.from(value)) - } else { - setSelectedValue([value]) - } - } - } - }, [isControlled, value, props.type]) - - const handleButtonClick = (buttonValue: T) => { - if (props.type === 'radio') { - if (!isControlled) { - setSelectedValue(buttonValue) - } - - onChange?.(buttonValue as any) - } else if (props.type === 'checkbox') { - const newValue = Array.isArray(selectedValue) - ? selectedValue.includes(buttonValue) - ? selectedValue.filter(val => val !== buttonValue) // Deselect - : [...selectedValue, buttonValue] // Select - : [buttonValue] // Initial selection if value is not array yet - - if (!isControlled) { - setSelectedValue(newValue) - } - - onChange?.(newValue) - } - } - - // Clone children and add custom onClick handlers - const modifiedChildren = Children.map(children, child => { - if (isValidElement(child)) { - const childElement = child as React.ReactElement< - BS3ToggleButtonProps & { active?: boolean } - > - - const isActive = - props.type === 'radio' - ? selectedValue === childElement.props.value - : Array.isArray(selectedValue) && - selectedValue.includes(childElement.props.value as T) - - return cloneElement(childElement, { - onClick: () => { - handleButtonClick(childElement.props.value as T) - }, - active: isActive, - }) - } - - return child - }) - - return ( - {}} - > - {modifiedChildren} - - ) -} - -export default ToggleButtonGroup diff --git a/services/web/frontend/js/features/ui/components/bootstrap-5/bootstrap-version-switcher.tsx b/services/web/frontend/js/features/ui/components/bootstrap-5/bootstrap-version-switcher.tsx deleted file mode 100644 index 0bdfcca31f..0000000000 --- a/services/web/frontend/js/features/ui/components/bootstrap-5/bootstrap-version-switcher.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { isBootstrap5 } from '@/features/utils/bootstrap-5' - -type BootstrapVersionSwitcherProps = { - bs3?: React.ReactNode - bs5?: React.ReactNode -} - -function BootstrapVersionSwitcher({ - bs3, - bs5, -}: BootstrapVersionSwitcherProps): React.ReactElement { - return <>{isBootstrap5() ? bs5 : bs3} -} - -export default BootstrapVersionSwitcher diff --git a/services/web/frontend/js/features/ui/components/ol/icons/ol-tag-icon.tsx b/services/web/frontend/js/features/ui/components/ol/icons/ol-tag-icon.tsx index 8e81387bbe..4a2fbadec9 100644 --- a/services/web/frontend/js/features/ui/components/ol/icons/ol-tag-icon.tsx +++ b/services/web/frontend/js/features/ui/components/ol/icons/ol-tag-icon.tsx @@ -1,12 +1,5 @@ -import Icon from '@/shared/components/icon' import MaterialIcon from '@/shared/components/material-icon' -import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' export default function OLTagIcon() { - return ( - } - bs5={} - /> - ) + return } diff --git a/services/web/frontend/js/features/ui/components/ol/ol-badge.tsx b/services/web/frontend/js/features/ui/components/ol/ol-badge.tsx index 0e88529a86..47fd163d5c 100644 --- a/services/web/frontend/js/features/ui/components/ol/ol-badge.tsx +++ b/services/web/frontend/js/features/ui/components/ol/ol-badge.tsx @@ -1,40 +1,7 @@ -import { Label } from 'react-bootstrap' import Badge from '@/features/ui/components/bootstrap-5/badge' -import BS3Badge from '@/shared/components/badge' -import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' -type OLBadgeProps = React.ComponentProps & { - bs3Props?: { - bsStyle?: React.ComponentProps['bsStyle'] | null - } -} - -function OLBadge(props: OLBadgeProps) { - const { bs3Props, ...rest } = props - - let bs3BadgeProps: React.ComponentProps = { - prepend: rest.prepend, - children: rest.children, - className: rest.className, - bsStyle: rest.bg, - } - - if (bs3Props) { - const { bsStyle, ...restBs3Props } = bs3Props - - bs3BadgeProps = { - ...bs3BadgeProps, - ...restBs3Props, - bsStyle: 'bsStyle' in bs3Props ? bsStyle : rest.bg, - } - } - - return ( - } - bs5={} - /> - ) +function OLBadge(props: React.ComponentProps) { + return } export default OLBadge diff --git a/services/web/frontend/js/features/ui/components/ol/ol-button-group.tsx b/services/web/frontend/js/features/ui/components/ol/ol-button-group.tsx index c9a9d1188b..dc26595aac 100644 --- a/services/web/frontend/js/features/ui/components/ol/ol-button-group.tsx +++ b/services/web/frontend/js/features/ui/components/ol/ol-button-group.tsx @@ -1,30 +1,7 @@ import { ButtonGroup, ButtonGroupProps } from 'react-bootstrap-5' -import { - ButtonGroup as BS3ButtonGroup, - ButtonGroupProps as BS3ButtonGroupProps, -} from 'react-bootstrap' -import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' -import { getAriaAndDataProps } from '@/features/utils/bootstrap-5' -type OLButtonGroupProps = ButtonGroupProps & { - bs3Props?: Record -} - -function OLButtonGroup({ bs3Props, as, ...rest }: OLButtonGroupProps) { - const bs3ButtonGroupProps: BS3ButtonGroupProps = { - children: rest.children, - className: rest.className, - vertical: rest.vertical, - ...getAriaAndDataProps(rest), - ...bs3Props, - } - - return ( - } - bs5={} - /> - ) +function OLButtonGroup({ as, ...rest }: ButtonGroupProps) { + return } export default OLButtonGroup diff --git a/services/web/frontend/js/features/ui/components/ol/ol-button-toolbar.tsx b/services/web/frontend/js/features/ui/components/ol/ol-button-toolbar.tsx index 16d85c29eb..377228f72d 100644 --- a/services/web/frontend/js/features/ui/components/ol/ol-button-toolbar.tsx +++ b/services/web/frontend/js/features/ui/components/ol/ol-button-toolbar.tsx @@ -1,31 +1,7 @@ import { ButtonToolbar, ButtonToolbarProps } from 'react-bootstrap-5' -import { - ButtonToolbar as BS3ButtonToolbar, - ButtonToolbarProps as BS3ButtonToolbarProps, -} from 'react-bootstrap' -import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' -import { getAriaAndDataProps } from '@/features/utils/bootstrap-5' -type OLButtonToolbarProps = ButtonToolbarProps & { - bs3Props?: Record -} - -function OLButtonToolbar(props: OLButtonToolbarProps) { - const { bs3Props, ...rest } = props - - const bs3ButtonToolbarProps: BS3ButtonToolbarProps = { - children: rest.children, - className: rest.className, - ...getAriaAndDataProps(rest), - ...bs3Props, - } - - return ( - } - bs5={} - /> - ) +function OLButtonToolbar(props: ButtonToolbarProps) { + return } export default OLButtonToolbar diff --git a/services/web/frontend/js/features/ui/components/ol/ol-button.tsx b/services/web/frontend/js/features/ui/components/ol/ol-button.tsx index 6df9266744..3f5e06e8c4 100644 --- a/services/web/frontend/js/features/ui/components/ol/ol-button.tsx +++ b/services/web/frontend/js/features/ui/components/ol/ol-button.tsx @@ -1,132 +1,13 @@ import { forwardRef } from 'react' -import BootstrapVersionSwitcher from '../bootstrap-5/bootstrap-version-switcher' -import { Button as BS3Button } from 'react-bootstrap' import type { ButtonProps } from '@/features/ui/components/types/button-props' -import type { ButtonProps as BS3ButtonPropsBase } from 'react-bootstrap' import Button from '../bootstrap-5/button' -import classnames from 'classnames' -import { getAriaAndDataProps } from '@/features/utils/bootstrap-5' -import { callFnsInSequence } from '@/utils/functions' -import Icon from '@/shared/components/icon' -export type BS3ButtonSize = 'xsmall' | 'sm' | 'medium' | 'lg' +export type OLButtonProps = ButtonProps -export type OLButtonProps = ButtonProps & { - bs3Props?: { - loading?: React.ReactNode - bsSize?: BS3ButtonSize - block?: boolean - className?: string - onMouseOver?: React.MouseEventHandler - onMouseOut?: React.MouseEventHandler - onFocus?: React.FocusEventHandler - onBlur?: React.FocusEventHandler - } -} +const OLButton = forwardRef((props, ref) => { + return
    } - bs5={ - - {children} - - } - /> + + {children} + ) } diff --git a/services/web/frontend/js/features/ui/components/ol/ol-close-button.tsx b/services/web/frontend/js/features/ui/components/ol/ol-close-button.tsx index 7034392949..414a329eec 100644 --- a/services/web/frontend/js/features/ui/components/ol/ol-close-button.tsx +++ b/services/web/frontend/js/features/ui/components/ol/ol-close-button.tsx @@ -1,6 +1,4 @@ -import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' import { CloseButton, CloseButtonProps } from 'react-bootstrap-5' -import classNames from 'classnames' import { useTranslation } from 'react-i18next' import { forwardRef } from 'react' @@ -8,25 +6,7 @@ const OLCloseButton = forwardRef( (props, ref) => { const { t } = useTranslation() - const bs3CloseButtonProps: React.ButtonHTMLAttributes = { - className: classNames('close', props.className), - onClick: props.onClick, - onMouseOver: props.onMouseOver, - onMouseOut: props.onMouseOut, - - 'aria-label': t('close'), - } - - return ( - - - - } - bs5={} - /> - ) + return } ) diff --git a/services/web/frontend/js/features/ui/components/ol/ol-col.tsx b/services/web/frontend/js/features/ui/components/ol/ol-col.tsx index e2c7c1ce7b..dc70ca23c8 100644 --- a/services/web/frontend/js/features/ui/components/ol/ol-col.tsx +++ b/services/web/frontend/js/features/ui/components/ol/ol-col.tsx @@ -1,73 +1,7 @@ import { Col } from 'react-bootstrap-5' -import { Col as BS3Col } from 'react-bootstrap' -import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' -type OLColProps = React.ComponentProps & { - bs3Props?: Record -} - -function OLCol(props: OLColProps) { - const { bs3Props, ...rest } = props - - const getBs3Sizes = (obj: typeof rest) => { - const bs5ToBs3SizeMap = { - xs: 'xs', - sm: 'xs', - md: 'sm', - lg: 'md', - xl: 'lg', - xxl: undefined, - } as const - - const isBs5ToBs3SizeMapKey = ( - key: string - ): key is keyof typeof bs5ToBs3SizeMap => { - return key in bs5ToBs3SizeMap - } - - const sizes = Object.entries(obj).reduce( - (prev, [key, value]) => { - if (isBs5ToBs3SizeMapKey(key)) { - const bs3Size = bs5ToBs3SizeMap[key] - - if (bs3Size) { - if (typeof value === 'object') { - prev[bs3Size] = value.span - prev[`${bs3Size}Offset`] = value.offset - } else { - prev[bs3Size] = value - } - } - } - - return prev - }, - {} as Record - ) - - // Add a default sizing for `col-xs-12` if no sizing is available - if ( - !Object.keys(sizes).some(key => ['xs', 'sm', 'md', 'lg'].includes(key)) - ) { - sizes.xs = 12 - } - - return sizes - } - - const bs3ColProps: React.ComponentProps = { - children: rest.children, - className: rest.className, - ...getBs3Sizes(rest), - ...bs3Props, - } - - return ( - } - bs5={} - /> - ) +function OLCol(props: React.ComponentProps) { + return } export default OLCol diff --git a/services/web/frontend/js/features/ui/components/ol/ol-dropdown-menu-item.tsx b/services/web/frontend/js/features/ui/components/ol/ol-dropdown-menu-item.tsx index 59567ecce9..20d05d5346 100644 --- a/services/web/frontend/js/features/ui/components/ol/ol-dropdown-menu-item.tsx +++ b/services/web/frontend/js/features/ui/components/ol/ol-dropdown-menu-item.tsx @@ -1,43 +1,13 @@ -import { MenuItem, MenuItemProps } from 'react-bootstrap' import { DropdownItem } from '@/features/ui/components/bootstrap-5/dropdown-menu' import { DropdownItemProps } from '@/features/ui/components/types/dropdown-menu-props' -import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' import DropdownListItem from '@/features/ui/components/bootstrap-5/dropdown-list-item' -type OLDropdownMenuItemProps = DropdownItemProps & { - bs3Props?: MenuItemProps -} - // This represents a menu item. It wraps the item within an
  • element. -function OLDropdownMenuItem(props: OLDropdownMenuItemProps) { - const { bs3Props, ...rest } = props - - const bs3MenuItemProps: MenuItemProps = { - children: rest.leadingIcon ? ( - <> - {rest.leadingIcon} -   - {rest.children} - - ) : ( - rest.children - ), - onClick: rest.onClick, - href: rest.href, - download: rest.download, - eventKey: rest.eventKey, - ...bs3Props, - } - +function OLDropdownMenuItem(props: DropdownItemProps) { return ( - } - bs5={ - - - - } - /> + + + ) } diff --git a/services/web/frontend/js/features/ui/components/ol/ol-form-checkbox.tsx b/services/web/frontend/js/features/ui/components/ol/ol-form-checkbox.tsx index 27de2f4ed3..d82e49ea2d 100644 --- a/services/web/frontend/js/features/ui/components/ol/ol-form-checkbox.tsx +++ b/services/web/frontend/js/features/ui/components/ol/ol-form-checkbox.tsx @@ -1,7 +1,4 @@ import { Form, FormCheckProps } from 'react-bootstrap-5' -import { Checkbox as BS3Checkbox } from 'react-bootstrap' -import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' -import { getAriaAndDataProps } from '@/features/utils/bootstrap-5' import { MergeAndOverride } from '../../../../../../types/utils' import FormText from '../bootstrap-5/form/form-text' @@ -9,128 +6,36 @@ type OLFormCheckboxProps = MergeAndOverride< FormCheckProps, { inputRef?: React.MutableRefObject - bs3Props?: Record } & ( | { description: string; id: string } | { description?: undefined; id?: string } ) > -type RadioButtonProps = { - checked?: boolean - className?: string - description?: string - disabled?: boolean - id: string - name?: string - onChange: (e: React.ChangeEvent) => void - required?: boolean - label: React.ReactElement | string - value: string -} - function OLFormCheckbox(props: OLFormCheckboxProps) { - const { bs3Props, inputRef, ...rest } = props + const { inputRef, ...rest } = props - const bs3FormCheckboxProps: React.ComponentProps = { - children: rest.label, - checked: rest.checked, - value: rest.value, - id: rest.id, - name: rest.name, - required: rest.required, - readOnly: rest.readOnly, - disabled: rest.disabled, - inline: rest.inline, - title: rest.title, - autoComplete: rest.autoComplete, - defaultChecked: rest.defaultChecked, - className: rest.className, - onChange: rest.onChange as (e: React.ChangeEvent) => void, - inputRef: node => { - if (inputRef) { - inputRef.current = node - } - }, - ...getAriaAndDataProps(rest), - ...bs3Props, - } - - return ( - - ) : ( - - ) - } - bs5={ - rest.type === 'radio' ? ( - - {rest.label} - {rest.description && ( - - {rest.description} - - )} - - } - /> - ) : ( - - ) + return rest.type === 'radio' ? ( + + {rest.label} + {rest.description && ( + + {rest.description} + + )} + } /> - ) -} - -function BS3Radio(props: RadioButtonProps) { - const { - label, - checked, - className, - description, - disabled, - id, - name, - onChange, - required, - value, - } = props - return ( -
    - - {' '} - {description && ( - - )} -
    + ) : ( + ) } diff --git a/services/web/frontend/js/features/ui/components/ol/ol-form-control.tsx b/services/web/frontend/js/features/ui/components/ol/ol-form-control.tsx index 398d2556b3..bae3282c6f 100644 --- a/services/web/frontend/js/features/ui/components/ol/ol-form-control.tsx +++ b/services/web/frontend/js/features/ui/components/ol/ol-form-control.tsx @@ -1,96 +1,27 @@ -import { forwardRef, ComponentProps, useCallback } from 'react' -import { getAriaAndDataProps } from '@/features/utils/bootstrap-5' +import { forwardRef } from 'react' import FormControl, { type OLBS5FormControlProps, } from '@/features/ui/components/bootstrap-5/form/form-control' -import BS3FormControl from '@/features/ui/components/bootstrap-3/form/form-control' -import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' import OLSpinner from '@/features/ui/components/ol/ol-spinner' -import Icon from '@/shared/components/icon' import type { BsPrefixRefForwardingComponent } from 'react-bootstrap-5/helpers' type OLFormControlProps = OLBS5FormControlProps & { - bs3Props?: Record 'data-ol-dirty'?: unknown 'main-field'?: any // For the CM6's benefit in the editor search panel loading?: boolean } -type BS3FormControlProps = ComponentProps & { - 'main-field'?: any -} - const OLFormControl: BsPrefixRefForwardingComponent< 'input', OLFormControlProps > = forwardRef((props, ref) => { - const { bs3Props, append, ...rest } = props - - // Use a callback so that the ref passed to the BS3 FormControl is stable - const bs3InputRef = useCallback( - (inputElement: HTMLInputElement) => { - if (typeof ref === 'function') { - ref(inputElement) - } else if (ref) { - ref.current = inputElement - } - }, - [ref] - ) - - let bs3FormControlProps: BS3FormControlProps = { - inputRef: bs3InputRef, - componentClass: rest.as, - bsSize: rest.size, - id: rest.id, - name: rest.name, - className: rest.className, - style: rest.style, - type: rest.type, - value: rest.value, - defaultValue: rest.defaultValue, - required: rest.required, - disabled: rest.disabled, - placeholder: rest.placeholder, - readOnly: rest.readOnly, - autoComplete: rest.autoComplete, - autoFocus: rest.autoFocus, - minLength: rest.minLength, - maxLength: rest.maxLength, - onChange: rest.onChange as BS3FormControlProps['onChange'], - onKeyDown: rest.onKeyDown as BS3FormControlProps['onKeyDown'], - onFocus: rest.onFocus as BS3FormControlProps['onFocus'], - onBlur: rest.onBlur as BS3FormControlProps['onBlur'], - onInvalid: rest.onInvalid as BS3FormControlProps['onInvalid'], - onPaste: rest.onPaste as BS3FormControlProps['onPaste'], - prepend: rest.prepend, - size: rest.htmlSize, - 'main-field': rest['main-field'], - children: rest.children, - ...bs3Props, - } - - bs3FormControlProps = { - ...bs3FormControlProps, - ...getAriaAndDataProps(rest), - 'data-ol-dirty': rest['data-ol-dirty'], - } as typeof bs3FormControlProps & Record + const { append, ...rest } = props return ( - : append} - /> - } - bs5={ - : append} - /> - } + : append} /> ) }) diff --git a/services/web/frontend/js/features/ui/components/ol/ol-form-feedback.tsx b/services/web/frontend/js/features/ui/components/ol/ol-form-feedback.tsx index 2ff193e0d8..1c850c1ffc 100644 --- a/services/web/frontend/js/features/ui/components/ol/ol-form-feedback.tsx +++ b/services/web/frontend/js/features/ui/components/ol/ol-form-feedback.tsx @@ -1,38 +1,14 @@ import { Form } from 'react-bootstrap-5' -import { - HelpBlock as BS3HelpBlock, - HelpBlockProps as BS3HelpBlockProps, -} from 'react-bootstrap' -import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' import { ComponentProps } from 'react' -import classnames from 'classnames' import FormFeedback from '@/features/ui/components/bootstrap-5/form/form-feedback' type OLFormFeedbackProps = Pick< ComponentProps, 'type' | 'className' | 'children' -> & { - bs3Props?: Record -} +> function OLFormFeedback(props: OLFormFeedbackProps) { - const { bs3Props, children, ...bs5Props } = props - - const bs3HelpBlockProps: BS3HelpBlockProps = { - className: classnames( - bs5Props.className, - bs5Props.type === 'invalid' ? 'invalid-only' : null - ), - children, - ...bs3Props, - } - - return ( - } - bs5={{children}} - /> - ) + return } export default OLFormFeedback diff --git a/services/web/frontend/js/features/ui/components/ol/ol-form-group.tsx b/services/web/frontend/js/features/ui/components/ol/ol-form-group.tsx index 1da249865b..8ccc974d4e 100644 --- a/services/web/frontend/js/features/ui/components/ol/ol-form-group.tsx +++ b/services/web/frontend/js/features/ui/components/ol/ol-form-group.tsx @@ -1,42 +1,8 @@ import { FormGroupProps } from 'react-bootstrap-5' -import { - FormGroup as BS3FormGroup, - FormGroupProps as BS3FormGroupProps, - FormControl, -} from 'react-bootstrap' import FormGroup from '@/features/ui/components/bootstrap-5/form/form-group' -import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' -import classNames from 'classnames' -type OLFormGroupProps = FormGroupProps & { - bs3Props?: { - withFeedback?: boolean - hiddenLabel?: boolean - validationState?: BS3FormGroupProps['validationState'] - } -} - -function OLFormGroup(props: OLFormGroupProps) { - const { bs3Props, className, ...rest } = props - const { withFeedback, hiddenLabel, ...bs3PropsRest } = bs3Props || {} - - const bs3FormGroupProps: BS3FormGroupProps = { - controlId: rest.controlId, - className: classNames(className, { 'hidden-label': hiddenLabel }), - ...bs3PropsRest, - } - - return ( - - {rest.children} - {withFeedback ? : null} - - } - bs5={} - /> - ) +function OLFormGroup(props: FormGroupProps) { + return } export default OLFormGroup diff --git a/services/web/frontend/js/features/ui/components/ol/ol-form-label.tsx b/services/web/frontend/js/features/ui/components/ol/ol-form-label.tsx index 5ce2f7e556..1e1038f9e3 100644 --- a/services/web/frontend/js/features/ui/components/ol/ol-form-label.tsx +++ b/services/web/frontend/js/features/ui/components/ol/ol-form-label.tsx @@ -1,28 +1,7 @@ import { Form } from 'react-bootstrap-5' -import { ControlLabel as BS3FormLabel } from 'react-bootstrap' -import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' -type OLFormLabelProps = React.ComponentProps<(typeof Form)['Label']> & { - bs3Props?: Record -} - -function OLFormLabel(props: OLFormLabelProps) { - const { bs3Props, ...rest } = props - - const bs3FormLabelProps: React.ComponentProps = { - children: rest.children, - htmlFor: rest.htmlFor, - srOnly: rest.visuallyHidden, - className: rest.className, - ...bs3Props, - } - - return ( - } - bs5={} - /> - ) +function OLFormLabel(props: React.ComponentProps<(typeof Form)['Label']>) { + return } export default OLFormLabel diff --git a/services/web/frontend/js/features/ui/components/ol/ol-form-select.tsx b/services/web/frontend/js/features/ui/components/ol/ol-form-select.tsx index f9f757abcb..dfcd147dfd 100644 --- a/services/web/frontend/js/features/ui/components/ol/ol-form-select.tsx +++ b/services/web/frontend/js/features/ui/components/ol/ol-form-select.tsx @@ -1,56 +1,9 @@ import { forwardRef } from 'react' import { Form, FormSelectProps } from 'react-bootstrap-5' -import { - FormControl as BS3FormControl, - FormControlProps as BS3FormControlProps, -} from 'react-bootstrap' -import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' -import { getAriaAndDataProps } from '@/features/utils/bootstrap-5' -type OLFormSelectProps = FormSelectProps & { - bs3Props?: Record -} - -const OLFormSelect = forwardRef( +const OLFormSelect = forwardRef( (props, ref) => { - const { bs3Props, ...bs5Props } = props - - const bs3FormSelectProps: BS3FormControlProps = { - children: bs5Props.children, - bsSize: bs5Props.size, - name: bs5Props.name, - value: bs5Props.value, - defaultValue: bs5Props.defaultValue, - disabled: bs5Props.disabled, - onChange: bs5Props.onChange as BS3FormControlProps['onChange'], - required: bs5Props.required, - placeholder: bs5Props.placeholder, - className: bs5Props.className, - inputRef: (inputElement: HTMLInputElement) => { - if (typeof ref === 'function') { - ref(inputElement as unknown as HTMLSelectElement) - } else if (ref) { - ref.current = inputElement as unknown as HTMLSelectElement - } - }, - ...bs3Props, - } - - // Get all `aria-*` and `data-*` attributes - const extraProps = getAriaAndDataProps(bs5Props) - - return ( - - } - bs5={} - /> - ) + return } ) OLFormSelect.displayName = 'OLFormSelect' diff --git a/services/web/frontend/js/features/ui/components/ol/ol-form-switch.tsx b/services/web/frontend/js/features/ui/components/ol/ol-form-switch.tsx index b751642d8b..a9a6ffe041 100644 --- a/services/web/frontend/js/features/ui/components/ol/ol-form-switch.tsx +++ b/services/web/frontend/js/features/ui/components/ol/ol-form-switch.tsx @@ -1,53 +1,19 @@ import { FormCheck, FormCheckProps, FormLabel } from 'react-bootstrap-5' -import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' -import { getAriaAndDataProps } from '@/features/utils/bootstrap-5' type OLFormSwitchProps = FormCheckProps & { inputRef?: React.MutableRefObject - bs3Props?: React.InputHTMLAttributes } function OLFormSwitch(props: OLFormSwitchProps) { - const { bs3Props, inputRef, label, id, ...rest } = props - - const bs3FormSwitchProps: React.InputHTMLAttributes = { - id, - checked: rest.checked, - required: rest.required, - readOnly: rest.readOnly, - disabled: rest.disabled, - autoComplete: rest.autoComplete, - defaultChecked: rest.defaultChecked, - onChange: rest.onChange as (e: React.ChangeEvent) => void, - ...getAriaAndDataProps(rest), - ...bs3Props, - } + const { inputRef, label, id, ...rest } = props return ( - - - -
  • - } - bs5={ - <> - - - {label} - - - } - /> + <> + + + {label} + + ) } diff --git a/services/web/frontend/js/features/ui/components/ol/ol-form-text.tsx b/services/web/frontend/js/features/ui/components/ol/ol-form-text.tsx index d465eb4050..d35654fa79 100644 --- a/services/web/frontend/js/features/ui/components/ol/ol-form-text.tsx +++ b/services/web/frontend/js/features/ui/components/ol/ol-form-text.tsx @@ -1,36 +1,9 @@ import FormText, { FormTextProps, - getFormTextClass, } from '@/features/ui/components/bootstrap-5/form/form-text' -import PolymorphicComponent from '@/shared/components/polymorphic-component' -import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' -import classnames from 'classnames' -import { getAriaAndDataProps } from '@/features/utils/bootstrap-5' -type OLFormTextProps = FormTextProps & { - bs3Props?: Record -} - -function OLFormText({ as = 'div', ...props }: OLFormTextProps) { - const { bs3Props, ...rest } = props - - const bs3HelpBlockProps = { - children: rest.children, - className: classnames('small', rest.className, getFormTextClass(rest.type)), - ...bs3Props, - } as const satisfies React.ComponentProps - - // Get all `aria-*` and `data-*` attributes - const extraProps = getAriaAndDataProps(rest) - - return ( - - } - bs5={} - /> - ) +function OLFormText({ as = 'div', ...rest }: FormTextProps) { + return } export default OLFormText diff --git a/services/web/frontend/js/features/ui/components/ol/ol-form.tsx b/services/web/frontend/js/features/ui/components/ol/ol-form.tsx index 32fd5073ea..724578769e 100644 --- a/services/web/frontend/js/features/ui/components/ol/ol-form.tsx +++ b/services/web/frontend/js/features/ui/components/ol/ol-form.tsx @@ -1,45 +1,8 @@ import { Form } from 'react-bootstrap-5' -import { Form as BS3Form, FormProps as BS3FormProps } from 'react-bootstrap' -import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' import { ComponentProps } from 'react' -import classnames from 'classnames' -import { getAriaAndDataProps } from '@/features/utils/bootstrap-5' -type OLFormProps = ComponentProps & { - bs3Props?: ComponentProps -} - -function OLForm(props: OLFormProps) { - const { bs3Props, ...rest } = props - - const bs3FormProps: BS3FormProps = { - componentClass: rest.as, - children: rest.children, - id: rest.id, - onSubmit: rest.onSubmit as BS3FormProps['onSubmit'], - onClick: rest.onClick as BS3FormProps['onClick'], - name: rest.name, - noValidate: rest.noValidate, - role: rest.role, - ...bs3Props, - } - - const bs3ClassName = classnames( - rest.className, - rest.validated ? 'was-validated' : null - ) - - // Get all `aria-*` and `data-*` attributes - const extraProps = getAriaAndDataProps(rest) - - return ( - - } - bs5={
    } - /> - ) +function OLForm(props: ComponentProps) { + return } export default OLForm diff --git a/services/web/frontend/js/features/ui/components/ol/ol-icon-button.tsx b/services/web/frontend/js/features/ui/components/ol/ol-icon-button.tsx index 5d34b1c2ff..27e5960133 100644 --- a/services/web/frontend/js/features/ui/components/ol/ol-icon-button.tsx +++ b/services/web/frontend/js/features/ui/components/ol/ol-icon-button.tsx @@ -1,54 +1,13 @@ import { forwardRef } from 'react' -import { bs3ButtonProps, BS3ButtonSize } from './ol-button' -import { Button as BS3Button } from 'react-bootstrap' import type { IconButtonProps } from '@/features/ui/components/types/icon-button-props' -import BootstrapVersionSwitcher from '../bootstrap-5/bootstrap-version-switcher' -import Icon, { IconProps } from '@/shared/components/icon' import IconButton from '../bootstrap-5/icon-button' -import { callFnsInSequence } from '@/utils/functions' -export type OLIconButtonProps = IconButtonProps & { - bs3Props?: { - loading?: React.ReactNode - fw?: IconProps['fw'] - className?: string - bsSize?: BS3ButtonSize - onMouseOver?: React.MouseEventHandler - onMouseOut?: React.MouseEventHandler - onFocus?: React.FocusEventHandler - onBlur?: React.FocusEventHandler - } -} +export type OLIconButtonProps = IconButtonProps const OLIconButton = forwardRef( (props, ref) => { - const { bs3Props, ...rest } = props - - const { fw, loading, ...bs3Rest } = bs3Props || {} - - // BS3 OverlayTrigger automatically provides 'onMouseOver', 'onMouseOut', 'onFocus', 'onBlur' event handlers - const bs3FinalProps = { - 'aria-label': rest.accessibilityLabel, - ...bs3ButtonProps(rest), - ...bs3Rest, - onMouseOver: callFnsInSequence(bs3Props?.onMouseOver, rest.onMouseOver), - onMouseOut: callFnsInSequence(bs3Props?.onMouseOut, rest.onMouseOut), - onFocus: callFnsInSequence(bs3Props?.onFocus, rest.onFocus), - onBlur: callFnsInSequence(bs3Props?.onBlur, rest.onBlur), - } - - // BS3 tooltip relies on the 'onMouseOver', 'onMouseOut', 'onFocus', 'onBlur' props // BS5 tooltip relies on the ref - return ( - - {loading || } - - } - bs5={} - /> - ) + return } ) OLIconButton.displayName = 'OLIconButton' diff --git a/services/web/frontend/js/features/ui/components/ol/ol-list-group-item.tsx b/services/web/frontend/js/features/ui/components/ol/ol-list-group-item.tsx index c177ee3a1c..a27457fa7a 100644 --- a/services/web/frontend/js/features/ui/components/ol/ol-list-group-item.tsx +++ b/services/web/frontend/js/features/ui/components/ol/ol-list-group-item.tsx @@ -1,40 +1,13 @@ import { ListGroupItem, ListGroupItemProps } from 'react-bootstrap-5' -import { - ListGroupItem as BS3ListGroupItem, - ListGroupItemProps as BS3ListGroupItemProps, -} from 'react-bootstrap' -import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' -import { getAriaAndDataProps } from '@/features/utils/bootstrap-5' -type OLListGroupItemProps = ListGroupItemProps & { - bs3Props?: BS3ListGroupItemProps -} - -function OLListGroupItem(props: OLListGroupItemProps) { - const { bs3Props, ...rest } = props - - const bs3ListGroupItemProps: BS3ListGroupItemProps = { - children: rest.children, - active: rest.active, - disabled: rest.disabled, - href: rest.href, - onClick: rest.onClick as BS3ListGroupItemProps['onClick'], - ...bs3Props, - } - - const extraProps = getAriaAndDataProps(rest) - const as = rest.as ?? 'button' +function OLListGroupItem(props: ListGroupItemProps) { + const as = props.as ?? 'button' return ( - } - bs5={ - - } + ) } diff --git a/services/web/frontend/js/features/ui/components/ol/ol-list-group.tsx b/services/web/frontend/js/features/ui/components/ol/ol-list-group.tsx index 65af7b3ec3..a28c7e977d 100644 --- a/services/web/frontend/js/features/ui/components/ol/ol-list-group.tsx +++ b/services/web/frontend/js/features/ui/components/ol/ol-list-group.tsx @@ -1,34 +1,9 @@ import { ListGroup, ListGroupProps } from 'react-bootstrap-5' -import { - ListGroup as BS3ListGroup, - ListGroupProps as BS3ListGroupProps, -} from 'react-bootstrap' -import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' -import { getAriaAndDataProps } from '@/features/utils/bootstrap-5' -type OLListGroupProps = ListGroupProps & { - bs3Props?: BS3ListGroupProps -} +function OLListGroup(props: ListGroupProps) { + const as = props.as ?? 'div' -function OLListGroup(props: OLListGroupProps) { - const { bs3Props, ...rest } = props - - const bs3ListGroupProps: BS3ListGroupProps = { - children: rest.children, - role: rest.role, - componentClass: rest.as, - ...bs3Props, - } - - const extraProps = getAriaAndDataProps(rest) - const as = rest.as ?? 'div' - - return ( - } - bs5={} - /> - ) + return } export default OLListGroup diff --git a/services/web/frontend/js/features/ui/components/ol/ol-modal.tsx b/services/web/frontend/js/features/ui/components/ol/ol-modal.tsx index 43dcddcf87..bf20d18eef 100644 --- a/services/web/frontend/js/features/ui/components/ol/ol-modal.tsx +++ b/services/web/frontend/js/features/ui/components/ol/ol-modal.tsx @@ -1,133 +1,37 @@ import { - Modal as BS5Modal, + Modal, ModalProps, ModalHeaderProps, ModalTitleProps, - ModalBody, ModalFooterProps, } from 'react-bootstrap-5' -import { - Modal as BS3Modal, - ModalProps as BS3ModalProps, - ModalHeaderProps as BS3ModalHeaderProps, - ModalTitleProps as BS3ModalTitleProps, - ModalBodyProps as BS3ModalBodyProps, - ModalFooterProps as BS3ModalFooterProps, -} from 'react-bootstrap' -import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' -import AccessibleModal from '@/shared/components/accessible-modal' +import { ModalBodyProps } from 'react-bootstrap-5/ModalBody' type OLModalProps = ModalProps & { - bs3Props?: Record size?: 'sm' | 'lg' onHide: () => void } -type OLModalHeaderProps = ModalHeaderProps & { - bs3Props?: Record -} - -type OLModalTitleProps = ModalTitleProps & { - bs3Props?: Record -} - -type OLModalBodyProps = React.ComponentProps & { - bs3Props?: Record -} - -type OLModalFooterProps = ModalFooterProps & { - bs3Props?: Record -} - export default function OLModal({ children, ...props }: OLModalProps) { - const { bs3Props, ...bs5Props } = props + return {children} +} - const bs3ModalProps: BS3ModalProps = { - bsClass: bs5Props.bsPrefix, - bsSize: bs5Props.size, - show: bs5Props.show, - onHide: bs5Props.onHide, - onExited: bs5Props.onExited, - backdrop: bs5Props.backdrop, - animation: bs5Props.animation, - id: bs5Props.id, - className: bs5Props.className, - backdropClassName: bs5Props.backdropClassName, - ...bs3Props, - } +export function OLModalHeader({ children, ...props }: ModalHeaderProps) { + return {children} +} +export function OLModalTitle({ children, ...props }: ModalTitleProps) { return ( - {children}} - bs5={{children}} - /> + + {children} + ) } -export function OLModalHeader({ children, ...props }: OLModalHeaderProps) { - const { bs3Props, ...bs5Props } = props - - const bs3ModalProps: BS3ModalHeaderProps = { - bsClass: bs5Props.bsPrefix, - onHide: bs5Props.onHide, - closeButton: bs5Props.closeButton, - closeLabel: bs5Props.closeLabel, - } - return ( - {children}} - bs5={{children}} - /> - ) +export function OLModalBody({ children, ...props }: ModalBodyProps) { + return {children} } -export function OLModalTitle({ children, ...props }: OLModalTitleProps) { - const { bs3Props, ...bs5Props } = props - - const bs3ModalProps: BS3ModalTitleProps = { - componentClass: bs5Props.as, - } - - return ( - {children}} - bs5={ - - {children} - - } - /> - ) -} - -export function OLModalBody({ children, ...props }: OLModalBodyProps) { - const { bs3Props, ...bs5Props } = props - - const bs3ModalProps: BS3ModalBodyProps = { - componentClass: bs5Props.as, - className: bs5Props.className, - } - - return ( - {children}} - bs5={{children}} - /> - ) -} - -export function OLModalFooter({ children, ...props }: OLModalFooterProps) { - const { bs3Props, ...bs5Props } = props - - const bs3ModalProps: BS3ModalFooterProps = { - componentClass: bs5Props.as, - className: bs5Props.className, - } - - return ( - {children}} - bs5={{children}} - /> - ) +export function OLModalFooter({ children, ...props }: ModalFooterProps) { + return {children} } diff --git a/services/web/frontend/js/features/ui/components/ol/ol-notification.tsx b/services/web/frontend/js/features/ui/components/ol/ol-notification.tsx index e312d48c91..7ca811a796 100644 --- a/services/web/frontend/js/features/ui/components/ol/ol-notification.tsx +++ b/services/web/frontend/js/features/ui/components/ol/ol-notification.tsx @@ -1,42 +1,10 @@ import Notification from '@/shared/components/notification' -import { Alert, AlertProps } from 'react-bootstrap' -import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' -import classnames from 'classnames' - -type OLNotificationProps = React.ComponentProps & { - bs3Props?: { - icon?: React.ReactElement - className?: string - } -} - -function OLNotification(props: OLNotificationProps) { - const { bs3Props, ...notificationProps } = props - - const alertProps = { - // Map `error` to `danger` - bsStyle: - notificationProps.type === 'error' ? 'danger' : notificationProps.type, - className: classnames(notificationProps.className, bs3Props?.className), - onDismiss: notificationProps.onDismiss, - } as const satisfies AlertProps +function OLNotification(props: React.ComponentProps) { return ( - - {bs3Props?.icon} - {bs3Props?.icon && ' '} - {notificationProps.content} - {notificationProps.action} - - } - bs5={ -
    - -
    - } - /> +
    + +
    ) } diff --git a/services/web/frontend/js/features/ui/components/ol/ol-overlay.tsx b/services/web/frontend/js/features/ui/components/ol/ol-overlay.tsx index 40b7872bc8..bcf2a024c2 100644 --- a/services/web/frontend/js/features/ui/components/ol/ol-overlay.tsx +++ b/services/web/frontend/js/features/ui/components/ol/ol-overlay.tsx @@ -1,61 +1,7 @@ import { Overlay, OverlayProps } from 'react-bootstrap-5' -import { - Overlay as BS3Overlay, - OverlayProps as BS3OverlayProps, -} from 'react-bootstrap' -import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' -type OLOverlayProps = OverlayProps & { - bs3Props?: BS3OverlayProps -} - -function OLOverlay(props: OLOverlayProps) { - const { bs3Props, ...bs5Props } = props - - let bs3OverlayProps: BS3OverlayProps = { - children: bs5Props.children, - target: bs5Props.target as BS3OverlayProps['target'], - container: bs5Props.container, - containerPadding: bs5Props.containerPadding, - show: bs5Props.show, - rootClose: bs5Props.rootClose, - animation: bs5Props.transition, - onHide: bs5Props.onHide as BS3OverlayProps['onHide'], - onEnter: bs5Props.onEnter as BS3OverlayProps['onEnter'], - onEntering: bs5Props.onEntering as BS3OverlayProps['onEntering'], - onEntered: bs5Props.onEntered as BS3OverlayProps['onEntered'], - onExit: bs5Props.onExit as BS3OverlayProps['onExit'], - onExiting: bs5Props.onExiting as BS3OverlayProps['onExiting'], - onExited: bs5Props.onExited as BS3OverlayProps['onExited'], - } - - if (bs5Props.placement) { - const bs3PlacementOptions = [ - 'top', - 'right', - 'bottom', - 'left', - ] satisfies Array< - Extract - > - - for (const placement of bs3PlacementOptions) { - // BS5 has more placement options than BS3, such as "left-start", so these are mapped to "left" etc. - if (bs5Props.placement.startsWith(placement)) { - bs3OverlayProps.placement = placement - break - } - } - } - - bs3OverlayProps = { ...bs3OverlayProps, ...bs3Props } - - return ( - } - bs5={} - /> - ) +function OLOverlay(props: OverlayProps) { + return } export default OLOverlay diff --git a/services/web/frontend/js/features/ui/components/ol/ol-page-content-card.tsx b/services/web/frontend/js/features/ui/components/ol/ol-page-content-card.tsx index ba6fc75ff9..549e63a5c1 100644 --- a/services/web/frontend/js/features/ui/components/ol/ol-page-content-card.tsx +++ b/services/web/frontend/js/features/ui/components/ol/ol-page-content-card.tsx @@ -1,24 +1,18 @@ import { Card, CardBody } from 'react-bootstrap-5' -import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' import { FC } from 'react' import classNames from 'classnames' // This wraps the Bootstrap 5 Card component but is restricted to the very // basic way we're using it, which is as a container for page content. The -// Bootstrap 3 equivalent in our codebase is a div with class "card" +// Bootstrap 3 equivalent previously in our codebase is a div with class "card" const OLPageContentCard: FC<{ className?: string }> = ({ children, className, }) => { return ( - {children}} - bs5={ - - {children} - - } - /> + + {children} + ) } diff --git a/services/web/frontend/js/features/ui/components/ol/ol-popover.tsx b/services/web/frontend/js/features/ui/components/ol/ol-popover.tsx index fbf74d3225..772084bc22 100644 --- a/services/web/frontend/js/features/ui/components/ol/ol-popover.tsx +++ b/services/web/frontend/js/features/ui/components/ol/ol-popover.tsx @@ -1,83 +1,18 @@ import { forwardRef } from 'react' import { Popover, PopoverProps } from 'react-bootstrap-5' -import { - Popover as BS3Popover, - PopoverProps as BS3PopoverProps, -} from 'react-bootstrap' -import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' type OLPopoverProps = Omit & { title?: React.ReactNode - bs3Props?: BS3PopoverProps } const OLPopover = forwardRef((props, ref) => { - // BS3 passes in some props automatically so the `props` - // type should be adjusted to reflect the actual received object - const propsCombinedWithAutoInjectedBs3Props = props as OLPopoverProps & - Pick< - BS3PopoverProps, - 'arrowOffsetLeft' | 'arrowOffsetTop' | 'positionLeft' | 'positionTop' - > - - const { - bs3Props, - title, - children, - arrowOffsetLeft, - arrowOffsetTop, - positionLeft, - positionTop, - ...bs5Props - } = propsCombinedWithAutoInjectedBs3Props - - let bs3PopoverProps: BS3PopoverProps = { - children, - arrowOffsetLeft, - arrowOffsetTop, - positionLeft, - positionTop, - title, - id: bs5Props.id, - className: bs5Props.className, - style: bs5Props.style, - } - - if (bs5Props.placement) { - const bs3PlacementOptions = [ - 'top', - 'right', - 'bottom', - 'left', - ] satisfies Array< - Extract - > - - for (const placement of bs3PlacementOptions) { - if (placement === bs5Props.placement) { - bs3PopoverProps.placement = bs5Props.placement - break - } - } - } - - bs3PopoverProps = { ...bs3PopoverProps, ...bs3Props } + const { title, children, ...bs5Props } = props return ( - } - /> - } - bs5={ - - {title && {title}} - {children} - - } - /> + + {title && {title}} + {children} + ) }) OLPopover.displayName = 'OLPopover' diff --git a/services/web/frontend/js/features/ui/components/ol/ol-row.tsx b/services/web/frontend/js/features/ui/components/ol/ol-row.tsx index ef68a6887f..88c05ce102 100644 --- a/services/web/frontend/js/features/ui/components/ol/ol-row.tsx +++ b/services/web/frontend/js/features/ui/components/ol/ol-row.tsx @@ -1,16 +1,7 @@ import { Row } from 'react-bootstrap-5' -import { Row as BS3Row } from 'react-bootstrap' -import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' -type OLRowProps = React.ComponentProps - -function OLRow(props: OLRowProps) { - return ( - {props.children}} - bs5={} - /> - ) +function OLRow(props: React.ComponentProps) { + return } export default OLRow diff --git a/services/web/frontend/js/features/ui/components/ol/ol-spinner.tsx b/services/web/frontend/js/features/ui/components/ol/ol-spinner.tsx index 615f5acd47..4c1be6b125 100644 --- a/services/web/frontend/js/features/ui/components/ol/ol-spinner.tsx +++ b/services/web/frontend/js/features/ui/components/ol/ol-spinner.tsx @@ -1,29 +1,14 @@ -import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher' -import Icon from '@/shared/components/icon' import { Spinner } from 'react-bootstrap-5' -import classNames from 'classnames' export type OLSpinnerSize = 'sm' | 'lg' function OLSpinner({ size = 'sm' }: { size: OLSpinnerSize }) { return ( - - } - bs5={ -