Merge pull request #16971 from overleaf/td-bootstrap-5-base

Bootstrap 5 base

GitOrigin-RevId: 2ac614298d31a9cf65430a46d726648a742044f9
This commit is contained in:
Tim Down 2024-02-14 15:04:08 +00:00 committed by Copybot
parent 28106dd66c
commit 07e16838b8
25 changed files with 1543 additions and 24 deletions

530
package-lock.json generated
View file

@ -50,6 +50,9 @@
"eslint-plugin-prettier": "^4.0.0", "eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-promise": "^6.0.0", "eslint-plugin-promise": "^6.0.0",
"prettier": "2.5.1", "prettier": "2.5.1",
"resolve-url-loader": "^5.0.0",
"sass": "^1.69.5",
"sass-loader": "^13.3.2",
"typescript": "^5.0.4" "typescript": "^5.0.4"
} }
}, },
@ -9023,9 +9026,9 @@
} }
}, },
"node_modules/@popperjs/core": { "node_modules/@popperjs/core": {
"version": "2.11.6", "version": "2.11.8",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz", "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
"integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==", "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
"dev": true, "dev": true,
"funding": { "funding": {
"type": "opencollective", "type": "opencollective",
@ -9808,6 +9811,21 @@
"react-dom": "^16.8.0 || 17.x" "react-dom": "^16.8.0 || 17.x"
} }
}, },
"node_modules/@react-aria/ssr": {
"version": "3.9.1",
"resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.1.tgz",
"integrity": "sha512-NqzkLFP8ZVI4GSorS0AYljC13QW2sc8bDqJOkBvkAt3M8gbcAXJWVRGtZBCRscki9RZF+rNlnPdg0G0jYkhJcg==",
"dev": true,
"dependencies": {
"@swc/helpers": "^0.5.0"
},
"engines": {
"node": ">= 12"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0"
}
},
"node_modules/@react-dnd/asap": { "node_modules/@react-dnd/asap": {
"version": "5.0.2", "version": "5.0.2",
"resolved": "https://registry.npmjs.org/@react-dnd/asap/-/asap-5.0.2.tgz", "resolved": "https://registry.npmjs.org/@react-dnd/asap/-/asap-5.0.2.tgz",
@ -9866,6 +9884,67 @@
"@codemirror/view": "^6.0.3" "@codemirror/view": "^6.0.3"
} }
}, },
"node_modules/@restart/hooks": {
"version": "0.4.16",
"resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.16.tgz",
"integrity": "sha512-f7aCv7c+nU/3mF7NWLtVVr0Ra80RqsO89hO72r+Y/nvQr5+q0UFGkocElTH6MJApvReVh6JHUFYn2cw1WdHF3w==",
"dev": true,
"dependencies": {
"dequal": "^2.0.3"
},
"peerDependencies": {
"react": ">=16.8.0"
}
},
"node_modules/@restart/ui": {
"version": "1.6.6",
"resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.6.6.tgz",
"integrity": "sha512-eC3puKuWE1SRYbojWHXnvCNHGgf3uzHCb6JOhnF4OXPibOIPEkR1sqDSkL643ydigxwh+ruCa1CmYHlzk7ikKA==",
"dev": true,
"dependencies": {
"@babel/runtime": "^7.21.0",
"@popperjs/core": "^2.11.6",
"@react-aria/ssr": "^3.5.0",
"@restart/hooks": "^0.4.9",
"@types/warning": "^3.0.0",
"dequal": "^2.0.3",
"dom-helpers": "^5.2.0",
"uncontrollable": "^8.0.1",
"warning": "^4.0.3"
},
"peerDependencies": {
"react": ">=16.14.0",
"react-dom": ">=16.14.0"
}
},
"node_modules/@restart/ui/node_modules/dom-helpers": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
"integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
"dev": true,
"dependencies": {
"@babel/runtime": "^7.8.7",
"csstype": "^3.0.2"
}
},
"node_modules/@restart/ui/node_modules/uncontrollable": {
"version": "8.0.4",
"resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-8.0.4.tgz",
"integrity": "sha512-ulRWYWHvscPFc0QQXvyJjY6LIXU56f0h8pQFvhxiKk5V1fcI8gp9Ht9leVAhrVjzqMw0BgjspBINx9r6oyJUvQ==",
"dev": true,
"peerDependencies": {
"react": ">=16.14.0"
}
},
"node_modules/@restart/ui/node_modules/warning": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
"integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
"dev": true,
"dependencies": {
"loose-envify": "^1.0.0"
}
},
"node_modules/@sentry/browser": { "node_modules/@sentry/browser": {
"version": "7.8.1", "version": "7.8.1",
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.8.1.tgz", "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.8.1.tgz",
@ -15042,6 +15121,15 @@
"integrity": "sha512-9F4ys4C74eSTEUNndnER3VJ15oru2NumfQxS8geE+f3eB5xvfxpWyqE5XlVnxb/R14uoXi6SLbBwwiDSkv+XEw==", "integrity": "sha512-9F4ys4C74eSTEUNndnER3VJ15oru2NumfQxS8geE+f3eB5xvfxpWyqE5XlVnxb/R14uoXi6SLbBwwiDSkv+XEw==",
"dev": true "dev": true
}, },
"node_modules/@swc/helpers": {
"version": "0.5.6",
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.6.tgz",
"integrity": "sha512-aYX01Ke9hunpoCexYAgQucEpARGQ5w/cqHFrIR+e9gdKb1QWTsVJuTJ2ozQzIAxLyRQe/m+2RqzkyOOGiMKRQA==",
"dev": true,
"dependencies": {
"tslib": "^2.4.0"
}
},
"node_modules/@swc/types": { "node_modules/@swc/types": {
"version": "0.1.5", "version": "0.1.5",
"resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.5.tgz", "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.5.tgz",
@ -15380,9 +15468,9 @@
} }
}, },
"node_modules/@types/bootstrap": { "node_modules/@types/bootstrap": {
"version": "5.2.6", "version": "5.2.10",
"resolved": "https://registry.npmjs.org/@types/bootstrap/-/bootstrap-5.2.6.tgz", "resolved": "https://registry.npmjs.org/@types/bootstrap/-/bootstrap-5.2.10.tgz",
"integrity": "sha512-BlAc3YATdasbHoxMoBWODrSF6qwQO/E9X8wVxCCSa6rWjnaZfpkr2N6pUMCY6jj2+wf0muUtLySbvU9etX6YqA==", "integrity": "sha512-F2X+cd6551tep0MvVZ6nM8v7XgGN/twpdNDjqS1TUM7YFNEtQYWk+dKAnH+T1gr6QgCoGMPl487xw/9hXooa2g==",
"dev": true, "dev": true,
"dependencies": { "dependencies": {
"@popperjs/core": "^2.9.2" "@popperjs/core": "^2.9.2"
@ -15982,6 +16070,15 @@
"@types/react": "*" "@types/react": "*"
} }
}, },
"node_modules/@types/react-transition-group": {
"version": "4.4.10",
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz",
"integrity": "sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==",
"dev": true,
"dependencies": {
"@types/react": "*"
}
},
"node_modules/@types/reactcss": { "node_modules/@types/reactcss": {
"version": "1.2.6", "version": "1.2.6",
"resolved": "https://registry.npmjs.org/@types/reactcss/-/reactcss-1.2.6.tgz", "resolved": "https://registry.npmjs.org/@types/reactcss/-/reactcss-1.2.6.tgz",
@ -16136,6 +16233,12 @@
"resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.15.tgz", "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.15.tgz",
"integrity": "sha512-yeinDVQunb03AEP8luErFcyf/7Lf7AzKCD0NXfgVoGCCQDNpZET8Jgq74oBgqKld3hafLbfzt/3inUdQvaFeXQ==" "integrity": "sha512-yeinDVQunb03AEP8luErFcyf/7Lf7AzKCD0NXfgVoGCCQDNpZET8Jgq74oBgqKld3hafLbfzt/3inUdQvaFeXQ=="
}, },
"node_modules/@types/warning": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.3.tgz",
"integrity": "sha512-D1XC7WK8K+zZEveUPY+cf4+kgauk8N4eHr/XIHXGlGYkHLud6hK9lYfZk1ry1TNh798cZUCgb6MqGEG8DkJt6Q==",
"dev": true
},
"node_modules/@types/webidl-conversions": { "node_modules/@types/webidl-conversions": {
"version": "7.0.0", "version": "7.0.0",
"resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz", "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
@ -16871,6 +16974,19 @@
"node": ">= 10.0.0" "node": ">= 10.0.0"
} }
}, },
"node_modules/adjust-sourcemap-loader": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz",
"integrity": "sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==",
"dev": true,
"dependencies": {
"loader-utils": "^2.0.0",
"regex-parser": "^2.2.11"
},
"engines": {
"node": ">=8.9"
}
},
"node_modules/agent-base": { "node_modules/agent-base": {
"version": "6.0.2", "version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
@ -18517,6 +18633,26 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/bootstrap-5": {
"name": "bootstrap",
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.2.tgz",
"integrity": "sha512-D32nmNWiQHo94BKHLmOrdjlL05q1c8oxbtBphQFb9Z5to6eGRDCm0QgeaZ4zFBHzfg2++rqa2JkqCcxDy0sH0g==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/twbs"
},
{
"type": "opencollective",
"url": "https://opencollective.com/bootstrap"
}
],
"peerDependencies": {
"@popperjs/core": "^2.11.8"
}
},
"node_modules/bowser": { "node_modules/bowser": {
"version": "2.11.0", "version": "2.11.0",
"resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz",
@ -19497,9 +19633,9 @@
"integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==" "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ=="
}, },
"node_modules/classnames": { "node_modules/classnames": {
"version": "2.3.1", "version": "2.5.1",
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz", "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz",
"integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==" "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow=="
}, },
"node_modules/clean-css": { "node_modules/clean-css": {
"version": "5.3.0", "version": "5.3.0",
@ -27497,6 +27633,12 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/immutable": {
"version": "4.3.5",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.5.tgz",
"integrity": "sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw==",
"dev": true
},
"node_modules/import-fresh": { "node_modules/import-fresh": {
"version": "3.3.0", "version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
@ -36186,6 +36328,72 @@
"react-dom": ">=16.3.0" "react-dom": ">=16.3.0"
} }
}, },
"node_modules/react-bootstrap-5": {
"name": "react-bootstrap",
"version": "2.10.1",
"resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.10.1.tgz",
"integrity": "sha512-J3OpRZIvCTQK+Tg/jOkRUvpYLHMdGeU9KqFUBQrV0d/Qr/3nsINpiOJyZMWnM5SJ3ctZdhPA6eCIKpEJR3Ellg==",
"dev": true,
"dependencies": {
"@babel/runtime": "^7.22.5",
"@restart/hooks": "^0.4.9",
"@restart/ui": "^1.6.6",
"@types/react-transition-group": "^4.4.6",
"classnames": "^2.3.2",
"dom-helpers": "^5.2.1",
"invariant": "^2.2.4",
"prop-types": "^15.8.1",
"prop-types-extra": "^1.1.0",
"react-transition-group": "^4.4.5",
"uncontrollable": "^7.2.1",
"warning": "^4.0.3"
},
"peerDependencies": {
"@types/react": ">=16.14.8",
"react": ">=16.14.0",
"react-dom": ">=16.14.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/react-bootstrap-5/node_modules/dom-helpers": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
"integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
"dev": true,
"dependencies": {
"@babel/runtime": "^7.8.7",
"csstype": "^3.0.2"
}
},
"node_modules/react-bootstrap-5/node_modules/react-transition-group": {
"version": "4.4.5",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
"integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
"dev": true,
"dependencies": {
"@babel/runtime": "^7.5.5",
"dom-helpers": "^5.0.1",
"loose-envify": "^1.4.0",
"prop-types": "^15.6.2"
},
"peerDependencies": {
"react": ">=16.6.0",
"react-dom": ">=16.6.0"
}
},
"node_modules/react-bootstrap-5/node_modules/warning": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
"integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
"dev": true,
"dependencies": {
"loose-envify": "^1.0.0"
}
},
"node_modules/react-chartjs-2": { "node_modules/react-chartjs-2": {
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-5.0.1.tgz", "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-5.0.1.tgz",
@ -37062,6 +37270,12 @@
"@babel/runtime": "^7.8.4" "@babel/runtime": "^7.8.4"
} }
}, },
"node_modules/regex-parser": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.3.0.tgz",
"integrity": "sha512-TVILVSz2jY5D47F4mA4MppkBrafEaiUWJO/TcZHEIuI13AqoZMkK1WMA4Om1YkYbTx+9Ki1/tSUXbceyr9saRg==",
"dev": true
},
"node_modules/regexp.prototype.flags": { "node_modules/regexp.prototype.flags": {
"version": "1.5.1", "version": "1.5.1",
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz",
@ -37399,6 +37613,22 @@
"node": ">= 10.13.0" "node": ">= 10.13.0"
} }
}, },
"node_modules/resolve-url-loader": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-5.0.0.tgz",
"integrity": "sha512-uZtduh8/8srhBoMx//5bwqjQ+rfYOUq8zC9NrMUGtjBiGTtFJM42s58/36+hTqeqINcnYe08Nj3LkK9lW4N8Xg==",
"dev": true,
"dependencies": {
"adjust-sourcemap-loader": "^4.0.0",
"convert-source-map": "^1.7.0",
"loader-utils": "^2.0.0",
"postcss": "^8.2.14",
"source-map": "0.6.1"
},
"engines": {
"node": ">=12"
}
},
"node_modules/restore-cursor": { "node_modules/restore-cursor": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
@ -37723,6 +37953,60 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/sass": {
"version": "1.70.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.70.0.tgz",
"integrity": "sha512-uUxNQ3zAHeAx5nRFskBnrWzDUJrrvpCPD5FNAoRvTi0WwremlheES3tg+56PaVtCs5QDRX5CBLxxKMDJMEa1WQ==",
"dev": true,
"dependencies": {
"chokidar": ">=3.0.0 <4.0.0",
"immutable": "^4.0.0",
"source-map-js": ">=0.6.2 <2.0.0"
},
"bin": {
"sass": "sass.js"
},
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/sass-loader": {
"version": "13.3.3",
"resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.3.3.tgz",
"integrity": "sha512-mt5YN2F1MOZr3d/wBRcZxeFgwgkH44wVc2zohO2YF6JiOMkiXe4BYRZpSu2sO1g71mo/j16txzUhsKZlqjVGzA==",
"dev": true,
"dependencies": {
"neo-async": "^2.6.2"
},
"engines": {
"node": ">= 14.15.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
},
"peerDependencies": {
"fibers": ">= 3.1.0",
"node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0",
"sass": "^1.3.0",
"sass-embedded": "*",
"webpack": "^5.0.0"
},
"peerDependenciesMeta": {
"fibers": {
"optional": true
},
"node-sass": {
"optional": true
},
"sass": {
"optional": true
},
"sass-embedded": {
"optional": true
}
}
},
"node_modules/sax": { "node_modules/sax": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz",
@ -46059,7 +46343,7 @@
"@testing-library/react": "^12.1.5", "@testing-library/react": "^12.1.5",
"@testing-library/react-hooks": "^8.0.1", "@testing-library/react-hooks": "^8.0.1",
"@testing-library/user-event": "^14.4.3", "@testing-library/user-event": "^14.4.3",
"@types/bootstrap": "^5.2.6", "@types/bootstrap": "^5.2.10",
"@types/chai": "^4.3.0", "@types/chai": "^4.3.0",
"@types/events": "^3.0.0", "@types/events": "^3.0.0",
"@types/express": "^4.17.13", "@types/express": "^4.17.13",
@ -46095,6 +46379,7 @@
"babel-plugin-module-resolver": "^5.0.0", "babel-plugin-module-resolver": "^5.0.0",
"backbone": "^1.3.3", "backbone": "^1.3.3",
"bootstrap": "^3.4.1", "bootstrap": "^3.4.1",
"bootstrap-5": "npm:bootstrap@^5.3.2",
"c8": "^7.2.0", "c8": "^7.2.0",
"chai": "^4.3.6", "chai": "^4.3.6",
"chai-as-promised": "^7.1.1", "chai-as-promised": "^7.1.1",
@ -46152,6 +46437,7 @@
"qrcode": "^1.4.4", "qrcode": "^1.4.4",
"react": "^17.0.2", "react": "^17.0.2",
"react-bootstrap": "^0.33.1", "react-bootstrap": "^0.33.1",
"react-bootstrap-5": "npm:react-bootstrap@^2.10.0",
"react-chartjs-2": "^5.0.1", "react-chartjs-2": "^5.0.1",
"react-color": "^2.19.3", "react-color": "^2.19.3",
"react-dnd": "^16.0.1", "react-dnd": "^16.0.1",
@ -54796,7 +55082,7 @@
"@testing-library/react": "^12.1.5", "@testing-library/react": "^12.1.5",
"@testing-library/react-hooks": "^8.0.1", "@testing-library/react-hooks": "^8.0.1",
"@testing-library/user-event": "^14.4.3", "@testing-library/user-event": "^14.4.3",
"@types/bootstrap": "^5.2.6", "@types/bootstrap": "^5.2.10",
"@types/chai": "^4.3.0", "@types/chai": "^4.3.0",
"@types/events": "^3.0.0", "@types/events": "^3.0.0",
"@types/express": "^4.17.13", "@types/express": "^4.17.13",
@ -54840,6 +55126,7 @@
"bcrypt": "^5.0.0", "bcrypt": "^5.0.0",
"body-parser": "^1.19.0", "body-parser": "^1.19.0",
"bootstrap": "^3.4.1", "bootstrap": "^3.4.1",
"bootstrap-5": "npm:bootstrap@^5.3.2",
"bowser": "^2.11.0", "bowser": "^2.11.0",
"bull": "^3.18.0", "bull": "^3.18.0",
"bunyan": "^1.8.15", "bunyan": "^1.8.15",
@ -54957,6 +55244,7 @@
"rate-limiter-flexible": "^2.4.1", "rate-limiter-flexible": "^2.4.1",
"react": "^17.0.2", "react": "^17.0.2",
"react-bootstrap": "^0.33.1", "react-bootstrap": "^0.33.1",
"react-bootstrap-5": "npm:react-bootstrap@^2.10.0",
"react-chartjs-2": "^5.0.1", "react-chartjs-2": "^5.0.1",
"react-color": "^2.19.3", "react-color": "^2.19.3",
"react-dnd": "^16.0.1", "react-dnd": "^16.0.1",
@ -56167,9 +56455,9 @@
} }
}, },
"@popperjs/core": { "@popperjs/core": {
"version": "2.11.6", "version": "2.11.8",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz", "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
"integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==", "integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
"dev": true "dev": true
}, },
"@protobufjs/aspromise": { "@protobufjs/aspromise": {
@ -56619,6 +56907,15 @@
"tslib": "^2.3.0" "tslib": "^2.3.0"
} }
}, },
"@react-aria/ssr": {
"version": "3.9.1",
"resolved": "https://registry.npmjs.org/@react-aria/ssr/-/ssr-3.9.1.tgz",
"integrity": "sha512-NqzkLFP8ZVI4GSorS0AYljC13QW2sc8bDqJOkBvkAt3M8gbcAXJWVRGtZBCRscki9RZF+rNlnPdg0G0jYkhJcg==",
"dev": true,
"requires": {
"@swc/helpers": "^0.5.0"
}
},
"@react-dnd/asap": { "@react-dnd/asap": {
"version": "5.0.2", "version": "5.0.2",
"resolved": "https://registry.npmjs.org/@react-dnd/asap/-/asap-5.0.2.tgz", "resolved": "https://registry.npmjs.org/@react-dnd/asap/-/asap-5.0.2.tgz",
@ -56658,6 +56955,60 @@
"from": "@replit/codemirror-vim@overleaf/codemirror-vim#53ce7363f80fba133d51ee861ca5e9b49af8e96b", "from": "@replit/codemirror-vim@overleaf/codemirror-vim#53ce7363f80fba133d51ee861ca5e9b49af8e96b",
"requires": {} "requires": {}
}, },
"@restart/hooks": {
"version": "0.4.16",
"resolved": "https://registry.npmjs.org/@restart/hooks/-/hooks-0.4.16.tgz",
"integrity": "sha512-f7aCv7c+nU/3mF7NWLtVVr0Ra80RqsO89hO72r+Y/nvQr5+q0UFGkocElTH6MJApvReVh6JHUFYn2cw1WdHF3w==",
"dev": true,
"requires": {
"dequal": "^2.0.3"
}
},
"@restart/ui": {
"version": "1.6.6",
"resolved": "https://registry.npmjs.org/@restart/ui/-/ui-1.6.6.tgz",
"integrity": "sha512-eC3puKuWE1SRYbojWHXnvCNHGgf3uzHCb6JOhnF4OXPibOIPEkR1sqDSkL643ydigxwh+ruCa1CmYHlzk7ikKA==",
"dev": true,
"requires": {
"@babel/runtime": "^7.21.0",
"@popperjs/core": "^2.11.6",
"@react-aria/ssr": "^3.5.0",
"@restart/hooks": "^0.4.9",
"@types/warning": "^3.0.0",
"dequal": "^2.0.3",
"dom-helpers": "^5.2.0",
"uncontrollable": "^8.0.1",
"warning": "^4.0.3"
},
"dependencies": {
"dom-helpers": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
"integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
"dev": true,
"requires": {
"@babel/runtime": "^7.8.7",
"csstype": "^3.0.2"
}
},
"uncontrollable": {
"version": "8.0.4",
"resolved": "https://registry.npmjs.org/uncontrollable/-/uncontrollable-8.0.4.tgz",
"integrity": "sha512-ulRWYWHvscPFc0QQXvyJjY6LIXU56f0h8pQFvhxiKk5V1fcI8gp9Ht9leVAhrVjzqMw0BgjspBINx9r6oyJUvQ==",
"dev": true,
"requires": {}
},
"warning": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
"integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
"dev": true,
"requires": {
"loose-envify": "^1.0.0"
}
}
}
},
"@sentry/browser": { "@sentry/browser": {
"version": "7.8.1", "version": "7.8.1",
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.8.1.tgz", "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.8.1.tgz",
@ -60496,6 +60847,15 @@
"integrity": "sha512-9F4ys4C74eSTEUNndnER3VJ15oru2NumfQxS8geE+f3eB5xvfxpWyqE5XlVnxb/R14uoXi6SLbBwwiDSkv+XEw==", "integrity": "sha512-9F4ys4C74eSTEUNndnER3VJ15oru2NumfQxS8geE+f3eB5xvfxpWyqE5XlVnxb/R14uoXi6SLbBwwiDSkv+XEw==",
"dev": true "dev": true
}, },
"@swc/helpers": {
"version": "0.5.6",
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.6.tgz",
"integrity": "sha512-aYX01Ke9hunpoCexYAgQucEpARGQ5w/cqHFrIR+e9gdKb1QWTsVJuTJ2ozQzIAxLyRQe/m+2RqzkyOOGiMKRQA==",
"dev": true,
"requires": {
"tslib": "^2.4.0"
}
},
"@swc/types": { "@swc/types": {
"version": "0.1.5", "version": "0.1.5",
"resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.5.tgz", "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.5.tgz",
@ -60751,9 +61111,9 @@
} }
}, },
"@types/bootstrap": { "@types/bootstrap": {
"version": "5.2.6", "version": "5.2.10",
"resolved": "https://registry.npmjs.org/@types/bootstrap/-/bootstrap-5.2.6.tgz", "resolved": "https://registry.npmjs.org/@types/bootstrap/-/bootstrap-5.2.10.tgz",
"integrity": "sha512-BlAc3YATdasbHoxMoBWODrSF6qwQO/E9X8wVxCCSa6rWjnaZfpkr2N6pUMCY6jj2+wf0muUtLySbvU9etX6YqA==", "integrity": "sha512-F2X+cd6551tep0MvVZ6nM8v7XgGN/twpdNDjqS1TUM7YFNEtQYWk+dKAnH+T1gr6QgCoGMPl487xw/9hXooa2g==",
"dev": true, "dev": true,
"requires": { "requires": {
"@popperjs/core": "^2.9.2" "@popperjs/core": "^2.9.2"
@ -61352,6 +61712,15 @@
"@types/react": "*" "@types/react": "*"
} }
}, },
"@types/react-transition-group": {
"version": "4.4.10",
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.10.tgz",
"integrity": "sha512-hT/+s0VQs2ojCX823m60m5f0sL5idt9SO6Tj6Dg+rdphGPIeJbJ6CxvBYkgkGKrYeDjvIpKTR38UzmtHJOGW3Q==",
"dev": true,
"requires": {
"@types/react": "*"
}
},
"@types/reactcss": { "@types/reactcss": {
"version": "1.2.6", "version": "1.2.6",
"resolved": "https://registry.npmjs.org/@types/reactcss/-/reactcss-1.2.6.tgz", "resolved": "https://registry.npmjs.org/@types/reactcss/-/reactcss-1.2.6.tgz",
@ -61506,6 +61875,12 @@
"resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.15.tgz", "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.7.15.tgz",
"integrity": "sha512-yeinDVQunb03AEP8luErFcyf/7Lf7AzKCD0NXfgVoGCCQDNpZET8Jgq74oBgqKld3hafLbfzt/3inUdQvaFeXQ==" "integrity": "sha512-yeinDVQunb03AEP8luErFcyf/7Lf7AzKCD0NXfgVoGCCQDNpZET8Jgq74oBgqKld3hafLbfzt/3inUdQvaFeXQ=="
}, },
"@types/warning": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/warning/-/warning-3.0.3.tgz",
"integrity": "sha512-D1XC7WK8K+zZEveUPY+cf4+kgauk8N4eHr/XIHXGlGYkHLud6hK9lYfZk1ry1TNh798cZUCgb6MqGEG8DkJt6Q==",
"dev": true
},
"@types/webidl-conversions": { "@types/webidl-conversions": {
"version": "7.0.0", "version": "7.0.0",
"resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz", "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
@ -62072,6 +62447,16 @@
"integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==",
"dev": true "dev": true
}, },
"adjust-sourcemap-loader": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz",
"integrity": "sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==",
"dev": true,
"requires": {
"loader-utils": "^2.0.0",
"regex-parser": "^2.2.11"
}
},
"agent-base": { "agent-base": {
"version": "6.0.2", "version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
@ -63355,6 +63740,13 @@
"integrity": "sha512-yN5oZVmRCwe5aKwzRj6736nSmKDX7pLYwsXiCj/EYmo16hODaBiT4En5btW/jhBF/seV+XMx3aYwukYC3A49DA==", "integrity": "sha512-yN5oZVmRCwe5aKwzRj6736nSmKDX7pLYwsXiCj/EYmo16hODaBiT4En5btW/jhBF/seV+XMx3aYwukYC3A49DA==",
"dev": true "dev": true
}, },
"bootstrap-5": {
"version": "npm:bootstrap@5.3.2",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.3.2.tgz",
"integrity": "sha512-D32nmNWiQHo94BKHLmOrdjlL05q1c8oxbtBphQFb9Z5to6eGRDCm0QgeaZ4zFBHzfg2++rqa2JkqCcxDy0sH0g==",
"dev": true,
"requires": {}
},
"bowser": { "bowser": {
"version": "2.11.0", "version": "2.11.0",
"resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz",
@ -64109,9 +64501,9 @@
"integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==" "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ=="
}, },
"classnames": { "classnames": {
"version": "2.3.1", "version": "2.5.1",
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz", "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz",
"integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==" "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow=="
}, },
"clean-css": { "clean-css": {
"version": "5.3.0", "version": "5.3.0",
@ -70211,6 +70603,12 @@
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"immutable": {
"version": "4.3.5",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.5.tgz",
"integrity": "sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw==",
"dev": true
},
"import-fresh": { "import-fresh": {
"version": "3.3.0", "version": "3.3.0",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
@ -77759,6 +78157,59 @@
"warning": "^3.0.0" "warning": "^3.0.0"
} }
}, },
"react-bootstrap-5": {
"version": "npm:react-bootstrap@2.10.1",
"resolved": "https://registry.npmjs.org/react-bootstrap/-/react-bootstrap-2.10.1.tgz",
"integrity": "sha512-J3OpRZIvCTQK+Tg/jOkRUvpYLHMdGeU9KqFUBQrV0d/Qr/3nsINpiOJyZMWnM5SJ3ctZdhPA6eCIKpEJR3Ellg==",
"dev": true,
"requires": {
"@babel/runtime": "^7.22.5",
"@restart/hooks": "^0.4.9",
"@restart/ui": "^1.6.6",
"@types/react-transition-group": "^4.4.6",
"classnames": "^2.3.2",
"dom-helpers": "^5.2.1",
"invariant": "^2.2.4",
"prop-types": "^15.8.1",
"prop-types-extra": "^1.1.0",
"react-transition-group": "^4.4.5",
"uncontrollable": "^7.2.1",
"warning": "^4.0.3"
},
"dependencies": {
"dom-helpers": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
"integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
"dev": true,
"requires": {
"@babel/runtime": "^7.8.7",
"csstype": "^3.0.2"
}
},
"react-transition-group": {
"version": "4.4.5",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
"integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
"dev": true,
"requires": {
"@babel/runtime": "^7.5.5",
"dom-helpers": "^5.0.1",
"loose-envify": "^1.4.0",
"prop-types": "^15.6.2"
}
},
"warning": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
"integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
"dev": true,
"requires": {
"loose-envify": "^1.0.0"
}
}
}
},
"react-chartjs-2": { "react-chartjs-2": {
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-5.0.1.tgz", "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-5.0.1.tgz",
@ -78433,6 +78884,12 @@
"@babel/runtime": "^7.8.4" "@babel/runtime": "^7.8.4"
} }
}, },
"regex-parser": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.3.0.tgz",
"integrity": "sha512-TVILVSz2jY5D47F4mA4MppkBrafEaiUWJO/TcZHEIuI13AqoZMkK1WMA4Om1YkYbTx+9Ki1/tSUXbceyr9saRg==",
"dev": true
},
"regexp.prototype.flags": { "regexp.prototype.flags": {
"version": "1.5.1", "version": "1.5.1",
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz",
@ -78692,6 +79149,19 @@
"value-or-function": "^4.0.0" "value-or-function": "^4.0.0"
} }
}, },
"resolve-url-loader": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-5.0.0.tgz",
"integrity": "sha512-uZtduh8/8srhBoMx//5bwqjQ+rfYOUq8zC9NrMUGtjBiGTtFJM42s58/36+hTqeqINcnYe08Nj3LkK9lW4N8Xg==",
"dev": true,
"requires": {
"adjust-sourcemap-loader": "^4.0.0",
"convert-source-map": "^1.7.0",
"loader-utils": "^2.0.0",
"postcss": "^8.2.14",
"source-map": "0.6.1"
}
},
"restore-cursor": { "restore-cursor": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
@ -78943,6 +79413,26 @@
} }
} }
}, },
"sass": {
"version": "1.70.0",
"resolved": "https://registry.npmjs.org/sass/-/sass-1.70.0.tgz",
"integrity": "sha512-uUxNQ3zAHeAx5nRFskBnrWzDUJrrvpCPD5FNAoRvTi0WwremlheES3tg+56PaVtCs5QDRX5CBLxxKMDJMEa1WQ==",
"dev": true,
"requires": {
"chokidar": ">=3.0.0 <4.0.0",
"immutable": "^4.0.0",
"source-map-js": ">=0.6.2 <2.0.0"
}
},
"sass-loader": {
"version": "13.3.3",
"resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.3.3.tgz",
"integrity": "sha512-mt5YN2F1MOZr3d/wBRcZxeFgwgkH44wVc2zohO2YF6JiOMkiXe4BYRZpSu2sO1g71mo/j16txzUhsKZlqjVGzA==",
"dev": true,
"requires": {
"neo-async": "^2.6.2"
}
},
"sax": { "sax": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz",

View file

@ -18,6 +18,9 @@
"eslint-plugin-prettier": "^4.0.0", "eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-promise": "^6.0.0", "eslint-plugin-promise": "^6.0.0",
"prettier": "2.5.1", "prettier": "2.5.1",
"resolve-url-loader": "^5.0.0",
"sass": "^1.69.5",
"sass-loader": "^13.3.2",
"typescript": "^5.0.4" "typescript": "^5.0.4"
}, },
"scripts": { "scripts": {

View file

@ -55,6 +55,8 @@ const preview: Preview = {
// render stories in iframes, to isolate modals // render stories in iframes, to isolate modals
inlineStories: false, inlineStories: false,
}, },
// Default to Bootstrap 3 styles
bootstrap5: false,
}, },
globalTypes: { globalTypes: {
theme: { theme: {
@ -78,15 +80,23 @@ const preview: Preview = {
return { return {
// NOTE: this uses `${theme}style.less` rather than `${theme}.less` // NOTE: this uses `${theme}style.less` rather than `${theme}.less`
// so that webpack only bundles files ending with "style.less" // so that webpack only bundles files ending with "style.less"
activeStyle: await import( bootstrap3Style: await import(
`!!to-string-loader!css-loader!less-loader!../../../services/web/frontend/stylesheets/${theme}style.less` `!!to-string-loader!css-loader!less-loader!../../../services/web/frontend/stylesheets/${theme}style.less`
), ),
// NOTE: this uses `${theme}style.scss` rather than `${theme}.scss`
// so that webpack only bundles files ending with "style.scss"
bootstrap5Style: await import(
`!!to-string-loader!css-loader!resolve-url-loader!sass-loader!../../../services/web/frontend/stylesheets/bootstrap-5/${theme}style.scss`
),
} }
}, },
], ],
decorators: [ decorators: [
(Story, context) => { (Story, context) => {
const { activeStyle } = context.loaded const { bootstrap3Style, bootstrap5Style } = context.loaded
const activeStyle = context.parameters.bootstrap5
? bootstrap5Style
: bootstrap3Style
return ( return (
<> <>

View file

@ -213,7 +213,13 @@ module.exports = function (webRouter, privateApiRouter, publicApiRouter) {
} }
res.locals.buildCssPath = function (themeModifier = '') { res.locals.buildCssPath = function (themeModifier = '') {
return res.locals.buildStylesheetPath(`main-${themeModifier}style.css`) // Pick which main stylesheet to use based on Bootstrap version
const bootstrap5Modifier =
res.locals.bootstrapVersion === 5 ? '-bootstrap-5' : ''
return res.locals.buildStylesheetPath(
`main-${themeModifier}style${bootstrap5Modifier}.css`
)
} }
res.locals.buildImgPath = function (imgFile) { res.locals.buildImgPath = function (imgFile) {
@ -362,6 +368,13 @@ module.exports = function (webRouter, privateApiRouter, publicApiRouter) {
next() next()
}) })
webRouter.use(function (req, res, next) {
// Set the Bootstrap version to 3 in all cases for now. This will come from
// a split test/feature flag in future.
res.locals.bootstrapVersion = 3
next()
})
webRouter.use(function (req, res, next) { webRouter.use(function (req, res, next) {
res.locals.ExposedSettings = { res.locals.ExposedSettings = {
isOverleaf: Settings.overleaf != null, isOverleaf: Settings.overleaf != null,

View file

@ -61,6 +61,7 @@ html(
meta(name="ol-isManagedAccount" data-type="boolean" content=isManagedAccount) meta(name="ol-isManagedAccount" data-type="boolean" content=isManagedAccount)
each restriction in userRestrictions || [] each restriction in userRestrictions || []
meta(name='ol-cannot-' + restriction data-type="boolean" content=true) meta(name='ol-cannot-' + restriction data-type="boolean" content=true)
meta(name="ol-bootstrapVersion" data-type="json" content=bootstrapVersion)
block head-scripts block head-scripts

View file

@ -0,0 +1,32 @@
import { Button as BootstrapButton } from 'react-bootstrap-5'
import type { ButtonProps } from '@/features/ui/components/types/button-props'
const sizeClasses = new Map<ButtonProps['size'], string>([
['small', 'btn-sm'],
['default', ''],
['large', 'btn-lg'],
])
// TODO: Display a spinner when `loading` is true
function Button({
variant = 'primary',
size = 'default',
disabled = false,
loading = false,
children,
}: ButtonProps) {
const sizeClass = sizeClasses.get(size)
return (
<BootstrapButton
variant={variant}
className={sizeClass}
disabled={disabled}
{...(loading ? { 'data-ol-loading': true } : null)}
>
{children}
</BootstrapButton>
)
}
export default Button

View file

@ -0,0 +1,15 @@
import type { ReactNode } from 'react'
export type ButtonProps = {
variant?:
| 'primary'
| 'secondary'
| 'ghost'
| 'danger'
| 'danger-ghost'
| 'premium'
size?: 'small' | 'default' | 'large'
disabled?: boolean
loading?: boolean
children: ReactNode
}

View file

@ -0,0 +1,21 @@
import Button from '@/features/ui/components/bootstrap-5/button'
import type { Meta } from '@storybook/react'
type Args = React.ComponentProps<typeof Button>
export const NewButton = (args: Args) => {
return <Button {...args} />
}
const meta: Meta<typeof Button> = {
title: 'Shared / Components / Bootstrap 5 / Button',
component: Button,
args: {
children: 'A Bootstrap 5 button',
},
parameters: {
bootstrap5: true,
},
}
export default meta

View file

@ -0,0 +1 @@
/* IEEE CSS variable overrides go in here */

View file

@ -0,0 +1 @@
/* Light theme CSS variable overrides go in here */

View file

@ -0,0 +1,12 @@
// This file provides both Sass and CSS variables for border radiuses
$border-radius-base: 4px;
$border-radius-medium: 8px;
$border-radius-large: 16px;
$border-radius-full: 9999px;
:root {
--border-radius-base: #{$border-radius-base};
--border-radius-medium: #{$border-radius-medium};
--border-radius-large: #{$border-radius-large};
--border-radius-full: #{$border-radius-full};
}

View file

@ -0,0 +1,500 @@
// This file provides CSS and Sass variables for colours as both RGB triples,
// which can be combined with an alpha value, and actual colour values.
// Note that colours used by Bootstrap's Sass are used in calculations and
// therefore cannot contain CSS variables
/* ====== RGB triples, for use with alpha values ====== */
/* Neutral */
$white-rgb: 255 255 255;
$neutral-10-rgb: 244 245 246;
$neutral-20-rgb: 231 233 238;
$neutral-30-rgb: 208 213 221;
$neutral-40-rgb: 175 181 192;
$neutral-50-rgb: 141 150 165;
$neutral-60-rgb: 103 114 131;
$neutral-70-rgb: 73 83 101;
$neutral-80-rgb: 47 58 76;
$neutral-90-rgb: 27 34 44;
/* Green */
$green-10-rgb: 235 246 234;
$green-20-rgb: 187 219 184;
$green-30-rgb: 140 202 134;
$green-40-rgb: 91 181 83;
$green-50-rgb: 19 138 7;
$green-60-rgb: 36 107 30;
$green-70-rgb: 31 89 25;
/* Blue */
$blue-10-rgb: 241 244 249;
$blue-20-rgb: 195 208 227;
$blue-30-rgb: 151 182 229;
$blue-40-rgb: 101 151 224;
$blue-50-rgb: 50 101 178;
$blue-60-rgb: 40 81 143;
$blue-70-rgb: 33 68 117;
/* Red */
$red-10-rgb: 249 241 241;
$red-20-rgb: 245 190 186;
$red-30-rgb: 229 157 154;
$red-40-rgb: 227 109 102;
$red-50-rgb: 184 58 51;
$red-60-rgb: 148 47 42;
$red-70-rgb: 120 39 34;
/* Yellow */
$yellow-10-rgb: 252 241 227;
$yellow-20-rgb: 252 196 131;
$yellow-30-rgb: 247 164 69;
$yellow-40-rgb: 222 128 20;
$yellow-50-rgb: 143 85 20;
$yellow-60-rgb: 122 67 4;
$yellow-70-rgb: 99 58 11;
/* ====== Full RGB colour values ====== */
/* Neutral */
$white: rgb($white-rgb);
$neutral-10: rgb($neutral-10-rgb);
$neutral-20: rgb($neutral-20-rgb);
$neutral-30: rgb($neutral-30-rgb);
$neutral-40: rgb($neutral-40-rgb);
$neutral-50: rgb($neutral-50-rgb);
$neutral-60: rgb($neutral-60-rgb);
$neutral-70: rgb($neutral-70-rgb);
$neutral-80: rgb($neutral-80-rgb);
$neutral-90: rgb($neutral-90-rgb);
/* Green */
$green-10: rgb($green-10-rgb);
$green-20: rgb($green-20-rgb);
$green-30: rgb($green-30-rgb);
$green-40: rgb($green-40-rgb);
$green-50: rgb($green-50-rgb);
$green-60: rgb($green-60-rgb);
$green-70: rgb($green-70-rgb);
/* Blue */
$blue-10: rgb($blue-10-rgb);
$blue-20: rgb($blue-20-rgb);
$blue-30: rgb($blue-30-rgb);
$blue-40: rgb($blue-40-rgb);
$blue-50: rgb($blue-50-rgb);
$blue-60: rgb($blue-60-rgb);
$blue-70: rgb($blue-70-rgb);
/* Red */
$red-10: rgb($red-10-rgb);
$red-20: rgb($red-20-rgb);
$red-30: rgb($red-30-rgb);
$red-40: rgb($red-40-rgb);
$red-50: rgb($red-50-rgb);
$red-60: rgb($red-60-rgb);
$red-70: rgb($red-70-rgb);
/* Yellow */
$yellow-10: rgb($yellow-10-rgb);
$yellow-20: rgb($yellow-20-rgb);
$yellow-30: rgb($yellow-30-rgb);
$yellow-40: rgb($yellow-40-rgb);
$yellow-50: rgb($yellow-50-rgb);
$yellow-60: rgb($yellow-60-rgb);
$yellow-70: rgb($yellow-70-rgb);
/* ====== RGB triples for semantic colour variables, for use with alpha values ====== */
$bg-light-primary-rgb: $white-rgb;
$bg-light-secondary-rgb: $neutral-10-rgb;
$bg-light-tertiary-rgb: $neutral-20-rgb;
$bg-light-disabled-rgb: $neutral-20-rgb;
$bg-dark-primary-rgb: $neutral-90-rgb;
$bg-dark-secondary-rgb: $neutral-80-rgb;
$bg-dark-tertiary-rgb: $neutral-70-rgb;
$bg-dark-disabled-rgb: $neutral-70-rgb;
$bg-accent-01-rgb: $green-50-rgb;
$bg-accent-02-rgb: $green-60-rgb;
$bg-accent-03-rgb: $green-10-rgb;
$bg-danger-01-rgb: $red-50-rgb;
$bg-danger-02-rgb: $red-60-rgb;
$bg-danger-03-rgb: $red-10-rgb;
$bg-warning-01-rgb: $yellow-50-rgb;
$bg-warning-02-rgb: $yellow-60-rgb;
$bg-warning-03-rgb: $yellow-10-rgb;
$bg-info-01-rgb: $blue-50-rgb;
$bg-info-02-rgb: $blue-60-rgb;
$bg-info-03-rgb: $blue-10-rgb;
$content-primary-rgb: $neutral-90-rgb;
$content-secondary-rgb: $neutral-70-rgb;
$content-disabled-rgb: $neutral-40-rgb;
$content-placeholder-rgb: $neutral-60-rgb;
$content-danger-rgb: $red-50-rgb;
$content-warning-rgb: $yellow-50-rgb;
$content-positive-rgb: $green-50-rgb;
$border-primary-rgb: $neutral-60-rgb;
$border-hover-rgb: $neutral-70-rgb;
$border-disabled-rgb: $neutral-20-rgb;
$border-active-rgb: $blue-50-rgb;
$border-danger-rgb: $red-50-rgb;
$border-divider-rgb: $neutral-20-rgb;
$link-web-rgb: $green-60-rgb;
$link-web-hover-rgb: $green-70-rgb;
$link-web-visited-rgb: $green-70-rgb;
$link-ui-rgb: $blue-50-rgb;
$link-ui-hover-rgb: $blue-60-rgb;
$link-ui-visited-rgb: $blue-60-rgb;
$content-primary-dark-rgb: $white-rgb;
$content-secondary-dark-rgb: $neutral-20-rgb;
$content-disabled-dark-rgb: $neutral-60-rgb;
$content-placeholder-dark-rgb: $neutral-50-rgb;
$content-danger-dark-rgb: $red-40-rgb;
$content-warning-dark-rgb: $yellow-40-rgb;
$content-positive-dark-rgb: $green-40-rgb;
$border-primary-dark-rgb: $neutral-30-rgb;
$border-hover-dark-rgb: $neutral-20-rgb;
$border-disabled-dark-rgb: $neutral-80-rgb;
$border-active-dark-rgb: $blue-30-rgb;
$border-danger-dark-rgb: $red-40-rgb;
$border-divider-dark-rgb: $neutral-80-rgb;
$link-web-dark-rgb: $green-30-rgb;
$link-web-hover-dark-rgb: $green-40-rgb;
$link-web-visited-dark-rgb: $green-40-rgb;
$link-ui-dark-rgb: $blue-30-rgb;
$link-ui-hover-dark-rgb: $blue-40-rgb;
$link-ui-visited-dark-rgb: $blue-40-rgb;
/* ====== Full RGB colour values for semantic colour variables ====== */
$bg-light-primary: rgb($bg-light-primary-rgb);
$bg-light-secondary: rgb($bg-light-secondary-rgb);
$bg-light-tertiary: rgb($bg-light-tertiary-rgb);
$bg-light-disabled: rgb($bg-light-disabled-rgb);
$bg-dark-primary: rgb($bg-dark-primary-rgb);
$bg-dark-secondary: rgb($bg-dark-secondary-rgb);
$bg-dark-tertiary: rgb($bg-dark-tertiary-rgb);
$bg-dark-disabled: rgb($bg-dark-disabled-rgb);
$bg-accent-01: rgb($bg-accent-01-rgb);
$bg-accent-02: rgb($bg-accent-02-rgb);
$bg-accent-03: rgb($bg-accent-03-rgb);
$bg-danger-01: rgb($bg-danger-01-rgb);
$bg-danger-02: rgb($bg-danger-02-rgb);
$bg-danger-03: rgb($bg-danger-03-rgb);
$bg-warning-01: rgb($bg-warning-01-rgb);
$bg-warning-02: rgb($bg-warning-02-rgb);
$bg-warning-03: rgb($bg-warning-03-rgb);
$bg-info-01: rgb($bg-info-01-rgb);
$bg-info-02: rgb($bg-info-02-rgb);
$bg-info-03: rgb($bg-info-03-rgb);
$content-primary: rgb($content-primary-rgb);
$content-secondary: rgb($content-secondary-rgb);
$content-disabled: rgb($content-disabled-rgb);
$content-placeholder: rgb($content-placeholder-rgb);
$content-danger: rgb($content-danger-rgb);
$content-warning: rgb($content-warning-rgb);
$content-positive: rgb($content-positive-rgb);
$border-primary: rgb($border-primary-rgb);
$border-hover: rgb($border-hover-rgb);
$border-disabled: rgb($border-disabled-rgb);
$border-active: rgb($border-active-rgb);
$border-danger: rgb($border-danger-rgb);
$border-divider: rgb($border-divider-rgb);
$link-web: rgb($link-web-rgb);
$link-web-hover: rgb($link-web-hover-rgb);
$link-web-visited: rgb($link-web-visited-rgb);
$link-ui: rgb($link-ui-rgb);
$link-ui-hover: rgb($link-ui-hover-rgb);
$link-ui-visited: rgb($link-ui-visited-rgb);
$content-primary-dark: rgb($content-primary-dark-rgb);
$content-secondary-dark: rgb($content-secondary-dark-rgb);
$content-disabled-dark: rgb($content-disabled-dark-rgb);
$content-placeholder-dark: rgb($content-placeholder-dark-rgb);
$content-danger-dark: rgb($content-danger-dark-rgb);
$content-warning-dark: rgb($content-warning-dark-rgb);
$content-positive-dark: rgb($content-positive-dark-rgb);
$border-primary-dark: rgb($border-primary-dark-rgb);
$border-hover-dark: rgb($border-hover-dark-rgb);
$border-disabled-dark: rgb($border-disabled-dark-rgb);
$border-active-dark: rgb($border-active-dark-rgb);
$border-danger-dark: rgb($border-danger-dark-rgb);
$border-divider-dark: rgb($border-divider-dark-rgb);
$link-web-dark: rgb($link-web-dark-rgb);
$link-web-hover-dark: rgb($link-web-hover-dark-rgb);
$link-web-visited-dark: rgb($link-web-visited-dark-rgb);
$link-ui-dark: rgb($link-ui-dark-rgb);
$link-ui-hover-dark: rgb($link-ui-hover-dark-rgb);
$link-ui-visited-dark: rgb($link-ui-visited-dark-rgb);
:root {
/* ====== RGB triples, for use with alpha values ====== */
/* Neutral */
--white-rgb: #{$white-rgb};
--neutral-10-rgb: #{$neutral-10-rgb};
--neutral-20-rgb: #{$neutral-20-rgb};
--neutral-30-rgb: #{$neutral-30-rgb};
--neutral-40-rgb: #{$neutral-40-rgb};
--neutral-50-rgb: #{$neutral-50-rgb};
--neutral-60-rgb: #{$neutral-60-rgb};
--neutral-70-rgb: #{$neutral-70-rgb};
--neutral-80-rgb: #{$neutral-80-rgb};
--neutral-90-rgb: #{$neutral-90-rgb};
/* Green */
--green-10-rgb: #{$green-10-rgb};
--green-20-rgb: #{$green-20-rgb};
--green-30-rgb: #{$green-30-rgb};
--green-40-rgb: #{$green-40-rgb};
--green-50-rgb: #{$green-50-rgb};
--green-60-rgb: #{$green-60-rgb};
--green-70-rgb: #{$green-70-rgb};
/* Blue */
--blue-10-rgb: #{$blue-10-rgb};
--blue-20-rgb: #{$blue-20-rgb};
--blue-30-rgb: #{$blue-30-rgb};
--blue-40-rgb: #{$blue-40-rgb};
--blue-50-rgb: #{$blue-50-rgb};
--blue-60-rgb: #{$blue-60-rgb};
--blue-70-rgb: #{$blue-70-rgb};
/* Red */
--red-10-rgb: #{$red-10-rgb};
--red-20-rgb: #{$red-20-rgb};
--red-30-rgb: #{$red-30-rgb};
--red-40-rgb: #{$red-40-rgb};
--red-50-rgb: #{$red-50-rgb};
--red-60-rgb: #{$red-60-rgb};
--red-70-rgb: #{$red-70-rgb};
/* Yellow */
--yellow-10-rgb: #{$yellow-10-rgb};
--yellow-20-rgb: #{$yellow-20-rgb};
--yellow-30-rgb: #{$yellow-30-rgb};
--yellow-40-rgb: #{$yellow-40-rgb};
--yellow-50-rgb: #{$yellow-50-rgb};
--yellow-60-rgb: #{$yellow-60-rgb};
--yellow-70-rgb: #{$yellow-70-rgb};
/* ====== Full RGB colour values ====== */
/* Neutral */
--white: rgb(var(--white-rgb));
--neutral-10: rgb(var(--neutral-10-rgb));
--neutral-20: rgb(var(--neutral-20-rgb));
--neutral-30: rgb(var(--neutral-30-rgb));
--neutral-40: rgb(var(--neutral-40-rgb));
--neutral-50: rgb(var(--neutral-50-rgb));
--neutral-60: rgb(var(--neutral-60-rgb));
--neutral-70: rgb(var(--neutral-70-rgb));
--neutral-80: rgb(var(--neutral-80-rgb));
--neutral-90: rgb(var(--neutral-90-rgb));
/* Green */
--green-10: rgb(var(--green-10-rgb));
--green-20: rgb(var(--green-20-rgb));
--green-30: rgb(var(--green-30-rgb));
--green-40: rgb(var(--green-40-rgb));
--green-50: rgb(var(--green-50-rgb));
--green-60: rgb(var(--green-60-rgb));
--green-70: rgb(var(--green-70-rgb));
/* Blue */
--blue-10: rgb(var(--blue-10-rgb));
--blue-20: rgb(var(--blue-20-rgb));
--blue-30: rgb(var(--blue-30-rgb));
--blue-40: rgb(var(--blue-40-rgb));
--blue-50: rgb(var(--blue-50-rgb));
--blue-60: rgb(var(--blue-60-rgb));
--blue-70: rgb(var(--blue-70-rgb));
/* Red */
--red-10: rgb(var(--red-10-rgb));
--red-20: rgb(var(--red-20-rgb));
--red-30: rgb(var(--red-30-rgb));
--red-40: rgb(var(--red-40-rgb));
--red-50: rgb(var(--red-50-rgb));
--red-60: rgb(var(--red-60-rgb));
--red-70: rgb(var(--red-70-rgb));
/* Yellow */
--yellow-10: rgb(var(--yellow-10-rgb));
--yellow-20: rgb(var(--yellow-20-rgb));
--yellow-30: rgb(var(--yellow-30-rgb));
--yellow-40: rgb(var(--yellow-40-rgb));
--yellow-50: rgb(var(--yellow-50-rgb));
--yellow-60: rgb(var(--yellow-60-rgb));
--yellow-70: rgb(var(--yellow-70-rgb));
/* ====== RGB triples for semantic colour variables, for use with alpha values ====== */
--bg-light-primary-rgb: var(--white-rgb);
--bg-light-secondary-rgb: var(--neutral-10-rgb);
--bg-light-tertiary-rgb: var(--neutral-20-rgb);
--bg-light-disabled-rgb: var(--neutral-20-rgb);
--bg-dark-primary-rgb: var(--neutral-90-rgb);
--bg-dark-secondary-rgb: var(--neutral-80-rgb);
--bg-dark-tertiary-rgb: var(--neutral-70-rgb);
--bg-dark-disabled-rgb: var(--neutral-70-rgb);
--bg-accent-01-rgb: var(--green-50-rgb);
--bg-accent-02-rgb: var(--green-60-rgb);
--bg-accent-03-rgb: var(--green-10-rgb);
--bg-danger-01-rgb: var(--red-50-rgb);
--bg-danger-02-rgb: var(--red-60-rgb);
--bg-danger-03-rgb: var(--red-10-rgb);
--bg-warning-01-rgb: var(--yellow-50-rgb);
--bg-warning-02-rgb: var(--yellow-60-rgb);
--bg-warning-03-rgb: var(--yellow-10-rgb);
--bg-info-01-rgb: var(--blue-50-rgb);
--bg-info-02-rgb: var(--blue-60-rgb);
--bg-info-03-rgb: var(--blue-10-rgb);
--content-primary-rgb: var(--neutral-90-rgb);
--content-secondary-rgb: var(--neutral-70-rgb);
--content-disabled-rgb: var(--neutral-40-rgb);
--content-placeholder-rgb: var(--neutral-60-rgb);
--content-danger-rgb: var(--red-50-rgb);
--content-warning-rgb: var(--yellow-50-rgb);
--content-positive-rgb: var(--green-50-rgb);
--border-primary-rgb: var(--neutral-60-rgb);
--border-hover-rgb: var(--neutral-70-rgb);
--border-disabled-rgb: var(--neutral-20-rgb);
--border-active-rgb: var(--blue-50-rgb);
--border-danger-rgb: var(--red-50-rgb);
--border-divider-rgb: var(--neutral-20-rgb);
--link-web-rgb: var(--green-60-rgb);
--link-web-hover-rgb: var(--green-70-rgb);
--link-web-visited-rgb: var(--green-70-rgb);
--link-ui-rgb: var(--blue-50-rgb);
--link-ui-hover-rgb: var(--blue-60-rgb);
--link-ui-visited-rgb: var(--blue-60-rgb);
--content-primary-dark-rgb: var(--white-rgb);
--content-secondary-dark-rgb: var(--neutral-20-rgb);
--content-disabled-dark-rgb: var(--neutral-60-rgb);
--content-placeholder-dark-rgb: var(--neutral-50-rgb);
--content-danger-dark-rgb: var(--red-40-rgb);
--content-warning-dark-rgb: var(--yellow-40-rgb);
--content-positive-dark-rgb: var(--green-40-rgb);
--border-primary-dark-rgb: var(--neutral-30-rgb);
--border-hover-dark-rgb: var(--neutral-20-rgb);
--border-disabled-dark-rgb: var(--neutral-80-rgb);
--border-active-dark-rgb: var(--blue-30-rgb);
--border-danger-dark-rgb: var(--red-40-rgb);
--border-divider-dark-rgb: var(--neutral-80-rgb);
--link-web-dark-rgb: var(--green-30-rgb);
--link-web-hover-dark-rgb: var(--green-40-rgb);
--link-web-visited-dark-rgb: var(--green-40-rgb);
--link-ui-dark-rgb: var(--blue-30-rgb);
--link-ui-hover-dark-rgb: var(--blue-40-rgb);
--link-ui-visited-dark-rgb: var(--blue-40-rgb);
/* ====== Full RGB colour values for semantic colour variables ====== */
--bg-light-primary: rgb(var(--bg-light-primary-rgb));
--bg-light-secondary: rgb(var(--bg-light-secondary-rgb));
--bg-light-tertiary: rgb(var(--bg-light-tertiary-rgb));
--bg-light-disabled: rgb(var(--bg-light-disabled-rgb));
--bg-dark-primary: rgb(var(--bg-dark-primary-rgb));
--bg-dark-secondary: rgb(var(--bg-dark-secondary-rgb));
--bg-dark-tertiary: rgb(var(--bg-dark-tertiary-rgb));
--bg-dark-disabled: rgb(var(--bg-dark-disabled-rgb));
--bg-accent-01: rgb(var(--bg-accent-01-rgb));
--bg-accent-02: rgb(var(--bg-accent-02-rgb));
--bg-accent-03: rgb(var(--bg-accent-03-rgb));
--bg-danger-01: rgb(var(--bg-danger-01-rgb));
--bg-danger-02: rgb(var(--bg-danger-02-rgb));
--bg-danger-03: rgb(var(--bg-danger-03-rgb));
--bg-warning-01: rgb(var(--bg-warning-01-rgb));
--bg-warning-02: rgb(var(--bg-warning-02-rgb));
--bg-warning-03: rgb(var(--bg-warning-03-rgb));
--bg-info-01: rgb(var(--bg-info-01-rgb));
--bg-info-02: rgb(var(--bg-info-02-rgb));
--bg-info-03: rgb(var(--bg-info-03-rgb));
--content-primary: rgb(var(--content-primary-rgb));
--content-secondary: rgb(var(--content-secondary-rgb));
--content-disabled: rgb(var(--content-disabled-rgb));
--content-placeholder: rgb(var(--content-placeholder-rgb));
--content-danger: rgb(var(--content-danger-rgb));
--content-warning: rgb(var(--content-warning-rgb));
--content-positive: rgb(var(--content-positive-rgb));
--border-primary: rgb(var(--border-primary-rgb));
--border-hover: rgb(var(--border-hover-rgb));
--border-disabled: rgb(var(--border-disabled-rgb));
--border-active: rgb(var(--border-active-rgb));
--border-danger: rgb(var(--border-danger-rgb));
--border-divider: rgb(var(--border-divider-rgb));
--link-web: rgb(var(--link-web-rgb));
--link-web-hover: rgb(var(--link-web-hover-rgb));
--link-web-visited: rgb(var(--link-web-visited-rgb));
--link-ui: rgb(var(--link-ui-rgb));
--link-ui-hover: rgb(var(--link-ui-hover-rgb));
--link-ui-visited: rgb(var(--link-ui-visited-rgb));
--content-primary-dark: rgb(var(--content-primary-dark-rgb));
--content-secondary-dark: rgb(var(--content-secondary-dark-rgb));
--content-disabled-dark: rgb(var(--content-disabled-dark-rgb));
--content-placeholder-dark: rgb(var(--content-placeholder-dark-rgb));
--content-danger-dark: rgb(var(--content-danger-dark-rgb));
--content-warning-dark: rgb(var(--content-warning-dark-rgb));
--content-positive-dark: rgb(var(--content-positive-dark-rgb));
--border-primary-dark: rgb(var(--border-primary-dark-rgb));
--border-hover-dark: rgb(var(--border-hover-dark-rgb));
--border-disabled-dark: rgb(var(--border-disabled-dark-rgb));
--border-active-dark: rgb(var(--border-active-dark-rgb));
--border-danger-dark: rgb(var(--border-danger-dark-rgb));
--border-divider-dark: rgb(var(--border-divider-dark-rgb));
--link-web-dark: rgb(var(--link-web-dark-rgb));
--link-web-hover-dark: rgb(var(--link-web-hover-dark-rgb));
--link-web-visited-dark: rgb(var(--link-web-visited-dark-rgb));
--link-ui-dark: rgb(var(--link-ui-dark-rgb));
--link-ui-hover-dark: rgb(var(--link-ui-hover-dark-rgb));
--link-ui-visited-dark: rgb(var(--link-ui-visited-dark-rgb));
// Gradients
--premium-gradient: linear-gradient(
246deg,
var(--blue-70) 0%,
#254c84 29%,
var(--blue-40) 97%
);
}

View file

@ -0,0 +1,38 @@
// This file provided both Sass and CSS variables for spacing
$spacing-00: 0;
$spacing-01: 2px;
$spacing-02: 4px;
$spacing-03: 6px;
$spacing-04: 8px;
$spacing-05: 12px;
$spacing-06: 16px;
$spacing-07: 20px;
$spacing-08: 24px;
$spacing-09: 32px;
$spacing-10: 40px;
$spacing-11: 48px;
$spacing-12: 56px;
$spacing-13: 64px;
$spacing-14: 72px;
$spacing-15: 80px;
$spacing-16: 96px;
:root {
--spacing-00: #{$spacing-00};
--spacing-01: #{$spacing-01};
--spacing-02: #{$spacing-02};
--spacing-03: #{$spacing-03};
--spacing-04: #{$spacing-04};
--spacing-05: #{$spacing-05};
--spacing-06: #{$spacing-06};
--spacing-07: #{$spacing-07};
--spacing-08: #{$spacing-08};
--spacing-09: #{$spacing-09};
--spacing-10: #{$spacing-10};
--spacing-11: #{$spacing-11};
--spacing-12: #{$spacing-12};
--spacing-13: #{$spacing-13};
--spacing-14: #{$spacing-14};
--spacing-15: #{$spacing-15};
--spacing-16: #{$spacing-16};
}

View file

@ -0,0 +1,104 @@
// This file provides CSS variables for font size and line height, plus Sass variables for base text size for Bootstrap
@use 'sass:math';
$default-font-size: 1rem;
$default-line-height: 1.5;
:root {
--font-size-01: 0.75rem; // 12px
--font-size-02: 0.875rem; // 14px
--font-size-03: 1rem; // 16px
--font-size-04: 1.125rem; // 18px
--font-size-05: 1.25rem; // 20px
--font-size-06: 1.5rem; // 24px
--font-size-07: 1.875rem; // 30px
--font-size-08: 2.25rem; // 36px
--font-size-09: 3rem; // 48px
--font-size-10: 3.25rem; // 52px
--font-size-11: 3.75rem; // 60px
--font-size-12: 4.5rem; // 72px
--font-size-13: 6em; // 96px
--line-height-01: 1rem; // 16px
--line-height-02: 1.25rem; // 20px
--line-height-03: 1.5rem; // 24px
--line-height-04: 1.75rem; // 28px
--line-height-05: 2rem; // 32px
--line-height-06: 2.5rem; // 40px
--line-height-07: 3rem; // 48px
--line-height-08: 4rem; // 64px
--line-height-09: 4.25rem; // 68px
--line-height-10: 5rem; // 80px
--line-height-11: 6rem; // 96px
--line-height-12: 8rem; // 128px
}
// Semantic styles, as Sass mixins
@mixin display-lg {
font-size: var(--font-size-13);
line-height: var(--line-height-12);
}
@mixin display-md {
font-size: var(--font-size-12);
line-height: var(--line-height-11);
}
@mixin display-sm {
font-size: var(--font-size-11);
line-height: var(--line-height-10);
}
@mixin display-xs {
font-size: var(--font-size-10);
line-height: var(--line-height-09);
}
@mixin heading-2xl {
font-size: var(--font-size-09);
line-height: var(--line-height-08);
}
@mixin heading-xl {
font-size: var(--font-size-08);
line-height: var(--line-height-07);
}
@mixin heading-lg {
font-size: var(--font-size-07);
line-height: var(--line-height-06);
}
@mixin heading-md {
font-size: var(--font-size-06);
line-height: var(--line-height-05);
}
@mixin heading-sm {
font-size: var(--font-size-05);
line-height: var(--line-height-04);
}
@mixin heading-xs {
font-size: var(--font-size-04);
line-height: var(--line-height-03);
}
@mixin body-lg {
font-size: var(--font-size-04);
line-height: var(--line-height-03);
}
@mixin body-base {
font-size: var(--font-size-03);
line-height: var(--line-height-03);
}
@mixin body-sm {
font-size: var(--font-size-02);
line-height: var(--line-height-02);
}
@mixin body-xs {
font-size: var(--font-size-01);
line-height: var(--line-height-01);
}

View file

@ -0,0 +1,7 @@
@import 'main-style';
// IEEE-specific theme overrides
@import 'css-variables/themes/ieee';
// IEEE-specific rules
$ieee-wedge: 30px;

View file

@ -0,0 +1,4 @@
@import 'main-style';
@import 'css-variables/themes/light';
$is-overleaf-light: true

View file

@ -0,0 +1,34 @@
// Web fonts
@import '../../fonts/lato.css';
@import '../../fonts/merriweather.css';
@import '../../fonts/source-code-pro.css';
@import '../../fonts/stix-two-math.css';
@import '../../fonts/noto-serif.css';
@import '../../fonts/material-symbols.css';
@import '../../fonts/font-awesome.css';
$is-overleaf-light: false;
// Vendor CSS
// TODO Bootstrap 5: Check whether this works with Bootstrap 5, and whether we can replace it
@import '../vendor/select/select.css';
// Sass and CSS variables from Overleaf foundations
@import 'foundations/colours';
@import 'foundations/spacing';
@import 'foundations/typography';
@import 'foundations/border-radius';
// Boostrap-related
// Note that files containing Bootstrap or Sass files that interact with
// Bootstrap's Sass variable must use @import rather than @use because
// Bootstrap relies on its variables, mixins etc. all being global.
// Include Bootstrap 5 itself, plus overrides of its Sass variable
@import 'scss/bootstrap';
// Override and extend Bootstrap styles. This can include overriding CSS
// variables in the usual CSS way, and can also refer to (but not override)
// Bootstrap Sass variables.
@import 'scss/bootstrap-rule-overrides';

View file

@ -0,0 +1,3 @@
// This file is included after Bootstrap and is used to override non-default
// Bootstrap variables and styles
@import 'bootstrap-rule-overrides/buttons';

View file

@ -0,0 +1,124 @@
@mixin ol-button-size($font-size, $line-height, $padding-y, $padding-x: var(--spacing-06)) {
--bs-btn-font-size: #{$font-size};
--bs-btn-line-height: #{$line-height};
--bs-btn-padding-y: #{$padding-y};
--bs-btn-padding-x: #{$padding-x};
}
@mixin ol-button-variant(
$color,
$background,
$border: $background,
$hover-background: $background,
$hover-border: $hover-background,
$borderless: true
) {
--bs-btn-color: #{$color};
--bs-btn-bg: #{$background};
--bs-btn-border-color: #{$border};
--bs-btn-hover-color: #{$color};
--bs-btn-hover-bg: #{$hover-background};
--bs-btn-hover-border-color: #{$hover-border};
--bs-btn-active-color: #{$color};
--bs-btn-active-bg: #{$hover-background};
--bs-btn-active-border-color: #{$hover-border};
--bs-btn-disabled-color: var(--content-disabled);
--bs-btn-disabled-bg: var(--bg-light-disabled);
--bs-btn-disabled-border-color: var(--bg-light-disabled);
@if $borderless {
--bs-btn-border-width: 0;
}
// Use the default state colors when in a loading state
&[data-ol-loading='true'] {
color: var(--bs-btn-color);
background-color: var(--bs-btn-bg);
border-color: var(--bs-btn-border-color);
}
}
.btn {
// Focus style for all buttons
--bs-btn-focus-box-shadow: 0 0 0 2px var(--border-active-dark);
// Sizes
// Default size
@include ol-button-size(
$font-size: var(--font-size-03),
$line-height: var(--line-height-03),
$padding-y: var(--spacing-03),
);
&.btn-lg {
@include ol-button-size(
$font-size: var(--font-size-03),
$line-height: var(--line-height-03),
$padding-y: var(--spacing-05),
);
}
&.btn-sm {
@include ol-button-size(
$font-size: var(--font-size-02),
$line-height: var(--line-height-02),
$padding-y: var(--spacing-01),
$padding-x: var(--spacing-05),
);
}
// Variants
&.btn-primary {
@include ol-button-variant(
$color: var(--content-primary-dark),
$background: var(--bg-accent-01),
$hover-background: var(--bg-accent-02),
$hover-border: var(--bg-accent-02),
);
}
&.btn-secondary {
@include ol-button-variant(
$color: var(--content-primary),
$background: var(--bg-light-primary),
$border: var(--border-primary),
$hover-background: var(--bg-light-tertiary),
$hover-border: var(--border-primary),
$borderless: false,
);
}
&.btn-ghost {
@include ol-button-variant(
$color: var(--content-primary),
$background: var(--bg-light-primary),
$hover-background: var(--bg-light-tertiary),
)
}
&.btn-danger {
@include ol-button-variant(
$color: var(--content-primary-dark),
$background: var(--bg-danger-01),
$border: var(--bg-danger-01),
$hover-background: var(--bg-danger-02),
)
}
&.btn-danger-ghost {
@include ol-button-variant(
$color: var(--content-danger),
$background: var(--bg-light-primary),
$hover-background: var(--bg-danger-03),
)
}
&.btn-premium {
@include ol-button-variant(
$color: var(--content-primary-dark),
$background: var(--blue-70),
);
background: var(--premium-gradient);
}
}

View file

@ -0,0 +1,8 @@
// This file is included before Bootstrap and is used to override Bootstrap
// default variables and styles
@import 'bootstrap-variable-overrides/fonts';
@import 'bootstrap-variable-overrides/buttons';
// This isn't great but is necessary to persuade Bootstrap to render white text
// on our green buttons
$min-contrast-ratio: 3;

View file

@ -0,0 +1,9 @@
// This file provides overrides for Bootstrap 5's default button-related Sass variables
$btn-font-family: $font-family-sans-serif;
$btn-font-weight: 700;
$btn-padding-x: $spacing-06;
$btn-padding-y: $spacing-02;
$btn-border-radius: $border-radius-full;
$btn-border-radius-lg: $border-radius-full;
$btn-border-radius-sm: $border-radius-full;

View file

@ -0,0 +1,11 @@
// This file provides overrides for Bootstrap 5's default font-related Sass variables
$font-family-sans-serif: 'Lato', sans-serif;
$font-family-serif: 'Merriweather', serif;
$font-family-monospace: 'Menlo', 'Monaco', 'Consolas', 'Courier New', monospace;
$font-size-base: $default-font-size;
$line-height-base: $default-line-height;
// Colours
$primary: $bg-accent-01;
$secondary: $bg-light-primary;

View file

@ -0,0 +1,30 @@
// Only include the parts of Bootstrap we need to minimize bundle size
// Include functions first (enabling manipulation of colors, SVGs, calc, etc. in the variable overrides)
@import 'bootstrap-5/scss/functions';
// Overrides for Bootstrap 5 Sass variables. These have to be included before
// Bootstrap itself because Bootstrap uses them to create the CSS variables it
// uses, and in calculations to determine, for example, what colour text to use
// on a button based on contrast.
@import 'bootstrap-variable-overrides';
// Include remainder of required Bootstrap stylesheets (including any separate color mode stylesheets)
@import 'bootstrap-5/scss/variables';
@import 'bootstrap-5/scss/variables-dark';
// Include remainder of required parts
@import 'bootstrap-5/scss/maps';
@import 'bootstrap-5/scss/mixins';
@import 'bootstrap-5/scss/root';
// Include any other optional parts as needed, including components
@import 'bootstrap-5/scss/utilities';
@import 'bootstrap-5/scss/reboot';
@import 'bootstrap-5/scss/type';
@import 'bootstrap-5/scss/images';
@import 'bootstrap-5/scss/containers';
@import 'bootstrap-5/scss/grid';
@import 'bootstrap-5/scss/helpers';
@import 'bootstrap-5/scss/buttons';
@import 'bootstrap-5/scss/modal';

View file

@ -227,7 +227,7 @@
"@testing-library/react": "^12.1.5", "@testing-library/react": "^12.1.5",
"@testing-library/react-hooks": "^8.0.1", "@testing-library/react-hooks": "^8.0.1",
"@testing-library/user-event": "^14.4.3", "@testing-library/user-event": "^14.4.3",
"@types/bootstrap": "^5.2.6", "@types/bootstrap": "^5.2.10",
"@types/chai": "^4.3.0", "@types/chai": "^4.3.0",
"@types/events": "^3.0.0", "@types/events": "^3.0.0",
"@types/express": "^4.17.13", "@types/express": "^4.17.13",
@ -263,6 +263,7 @@
"babel-plugin-module-resolver": "^5.0.0", "babel-plugin-module-resolver": "^5.0.0",
"backbone": "^1.3.3", "backbone": "^1.3.3",
"bootstrap": "^3.4.1", "bootstrap": "^3.4.1",
"bootstrap-5": "npm:bootstrap@^5.3.2",
"c8": "^7.2.0", "c8": "^7.2.0",
"chai": "^4.3.6", "chai": "^4.3.6",
"chai-as-promised": "^7.1.1", "chai-as-promised": "^7.1.1",
@ -320,6 +321,7 @@
"qrcode": "^1.4.4", "qrcode": "^1.4.4",
"react": "^17.0.2", "react": "^17.0.2",
"react-bootstrap": "^0.33.1", "react-bootstrap": "^0.33.1",
"react-bootstrap-5": "npm:react-bootstrap@^2.10.0",
"react-chartjs-2": "^5.0.1", "react-chartjs-2": "^5.0.1",
"react-color": "^2.19.3", "react-color": "^2.19.3",
"react-dnd": "^16.0.1", "react-dnd": "^16.0.1",

View file

@ -25,6 +25,12 @@ const entryPoints = {
'main-style': './frontend/stylesheets/main-style.less', 'main-style': './frontend/stylesheets/main-style.less',
'main-ieee-style': './frontend/stylesheets/main-ieee-style.less', 'main-ieee-style': './frontend/stylesheets/main-ieee-style.less',
'main-light-style': './frontend/stylesheets/main-light-style.less', 'main-light-style': './frontend/stylesheets/main-light-style.less',
'main-style-bootstrap-5':
'./frontend/stylesheets/bootstrap-5/main-style.scss',
'main-ieee-style-bootstrap-5':
'./frontend/stylesheets/bootstrap-5/main-ieee-style.scss',
'main-light-style-bootstrap-5':
'./frontend/stylesheets/bootstrap-5/main-light-style.scss',
} }
// Add entrypoints for each "page" // Add entrypoints for each "page"
@ -167,6 +173,46 @@ module.exports = {
{ loader: 'less-loader' }, { loader: 'less-loader' },
], ],
}, },
{
// Pass Sass files through sass-loader/css-loader/mini-css-extract-
// plugin (note: run in reverse order)
test: /\.s[ac]ss$/,
use: [
// Allows the CSS to be extracted to a separate .css file
{ loader: MiniCssExtractPlugin.loader },
// Resolves any CSS dependencies (e.g. url())
{ loader: 'css-loader' },
// Resolve relative paths sensibly in SASS
{ loader: 'resolve-url-loader' },
{
// Runs autoprefixer on CSS via postcss
loader: 'postcss-loader',
options: {
postcssOptions: {
plugins: ['autoprefixer'],
},
},
},
// Compile Sass off the main event loop
{
loader: 'thread-loader',
options: {
// keep workers alive for dev-server, and shut them down when not needed
poolTimeout:
process.env.NODE_ENV === 'development' ? 10 * 60 * 1000 : 500,
// bring up more workers after they timed out
poolRespawn: true,
// limit concurrency (one per entrypoint and let the small includes queue up)
workers: 6,
},
},
// Compiles Sass to CSS
{
loader: 'sass-loader',
options: { sourceMap: true }, // sourceMap: true is required for resolve-url-loader
},
],
},
{ {
// Pass CSS files through css-loader & mini-css-extract-plugin (note: run in reverse order) // Pass CSS files through css-loader & mini-css-extract-plugin (note: run in reverse order)
test: /\.css$/i, test: /\.css$/i,