Merge pull request #24660 from overleaf/td-bs5-remove-react-bootstrap-0
Remove react-bootstrap 0.33.1 GitOrigin-RevId: c320a6b18c576afdc0fd49559915d3d2f3a7a1ef
This commit is contained in:
Generated
-128
@@ -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",
|
||||
|
||||
@@ -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 (
|
||||
<div
|
||||
@@ -179,12 +159,8 @@ const preview: Preview = {
|
||||
context.globals.theme === 'main-light-' ? 'light' : 'default'
|
||||
}
|
||||
>
|
||||
{activeStyle && <style>{activeStyle.default}</style>}
|
||||
<Story
|
||||
{...context}
|
||||
// force re-renders when switching between Bootstrap versions
|
||||
key={bootstrapVersion}
|
||||
/>
|
||||
{mainStyle && <style>{mainStyle.default}</style>}
|
||||
<Story {...context} />
|
||||
</div>
|
||||
)
|
||||
},
|
||||
|
||||
@@ -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',
|
||||
},
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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<undefined, { bsRole: string }>(
|
||||
({ bsRole }, ref) => {
|
||||
return null
|
||||
}
|
||||
)
|
||||
|
||||
FakeDropDownToggle.displayName = 'FakeDropDownToggle'
|
||||
|
||||
export default FileTreeContextMenu
|
||||
|
||||
@@ -11,10 +11,7 @@ function ChangeList() {
|
||||
<div className="history-header history-toggle-switch-container">
|
||||
<ToggleSwitch labelsOnly={labelsOnly} setLabelsOnly={setLabelsOnly} />
|
||||
</div>
|
||||
<div
|
||||
className="history-version-list-container"
|
||||
data-history-version-list-container
|
||||
>
|
||||
<div className="history-version-list-container">
|
||||
{labelsOnly ? <LabelsList /> : <AllHistoryList />}
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
+6
-16
@@ -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<ActionDropdownProps, 'parentSelector'>) {
|
||||
function ActionsDropdown(props: ActionDropdownProps) {
|
||||
const { id, children, isOpened, iconTag, setIsOpened, toolTipDescription } =
|
||||
props
|
||||
return (
|
||||
<Dropdown
|
||||
align="end"
|
||||
@@ -30,7 +24,7 @@ function BS5ActionsDropdown({
|
||||
show={isOpened}
|
||||
onToggle={open => setIsOpened(open)}
|
||||
>
|
||||
<BS5DropdownToggleWithTooltip
|
||||
<DropdownToggleWithTooltip
|
||||
id={`history-version-dropdown-${id}`}
|
||||
className="history-version-dropdown-menu-btn"
|
||||
aria-label={toolTipDescription}
|
||||
@@ -39,7 +33,7 @@ function BS5ActionsDropdown({
|
||||
tooltipProps={{ hidden: isOpened }}
|
||||
>
|
||||
{iconTag}
|
||||
</BS5DropdownToggleWithTooltip>
|
||||
</DropdownToggleWithTooltip>
|
||||
<DropdownMenu className="history-version-dropdown-menu">
|
||||
{children}
|
||||
</DropdownMenu>
|
||||
@@ -47,8 +41,4 @@ function BS5ActionsDropdown({
|
||||
)
|
||||
}
|
||||
|
||||
function ActionsDropdown(props: ActionDropdownProps) {
|
||||
return <BS5ActionsDropdown {...props} />
|
||||
}
|
||||
|
||||
export default ActionsDropdown
|
||||
|
||||
-1
@@ -21,7 +21,6 @@ function CompareVersionDropdown({
|
||||
id={id}
|
||||
isOpened={isOpened}
|
||||
setIsOpened={setIsOpened}
|
||||
parentSelector="[data-history-version-list-container]"
|
||||
toolTipDescription={t('compare')}
|
||||
iconTag={
|
||||
<MaterialIcon
|
||||
|
||||
-1
@@ -25,7 +25,6 @@ function HistoryDropdown({
|
||||
iconTag={
|
||||
<MaterialIcon type="more_vert" accessibilityLabel={t('more_actions')} />
|
||||
}
|
||||
parentSelector="[data-history-version-list-container]"
|
||||
>
|
||||
{children}
|
||||
</ActionsDropdown>
|
||||
|
||||
+1
-2
@@ -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<typeof AccessibleModal>,
|
||||
React.ComponentProps<typeof OLModal>,
|
||||
{
|
||||
email: string
|
||||
isConfirmDisabled: boolean
|
||||
|
||||
-3
@@ -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}
|
||||
<Trans
|
||||
i18nKey="are_you_still_at"
|
||||
values={{
|
||||
|
||||
+12
-32
@@ -3,8 +3,6 @@ import { useTranslation } from 'react-i18next'
|
||||
import { useLocation } from '@/shared/hooks/use-location'
|
||||
import MaterialIcon from '@/shared/components/material-icon'
|
||||
import OLTag from '@/features/ui/components/ol/ol-tag'
|
||||
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
|
||||
import { bsVersion } from '@/features/utils/bootstrap-5'
|
||||
import { ManagedGroupSubscription } from '../../../../../../types/subscription/dashboard/subscription'
|
||||
import { sendMB } from '../../../../infrastructure/event-tracking'
|
||||
import starIcon from '../../images/star-gradient.svg'
|
||||
@@ -24,7 +22,7 @@ function AvailableWithGroupProfessionalBadge() {
|
||||
<OLTag
|
||||
prepend={<img aria-hidden="true" src={starIcon} alt="" />}
|
||||
contentProps={{
|
||||
className: bsVersion({ bs5: 'mw-100' }),
|
||||
className: 'mw-100',
|
||||
onClick: handleUpgradeClick,
|
||||
}}
|
||||
>
|
||||
@@ -82,35 +80,17 @@ export function GroupSettingsButtonWithAdBadge({
|
||||
useGroupSettingsButton(subscription)
|
||||
|
||||
return (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={
|
||||
<div className="row-link text-muted">
|
||||
<div className="icon">
|
||||
<MaterialIcon type="settings" />
|
||||
</div>
|
||||
<div className="text">
|
||||
<div className="heading">{heading}</div>
|
||||
<div className="subtext">{groupSettingRowSubText}</div>
|
||||
</div>
|
||||
<span>
|
||||
<AvailableWithGroupProfessionalBadge />
|
||||
</span>
|
||||
<li className="list-group-item row-link">
|
||||
<div className="row-link-inner">
|
||||
<MaterialIcon type="settings" className="p-2 p-md-3 text-muted" />
|
||||
<div className="flex-grow-1 text-truncate text-muted">
|
||||
<strong>{heading}</strong>
|
||||
<div className="text-truncate">{groupSettingRowSubText}</div>
|
||||
</div>
|
||||
}
|
||||
bs5={
|
||||
<li className="list-group-item row-link">
|
||||
<div className="row-link-inner">
|
||||
<MaterialIcon type="settings" className="p-2 p-md-3 text-muted" />
|
||||
<div className="flex-grow-1 text-truncate text-muted">
|
||||
<strong>{heading}</strong>
|
||||
<div className="text-truncate">{groupSettingRowSubText}</div>
|
||||
</div>
|
||||
<span className="p-2 p-md-3">
|
||||
<AvailableWithGroupProfessionalBadge />
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
}
|
||||
/>
|
||||
<span className="p-2 p-md-3">
|
||||
<AvailableWithGroupProfessionalBadge />
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
)
|
||||
}
|
||||
|
||||
-5
@@ -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')}
|
||||
</OLButton>
|
||||
|
||||
+1
-5
@@ -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 (
|
||||
<div key={`managed-group-${subscription._id}`}>
|
||||
<h2 className={classnames('h3', bsVersion({ bs5: 'fw-bold' }))}>
|
||||
{t('group_management')}
|
||||
</h2>
|
||||
<h2 className="h3 fw-bold">{t('group_management')}</h2>
|
||||
<p>
|
||||
<ManagedGroupAdministrator subscription={subscription} />
|
||||
</p>
|
||||
|
||||
-3
@@ -51,9 +51,6 @@ function PersonalSubscriptionRecurlySyncEmail() {
|
||||
disabled={isLoading}
|
||||
isLoading={isLoading}
|
||||
loadingLabel={t('updating')}
|
||||
bs3Props={{
|
||||
loading: isLoading ? t('updating') + '…' : t('update'),
|
||||
}}
|
||||
>
|
||||
{t('update')}
|
||||
</OLButton>
|
||||
|
||||
@@ -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() ? <BS5RowLink {...props} /> : <BS3RowLink {...props} />
|
||||
}
|
||||
|
||||
function BS3RowLink({ href, heading, subtext, icon }: RowLinkProps) {
|
||||
return (
|
||||
<a href={href} className="row-link">
|
||||
<div className="icon">
|
||||
<MaterialIcon type={icon} />
|
||||
</div>
|
||||
<div className="text">
|
||||
<div className="heading">{heading}</div>
|
||||
<div className="subtext">{subtext}</div>
|
||||
</div>
|
||||
<div className="icon arrow">
|
||||
<MaterialIcon type="keyboard_arrow_right" />
|
||||
</div>
|
||||
</a>
|
||||
)
|
||||
}
|
||||
|
||||
function BS5RowLink({ href, heading, subtext, icon }: RowLinkProps) {
|
||||
export function RowLink({ href, heading, subtext, icon }: RowLinkProps) {
|
||||
return (
|
||||
<li className="list-group-item row-link">
|
||||
<a href={href} className="row-link-inner">
|
||||
|
||||
+3
-11
@@ -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({
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<h2 className={classnames('h3', bsVersion({ bs5: 'fw-bold' }))}>
|
||||
{t('billing')}
|
||||
</h2>
|
||||
<h2 className="h3 fw-bold">{t('billing')}</h2>
|
||||
<p className="mb-1">
|
||||
{subscription.plan.annual ? (
|
||||
<Trans
|
||||
@@ -169,12 +165,8 @@ export function ActiveSubscriptionNew({
|
||||
)}
|
||||
</div>
|
||||
<hr />
|
||||
<h2 className={classnames('h3', bsVersion({ bs5: 'fw-bold' }))}>
|
||||
{t('plan')}
|
||||
</h2>
|
||||
<h3 className={classnames('h5 mt-0 mb-1', bsVersion({ bs5: 'fw-bold' }))}>
|
||||
{planName}
|
||||
</h3>
|
||||
<h2 className="h3 fw-bold">{t('plan')}</h2>
|
||||
<h3 className="h5 mt-0 mb-1 fw-bold">{planName}</h3>
|
||||
{subscription.pendingPlan &&
|
||||
subscription.pendingPlan.name !== subscription.plan.name && (
|
||||
<p className="mb-1">{t('want_change_to_apply_before_plan_end')}</p>
|
||||
|
||||
-3
@@ -41,9 +41,6 @@ export default function DowngradePlanButton({
|
||||
disabled={isButtonDisabled}
|
||||
isLoading={isLoading}
|
||||
loadingLabel={t('processing_uppercase') + '…'}
|
||||
bs3Props={{
|
||||
loading: isLoading ? t('processing_uppercase') + '…' : buttonText,
|
||||
}}
|
||||
>
|
||||
{buttonText}
|
||||
</OLButton>
|
||||
|
||||
-3
@@ -34,9 +34,6 @@ export default function ExtendTrialButton({
|
||||
disabled={isButtonDisabled}
|
||||
isLoading={isLoading}
|
||||
loadingLabel={t('processing_uppercase') + '…'}
|
||||
bs3Props={{
|
||||
loading: isLoading ? t('processing_uppercase') + '…' : buttonText,
|
||||
}}
|
||||
>
|
||||
{buttonText}
|
||||
</OLButton>
|
||||
|
||||
-5
@@ -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')}
|
||||
</OLButton>
|
||||
|
||||
+1
-13
@@ -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({
|
||||
})}
|
||||
</span>
|
||||
|
||||
<BootstrapVersionSwitcher bs3={<br />} />
|
||||
|
||||
<span className="circle-subtext">
|
||||
<span aria-hidden>
|
||||
{t('x_price_per_user', {
|
||||
@@ -221,10 +217,7 @@ export function ChangeToGroupModal() {
|
||||
<fieldset className="form-group">
|
||||
<legend className="legend-as-label">{t('plan')}</legend>
|
||||
{groupPlans.plans.map(option => (
|
||||
<div
|
||||
className={bsVersion({ bs3: 'radio' })}
|
||||
key={option.code}
|
||||
>
|
||||
<div key={option.code}>
|
||||
<OLFormCheckbox
|
||||
type="radio"
|
||||
name="plan-code"
|
||||
@@ -333,11 +326,6 @@ export function ChangeToGroupModal() {
|
||||
onClick={upgrade}
|
||||
isLoading={inflight}
|
||||
loadingLabel={t('processing_uppercase') + '…'}
|
||||
bs3Props={{
|
||||
loading: inflight
|
||||
? t('processing_uppercase') + '…'
|
||||
: t('upgrade_now'),
|
||||
}}
|
||||
>
|
||||
{t('upgrade_now')}
|
||||
</OLButton>
|
||||
|
||||
-5
@@ -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')}
|
||||
</OLButton>
|
||||
|
||||
-5
@@ -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')}
|
||||
</OLButton>
|
||||
|
||||
-71
@@ -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<DropdownProps, 'bsClass' | 'open' | 'pullRight' | 'onClose'>,
|
||||
{
|
||||
children: React.ReactNode
|
||||
bsRole: 'menu'
|
||||
menuRef: React.MutableRefObject<HTMLElement | undefined>
|
||||
className?: string
|
||||
// The props below are passed by react-bootstrap
|
||||
labelledBy?: string | undefined
|
||||
rootCloseEvent?: 'click' | 'mousedown' | undefined
|
||||
onClose?: (e: SyntheticEvent<any>) => 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 (
|
||||
<RootCloseWrapper
|
||||
disabled={!open}
|
||||
onRootClose={onClose}
|
||||
event={rootCloseEvent}
|
||||
>
|
||||
<ul
|
||||
role={bsRole}
|
||||
className={classnames(className, bsClass, {
|
||||
'dropdown-menu-right': pullRight,
|
||||
})}
|
||||
aria-labelledby={labelledBy}
|
||||
ref={handleRefs}
|
||||
{...rest}
|
||||
>
|
||||
{children}
|
||||
</ul>
|
||||
</RootCloseWrapper>
|
||||
)
|
||||
})
|
||||
DropdownMenuWithRef.displayName = 'DropdownMenuWithRef'
|
||||
|
||||
export default DropdownMenuWithRef
|
||||
-53
@@ -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<DropdownProps, 'bsClass' | 'open'>,
|
||||
{
|
||||
children: React.ReactNode
|
||||
isOpened: boolean
|
||||
bsRole: 'toggle'
|
||||
className?: string
|
||||
tooltipProps: Omit<React.ComponentProps<typeof Tooltip>, 'children'>
|
||||
}
|
||||
>
|
||||
|
||||
const DropdownToggleWithTooltip = forwardRef<
|
||||
HTMLButtonElement,
|
||||
CustomToggleProps
|
||||
>(function (props, ref) {
|
||||
const {
|
||||
tooltipProps,
|
||||
isOpened,
|
||||
children,
|
||||
bsClass,
|
||||
className,
|
||||
open,
|
||||
bsRole: _bsRole,
|
||||
...rest
|
||||
} = props
|
||||
|
||||
const button = (
|
||||
<button
|
||||
type="button"
|
||||
ref={ref}
|
||||
className={classnames(bsClass, 'btn', className)}
|
||||
aria-expanded={open}
|
||||
aria-haspopup="true"
|
||||
{...rest}
|
||||
>
|
||||
{children}
|
||||
</button>
|
||||
)
|
||||
|
||||
return (
|
||||
<>{isOpened ? button : <Tooltip {...tooltipProps}>{button}</Tooltip>}</>
|
||||
)
|
||||
})
|
||||
|
||||
DropdownToggleWithTooltip.displayName = 'DropdownToggleWithTooltip'
|
||||
|
||||
export default DropdownToggleWithTooltip
|
||||
@@ -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 && <div className="form-control-feedback-left">{prepend}</div>}
|
||||
<BS3FormControl {...props} />
|
||||
{append && <div className="form-control-feedback">{append}</div>}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default FormControl
|
||||
@@ -1,14 +0,0 @@
|
||||
import classNames from 'classnames'
|
||||
import { FC, HTMLProps } from 'react'
|
||||
|
||||
export const ToastContainer: FC<HTMLProps<HTMLDivElement>> = ({
|
||||
children,
|
||||
className,
|
||||
...props
|
||||
}) => {
|
||||
return (
|
||||
<div className={classNames('toast-container', className)} {...props}>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -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<ToastProps> = ({
|
||||
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 (
|
||||
<div
|
||||
className={classNames('toast', show ? 'show' : 'hide', className)}
|
||||
aria-live="assertive"
|
||||
role="alert"
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -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<T extends string | number>({
|
||||
children,
|
||||
value,
|
||||
defaultValue,
|
||||
onChange,
|
||||
...props
|
||||
}: BS3ToggleButtonGroupProps) {
|
||||
const [selectedValue, setSelectedValue] = useState<T | T[] | null>(
|
||||
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 (
|
||||
<BS3ToggleButtonGroup
|
||||
{...props}
|
||||
value={isControlled ? value : undefined}
|
||||
defaultValue={defaultValue}
|
||||
// Ignore the broken onChange handler
|
||||
onChange={() => {}}
|
||||
>
|
||||
{modifiedChildren}
|
||||
</BS3ToggleButtonGroup>
|
||||
)
|
||||
}
|
||||
|
||||
export default ToggleButtonGroup
|
||||
-15
@@ -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
|
||||
@@ -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 (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={<Icon type="tag" fw />}
|
||||
bs5={<MaterialIcon type="sell" />}
|
||||
/>
|
||||
)
|
||||
return <MaterialIcon type="sell" />
|
||||
}
|
||||
|
||||
@@ -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<typeof Badge> & {
|
||||
bs3Props?: {
|
||||
bsStyle?: React.ComponentProps<typeof Label>['bsStyle'] | null
|
||||
}
|
||||
}
|
||||
|
||||
function OLBadge(props: OLBadgeProps) {
|
||||
const { bs3Props, ...rest } = props
|
||||
|
||||
let bs3BadgeProps: React.ComponentProps<typeof BS3Badge> = {
|
||||
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 (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={<BS3Badge {...bs3BadgeProps} />}
|
||||
bs5={<Badge {...rest} />}
|
||||
/>
|
||||
)
|
||||
function OLBadge(props: React.ComponentProps<typeof Badge>) {
|
||||
return <Badge {...props} />
|
||||
}
|
||||
|
||||
export default OLBadge
|
||||
|
||||
@@ -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<string, unknown>
|
||||
}
|
||||
|
||||
function OLButtonGroup({ bs3Props, as, ...rest }: OLButtonGroupProps) {
|
||||
const bs3ButtonGroupProps: BS3ButtonGroupProps = {
|
||||
children: rest.children,
|
||||
className: rest.className,
|
||||
vertical: rest.vertical,
|
||||
...getAriaAndDataProps(rest),
|
||||
...bs3Props,
|
||||
}
|
||||
|
||||
return (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={<BS3ButtonGroup {...bs3ButtonGroupProps} />}
|
||||
bs5={<ButtonGroup {...rest} as={as} />}
|
||||
/>
|
||||
)
|
||||
function OLButtonGroup({ as, ...rest }: ButtonGroupProps) {
|
||||
return <ButtonGroup {...rest} as={as} />
|
||||
}
|
||||
|
||||
export default OLButtonGroup
|
||||
|
||||
@@ -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<string, unknown>
|
||||
}
|
||||
|
||||
function OLButtonToolbar(props: OLButtonToolbarProps) {
|
||||
const { bs3Props, ...rest } = props
|
||||
|
||||
const bs3ButtonToolbarProps: BS3ButtonToolbarProps = {
|
||||
children: rest.children,
|
||||
className: rest.className,
|
||||
...getAriaAndDataProps(rest),
|
||||
...bs3Props,
|
||||
}
|
||||
|
||||
return (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={<BS3ButtonToolbar {...bs3ButtonToolbarProps} />}
|
||||
bs5={<ButtonToolbar {...rest} />}
|
||||
/>
|
||||
)
|
||||
function OLButtonToolbar(props: ButtonToolbarProps) {
|
||||
return <ButtonToolbar {...props} />
|
||||
}
|
||||
|
||||
export default OLButtonToolbar
|
||||
|
||||
@@ -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<HTMLButtonElement>
|
||||
onMouseOut?: React.MouseEventHandler<HTMLButtonElement>
|
||||
onFocus?: React.FocusEventHandler<HTMLButtonElement>
|
||||
onBlur?: React.FocusEventHandler<HTMLButtonElement>
|
||||
}
|
||||
}
|
||||
const OLButton = forwardRef<HTMLButtonElement, OLButtonProps>((props, ref) => {
|
||||
return <Button {...props} ref={ref} />
|
||||
})
|
||||
|
||||
// Resolve type mismatch of the onClick event handler
|
||||
export type BS3ButtonProps = Omit<BS3ButtonPropsBase, 'onClick'> & {
|
||||
onClick?: React.MouseEventHandler<any>
|
||||
}
|
||||
|
||||
export function bs3ButtonProps(props: ButtonProps) {
|
||||
const bs3ButtonProps: BS3ButtonProps = {
|
||||
bsStyle: null,
|
||||
bsSize: props.size,
|
||||
className: classnames(`btn-${props.variant || 'primary'}`, props.className),
|
||||
disabled: props.isLoading || props.disabled,
|
||||
form: props.form,
|
||||
href: props.href,
|
||||
id: props.id,
|
||||
target: props.target,
|
||||
rel: props.rel,
|
||||
onClick: props.onClick,
|
||||
onMouseDown: props.onMouseDown as BS3ButtonProps['onMouseDown'],
|
||||
type: props.type,
|
||||
draggable: props.draggable,
|
||||
download: props.download,
|
||||
style: props.style,
|
||||
active: props.active,
|
||||
}
|
||||
return bs3ButtonProps
|
||||
}
|
||||
|
||||
function BS3ButtonContent({
|
||||
children,
|
||||
leadingIcon,
|
||||
trailingIcon,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
leadingIcon: OLButtonProps['leadingIcon']
|
||||
trailingIcon: OLButtonProps['trailingIcon']
|
||||
}) {
|
||||
const leadingIconComponent =
|
||||
leadingIcon && typeof leadingIcon === 'string' ? (
|
||||
<Icon type={leadingIcon} />
|
||||
) : (
|
||||
leadingIcon
|
||||
)
|
||||
|
||||
const trailingIconComponent =
|
||||
trailingIcon && typeof trailingIcon === 'string' ? (
|
||||
<Icon type={trailingIcon} />
|
||||
) : (
|
||||
trailingIcon
|
||||
)
|
||||
|
||||
return (
|
||||
<>
|
||||
{leadingIconComponent ? <>{leadingIconComponent} </> : null}
|
||||
{children}
|
||||
{trailingIconComponent ? <> {trailingIconComponent}</> : null}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const OLButton = forwardRef<HTMLButtonElement, OLButtonProps>(
|
||||
({ bs3Props = {}, ...rest }, ref) => {
|
||||
const { className: _, ...restBs3Props } = bs3Props
|
||||
|
||||
// BS3 OverlayTrigger automatically provides 'onMouseOver', 'onMouseOut', 'onFocus', 'onBlur' event handlers
|
||||
const bs3FinalProps = {
|
||||
...restBs3Props,
|
||||
onMouseOver: callFnsInSequence(bs3Props?.onMouseOver, rest.onMouseOver),
|
||||
onMouseOut: callFnsInSequence(bs3Props?.onMouseOut, rest.onMouseOut),
|
||||
onFocus: callFnsInSequence(bs3Props?.onFocus, rest.onFocus),
|
||||
onBlur: callFnsInSequence(bs3Props?.onBlur, rest.onBlur),
|
||||
}
|
||||
|
||||
// Get all `aria-*` and `data-*` attributes
|
||||
const extraProps = getAriaAndDataProps(rest)
|
||||
|
||||
return (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={
|
||||
<BS3Button
|
||||
{...bs3ButtonProps({
|
||||
...rest,
|
||||
// Override the `className` with bs3 specific className (if provided)
|
||||
className: bs3Props?.className ?? rest.className,
|
||||
})}
|
||||
{...extraProps}
|
||||
{...bs3FinalProps}
|
||||
ref={ref as React.LegacyRef<any> | undefined}
|
||||
>
|
||||
{bs3Props?.loading || (
|
||||
<BS3ButtonContent
|
||||
leadingIcon={rest.leadingIcon}
|
||||
trailingIcon={rest.trailingIcon}
|
||||
>
|
||||
{rest.children}
|
||||
</BS3ButtonContent>
|
||||
)}
|
||||
</BS3Button>
|
||||
}
|
||||
bs5={<Button {...rest} ref={ref} />}
|
||||
/>
|
||||
)
|
||||
}
|
||||
)
|
||||
OLButton.displayName = 'OLButton'
|
||||
|
||||
export default OLButton
|
||||
|
||||
@@ -1,18 +1,11 @@
|
||||
import { Card } from 'react-bootstrap-5'
|
||||
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
|
||||
import { FC } from 'react'
|
||||
import classNames from 'classnames'
|
||||
|
||||
const OLCard: FC<{ className?: string }> = ({ children, className }) => {
|
||||
return (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={<div className={classNames('card', className)}>{children}</div>}
|
||||
bs5={
|
||||
<Card className={className}>
|
||||
<Card.Body>{children}</Card.Body>
|
||||
</Card>
|
||||
}
|
||||
/>
|
||||
<Card className={className}>
|
||||
<Card.Body>{children}</Card.Body>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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<HTMLButtonElement, CloseButtonProps>(
|
||||
(props, ref) => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
const bs3CloseButtonProps: React.ButtonHTMLAttributes<HTMLButtonElement> = {
|
||||
className: classNames('close', props.className),
|
||||
onClick: props.onClick,
|
||||
onMouseOver: props.onMouseOver,
|
||||
onMouseOut: props.onMouseOut,
|
||||
|
||||
'aria-label': t('close'),
|
||||
}
|
||||
|
||||
return (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={
|
||||
<button {...bs3CloseButtonProps}>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
}
|
||||
bs5={<CloseButton ref={ref} {...props} />}
|
||||
/>
|
||||
)
|
||||
return <CloseButton ref={ref} aria-label={t('close')} {...props} />
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -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<typeof Col> & {
|
||||
bs3Props?: Record<string, unknown>
|
||||
}
|
||||
|
||||
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<string, (typeof rest)['xs']>
|
||||
)
|
||||
|
||||
// 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<typeof BS3Col> = {
|
||||
children: rest.children,
|
||||
className: rest.className,
|
||||
...getBs3Sizes(rest),
|
||||
...bs3Props,
|
||||
}
|
||||
|
||||
return (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={<BS3Col {...bs3ColProps} />}
|
||||
bs5={<Col {...rest} />}
|
||||
/>
|
||||
)
|
||||
function OLCol(props: React.ComponentProps<typeof Col>) {
|
||||
return <Col {...props} />
|
||||
}
|
||||
|
||||
export default OLCol
|
||||
|
||||
@@ -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 <li> 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 (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={<MenuItem {...bs3MenuItemProps} />}
|
||||
bs5={
|
||||
<DropdownListItem>
|
||||
<DropdownItem {...rest} />
|
||||
</DropdownListItem>
|
||||
}
|
||||
/>
|
||||
<DropdownListItem>
|
||||
<DropdownItem {...props} />
|
||||
</DropdownListItem>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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<HTMLInputElement | null>
|
||||
bs3Props?: Record<PropertyKey, unknown>
|
||||
} & (
|
||||
| { 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<HTMLInputElement>) => 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<typeof BS3Checkbox> = {
|
||||
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<unknown>) => void,
|
||||
inputRef: node => {
|
||||
if (inputRef) {
|
||||
inputRef.current = node
|
||||
}
|
||||
},
|
||||
...getAriaAndDataProps(rest),
|
||||
...bs3Props,
|
||||
}
|
||||
|
||||
return (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={
|
||||
rest.type === 'radio' ? (
|
||||
<BS3Radio {...(rest as RadioButtonProps)} />
|
||||
) : (
|
||||
<BS3Checkbox {...bs3FormCheckboxProps} />
|
||||
)
|
||||
}
|
||||
bs5={
|
||||
rest.type === 'radio' ? (
|
||||
<Form.Check
|
||||
ref={inputRef}
|
||||
aria-describedby={
|
||||
rest.description ? `${rest.id}-description` : undefined
|
||||
}
|
||||
{...rest}
|
||||
label={
|
||||
<>
|
||||
{rest.label}
|
||||
{rest.description && (
|
||||
<FormText
|
||||
id={`${rest.id}-description`}
|
||||
className="form-check-label-description"
|
||||
>
|
||||
{rest.description}
|
||||
</FormText>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<Form.Check ref={inputRef} {...rest} />
|
||||
)
|
||||
return rest.type === 'radio' ? (
|
||||
<Form.Check
|
||||
ref={inputRef}
|
||||
aria-describedby={rest.description ? `${rest.id}-description` : undefined}
|
||||
{...rest}
|
||||
label={
|
||||
<>
|
||||
{rest.label}
|
||||
{rest.description && (
|
||||
<FormText
|
||||
id={`${rest.id}-description`}
|
||||
className="form-check-label-description"
|
||||
>
|
||||
{rest.description}
|
||||
</FormText>
|
||||
)}
|
||||
</>
|
||||
}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function BS3Radio(props: RadioButtonProps) {
|
||||
const {
|
||||
label,
|
||||
checked,
|
||||
className,
|
||||
description,
|
||||
disabled,
|
||||
id,
|
||||
name,
|
||||
onChange,
|
||||
required,
|
||||
value,
|
||||
} = props
|
||||
return (
|
||||
<div className={className}>
|
||||
<input
|
||||
checked={checked}
|
||||
className="me-1"
|
||||
disabled={disabled}
|
||||
id={id}
|
||||
name={name}
|
||||
onChange={onChange}
|
||||
type="radio"
|
||||
required={required}
|
||||
value={value}
|
||||
aria-describedby={description ? `${id}-description` : undefined}
|
||||
/>
|
||||
<label htmlFor={id} data-disabled={disabled ? 'true' : undefined}>
|
||||
{label}
|
||||
</label>{' '}
|
||||
{description && (
|
||||
<small id={`${id}-description`} aria-hidden="true">
|
||||
{description}
|
||||
</small>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<Form.Check ref={inputRef} {...rest} />
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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<string, unknown>
|
||||
'data-ol-dirty'?: unknown
|
||||
'main-field'?: any // For the CM6's benefit in the editor search panel
|
||||
loading?: boolean
|
||||
}
|
||||
|
||||
type BS3FormControlProps = ComponentProps<typeof BS3FormControl> & {
|
||||
'main-field'?: any
|
||||
}
|
||||
|
||||
const OLFormControl: BsPrefixRefForwardingComponent<
|
||||
'input',
|
||||
OLFormControlProps
|
||||
> = forwardRef<HTMLInputElement, OLFormControlProps>((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<string, unknown>
|
||||
const { append, ...rest } = props
|
||||
|
||||
return (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={
|
||||
<BS3FormControl
|
||||
{...bs3FormControlProps}
|
||||
append={rest.loading ? <Icon type="spinner" spin /> : append}
|
||||
/>
|
||||
}
|
||||
bs5={
|
||||
<FormControl
|
||||
ref={ref}
|
||||
{...rest}
|
||||
append={rest.loading ? <OLSpinner size="sm" /> : append}
|
||||
/>
|
||||
}
|
||||
<FormControl
|
||||
ref={ref}
|
||||
{...rest}
|
||||
append={rest.loading ? <OLSpinner size="sm" /> : append}
|
||||
/>
|
||||
)
|
||||
})
|
||||
|
||||
@@ -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<typeof Form.Control.Feedback>,
|
||||
'type' | 'className' | 'children'
|
||||
> & {
|
||||
bs3Props?: Record<string, unknown>
|
||||
}
|
||||
>
|
||||
|
||||
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 (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={<BS3HelpBlock {...bs3HelpBlockProps} />}
|
||||
bs5={<FormFeedback {...bs5Props}>{children}</FormFeedback>}
|
||||
/>
|
||||
)
|
||||
return <FormFeedback {...props} />
|
||||
}
|
||||
|
||||
export default OLFormFeedback
|
||||
|
||||
@@ -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 (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={
|
||||
<BS3FormGroup {...bs3FormGroupProps}>
|
||||
{rest.children}
|
||||
{withFeedback ? <FormControl.Feedback /> : null}
|
||||
</BS3FormGroup>
|
||||
}
|
||||
bs5={<FormGroup className={className} {...rest} />}
|
||||
/>
|
||||
)
|
||||
function OLFormGroup(props: FormGroupProps) {
|
||||
return <FormGroup {...props} />
|
||||
}
|
||||
|
||||
export default OLFormGroup
|
||||
|
||||
@@ -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<string, unknown>
|
||||
}
|
||||
|
||||
function OLFormLabel(props: OLFormLabelProps) {
|
||||
const { bs3Props, ...rest } = props
|
||||
|
||||
const bs3FormLabelProps: React.ComponentProps<typeof BS3FormLabel> = {
|
||||
children: rest.children,
|
||||
htmlFor: rest.htmlFor,
|
||||
srOnly: rest.visuallyHidden,
|
||||
className: rest.className,
|
||||
...bs3Props,
|
||||
}
|
||||
|
||||
return (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={<BS3FormLabel {...bs3FormLabelProps} />}
|
||||
bs5={<Form.Label {...rest} />}
|
||||
/>
|
||||
)
|
||||
function OLFormLabel(props: React.ComponentProps<(typeof Form)['Label']>) {
|
||||
return <Form.Label {...props} />
|
||||
}
|
||||
|
||||
export default OLFormLabel
|
||||
|
||||
@@ -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<string, unknown>
|
||||
}
|
||||
|
||||
const OLFormSelect = forwardRef<HTMLSelectElement, OLFormSelectProps>(
|
||||
const OLFormSelect = forwardRef<HTMLSelectElement, FormSelectProps>(
|
||||
(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 (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={
|
||||
<BS3FormControl
|
||||
componentClass="select"
|
||||
{...bs3FormSelectProps}
|
||||
{...extraProps}
|
||||
/>
|
||||
}
|
||||
bs5={<Form.Select ref={ref} {...bs5Props} />}
|
||||
/>
|
||||
)
|
||||
return <Form.Select ref={ref} {...props} />
|
||||
}
|
||||
)
|
||||
OLFormSelect.displayName = 'OLFormSelect'
|
||||
|
||||
@@ -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<HTMLInputElement | null>
|
||||
bs3Props?: React.InputHTMLAttributes<HTMLInputElement>
|
||||
}
|
||||
|
||||
function OLFormSwitch(props: OLFormSwitchProps) {
|
||||
const { bs3Props, inputRef, label, id, ...rest } = props
|
||||
|
||||
const bs3FormSwitchProps: React.InputHTMLAttributes<HTMLInputElement> = {
|
||||
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<unknown>) => void,
|
||||
...getAriaAndDataProps(rest),
|
||||
...bs3Props,
|
||||
}
|
||||
const { inputRef, label, id, ...rest } = props
|
||||
|
||||
return (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={
|
||||
<div className="input-switch">
|
||||
<input
|
||||
id={id}
|
||||
type="checkbox"
|
||||
className="input-switch-hidden-input"
|
||||
ref={inputRef}
|
||||
{...bs3FormSwitchProps}
|
||||
/>
|
||||
<label htmlFor={id} className="input-switch-btn">
|
||||
<span className="sr-only">{label}</span>
|
||||
</label>
|
||||
</div>
|
||||
}
|
||||
bs5={
|
||||
<>
|
||||
<FormCheck type="switch" ref={inputRef} id={id} {...rest} />
|
||||
<FormLabel htmlFor={id} visuallyHidden>
|
||||
{label}
|
||||
</FormLabel>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
<>
|
||||
<FormCheck type="switch" ref={inputRef} id={id} {...rest} />
|
||||
<FormLabel htmlFor={id} visuallyHidden>
|
||||
{label}
|
||||
</FormLabel>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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<string, unknown>
|
||||
}
|
||||
|
||||
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<typeof PolymorphicComponent>
|
||||
|
||||
// Get all `aria-*` and `data-*` attributes
|
||||
const extraProps = getAriaAndDataProps(rest)
|
||||
|
||||
return (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={
|
||||
<PolymorphicComponent {...bs3HelpBlockProps} {...extraProps} as={as} />
|
||||
}
|
||||
bs5={<FormText {...rest} as={as} />}
|
||||
/>
|
||||
)
|
||||
function OLFormText({ as = 'div', ...rest }: FormTextProps) {
|
||||
return <FormText {...rest} as={as} />
|
||||
}
|
||||
|
||||
export default OLFormText
|
||||
|
||||
@@ -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<typeof Form> & {
|
||||
bs3Props?: ComponentProps<typeof BS3Form>
|
||||
}
|
||||
|
||||
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 (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={
|
||||
<BS3Form className={bs3ClassName} {...bs3FormProps} {...extraProps} />
|
||||
}
|
||||
bs5={<Form {...rest} />}
|
||||
/>
|
||||
)
|
||||
function OLForm(props: ComponentProps<typeof Form>) {
|
||||
return <Form {...props} />
|
||||
}
|
||||
|
||||
export default OLForm
|
||||
|
||||
@@ -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<HTMLButtonElement>
|
||||
onMouseOut?: React.MouseEventHandler<HTMLButtonElement>
|
||||
onFocus?: React.FocusEventHandler<HTMLButtonElement>
|
||||
onBlur?: React.FocusEventHandler<HTMLButtonElement>
|
||||
}
|
||||
}
|
||||
export type OLIconButtonProps = IconButtonProps
|
||||
|
||||
const OLIconButton = forwardRef<HTMLButtonElement, OLIconButtonProps>(
|
||||
(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 (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={
|
||||
<BS3Button {...bs3FinalProps}>
|
||||
{loading || <Icon type={rest.icon} fw={fw} />}
|
||||
</BS3Button>
|
||||
}
|
||||
bs5={<IconButton {...rest} ref={ref} />}
|
||||
/>
|
||||
)
|
||||
return <IconButton {...props} ref={ref} />
|
||||
}
|
||||
)
|
||||
OLIconButton.displayName = 'OLIconButton'
|
||||
|
||||
@@ -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 (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={<BS3ListGroupItem {...bs3ListGroupItemProps} {...extraProps} />}
|
||||
bs5={
|
||||
<ListGroupItem
|
||||
{...rest}
|
||||
as={as}
|
||||
type={as === 'button' ? 'button' : undefined}
|
||||
/>
|
||||
}
|
||||
<ListGroupItem
|
||||
{...props}
|
||||
as={as}
|
||||
type={as === 'button' ? 'button' : undefined}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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 (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={<BS3ListGroup {...bs3ListGroupProps} {...extraProps} />}
|
||||
bs5={<ListGroup {...rest} as={as} />}
|
||||
/>
|
||||
)
|
||||
return <ListGroup {...props} as={as} />
|
||||
}
|
||||
|
||||
export default OLListGroup
|
||||
|
||||
@@ -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<string, unknown>
|
||||
size?: 'sm' | 'lg'
|
||||
onHide: () => void
|
||||
}
|
||||
|
||||
type OLModalHeaderProps = ModalHeaderProps & {
|
||||
bs3Props?: Record<string, unknown>
|
||||
}
|
||||
|
||||
type OLModalTitleProps = ModalTitleProps & {
|
||||
bs3Props?: Record<string, unknown>
|
||||
}
|
||||
|
||||
type OLModalBodyProps = React.ComponentProps<typeof ModalBody> & {
|
||||
bs3Props?: Record<string, unknown>
|
||||
}
|
||||
|
||||
type OLModalFooterProps = ModalFooterProps & {
|
||||
bs3Props?: Record<string, unknown>
|
||||
}
|
||||
|
||||
export default function OLModal({ children, ...props }: OLModalProps) {
|
||||
const { bs3Props, ...bs5Props } = props
|
||||
return <Modal {...props}>{children}</Modal>
|
||||
}
|
||||
|
||||
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 <Modal.Header {...props}>{children}</Modal.Header>
|
||||
}
|
||||
|
||||
export function OLModalTitle({ children, ...props }: ModalTitleProps) {
|
||||
return (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={<AccessibleModal {...bs3ModalProps}>{children}</AccessibleModal>}
|
||||
bs5={<BS5Modal {...bs5Props}>{children}</BS5Modal>}
|
||||
/>
|
||||
<Modal.Title as="h2" {...props}>
|
||||
{children}
|
||||
</Modal.Title>
|
||||
)
|
||||
}
|
||||
|
||||
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 (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={<BS3Modal.Header {...bs3ModalProps}>{children}</BS3Modal.Header>}
|
||||
bs5={<BS5Modal.Header {...bs5Props}>{children}</BS5Modal.Header>}
|
||||
/>
|
||||
)
|
||||
export function OLModalBody({ children, ...props }: ModalBodyProps) {
|
||||
return <Modal.Body {...props}>{children}</Modal.Body>
|
||||
}
|
||||
|
||||
export function OLModalTitle({ children, ...props }: OLModalTitleProps) {
|
||||
const { bs3Props, ...bs5Props } = props
|
||||
|
||||
const bs3ModalProps: BS3ModalTitleProps = {
|
||||
componentClass: bs5Props.as,
|
||||
}
|
||||
|
||||
return (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={<BS3Modal.Title {...bs3ModalProps}>{children}</BS3Modal.Title>}
|
||||
bs5={
|
||||
<BS5Modal.Title as="h2" {...bs5Props}>
|
||||
{children}
|
||||
</BS5Modal.Title>
|
||||
}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export function OLModalBody({ children, ...props }: OLModalBodyProps) {
|
||||
const { bs3Props, ...bs5Props } = props
|
||||
|
||||
const bs3ModalProps: BS3ModalBodyProps = {
|
||||
componentClass: bs5Props.as,
|
||||
className: bs5Props.className,
|
||||
}
|
||||
|
||||
return (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={<BS3Modal.Body {...bs3ModalProps}>{children}</BS3Modal.Body>}
|
||||
bs5={<BS5Modal.Body {...bs5Props}>{children}</BS5Modal.Body>}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export function OLModalFooter({ children, ...props }: OLModalFooterProps) {
|
||||
const { bs3Props, ...bs5Props } = props
|
||||
|
||||
const bs3ModalProps: BS3ModalFooterProps = {
|
||||
componentClass: bs5Props.as,
|
||||
className: bs5Props.className,
|
||||
}
|
||||
|
||||
return (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={<BS3Modal.Footer {...bs3ModalProps}>{children}</BS3Modal.Footer>}
|
||||
bs5={<BS5Modal.Footer {...bs5Props}>{children}</BS5Modal.Footer>}
|
||||
/>
|
||||
)
|
||||
export function OLModalFooter({ children, ...props }: ModalFooterProps) {
|
||||
return <Modal.Footer {...props}>{children}</Modal.Footer>
|
||||
}
|
||||
|
||||
@@ -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<typeof Notification> & {
|
||||
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<typeof Notification>) {
|
||||
return (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={
|
||||
<Alert {...alertProps}>
|
||||
{bs3Props?.icon}
|
||||
{bs3Props?.icon && ' '}
|
||||
{notificationProps.content}
|
||||
{notificationProps.action}
|
||||
</Alert>
|
||||
}
|
||||
bs5={
|
||||
<div className="notification-list">
|
||||
<Notification {...notificationProps} />
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
<div className="notification-list">
|
||||
<Notification {...props} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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<OverlayProps['placement'], BS3OverlayProps['placement']>
|
||||
>
|
||||
|
||||
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 (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={<BS3Overlay {...bs3OverlayProps} />}
|
||||
bs5={<Overlay {...bs5Props} />}
|
||||
/>
|
||||
)
|
||||
function OLOverlay(props: OverlayProps) {
|
||||
return <Overlay {...props} />
|
||||
}
|
||||
|
||||
export default OLOverlay
|
||||
|
||||
@@ -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 (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={<div className={classNames('card', className)}>{children}</div>}
|
||||
bs5={
|
||||
<Card className={classNames('page-content-card', className)}>
|
||||
<CardBody>{children}</CardBody>
|
||||
</Card>
|
||||
}
|
||||
/>
|
||||
<Card className={classNames('page-content-card', className)}>
|
||||
<CardBody>{children}</CardBody>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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<PopoverProps, 'title'> & {
|
||||
title?: React.ReactNode
|
||||
bs3Props?: BS3PopoverProps
|
||||
}
|
||||
|
||||
const OLPopover = forwardRef<HTMLDivElement, OLPopoverProps>((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<PopoverProps['placement'], BS3PopoverProps['placement']>
|
||||
>
|
||||
|
||||
for (const placement of bs3PlacementOptions) {
|
||||
if (placement === bs5Props.placement) {
|
||||
bs3PopoverProps.placement = bs5Props.placement
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bs3PopoverProps = { ...bs3PopoverProps, ...bs3Props }
|
||||
const { title, children, ...bs5Props } = props
|
||||
|
||||
return (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={
|
||||
<BS3Popover
|
||||
{...bs3PopoverProps}
|
||||
ref={ref as React.LegacyRef<BS3Popover>}
|
||||
/>
|
||||
}
|
||||
bs5={
|
||||
<Popover {...bs5Props} ref={ref}>
|
||||
{title && <Popover.Header>{title}</Popover.Header>}
|
||||
<Popover.Body>{children}</Popover.Body>
|
||||
</Popover>
|
||||
}
|
||||
/>
|
||||
<Popover {...bs5Props} ref={ref}>
|
||||
{title && <Popover.Header>{title}</Popover.Header>}
|
||||
<Popover.Body>{children}</Popover.Body>
|
||||
</Popover>
|
||||
)
|
||||
})
|
||||
OLPopover.displayName = 'OLPopover'
|
||||
|
||||
@@ -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<typeof Row>
|
||||
|
||||
function OLRow(props: OLRowProps) {
|
||||
return (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={<BS3Row className={props.className}>{props.children}</BS3Row>}
|
||||
bs5={<Row {...props} />}
|
||||
/>
|
||||
)
|
||||
function OLRow(props: React.ComponentProps<typeof Row>) {
|
||||
return <Row {...props} />
|
||||
}
|
||||
|
||||
export default OLRow
|
||||
|
||||
@@ -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 (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={
|
||||
<Icon
|
||||
type="refresh"
|
||||
fw
|
||||
spin
|
||||
className={classNames({ 'fa-2x': size === 'lg' })}
|
||||
/>
|
||||
}
|
||||
bs5={
|
||||
<Spinner
|
||||
size={size === 'sm' ? 'sm' : undefined}
|
||||
animation="border"
|
||||
aria-hidden="true"
|
||||
role="status"
|
||||
/>
|
||||
}
|
||||
<Spinner
|
||||
size={size === 'sm' ? 'sm' : undefined}
|
||||
animation="border"
|
||||
aria-hidden="true"
|
||||
role="status"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,32 +1,7 @@
|
||||
import Table from '@/features/ui/components/bootstrap-5/table'
|
||||
import { Table as BS3Table } from 'react-bootstrap'
|
||||
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
|
||||
import { getAriaAndDataProps } from '@/features/utils/bootstrap-5'
|
||||
|
||||
type OLFormProps = React.ComponentProps<typeof Table> & {
|
||||
bs3Props?: React.ComponentProps<typeof BS3Table>
|
||||
}
|
||||
|
||||
function OLTable(props: OLFormProps) {
|
||||
const { bs3Props, container, ...rest } = props
|
||||
|
||||
const bs3FormProps: React.ComponentProps<typeof BS3Table> = {
|
||||
bsClass: rest.className,
|
||||
id: rest.id,
|
||||
condensed: rest.size === 'sm',
|
||||
children: rest.children,
|
||||
responsive:
|
||||
typeof rest.responsive !== 'string' ? rest.responsive : undefined,
|
||||
...getAriaAndDataProps(rest),
|
||||
...bs3Props,
|
||||
}
|
||||
|
||||
return (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={<BS3Table {...bs3FormProps} />}
|
||||
bs5={<Table container={container} {...rest} />}
|
||||
/>
|
||||
)
|
||||
function OLTable(props: React.ComponentProps<typeof Table>) {
|
||||
return <Table {...props} />
|
||||
}
|
||||
|
||||
export default OLTable
|
||||
|
||||
@@ -1,37 +1,10 @@
|
||||
import Tag from '@/features/ui/components/bootstrap-5/tag'
|
||||
import BS3Tag from '@/shared/components/tag'
|
||||
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
|
||||
import { forwardRef } from 'react'
|
||||
import { getAriaAndDataProps } from '@/features/utils/bootstrap-5'
|
||||
|
||||
type OLTagProps = React.ComponentProps<typeof Tag> & {
|
||||
bs3Props?: React.ComponentProps<typeof BS3Tag>
|
||||
}
|
||||
type OLTagProps = React.ComponentProps<typeof Tag>
|
||||
|
||||
const OLTag = forwardRef<HTMLElement, OLTagProps>((props: OLTagProps, ref) => {
|
||||
const { bs3Props, ...rest } = props
|
||||
|
||||
const bs3TagProps: React.ComponentProps<typeof BS3Tag> = {
|
||||
children: rest.children,
|
||||
prepend: rest.prepend,
|
||||
closeBtnProps: rest.closeBtnProps,
|
||||
className: rest.className,
|
||||
onClick: rest.onClick,
|
||||
onFocus: rest.onFocus,
|
||||
onBlur: rest.onBlur,
|
||||
onMouseOver: rest.onMouseOver,
|
||||
onMouseOut: rest.onMouseOut,
|
||||
contentProps: rest.contentProps,
|
||||
...getAriaAndDataProps(rest),
|
||||
...bs3Props,
|
||||
}
|
||||
|
||||
return (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={<BS3Tag {...bs3TagProps} />}
|
||||
bs5={<Tag ref={ref} {...rest} />}
|
||||
/>
|
||||
)
|
||||
return <Tag ref={ref} {...props} />
|
||||
})
|
||||
|
||||
OLTag.displayName = 'OLTag'
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
|
||||
|
||||
import { CSSProperties, FC } from 'react'
|
||||
import { ToastContainer as BS5ToastContainer } from 'react-bootstrap-5'
|
||||
import { ToastContainer as BS3ToastContainer } from '../bootstrap-3/toast-container'
|
||||
|
||||
type OLToastContainerProps = {
|
||||
style?: CSSProperties
|
||||
@@ -15,17 +12,8 @@ export const OLToastContainer: FC<OLToastContainerProps> = ({
|
||||
style,
|
||||
}) => {
|
||||
return (
|
||||
<BootstrapVersionSwitcher
|
||||
bs5={
|
||||
<BS5ToastContainer className={className} style={style}>
|
||||
{children}
|
||||
</BS5ToastContainer>
|
||||
}
|
||||
bs3={
|
||||
<BS3ToastContainer className={className} style={style}>
|
||||
{children}
|
||||
</BS3ToastContainer>
|
||||
}
|
||||
/>
|
||||
<BS5ToastContainer className={className} style={style}>
|
||||
{children}
|
||||
</BS5ToastContainer>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -7,8 +7,6 @@ import {
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import MaterialIcon from '../../../../shared/components/material-icon'
|
||||
import { ReactNode, useCallback, useState } from 'react'
|
||||
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
|
||||
import { Toast as BS3Toast } from '../bootstrap-3/toast'
|
||||
|
||||
export type OLToastProps = {
|
||||
type: NotificationType
|
||||
@@ -78,29 +76,14 @@ export const OLToast = ({
|
||||
</div>
|
||||
)
|
||||
return (
|
||||
<BootstrapVersionSwitcher
|
||||
bs5={
|
||||
<BS5Toast
|
||||
onClose={handleClose}
|
||||
autohide={autoHide}
|
||||
onExited={handleOnHidden}
|
||||
delay={delay}
|
||||
show={show}
|
||||
>
|
||||
{toastElement}
|
||||
</BS5Toast>
|
||||
}
|
||||
bs3={
|
||||
<BS3Toast
|
||||
onClose={handleClose}
|
||||
autohide={autoHide}
|
||||
delay={delay}
|
||||
onExited={handleOnHidden}
|
||||
show={show}
|
||||
>
|
||||
{toastElement}
|
||||
</BS3Toast>
|
||||
}
|
||||
/>
|
||||
<BS5Toast
|
||||
onClose={handleClose}
|
||||
autohide={autoHide}
|
||||
onExited={handleOnHidden}
|
||||
delay={delay}
|
||||
show={show}
|
||||
>
|
||||
{toastElement}
|
||||
</BS5Toast>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,42 +1,7 @@
|
||||
import { ToggleButtonGroup, ToggleButtonGroupProps } from 'react-bootstrap-5'
|
||||
import BS3ToggleButtonGroup from '@/features/ui/components/bootstrap-3/toggle-button-group'
|
||||
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
|
||||
import { getAriaAndDataProps } from '@/features/utils/bootstrap-5'
|
||||
|
||||
type BS3ToggleButtonGroupProps = React.ComponentProps<
|
||||
typeof BS3ToggleButtonGroup
|
||||
>
|
||||
|
||||
type OLToggleButtonGroupProps<T> = ToggleButtonGroupProps<T> & {
|
||||
bs3Props?: BS3ToggleButtonGroupProps
|
||||
}
|
||||
|
||||
function OLToggleButtonGroup<T>(props: OLToggleButtonGroupProps<T>) {
|
||||
const { bs3Props, ...rest } = props
|
||||
|
||||
const bs3ToggleButtonGroupProps = {
|
||||
name: rest.name,
|
||||
type: rest.type,
|
||||
value: rest.value,
|
||||
onChange: rest.onChange,
|
||||
children: rest.children,
|
||||
className: rest.className,
|
||||
defaultValue: rest.defaultValue,
|
||||
defaultChecked: rest.defaultChecked,
|
||||
...bs3Props,
|
||||
} as BS3ToggleButtonGroupProps
|
||||
|
||||
// Get all `aria-*` and `data-*` attributes
|
||||
const extraProps = getAriaAndDataProps(rest)
|
||||
|
||||
return (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={
|
||||
<BS3ToggleButtonGroup {...extraProps} {...bs3ToggleButtonGroupProps} />
|
||||
}
|
||||
bs5={<ToggleButtonGroup {...rest} />}
|
||||
/>
|
||||
)
|
||||
function OLToggleButtonGroup<T>(props: ToggleButtonGroupProps<T>) {
|
||||
return <ToggleButtonGroup {...props} />
|
||||
}
|
||||
|
||||
export default OLToggleButtonGroup
|
||||
|
||||
@@ -1,48 +1,7 @@
|
||||
import { ToggleButton, ToggleButtonProps } from 'react-bootstrap-5'
|
||||
import {
|
||||
ToggleButton as BS3ToggleButton,
|
||||
ToggleButtonProps as BS3ToggleButtonProps,
|
||||
} from 'react-bootstrap'
|
||||
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
|
||||
import { getAriaAndDataProps } from '@/features/utils/bootstrap-5'
|
||||
import classnames from 'classnames'
|
||||
|
||||
type OLToggleButtonProps = ToggleButtonProps & {
|
||||
bs3Props?: BS3ToggleButtonProps
|
||||
}
|
||||
|
||||
function OLToggleButton(props: OLToggleButtonProps) {
|
||||
const { bs3Props, ...rest } = props
|
||||
|
||||
const bs3ToggleButtonProps: BS3ToggleButtonProps & { active?: boolean } = {
|
||||
type: rest.type,
|
||||
name: rest.name,
|
||||
active: rest.active,
|
||||
checked: rest.checked,
|
||||
disabled: rest.disabled,
|
||||
onChange: rest.onChange as BS3ToggleButtonProps['onChange'],
|
||||
onClick: rest.onClick as BS3ToggleButtonProps['onClick'],
|
||||
value: rest.value as BS3ToggleButtonProps['value'],
|
||||
children: rest.children,
|
||||
className: classnames(`btn-${props.variant || 'primary'}`, rest.className),
|
||||
...bs3Props,
|
||||
}
|
||||
|
||||
// Get all `aria-*` and `data-*` attributes
|
||||
const extraProps = getAriaAndDataProps(rest)
|
||||
|
||||
return (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={
|
||||
<BS3ToggleButton
|
||||
{...extraProps}
|
||||
{...bs3ToggleButtonProps}
|
||||
bsStyle={null}
|
||||
/>
|
||||
}
|
||||
bs5={<ToggleButton {...rest} />}
|
||||
/>
|
||||
)
|
||||
function OLToggleButton(props: ToggleButtonProps) {
|
||||
return <ToggleButton {...props} />
|
||||
}
|
||||
|
||||
export default OLToggleButton
|
||||
|
||||
@@ -1,48 +1,7 @@
|
||||
import Tooltip from '@/features/ui/components/bootstrap-5/tooltip'
|
||||
import BS3Tooltip from '@/shared/components/tooltip'
|
||||
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
|
||||
|
||||
type OLTooltipProps = React.ComponentProps<typeof Tooltip> & {
|
||||
bs3Props?: Record<string, unknown>
|
||||
}
|
||||
|
||||
function OLTooltip(props: OLTooltipProps) {
|
||||
const { bs3Props, ...bs5Props } = props
|
||||
|
||||
type BS3TooltipProps = React.ComponentProps<typeof BS3Tooltip>
|
||||
|
||||
const bs3TooltipProps: BS3TooltipProps = {
|
||||
children: bs5Props.children,
|
||||
id: bs5Props.id,
|
||||
description: bs5Props.description,
|
||||
tooltipProps: bs5Props.tooltipProps as BS3TooltipProps,
|
||||
overlayProps: {
|
||||
placement: bs5Props.overlayProps?.placement,
|
||||
rootClose: bs5Props.overlayProps?.rootClose,
|
||||
trigger: bs5Props.overlayProps?.trigger,
|
||||
},
|
||||
...bs3Props,
|
||||
}
|
||||
|
||||
if ('hidden' in bs5Props) {
|
||||
bs3TooltipProps.hidden = bs5Props.hidden
|
||||
}
|
||||
|
||||
const delay = bs5Props.overlayProps?.delay
|
||||
if (delay && typeof delay !== 'number') {
|
||||
bs3TooltipProps.overlayProps = {
|
||||
...bs3TooltipProps.overlayProps,
|
||||
delayShow: delay.show,
|
||||
delayHide: delay.hide,
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={<BS3Tooltip {...bs3TooltipProps} />}
|
||||
bs5={<Tooltip {...bs5Props} />}
|
||||
/>
|
||||
)
|
||||
function OLTooltip(props: React.ComponentProps<typeof Tooltip>) {
|
||||
return <Tooltip {...props} />
|
||||
}
|
||||
|
||||
export default OLTooltip
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
import getMeta from '@/utils/meta'
|
||||
|
||||
// The reason this is a function is to ensure that the meta tag is read before
|
||||
// any isBootstrap5 check is performed
|
||||
export const isBootstrap5 = () => getMeta('ol-bootstrapVersion') === 5
|
||||
|
||||
/* eslint-disable no-redeclare */
|
||||
export function bsVersion<A>({ bs5 }: { bs5: A }): A | undefined
|
||||
export function bsVersion<B>({ bs3 }: { bs3: B }): B | undefined
|
||||
export function bsVersion<A, B>({ bs5, bs3 }: { bs5: A; bs3: B }): A | B
|
||||
export function bsVersion({ bs5, bs3 }: { bs5?: unknown; bs3?: unknown }) {
|
||||
return isBootstrap5() ? bs5 : bs3
|
||||
}
|
||||
|
||||
// get all `aria-*` and `data-*` attributes
|
||||
export const getAriaAndDataProps = (obj: Record<string, unknown>) => {
|
||||
return Object.entries(obj).reduce(
|
||||
(acc, [key, value]) => {
|
||||
if (key.startsWith('aria-') || key.startsWith('data-')) {
|
||||
acc[key] = value
|
||||
}
|
||||
return acc
|
||||
},
|
||||
{} as Record<string, unknown>
|
||||
)
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
import { useCallback } from 'react'
|
||||
import { Modal, ModalProps } from 'react-bootstrap'
|
||||
|
||||
// A wrapper for the v0.33 React Bootstrap Modal component,
|
||||
// which ensures that the `aria-hidden` attribute is not set on the modal when it's visible,
|
||||
// and that role="dialog" is not duplicated.
|
||||
// https://github.com/react-bootstrap/react-bootstrap/issues/4790
|
||||
// There are other ARIA attributes on these modals which could be improved,
|
||||
// but this at least makes them accessible for tests.
|
||||
function AccessibleModal(props: ModalProps) {
|
||||
const modalRef = useCallback(
|
||||
element => {
|
||||
const modalNode = element?._modal?.modalNode
|
||||
if (modalNode) {
|
||||
if (props.show) {
|
||||
modalNode.removeAttribute('role')
|
||||
modalNode.removeAttribute('aria-hidden')
|
||||
} else {
|
||||
// NOTE: possibly not ever used, as the modal is only rendered when shown
|
||||
modalNode.setAttribute('aria-hidden', 'true')
|
||||
}
|
||||
}
|
||||
},
|
||||
[props.show]
|
||||
)
|
||||
|
||||
return <Modal {...props} ref={modalRef} />
|
||||
}
|
||||
|
||||
export default AccessibleModal
|
||||
@@ -1,29 +0,0 @@
|
||||
import { Label } from 'react-bootstrap'
|
||||
import classnames from 'classnames'
|
||||
import { MergeAndOverride } from '../../../../types/utils'
|
||||
|
||||
type BadgeProps = MergeAndOverride<
|
||||
React.ComponentProps<'span'>,
|
||||
{
|
||||
prepend?: React.ReactNode
|
||||
children: React.ReactNode
|
||||
className?: string
|
||||
bsStyle?: React.ComponentProps<typeof Label>['bsStyle'] | null
|
||||
}
|
||||
>
|
||||
|
||||
function Badge({ prepend, children, bsStyle, className, ...rest }: BadgeProps) {
|
||||
const classNames =
|
||||
bsStyle === null
|
||||
? className
|
||||
: classnames('label', `label-${bsStyle}`, className)
|
||||
|
||||
return (
|
||||
<span className={classNames} {...rest}>
|
||||
{prepend && <span className="badge-tag-bs3-prepend">{prepend}</span>}
|
||||
<span className="badge-tag-bs3-content">{children}</span>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
export default Badge
|
||||
@@ -1,14 +1,11 @@
|
||||
import type { FC } from 'react'
|
||||
import classnames from 'classnames'
|
||||
import MaterialIcon from '@/shared/components/material-icon'
|
||||
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
|
||||
import OLBadge from '@/features/ui/components/ol/ol-badge'
|
||||
|
||||
function BS5BetaBadgeIcon({
|
||||
badgeClass,
|
||||
}: {
|
||||
badgeClass: ReturnType<typeof chooseBadgeClass>
|
||||
}) {
|
||||
const BetaBadgeIcon: FC<{
|
||||
phase?: string
|
||||
}> = ({ phase = 'beta' }) => {
|
||||
const badgeClass = chooseBadgeClass(phase)
|
||||
if (badgeClass === 'info-badge') {
|
||||
return <MaterialIcon type="info" className="align-middle info-badge" />
|
||||
} else if (badgeClass === 'alpha-badge') {
|
||||
@@ -26,18 +23,6 @@ function BS5BetaBadgeIcon({
|
||||
}
|
||||
}
|
||||
|
||||
const BetaBadgeIcon: FC<{
|
||||
phase?: string
|
||||
}> = ({ phase = 'beta' }) => {
|
||||
const badgeClass = chooseBadgeClass(phase)
|
||||
return (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={<span className={classnames('badge', badgeClass)} />}
|
||||
bs5={<BS5BetaBadgeIcon badgeClass={badgeClass} />}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function chooseBadgeClass(phase?: string) {
|
||||
switch (phase) {
|
||||
case 'release':
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import type { FC, MouseEventHandler, ReactNode } from 'react'
|
||||
import OLTooltip from '@/features/ui/components/ol/ol-tooltip'
|
||||
import { bsVersion } from '@/features/utils/bootstrap-5'
|
||||
import BetaBadgeIcon from '@/shared/components/beta-badge-icon'
|
||||
|
||||
type TooltipProps = {
|
||||
@@ -40,9 +39,7 @@ const BetaBadge: FC<{
|
||||
href={href || defaultHref}
|
||||
{...linkProps}
|
||||
>
|
||||
<span className={bsVersion({ bs5: 'visually-hidden', bs3: 'sr-only' })}>
|
||||
{description || tooltip?.text}
|
||||
</span>
|
||||
<span className="visually-hidden">{description || tooltip?.text}</span>
|
||||
<BetaBadgeIcon phase={phase} />
|
||||
</a>
|
||||
)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import MaterialIcon from '@/shared/components/material-icon'
|
||||
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
|
||||
|
||||
type CloseProps = {
|
||||
onDismiss: React.MouseEventHandler<HTMLButtonElement>
|
||||
@@ -16,15 +15,10 @@ function Close({ onDismiss, variant = 'light' }: CloseProps) {
|
||||
className={`close pull-right ${variant}`}
|
||||
onClick={onDismiss}
|
||||
>
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={<span aria-hidden="true">×</span>}
|
||||
bs5={
|
||||
<MaterialIcon
|
||||
type="close"
|
||||
className="align-text-bottom"
|
||||
accessibilityLabel={t('close')}
|
||||
/>
|
||||
}
|
||||
<MaterialIcon
|
||||
type="close"
|
||||
className="align-text-bottom"
|
||||
accessibilityLabel={t('close')}
|
||||
/>
|
||||
<span className="sr-only">{t('close')}</span>
|
||||
</button>
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
import React, {
|
||||
Children,
|
||||
cloneElement,
|
||||
type FC,
|
||||
isValidElement,
|
||||
useCallback,
|
||||
} from 'react'
|
||||
import { Dropdown, DropdownProps } from 'react-bootstrap'
|
||||
import useDropdown from '../hooks/use-dropdown'
|
||||
|
||||
type ControlledDropdownProps = DropdownProps & {
|
||||
defaultOpen?: boolean
|
||||
onMainButtonClick?: (dropdownOpen: boolean) => void
|
||||
}
|
||||
|
||||
const ControlledDropdown: FC<ControlledDropdownProps> = ({
|
||||
defaultOpen,
|
||||
onMainButtonClick,
|
||||
...props
|
||||
}) => {
|
||||
const { onClick, ...dropdownProps } = useDropdown(Boolean(defaultOpen))
|
||||
|
||||
const handleClick = useCallback(
|
||||
(e: React.MouseEvent<Dropdown, MouseEvent>) => {
|
||||
onClick(e)
|
||||
|
||||
if (onMainButtonClick) {
|
||||
onMainButtonClick(dropdownProps.open)
|
||||
}
|
||||
},
|
||||
[onClick, onMainButtonClick, dropdownProps.open]
|
||||
)
|
||||
|
||||
return (
|
||||
<Dropdown {...props} {...dropdownProps} onClick={handleClick}>
|
||||
{Children.map(props.children, child => {
|
||||
if (!isValidElement(child)) {
|
||||
return child
|
||||
}
|
||||
|
||||
// Dropdown.Menu
|
||||
if ('open' in child.props) {
|
||||
return cloneElement<any>(child, { open: dropdownProps.open })
|
||||
}
|
||||
|
||||
// Overlay
|
||||
if ('show' in child.props) {
|
||||
return cloneElement<any>(child, { show: dropdownProps.open })
|
||||
}
|
||||
|
||||
// anything else
|
||||
return cloneElement(child)
|
||||
})}
|
||||
</Dropdown>
|
||||
)
|
||||
}
|
||||
|
||||
export default ControlledDropdown
|
||||
@@ -3,7 +3,6 @@ import { useTranslation } from 'react-i18next'
|
||||
import OLButton from '@/features/ui/components/ol/ol-button'
|
||||
import OLTooltip from '@/features/ui/components/ol/ol-tooltip'
|
||||
import OLIconButton from '@/features/ui/components/ol/ol-icon-button'
|
||||
import { bsVersion } from '@/features/utils/bootstrap-5'
|
||||
|
||||
export const CopyToClipboard = memo<{
|
||||
content: string
|
||||
@@ -39,7 +38,6 @@ export const CopyToClipboard = memo<{
|
||||
size="sm"
|
||||
variant="secondary"
|
||||
className="copy-button"
|
||||
bs3Props={{ bsSize: 'xsmall' }}
|
||||
>
|
||||
{t('copy')}
|
||||
</OLButton>
|
||||
@@ -50,11 +48,7 @@ export const CopyToClipboard = memo<{
|
||||
size="sm"
|
||||
accessibilityLabel={t('copy')}
|
||||
className="copy-button"
|
||||
bs3Props={{ bsSize: 'xsmall' }}
|
||||
icon={bsVersion({
|
||||
bs5: copied ? 'check' : 'content_copy',
|
||||
bs3: copied ? 'check' : 'clipboard',
|
||||
})}
|
||||
icon={copied ? 'check' : 'content_copy'}
|
||||
/>
|
||||
)}
|
||||
</OLTooltip>
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Icon from './icon'
|
||||
import { useLocation } from '../hooks/use-location'
|
||||
import { DefaultMessage } from './default-message'
|
||||
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
|
||||
import MaterialIcon from './material-icon'
|
||||
import OLButton from '@/features/ui/components/ol/ol-button'
|
||||
|
||||
@@ -13,25 +11,12 @@ export const GenericErrorBoundaryFallback: FC = ({ children }) => {
|
||||
|
||||
return (
|
||||
<div className="error-boundary-container">
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={
|
||||
<Icon
|
||||
accessibilityLabel={`${t('generic_something_went_wrong')} ${t(
|
||||
'please_refresh'
|
||||
)}`}
|
||||
type="exclamation-triangle fa-2x"
|
||||
fw
|
||||
/>
|
||||
}
|
||||
bs5={
|
||||
<MaterialIcon
|
||||
accessibilityLabel={`${t('generic_something_went_wrong')} ${t(
|
||||
'please_refresh'
|
||||
)}`}
|
||||
type="warning"
|
||||
size="2x"
|
||||
/>
|
||||
}
|
||||
<MaterialIcon
|
||||
accessibilityLabel={`${t('generic_something_went_wrong')} ${t(
|
||||
'please_refresh'
|
||||
)}`}
|
||||
type="warning"
|
||||
size="2x"
|
||||
/>
|
||||
{children || (
|
||||
<div className="error-message">
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import classNames from 'classnames'
|
||||
import { bsVersion } from '@/features/utils/bootstrap-5'
|
||||
|
||||
type IconOwnProps = {
|
||||
type: string
|
||||
@@ -36,9 +35,7 @@ function Icon({
|
||||
<>
|
||||
<i className={iconClassName} aria-hidden="true" {...rest} />
|
||||
{accessibilityLabel && (
|
||||
<span className={bsVersion({ bs5: 'visually-hidden', bs3: 'sr-only' })}>
|
||||
{accessibilityLabel}
|
||||
</span>
|
||||
<span className="visually-hidden">{accessibilityLabel}</span>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -5,7 +5,6 @@ import OLTooltip from '@/features/ui/components/ol/ol-tooltip'
|
||||
import { postJSON } from '@/infrastructure/fetch-json'
|
||||
import OLButton from '@/features/ui/components/ol/ol-button'
|
||||
import getMeta from '@/utils/meta'
|
||||
import { isBootstrap5 } from '@/features/utils/bootstrap-5'
|
||||
|
||||
type IntegrationLinkingWidgetProps = {
|
||||
logo: ReactNode
|
||||
@@ -117,17 +116,14 @@ function ActionButton({
|
||||
</OLButton>
|
||||
)
|
||||
} else if (disabled) {
|
||||
const tooltipableButton = isBootstrap5() ? (
|
||||
const tooltipableButton = (
|
||||
<div className="d-inline-block">
|
||||
<OLButton variant="primary" disabled>
|
||||
{t('turn_on')}
|
||||
</OLButton>
|
||||
</div>
|
||||
) : (
|
||||
<OLButton variant="primary" disabled>
|
||||
{t('turn_on')}
|
||||
</OLButton>
|
||||
)
|
||||
|
||||
return (
|
||||
<OLTooltip
|
||||
id="experiment-disabled"
|
||||
|
||||
@@ -3,7 +3,6 @@ import { useEffect, useState } from 'react'
|
||||
import OLSpinner, {
|
||||
OLSpinnerSize,
|
||||
} from '@/features/ui/components/ol/ol-spinner'
|
||||
import { isBootstrap5 } from '@/features/utils/bootstrap-5'
|
||||
import classNames from 'classnames'
|
||||
|
||||
function LoadingSpinner({
|
||||
@@ -43,12 +42,14 @@ function LoadingSpinner({
|
||||
return null
|
||||
}
|
||||
|
||||
const extraClasses = isBootstrap5()
|
||||
? [align === 'left' ? 'align-items-start' : 'align-items-center']
|
||||
: null
|
||||
|
||||
return (
|
||||
<div className={classNames('loading', className, extraClasses)}>
|
||||
<div
|
||||
className={classNames(
|
||||
'loading',
|
||||
className,
|
||||
align === 'left' ? 'align-items-start' : 'align-items-center'
|
||||
)}
|
||||
>
|
||||
<OLSpinner size={size} />
|
||||
|
||||
{loadingText || `${t('loading')}…`}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import classNames from 'classnames'
|
||||
import React from 'react'
|
||||
import { bsVersion } from '@/features/utils/bootstrap-5'
|
||||
import unfilledIconTypes from '../../../fonts/material-symbols/unfilled-symbols.mjs'
|
||||
|
||||
export type AvailableUnfilledIcon = (typeof unfilledIconTypes)[number]
|
||||
@@ -43,9 +42,7 @@ function MaterialIcon({
|
||||
{type}
|
||||
</span>
|
||||
{accessibilityLabel && (
|
||||
<span className={bsVersion({ bs5: 'visually-hidden', bs3: 'sr-only' })}>
|
||||
{accessibilityLabel}
|
||||
</span>
|
||||
<span className="visually-hidden">{accessibilityLabel}</span>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -10,9 +10,7 @@ import {
|
||||
} from 'react'
|
||||
import classNames from 'classnames'
|
||||
import { useSelect } from 'downshift'
|
||||
import Icon from './icon'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
|
||||
import { Form, Spinner } from 'react-bootstrap-5'
|
||||
import FormControl from '@/features/ui/components/bootstrap-5/form/form-control'
|
||||
import MaterialIcon from '@/shared/components/material-icon'
|
||||
@@ -150,150 +148,73 @@ export const Select = <T,>({
|
||||
} else {
|
||||
value = defaultText
|
||||
}
|
||||
return (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={
|
||||
<div className="select-wrapper" ref={rootRef}>
|
||||
<div>
|
||||
{label ? (
|
||||
<label {...getLabelProps()}>
|
||||
{label}{' '}
|
||||
{optionalLabel && (
|
||||
<span className="select-optional-label text-muted">
|
||||
({t('optional')})
|
||||
</span>
|
||||
)}{' '}
|
||||
{loading && (
|
||||
<Icon data-testid="spinner" fw type="spinner" spin />
|
||||
)}
|
||||
</label>
|
||||
) : null}
|
||||
<div
|
||||
className={classNames({ disabled }, 'select-trigger')}
|
||||
// eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
|
||||
tabIndex={0}
|
||||
{...getToggleButtonProps({
|
||||
disabled,
|
||||
onKeyDown,
|
||||
})}
|
||||
>
|
||||
<div>{value}</div>
|
||||
<div>
|
||||
{isOpen ? (
|
||||
<Icon type="chevron-up" fw />
|
||||
) : (
|
||||
<Icon type="chevron-down" fw />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ul
|
||||
className={classNames({ hidden: !isOpen }, 'select-items')}
|
||||
{...getMenuProps({ disabled, onKeyDown: handleMenuKeyDown })}
|
||||
>
|
||||
{isOpen &&
|
||||
items?.map((item, index) => {
|
||||
const isDisabled = itemToDisabled && itemToDisabled(item)
|
||||
return (
|
||||
<li
|
||||
className={classNames({
|
||||
'select-highlighted': highlightedIndex === index,
|
||||
'selected-active': selectedItem === item,
|
||||
'select-icon': selectedIcon,
|
||||
'select-disabled': isDisabled,
|
||||
})}
|
||||
key={itemToKey(item)}
|
||||
{...getItemProps({ item, index, disabled: isDisabled })}
|
||||
>
|
||||
<span className="select-item-title">
|
||||
{selectedIcon && (
|
||||
<div className="select-item-icon">
|
||||
{(selectedItem === item ||
|
||||
(!selectedItem && defaultItem === item)) && (
|
||||
<Icon type="check" fw />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{itemToString(item)}
|
||||
</span>
|
||||
|
||||
{itemToSubtitle ? (
|
||||
<span className="text-muted select-item-subtitle">
|
||||
{itemToSubtitle(item)}
|
||||
</span>
|
||||
) : null}
|
||||
</li>
|
||||
)
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
}
|
||||
bs5={
|
||||
<div className="select-wrapper" ref={rootRef}>
|
||||
{label ? (
|
||||
<Form.Label {...getLabelProps()}>
|
||||
{label}{' '}
|
||||
{optionalLabel && (
|
||||
<span className="fw-normal">({t('optional')})</span>
|
||||
)}{' '}
|
||||
{loading && (
|
||||
<span data-testid="spinner">
|
||||
<Spinner
|
||||
animation="border"
|
||||
aria-hidden="true"
|
||||
as="span"
|
||||
role="status"
|
||||
size="sm"
|
||||
/>
|
||||
</span>
|
||||
)}
|
||||
</Form.Label>
|
||||
) : null}
|
||||
<FormControl
|
||||
data-testid={dataTestId}
|
||||
{...getToggleButtonProps({
|
||||
disabled,
|
||||
onKeyDown,
|
||||
className: 'select-trigger',
|
||||
})}
|
||||
value={value}
|
||||
readOnly
|
||||
append={
|
||||
<MaterialIcon
|
||||
type={isOpen ? 'keyboard_arrow_up' : 'keyboard_arrow_down'}
|
||||
className="align-text-bottom"
|
||||
return (
|
||||
<div className="select-wrapper" ref={rootRef}>
|
||||
{label ? (
|
||||
<Form.Label {...getLabelProps()}>
|
||||
{label}{' '}
|
||||
{optionalLabel && (
|
||||
<span className="fw-normal">({t('optional')})</span>
|
||||
)}{' '}
|
||||
{loading && (
|
||||
<span data-testid="spinner">
|
||||
<Spinner
|
||||
animation="border"
|
||||
aria-hidden="true"
|
||||
as="span"
|
||||
role="status"
|
||||
size="sm"
|
||||
/>
|
||||
}
|
||||
</span>
|
||||
)}
|
||||
</Form.Label>
|
||||
) : null}
|
||||
<FormControl
|
||||
data-testid={dataTestId}
|
||||
{...getToggleButtonProps({
|
||||
disabled,
|
||||
onKeyDown,
|
||||
className: 'select-trigger',
|
||||
})}
|
||||
value={value}
|
||||
readOnly
|
||||
append={
|
||||
<MaterialIcon
|
||||
type={isOpen ? 'keyboard_arrow_up' : 'keyboard_arrow_down'}
|
||||
className="align-text-bottom"
|
||||
/>
|
||||
<ul
|
||||
{...getMenuProps({ disabled, onKeyDown: handleMenuKeyDown })}
|
||||
className={classNames('dropdown-menu w-100', { show: isOpen })}
|
||||
>
|
||||
{isOpen &&
|
||||
items?.map((item, index) => {
|
||||
const isDisabled = itemToDisabled && itemToDisabled(item)
|
||||
return (
|
||||
<li role="none" key={itemToKey(item)}>
|
||||
<DropdownItem
|
||||
as="button"
|
||||
className={classNames({
|
||||
'select-highlighted': highlightedIndex === index,
|
||||
})}
|
||||
active={selectedItem === item}
|
||||
trailingIcon={selectedItem === item ? 'check' : undefined}
|
||||
description={
|
||||
itemToSubtitle ? itemToSubtitle(item) : undefined
|
||||
}
|
||||
{...getItemProps({ item, index, disabled: isDisabled })}
|
||||
>
|
||||
{itemToString(item)}
|
||||
</DropdownItem>
|
||||
</li>
|
||||
)
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
<ul
|
||||
{...getMenuProps({ disabled, onKeyDown: handleMenuKeyDown })}
|
||||
className={classNames('dropdown-menu w-100', { show: isOpen })}
|
||||
>
|
||||
{isOpen &&
|
||||
items?.map((item, index) => {
|
||||
const isDisabled = itemToDisabled && itemToDisabled(item)
|
||||
return (
|
||||
<li role="none" key={itemToKey(item)}>
|
||||
<DropdownItem
|
||||
as="button"
|
||||
className={classNames({
|
||||
'select-highlighted': highlightedIndex === index,
|
||||
})}
|
||||
active={selectedItem === item}
|
||||
trailingIcon={
|
||||
selectedIcon && selectedItem === item ? 'check' : undefined
|
||||
}
|
||||
description={
|
||||
itemToSubtitle ? itemToSubtitle(item) : undefined
|
||||
}
|
||||
{...getItemProps({ item, index, disabled: isDisabled })}
|
||||
>
|
||||
{itemToString(item)}
|
||||
</DropdownItem>
|
||||
</li>
|
||||
)
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Label } from 'react-bootstrap'
|
||||
import { MergeAndOverride } from '../../../../types/utils'
|
||||
import classnames from 'classnames'
|
||||
|
||||
type TagProps = MergeAndOverride<
|
||||
React.ComponentProps<'span'>,
|
||||
{
|
||||
prepend?: React.ReactNode
|
||||
children: React.ReactNode
|
||||
contentProps?: React.ComponentProps<'button'>
|
||||
closeBtnProps?: React.ComponentProps<'button'>
|
||||
className?: string
|
||||
bsStyle?: React.ComponentProps<typeof Label>['bsStyle'] | null
|
||||
}
|
||||
>
|
||||
|
||||
function Tag({
|
||||
prepend,
|
||||
children,
|
||||
contentProps,
|
||||
closeBtnProps,
|
||||
bsStyle,
|
||||
className,
|
||||
...rest
|
||||
}: TagProps) {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<span className={classnames('badge-tag-bs3', className)} {...rest}>
|
||||
<span
|
||||
{...contentProps}
|
||||
className={classnames(
|
||||
'badge-tag-bs3-content-wrapper',
|
||||
{ clickable: Boolean(contentProps?.onClick) },
|
||||
contentProps?.className
|
||||
)}
|
||||
>
|
||||
{prepend && <span className="badge-tag-bs3-prepend">{prepend}</span>}
|
||||
<span className="badge-tag-bs3-content">{children}</span>
|
||||
</span>
|
||||
{closeBtnProps && (
|
||||
<button
|
||||
type="button"
|
||||
className="badge-tag-bs3-close"
|
||||
aria-label={t('remove_tag', { tagName: children })}
|
||||
{...closeBtnProps}
|
||||
>
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
)}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
export default Tag
|
||||
@@ -1,57 +0,0 @@
|
||||
import { cloneElement } from 'react'
|
||||
import {
|
||||
OverlayTrigger,
|
||||
OverlayTriggerProps,
|
||||
Tooltip as BSTooltip,
|
||||
} from 'react-bootstrap'
|
||||
import { callFnsInSequence } from '../../utils/functions'
|
||||
|
||||
type OverlayProps = Omit<OverlayTriggerProps, 'overlay'> & {
|
||||
shouldUpdatePosition?: boolean // Not officially documented https://stackoverflow.com/a/43138470
|
||||
}
|
||||
|
||||
export type TooltipProps = {
|
||||
description: React.ReactNode
|
||||
id: string
|
||||
overlayProps?: OverlayProps
|
||||
tooltipProps?: BSTooltip.TooltipProps
|
||||
hidden?: boolean
|
||||
children: React.ReactElement
|
||||
}
|
||||
|
||||
function Tooltip({
|
||||
id,
|
||||
description,
|
||||
children,
|
||||
tooltipProps,
|
||||
overlayProps,
|
||||
hidden,
|
||||
}: TooltipProps) {
|
||||
const hideTooltip = (e: React.MouseEvent) => {
|
||||
if (e.currentTarget instanceof HTMLElement) {
|
||||
e.currentTarget.blur()
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<OverlayTrigger
|
||||
overlay={
|
||||
<BSTooltip
|
||||
id={`${id}-tooltip`}
|
||||
{...tooltipProps}
|
||||
style={{ display: hidden ? 'none' : 'block' }}
|
||||
>
|
||||
{description}
|
||||
</BSTooltip>
|
||||
}
|
||||
{...overlayProps}
|
||||
placement={overlayProps?.placement || 'top'}
|
||||
>
|
||||
{cloneElement(children, {
|
||||
onClick: callFnsInSequence(children.props.onClick, hideTooltip),
|
||||
})}
|
||||
</OverlayTrigger>
|
||||
)
|
||||
}
|
||||
|
||||
export default Tooltip
|
||||
@@ -1,16 +1,9 @@
|
||||
import Icon from './icon'
|
||||
import MaterialIcon from '@/shared/components/material-icon'
|
||||
import BootstrapVersionSwitcher from '@/features/ui/components/bootstrap-5/bootstrap-version-switcher'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { memo } from 'react'
|
||||
|
||||
function Check() {
|
||||
return (
|
||||
<BootstrapVersionSwitcher
|
||||
bs3={<Icon type="check" />}
|
||||
bs5={<MaterialIcon type="check" />}
|
||||
/>
|
||||
)
|
||||
return <MaterialIcon type="check" />
|
||||
}
|
||||
|
||||
function UpgradeBenefits() {
|
||||
|
||||
@@ -3,40 +3,10 @@ import useFetchMock from './hooks/use-fetch-mock'
|
||||
import ContactUsModal from '../../modules/support/frontend/js/components/contact-us-modal'
|
||||
import fixedHelpSuggestionSearch from '../../modules/support/test/frontend/util/fixed-help-suggestion-search'
|
||||
import { ScopeDecorator } from './decorators/scope'
|
||||
import { StoryObj } from '@storybook/react'
|
||||
import OLButton from '@/features/ui/components/ol/ol-button'
|
||||
import { bsVersionDecorator } from '../../.storybook/utils/with-bootstrap-switcher'
|
||||
|
||||
type Story = StoryObj<typeof ContactUsModal>
|
||||
type ContactUsModalProps = ComponentProps<typeof ContactUsModal>
|
||||
|
||||
function bootstrap3Story(render: Story['render']): Story {
|
||||
return {
|
||||
render,
|
||||
decorators: [
|
||||
story => {
|
||||
return ScopeDecorator(story)
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
function bootstrap5Story(render: Story['render']): Story {
|
||||
return {
|
||||
render,
|
||||
decorators: [
|
||||
story => {
|
||||
return ScopeDecorator(story, undefined, {
|
||||
'ol-bootstrapVersion': 5,
|
||||
})
|
||||
},
|
||||
],
|
||||
parameters: {
|
||||
bootstrap5: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
function GenericContactUsModal(args: ContactUsModalProps) {
|
||||
useFetchMock(fetchMock => {
|
||||
fetchMock.post('/support', { status: 200 }, { delay: 1000 })
|
||||
@@ -50,13 +20,9 @@ function GenericContactUsModal(args: ContactUsModalProps) {
|
||||
)
|
||||
}
|
||||
|
||||
export const Generic: Story = bootstrap3Story(args => (
|
||||
export const Generic = (args: ContactUsModalProps) => (
|
||||
<GenericContactUsModal {...args} />
|
||||
))
|
||||
|
||||
export const GenericBootstrap5: Story = bootstrap5Story(args => (
|
||||
<GenericContactUsModal {...args} />
|
||||
))
|
||||
)
|
||||
|
||||
const ContactUsModalWithRequestError = (args: ContactUsModalProps) => {
|
||||
useFetchMock(fetchMock => {
|
||||
@@ -71,18 +37,10 @@ const ContactUsModalWithRequestError = (args: ContactUsModalProps) => {
|
||||
)
|
||||
}
|
||||
|
||||
const renderContactUsModalWithRequestError = (args: ContactUsModalProps) => (
|
||||
export const RequestError = (args: ContactUsModalProps) => (
|
||||
<ContactUsModalWithRequestError {...args} />
|
||||
)
|
||||
|
||||
export const RequestError: Story = bootstrap3Story(
|
||||
renderContactUsModalWithRequestError
|
||||
)
|
||||
|
||||
export const RequestErrorBootstrap5: Story = bootstrap5Story(
|
||||
renderContactUsModalWithRequestError
|
||||
)
|
||||
|
||||
const ContactUsModalWithAcknowledgement = (
|
||||
args: Omit<ContactUsModalProps, 'show' | 'handleHide'>
|
||||
) => {
|
||||
@@ -110,19 +68,11 @@ const ContactUsModalWithAcknowledgement = (
|
||||
)
|
||||
}
|
||||
|
||||
const renderContactUsModalWithAcknowledgement = (args: ContactUsModalProps) => {
|
||||
export const WithAcknowledgement = (args: ContactUsModalProps) => {
|
||||
const { show, handleHide, ...rest } = args
|
||||
return <ContactUsModalWithAcknowledgement {...rest} />
|
||||
}
|
||||
|
||||
export const WithAcknowledgement: Story = bootstrap3Story(
|
||||
renderContactUsModalWithAcknowledgement
|
||||
)
|
||||
|
||||
export const WithAcknowledgementBootstrap5: Story = bootstrap5Story(
|
||||
renderContactUsModalWithAcknowledgement
|
||||
)
|
||||
|
||||
export default {
|
||||
title: 'Shared / Modals / Contact Us',
|
||||
component: ContactUsModal,
|
||||
@@ -133,6 +83,6 @@ export default {
|
||||
},
|
||||
argTypes: {
|
||||
handleHide: { action: 'close modal' },
|
||||
...bsVersionDecorator.argTypes,
|
||||
},
|
||||
decorators: [ScopeDecorator],
|
||||
}
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
import { Dropdown, MenuItem } from 'react-bootstrap'
|
||||
import ControlledDropdown from '../js/shared/components/controlled-dropdown'
|
||||
|
||||
export const Customized = args => {
|
||||
return (
|
||||
<ControlledDropdown
|
||||
pullRight={args.pullRight}
|
||||
defaultOpen={args.defaultOpen}
|
||||
id="dropdown-story"
|
||||
>
|
||||
<Dropdown.Toggle
|
||||
noCaret={args.noCaret}
|
||||
className={args.className}
|
||||
bsStyle={args.bsStyle}
|
||||
>
|
||||
{args.title}
|
||||
</Dropdown.Toggle>
|
||||
<Dropdown.Menu>
|
||||
<MenuItem eventKey="1">Action</MenuItem>
|
||||
<MenuItem eventKey="2">Another action</MenuItem>
|
||||
<MenuItem eventKey="3" active>
|
||||
Active Item
|
||||
</MenuItem>
|
||||
<MenuItem divider />
|
||||
<MenuItem eventKey="4">Separated link</MenuItem>
|
||||
</Dropdown.Menu>
|
||||
</ControlledDropdown>
|
||||
)
|
||||
}
|
||||
Customized.args = {
|
||||
title: 'Toggle & Menu used separately',
|
||||
}
|
||||
|
||||
export default {
|
||||
title: 'Shared / Components / Dropdown',
|
||||
component: ControlledDropdown,
|
||||
args: {
|
||||
bsStyle: 'default',
|
||||
title: 'Dropdown',
|
||||
pullRight: false,
|
||||
noCaret: false,
|
||||
className: '',
|
||||
defaultOpen: true,
|
||||
},
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
import { ScopeDecorator } from './decorators/scope'
|
||||
import { FeedbackBadge } from '@/shared/components/feedback-badge'
|
||||
import { bsVersionDecorator } from '../../.storybook/utils/with-bootstrap-switcher'
|
||||
|
||||
export const WithDefaultText = () => {
|
||||
return (
|
||||
@@ -33,7 +32,4 @@ export default {
|
||||
title: 'Shared / Components / Feedback Badge',
|
||||
component: FeedbackBadge,
|
||||
decorators: [ScopeDecorator],
|
||||
argTypes: {
|
||||
...bsVersionDecorator.argTypes,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import OLFormSwitch from '@/features/ui/components/ol/ol-form-switch'
|
||||
import { bsVersionDecorator } from '../../.storybook/utils/with-bootstrap-switcher'
|
||||
import { disableControlsOf } from './utils/arg-types'
|
||||
|
||||
export const Unchecked = () => {
|
||||
@@ -22,10 +21,6 @@ export default {
|
||||
title: 'Shared / Components / Input Switch',
|
||||
component: OLFormSwitch,
|
||||
argTypes: {
|
||||
...bsVersionDecorator.argTypes,
|
||||
...disableControlsOf('inputRef', 'bs3Props'),
|
||||
},
|
||||
args: {
|
||||
...bsVersionDecorator.args,
|
||||
...disableControlsOf('inputRef'),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react'
|
||||
import { LoadingUI } from '@/features/ide-react/components/loading'
|
||||
import { EditorProviders } from '../../../test/frontend/helpers/editor-providers'
|
||||
import { bsVersionDecorator } from '../../../.storybook/utils/with-bootstrap-switcher'
|
||||
import { PartialMeta } from '@/utils/meta'
|
||||
|
||||
const meta: Meta<typeof LoadingUI> = {
|
||||
@@ -19,7 +18,6 @@ const meta: Meta<typeof LoadingUI> = {
|
||||
],
|
||||
},
|
||||
progress: { control: { type: 'range', min: 0, max: 100 } },
|
||||
...bsVersionDecorator.argTypes,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -30,9 +30,6 @@ const meta: Meta<typeof MenuBar> = {
|
||||
title: 'Shared / Components / MenuBar',
|
||||
component: MenuBar,
|
||||
argTypes: {},
|
||||
parameters: {
|
||||
bootstrap5: true,
|
||||
},
|
||||
}
|
||||
|
||||
export default meta
|
||||
|
||||
@@ -1,18 +1,11 @@
|
||||
import { Meta, StoryObj } from '@storybook/react'
|
||||
import { UnsavedDocsLockedAlert } from '@/features/ide-react/components/unsaved-docs/unsaved-docs-locked-alert'
|
||||
import { ScopeDecorator } from '../decorators/scope'
|
||||
import { bsVersionDecorator } from '../../../.storybook/utils/with-bootstrap-switcher'
|
||||
|
||||
export default {
|
||||
title: 'Editor / Modals / Unsaved Docs Locked',
|
||||
component: UnsavedDocsLockedAlert,
|
||||
decorators: [Story => ScopeDecorator(Story)],
|
||||
argTypes: {
|
||||
...bsVersionDecorator.argTypes,
|
||||
},
|
||||
parameters: {
|
||||
bootstrap5: true,
|
||||
},
|
||||
} satisfies Meta
|
||||
|
||||
type Story = StoryObj<typeof UnsavedDocsLockedAlert>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useCallback, useMemo, useState } from 'react'
|
||||
import useFetchMock from './hooks/use-fetch-mock'
|
||||
import { Button } from 'react-bootstrap'
|
||||
import OLButton from '@/features/ui/components/ol/ol-button'
|
||||
import PdfPreviewPane from '../js/features/pdf-preview/components/pdf-preview-pane'
|
||||
import PdfPreview from '../js/features/pdf-preview/components/pdf-preview'
|
||||
import PdfFileList from '../js/features/pdf-preview/components/pdf-file-list'
|
||||
@@ -123,10 +123,12 @@ export const Interactive = () => {
|
||||
margin: '10px 0',
|
||||
}}
|
||||
>
|
||||
<Button onClick={dispatchDocChanged}>trigger doc change</Button>
|
||||
<Button onClick={toggleLintingError}>
|
||||
<OLButton onClick={dispatchDocChanged}>
|
||||
trigger doc change
|
||||
</OLButton>
|
||||
<OLButton onClick={toggleLintingError}>
|
||||
toggle linting error
|
||||
</Button>
|
||||
</OLButton>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -26,7 +26,4 @@ export const Add = (args: any) => {
|
||||
export default {
|
||||
title: 'Project List / Affiliation',
|
||||
component: AddAffiliation,
|
||||
parameters: {
|
||||
bootstrap5: true,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -12,7 +12,4 @@ export const Select = (args: any) => {
|
||||
export default {
|
||||
title: 'Project List / Color Picker',
|
||||
component: ColorPicker,
|
||||
parameters: {
|
||||
bootstrap5: true,
|
||||
},
|
||||
}
|
||||
|
||||
-3
@@ -62,7 +62,4 @@ export default {
|
||||
</div>
|
||||
),
|
||||
],
|
||||
parameters: {
|
||||
bootstrap5: true,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -72,7 +72,4 @@ export const PausedPlan = (args: any) => {
|
||||
export default {
|
||||
title: 'Project List / Current Plan Widget',
|
||||
component: CurrentPlanWidget,
|
||||
parameters: {
|
||||
bootstrap5: true,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -7,7 +7,4 @@ export const Default = () => {
|
||||
export default {
|
||||
title: 'Project List / INR Banner',
|
||||
component: INRBanner,
|
||||
parameters: {
|
||||
bootstrap5: true,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -104,7 +104,4 @@ export const Error = () => {
|
||||
export default {
|
||||
title: 'Project List / New Project Button',
|
||||
component: NewProjectButton,
|
||||
parameters: {
|
||||
bootstrap5: true,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -343,7 +343,4 @@ export const ReconfirmedAffiliationSuccess = (args: any) => {
|
||||
export default {
|
||||
title: 'Project List / Notifications',
|
||||
component: UserNotifications,
|
||||
parameters: {
|
||||
bootstrap5: true,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -57,7 +57,4 @@ export default {
|
||||
</div>
|
||||
),
|
||||
],
|
||||
parameters: {
|
||||
bootstrap5: true,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -24,7 +24,4 @@ export default {
|
||||
args: {
|
||||
inputValue: '',
|
||||
},
|
||||
parameters: {
|
||||
bootstrap5: true,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -28,7 +28,4 @@ export const EmptySurvey = (args: any) => {
|
||||
export default {
|
||||
title: 'Project List / Survey Widget',
|
||||
component: SurveyWidget,
|
||||
parameters: {
|
||||
bootstrap5: true,
|
||||
},
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user