--- /dev/null
+### react template
+.DS_*
+*.log
+logs
+**/*.backup.*
+**/*.back.*
+
+.zencoder/
+
+node_modules
+bower_components
+
+*.sublime*
+
+psd
+thumb
+sketch
+
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="MaterialThemeProjectNewConfig">
+ <option name="metadata">
+ <MTProjectMetadataState>
+ <option name="migrated" value="true" />
+ <option name="pristineConfig" value="false" />
+ <option name="userId" value="351393cd:182cd05972c:-8000" />
+ <option name="version" value="8.13.2" />
+ </MTProjectMetadataState>
+ </option>
+ <option name="titleBarState">
+ <MTProjectTitleBarConfigState>
+ <option name="overrideColor" value="false" />
+ </MTProjectTitleBarConfigState>
+ </option>
+ </component>
+</project>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ChangeListManager">
+ <list default="true" id="ab92709f-5288-4a55-873b-517f6adb96d1" name="Changes" comment="">
+ <change afterPath="$PROJECT_DIR$/.gitignore" afterDir="false" />
+ <change afterPath="$PROJECT_DIR$/.idea/material_theme_project_new.xml" afterDir="false" />
+ <change afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
+ <change afterPath="$PROJECT_DIR$/index.js" afterDir="false" />
+ <change afterPath="$PROJECT_DIR$/package.json" afterDir="false" />
+ </list>
+ <option name="SHOW_DIALOG" value="false" />
+ <option name="HIGHLIGHT_CONFLICTS" value="true" />
+ <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
+ <option name="LAST_RESOLUTION" value="IGNORE" />
+ </component>
+ <component name="Git.Settings">
+ <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
+ </component>
+ <component name="ProjectColorInfo"><![CDATA[{
+ "associatedIndex": 4
+}]]></component>
+ <component name="ProjectId" id="32Dry7FSPVcfWGtlGB2gLTw7dUl" />
+ <component name="ProjectViewState">
+ <option name="hideEmptyMiddlePackages" value="true" />
+ <option name="showLibraryContents" value="true" />
+ </component>
+ <component name="PropertiesComponent"><![CDATA[{
+ "keyToString": {
+ "ModuleVcsDetector.initialDetectionPerformed": "true",
+ "RunOnceActivity.ShowReadmeOnStart": "true",
+ "RunOnceActivity.git.unshallow": "true",
+ "RunOnceActivity.zencoder-patch-add-chat-message-raw-content": "true",
+ "RunOnceActivity.zencoder-patch-chat-storage-migration": "true",
+ "RunOnceActivity.zencoder-patch-generate-chat-message-id": "true",
+ "RunOnceActivity.zencoder-patch-migrate-custom-instruction": "true",
+ "RunOnceActivity.zencoder-patch-migrate-repo-info-to-rules": "true",
+ "git-widget-placeholder": "main",
+ "nodejs_interpreter_path": "/Users/charleswray/.nvm/versions/node/v20.12.1/bin/node",
+ "nodejs_package_manager_path": "npm",
+ "settings.editor.selected.configurable": "settings.nodejs",
+ "vue.rearranger.settings.migration": "true"
+ }
+}]]></component>
+ <component name="SharedIndexes">
+ <attachedChunks>
+ <set>
+ <option value="bundled-js-predefined-d6986cc7102b-09060db00ec0-JavaScript-WS-251.26927.40" />
+ </set>
+ </attachedChunks>
+ </component>
+ <component name="TaskManager">
+ <task active="true" id="Default" summary="Default task">
+ <changelist id="ab92709f-5288-4a55-873b-517f6adb96d1" name="Changes" comment="" />
+ <created>1756966236399</created>
+ <option name="number" value="Default" />
+ <option name="presentableId" value="Default" />
+ <updated>1756966236399</updated>
+ <workItem from="1756966239169" duration="57000" />
+ </task>
+ <servers />
+ </component>
+ <component name="TypeScriptGeneratedFilesManager">
+ <option name="version" value="3" />
+ </component>
+ <component name="ai.zencoder.plugin.mcp">
+ <option name="internalToolsState" value="{"file_search":true,"list_resources":true,"fulltext_search":true,"read_resource":true}" />
+ </component>
+</project>
\ No newline at end of file
--- /dev/null
+FROM node:20.12.1
+WORKDIR /usr/src/app
+RUN groupmod -g 1001 node && usermod -u 1001 -g 1001 node
+RUN apt-get update && apt-get -y install vim
+
+# Install `serve` to run the application.
+RUN npm install -g serve tailwindcss
--- /dev/null
+const aliases = (prefix = `src`) => ({
+ '@fuse': `${prefix}/@fuse`,
+ '@history': `${prefix}/@history`,
+ '@lodash': `${prefix}/@lodash`,
+ '@mock-api': `${prefix}/@mock-api`,
+ 'app/store': `${prefix}/app/store`,
+ 'app/shared-components': `${prefix}/app/shared-components`,
+ 'app/services': `${prefix}/app/services`,
+ 'app/configs': `${prefix}/app/configs`,
+ 'app/auth/authRoles': `${prefix}/app/auth/authRoles`,
+ 'app/theme-layouts': `${prefix}/app/theme-layouts`,
+ 'app/AppContext': `${prefix}/app/AppContext`
+});
+
+module.exports = aliases;
--- /dev/null
+const path = require(`path`);
+const alias = require(`./aliases`);
+const { aliasWebpack } = require('react-app-alias');
+
+const SRC = `./src`;
+const aliases = alias(SRC);
+
+const resolvedAliases = Object.fromEntries(
+ Object.entries(aliases).map(([key, value]) => [key, path.resolve(__dirname, value)])
+);
+
+const options = {
+ alias: resolvedAliases,
+};
+
+module.exports = function override(config) {
+ config.ignoreWarnings = [{ message: /Failed to parse source map/ }];
+
+ return aliasWebpack(options)(config);
+};
--- /dev/null
+{
+ "compilerOptions": {
+ "baseUrl": "./",
+ "paths": {
+ "@fuse/*": ["./src/@fuse/*"],
+ "@history*": ["./src/@history"],
+ "@lodash": ["./src/@lodash"],
+ "@mock-api": ["./src/@mock-api"],
+ "app/store/*": ["./src/app/store/*"],
+ "app/shared-components/*": ["./src/app/shared-components/*"],
+ "app/configs/*": ["./src/app/configs/*"],
+ "app/theme-layouts/*": ["./src/app/theme-layouts/*"],
+ "app/AppContext": ["./src/app/AppContext"]
+ }
+ }
+}
--- /dev/null
+{
+ "name": "phs-home",
+ "version": "1.0.0",
+ "description": "",
+ "main": "src/App.js",
+ "private": true,
+ "dependencies": {
+ "@emotion/react": "^11.14.0",
+ "@emotion/styled": "^11.14.1",
+ "@hookform/resolvers": "^5.2.1",
+ "@mui/icons-material": "^7.3.1",
+ "@mui/material": "^7.3.1",
+ "@mui/x-date-pickers": "^8.10.2",
+ "@testing-library/dom": "^10.4.1",
+ "@testing-library/jest-dom": "^6.8.0",
+ "@testing-library/react": "^16.3.0",
+ "@testing-library/user-event": "^13.5.0",
+ "axios": "^1.11.0",
+ "framer-motion": "^12.23.12",
+ "lodash": "^4.17.21",
+ "material-react-table": "^3.2.1",
+ "notistack": "^3.0.2",
+ "react": "^19.1.1",
+ "react-dom": "^19.1.1",
+ "react-hook-form": "^7.62.0",
+ "react-router-dom": "^7.8.2",
+ "react-scripts": "5.0.1",
+ "uuid": "^11.1.0",
+ "web-vitals": "^2.1.4",
+ "yup": "^1.7.0"
+ },
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "eslintConfig": {
+ "extends": [
+ "react-app",
+ "react-app/jest"
+ ]
+ },
+ "browserslist": {
+ "production": [
+ ">0.2%",
+ "not dead",
+ "not op_mini all"
+ ],
+ "development": [
+ "last 1 chrome version",
+ "last 1 firefox version",
+ "last 1 safari version"
+ ]
+ },
+ "devDependencies": {
+ "@tailwindcss/aspect-ratio": "^0.4.2",
+ "@tailwindcss/typography": "^0.5.16",
+ "autoprefixer": "^10.4.20",
+ "postcss": "^8.4.47",
+ "tailwindcss": "^3.4.13"
+ }
+}
--- /dev/null
+module.exports = {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+}
--- /dev/null
+#!/bin/bash
+if [ -z "$1" ]
+then
+ echo "No env supplied to build script."
+# exit
+fi
+
+env="$1"
+
+fixurl() {
+ ls -l "/tmp/test/my dir"
+}
+
+new_api_url="http://localhost:23601/"
+new_it_url="http://localhost:23601/it/"
+echo "Pre-building for env: $env"
+
+if [ $env = "test" ]; then
+ new_api_url="https://api-t.phasecustomsoft.com/"
+ new_it_url="https://api-t.phasecustomsoft.com/it/"
+fi
+if [ $env = 'live' ]; then
+ new_api_url="https://clr-api.phasecustomsoft.com/"
+ new_it_url="https://clr-api.phasecustomsoft.com/it/"
+fi
+
+echo "New API Url: $new_api_url"
+echo "New IT Url: $new_it_url"
+
+echo "Replacing base URLs in src/globals.js"
+echo "export const base_url = '$new_api_url';" > src/globals.js
+echo "export const it_url = '$new_it_url';" >> src/globals.js
+
+echo "Updated lines in src/globals.js"
+cat src/globals.js | grep base_url
+cat src/globals.js | grep it_url
--- /dev/null
+#!/bin/bash
+
+env=""
+if [[ ! -z "${PHS_ENV}" ]]; then
+ env=${PHS_ENV}
+fi
+
+if [ "$env" == "TEST" ]; then
+ echo "PHS API Test Stack"
+ npm install --force && /usr/src/app/pre-build.sh test && npm run build && serve -s build
+ #npm install --force && /usr/src/app/pre-build.sh test && npm run start
+elif [ "$env" == "PRODUCTION" ]; then
+ echo "PHS API Production Stack"
+ npm install --force && /usr/src/app/pre-build.sh live && npm run build && serve -s build
+ #npm install --force && /usr/src/app/pre-build.sh live && npm run start
+else
+ echo "PHS API Dev Stack"
+ npm install --force && npm start
+fi
--- /dev/null
+const plugin = require('tailwindcss/plugin');
+
+const iconSize = plugin(
+ ({ addUtilities, theme, e, variants }) => {
+ const values = theme('iconSize');
+
+ addUtilities(
+ Object.entries(values).map(([key, value]) => ({
+ [`.${e(`icon-size-${key}`)}`]: {
+ width: value,
+ height: value,
+ minWidth: value,
+ minHeight: value,
+ fontSize: value,
+ lineHeight: value,
+ [`svg`]: {
+ width: value,
+ height: value,
+ },
+ },
+ })),
+ variants('iconSize')
+ );
+ },
+ {
+ theme: {
+ iconSize: (theme) => ({
+ ...theme('spacing'),
+ }),
+ },
+ variants: {
+ iconSize: ['responsive'],
+ },
+ }
+);
+
+module.exports = iconSize;
--- /dev/null
+import __ from 'lodash';
+
+/**
+ * You can extend Lodash with mixins
+ * And use it as below
+ * import _ from '@lodash'
+ */
+const _ = __.runInContext();
+
+_.mixin({
+ // Immutable Set for setting state
+ setIn: (state, name, value) => {
+ return _.setWith(_.clone(state), name, value, _.clone);
+ },
+});
+
+export default _;
--- /dev/null
+export { default } from './@lodash';
--- /dev/null
+import './styles/App.css';
+import AppRoutes from './app/routes';
+
+function App() {
+ return (
+ <div className="App">
+ <header className="app-header">
+ </header>
+ { AppRoutes() }
+ </div>
+ );
+}
+
+export default App;
--- /dev/null
+import { render, screen } from '@testing-library/react';
+import App from './App';
+
+test('renders learn react link', () => {
+ render(<App />);
+ const linkElement = screen.getByText(/learn react/i);
+ expect(linkElement).toBeInTheDocument();
+});
--- /dev/null
+import { Route, Routes } from 'react-router-dom';
+import Login from './views/Login';
+import NotFound from './views/404/Error404Page';
+import Dashboard from './views/Dashboard/Dashboard';
+import Git from './views/Git';
+
+export default function AppRoutes() {
+ return (
+ <Routes>
+ <Route path="/" element={<Dashboard />} />
+ <Route path="/login" element={<Login />} />
+ <Route path="/git" element={<Git />} />
+ <Route path="*" element={<NotFound />} />
+ </Routes>
+ );
+};
--- /dev/null
+export const getFormattedDate = (date) => {
+ return new Date(date).toLocaleString('en-US', {
+ year: 'numeric',
+ month: '2-digit',
+ day: '2-digit',
+ hour: '2-digit',
+ minute:'2-digit'
+ });
+};
\ No newline at end of file
--- /dev/null
+import Typography from '@mui/material/Typography';
+import { motion } from 'framer-motion';
+import { Link } from 'react-router-dom';
+import Box from '@mui/material/Box';
+
+function Error404Page() {
+ return (
+ <div className="flex flex-col flex-1 items-center justify-center p-16">
+ <div className="w-full max-w-3xl text-center">
+ <motion.div
+ initial={{ opacity: 0, scale: 0.6 }}
+ animate={{ opacity: 1, scale: 1, transition: { delay: 0.1 } }}
+ >
+ <Box
+ component="svg"
+ width="100%"
+ height="100%"
+ viewBox="0 0 1075 585"
+ fill="none"
+ preserveAspectRatio="xMidYMax slice"
+ xmlns="http://www.w3.org/2000/svg"
+ sx={{ color: 'secondary.main' }}
+ >
+ <g clipPath="url(#clip0)">
+ <path
+ d="M520.426 167.01C434.482 167.01 372.775 222.149 372.775 350.808C372.775 496.621 434.482 535.218 520.426 535.218C606.37 535.218 671.753 492.945 671.753 350.808C671.753 198.868 606.37 167.01 520.426 167.01ZM520.991 486.818C461.464 486.818 430.365 451.895 430.365 350.902C430.365 261.79 462.737 214.797 522.264 214.797C581.791 214.797 614.163 245.665 614.163 350.902C614.163 449.349 580.517 486.818 520.991 486.818Z"
+ className="text-gray-800 dark:text-gray-600"
+ fill="currentColor"
+ />
+ <path
+ d="M321.311 433.517H285.777V328.877C285.777 323.32 283.569 317.989 279.639 314.059C275.709 310.129 270.379 307.922 264.821 307.922H256.495C253.743 307.922 251.018 308.464 248.475 309.517C245.933 310.57 243.623 312.113 241.677 314.059C239.731 316.005 238.187 318.315 237.134 320.858C236.081 323.4 235.539 326.125 235.539 328.877V433.517H135.309C133.247 433.517 131.22 432.984 129.425 431.97C127.629 430.955 126.127 429.494 125.062 427.728C123.998 425.962 123.408 423.951 123.35 421.89C123.292 419.829 123.768 417.788 124.731 415.965L230.814 215.184C232.136 212.681 232.938 209.936 233.17 207.114C233.402 204.293 233.061 201.453 232.165 198.768C231.27 196.082 229.84 193.605 227.961 191.487C226.082 189.37 223.793 187.654 221.233 186.445L214.971 183.488C210.108 181.192 204.549 180.853 199.444 182.541C194.338 184.23 190.077 187.816 187.542 192.558L58.1602 434.591C55.957 438.712 54.8043 443.314 54.8043 447.987V447.987C54.8043 451.719 55.5393 455.414 56.9673 458.861C58.3954 462.309 60.4885 465.441 63.1271 468.08C65.7658 470.719 68.8983 472.812 72.3459 474.24C75.7935 475.668 79.4885 476.403 83.2202 476.403H235.539V542.57C235.539 545.869 236.189 549.135 237.451 552.183C238.713 555.23 240.564 557.999 242.896 560.332C245.229 562.664 247.998 564.515 251.045 565.777C254.093 567.039 257.359 567.689 260.658 567.689H260.658C263.957 567.689 267.223 567.039 270.271 565.777C273.318 564.515 276.087 562.664 278.42 560.332C280.752 557.999 282.603 555.23 283.865 552.183C285.127 549.135 285.777 545.869 285.777 542.57V476.403H321.311C326.998 476.403 332.452 474.144 336.474 470.122C340.495 466.101 342.754 460.647 342.754 454.96V454.96C342.754 449.273 340.495 443.819 336.474 439.797C332.453 435.776 326.998 433.517 321.311 433.517V433.517Z"
+ className="text-gray-800 dark:text-gray-600"
+ fill="currentColor"
+ />
+ <path
+ d="M979.308 433.517H943.774V328.877C943.774 323.32 941.566 317.989 937.636 314.059C933.706 310.129 928.376 307.922 922.818 307.922H914.491C911.739 307.922 909.014 308.464 906.472 309.517C903.929 310.57 901.619 312.113 899.673 314.059C897.727 316.005 896.184 318.315 895.131 320.858C894.077 323.4 893.535 326.125 893.535 328.877V433.517H793.305C791.243 433.517 789.216 432.984 787.421 431.97C785.626 430.955 784.123 429.494 783.059 427.728C781.995 425.962 781.405 423.951 781.347 421.89C781.289 419.829 781.764 417.788 782.728 415.965L888.81 215.184C890.133 212.681 890.934 209.936 891.167 207.114C891.399 204.293 891.057 201.453 890.162 198.768C889.266 196.082 887.836 193.605 885.957 191.487C884.078 189.37 881.79 187.654 879.23 186.445L872.967 183.488C868.105 181.192 862.546 180.853 857.44 182.541C852.334 184.23 848.073 187.816 845.538 192.558L716.157 434.591C713.953 438.712 712.801 443.314 712.801 447.987V447.987C712.801 455.523 715.795 462.751 721.124 468.08C726.453 473.409 733.68 476.403 741.217 476.403H893.535V542.57C893.535 549.232 896.182 555.621 900.893 560.332C905.603 565.043 911.992 567.689 918.654 567.689V567.689C925.316 567.689 931.706 565.043 936.416 560.332C941.127 555.621 943.773 549.232 943.773 542.57V476.403H979.308C984.995 476.403 990.449 474.144 994.47 470.122C998.492 466.101 1000.75 460.647 1000.75 454.96V454.96C1000.75 449.273 998.492 443.819 994.47 439.797C990.449 435.776 984.995 433.517 979.308 433.517Z"
+ className="text-gray-800 dark:text-gray-600"
+ fill="currentColor"
+ />
+ </g>
+ <defs>
+ <clipPath id="clip0">
+ <rect width="1074.39" height="584.231" fill="white" />
+ </clipPath>
+ </defs>
+ </Box>
+ </motion.div>
+
+ <motion.div
+ initial={{ opacity: 0, y: 40 }}
+ animate={{ opacity: 1, y: 0, transition: { delay: 0.2 } }}
+ >
+ <Typography
+ variant="h1"
+ className="mt-48 sm:mt-96 text-4xl md:text-7xl font-extrabold tracking-tight leading-tight md:leading-none text-center"
+ >
+ Ooops... 404!
+ </Typography>
+ </motion.div>
+
+ <motion.div
+ initial={{ opacity: 0, y: 40 }}
+ animate={{ opacity: 1, y: 0, transition: { delay: 0.2 } }}
+ >
+ <Typography
+ variant="h5"
+ color="text.secondary"
+ className="mt-8 text-lg md:text-xl font-medium tracking-tight text-center"
+ >
+ The page you requested could not be found.
+ </Typography>
+ </motion.div>
+
+ <Link className="block font-normal mt-48" to="/">
+ Back to Dashboard
+ </Link>
+ </div>
+ </div>
+ );
+}
+
+export default Error404Page;
--- /dev/null
+import React, { useState, useEffect } from 'react';
+import { useMaterialReactTable, MaterialReactTable } from 'material-react-table';
+import { Container, IconButton } from '@mui/material';
+import { VisibilityOutlined } from '@mui/icons-material';
+import { FormService } from '../../services';
+import { FormDetail } from '../../components';
+import { getFormattedDate } from '../../utils';
+
+const Dashboard = () => {
+ const [data, setData] = useState( [] );
+ const [selectedFormID, setSelectedFormID] = useState( null );
+ const [detailOpen, setDetailOpen] = useState( false );
+ const [selectedForm, setSelectedForm] = useState( null );
+
+
+ useEffect( () => {
+ FormService.get( null, null ).then( response => {
+ console.log('response', response);
+ setData(response);
+ });
+ }, [] );
+
+ useEffect( () => {
+ if (selectedFormID) {
+ FormService.get( null, selectedFormID ).then( response => {
+ setSelectedForm( response );
+ });
+ }
+ }, [selectedFormID] );
+
+ const table = useMaterialReactTable({
+ columns: [
+ {
+ header: 'Actions',
+ id: 'woActions',
+ enableSorting: false,
+ enableGlobalFilter: false,
+ enableColumnFilter: false,
+ enableGrouping: false,
+ enableEditing: false,
+ size: 150,
+ accessorFn: (row) => {
+ const showSelectedModal = () => {
+ setSelectedFormID(row.id)
+ setDetailOpen(true);
+ };
+
+ return(
+ <IconButton size='small'
+ color='primary'
+ onClick={ showSelectedModal }>
+ <VisibilityOutlined fontSize="inherit" />
+ </IconButton>
+ )
+ },
+ },
+ {
+ header: 'ID',
+ accessorKey: 'id', //access nested data with dot notation
+ },
+ {
+ header:'Unit#',
+ accessorKey: 'unit_number', //simple function
+ },
+ {
+ header: 'Employee Name',
+ accessorKey: 'employee_name'
+ },
+ {
+ header: 'Employee Number',
+ accessorKey: 'employee_number'
+ },
+ {
+ header: 'Email Address',
+ accessorKey: 'email_address'
+ },
+ {
+ header: 'Photos',
+ accessorKey: 'photo_count'
+ },
+ {
+ header: 'Date',
+ accessorKey: 'created_at',
+ accessorFn: (row) => {
+ return getFormattedDate(row.created_at);
+ }
+ }
+ ],
+ data
+ });
+ return <Container maxWidth='xl' >
+
+ <FormDetail isOpen={detailOpen} setOpen={setDetailOpen} inspection={selectedForm} setSelectedForm={setSelectedForm} setSelectedFormID={setSelectedFormID}/>
+ <MaterialReactTable table={table} />
+ </Container>;
+};
+
+export default Dashboard;
\ No newline at end of file
--- /dev/null
+import { useState } from 'react';
+import axios from 'axios';
+
+const Git = () => {
+ const [repoName, setRepoName] = useState('');
+ const [repoType, setRepoType] = useState('global');
+ const [user, setUser] = useState('');
+ const [message, setMessage] = useState('');
+
+ const handleSubmit = async (e) => {
+ e.preventDefault();
+ if (!repoName.match(/^[a-zA-Z0-9_-]+$/)) {
+ setMessage('Error: Repository name must contain only letters, numbers, hyphens, or underscores.');
+ return;
+ }
+ if (repoType === 'private' && !user) {
+ setMessage('Error: Username required for private repository.');
+ return;
+ }
+
+ try {
+ const response = await axios.post('http://localhost:3000/create-repo', {
+ name: repoName,
+ type: repoType,
+ user: repoType === 'private' ? user : undefined,
+ });
+ setMessage(response.data.message);
+ } catch (error) {
+ setMessage(`Error: ${error.response?.data?.error || 'Failed to create repository'}`);
+ }
+ };
+
+ return (
+ <div className="min-h-screen bg-gray-100 flex items-center justify-center">
+ <div className="bg-white p-8 rounded-lg shadow-lg w-full max-w-md">
+ <h1 className="text-2xl font-bold mb-6 text-center">Git Repository Manager</h1>
+ <form onSubmit={handleSubmit}>
+ <div className="mb-4">
+ <label className="block text-gray-700 mb-2" htmlFor="repoName">Repository Name</label>
+ <input
+ id="repoName"
+ type="text"
+ value={repoName}
+ onChange={(e) => setRepoName(e.target.value)}
+ className="w-full p-2 border rounded"
+ placeholder="e.g., my-project"
+ required
+ />
+ </div>
+ <div className="mb-4">
+ <label className="block text-gray-700 mb-2">Repository Type</label>
+ <select
+ value={repoType}
+ onChange={(e) => setRepoType(e.target.value)}
+ className="w-full p-2 border rounded"
+ >
+ <option value="global">Global (Group-Shared)</option>
+ <option value="private">Private (User-Specific)</option>
+ </select>
+ </div>
+ {repoType === 'private' && (
+ <div className="mb-4">
+ <label className="block text-gray-700 mb-2" htmlFor="user">Username</label>
+ <input
+ id="user"
+ type="text"
+ value={user}
+ onChange={(e) => setUser(e.target.value)}
+ className="w-full p-2 border rounded"
+ placeholder="e.g., gituser1"
+ required
+ />
+ </div>
+ )}
+ <button
+ type="submit"
+ className="w-full bg-blue-500 text-white p-2 rounded hover:bg-blue-600"
+ >
+ Create Repository
+ </button>
+ </form>
+ {message && (
+ <p className={`mt-4 text-center ${message.startsWith('Error') ? 'text-red-500' : 'text-green-500'}`}>
+ {message}
+ </p>
+ )}
+ </div>
+ </div>
+ );
+}
+
+export default Git;
\ No newline at end of file
--- /dev/null
+import { useState } from 'react';
+import { yupResolver } from '@hookform/resolvers/yup';
+import { Controller, useForm } from 'react-hook-form';
+import {
+ Button,
+ Checkbox,
+ FormControl,
+ FormControlLabel,
+ FormHelperText,
+ TextField,
+ Typography,
+ Box,
+ Paper,
+ InputAdornment, IconButton
+} from '@mui/material';
+import * as yup from 'yup';
+import _ from '../../@lodash';
+// import jwtService from '../../auth/services/jwtService';
+import { Visibility, VisibilityOff } from '@mui/icons-material';
+import { useNavigate } from 'react-router-dom';
+
+/**
+ * Form Validation Schema
+ */
+const schema = yup.object().shape( {
+ email:yup.string().email( 'You must enter a valid email' ).required( 'You must enter a email' ),
+ password:yup
+ .string()
+ .required( 'Please enter your password.' )
+ .min( 4, 'Password is too short - must be at least 4 chars.' ),
+} );
+
+const defaultValues = {
+ email:'',
+ password:'',
+ remember:true,
+};
+
+function SignInPage() {
+ const { control, formState, handleSubmit, setError } = useForm( {
+ mode:'onChange',
+ defaultValues,
+ resolver:yupResolver( schema ),
+ } );
+ const [showPassword, setShowPassword] = useState( false );
+ const [signInError, setSignInError] = useState(null);
+ const navigate = useNavigate();
+ const { isValid, dirtyFields, errors } = formState;
+
+ function onSubmit( { email, password } ) {
+ setSignInError(null);
+ /*jwtService
+ .signInWithEmailAndPassword( email, password )
+ .then( data => {
+ if(data.requires_2fa) {
+ navigate('/sign-in-verify', { state: { data: data } });
+ }
+ } )
+ .catch( (error) => {
+ const message = error?.response?.data?.message;
+ console.log(`Sign-in error: ${error}, sub error: ${message}`);
+ setSignInError(message);
+ } );*/
+ }
+
+ return (
+ <div
+ className="flex flex-col sm:flex-row items-center md:items-start sm:justify-center md:justify-start flex-1 min-w-0">
+ <Paper
+ className="h-full sm:h-auto md:flex md:items-center md:justify-end w-full sm:w-auto md:h-full md:w-1/2 py-8 px-16 sm:p-48 md:p-64 sm:rounded-2xl md:rounded-none sm:shadow md:shadow-none ltr:border-r-1 rtl:border-l-1">
+ <div className="w-full max-w-320 sm:w-320 mx-auto sm:mx-0">
+
+ <Typography fontSize={'2rem'} className="mt-32 text-4xl font-extrabold tracking-tight leading-tight">
+ Sign in
+ </Typography>
+
+ {signInError &&
+ <FormHelperText id="validation-helper-text" className="mt-24 mb-24 text-lg" error>
+ {signInError}
+ </FormHelperText>
+ }
+
+ <form
+ name="loginForm"
+ noValidate
+ className="flex flex-col justify-center w-full mt-32"
+ onSubmit={ handleSubmit( onSubmit ) }
+ >
+ <Controller
+ name="employee_number"
+ control={ control }
+ render={ ( { field } ) => (
+ <TextField
+ { ...field }
+ className="mb-24"
+ label="Employee Number"
+ autoFocus
+ type="text"
+ error={ !!errors.employee_number }
+ helperText={ errors?.employee_number?.message }
+ variant="outlined"
+ required
+ fullWidth
+ />
+ ) }
+ />
+
+ <Controller
+ name="password"
+ control={ control }
+ render={ ( { field } ) => (
+ <TextField
+ { ...field }
+ className="mb-6"
+ label="Password"
+ type={ showPassword ? 'text' : 'password' }
+ error={ !!errors.password }
+ inputProps={{
+ 'aria-describedby': errors.password ? 'password-helper-text' : undefined,
+ }}
+ InputProps={{
+ endAdornment:
+ <InputAdornment position='end' >
+ <IconButton aria-label='toggle password visibility' onClick={ () => setShowPassword( prevState => !prevState ) }>
+ { showPassword ? <VisibilityOff/> : <Visibility/> }
+ </IconButton>
+ </InputAdornment>
+ }}
+ variant="outlined"
+ required
+ fullWidth
+ />
+ ) }
+ />
+ {errors?.password && (
+ <FormHelperText id="password-helper-text" className="mb-24" error>
+ {errors.password.message}
+ </FormHelperText>
+ )}
+
+ <div className="flex flex-col sm:flex-row items-center justify-center sm:justify-between">
+ <Controller
+ name="remember"
+ control={ control }
+ render={ ( { field } ) => (
+ <FormControl>
+ <FormControlLabel
+ label="Remember me"
+ control={ <Checkbox size="small" { ...field } /> }
+ />
+ </FormControl>
+ ) }
+ />
+ </div>
+
+ <Button
+ variant="contained"
+ color="secondary"
+ className=" w-full mt-16"
+ aria-label="Sign in"
+ disabled={ _.isEmpty( dirtyFields ) || !isValid }
+ type="submit"
+ size="large"
+ >Sign in</Button>
+
+ <Button
+ variant="outlined"
+ color="primary"
+ className=" w-full mt-16"
+ aria-label="Forgot Password"
+ size="large"
+ onClick={() => {
+ navigate('/forgot-password');
+ }}
+ >Forgot Password</Button>
+
+ </form>
+ </div>
+ </Paper>
+
+ <Box
+ className="relative hidden md:flex flex-auto items-center justify-center h-full p-64 lg:px-112 overflow-hidden"
+ sx={ { backgroundColor:'primary.main' } }
+ >
+ <svg
+ className="absolute inset-0 pointer-events-none"
+ viewBox="0 0 960 540"
+ width="100%"
+ height="100%"
+ preserveAspectRatio="xMidYMax slice"
+ xmlns="http://www.w3.org/2000/svg"
+ >
+ <Box
+ component="g"
+ sx={ { color:'primary.light' } }
+ className="opacity-20"
+ fill="none"
+ stroke="currentColor"
+ strokeWidth="100"
+ >
+ <circle r="234" cx="196" cy="23"/>
+ <circle r="234" cx="790" cy="491"/>
+ </Box>
+ </svg>
+ <Box
+ component="svg"
+ className="absolute -top-64 -right-64 opacity-20"
+ sx={ { color:'primary.light' } }
+ viewBox="0 0 220 192"
+ width="220px"
+ height="192px"
+ fill="none"
+ >
+ <defs>
+ <pattern
+ id="837c3e70-6c3a-44e6-8854-cc48c737b659"
+ x="0"
+ y="0"
+ width="20"
+ height="20"
+ patternUnits="userSpaceOnUse"
+ >
+ <rect x="0" y="0" width="4" height="4" fill="currentColor"/>
+ </pattern>
+ </defs>
+ <rect width="220" height="192" fill="url(#837c3e70-6c3a-44e6-8854-cc48c737b659)"/>
+ </Box>
+
+ <div className="z-10 relative w-full max-w-2xl">
+ <div className="text-7xl font-bold leading-none text-grey-100">
+ <div>Please Login</div>
+ </div>
+ <div className="mt-24 text-lg tracking-tight leading-6 text-grey-400">
+ Enter your company employee number and password to log in.
+ </div>
+ </div>
+ </Box>
+ </div>
+ );
+}
+
+export default SignInPage;
--- /dev/null
+export const base_url = 'http://localhost:23601/';
--- /dev/null
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+body {
+ margin: 0;
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
+ 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
+ sans-serif;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+code {
+ font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
+ monospace;
+}
--- /dev/null
+import React from 'react';
+import ReactDOM from 'react-dom/client';
+import './index.css';
+import App from './App';
+import reportWebVitals from './reportWebVitals';
+import { BrowserRouter } from 'react-router-dom';
+
+const root = ReactDOM.createRoot(document.getElementById('root'));
+root.render(
+ <React.StrictMode>
+ <BrowserRouter>
+ <App/>
+ </BrowserRouter>
+ </React.StrictMode>
+);
+
+// If you want to start measuring performance in your app, pass a function
+// to log results (for example: reportWebVitals(console.log))
+// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
+reportWebVitals();
--- /dev/null
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#61DAFB"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/><circle cx="420.9" cy="296.5" r="45.7"/><path d="M520.5 78.1z"/></g></svg>
\ No newline at end of file
--- /dev/null
+const reportWebVitals = onPerfEntry => {
+ if (onPerfEntry && onPerfEntry instanceof Function) {
+ import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
+ getCLS(onPerfEntry);
+ getFID(onPerfEntry);
+ getFCP(onPerfEntry);
+ getLCP(onPerfEntry);
+ getTTFB(onPerfEntry);
+ });
+ }
+};
+
+export default reportWebVitals;
--- /dev/null
+// jest-dom adds custom jest matchers for asserting on DOM nodes.
+// allows you to do things like:
+// expect(element).toHaveTextContent(/react/i)
+// learn more: https://github.com/testing-library/jest-dom
+import '@testing-library/jest-dom';
--- /dev/null
+/* main.css or similar */
+
+.App {
+ text-align: center;
+}
+
+.app-header {
+ min-height: 2rem;
+ background-color: rgb(103, 58, 183);
+ padding: .25rem;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ font-size: calc(10px + 2vmin);
+ color: white;
+}
+
+.App-link {
+ color: #61dafb;
+}
+
+@keyframes App-logo-spin {
+ from {
+ transform: rotate(0deg);
+ }
+ to {
+ transform: rotate(360deg);
+ }
+}
--- /dev/null
+/**
+ * Component classes registered by plugins.
+ *
+ */
+
+@import 'print.css';
+
+@import 'tables.css';
+
+@import 'prism.css';
+
+@tailwind components;
--- /dev/null
+/**
+ * Tailwind's utility classes, generated based on your config file.
+ */
+
+@tailwind utilities;
--- /dev/null
+/*----------------------------------------------------------------*/
+/* Print
+/*----------------------------------------------------------------*/
+@media all {
+ /* Never show page breaks in normal view */
+ .page-break-after,
+ .page-break-before {
+ display: none;
+ }
+}
+
+@media print {
+ /* html and body tweaks */
+ html, body {
+ height: auto !important;
+ overflow: initial !important;
+ background: none
+ }
+
+ /* Page breaks */
+ .page-break-after {
+ display: block;
+ page-break-after: always;
+ position: relative;
+ }
+
+ .page-break-before {
+ display: block;
+ page-break-before: always;
+ position: relative;
+ }
+
+ /* General styles */
+ #fuse-toolbar,
+ #fuse-footer,
+ #fuse-navbar,
+ #fuse-settings-presets,
+ #fuse-layout .ps > .ps__rail-x,
+ #fuse-layout .ps > .ps__rail-y {
+ display: none !important;
+ }
+
+ #fuse-layout .ps {
+ overflow: visible !important;
+ }
+}
--- /dev/null
+code[class*="language-"],
+pre[class*="language-"] {
+ text-align: left;
+ white-space: pre-wrap;
+ word-break: break-all;
+ word-wrap: break-word;
+ color: #c3cee3;
+ background: #263238;
+ font-family: Roboto Mono,"Liberation Mono",Menlo,Courier,monospace;
+ font-size: 1em;
+ line-height: 1.5;
+ -moz-tab-size: 4;
+ -o-tab-size: 4;
+ tab-size: 4;
+ -webkit-hyphens: none;
+ -moz-hyphens: none;
+ -ms-hyphens: none;
+ hyphens: none;
+}
+
+
+code[class*="language-"]::-moz-selection,
+pre[class*="language-"]::-moz-selection,
+code[class*="language-"] ::-moz-selection,
+pre[class*="language-"] ::-moz-selection {
+ background: #000000;
+}
+
+code[class*="language-"]::selection,
+pre[class*="language-"]::selection,
+code[class*="language-"] ::selection,
+pre[class*="language-"] ::selection {
+ background: #000000;
+}
+
+:not(pre) > code[class*="language-"] {
+ white-space: normal;
+ border-radius: 0.2em;
+ padding: 0.1em;
+}
+
+pre[class*="language-"] {
+ overflow: auto;
+ position: relative;
+ padding: 12px;
+ border-radius: 4px;;
+}
+
+.language-css > code,
+.language-sass > code,
+.language-scss > code {
+ color: #fd9170;
+}
+
+[class*="language-"] .namespace {
+ opacity: 0.7;
+}
+
+.token.plain-text {
+ color: #c3cee3;
+}
+
+.token.atrule {
+ color: #c792ea;
+}
+
+.token.attr-name {
+ color: #ffcb6b;
+}
+
+.token.attr-value {
+ color: #c3e88d;
+}
+
+.token.attribute {
+ color: #c3e88d;
+}
+
+.token.boolean {
+ color: #c792ea;
+}
+
+.token.builtin {
+ color: #ffcb6b;
+}
+
+.token.cdata {
+ color: #80cbc4;
+}
+
+.token.char {
+ color: #80cbc4;
+}
+
+.token.class {
+ color: #ffcb6b;
+}
+
+.token.class-name {
+ color: #82aaff;
+}
+
+.token.color {
+ color: #f2ff00;
+}
+
+.token.comment {
+ color: #546e7a;
+}
+
+.token.constant {
+ color: #c792ea;
+}
+
+.token.deleted {
+ color: #f07178;
+}
+
+.token.doctype {
+ color: #546e7a;
+}
+
+.token.entity {
+ color: #f07178;
+}
+
+.token.function {
+ color: #c792ea;
+}
+
+.token.hexcode {
+ color: #f2ff00;
+}
+
+.token.id {
+ color: #c792ea;
+ font-weight: bold;
+}
+
+.token.important {
+ color: #c792ea;
+ font-weight: bold;
+}
+
+.token.inserted {
+ color: #80cbc4;
+}
+
+.token.keyword {
+ color: #c792ea;
+ font-style: italic;
+}
+
+.token.number {
+ color: #fd9170;
+}
+
+.token.operator {
+ color: #89ddff;
+}
+
+.token.prolog {
+ color: #546e7a;
+}
+
+.token.property {
+ color: #80cbc4;
+}
+
+.token.pseudo-class {
+ color: #c3e88d;
+}
+
+.token.pseudo-element {
+ color: #c3e88d;
+}
+
+.token.punctuation {
+ color: #89ddff;
+}
+
+.token.regex {
+ color: #f2ff00;
+}
+
+.token.selector {
+ color: #f07178;
+}
+
+.token.string {
+ color: #c3e88d;
+}
+
+.token.symbol {
+ color: #c792ea;
+}
+
+.token.tag {
+ color: #f07178;
+}
+
+.token.unit {
+ color: #f07178;
+}
+
+.token.url {
+ color: #fd9170;
+}
+
+.token.variable {
+ color: #f07178;
+}
--- /dev/null
+/**
+Basic Table Styles
+ */
+/*.table-responsive {*/
+/* display: block;*/
+/* width: 100%;*/
+/* overflow-x: auto;*/
+/* -webkit-overflow-scrolling: touch;*/
+/* -ms-overflow-style: -ms-autohiding-scrollbar;*/
+/*}*/
+
+/*table.simple {*/
+/* width: 100%;*/
+/* border: none;*/
+/* border-spacing: 0;*/
+/* text-align: left;*/
+/*}*/
+
+/*table.simple thead tr th {*/
+/* padding: 16px 8px;*/
+/* font-weight: 500;*/
+/* border-bottom: 1px solid rgba(0, 0, 0, 0.12);*/
+/* white-space: nowrap;*/
+/*}*/
+
+/*table.simple thead tr th:first-child {*/
+/* padding-left: 24px;*/
+/*}*/
+
+/*table.simple thead tr th:last-child {*/
+/* padding-right: 24px;*/
+/*}*/
+
+/*table.simple tbody tr td {*/
+/* padding: 12px 8px;*/
+/* border-bottom: 1px solid rgba(0, 0, 0, 0.12);*/
+/*}*/
+
+/*table.simple tbody tr td:first-child {*/
+/* padding-left: 24px;*/
+/*}*/
+
+/*table.simple tbody tr td:last-child {*/
+/* padding-right: 24px;*/
+/*}*/
+
+/*table.simple tbody tr:last-child td {*/
+/* border-bottom: none;*/
+/*}*/
+
+/*table.simple.clickable tbody tr {*/
+/* cursor: pointer;*/
+/*}*/
+
+/*table.simple.clickable tbody tr:hover {*/
+/* background: rgba(0, 0, 0, 0.03);*/
+/*}*/
+
+/*table.simple.borderless {*/
+/* border: none;*/
+/*}*/
+
+/*table.simple.borderless tbody tr td{*/
+/* border: none;*/
+/*}*/
+
+/*table.simple.borderless thead tr th{*/
+/* border: none;*/
+/*}*/
--- /dev/null
+/** @type {import('tailwindcss').Config} */
+/* eslint-disable import/no-extraneous-dependencies */
+const path = require('path');
+
+module.exports = {
+ content: ['./src/**/*.{js,jsx,ts,tsx}', './public/index.html'],
+ safelist: ['pl-24', 'pl-40', 'pl-56', 'pl-72', 'pl-80'],
+ presets: [],
+ darkMode: 'class', // or 'class'
+ theme: {
+ accentColor: ({ theme }) => ({
+ ...theme('colors'),
+ auto: 'auto',
+ }),
+ animation: {
+ none: 'none',
+ spin: 'spin 1s linear infinite',
+ ping: 'ping 1s cubic-bezier(0, 0, 0.2, 1) infinite',
+ pulse: 'pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite',
+ bounce: 'bounce 1s infinite',
+ },
+ aria: {
+ checked: 'checked="true"',
+ disabled: 'disabled="true"',
+ expanded: 'expanded="true"',
+ hidden: 'hidden="true"',
+ pressed: 'pressed="true"',
+ readonly: 'readonly="true"',
+ required: 'required="true"',
+ selected: 'selected="true"',
+ },
+ aspectRatio: {
+ auto: 'auto',
+ square: '1 / 1',
+ video: '16 / 9',
+ },
+ backdropBlur: ({ theme }) => theme('blur'),
+ backdropBrightness: ({ theme }) => theme('brightness'),
+ backdropContrast: ({ theme }) => theme('contrast'),
+ backdropGrayscale: ({ theme }) => theme('grayscale'),
+ backdropHueRotate: ({ theme }) => theme('hueRotate'),
+ backdropInvert: ({ theme }) => theme('invert'),
+ backdropOpacity: ({ theme }) => theme('opacity'),
+ backdropSaturate: ({ theme }) => theme('saturate'),
+ backdropSepia: ({ theme }) => theme('sepia'),
+ backgroundColor: ({ theme }) => theme('colors'),
+ backgroundImage: {
+ none: 'none',
+ 'gradient-to-t': 'linear-gradient(to top, var(--tw-gradient-stops))',
+ 'gradient-to-tr': 'linear-gradient(to top right, var(--tw-gradient-stops))',
+ 'gradient-to-r': 'linear-gradient(to right, var(--tw-gradient-stops))',
+ 'gradient-to-br': 'linear-gradient(to bottom right, var(--tw-gradient-stops))',
+ 'gradient-to-b': 'linear-gradient(to bottom, var(--tw-gradient-stops))',
+ 'gradient-to-bl': 'linear-gradient(to bottom left, var(--tw-gradient-stops))',
+ 'gradient-to-l': 'linear-gradient(to left, var(--tw-gradient-stops))',
+ 'gradient-to-tl': 'linear-gradient(to top left, var(--tw-gradient-stops))',
+ },
+ backgroundOpacity: ({ theme }) => theme('opacity'),
+ backgroundPosition: {
+ bottom: 'bottom',
+ center: 'center',
+ left: 'left',
+ 'left-bottom': 'left bottom',
+ 'left-top': 'left top',
+ right: 'right',
+ 'right-bottom': 'right bottom',
+ 'right-top': 'right top',
+ top: 'top',
+ },
+ backgroundSize: {
+ auto: 'auto',
+ cover: 'cover',
+ contain: 'contain',
+ },
+ blur: {
+ 0: '0',
+ none: '0',
+ sm: '4px',
+ DEFAULT: '8px',
+ md: '12px',
+ lg: '16px',
+ xl: '24px',
+ '2xl': '40px',
+ '3xl': '64px',
+ },
+ borderColor: ({ theme }) => ({
+ ...theme('colors'),
+ DEFAULT: theme('colors.gray.200', 'currentColor'),
+ }),
+ borderOpacity: ({ theme }) => theme('opacity'),
+ borderRadius: {
+ none: '0px',
+ sm: '.2rem',
+ DEFAULT: '.4rem',
+ md: '.6rem',
+ lg: '.8rem',
+ xl: '1.2rem',
+ '2xl': '1.6rem',
+ '3xl': '2.4rem',
+ full: '9999px',
+ 0: '0px',
+ 2: '.2rem',
+ 4: '.4rem',
+ 6: '.6rem',
+ 8: '.8rem',
+ 12: '1.2rem',
+ 16: '1.6rem',
+ 20: '2rem',
+ 24: '2.4rem',
+ 28: '2.8rem',
+ 32: '3.2rem',
+ },
+ borderSpacing: ({ theme }) => ({
+ ...theme('spacing'),
+ }),
+ borderWidth: {
+ DEFAULT: '1px',
+ 0: '0px',
+ 1: '1px',
+ 2: '2px',
+ 3: '3px',
+ 4: '4px',
+ 8: '8px',
+ },
+ boxShadow: {
+ sm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
+ DEFAULT: '0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)',
+ md: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
+ lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
+ xl: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
+ '2xl': '0 25px 50px -12px rgba(0, 0, 0, 0.25)',
+ inner: 'inset 0 2px 4px 0 rgba(0,0,0,0.06)',
+ none: 'none',
+ 0: '0px 0px 0px 0px rgba(0, 0, 0, 0.2), 0px 0px 0px 0px rgba(0, 0, 0, 0.14), 0px 0px 0px 0px rgba(0, 0, 0, 0.12)',
+ 1: '0px 2px 1px -1px rgba(0, 0, 0, 0.2), 0px 1px 1px 0px rgba(0, 0, 0, 0.14), 0px 1px 3px 0px rgba(0, 0, 0, 0.12)',
+ 2: '0px 3px 1px -2px rgba(0, 0, 0, 0.2), 0px 2px 2px 0px rgba(0, 0, 0, 0.14), 0px 1px 5px 0px rgba(0, 0, 0, 0.12)',
+ 3: '0px 3px 3px -2px rgba(0, 0, 0, 0.2), 0px 3px 4px 0px rgba(0, 0, 0, 0.14), 0px 1px 8px 0px rgba(0, 0, 0, 0.12)',
+ 4: '0px 2px 4px -1px rgba(0, 0, 0, 0.2), 0px 4px 5px 0px rgba(0, 0, 0, 0.14), 0px 1px 10px 0px rgba(0, 0, 0, 0.12)',
+ 5: '0px 3px 5px -1px rgba(0, 0, 0, 0.2), 0px 5px 8px 0px rgba(0, 0, 0, 0.14), 0px 1px 14px 0px rgba(0, 0, 0, 0.12)',
+ 6: '0px 3px 5px -1px rgba(0, 0, 0, 0.2), 0px 6px 10px 0px rgba(0, 0, 0, 0.14), 0px 1px 18px 0px rgba(0, 0, 0, 0.12)',
+ 7: '0px 4px 5px -2px rgba(0, 0, 0, 0.2), 0px 7px 10px 1px rgba(0, 0, 0, 0.14), 0px 2px 16px 1px rgba(0, 0, 0, 0.12)',
+ 8: '0px 5px 5px -3px rgba(0, 0, 0, 0.2), 0px 8px 10px 1px rgba(0, 0, 0, 0.14), 0px 3px 14px 2px rgba(0, 0, 0, 0.12)',
+ 9: '0px 5px 6px -3px rgba(0, 0, 0, 0.2), 0px 9px 12px 1px rgba(0, 0, 0, 0.14), 0px 3px 16px 2px rgba(0, 0, 0, 0.12)',
+ 10: '0px 6px 6px -3px rgba(0, 0, 0, 0.2), 0px 10px 14px 1px rgba(0, 0, 0, 0.14), 0px 4px 18px 3px rgba(0, 0, 0, 0.12)',
+ 11: '0px 6px 7px -4px rgba(0, 0, 0, 0.2), 0px 11px 15px 1px rgba(0, 0, 0, 0.14), 0px 4px 20px 3px rgba(0, 0, 0, 0.12)',
+ 12: '0px 7px 8px -4px rgba(0, 0, 0, 0.2), 0px 12px 17px 2px rgba(0, 0, 0, 0.14), 0px 5px 22px 4px rgba(0, 0, 0, 0.12)',
+ 13: '0px 7px 8px -4px rgba(0, 0, 0, 0.2), 0px 13px 19px 2px rgba(0, 0, 0, 0.14), 0px 5px 24px 4px rgba(0, 0, 0, 0.12)',
+ 14: '0px 7px 9px -4px rgba(0, 0, 0, 0.2), 0px 14px 21px 2px rgba(0, 0, 0, 0.14), 0px 5px 26px 4px rgba(0, 0, 0, 0.12)',
+ 15: '0px 8px 9px -5px rgba(0, 0, 0, 0.2), 0px 15px 22px 2px rgba(0, 0, 0, 0.14), 0px 6px 28px 5px rgba(0, 0, 0, 0.12)',
+ 16: '0px 8px 10px -5px rgba(0, 0, 0, 0.2), 0px 16px 24px 2px rgba(0, 0, 0, 0.14), 0px 6px 30px 5px rgba(0, 0, 0, 0.12)',
+ 17: '0px 8px 11px -5px rgba(0, 0, 0, 0.2), 0px 17px 26px 2px rgba(0, 0, 0, 0.14), 0px 6px 32px 5px rgba(0, 0, 0, 0.12)',
+ 18: '0px 9px 11px -5px rgba(0, 0, 0, 0.2), 0px 18px 28px 2px rgba(0, 0, 0, 0.14), 0px 7px 34px 6px rgba(0, 0, 0, 0.12)',
+ 19: '0px 9px 12px -6px rgba(0, 0, 0, 0.2), 0px 19px 29px 2px rgba(0, 0, 0, 0.14), 0px 7px 36px 6px rgba(0, 0, 0, 0.12)',
+ 20: '0px 10px 13px -6px rgba(0, 0, 0, 0.2), 0px 20px 31px 3px rgba(0, 0, 0, 0.14), 0px 8px 38px 7px rgba(0, 0, 0, 0.12)',
+ 21: '0px 10px 13px -6px rgba(0, 0, 0, 0.2), 0px 21px 33px 3px rgba(0, 0, 0, 0.14), 0px 8px 40px 7px rgba(0, 0, 0, 0.12)',
+ 22: '0px 10px 14px -6px rgba(0, 0, 0, 0.2), 0px 22px 35px 3px rgba(0, 0, 0, 0.14), 0px 8px 42px 7px rgba(0, 0, 0, 0.12)',
+ 23: '0px 11px 14px -7px rgba(0, 0, 0, 0.2), 0px 23px 36px 3px rgba(0, 0, 0, 0.14), 0px 9px 44px 8px rgba(0, 0, 0, 0.12)',
+ 24: '0px 11px 15px -7px rgba(0, 0, 0, 0.2), 0px 24px 38px 3px rgba(0, 0, 0, 0.14), 0px 9px 46px 8px rgba(0, 0, 0, 0.12)',
+ },
+ boxShadowColor: ({ theme }) => theme('colors'),
+ brightness: {
+ 0: '0',
+ 50: '.5',
+ 75: '.75',
+ 90: '.9',
+ 95: '.95',
+ 100: '1',
+ 105: '1.05',
+ 110: '1.1',
+ 125: '1.25',
+ 150: '1.5',
+ 200: '2',
+ },
+ caretColor: ({ theme }) => theme('colors'),
+ colors: ({ colors }) => ({
+ inherit: colors.inherit,
+ current: colors.current,
+ transparent: 'transparent',
+ black: '#22292F',
+ white: '#fff',
+ grey: {
+ 50: '#FAFAFA',
+ 100: '#F5F5F5',
+ 200: '#EEEEEE',
+ 300: '#E0E0E0',
+ 400: '#BDBDBD',
+ 500: '#9E9E9E',
+ DEFAULT: '#9E9E9E',
+ 600: '#757575',
+ 700: '#616161',
+ 800: '#424242',
+ 900: '#212121',
+ A100: '#D5D5D5',
+ A200: '#AAAAAA',
+ A400: '#303030',
+ A700: '#616161',
+ },
+ gray: {
+ 50: '#FAFAFA',
+ 100: '#F5F5F5',
+ 200: '#EEEEEE',
+ 300: '#E0E0E0',
+ 400: '#BDBDBD',
+ 500: '#9E9E9E',
+ DEFAULT: '#9E9E9E',
+ 600: '#757575',
+ 700: '#616161',
+ 800: '#424242',
+ 900: '#212121',
+ A100: '#D5D5D5',
+ A200: '#AAAAAA',
+ A400: '#303030',
+ A700: '#616161',
+ },
+ red: {
+ 50: '#FFEBEE',
+ 100: '#FFCDD2',
+ 200: '#EF9A9A',
+ 300: '#E57373',
+ 400: '#EF5350',
+ 500: '#F44336',
+ DEFAULT: '#F44336',
+ 600: '#E53935',
+ 700: '#D32F2F',
+ 800: '#C62828',
+ 900: '#B71C1C',
+ A100: '#FF8A80',
+ A200: '#FF5252',
+ A400: '#FF1744',
+ A700: '#D50000',
+ },
+ orange: {
+ 50: '#FFF3E0',
+ 100: '#FFE0B2',
+ 200: '#FFCC80',
+ 300: '#FFB74D',
+ 400: '#FFA726',
+ 500: '#FF9800',
+ DEFAULT: '#FF9800',
+ 600: '#FB8C00',
+ 700: '#F57C00',
+ 800: '#EF6C00',
+ 900: '#E65100',
+ A100: '#FFD180',
+ A200: '#FFAB40',
+ A400: '#FF9100',
+ A700: '#FF6D00',
+ },
+ 'deep-orange': {
+ 50: '#FBE9E7',
+ 100: '#FFCCBC',
+ 200: '#FFAB91',
+ 300: '#FF8A65',
+ 400: '#FF7043',
+ 500: '#FF5722',
+ DEFAULT: '#FF5722',
+ 600: '#F4511E',
+ 700: '#E64A19',
+ 800: '#D84315',
+ 900: '#BF360C',
+ A100: '#FF9E80',
+ A200: '#FF6E40',
+ A400: '#FF3D00',
+ A700: '#DD2C00',
+ },
+ yellow: {
+ 50: '#FFFDE7',
+ 100: '#FFF9C4',
+ 200: '#FFF59D',
+ 300: '#FFF176',
+ 400: '#FFEE58',
+ 500: '#FFEB3B',
+ DEFAULT: '#FFEB3B',
+ 600: '#FDD835',
+ 700: '#FBC02D',
+ 800: '#F9A825',
+ 900: '#F57F17',
+ A100: '#FFFF8D',
+ A200: '#FFFF00',
+ A400: '#FFEA00',
+ A700: '#FFD600',
+ },
+ green: {
+ 50: '#E8F5E9',
+ 100: '#C8E6C9',
+ 200: '#A5D6A7',
+ 300: '#81C784',
+ 400: '#66BB6A',
+ 500: '#4CAF50',
+ DEFAULT: '#4CAF50',
+ 600: '#43A047',
+ 700: '#388E3C',
+ 800: '#2E7D32',
+ 900: '#1B5E20',
+ A100: '#B9F6CA',
+ A200: '#69F0AE',
+ A400: '#00E676',
+ A700: '#00C853',
+ },
+ 'light-green': {
+ 50: '#F1F8E9',
+ 100: '#DCEDC8',
+ 200: '#C5E1A5',
+ 300: '#AED581',
+ 400: '#9CCC65',
+ 500: '#8BC34A',
+ DEFAULT: '#8BC34A',
+ 600: '#7CB342',
+ 700: '#689F38',
+ 800: '#558B2F',
+ 900: '#33691E',
+ A100: '#CCFF90',
+ A200: '#B2FF59',
+ A400: '#76FF03',
+ A700: '#64DD17',
+ },
+ teal: {
+ 50: '#E0F2F1',
+ 100: '#B2DFDB',
+ 200: '#80CBC4',
+ 300: '#4DB6AC',
+ 400: '#26A69A',
+ 500: '#009688',
+ DEFAULT: '#009688',
+ 600: '#00897B',
+ 700: '#00796B',
+ 800: '#00695C',
+ 900: '#004D40',
+ A100: '#A7FFEB',
+ A200: '#64FFDA',
+ A400: '#1DE9B6',
+ A700: '#00BFA5',
+ },
+ blue: {
+ 50: '#E3F2FD',
+ 100: '#BBDEFB',
+ 200: '#90CAF9',
+ 300: '#64B5F6',
+ 400: '#42A5F5',
+ 500: '#2196F3',
+ DEFAULT: '#2196F3',
+ 600: '#1E88E5',
+ 700: '#1976D2',
+ 800: '#1565C0',
+ 900: '#0D47A1',
+ A100: '#82B1FF',
+ A200: '#448AFF',
+ A400: '#2979FF',
+ A700: '#2962FF',
+ },
+ 'light-blue': {
+ 50: '#E1F5FE',
+ 100: '#B3E5FC',
+ 200: '#81D4FA',
+ 300: '#4FC3F7',
+ 400: '#29B6F6',
+ 500: '#03A9F4',
+ DEFAULT: '#03A9F4',
+ 600: '#039BE5',
+ 700: '#0288D1',
+ 800: '#0277BD',
+ 900: '#01579B',
+ A100: '#80D8FF',
+ A200: '#40C4FF',
+ A400: '#00B0FF',
+ A700: '#0091EA',
+ },
+ indigo: {
+ 50: '#E8EAF6',
+ 100: '#C5CAE9',
+ 200: '#9FA8DA',
+ 300: '#7986CB',
+ 400: '#5C6BC0',
+ 500: '#3F51B5',
+ DEFAULT: '#3F51B5',
+ 600: '#3949AB',
+ 700: '#303F9F',
+ 800: '#283593',
+ 900: '#1A237E',
+ A100: '#8C9EFF',
+ A200: '#536DFE',
+ A400: '#3D5AFE',
+ A700: '#304FFE',
+ },
+ purple: {
+ 50: '#F3E5F5',
+ 100: '#E1BEE7',
+ 200: '#CE93D8',
+ 300: '#BA68C8',
+ 400: '#AB47BC',
+ 500: '#9C27B0',
+ DEFAULT: '#9C27B0',
+ 600: '#8E24AA',
+ 700: '#7B1FA2',
+ 800: '#6A1B9A',
+ 900: '#4A148C',
+ A100: '#EA80FC',
+ A200: '#E040FB',
+ A400: '#D500F9',
+ A700: '#AA00FF',
+ },
+ 'deep-purple': {
+ 50: '#EDE7F6',
+ 100: '#D1C4E9',
+ 200: '#B39DDB',
+ 300: '#9575CD',
+ 400: '#7E57C2',
+ 500: '#673AB7',
+ DEFAULT: '#673AB7',
+ 600: '#5E35B1',
+ 700: '#512DA8',
+ 800: '#4527A0',
+ 900: '#311B92',
+ A100: '#B388FF',
+ A200: '#7C4DFF',
+ A400: '#651FFF',
+ A700: '#6200EA',
+ },
+ pink: {
+ 50: '#FCE4EC',
+ 100: '#F8BBD0',
+ 200: '#F48FB1',
+ 300: '#F06292',
+ 400: '#EC407A',
+ 500: '#E91E63',
+ DEFAULT: '#E91E63',
+ 600: '#D81B60',
+ 700: '#C2185B',
+ 800: '#AD1457',
+ 900: '#880E4F',
+ A100: '#FF80AB',
+ A200: '#FF4081',
+ A400: '#F50057',
+ A700: '#C51162',
+ },
+ lime: {
+ 50: '#F9FBE7',
+ 100: '#F0F4C3',
+ 200: '#E6EE9C',
+ 300: '#DCE775',
+ 400: '#D4E157',
+ 500: '#CDDC39',
+ DEFAULT: '#CDDC39',
+ 600: '#C0CA33',
+ 700: '#AFB42B',
+ 800: '#9E9D24',
+ 900: '#827717',
+ A100: '#F4FF81',
+ A200: '#EEFF41',
+ A400: '#C6FF00',
+ A700: '#AEEA00',
+ },
+ amber: {
+ 50: '#FFF8E1',
+ 100: '#FFECB3',
+ 200: '#FFE082',
+ 300: '#FFD54F',
+ 400: '#FFCA28',
+ 500: '#FFC107',
+ DEFAULT: '#FFC107',
+ 600: '#FFB300',
+ 700: '#FFA000',
+ 800: '#FF8F00',
+ 900: '#FF6F00',
+ A100: '#FFE57F',
+ A200: '#FFD740',
+ A400: '#FFC400',
+ A700: '#FFAB00',
+ },
+ brown: {
+ 50: '#EFEBE9',
+ 100: '#D7CCC8',
+ 200: '#BCAAA4',
+ 300: '#A1887F',
+ 400: '#8D6E63',
+ 500: '#795548',
+ DEFAULT: '#795548',
+ 600: '#6D4C41',
+ 700: '#5D4037',
+ 800: '#4E342E',
+ 900: '#3E2723',
+ A100: '#D7CCC8',
+ A200: '#BCAAA4',
+ A400: '#8D6E63',
+ A700: '#5D4037',
+ },
+ 'blue-gray': {
+ 50: '#ECEFF1',
+ 100: '#CFD8DC',
+ 200: '#B0BEC5',
+ 300: '#90A4AE',
+ 400: '#78909C',
+ 500: '#607D8B',
+ DEFAULT: '#607D8B',
+ 600: '#546E7A',
+ 700: '#455A64',
+ 800: '#37474F',
+ 900: '#263238',
+ A100: '#CFD8DC',
+ A200: '#B0BEC5',
+ A400: '#78909C',
+ A700: '#455A64',
+ },
+ cyan: {
+ 50: '#E0F7FA',
+ 100: '#B2EBF2',
+ 200: '#80DEEA',
+ 300: '#4DD0E1',
+ 400: '#26C6DA',
+ 500: '#00BCD4',
+ DEFAULT: '#00BCD4',
+ 600: '#00ACC1',
+ 700: '#0097A7',
+ 800: '#00838F',
+ 900: '#006064',
+ A100: '#84FFFF',
+ A200: '#18FFFF',
+ A400: '#00E5FF',
+ A700: '#00B8D4',
+ },
+ }),
+ columns: {
+ auto: 'auto',
+ 1: '1',
+ 2: '2',
+ 3: '3',
+ 4: '4',
+ 5: '5',
+ 6: '6',
+ 7: '7',
+ 8: '8',
+ 9: '9',
+ 10: '10',
+ 11: '11',
+ 12: '12',
+ '3xs': '16rem',
+ '2xs': '18rem',
+ xs: '32rem',
+ sm: '48rem',
+ md: '64rem',
+ lg: '80rem',
+ xl: '57.6rem',
+ '2xl': '65.6rem',
+ '3xl': '76.8rem',
+ '4xl': '89.6rem',
+ '5xl': '102.4rem',
+ '6xl': '115.2rem',
+ '7xl': '128rem',
+ },
+ container: {},
+ content: {
+ none: 'none',
+ },
+ contrast: {
+ 0: '0',
+ 50: '.5',
+ 75: '.75',
+ 100: '1',
+ 125: '1.25',
+ 150: '1.5',
+ 200: '2',
+ },
+ cursor: {
+ auto: 'auto',
+ default: 'default',
+ pointer: 'pointer',
+ wait: 'wait',
+ text: 'text',
+ move: 'move',
+ help: 'help',
+ 'not-allowed': 'not-allowed',
+ none: 'none',
+ 'context-menu': 'context-menu',
+ progress: 'progress',
+ cell: 'cell',
+ crosshair: 'crosshair',
+ 'vertical-text': 'vertical-text',
+ alias: 'alias',
+ copy: 'copy',
+ 'no-drop': 'no-drop',
+ grab: 'grab',
+ grabbing: 'grabbing',
+ 'all-scroll': 'all-scroll',
+ 'col-resize': 'col-resize',
+ 'row-resize': 'row-resize',
+ 'n-resize': 'n-resize',
+ 'e-resize': 'e-resize',
+ 's-resize': 's-resize',
+ 'w-resize': 'w-resize',
+ 'ne-resize': 'ne-resize',
+ 'nw-resize': 'nw-resize',
+ 'se-resize': 'se-resize',
+ 'sw-resize': 'sw-resize',
+ 'ew-resize': 'ew-resize',
+ 'ns-resize': 'ns-resize',
+ 'nesw-resize': 'nesw-resize',
+ 'nwse-resize': 'nwse-resize',
+ 'zoom-in': 'zoom-in',
+ 'zoom-out': 'zoom-out',
+ },
+ divideColor: ({ theme }) => theme('borderColor'),
+ divideOpacity: ({ theme }) => theme('borderOpacity'),
+ divideWidth: ({ theme }) => theme('borderWidth'),
+ dropShadow: {
+ sm: '0 1px 1px rgba(0,0,0,0.05)',
+ DEFAULT: ['0 1px 2px rgba(0, 0, 0, 0.1)', '0 1px 1px rgba(0, 0, 0, 0.06)'],
+ md: ['0 4px 3px rgba(0, 0, 0, 0.07)', '0 2px 2px rgba(0, 0, 0, 0.06)'],
+ lg: ['0 10px 8px rgba(0, 0, 0, 0.04)', '0 4px 3px rgba(0, 0, 0, 0.1)'],
+ xl: ['0 20px 13px rgba(0, 0, 0, 0.03)', '0 8px 5px rgba(0, 0, 0, 0.08)'],
+ '2xl': '0 25px 25px rgba(0, 0, 0, 0.15)',
+ none: '0 0 #0000',
+ },
+ fill: ({ theme }) => ({
+ none: 'none',
+ ...theme('colors'),
+ }),
+ flex: {
+ 1: '1 1 0%',
+ auto: '1 1 auto',
+ initial: '0 1 auto',
+ none: 'none',
+ },
+ flexBasis: ({ theme }) => ({
+ auto: 'auto',
+ ...theme('spacing'),
+ '1/2': '50%',
+ '1/3': '33.333333%',
+ '2/3': '66.666667%',
+ '1/4': '25%',
+ '2/4': '50%',
+ '3/4': '75%',
+ '1/5': '20%',
+ '2/5': '40%',
+ '3/5': '60%',
+ '4/5': '80%',
+ '1/6': '16.666667%',
+ '2/6': '33.333333%',
+ '3/6': '50%',
+ '4/6': '66.666667%',
+ '5/6': '83.333333%',
+ '1/12': '8.333333%',
+ '2/12': '16.666667%',
+ '3/12': '25%',
+ '4/12': '33.333333%',
+ '5/12': '41.666667%',
+ '6/12': '50%',
+ '7/12': '58.333333%',
+ '8/12': '66.666667%',
+ '9/12': '75%',
+ '10/12': '83.333333%',
+ '11/12': '91.666667%',
+ full: '100%',
+ }),
+ flexGrow: {
+ 0: '0',
+ DEFAULT: '1',
+ },
+ flexShrink: {
+ 0: '0',
+ DEFAULT: '1',
+ },
+ fontFamily: {
+ sans: [
+ 'Inter var',
+ 'Roboto',
+ '-apple-system',
+ 'BlinkMacSystemFont',
+ '"Segoe UI"',
+ 'Roboto',
+ '"Helvetica Neue"',
+ 'Arial',
+ '"Noto Sans"',
+ 'sans-serif',
+ '"Apple Color Emoji"',
+ '"Segoe UI Emoji"',
+ '"Segoe UI Symbol"',
+ '"Noto Color Emoji"',
+ ],
+ serif: ['ui-serif', 'Georgia', 'Cambria', '"Times New Roman"', 'Times', 'serif'],
+ mono: [
+ 'ui-monospace',
+ 'SFMono-Regular',
+ 'Menlo',
+ 'Monaco',
+ 'Consolas',
+ '"Liberation Mono"',
+ '"Courier New"',
+ 'monospace',
+ ],
+ },
+ fontSize: {
+ xs: '1rem',
+ sm: '1.2rem',
+ md: '1.3rem',
+ base: '1.4rem',
+ lg: '1.6rem',
+ xl: '1.8rem',
+ '2xl': '2rem',
+ '3xl': '2.4rem',
+ '4xl': '3.2rem',
+ '5xl': '3.6rem',
+ '6xl': '4rem',
+ '7xl': '4.8rem',
+ '8xl': '6.4rem',
+ '9xl': '9.6rem',
+ '10xl': '12.8rem',
+ 10: ['1rem'],
+ 11: ['1.1rem'],
+ 12: ['1.2rem'],
+ 13: ['1.3rem'],
+ 14: ['1.4rem'],
+ 15: ['1.5rem'],
+ 16: ['1.6rem'],
+ 17: ['1.7rem'],
+ 18: ['1.8rem'],
+ 19: ['1.9rem'],
+ 20: ['2rem'],
+ 24: ['2.4rem'],
+ 28: ['2.8rem'],
+ 32: ['3.2rem'],
+ 36: ['3.6rem'],
+ 40: ['4rem'],
+ 44: ['4.4rem'],
+ 48: ['4.8rem'],
+ 52: ['5.2rem'],
+ 56: ['5.6rem'],
+ 60: ['6rem'],
+ 64: ['6.4rem'],
+ 68: ['6.8rem'],
+ 72: ['7.2rem'],
+ 96: ['9.6rem'],
+ 128: ['12.8rem'],
+ },
+ fontWeight: {
+ thin: '100',
+ extralight: '200',
+ light: '300',
+ normal: '400',
+ medium: '500',
+ semibold: '600',
+ bold: '700',
+ extrabold: '800',
+ black: '900',
+ 100: '100',
+ 200: '200',
+ 300: '300',
+ 400: '400',
+ 500: '500',
+ 600: '600',
+ 700: '700',
+ 800: '800',
+ 900: '900',
+ },
+ gap: ({ theme }) => theme('spacing'),
+ gradientColorStops: ({ theme }) => theme('colors'),
+ gradientColorStopPositions: {
+ '0%': '0%',
+ '5%': '5%',
+ '10%': '10%',
+ '15%': '15%',
+ '20%': '20%',
+ '25%': '25%',
+ '30%': '30%',
+ '35%': '35%',
+ '40%': '40%',
+ '45%': '45%',
+ '50%': '50%',
+ '55%': '55%',
+ '60%': '60%',
+ '65%': '65%',
+ '70%': '70%',
+ '75%': '75%',
+ '80%': '80%',
+ '85%': '85%',
+ '90%': '90%',
+ '95%': '95%',
+ '100%': '100%',
+ },
+ grayscale: {
+ 0: '0',
+ DEFAULT: '100%',
+ },
+ gridAutoColumns: {
+ auto: 'auto',
+ min: 'min-content',
+ max: 'max-content',
+ fr: 'minmax(0, 1fr)',
+ },
+ gridAutoRows: {
+ auto: 'auto',
+ min: 'min-content',
+ max: 'max-content',
+ fr: 'minmax(0, 1fr)',
+ },
+ gridColumn: {
+ auto: 'auto',
+ 'span-1': 'span 1 / span 1',
+ 'span-2': 'span 2 / span 2',
+ 'span-3': 'span 3 / span 3',
+ 'span-4': 'span 4 / span 4',
+ 'span-5': 'span 5 / span 5',
+ 'span-6': 'span 6 / span 6',
+ 'span-7': 'span 7 / span 7',
+ 'span-8': 'span 8 / span 8',
+ 'span-9': 'span 9 / span 9',
+ 'span-10': 'span 10 / span 10',
+ 'span-11': 'span 11 / span 11',
+ 'span-12': 'span 12 / span 12',
+ 'span-full': '1 / -1',
+ },
+ gridColumnEnd: {
+ auto: 'auto',
+ 1: '1',
+ 2: '2',
+ 3: '3',
+ 4: '4',
+ 5: '5',
+ 6: '6',
+ 7: '7',
+ 8: '8',
+ 9: '9',
+ 10: '10',
+ 11: '11',
+ 12: '12',
+ 13: '13',
+ },
+ gridColumnStart: {
+ auto: 'auto',
+ 1: '1',
+ 2: '2',
+ 3: '3',
+ 4: '4',
+ 5: '5',
+ 6: '6',
+ 7: '7',
+ 8: '8',
+ 9: '9',
+ 10: '10',
+ 11: '11',
+ 12: '12',
+ 13: '13',
+ },
+ gridRow: {
+ auto: 'auto',
+ 'span-1': 'span 1 / span 1',
+ 'span-2': 'span 2 / span 2',
+ 'span-3': 'span 3 / span 3',
+ 'span-4': 'span 4 / span 4',
+ 'span-5': 'span 5 / span 5',
+ 'span-6': 'span 6 / span 6',
+ 'span-full': '1 / -1',
+ },
+ gridRowEnd: {
+ auto: 'auto',
+ 1: '1',
+ 2: '2',
+ 3: '3',
+ 4: '4',
+ 5: '5',
+ 6: '6',
+ 7: '7',
+ },
+ gridRowStart: {
+ auto: 'auto',
+ 1: '1',
+ 2: '2',
+ 3: '3',
+ 4: '4',
+ 5: '5',
+ 6: '6',
+ 7: '7',
+ },
+ gridTemplateColumns: {
+ none: 'none',
+ 1: 'repeat(1, minmax(0, 1fr))',
+ 2: 'repeat(2, minmax(0, 1fr))',
+ 3: 'repeat(3, minmax(0, 1fr))',
+ 4: 'repeat(4, minmax(0, 1fr))',
+ 5: 'repeat(5, minmax(0, 1fr))',
+ 6: 'repeat(6, minmax(0, 1fr))',
+ 7: 'repeat(7, minmax(0, 1fr))',
+ 8: 'repeat(8, minmax(0, 1fr))',
+ 9: 'repeat(9, minmax(0, 1fr))',
+ 10: 'repeat(10, minmax(0, 1fr))',
+ 11: 'repeat(11, minmax(0, 1fr))',
+ 12: 'repeat(12, minmax(0, 1fr))',
+ },
+ gridTemplateRows: {
+ none: 'none',
+ 1: 'repeat(1, minmax(0, 1fr))',
+ 2: 'repeat(2, minmax(0, 1fr))',
+ 3: 'repeat(3, minmax(0, 1fr))',
+ 4: 'repeat(4, minmax(0, 1fr))',
+ 5: 'repeat(5, minmax(0, 1fr))',
+ 6: 'repeat(6, minmax(0, 1fr))',
+ },
+ height: ({ theme }) => ({
+ auto: 'auto',
+ ...theme('spacing'),
+ '1/2': '50%',
+ '1/3': '33.333333%',
+ '2/3': '66.666667%',
+ '1/4': '25%',
+ '2/4': '50%',
+ '3/4': '75%',
+ '1/5': '20%',
+ '2/5': '40%',
+ '3/5': '60%',
+ '4/5': '80%',
+ '1/6': '16.666667%',
+ '2/6': '33.333333%',
+ '3/6': '50%',
+ '4/6': '66.666667%',
+ '5/6': '83.333333%',
+ full: '100%',
+ screen: '100vh',
+ min: 'min-content',
+ max: 'max-content',
+ fit: 'fit-content',
+ }),
+ hueRotate: {
+ '-180': '-180deg',
+ '-90': '-90deg',
+ '-60': '-60deg',
+ '-30': '-30deg',
+ '-15': '-15deg',
+ 0: '0deg',
+ 15: '15deg',
+ 30: '30deg',
+ 60: '60deg',
+ 90: '90deg',
+ 180: '180deg',
+ },
+ inset: (theme, { negative }) => ({
+ auto: 'auto',
+ ...theme('spacing'),
+ ...negative(theme('spacing')),
+ '1/2': '50%',
+ '1/3': '33.333333%',
+ '2/3': '66.666667%',
+ '1/4': '25%',
+ '2/4': '50%',
+ '3/4': '75%',
+ full: '100%',
+ '-1/2': '-50%',
+ '-1/3': '-33.333333%',
+ '-2/3': '-66.666667%',
+ '-1/4': '-25%',
+ '-2/4': '-50%',
+ '-3/4': '-75%',
+ '-full': '-100%',
+ }),
+ invert: {
+ 0: '0',
+ DEFAULT: '100%',
+ },
+ keyframes: {
+ spin: {
+ to: {
+ transform: 'rotate(360deg)',
+ },
+ },
+ ping: {
+ '75%, 100%': {
+ transform: 'scale(2)',
+ opacity: '0',
+ },
+ },
+ pulse: {
+ '50%': {
+ opacity: '.5',
+ },
+ },
+ bounce: {
+ '0%, 100%': {
+ transform: 'translateY(-25%)',
+ animationTimingFunction: 'cubic-bezier(0.8,0,1,1)',
+ },
+ '50%': {
+ transform: 'none',
+ animationTimingFunction: 'cubic-bezier(0,0,0.2,1)',
+ },
+ },
+ },
+ letterSpacing: {
+ tighter: '-0.05em',
+ tight: '-0.025em',
+ normal: '0em',
+ wide: '0.025em',
+ wider: '0.05em',
+ widest: '0.1em',
+ },
+ lineHeight: {
+ none: '1',
+ tight: '1.25',
+ snug: '1.375',
+ normal: '1.5',
+ relaxed: '1.625',
+ loose: '2',
+ 3: '1.2rem',
+ 4: '1.6rem',
+ 5: '2rem',
+ 6: '2.4rem',
+ 7: '2.8rem',
+ 8: '3.2rem',
+ 9: '3.6rem',
+ 10: '4rem',
+ },
+ listStyleType: {
+ none: 'none',
+ disc: 'disc',
+ decimal: 'decimal',
+ },
+ listStyleImage: {
+ none: 'none',
+ },
+ margin: (theme, { negative }) => ({
+ auto: 'auto',
+ ...theme('spacing'),
+ ...negative(theme('spacing')),
+ }),
+ lineClamp: {
+ 1: '1',
+ 2: '2',
+ 3: '3',
+ 4: '4',
+ 5: '5',
+ 6: '6',
+ },
+ maxHeight: ({ theme }) => ({
+ none: 'none',
+ ...theme('spacing'),
+ full: '100%',
+ screen: '100vh',
+ min: 'min-content',
+ max: 'max-content',
+ fit: 'fit-content',
+ auto: 'auto',
+ }),
+ maxWidth: (theme, { breakpoints }) => ({
+ none: 'none',
+ ...theme('spacing'),
+ full: '100%',
+ min: 'min-content',
+ max: 'max-content',
+ fit: 'fit-content',
+ prose: '65ch',
+ ...breakpoints(theme('screens')),
+ }),
+ minHeight: ({ theme }) => ({
+ auto: 'auto',
+ ...theme('spacing'),
+ full: '100%',
+ screen: '100vh',
+ min: 'min-content',
+ max: 'max-content',
+ fit: 'fit-content',
+ }),
+ minWidth: ({ theme }) => ({
+ ...theme('spacing'),
+ full: '100%',
+ min: 'min-content',
+ max: 'max-content',
+ screen: '100vw',
+ fit: 'fit-content',
+ }),
+ objectPosition: {
+ bottom: 'bottom',
+ center: 'center',
+ left: 'left',
+ 'left-bottom': 'left bottom',
+ 'left-top': 'left top',
+ right: 'right',
+ 'right-bottom': 'right bottom',
+ 'right-top': 'right top',
+ top: 'top',
+ },
+ opacity: {
+ 0: '0',
+ 5: '0.05',
+ 10: '0.1',
+ 20: '0.2',
+ 25: '0.25',
+ 30: '0.3',
+ 40: '0.4',
+ 50: '0.5',
+ 60: '0.6',
+ 70: '0.7',
+ 75: '0.75',
+ 80: '0.8',
+ 90: '0.9',
+ 95: '0.95',
+ 100: '1',
+ },
+ order: {
+ first: '-9999',
+ last: '9999',
+ none: '0',
+ 1: '1',
+ 2: '2',
+ 3: '3',
+ 4: '4',
+ 5: '5',
+ 6: '6',
+ 7: '7',
+ 8: '8',
+ 9: '9',
+ 10: '10',
+ 11: '11',
+ 12: '12',
+ },
+ outlineColor: ({ theme }) => theme('colors'),
+ outlineOffset: {
+ 0: '0px',
+ 1: '1px',
+ 2: '2px',
+ 4: '4px',
+ 8: '8px',
+ },
+ outlineWidth: {
+ 0: '0px',
+ 1: '1px',
+ 2: '2px',
+ 4: '4px',
+ 8: '8px',
+ },
+ padding: ({ theme }) => theme('spacing'),
+ placeholderColor: ({ theme }) => theme('colors'),
+ placeholderOpacity: ({ theme }) => theme('opacity'),
+ ringColor: ({ theme }) => ({
+ DEFAULT: theme('colors.blue.500', '#3b82f6'),
+ ...theme('colors'),
+ }),
+ ringOffsetColor: ({ theme }) => theme('colors'),
+ ringOffsetWidth: {
+ 0: '0px',
+ 1: '1px',
+ 2: '2px',
+ 4: '4px',
+ 8: '8px',
+ },
+ ringOpacity: ({ theme }) => ({
+ DEFAULT: '0.5',
+ ...theme('opacity'),
+ }),
+ ringWidth: {
+ DEFAULT: '3px',
+ 0: '0px',
+ 1: '1px',
+ 2: '2px',
+ 4: '4px',
+ 8: '8px',
+ },
+ rotate: {
+ '-180': '-180deg',
+ '-90': '-90deg',
+ '-45': '-45deg',
+ '-12': '-12deg',
+ '-6': '-6deg',
+ '-3': '-3deg',
+ '-2': '-2deg',
+ '-1': '-1deg',
+ 0: '0deg',
+ 1: '1deg',
+ 2: '2deg',
+ 3: '3deg',
+ 6: '6deg',
+ 12: '12deg',
+ 45: '45deg',
+ 90: '90deg',
+ 180: '180deg',
+ },
+ saturate: {
+ 0: '0',
+ 50: '.5',
+ 100: '1',
+ 150: '1.5',
+ 200: '2',
+ },
+ scale: {
+ 0: '0',
+ 50: '.5',
+ 75: '.75',
+ 90: '.9',
+ 95: '.95',
+ 100: '1',
+ 105: '1.05',
+ 110: '1.1',
+ 125: '1.25',
+ 150: '1.5',
+ },
+ screens: {
+ sm: '600px',
+ md: '960px',
+ lg: '1280px',
+ xl: '1920px',
+ print: { raw: 'print' },
+ },
+ scrollMargin: ({ theme }) => ({
+ ...theme('spacing'),
+ }),
+ scrollPadding: ({ theme }) => theme('spacing'),
+ sepia: {
+ 0: '0',
+ DEFAULT: '100%',
+ },
+ skew: {
+ '-12': '-12deg',
+ '-6': '-6deg',
+ '-3': '-3deg',
+ '-2': '-2deg',
+ '-1': '-1deg',
+ 0: '0deg',
+ 1: '1deg',
+ 2: '2deg',
+ 3: '3deg',
+ 6: '6deg',
+ 12: '12deg',
+ },
+ space: (theme, { negative }) => ({
+ ...theme('spacing'),
+ ...negative(theme('spacing')),
+ }),
+ spacing: {
+ xs: '32rem',
+ sm: '48rem',
+ md: '64rem',
+ lg: '80rem',
+ xl: '96rem',
+ '2xl': '65.6rem',
+ '3xl': '76.8rem',
+ '4xl': '89.6rem',
+ '5xl': '102.4rem',
+ '6xl': '115.2rem',
+ '7xl': '128rem',
+ px: '1px',
+ 0: '0px',
+ 0.5: '0.05rem',
+ 1: '0.1rem',
+ 1.5: '0.15rem',
+ 2: '0.2rem',
+ 2.5: '0.25rem',
+ 3: '0.3rem',
+ 3.5: '0.35rem',
+ 4: '0.4rem',
+ 5: '0.5rem',
+ 6: '0.6rem',
+ 7: '0.7rem',
+ 8: '0.8rem',
+ 9: '0.9rem',
+ 10: '1.0rem',
+ 11: '1.1rem',
+ 12: '1.2rem',
+ 14: '1.4rem',
+ 16: '1.6rem',
+ 20: '2rem',
+ 24: '2.4rem',
+ 28: '2.8rem',
+ 32: '3.2rem',
+ 36: '3.6rem',
+ 40: '4rem',
+ 44: '4.4rem',
+ 48: '4.8rem',
+ 52: '5.2rem',
+ 56: '5.6rem',
+ 60: '6rem',
+ 64: '6.4rem',
+ 68: '6.8rem',
+ 72: '7.2rem',
+ 76: '7.6rem',
+ 80: '8rem',
+ 84: '8.4rem',
+ 88: '8.8rem',
+ 92: '9.2rem',
+ 96: '9.6rem',
+ 112: '11.2rem',
+ 120: '12rem',
+ 128: '12.8rem',
+ 136: '13.6rem',
+ 144: '14.4rem',
+ 160: '16rem',
+ 192: '19.2rem',
+ 200: '20rem',
+ 208: '20.8rem',
+ 216: '21.6rem',
+ 224: '22.4rem',
+ 256: '25.6rem',
+ 288: '28.8rem',
+ 320: '32rem',
+ 360: '36rem',
+ 384: '38.4rem',
+ 400: '40rem',
+ 480: '48rem',
+ 512: '51.2rem',
+ 640: '64rem',
+ },
+ stroke: ({ theme }) => ({
+ none: 'none',
+ ...theme('colors'),
+ }),
+ strokeWidth: {
+ 0: '0',
+ 1: '1',
+ 2: '2',
+ },
+ supports: {},
+ data: {},
+ textColor: ({ theme }) => theme('colors'),
+ textDecorationColor: ({ theme }) => theme('colors'),
+ textDecorationThickness: {
+ auto: 'auto',
+ 'from-font': 'from-font',
+ 0: '0px',
+ 1: '1px',
+ 2: '2px',
+ 4: '4px',
+ 8: '8px',
+ },
+ textIndent: ({ theme }) => ({
+ ...theme('spacing'),
+ }),
+ textOpacity: ({ theme }) => theme('opacity'),
+ textUnderlineOffset: {
+ auto: 'auto',
+ 0: '0px',
+ 1: '1px',
+ 2: '2px',
+ 4: '4px',
+ 8: '8px',
+ },
+ transformOrigin: {
+ center: 'center',
+ top: 'top',
+ 'top-right': 'top right',
+ right: 'right',
+ 'bottom-right': 'bottom right',
+ bottom: 'bottom',
+ 'bottom-left': 'bottom left',
+ left: 'left',
+ 'top-left': 'top left',
+ },
+ transitionDelay: {
+ 0: '0s',
+ 75: '75ms',
+ 100: '100ms',
+ 150: '150ms',
+ 200: '200ms',
+ 300: '300ms',
+ 500: '500ms',
+ 700: '700ms',
+ 1000: '1000ms',
+ },
+ transitionDuration: {
+ DEFAULT: '150ms',
+ 0: '0s',
+ 75: '75ms',
+ 100: '100ms',
+ 150: '150ms',
+ 200: '200ms',
+ 300: '300ms',
+ 500: '500ms',
+ 700: '700ms',
+ 1000: '1000ms',
+ },
+ transitionProperty: {
+ none: 'none',
+ all: 'all',
+ DEFAULT:
+ 'color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter',
+ colors: 'color, background-color, border-color, text-decoration-color, fill, stroke',
+ opacity: 'opacity',
+ shadow: 'box-shadow',
+ transform: 'transform',
+ },
+ transitionTimingFunction: {
+ DEFAULT: 'cubic-bezier(0.4, 0, 0.2, 1)',
+ linear: 'linear',
+ in: 'cubic-bezier(0.4, 0, 1, 1)',
+ out: 'cubic-bezier(0, 0, 0.2, 1)',
+ 'in-out': 'cubic-bezier(0.4, 0, 0.2, 1)',
+ },
+ translate: (theme, { negative }) => ({
+ ...theme('spacing'),
+ ...negative(theme('spacing')),
+ '1/2': '50%',
+ '1/3': '33.333333%',
+ '2/3': '66.666667%',
+ '1/4': '25%',
+ '2/4': '50%',
+ '3/4': '75%',
+ full: '100%',
+ '-1/2': '-50%',
+ '-1/3': '-33.333333%',
+ '-2/3': '-66.666667%',
+ '-1/4': '-25%',
+ '-2/4': '-50%',
+ '-3/4': '-75%',
+ '-full': '-100%',
+ }),
+ width: ({ theme }) => ({
+ auto: 'auto',
+ ...theme('spacing'),
+ '1/2': '50%',
+ '1/3': '33.333333%',
+ '2/3': '66.666667%',
+ '1/4': '25%',
+ '2/4': '50%',
+ '3/4': '75%',
+ '1/5': '20%',
+ '2/5': '40%',
+ '3/5': '60%',
+ '4/5': '80%',
+ '1/6': '16.666667%',
+ '2/6': '33.333333%',
+ '3/6': '50%',
+ '4/6': '66.666667%',
+ '5/6': '83.333333%',
+ '1/12': '8.333333%',
+ '2/12': '16.666667%',
+ '3/12': '25%',
+ '4/12': '33.333333%',
+ '5/12': '41.666667%',
+ '6/12': '50%',
+ '7/12': '58.333333%',
+ '8/12': '66.666667%',
+ '9/12': '75%',
+ '10/12': '83.333333%',
+ '11/12': '91.666667%',
+ full: '100%',
+ screen: '100vw',
+ min: 'min-content',
+ max: 'max-content',
+ fit: 'fit-content',
+ }),
+ willChange: {
+ auto: 'auto',
+ scroll: 'scroll-position',
+ contents: 'contents',
+ transform: 'transform',
+ },
+ zIndex: {
+ auto: 'auto',
+ '-1': -1,
+ 0: '0',
+ 10: '10',
+ 20: '20',
+ 30: '30',
+ 40: '40',
+ 50: '50',
+ 99: '99',
+ 999: '999',
+ 9999: '9999',
+ },
+ extend: {
+ // @tailwindcss/typography
+ typography: ({ theme }) => ({
+ DEFAULT: {
+ css: {
+ fontSize: '1.4rem',
+ },
+ },
+ sm: {
+ css: {
+ fontSize: '1.2rem',
+ },
+ },
+ lg: {
+ css: {
+ fontSize: '1.6rem',
+ },
+ },
+ }),
+ },
+ },
+ variantOrder: [
+ 'first',
+ 'last',
+ 'odd',
+ 'even',
+ 'visited',
+ 'checked',
+ 'empty',
+ 'read-only',
+ 'group-hover',
+ 'group-focus',
+ 'focus-within',
+ 'hover',
+ 'focus',
+ 'focus-visible',
+ 'active',
+ 'disabled',
+ ],
+ plugins: [
+ // eslint-disable-next-line import/no-dynamic-require
+ require(path.resolve(__dirname, 'src/@fuse/tailwind/plugins/icon-size')),
+ // Other third party and/or custom plugins
+ require('@tailwindcss/typography')({ modifiers: ['sm', 'lg'] }),
+ require('@tailwindcss/aspect-ratio'),
+ ],
+};
+
+