mirror of
https://github.com/lingble/twenty.git
synced 2025-10-29 20:02:29 +00:00
Move frontend to Vite 5 (#2775)
* merge squashed
- A couple of CJS modules into ESM (config mostly)
- Vite complains about node.js modules: fixed `useIsMatchingLocation.ts`
> or use rollupOptions in vite.config.ts
> ref: f0e4f59d97/vite.config.js (L6)
- Adjust Storybook to work with Vite: use @storybook/test
- Use SWC for jest tranformations
- Remove unused deps:
- ts-jest: replaced with @swc/jest, typecheck by `tsc`
- babel plugins
- @svgr/plugin-jsx: not used
- @testing-library/user-event: handled by @storybook/test
- @typescript-eslint/utils: was not plugged in
- tsup, esbuild-plugin-svgr: will look into that later
- Install Vite required deps, and remove craco/webpack deps
- Adjust SVG to work with Vite as components
- Fixed `Step.tsx`: I dont know if one should be swaped for the other,
but there should be no slash
- Initial formating and linting:
- removed empty object params
- sorting imports, etc..
* prettier: fix pattern
* coverage: sb coverage report isnt working
* Add missing pieces
* `yarn lint --fix`
* fix: scripts permissions
* tsc: cut errors in half
* fix: remove `react-app-env.d.ts`
* tsc: all fixed, except `react-data-grid` types issue
* eslint: ignore env-config.js
* eslint: Align ci with config
* msw: bypass testing warnings
ref: https://stackoverflow.com/questions/68024935/msw-logging-warnings-for-unhandled-supertest-requests
* rebase: and fix things
* Adjust to current `graphql-codegen` no ESM support
* Remove vite plugin and use built-in methods
* rebase: and some fixes
* quick fix + `corepack use yarn@1.22.19`
* Fix build errors
---------
Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
2
.github/workflows/ci-front.yaml
vendored
2
.github/workflows/ci-front.yaml
vendored
@@ -145,7 +145,7 @@ jobs:
|
|||||||
- name: Front / Install Dependencies
|
- name: Front / Install Dependencies
|
||||||
run: cd front && yarn
|
run: cd front && yarn
|
||||||
- name: Front / Run linter
|
- name: Front / Run linter
|
||||||
run: cd front && yarn lint --config .eslintrc-ci.js
|
run: cd front && yarn lint --config .eslintrc-ci.cjs
|
||||||
front-jest:
|
front-jest:
|
||||||
needs: front-yarn-install
|
needs: front-yarn-install
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|||||||
8
.vscode/settings.json
vendored
8
.vscode/settings.json
vendored
@@ -38,5 +38,11 @@
|
|||||||
"cSpell.words": [
|
"cSpell.words": [
|
||||||
"twentyhq"
|
"twentyhq"
|
||||||
],
|
],
|
||||||
"typescript.preferences.importModuleSpecifier": "non-relative"
|
"typescript.preferences.importModuleSpecifier": "non-relative",
|
||||||
|
"[javascript][typescript][typescriptreact]": {
|
||||||
|
"editor.codeActionsOnSave": {
|
||||||
|
"source.fixAll.eslint": "explicit",
|
||||||
|
"source.addMissingImports": "always"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -8,7 +8,7 @@ module.exports = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
extends: [
|
extends: [
|
||||||
'./.eslintrc.js'
|
'./.eslintrc.cjs'
|
||||||
],
|
],
|
||||||
rules: {
|
rules: {
|
||||||
'no-console': 'error',
|
'no-console': 'error',
|
||||||
@@ -1,37 +1,118 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
parser: '@typescript-eslint/parser',
|
parser: '@typescript-eslint/parser',
|
||||||
parserOptions: {
|
|
||||||
project: 'tsconfig.json',
|
|
||||||
tsconfigRootDir: __dirname,
|
|
||||||
sourceType: 'module',
|
|
||||||
ecmaVersion: "2023"
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
'@typescript-eslint/eslint-plugin',
|
|
||||||
'unused-imports',
|
|
||||||
'simple-import-sort',
|
|
||||||
'prefer-arrow',
|
|
||||||
'import',
|
|
||||||
'twenty',
|
|
||||||
],
|
|
||||||
extends: [
|
|
||||||
'plugin:@typescript-eslint/recommended',
|
|
||||||
'plugin:prettier/recommended',
|
|
||||||
'plugin:storybook/recommended',
|
|
||||||
'plugin:react/recommended',
|
|
||||||
'plugin:react-hooks/recommended',
|
|
||||||
],
|
|
||||||
root: true,
|
root: true,
|
||||||
env: {
|
env: {
|
||||||
|
browser: true,
|
||||||
node: true,
|
node: true,
|
||||||
jest: true,
|
jest: true,
|
||||||
},
|
},
|
||||||
|
parserOptions: {
|
||||||
|
ecmaVersion: 'latest',
|
||||||
|
sourceType: 'module',
|
||||||
|
project: ['./tsconfig.json', './tsconfig.node.json'],
|
||||||
|
tsconfigRootDir: __dirname,
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
'@typescript-eslint/interface-name-prefix': 'off',
|
||||||
|
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||||
|
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||||
|
'@typescript-eslint/no-explicit-any': 'off',
|
||||||
|
'@typescript-eslint/no-unused-vars': 'off',
|
||||||
|
'simple-import-sort/imports': 'error',
|
||||||
|
'simple-import-sort/exports': 'error',
|
||||||
|
'twenty/effect-components': 'error',
|
||||||
|
'twenty/no-hardcoded-colors': 'error',
|
||||||
|
'twenty/matching-state-variable': 'error',
|
||||||
|
'twenty/component-props-naming': 'error',
|
||||||
|
'twenty/sort-css-properties-alphabetically': 'error',
|
||||||
|
'twenty/styled-components-prefixed-with-styled': 'error',
|
||||||
|
'twenty/no-state-useref': 'error',
|
||||||
|
'func-style': ['error', 'declaration', { allowArrowFunctions: true }],
|
||||||
|
'no-unused-vars': 'off',
|
||||||
|
'react/jsx-props-no-spreading': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
explicitSpread: 'ignore',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'react-hooks/exhaustive-deps': [
|
||||||
|
'warn',
|
||||||
|
{
|
||||||
|
additionalHooks: 'useRecoilCallback',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'unused-imports/no-unused-imports': 'warn',
|
||||||
|
'unused-imports/no-unused-vars': [
|
||||||
|
'warn',
|
||||||
|
{
|
||||||
|
vars: 'all',
|
||||||
|
varsIgnorePattern: '^_',
|
||||||
|
args: 'after-used',
|
||||||
|
argsIgnorePattern: '^_',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'no-restricted-imports': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
patterns: [
|
||||||
|
{
|
||||||
|
group: ['@tabler/icons-react'],
|
||||||
|
message: 'Icon imports are only allowed for `@/ui/icon`',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
group: ['react-hotkeys-web-hook'],
|
||||||
|
importNames: ['useHotkeys'],
|
||||||
|
message: 'Please use the custom wrapper: `useScopedHotkeys`',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'@typescript-eslint/consistent-type-imports': [
|
||||||
|
'error',
|
||||||
|
{ prefer: 'no-type-imports' },
|
||||||
|
],
|
||||||
|
'no-console': ['warn', { allow: ['group', 'groupCollapsed', 'groupEnd'] }],
|
||||||
|
// 'react-refresh/only-export-components': [
|
||||||
|
// 'warn',
|
||||||
|
// { allowConstantExport: true },
|
||||||
|
// ],
|
||||||
|
},
|
||||||
|
settings: {
|
||||||
|
react: {
|
||||||
|
version: 'detect',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
extends: [
|
||||||
|
'plugin:@typescript-eslint/recommended',
|
||||||
|
'eslint:recommended',
|
||||||
|
'plugin:react/recommended',
|
||||||
|
'plugin:react-hooks/recommended',
|
||||||
|
'plugin:prettier/recommended',
|
||||||
|
'plugin:storybook/recommended',
|
||||||
|
],
|
||||||
|
plugins: [
|
||||||
|
'@typescript-eslint/eslint-plugin',
|
||||||
|
'simple-import-sort',
|
||||||
|
'unused-imports',
|
||||||
|
'prefer-arrow',
|
||||||
|
'twenty',
|
||||||
|
'react-refresh',
|
||||||
|
],
|
||||||
|
ignorePatterns: [
|
||||||
|
'mockServiceWorker.js',
|
||||||
|
'**/generated*/*',
|
||||||
|
'.eslintrc.cjs',
|
||||||
|
'*.config.cjs',
|
||||||
|
'*.config.ts',
|
||||||
|
'*config.js',
|
||||||
|
'codegen*',
|
||||||
|
],
|
||||||
overrides: [
|
overrides: [
|
||||||
{
|
{
|
||||||
files: ['*.stories.tsx', '*.test.ts'],
|
files: ['*.stories.tsx', '*.test.ts'],
|
||||||
rules: {
|
rules: {
|
||||||
'no-console': 'off',
|
'no-console': 'off',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
files: ['*.js', '*.jsx', '*.ts', '*.tsx'],
|
files: ['*.js', '*.jsx', '*.ts', '*.tsx'],
|
||||||
@@ -43,7 +124,7 @@ module.exports = {
|
|||||||
'react/jsx-uses-react': 'off',
|
'react/jsx-uses-react': 'off',
|
||||||
'react/react-in-jsx-scope': 'off',
|
'react/react-in-jsx-scope': 'off',
|
||||||
'no-control-regex': 0,
|
'no-control-regex': 0,
|
||||||
'import/no-duplicates': ["error", {"considerQueryString": true}],
|
'no-undef': 'off',
|
||||||
'simple-import-sort/imports': [
|
'simple-import-sort/imports': [
|
||||||
'error',
|
'error',
|
||||||
{
|
{
|
||||||
@@ -53,76 +134,19 @@ module.exports = {
|
|||||||
['^\\u0000'],
|
['^\\u0000'],
|
||||||
['^\\.\\.(?!/?$)', '^\\.\\./?$'],
|
['^\\.\\.(?!/?$)', '^\\.\\./?$'],
|
||||||
['^\\./(?=.*/)(?!/?$)', '^\\.(?!/?$)', '^\\./?$'],
|
['^\\./(?=.*/)(?!/?$)', '^\\.(?!/?$)', '^\\./?$'],
|
||||||
['^.+\\.?(css)$']
|
['^.+\\.?(css)$'],
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
'prefer-arrow/prefer-arrow-functions': [
|
'prefer-arrow/prefer-arrow-functions': [
|
||||||
'error',
|
'error',
|
||||||
{
|
{
|
||||||
"disallowPrototype": true,
|
disallowPrototype: true,
|
||||||
"singleReturnOnly": false,
|
singleReturnOnly: false,
|
||||||
"classPropertiesAllowed": false
|
classPropertiesAllowed: false,
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
],
|
|
||||||
ignorePatterns: ['.eslintrc.js', 'codegen*.js', '**/generated*/*', '*.config.js'],
|
|
||||||
rules: {
|
|
||||||
'@typescript-eslint/interface-name-prefix': 'off',
|
|
||||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
|
||||||
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
|
||||||
'@typescript-eslint/no-explicit-any': 'off',
|
|
||||||
'simple-import-sort/imports': 'error',
|
|
||||||
'simple-import-sort/exports': 'error',
|
|
||||||
'twenty/effect-components': 'error',
|
|
||||||
'twenty/no-hardcoded-colors': 'error',
|
|
||||||
'twenty/matching-state-variable': 'error',
|
|
||||||
'twenty/component-props-naming': 'error',
|
|
||||||
'twenty/sort-css-properties-alphabetically': 'error',
|
|
||||||
'twenty/styled-components-prefixed-with-styled': 'error',
|
|
||||||
'twenty/no-state-useref': 'error',
|
|
||||||
'func-style':['error', 'declaration', { 'allowArrowFunctions': true }],
|
|
||||||
"@typescript-eslint/no-unused-vars": "off",
|
|
||||||
"no-unused-vars": "off",
|
|
||||||
"react/jsx-props-no-spreading": [
|
|
||||||
"error", {
|
|
||||||
"explicitSpread": "ignore",
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"react-hooks/exhaustive-deps": [
|
|
||||||
"warn", {
|
|
||||||
"additionalHooks": "useRecoilCallback"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"unused-imports/no-unused-imports": "warn",
|
|
||||||
"unused-imports/no-unused-vars": [
|
|
||||||
"warn",
|
|
||||||
{ "vars": "all", "varsIgnorePattern": "^_", "args": "after-used", "argsIgnorePattern": "^_" }
|
|
||||||
],
|
|
||||||
'no-restricted-imports': [
|
|
||||||
'error',
|
|
||||||
{
|
|
||||||
'patterns': [
|
|
||||||
{
|
|
||||||
'group': ['@tabler/icons-react'],
|
|
||||||
'message': 'Icon imports are only allowed for `@/ui/icon`',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'group': ['react-hotkeys-web-hook'],
|
|
||||||
"importNames": ["useHotkeys"],
|
|
||||||
'message': 'Please use the custom wrapper: `useScopedHotkeys`',
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
},
|
||||||
"@typescript-eslint/consistent-type-imports": ["error", { "prefer": "no-type-imports" }],
|
],
|
||||||
'no-console': ['warn', { allow: ['group', 'groupCollapsed', 'groupEnd'] }],
|
|
||||||
},
|
|
||||||
settings: {
|
|
||||||
"react": {
|
|
||||||
"version": "detect"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
30
front/.gitignore
vendored
30
front/.gitignore
vendored
@@ -1,7 +1,15 @@
|
|||||||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
# dependencies
|
# dependencies
|
||||||
/node_modules
|
/node_modules
|
||||||
|
/coverage*
|
||||||
/.pnp
|
/.pnp
|
||||||
.pnp.js
|
.pnp.js
|
||||||
|
|
||||||
@@ -12,16 +20,22 @@ build-storybook.log
|
|||||||
|
|
||||||
# production
|
# production
|
||||||
/build
|
/build
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
|
||||||
# misc
|
# env
|
||||||
.DS_Store
|
|
||||||
.env.local
|
.env.local
|
||||||
.env.development.local
|
.env.development.local
|
||||||
.env.test.local
|
.env.test.local
|
||||||
.env.production.local
|
.env.production.local
|
||||||
|
|
||||||
npm-debug.log*
|
# Editor directories and files
|
||||||
yarn-debug.log*
|
.vscode/*
|
||||||
yarn-error.log*
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
.nyc_output
|
.DS_Store
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
|
|||||||
3
front/.prettierignore
Normal file
3
front/.prettierignore
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
**/generated*/
|
||||||
|
*.lock
|
||||||
|
*.yaml
|
||||||
@@ -2,4 +2,4 @@
|
|||||||
"singleQuote": true,
|
"singleQuote": true,
|
||||||
"trailingComma": "all",
|
"trailingComma": "all",
|
||||||
"endOfLine": "auto"
|
"endOfLine": "auto"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,94 +0,0 @@
|
|||||||
const path = require('path');
|
|
||||||
|
|
||||||
computeStoriesGlob = () => {
|
|
||||||
if (process.env.STORYBOOK_SCOPE === 'pages') {
|
|
||||||
return [
|
|
||||||
'../src/pages/**/*.stories.@(js|jsx|ts|tsx)',
|
|
||||||
'../src/__stories__/*.stories.@(js|jsx|ts|tsx)',
|
|
||||||
'../src/pages/**/*.docs.mdx',
|
|
||||||
'../src/__stories__/*.docs.mdx'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
if (process.env.STORYBOOK_SCOPE === 'modules') {
|
|
||||||
return ['../src/modules/**/*.stories.@(js|jsx|ts|tsx)', '../src/modules/**/*.docs.mdx']
|
|
||||||
}
|
|
||||||
|
|
||||||
if (process.env.STORYBOOK_SCOPE === 'ui-docs') {
|
|
||||||
return ['../src/modules/ui/**/*.docs.mdx'];
|
|
||||||
}
|
|
||||||
|
|
||||||
return ['../src/**/*.stories.@(js|jsx|ts|tsx)', '../src/**/*.docs.mdx']
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
webpackFinal: (config) => {
|
|
||||||
config.module.rules.push({
|
|
||||||
test: /\.tsx?$/,
|
|
||||||
exclude: /node_modules/,
|
|
||||||
use: [
|
|
||||||
{
|
|
||||||
loader: require.resolve('babel-loader'),
|
|
||||||
options: {
|
|
||||||
presets: [
|
|
||||||
require('@babel/preset-typescript').default,
|
|
||||||
[
|
|
||||||
require('@babel/preset-react').default,
|
|
||||||
{
|
|
||||||
runtime: 'automatic',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
require('@babel/preset-env').default,
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
config.resolve.extensions.push('.ts', '.tsx');
|
|
||||||
config.module.rules.push({
|
|
||||||
test: /\.mjs$/,
|
|
||||||
include: /node_modules/,
|
|
||||||
type: 'javascript/auto',
|
|
||||||
});
|
|
||||||
config.module.rules.push({
|
|
||||||
test: /\.svg$/,
|
|
||||||
use: [
|
|
||||||
{
|
|
||||||
loader: '@svgr/webpack',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
loader: 'file-loader',
|
|
||||||
options: {
|
|
||||||
name: 'static/media/[path][name].[ext]',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
type: 'javascript/auto',
|
|
||||||
issuer: {
|
|
||||||
and: [/\.(ts|tsx|js|jsx|md|mdx)$/],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
config.resolve.extensions.push('.mjs');
|
|
||||||
config.resolve.alias = {
|
|
||||||
...config.resolve.alias,
|
|
||||||
'~': path.resolve(__dirname, '../src'),
|
|
||||||
'@': path.resolve(__dirname, '../src/modules'),
|
|
||||||
};
|
|
||||||
return config;
|
|
||||||
},
|
|
||||||
stories: computeStoriesGlob(),
|
|
||||||
addons: [
|
|
||||||
'@storybook/addon-links',
|
|
||||||
'@storybook/addon-essentials',
|
|
||||||
'@storybook/addon-interactions',
|
|
||||||
'@storybook/addon-coverage',
|
|
||||||
'@storybook/addon-styling',
|
|
||||||
'storybook-addon-pseudo-states',
|
|
||||||
'storybook-addon-cookie',
|
|
||||||
],
|
|
||||||
docs: { autodocs: false },
|
|
||||||
framework: {
|
|
||||||
name: '@storybook/react-webpack5',
|
|
||||||
options: {},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
45
front/.storybook/main.ts
Normal file
45
front/.storybook/main.ts
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import type { StorybookConfig } from '@storybook/react-vite';
|
||||||
|
|
||||||
|
const computeStoriesGlob = () => {
|
||||||
|
if (process.env.STORYBOOK_SCOPE === 'pages') {
|
||||||
|
return [
|
||||||
|
'../src/pages/**/*.stories.@(js|jsx|ts|tsx)',
|
||||||
|
'../src/__stories__/*.stories.@(js|jsx|ts|tsx)',
|
||||||
|
'../src/pages/**/*.docs.mdx',
|
||||||
|
'../src/__stories__/*.docs.mdx'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.env.STORYBOOK_SCOPE === 'modules') {
|
||||||
|
return ['../src/modules/**/*.stories.@(js|jsx|ts|tsx)', '../src/modules/**/*.docs.mdx']
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.env.STORYBOOK_SCOPE === 'ui-docs') {
|
||||||
|
return ['../src/modules/ui/**/*.docs.mdx'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return ['../src/**/*.docs.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)']
|
||||||
|
};
|
||||||
|
|
||||||
|
const config: StorybookConfig = {
|
||||||
|
stories: computeStoriesGlob(),
|
||||||
|
staticDirs: ['../public'],
|
||||||
|
addons: [
|
||||||
|
'@storybook/addon-links',
|
||||||
|
'@storybook/addon-essentials',
|
||||||
|
'@storybook/addon-onboarding',
|
||||||
|
'@storybook/addon-interactions',
|
||||||
|
'@storybook/addon-coverage',
|
||||||
|
'@storybook/addon-themes',
|
||||||
|
'storybook-addon-cookie',
|
||||||
|
'storybook-addon-pseudo-states',
|
||||||
|
],
|
||||||
|
framework: {
|
||||||
|
name: '@storybook/react-vite',
|
||||||
|
options: {},
|
||||||
|
},
|
||||||
|
docs: {
|
||||||
|
autodocs: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
export default config;
|
||||||
@@ -2,7 +2,12 @@
|
|||||||
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap"
|
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap"
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/iframe-resizer/4.3.7/iframeResizer.contentWindow.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/iframe-resizer/4.3.7/iframeResizer.contentWindow.min.js"></script>
|
||||||
|
<!-- <script>
|
||||||
|
window.global = window;
|
||||||
|
</script> -->
|
||||||
|
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|||||||
@@ -1,18 +1,19 @@
|
|||||||
import { initialize, mswLoader } from 'msw-storybook-addon';
|
|
||||||
import { Preview } from '@storybook/react';
|
|
||||||
import { ThemeProvider } from '@emotion/react';
|
import { ThemeProvider } from '@emotion/react';
|
||||||
import { withThemeFromJSXProvider } from '@storybook/addon-styling';
|
import { Preview, ReactRenderer } from '@storybook/react';
|
||||||
import { lightTheme, darkTheme } from '../src/modules/ui/theme/constants/theme';
|
import { withThemeFromJSXProvider } from "@storybook/addon-themes";
|
||||||
import { RootDecorator } from '../src/testing/decorators/RootDecorator';
|
import { initialize, mswLoader } from 'msw-storybook-addon';
|
||||||
import 'react-loading-skeleton/dist/skeleton.css';
|
|
||||||
import { mockedUserJWT } from '../src/testing/mock-data/jwt';
|
|
||||||
import { rest } from 'msw'
|
|
||||||
|
|
||||||
initialize();
|
import { RootDecorator } from '../src/testing/decorators/RootDecorator';
|
||||||
|
import { mockedUserJWT } from '../src/testing/mock-data/jwt';
|
||||||
|
|
||||||
|
import { lightTheme, darkTheme } from '../src/modules/ui/theme/constants/theme';
|
||||||
|
import 'react-loading-skeleton/dist/skeleton.css';
|
||||||
|
|
||||||
|
initialize({ onUnhandledRequest: 'bypass' });
|
||||||
|
|
||||||
const preview: Preview = {
|
const preview: Preview = {
|
||||||
decorators: [
|
decorators: [
|
||||||
withThemeFromJSXProvider({
|
withThemeFromJSXProvider<ReactRenderer>({
|
||||||
themes: {
|
themes: {
|
||||||
light: lightTheme,
|
light: lightTheme,
|
||||||
dark: darkTheme,
|
dark: darkTheme,
|
||||||
@@ -30,16 +31,16 @@ const preview: Preview = {
|
|||||||
date: /Date$/,
|
date: /Date$/,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
cookie: {
|
|
||||||
tokenPair: `{%22accessToken%22:{%22token%22:%22${mockedUserJWT}%22%2C%22expiresAt%22:%222023-07-18T15:06:40.704Z%22%2C%22__typename%22:%22AuthToken%22}%2C%22refreshToken%22:{%22token%22:%22${mockedUserJWT}%22%2C%22expiresAt%22:%222023-10-15T15:06:41.558Z%22%2C%22__typename%22:%22AuthToken%22}%2C%22__typename%22:%22AuthTokenPair%22}`,
|
|
||||||
},
|
|
||||||
options: {
|
options: {
|
||||||
storySort: {
|
storySort: {
|
||||||
order: ['UI', 'Modules', 'Pages'],
|
order: ['UI', 'Modules', 'Pages'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
cookie: {
|
||||||
|
tokenPair: `{%22accessToken%22:{%22token%22:%22${mockedUserJWT}%22%2C%22expiresAt%22:%222023-07-18T15:06:40.704Z%22%2C%22__typename%22:%22AuthToken%22}%2C%22refreshToken%22:{%22token%22:%22${mockedUserJWT}%22%2C%22expiresAt%22:%222023-10-15T15:06:41.558Z%22%2C%22__typename%22:%22AuthToken%22}%2C%22__typename%22:%22AuthTokenPair%22}`,
|
||||||
|
},
|
||||||
|
loaders: [mswLoader],
|
||||||
},
|
},
|
||||||
loaders: [mswLoader],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default preview;
|
export default preview;
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
const { getJestConfig } = require('@storybook/test-runner');
|
import { getJestConfig } from "@storybook/test-runner";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {import('@jest/types').Config.InitialOptions}
|
* @type {import('@jest/types').Config.InitialOptions}
|
||||||
*/
|
*/
|
||||||
module.exports = {
|
export default {
|
||||||
// The default configuration comes from @storybook/test-runner
|
// The default configuration comes from @storybook/test-runner
|
||||||
...getJestConfig(),
|
...getJestConfig(),
|
||||||
/** Add your own overrides below
|
/** Add your own overrides below
|
||||||
* @see https://jestjs.io/docs/configuration
|
* @see https://jestjs.io/docs/configuration
|
||||||
*/
|
*/
|
||||||
testTimeout: process.env.STORYBOOK_SCOPE=== 'pages' ? 60000 : 15000,
|
testTimeout: process.env.STORYBOOK_SCOPE === 'pages' ? 60000 : 15000,
|
||||||
};
|
};
|
||||||
31
front/.swcrc
Normal file
31
front/.swcrc
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"jsc": {
|
||||||
|
"target": "es2017",
|
||||||
|
"parser": {
|
||||||
|
"syntax": "typescript",
|
||||||
|
"tsx": true,
|
||||||
|
"decorators": false,
|
||||||
|
"dynamicImport": false
|
||||||
|
},
|
||||||
|
"transform": {
|
||||||
|
"react": {
|
||||||
|
"pragma": "React.createElement",
|
||||||
|
"pragmaFrag": "React.Fragment",
|
||||||
|
"throwIfNamespace": true,
|
||||||
|
"development": false,
|
||||||
|
"useBuiltins": false,
|
||||||
|
"runtime": "automatic"
|
||||||
|
},
|
||||||
|
"hidden": {
|
||||||
|
"jest": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"module": {
|
||||||
|
"type": "commonjs",
|
||||||
|
"strict": false,
|
||||||
|
"strictMode": true,
|
||||||
|
"lazy": false,
|
||||||
|
"noInterop": false
|
||||||
|
}
|
||||||
|
}
|
||||||
1
front/README.md
Normal file
1
front/README.md
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Run `yarn dev` while server running on port `3000`
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
const path = require("path");
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
devServer: {
|
|
||||||
client: {
|
|
||||||
overlay: {
|
|
||||||
runtimeErrors: (error) => {
|
|
||||||
switch (error.message) {
|
|
||||||
case "ResizeObserver loop limit exceeded":
|
|
||||||
case "Unauthenticated":
|
|
||||||
return false;
|
|
||||||
default:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
webpack: {
|
|
||||||
alias: {
|
|
||||||
'~': path.resolve(__dirname, 'src'),
|
|
||||||
'@': path.resolve(__dirname, 'src/modules'),
|
|
||||||
'@testing': path.resolve(__dirname, 'src/testing'),
|
|
||||||
},
|
|
||||||
// TODO: remove this workaround by resolving source map errors with @sniptt/guards
|
|
||||||
configure: {
|
|
||||||
module: {
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
test: /\.js$/,
|
|
||||||
enforce: "pre",
|
|
||||||
use: ["source-map-loader"],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
ignoreWarnings: [/Failed to parse source map/],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
jest: {
|
|
||||||
configure: {
|
|
||||||
moduleNameMapper: {
|
|
||||||
'~/(.+)': "<rootDir>/src/$1",
|
|
||||||
'@/(.+)': "<rootDir>/src/modules/$1",
|
|
||||||
'@testing/(.+)': "<rootDir>/src/testing/$1",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@@ -1,23 +1,18 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="UTF-8" />
|
||||||
<link
|
|
||||||
rel="icon"
|
<link rel="icon" href="/icons/android/android-launchericon-48-48.png" />
|
||||||
href="%PUBLIC_URL%/icons/android/android-launchericon-48-48.png"
|
<link rel="apple-touch-icon" href="/icons/ios/192.png" />
|
||||||
/>
|
|
||||||
<link
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
rel="apple-touch-icon"
|
|
||||||
href="%PUBLIC_URL%/icons/ios/icon-192x192.png"
|
|
||||||
/>
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
||||||
<meta name="theme-color" content="#000000" />
|
<meta name="theme-color" content="#000000" />
|
||||||
<meta name="description" content="A modern open-source CRM" />
|
<meta name="description" content="A modern open-source CRM" />
|
||||||
<meta
|
<meta
|
||||||
property="og:image"
|
property="og:image"
|
||||||
content="https://raw.githubusercontent.com/twentyhq/twenty/main/docs/static/img/social-card.png"
|
content="https://raw.githubusercontent.com/twentyhq/twenty/main/docs/static/img/social-card.png"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<meta property="og:description" content="A modern open-source CRM" />
|
<meta property="og:description" content="A modern open-source CRM" />
|
||||||
<meta property="og:title" content="Twenty" />
|
<meta property="og:title" content="Twenty" />
|
||||||
<meta name="twitter:card" content="summary_large_image" />
|
<meta name="twitter:card" content="summary_large_image" />
|
||||||
@@ -28,18 +23,17 @@
|
|||||||
|
|
||||||
<meta name="twitter:description" content="A modern open-source CRM" />
|
<meta name="twitter:description" content="A modern open-source CRM" />
|
||||||
<meta name="twitter:title" content="Twenty" />
|
<meta name="twitter:title" content="Twenty" />
|
||||||
|
|
||||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
|
||||||
<link
|
<link
|
||||||
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap"
|
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
|
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<title>Twenty</title>
|
<title>Twenty</title>
|
||||||
<script src="%PUBLIC_URL%/env-config.js"></script>
|
<script src="/env-config.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
|
<script type="module" src="/src/index.tsx"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -1,5 +1,17 @@
|
|||||||
const { createJestConfig } = require("@craco/craco");
|
export default {
|
||||||
const cracoConfig = require("./craco.config.js");
|
setupFilesAfterEnv: ["./src/setupTests.ts"],
|
||||||
const jestConfig = createJestConfig(cracoConfig);
|
testEnvironment: "jsdom",
|
||||||
|
transform: {
|
||||||
module.exports = jestConfig;
|
"^.+\\.(ts|js|tsx|jsx)$": "@swc/jest",
|
||||||
|
},
|
||||||
|
moduleNameMapper: {
|
||||||
|
'~/(.+)': "<rootDir>/src/$1",
|
||||||
|
'@/(.+)': "<rootDir>/src/modules/$1",
|
||||||
|
'@testing/(.+)': "<rootDir>/src/testing/$1",
|
||||||
|
},
|
||||||
|
extensionsToTreatAsEsm: ['.ts', '.tsx'],
|
||||||
|
// collectCoverage: true,
|
||||||
|
// collectCoverageFrom: ['<rootDir>/src/**/*.{ts,tsx}'],
|
||||||
|
// coveragePathIgnorePatterns: ['(tests/.*.mock).(jsx?|tsx?)$', '(.*).d.ts$'],
|
||||||
|
// coverageDirectory: '<rootDir>/coverage/',
|
||||||
|
}
|
||||||
@@ -26,10 +26,10 @@ const pagesCoverage = {
|
|||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const storybookStoriesFolders = process.env.STORYBOOK_SCOPE;
|
const storybookStoriesFolders = process.env.STORYBOOK_SCOPE;
|
||||||
|
|
||||||
module.exports = storybookStoriesFolders === 'pages' ?
|
module.exports = storybookStoriesFolders === 'pages'
|
||||||
pagesCoverage : storybookStoriesFolders === 'modules' ? modulesCoverage
|
? pagesCoverage
|
||||||
: globalCoverage;
|
: storybookStoriesFolders === 'modules'
|
||||||
|
? modulesCoverage
|
||||||
|
: globalCoverage;
|
||||||
@@ -2,6 +2,37 @@
|
|||||||
"name": "twenty",
|
"name": "twenty",
|
||||||
"version": "0.2.1",
|
"version": "0.2.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"dev:clean": "yarn dev --force",
|
||||||
|
"build": "tsc && vite build && yarn build:inject-runtime-env",
|
||||||
|
"build:inject-runtime-env": "./scripts/inject-runtime-env.sh",
|
||||||
|
"preview": "vite preview",
|
||||||
|
"eslint-plugin:setup": "cd ../packages/eslint-plugin-twenty/ && yarn && yarn build && cd ../../front/ && yarn upgrade eslint-plugin-twenty",
|
||||||
|
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
||||||
|
"fmt:fix": "prettier --cache --write \"src/**/*.ts\" \"src/**/*.tsx\"",
|
||||||
|
"fmt": "prettier --check \"src/**/*.ts\" \"src/**/*.tsx\"",
|
||||||
|
"test": "jest",
|
||||||
|
"coverage": "jest --coverage",
|
||||||
|
"storybook:modules:dev": "STORYBOOK_SCOPE=modules yarn storybook:dev",
|
||||||
|
"storybook:dev": "storybook dev -p 6006 --no-open",
|
||||||
|
"storybook:pages:dev": "STORYBOOK_SCOPE=pages yarn storybook:dev",
|
||||||
|
"storybook:docs:dev": "STORYBOOK_SCOPE=ui-docs yarn storybook:dev",
|
||||||
|
"storybook:build": "storybook build",
|
||||||
|
"storybook:modules:build": "STORYBOOK_SCOPE=modules yarn storybook:build",
|
||||||
|
"storybook:pages:build": "STORYBOOK_SCOPE=pages yarn storybook:build",
|
||||||
|
"storybook:docs:build": "STORYBOOK_SCOPE=ui-docs yarn storybook:build",
|
||||||
|
"storybook:test": "test-storybook",
|
||||||
|
"storybook:test-slow": "test-storybook --maxWorkers=3",
|
||||||
|
"storybook:coverage": "yarn storybook:test-slow --coverage && npx nyc report --reporter=lcov -t coverage/storybook --report-dir coverage/storybook --check-coverage",
|
||||||
|
"storybook:modules:coverage": "STORYBOOK_SCOPE=modules yarn storybook:coverage",
|
||||||
|
"storybook:pages:coverage": "STORYBOOK_SCOPE=pages yarn storybook:coverage",
|
||||||
|
"graphql:data:generate": "dotenv cross-var graphql-codegen -- --config codegen.cjs",
|
||||||
|
"graphql:metadata:generate": "dotenv cross-var graphql-codegen -- --config codegen-metadata.cjs",
|
||||||
|
"chromatic": "dotenv cross-var npx chromatic --project-token=$CHROMATIC_PROJECT_TOKEN",
|
||||||
|
"install": "yarn eslint-plugin:setup"
|
||||||
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@air/react-drag-to-select": "^5.0.8",
|
"@air/react-drag-to-select": "^5.0.8",
|
||||||
"@apollo/client": "^3.7.17",
|
"@apollo/client": "^3.7.17",
|
||||||
@@ -15,11 +46,9 @@
|
|||||||
"@hello-pangea/dnd": "^16.2.0",
|
"@hello-pangea/dnd": "^16.2.0",
|
||||||
"@hookform/resolvers": "^3.1.1",
|
"@hookform/resolvers": "^3.1.1",
|
||||||
"@sniptt/guards": "^0.2.0",
|
"@sniptt/guards": "^0.2.0",
|
||||||
|
"@swc/core": "^1.3.100",
|
||||||
|
"@swc/jest": "^0.2.29",
|
||||||
"@tabler/icons-react": "^2.30.0",
|
"@tabler/icons-react": "^2.30.0",
|
||||||
"@types/node": "^16.18.4",
|
|
||||||
"@types/react": "^18.0.25",
|
|
||||||
"@types/react-dom": "^18.0.9",
|
|
||||||
"@types/react-helmet-async": "^1.0.3",
|
|
||||||
"afterframe": "^1.0.2",
|
"afterframe": "^1.0.2",
|
||||||
"apollo-upload-client": "^17.0.0",
|
"apollo-upload-client": "^17.0.0",
|
||||||
"date-fns": "^2.30.0",
|
"date-fns": "^2.30.0",
|
||||||
@@ -57,43 +86,79 @@
|
|||||||
"ts-key-enum": "^2.0.12",
|
"ts-key-enum": "^2.0.12",
|
||||||
"type-fest": "^4.1.0",
|
"type-fest": "^4.1.0",
|
||||||
"uuid": "^9.0.0",
|
"uuid": "^9.0.0",
|
||||||
|
"vite-tsconfig-paths": "^4.2.1",
|
||||||
"xlsx-ugnis": "^0.19.3",
|
"xlsx-ugnis": "^0.19.3",
|
||||||
"zod": "^3.22.2"
|
"zod": "^3.22.2"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"devDependencies": {
|
||||||
"start": "PORT=3001 craco start --max-warnings=0",
|
"@graphql-codegen/cli": "^3.3.1",
|
||||||
"build:inject-runtime-env": "./scripts/inject-runtime-env.sh",
|
"@graphql-codegen/client-preset": "^4.1.0",
|
||||||
"build": "craco build && yarn build:inject-runtime-env",
|
"@graphql-codegen/typescript": "^3.0.4",
|
||||||
"test": "craco test",
|
"@graphql-codegen/typescript-operations": "^3.0.4",
|
||||||
"coverage": "craco test --coverage .",
|
"@graphql-codegen/typescript-react-apollo": "^3.3.7",
|
||||||
"lint": "eslint src --max-warnings=0",
|
"@storybook/addon-actions": "^7.6.3",
|
||||||
"eslint-plugin:setup": "cd ../packages/eslint-plugin-twenty/ && yarn && yarn build && cd ../../front/ && yarn upgrade eslint-plugin-twenty",
|
"@storybook/addon-coverage": "^1.0.0",
|
||||||
"storybook:dev": "storybook dev -p 6006 -s ../public",
|
"@storybook/addon-essentials": "^7.6.3",
|
||||||
"storybook:test": "test-storybook",
|
"@storybook/addon-interactions": "^7.6.3",
|
||||||
"storybook:test-slow": "test-storybook --maxWorkers=3",
|
"@storybook/addon-links": "^7.6.3",
|
||||||
"storybook:build": "storybook build -s public",
|
"@storybook/addon-onboarding": "^1.0.9",
|
||||||
"storybook:coverage": "test-storybook --coverage --maxWorkers=3 && npx nyc report --reporter=lcov -t coverage/storybook --report-dir coverage/storybook --check-coverage",
|
"@storybook/addon-themes": "^7.6.3",
|
||||||
"storybook:modules:dev": "STORYBOOK_SCOPE=modules yarn storybook:dev",
|
"@storybook/blocks": "^7.6.3",
|
||||||
"storybook:pages:dev": "STORYBOOK_SCOPE=pages yarn storybook:dev",
|
"@storybook/react": "^7.6.3",
|
||||||
"storybook:docs:dev": "STORYBOOK_SCOPE=ui-docs yarn storybook:dev",
|
"@storybook/react-vite": "^7.6.3",
|
||||||
"storybook:modules:build": "STORYBOOK_SCOPE=modules yarn storybook:build",
|
"@storybook/test": "^7.6.3",
|
||||||
"storybook:pages:build": "STORYBOOK_SCOPE=pages yarn storybook:build",
|
"@storybook/test-runner": "^0.16.0",
|
||||||
"storybook:docs:build": "STORYBOOK_SCOPE=ui-docs yarn storybook:build",
|
"@testing-library/jest-dom": "^6.1.5",
|
||||||
"storybook:modules:coverage": "STORYBOOK_SCOPE=modules yarn storybook:coverage",
|
"@testing-library/react": "^13.4.0",
|
||||||
"storybook:pages:coverage": "STORYBOOK_SCOPE=pages yarn storybook:coverage",
|
"@types/apollo-upload-client": "^17.0.2",
|
||||||
"graphql:data:generate": "dotenv cross-var graphql-codegen -- --config codegen.js",
|
"@types/deep-equal": "^1.0.1",
|
||||||
"graphql:metadata:generate": "dotenv cross-var graphql-codegen -- --config codegen-metadata.js",
|
"@types/jest": "^29.5.10",
|
||||||
"chromatic": "dotenv cross-var npx chromatic --project-token=$CHROMATIC_PROJECT_TOKEN",
|
"@types/js-cookie": "^3.0.3",
|
||||||
"install": "yarn eslint-plugin:setup"
|
"@types/lodash.camelcase": "^4.3.7",
|
||||||
|
"@types/lodash.debounce": "^4.0.7",
|
||||||
|
"@types/lodash.kebabcase": "^4.1.7",
|
||||||
|
"@types/lodash.snakecase": "^4.1.9",
|
||||||
|
"@types/luxon": "^3.3.0",
|
||||||
|
"@types/node": "^20.10.0",
|
||||||
|
"@types/react": "^18.2.39",
|
||||||
|
"@types/react-datepicker": "^4.11.2",
|
||||||
|
"@types/react-dom": "^18.2.15",
|
||||||
|
"@types/scroll-into-view": "^1.16.0",
|
||||||
|
"@types/uuid": "^9.0.1",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^6.10.0",
|
||||||
|
"@typescript-eslint/parser": "^6.10.0",
|
||||||
|
"@vitejs/plugin-react-swc": "^3.5.0",
|
||||||
|
"chromatic": "^6.18.0",
|
||||||
|
"concurrently": "^8.0.1",
|
||||||
|
"cross-var": "^1.1.0",
|
||||||
|
"dotenv-cli": "^7.2.1",
|
||||||
|
"eslint": "^8.53.0",
|
||||||
|
"eslint-config-prettier": "^9.0.0",
|
||||||
|
"eslint-plugin-prefer-arrow": "^1.2.3",
|
||||||
|
"eslint-plugin-prettier": "^5.0.1",
|
||||||
|
"eslint-plugin-react": "^7.33.2",
|
||||||
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
|
"eslint-plugin-react-refresh": "^0.4.4",
|
||||||
|
"eslint-plugin-simple-import-sort": "^10.0.0",
|
||||||
|
"eslint-plugin-storybook": "^0.6.15",
|
||||||
|
"eslint-plugin-twenty": "file:../packages/eslint-plugin-twenty",
|
||||||
|
"eslint-plugin-unused-imports": "^3.0.0",
|
||||||
|
"http-server": "^14.1.1",
|
||||||
|
"jest": "29.7.0",
|
||||||
|
"jest-environment-jsdom": "29.7.0",
|
||||||
|
"msw": "1.3.2",
|
||||||
|
"msw-storybook-addon": "^1.10.0",
|
||||||
|
"prettier": "^3.1.0",
|
||||||
|
"storybook": "^7.6.3",
|
||||||
|
"storybook-addon-cookie": "^3.1.0",
|
||||||
|
"storybook-addon-pseudo-states": "^2.1.2",
|
||||||
|
"typescript": "^5.2.2",
|
||||||
|
"vite": "^5.0.0",
|
||||||
|
"vite-plugin-svgr": "^4.2.0"
|
||||||
},
|
},
|
||||||
"overrides": {
|
"engines": {
|
||||||
"react-refresh": "0.14.0"
|
"node": "^18.16.0",
|
||||||
},
|
"npm": "please-use-yarn"
|
||||||
"jest": {
|
|
||||||
"testMatch": [
|
|
||||||
"<rootDir>/**/*.test.ts",
|
|
||||||
"<rootDir>/**/*.test.tsx"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"browserslist": {
|
"browserslist": {
|
||||||
"production": [
|
"production": [
|
||||||
@@ -107,76 +172,8 @@
|
|||||||
"last 1 safari version"
|
"last 1 safari version"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
|
||||||
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
|
||||||
"@craco/craco": "^7.1.0",
|
|
||||||
"@graphql-codegen/cli": "^3.3.1",
|
|
||||||
"@graphql-codegen/client-preset": "^4.1.0",
|
|
||||||
"@graphql-codegen/typescript": "^3.0.4",
|
|
||||||
"@graphql-codegen/typescript-operations": "^3.0.4",
|
|
||||||
"@graphql-codegen/typescript-react-apollo": "^3.3.7",
|
|
||||||
"@storybook/addon-actions": "^7.0.22",
|
|
||||||
"@storybook/addon-coverage": "^0.0.8",
|
|
||||||
"@storybook/addon-essentials": "^7.0.22",
|
|
||||||
"@storybook/addon-interactions": "^7.0.22",
|
|
||||||
"@storybook/addon-links": "^7.0.22",
|
|
||||||
"@storybook/addon-styling": "^1.3.0",
|
|
||||||
"@storybook/jest": "^0.1.0",
|
|
||||||
"@storybook/node-logger": "^7.0.22",
|
|
||||||
"@storybook/react": "^7.0.22",
|
|
||||||
"@storybook/react-webpack5": "^7.0.22",
|
|
||||||
"@storybook/test-runner": "^0.10.0",
|
|
||||||
"@storybook/testing-library": "^0.1.0",
|
|
||||||
"@svgr/plugin-jsx": "^8.1.0",
|
|
||||||
"@svgr/webpack": "^8.0.1",
|
|
||||||
"@testing-library/jest-dom": "^5.16.5",
|
|
||||||
"@testing-library/react": "^13.4.0",
|
|
||||||
"@testing-library/user-event": "^13.5.0",
|
|
||||||
"@types/apollo-upload-client": "^17.0.2",
|
|
||||||
"@types/deep-equal": "^1.0.1",
|
|
||||||
"@types/jest": "^27.5.2",
|
|
||||||
"@types/js-cookie": "^3.0.3",
|
|
||||||
"@types/lodash.camelcase": "^4.3.7",
|
|
||||||
"@types/lodash.debounce": "^4.0.7",
|
|
||||||
"@types/lodash.kebabcase": "^4.1.7",
|
|
||||||
"@types/lodash.snakecase": "^4.1.9",
|
|
||||||
"@types/luxon": "^3.3.0",
|
|
||||||
"@types/react-datepicker": "^4.11.2",
|
|
||||||
"@types/scroll-into-view": "^1.16.0",
|
|
||||||
"@types/uuid": "^9.0.1",
|
|
||||||
"@typescript-eslint/eslint-plugin": "^6.7.5",
|
|
||||||
"@typescript-eslint/parser": "^6.7.5",
|
|
||||||
"@typescript-eslint/utils": "^6.7.0",
|
|
||||||
"babel-plugin-named-exports-order": "^0.0.2",
|
|
||||||
"chromatic": "^6.18.0",
|
|
||||||
"concurrently": "^8.0.1",
|
|
||||||
"cross-var": "^1.1.0",
|
|
||||||
"dotenv-cli": "^7.2.1",
|
|
||||||
"esbuild-plugin-svgr": "^2.1.0",
|
|
||||||
"eslint": "^8.28.0",
|
|
||||||
"eslint-config-prettier": "^8.5.0",
|
|
||||||
"eslint-config-standard-with-typescript": "^23.0.0",
|
|
||||||
"eslint-plugin-prefer-arrow": "^1.2.3",
|
|
||||||
"eslint-plugin-prettier": "^4.2.1",
|
|
||||||
"eslint-plugin-react": "^7.31.11",
|
|
||||||
"eslint-plugin-simple-import-sort": "^10.0.0",
|
|
||||||
"eslint-plugin-storybook": "^0.6.12",
|
|
||||||
"eslint-plugin-twenty": "file:../packages/eslint-plugin-twenty",
|
|
||||||
"eslint-plugin-unused-imports": "^3.0.0",
|
|
||||||
"http-server": "^14.1.1",
|
|
||||||
"msw": "1.3.2",
|
|
||||||
"msw-storybook-addon": "^1.10.0",
|
|
||||||
"prettier": "^2.8.0",
|
|
||||||
"react-scripts": "5.0.1",
|
|
||||||
"storybook": "^7.0.22",
|
|
||||||
"storybook-addon-cookie": "^3.0.1",
|
|
||||||
"storybook-addon-pseudo-states": "^2.1.0",
|
|
||||||
"ts-jest": "^29.1.0",
|
|
||||||
"tsup": "^7.2.0",
|
|
||||||
"typescript": "^5.2.2",
|
|
||||||
"webpack": "^5.75.0"
|
|
||||||
},
|
|
||||||
"msw": {
|
"msw": {
|
||||||
"workerDirectory": "public"
|
"workerDirectory": "public"
|
||||||
}
|
},
|
||||||
}
|
"packageManager": "yarn@1.22.19+sha256.732620bac8b1690d507274f025f3c6cfdc3627a84d9642e38a07452cc00e0f2e"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
window._env_ = {
|
window._env_ = {
|
||||||
// This file should stay empty. It will be overwritten by the build process.
|
// This file should stay empty. It will be overwritten by the build process.
|
||||||
}
|
}
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
# https://www.robotstxt.org/robotstxt.html
|
|
||||||
User-agent: *
|
|
||||||
Disallow: /
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import { matchPath, useLocation } from 'react-router-dom';
|
import { matchPath, useLocation } from 'react-router-dom';
|
||||||
import { parse } from 'url';
|
|
||||||
|
|
||||||
import { AppBasePath } from '@/types/AppBasePath';
|
import { AppBasePath } from '@/types/AppBasePath';
|
||||||
|
|
||||||
@@ -10,7 +9,7 @@ export const useIsMatchingLocation = () => {
|
|||||||
return useCallback(
|
return useCallback(
|
||||||
(path: string, basePath?: AppBasePath) => {
|
(path: string, basePath?: AppBasePath) => {
|
||||||
const constructedPath = basePath
|
const constructedPath = basePath
|
||||||
? parse(`${basePath}/${path}`).pathname ?? ''
|
? new URL(basePath + path, document.location.origin).pathname ?? ''
|
||||||
: path;
|
: path;
|
||||||
|
|
||||||
return !!matchPath(constructedPath, location.pathname);
|
return !!matchPath(constructedPath, location.pathname);
|
||||||
|
|||||||
@@ -26,9 +26,7 @@ import '@emotion/react';
|
|||||||
import './index.css';
|
import './index.css';
|
||||||
import 'react-loading-skeleton/dist/skeleton.css';
|
import 'react-loading-skeleton/dist/skeleton.css';
|
||||||
|
|
||||||
const root = ReactDOM.createRoot(
|
const root = ReactDOM.createRoot(document.getElementById('root')!);
|
||||||
document.getElementById('root') as HTMLElement,
|
|
||||||
);
|
|
||||||
|
|
||||||
root.render(
|
root.render(
|
||||||
<RecoilRoot>
|
<RecoilRoot>
|
||||||
@@ -68,6 +66,5 @@ root.render(
|
|||||||
);
|
);
|
||||||
|
|
||||||
declare module '@emotion/react' {
|
declare module '@emotion/react' {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
|
||||||
export interface Theme extends ThemeType {}
|
export interface Theme extends ThemeType {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable no-loop-func */
|
|
||||||
import {
|
import {
|
||||||
ApolloClient,
|
ApolloClient,
|
||||||
ApolloClientOptions,
|
ApolloClientOptions,
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ const parseQuery = (queryString: string) => {
|
|||||||
const queryObj = gql`
|
const queryObj = gql`
|
||||||
${queryString}
|
${queryString}
|
||||||
`;
|
`;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
const { name } = queryObj.definitions[0] as any;
|
const { name } = queryObj.definitions[0] as any;
|
||||||
return [name ? name.value : 'Generic', queryString.trim()];
|
return [name ? name.value : 'Generic', queryString.trim()];
|
||||||
};
|
};
|
||||||
@@ -25,10 +25,10 @@ export const loggerLink = (getSchemaName: (operation: Operation) => string) =>
|
|||||||
operation.setContext({ start: Date.now() });
|
operation.setContext({ start: Date.now() });
|
||||||
|
|
||||||
const { variables } = operation;
|
const { variables } = operation;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
const operationType = (operation.query.definitions[0] as any).operation;
|
const operationType = (operation.query.definitions[0] as any).operation;
|
||||||
const headers = operation.getContext().headers;
|
const headers = operation.getContext().headers;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
||||||
const [queryName, query] = parseQuery(operation.query.loc!.source.body);
|
const [queryName, query] = parseQuery(operation.query.loc!.source.body);
|
||||||
|
|
||||||
if (operationType === 'subscription') {
|
if (operationType === 'subscription') {
|
||||||
@@ -65,7 +65,6 @@ export const loggerLink = (getSchemaName: (operation: Operation) => string) =>
|
|||||||
getGroup(!hasError)(...titleArgs);
|
getGroup(!hasError)(...titleArgs);
|
||||||
|
|
||||||
if (errors) {
|
if (errors) {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
errors.forEach((err: any) => {
|
errors.forEach((err: any) => {
|
||||||
logDebug(
|
logDebug(
|
||||||
`%c${err.message}`,
|
`%c${err.message}`,
|
||||||
|
|||||||
@@ -219,8 +219,8 @@ export const SignInUpForm = () => {
|
|||||||
SignInUpStep.Init
|
SignInUpStep.Init
|
||||||
? false
|
? false
|
||||||
: signInUpStep === SignInUpStep.Email
|
: signInUpStep === SignInUpStep.Email
|
||||||
? !watch('email')
|
? !watch('email')
|
||||||
: !watch('email') || !watch('password') || isSubmitting
|
: !watch('email') || !watch('password') || isSubmitting
|
||||||
}
|
}
|
||||||
fullWidth
|
fullWidth
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -176,124 +176,128 @@ export const CommandMenu = () => {
|
|||||||
.concat(activities.map((activity) => activity.id));
|
.concat(activities.map((activity) => activity.id));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
isCommandMenuOpened && (
|
<>
|
||||||
<StyledDialog>
|
{isCommandMenuOpened && (
|
||||||
<StyledInput
|
<StyledDialog>
|
||||||
value={search}
|
<StyledInput
|
||||||
placeholder="Search"
|
value={search}
|
||||||
onChange={handleSearchChange}
|
placeholder="Search"
|
||||||
/>
|
onChange={handleSearchChange}
|
||||||
<StyledList>
|
/>
|
||||||
<ScrollWrapper>
|
<StyledList>
|
||||||
<StyledInnerList>
|
<ScrollWrapper>
|
||||||
<SelectableList
|
<StyledInnerList>
|
||||||
selectableListId="command-menu-list"
|
<SelectableList
|
||||||
selectableItemIds={[selectableItemIds]}
|
selectableListId="command-menu-list"
|
||||||
hotkeyScope={AppHotkeyScope.CommandMenu}
|
selectableItemIds={[selectableItemIds]}
|
||||||
onEnter={(_itemId) => {}}
|
hotkeyScope={AppHotkeyScope.CommandMenu}
|
||||||
>
|
onEnter={(_itemId) => {}}
|
||||||
{!matchingCreateCommand.length &&
|
>
|
||||||
!matchingNavigateCommand.length &&
|
{!matchingCreateCommand.length &&
|
||||||
!people.length &&
|
!matchingNavigateCommand.length &&
|
||||||
!companies.length &&
|
!people.length &&
|
||||||
!activities.length && (
|
!companies.length &&
|
||||||
<StyledEmpty>No results found</StyledEmpty>
|
!activities.length && (
|
||||||
)}
|
<StyledEmpty>No results found</StyledEmpty>
|
||||||
<CommandGroup heading="Create">
|
)}
|
||||||
{matchingCreateCommand.map((cmd) => (
|
<CommandGroup heading="Create">
|
||||||
<SelectableItem itemId={cmd.id} key={cmd.id}>
|
{matchingCreateCommand.map((cmd) => (
|
||||||
<CommandMenuItem
|
<SelectableItem itemId={cmd.id} key={cmd.id}>
|
||||||
id={cmd.id}
|
<CommandMenuItem
|
||||||
to={cmd.to}
|
id={cmd.id}
|
||||||
key={cmd.id}
|
to={cmd.to}
|
||||||
Icon={cmd.Icon}
|
key={cmd.id}
|
||||||
label={cmd.label}
|
Icon={cmd.Icon}
|
||||||
onClick={cmd.onCommandClick}
|
label={cmd.label}
|
||||||
firstHotKey={cmd.firstHotKey}
|
onClick={cmd.onCommandClick}
|
||||||
secondHotKey={cmd.secondHotKey}
|
firstHotKey={cmd.firstHotKey}
|
||||||
/>
|
secondHotKey={cmd.secondHotKey}
|
||||||
</SelectableItem>
|
/>
|
||||||
))}
|
</SelectableItem>
|
||||||
</CommandGroup>
|
))}
|
||||||
<CommandGroup heading="Navigate">
|
</CommandGroup>
|
||||||
{matchingNavigateCommand.map((cmd) => (
|
<CommandGroup heading="Navigate">
|
||||||
<SelectableItem itemId={cmd.id} key={cmd.id}>
|
{matchingNavigateCommand.map((cmd) => (
|
||||||
<CommandMenuItem
|
<SelectableItem itemId={cmd.id} key={cmd.id}>
|
||||||
id={cmd.id}
|
<CommandMenuItem
|
||||||
to={cmd.to}
|
id={cmd.id}
|
||||||
key={cmd.id}
|
to={cmd.to}
|
||||||
label={cmd.label}
|
key={cmd.id}
|
||||||
Icon={cmd.Icon}
|
label={cmd.label}
|
||||||
onClick={cmd.onCommandClick}
|
Icon={cmd.Icon}
|
||||||
firstHotKey={cmd.firstHotKey}
|
onClick={cmd.onCommandClick}
|
||||||
secondHotKey={cmd.secondHotKey}
|
firstHotKey={cmd.firstHotKey}
|
||||||
/>
|
secondHotKey={cmd.secondHotKey}
|
||||||
</SelectableItem>
|
/>
|
||||||
))}
|
</SelectableItem>
|
||||||
</CommandGroup>
|
))}
|
||||||
<CommandGroup heading="People">
|
</CommandGroup>
|
||||||
{people.map((person) => (
|
<CommandGroup heading="People">
|
||||||
<SelectableItem itemId={person.id} key={person.id}>
|
{people.map((person) => (
|
||||||
<CommandMenuItem
|
<SelectableItem itemId={person.id} key={person.id}>
|
||||||
id={person.id}
|
<CommandMenuItem
|
||||||
key={person.id}
|
id={person.id}
|
||||||
to={`object/person/${person.id}`}
|
key={person.id}
|
||||||
label={
|
to={`object/person/${person.id}`}
|
||||||
person.name.firstName + ' ' + person.name.lastName
|
label={
|
||||||
}
|
person.name.firstName + ' ' + person.name.lastName
|
||||||
Icon={() => (
|
}
|
||||||
<Avatar
|
Icon={() => (
|
||||||
type="rounded"
|
<Avatar
|
||||||
avatarUrl={null}
|
type="rounded"
|
||||||
colorId={person.id}
|
avatarUrl={null}
|
||||||
placeholder={
|
colorId={person.id}
|
||||||
person.name.firstName + ' ' + person.name.lastName
|
placeholder={
|
||||||
}
|
person.name.firstName +
|
||||||
/>
|
' ' +
|
||||||
)}
|
person.name.lastName
|
||||||
/>
|
}
|
||||||
</SelectableItem>
|
/>
|
||||||
))}
|
)}
|
||||||
</CommandGroup>
|
/>
|
||||||
<CommandGroup heading="Companies">
|
</SelectableItem>
|
||||||
{companies.map((company) => (
|
))}
|
||||||
<SelectableItem itemId={company.id} key={company.id}>
|
</CommandGroup>
|
||||||
<CommandMenuItem
|
<CommandGroup heading="Companies">
|
||||||
id={company.id}
|
{companies.map((company) => (
|
||||||
key={company.id}
|
<SelectableItem itemId={company.id} key={company.id}>
|
||||||
label={company.name}
|
<CommandMenuItem
|
||||||
to={`object/company/${company.id}`}
|
id={company.id}
|
||||||
Icon={() => (
|
key={company.id}
|
||||||
<Avatar
|
label={company.name}
|
||||||
colorId={company.id}
|
to={`object/company/${company.id}`}
|
||||||
placeholder={company.name}
|
Icon={() => (
|
||||||
avatarUrl={getLogoUrlFromDomainName(
|
<Avatar
|
||||||
company.domainName,
|
colorId={company.id}
|
||||||
)}
|
placeholder={company.name}
|
||||||
/>
|
avatarUrl={getLogoUrlFromDomainName(
|
||||||
)}
|
company.domainName,
|
||||||
/>
|
)}
|
||||||
</SelectableItem>
|
/>
|
||||||
))}
|
)}
|
||||||
</CommandGroup>
|
/>
|
||||||
<CommandGroup heading="Notes">
|
</SelectableItem>
|
||||||
{activities.map((activity) => (
|
))}
|
||||||
<SelectableItem itemId={activity.id} key={activity.id}>
|
</CommandGroup>
|
||||||
<CommandMenuItem
|
<CommandGroup heading="Notes">
|
||||||
id={activity.id}
|
{activities.map((activity) => (
|
||||||
Icon={IconNotes}
|
<SelectableItem itemId={activity.id} key={activity.id}>
|
||||||
key={activity.id}
|
<CommandMenuItem
|
||||||
label={activity.title ?? ''}
|
id={activity.id}
|
||||||
onClick={() => openActivityRightDrawer(activity.id)}
|
Icon={IconNotes}
|
||||||
/>
|
key={activity.id}
|
||||||
</SelectableItem>
|
label={activity.title ?? ''}
|
||||||
))}
|
onClick={() => openActivityRightDrawer(activity.id)}
|
||||||
</CommandGroup>
|
/>
|
||||||
</SelectableList>
|
</SelectableItem>
|
||||||
</StyledInnerList>
|
))}
|
||||||
</ScrollWrapper>
|
</CommandGroup>
|
||||||
</StyledList>
|
</SelectableList>
|
||||||
</StyledDialog>
|
</StyledInnerList>
|
||||||
)
|
</ScrollWrapper>
|
||||||
|
</StyledList>
|
||||||
|
</StyledDialog>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { expect } from '@storybook/jest';
|
|
||||||
import { Meta, StoryObj } from '@storybook/react';
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
import { userEvent, within } from '@storybook/testing-library';
|
import { expect, userEvent, within } from '@storybook/test';
|
||||||
|
|
||||||
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
|
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
|
||||||
import { CommandType } from '@/command-menu/types/Command';
|
import { CommandType } from '@/command-menu/types/Command';
|
||||||
|
|||||||
@@ -17,14 +17,14 @@ export const mapFavorites = (favorites: any) => {
|
|||||||
link: `/object/person/${favorite.person.id}`,
|
link: `/object/person/${favorite.person.id}`,
|
||||||
}
|
}
|
||||||
: isDefined(favorite?.company)
|
: isDefined(favorite?.company)
|
||||||
? {
|
? {
|
||||||
id: favorite.company.id,
|
id: favorite.company.id,
|
||||||
labelIdentifier: favorite.company.name,
|
labelIdentifier: favorite.company.name,
|
||||||
avatarUrl: getLogoUrlFromDomainName(favorite.company.domainName),
|
avatarUrl: getLogoUrlFromDomainName(favorite.company.domainName),
|
||||||
avatarType: 'squared',
|
avatarType: 'squared',
|
||||||
link: `/object/company/${favorite.company.id}`,
|
link: `/object/company/${favorite.company.id}`,
|
||||||
}
|
}
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...recordInformation,
|
...recordInformation,
|
||||||
|
|||||||
@@ -42,19 +42,21 @@ export const KeyboardShortcutMenu = () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
isKeyboardShortcutMenuOpened && (
|
<>
|
||||||
<KeyboardMenuDialog onClose={toggleKeyboardShortcutMenu}>
|
{isKeyboardShortcutMenuOpened && (
|
||||||
<KeyboardMenuGroup heading="Table">
|
<KeyboardMenuDialog onClose={toggleKeyboardShortcutMenu}>
|
||||||
{keyboardShortcutsTable.map((TableShortcut) => (
|
<KeyboardMenuGroup heading="Table">
|
||||||
<KeyboardMenuItem shortcut={TableShortcut} />
|
{keyboardShortcutsTable.map((TableShortcut) => (
|
||||||
))}
|
<KeyboardMenuItem shortcut={TableShortcut} />
|
||||||
</KeyboardMenuGroup>
|
))}
|
||||||
<KeyboardMenuGroup heading="General">
|
</KeyboardMenuGroup>
|
||||||
{keyboardShortcutsGeneral.map((GeneralShortcut) => (
|
<KeyboardMenuGroup heading="General">
|
||||||
<KeyboardMenuItem shortcut={GeneralShortcut} />
|
{keyboardShortcutsGeneral.map((GeneralShortcut) => (
|
||||||
))}
|
<KeyboardMenuItem shortcut={GeneralShortcut} />
|
||||||
</KeyboardMenuGroup>
|
))}
|
||||||
</KeyboardMenuDialog>
|
</KeyboardMenuGroup>
|
||||||
)
|
</KeyboardMenuDialog>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -34,12 +34,12 @@ export const MobileNavigationBar = () => {
|
|||||||
const activeItemName = isNavigationDrawerOpen
|
const activeItemName = isNavigationDrawerOpen
|
||||||
? currentMobileNavigationDrawer
|
? currentMobileNavigationDrawer
|
||||||
: isCommandMenuOpened
|
: isCommandMenuOpened
|
||||||
? 'search'
|
? 'search'
|
||||||
: isTasksPage
|
: isTasksPage
|
||||||
? 'tasks'
|
? 'tasks'
|
||||||
: isSettingsPage
|
: isSettingsPage
|
||||||
? 'settings'
|
? 'settings'
|
||||||
: 'main';
|
: 'main';
|
||||||
|
|
||||||
const items: {
|
const items: {
|
||||||
name: NavigationBarItemName;
|
name: NavigationBarItemName;
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
/* eslint-disable no-console */
|
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { ApolloClient, InMemoryCache } from '@apollo/client';
|
import { ApolloClient, InMemoryCache } from '@apollo/client';
|
||||||
import { useRecoilState } from 'recoil';
|
import { useRecoilState } from 'recoil';
|
||||||
|
|||||||
@@ -54,18 +54,18 @@ const formatFieldMetadataItemAsFilterDefinition = ({
|
|||||||
field.type === FieldMetadataType.DateTime
|
field.type === FieldMetadataType.DateTime
|
||||||
? 'DATE_TIME'
|
? 'DATE_TIME'
|
||||||
: field.type === FieldMetadataType.Link
|
: field.type === FieldMetadataType.Link
|
||||||
? 'LINK'
|
? 'LINK'
|
||||||
: field.type === FieldMetadataType.FullName
|
: field.type === FieldMetadataType.FullName
|
||||||
? 'FULL_NAME'
|
? 'FULL_NAME'
|
||||||
: field.type === FieldMetadataType.Number
|
: field.type === FieldMetadataType.Number
|
||||||
? 'NUMBER'
|
? 'NUMBER'
|
||||||
: field.type === FieldMetadataType.Currency
|
: field.type === FieldMetadataType.Currency
|
||||||
? 'CURRENCY'
|
? 'CURRENCY'
|
||||||
: field.type === FieldMetadataType.Email
|
: field.type === FieldMetadataType.Email
|
||||||
? 'TEXT'
|
? 'TEXT'
|
||||||
: field.type === FieldMetadataType.Phone
|
: field.type === FieldMetadataType.Phone
|
||||||
? 'TEXT'
|
? 'TEXT'
|
||||||
: field.type === FieldMetadataType.Relation
|
: field.type === FieldMetadataType.Relation
|
||||||
? 'RELATION'
|
? 'RELATION'
|
||||||
: 'TEXT',
|
: 'TEXT',
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -72,8 +72,8 @@ export const RecordShowPage = () => {
|
|||||||
objectMetadataItem?.nameSingular === 'company'
|
objectMetadataItem?.nameSingular === 'company'
|
||||||
? 'Company'
|
? 'Company'
|
||||||
: objectMetadataItem?.nameSingular === 'person'
|
: objectMetadataItem?.nameSingular === 'person'
|
||||||
? 'Person'
|
? 'Person'
|
||||||
: 'Custom';
|
: 'Custom';
|
||||||
|
|
||||||
const useUpdateOneObjectRecordMutation: () => [
|
const useUpdateOneObjectRecordMutation: () => [
|
||||||
(params: any) => any,
|
(params: any) => any,
|
||||||
@@ -117,14 +117,14 @@ export const RecordShowPage = () => {
|
|||||||
recordId: record.id,
|
recordId: record.id,
|
||||||
}
|
}
|
||||||
: objectNameSingular === 'company'
|
: objectNameSingular === 'company'
|
||||||
? {
|
? {
|
||||||
labelIdentifier: record.name,
|
labelIdentifier: record.name,
|
||||||
avatarUrl: getLogoUrlFromDomainName(record.domainName ?? ''),
|
avatarUrl: getLogoUrlFromDomainName(record.domainName ?? ''),
|
||||||
avatarType: 'squared',
|
avatarType: 'squared',
|
||||||
link: `/object/companyV2/${record.id}`,
|
link: `/object/companyV2/${record.id}`,
|
||||||
recordId: record.id,
|
recordId: record.id,
|
||||||
}
|
}
|
||||||
: {};
|
: {};
|
||||||
createFavorite(record.id, additionalData);
|
createFavorite(record.id, additionalData);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -256,8 +256,8 @@ export const RecordShowPage = () => {
|
|||||||
objectMetadataItem?.nameSingular === 'company'
|
objectMetadataItem?.nameSingular === 'company'
|
||||||
? 'Company'
|
? 'Company'
|
||||||
: objectMetadataItem?.nameSingular === 'person'
|
: objectMetadataItem?.nameSingular === 'person'
|
||||||
? 'Person'
|
? 'Person'
|
||||||
: 'Custom',
|
: 'Custom',
|
||||||
}}
|
}}
|
||||||
timeline
|
timeline
|
||||||
tasks
|
tasks
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ export const useLinkField = () => {
|
|||||||
const initialValue: FieldLinkValue = fieldInitialValue?.isEmpty
|
const initialValue: FieldLinkValue = fieldInitialValue?.isEmpty
|
||||||
? { url: '', label: '' }
|
? { url: '', label: '' }
|
||||||
: fieldInitialValue?.value
|
: fieldInitialValue?.value
|
||||||
? { url: fieldInitialValue.value, label: '' }
|
? { url: fieldInitialValue.value, label: '' }
|
||||||
: fieldValue;
|
: fieldValue;
|
||||||
|
|
||||||
const persistField = usePersistField();
|
const persistField = usePersistField();
|
||||||
|
|
||||||
|
|||||||
@@ -44,8 +44,8 @@ export const useNumberField = () => {
|
|||||||
const initialValue = fieldInitialValue?.isEmpty
|
const initialValue = fieldInitialValue?.isEmpty
|
||||||
? null
|
? null
|
||||||
: !isNaN(Number(fieldInitialValue?.value))
|
: !isNaN(Number(fieldInitialValue?.value))
|
||||||
? Number(fieldInitialValue?.value)
|
? Number(fieldInitialValue?.value)
|
||||||
: null ?? fieldValue;
|
: null ?? fieldValue;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
fieldDefinition,
|
fieldDefinition,
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { expect, jest } from '@storybook/jest';
|
|
||||||
import { Meta, StoryObj } from '@storybook/react';
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
import { userEvent, within } from '@storybook/testing-library';
|
import { expect, fn, userEvent, within } from '@storybook/test';
|
||||||
|
|
||||||
import { FieldContextProvider } from '../../../__stories__/FieldContextProvider';
|
import { FieldContextProvider } from '../../../__stories__/FieldContextProvider';
|
||||||
import { useBooleanField } from '../../../hooks/useBooleanField';
|
import { useBooleanField } from '../../../hooks/useBooleanField';
|
||||||
@@ -61,7 +60,7 @@ export default meta;
|
|||||||
|
|
||||||
type Story = StoryObj<typeof BooleanFieldInputWithContext>;
|
type Story = StoryObj<typeof BooleanFieldInputWithContext>;
|
||||||
|
|
||||||
const submitJestFn = jest.fn();
|
const submitJestFn = fn();
|
||||||
|
|
||||||
export const Default: Story = {};
|
export const Default: Story = {};
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { expect, jest } from '@storybook/jest';
|
|
||||||
import { Meta, StoryObj } from '@storybook/react';
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
import { userEvent, within } from '@storybook/testing-library';
|
import { expect, fn, userEvent, within } from '@storybook/test';
|
||||||
|
|
||||||
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
||||||
|
|
||||||
@@ -65,9 +64,9 @@ const DateFieldInputWithContext = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const escapeJestFn = jest.fn();
|
const escapeJestFn = fn();
|
||||||
const enterJestFn = jest.fn();
|
const enterJestFn = fn();
|
||||||
const clickOutsideJestFn = jest.fn();
|
const clickOutsideJestFn = fn();
|
||||||
|
|
||||||
const meta: Meta = {
|
const meta: Meta = {
|
||||||
title: 'UI/Data/Field/Input/DateFieldInput',
|
title: 'UI/Data/Field/Input/DateFieldInput',
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { expect, jest } from '@storybook/jest';
|
|
||||||
import { Decorator, Meta, StoryObj } from '@storybook/react';
|
import { Decorator, Meta, StoryObj } from '@storybook/react';
|
||||||
import { userEvent, waitFor, within } from '@storybook/testing-library';
|
import { expect, fn, userEvent, waitFor, within } from '@storybook/test';
|
||||||
|
|
||||||
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
||||||
|
|
||||||
@@ -68,11 +67,11 @@ const EmailFieldInputWithContext = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const enterJestFn = jest.fn();
|
const enterJestFn = fn();
|
||||||
const escapeJestfn = jest.fn();
|
const escapeJestfn = fn();
|
||||||
const clickOutsideJestFn = jest.fn();
|
const clickOutsideJestFn = fn();
|
||||||
const tabJestFn = jest.fn();
|
const tabJestFn = fn();
|
||||||
const shiftTabJestFn = jest.fn();
|
const shiftTabJestFn = fn();
|
||||||
|
|
||||||
const clearMocksDecorator: Decorator = (Story, context) => {
|
const clearMocksDecorator: Decorator = (Story, context) => {
|
||||||
if (context.parameters.clearMocks) {
|
if (context.parameters.clearMocks) {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { expect, jest } from '@storybook/jest';
|
|
||||||
import { Decorator, Meta, StoryObj } from '@storybook/react';
|
import { Decorator, Meta, StoryObj } from '@storybook/react';
|
||||||
import { userEvent, waitFor, within } from '@storybook/testing-library';
|
import { expect, fn, userEvent, waitFor, within } from '@storybook/test';
|
||||||
|
|
||||||
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
||||||
|
|
||||||
@@ -68,11 +67,11 @@ const NumberFieldInputWithContext = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const enterJestFn = jest.fn();
|
const enterJestFn = fn();
|
||||||
const escapeJestfn = jest.fn();
|
const escapeJestfn = fn();
|
||||||
const clickOutsideJestFn = jest.fn();
|
const clickOutsideJestFn = fn();
|
||||||
const tabJestFn = jest.fn();
|
const tabJestFn = fn();
|
||||||
const shiftTabJestFn = jest.fn();
|
const shiftTabJestFn = fn();
|
||||||
|
|
||||||
const clearMocksDecorator: Decorator = (Story, context) => {
|
const clearMocksDecorator: Decorator = (Story, context) => {
|
||||||
if (context.parameters.clearMocks) {
|
if (context.parameters.clearMocks) {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { expect, jest } from '@storybook/jest';
|
|
||||||
import { Decorator, Meta, StoryObj } from '@storybook/react';
|
import { Decorator, Meta, StoryObj } from '@storybook/react';
|
||||||
import { userEvent, waitFor, within } from '@storybook/testing-library';
|
import { expect, fn, userEvent, waitFor, within } from '@storybook/test';
|
||||||
|
|
||||||
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
||||||
|
|
||||||
@@ -69,11 +68,11 @@ const PhoneFieldInputWithContext = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const enterJestFn = jest.fn();
|
const enterJestFn = fn();
|
||||||
const escapeJestfn = jest.fn();
|
const escapeJestfn = fn();
|
||||||
const clickOutsideJestFn = jest.fn();
|
const clickOutsideJestFn = fn();
|
||||||
const tabJestFn = jest.fn();
|
const tabJestFn = fn();
|
||||||
const shiftTabJestFn = jest.fn();
|
const shiftTabJestFn = fn();
|
||||||
|
|
||||||
const clearMocksDecorator: Decorator = (Story, context) => {
|
const clearMocksDecorator: Decorator = (Story, context) => {
|
||||||
if (context.parameters.clearMocks) {
|
if (context.parameters.clearMocks) {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { expect, jest } from '@storybook/jest';
|
|
||||||
import { Decorator, Meta, StoryObj } from '@storybook/react';
|
import { Decorator, Meta, StoryObj } from '@storybook/react';
|
||||||
import { userEvent, within } from '@storybook/testing-library';
|
import { expect, fn, userEvent, within } from '@storybook/test';
|
||||||
|
|
||||||
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
||||||
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
import { FieldMetadataType } from '~/generated-metadata/graphql';
|
||||||
@@ -60,7 +59,7 @@ const RatingFieldInputWithContext = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const submitJestFn = jest.fn();
|
const submitJestFn = fn();
|
||||||
|
|
||||||
const clearMocksDecorator: Decorator = (Story, context) => {
|
const clearMocksDecorator: Decorator = (Story, context) => {
|
||||||
if (context.parameters.clearMocks) {
|
if (context.parameters.clearMocks) {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { expect, jest } from '@storybook/jest';
|
|
||||||
import { Decorator, Meta, StoryObj } from '@storybook/react';
|
import { Decorator, Meta, StoryObj } from '@storybook/react';
|
||||||
import { userEvent, waitFor, within } from '@storybook/testing-library';
|
import { expect, fn, userEvent, waitFor, within } from '@storybook/test';
|
||||||
|
|
||||||
import { RelationPickerScope } from '@/object-record/relation-picker/scopes/RelationPickerScope';
|
import { RelationPickerScope } from '@/object-record/relation-picker/scopes/RelationPickerScope';
|
||||||
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
||||||
@@ -66,8 +65,8 @@ const RelationFieldInputWithContext = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const submitJestFn = jest.fn();
|
const submitJestFn = fn();
|
||||||
const cancelJestFn = jest.fn();
|
const cancelJestFn = fn();
|
||||||
|
|
||||||
const clearMocksDecorator: Decorator = (Story, context) => {
|
const clearMocksDecorator: Decorator = (Story, context) => {
|
||||||
if (context.parameters.clearMocks) {
|
if (context.parameters.clearMocks) {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { expect, jest } from '@storybook/jest';
|
|
||||||
import { Decorator, Meta, StoryObj } from '@storybook/react';
|
import { Decorator, Meta, StoryObj } from '@storybook/react';
|
||||||
import { userEvent, waitFor, within } from '@storybook/testing-library';
|
import { expect, fn, userEvent, waitFor, within } from '@storybook/test';
|
||||||
|
|
||||||
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
||||||
|
|
||||||
@@ -68,11 +67,11 @@ const TextFieldInputWithContext = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const enterJestFn = jest.fn();
|
const enterJestFn = fn();
|
||||||
const escapeJestfn = jest.fn();
|
const escapeJestfn = fn();
|
||||||
const clickOutsideJestFn = jest.fn();
|
const clickOutsideJestFn = fn();
|
||||||
const tabJestFn = jest.fn();
|
const tabJestFn = fn();
|
||||||
const shiftTabJestFn = jest.fn();
|
const shiftTabJestFn = fn();
|
||||||
|
|
||||||
const clearMocksDecorator: Decorator = (Story, context) => {
|
const clearMocksDecorator: Decorator = (Story, context) => {
|
||||||
if (context.parameters.clearMocks) {
|
if (context.parameters.clearMocks) {
|
||||||
|
|||||||
@@ -22,30 +22,32 @@ type AssertFieldMetadataFunction = <
|
|||||||
T extends E extends 'BOOLEAN'
|
T extends E extends 'BOOLEAN'
|
||||||
? FieldBooleanMetadata
|
? FieldBooleanMetadata
|
||||||
: E extends 'CURRENCY'
|
: E extends 'CURRENCY'
|
||||||
? FieldCurrencyMetadata
|
? FieldCurrencyMetadata
|
||||||
: E extends 'FULL_NAME'
|
: E extends 'FULL_NAME'
|
||||||
? FieldFullNameMetadata
|
? FieldFullNameMetadata
|
||||||
: E extends 'DATE_TIME'
|
: E extends 'DATE_TIME'
|
||||||
? FieldDateTimeMetadata
|
? FieldDateTimeMetadata
|
||||||
: E extends 'EMAIL'
|
: E extends 'EMAIL'
|
||||||
? FieldEmailMetadata
|
? FieldEmailMetadata
|
||||||
: E extends 'SELECT'
|
: E extends 'SELECT'
|
||||||
? FieldSelectMetadata
|
? FieldSelectMetadata
|
||||||
: E extends 'LINK'
|
: E extends 'RATING'
|
||||||
? FieldLinkMetadata
|
? FieldRatingMetadata
|
||||||
: E extends 'NUMBER'
|
: E extends 'LINK'
|
||||||
? FieldNumberMetadata
|
? FieldLinkMetadata
|
||||||
: E extends 'PHONE'
|
: E extends 'NUMBER'
|
||||||
? FieldPhoneMetadata
|
? FieldNumberMetadata
|
||||||
: E extends 'RATING'
|
: E extends 'PHONE'
|
||||||
? FieldRatingMetadata
|
? FieldPhoneMetadata
|
||||||
: E extends 'RELATION'
|
: E extends 'PROBABILITY'
|
||||||
? FieldRelationMetadata
|
? FieldRatingMetadata
|
||||||
: E extends 'TEXT'
|
: E extends 'RELATION'
|
||||||
? FieldTextMetadata
|
? FieldRelationMetadata
|
||||||
: E extends 'UUID'
|
: E extends 'TEXT'
|
||||||
? FieldUuidMetadata
|
? FieldTextMetadata
|
||||||
: never,
|
: E extends 'UUID'
|
||||||
|
? FieldUuidMetadata
|
||||||
|
: never,
|
||||||
>(
|
>(
|
||||||
fieldType: E,
|
fieldType: E,
|
||||||
fieldTypeGuard: (
|
fieldTypeGuard: (
|
||||||
|
|||||||
@@ -65,4 +65,4 @@ export const getRecordOptimisticEffectDefinition = ({
|
|||||||
},
|
},
|
||||||
isUsingFlexibleBackend: true,
|
isUsingFlexibleBackend: true,
|
||||||
objectMetadataItem,
|
objectMetadataItem,
|
||||||
} satisfies OptimisticEffectDefinition);
|
}) satisfies OptimisticEffectDefinition;
|
||||||
|
|||||||
@@ -22,10 +22,10 @@ export const useGenerateFindManyRecordsQuery = ({
|
|||||||
query FindMany${capitalize(
|
query FindMany${capitalize(
|
||||||
objectMetadataItem.namePlural,
|
objectMetadataItem.namePlural,
|
||||||
)}($filter: ${capitalize(
|
)}($filter: ${capitalize(
|
||||||
objectMetadataItem.nameSingular,
|
objectMetadataItem.nameSingular,
|
||||||
)}FilterInput, $orderBy: ${capitalize(
|
)}FilterInput, $orderBy: ${capitalize(
|
||||||
objectMetadataItem.nameSingular,
|
objectMetadataItem.nameSingular,
|
||||||
)}OrderByInput, $lastCursor: String, $limit: Float = 30) {
|
)}OrderByInput, $lastCursor: String, $limit: Float = 30) {
|
||||||
${
|
${
|
||||||
objectMetadataItem.namePlural
|
objectMetadataItem.namePlural
|
||||||
}(filter: $filter, orderBy: $orderBy, first: $limit, after: $lastCursor){
|
}(filter: $filter, orderBy: $orderBy, first: $limit, after: $lastCursor){
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export type RecordBoardInternalEffectProps = {
|
|||||||
onFieldsChange: (fields: any) => void;
|
onFieldsChange: (fields: any) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const RecordBoardInternalEffect = ({}) => {
|
export const RecordBoardInternalEffect = () => {
|
||||||
const updateCompanyColumnsBoardInternal =
|
const updateCompanyColumnsBoardInternal =
|
||||||
useUpdateCompanyBoardColumnsInternal();
|
useUpdateCompanyBoardColumnsInternal();
|
||||||
const { setActionBarEntries } = useRecordBoardActionBarEntriesInternal();
|
const { setActionBarEntries } = useRecordBoardActionBarEntriesInternal();
|
||||||
|
|||||||
@@ -22,13 +22,14 @@ export const useBoardColumnsInternal = () => {
|
|||||||
if (!stages.length) return;
|
if (!stages.length) return;
|
||||||
|
|
||||||
return Promise.all(
|
return Promise.all(
|
||||||
stages.map((stage) =>
|
stages.map(
|
||||||
updateOnePipelineStep?.({
|
(stage) =>
|
||||||
idToUpdate: stage.id,
|
updateOnePipelineStep?.({
|
||||||
input: {
|
idToUpdate: stage.id,
|
||||||
position: stage.position,
|
input: {
|
||||||
},
|
position: stage.position,
|
||||||
}),
|
},
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -161,8 +161,8 @@ export const RecordBoardOptionsDropdownContent = ({
|
|||||||
viewEditMode === 'create'
|
viewEditMode === 'create'
|
||||||
? 'New view'
|
? 'New view'
|
||||||
: viewEditMode === 'edit'
|
: viewEditMode === 'edit'
|
||||||
? 'View name'
|
? 'View name'
|
||||||
: ''
|
: ''
|
||||||
}
|
}
|
||||||
defaultValue={viewEditMode === 'create' ? '' : currentView?.name}
|
defaultValue={viewEditMode === 'create' ? '' : currentView?.name}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -109,8 +109,8 @@ export const TableOptionsDropdownContent = ({
|
|||||||
viewEditMode === 'create'
|
viewEditMode === 'create'
|
||||||
? 'New view'
|
? 'New view'
|
||||||
: viewEditMode === 'edit'
|
: viewEditMode === 'edit'
|
||||||
? 'View name'
|
? 'View name'
|
||||||
: ''
|
: ''
|
||||||
}
|
}
|
||||||
defaultValue={viewEditMode === 'create' ? '' : currentView?.name}
|
defaultValue={viewEditMode === 'create' ? '' : currentView?.name}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ export const allRowsSelectedStatusSelector = selector<AllRowsSelectedStatus>({
|
|||||||
numberOfSelectedRows === 0
|
numberOfSelectedRows === 0
|
||||||
? 'none'
|
? 'none'
|
||||||
: numberOfRows === numberOfSelectedRows
|
: numberOfRows === numberOfSelectedRows
|
||||||
? 'all'
|
? 'all'
|
||||||
: 'some';
|
: 'some';
|
||||||
|
|
||||||
return allRowsSelectedStatus;
|
return allRowsSelectedStatus;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { expect } from '@storybook/jest';
|
|
||||||
import { Meta, StoryObj } from '@storybook/react';
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
import { userEvent, within } from '@storybook/testing-library';
|
import { expect, userEvent, within } from '@storybook/test';
|
||||||
|
|
||||||
import { useRelationPicker } from '@/object-record/relation-picker/hooks/useRelationPicker';
|
import { useRelationPicker } from '@/object-record/relation-picker/hooks/useRelationPicker';
|
||||||
import { IconUserCircle } from '@/ui/display/icon';
|
import { IconUserCircle } from '@/ui/display/icon';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { MemoryRouter } from 'react-router-dom';
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
import { Meta, StoryObj } from '@storybook/react';
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
import { userEvent, within } from '@storybook/testing-library';
|
import { userEvent, within } from '@storybook/test';
|
||||||
|
|
||||||
import { ObjectMetadataItemsProvider } from '@/object-metadata/components/ObjectMetadataItemsProvider';
|
import { ObjectMetadataItemsProvider } from '@/object-metadata/components/ObjectMetadataItemsProvider';
|
||||||
import { SnackBarProviderScope } from '@/ui/feedback/snack-bar-manager/scopes/SnackBarProviderScope';
|
import { SnackBarProviderScope } from '@/ui/feedback/snack-bar-manager/scopes/SnackBarProviderScope';
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ export const useFieldPreview = ({
|
|||||||
fieldMetadata.type === FieldMetadataType.Relation
|
fieldMetadata.type === FieldMetadataType.Relation
|
||||||
? relationValue
|
? relationValue
|
||||||
: fieldMetadata.type === FieldMetadataType.Select
|
: fieldMetadata.type === FieldMetadataType.Select
|
||||||
? selectValue || defaultSelectValue
|
? selectValue || defaultSelectValue
|
||||||
: firstRecordFieldValue || settingsFieldMetadataType?.defaultValue,
|
: firstRecordFieldValue || settingsFieldMetadataType?.defaultValue,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
import { expect, jest } from '@storybook/jest';
|
|
||||||
import { Decorator, Meta, StoryObj } from '@storybook/react';
|
import { Decorator, Meta, StoryObj } from '@storybook/react';
|
||||||
import { userEvent, within } from '@storybook/testing-library';
|
import { expect, fn, userEvent, within } from '@storybook/test';
|
||||||
|
|
||||||
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
||||||
|
|
||||||
import { SettingsObjectDisabledMenuDropDown } from '../SettingsObjectDisabledMenuDropDown';
|
import { SettingsObjectDisabledMenuDropDown } from '../SettingsObjectDisabledMenuDropDown';
|
||||||
|
|
||||||
const handleActivateMockFunction = jest.fn();
|
const handleActivateMockFunction = fn();
|
||||||
const handleEraseMockFunction = jest.fn();
|
const handleEraseMockFunction = fn();
|
||||||
|
|
||||||
const ClearMocksDecorator: Decorator = (Story, context) => {
|
const ClearMocksDecorator: Decorator = (Story, context) => {
|
||||||
if (context.parameters.clearMocks) {
|
if (context.parameters.clearMocks) {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// @ts-expect-error // Todo: remove usage of react-data-grid
|
||||||
import DataGrid, { DataGridProps } from 'react-data-grid';
|
import DataGrid, { DataGridProps } from 'react-data-grid';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// @ts-expect-error // Todo: remove usage of react-data-grid
|
||||||
import { Column, FormatterProps, useRowSelection } from 'react-data-grid';
|
import { Column, FormatterProps, useRowSelection } from 'react-data-grid';
|
||||||
|
|
||||||
import { RawData } from '@/spreadsheet-import/types';
|
import { RawData } from '@/spreadsheet-import/types';
|
||||||
|
|||||||
@@ -20,20 +20,21 @@ export const SelectHeaderTable = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Table
|
<Table
|
||||||
rowKeyGetter={(row) => data.indexOf(row)}
|
// Todo: remove usage of react-data-grid
|
||||||
|
rowKeyGetter={(row: any) => data.indexOf(row)}
|
||||||
rows={data}
|
rows={data}
|
||||||
columns={columns}
|
columns={columns}
|
||||||
selectedRows={selectedRows}
|
selectedRows={selectedRows}
|
||||||
onSelectedRowsChange={(newRows) => {
|
onSelectedRowsChange={(newRows: any) => {
|
||||||
// allow selecting only one row
|
// allow selecting only one row
|
||||||
newRows.forEach((value) => {
|
newRows.forEach((value: any) => {
|
||||||
if (!selectedRows.has(value as number)) {
|
if (!selectedRows.has(value as number)) {
|
||||||
setSelectedRows(new Set([value as number]));
|
setSelectedRows(new Set([value as number]));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
onRowClick={(row) => {
|
onRowClick={(row: any) => {
|
||||||
setSelectedRows(new Set([data.indexOf(row)]));
|
setSelectedRows(new Set([data.indexOf(row)]));
|
||||||
}}
|
}}
|
||||||
headerRowHeight={0}
|
headerRowHeight={0}
|
||||||
|
|||||||
@@ -44,9 +44,17 @@ const StyledContainer = styled.div`
|
|||||||
${theme.font.color.primary} 20px
|
${theme.font.color.primary} 20px
|
||||||
);
|
);
|
||||||
`};
|
`};
|
||||||
background-position: 0 0, 0 0, 100% 0, 0 100%;
|
background-position:
|
||||||
|
0 0,
|
||||||
|
0 0,
|
||||||
|
100% 0,
|
||||||
|
0 100%;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-size: 2px 100%, 100% 2px, 2px 100%, 100% 2px;
|
background-size:
|
||||||
|
2px 100%,
|
||||||
|
100% 2px,
|
||||||
|
2px 100%,
|
||||||
|
100% 2px;
|
||||||
border-radius: ${({ theme }) => theme.border.radius.sm};
|
border-radius: ${({ theme }) => theme.border.radius.sm};
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// @ts-expect-error // Todo: remove usage of react-data-grid
|
||||||
import { Column } from 'react-data-grid';
|
import { Column } from 'react-data-grid';
|
||||||
import { createPortal } from 'react-dom';
|
import { createPortal } from 'react-dom';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
@@ -48,7 +49,7 @@ export const generateColumns = <T extends string>(fields: Fields<T>) =>
|
|||||||
)}
|
)}
|
||||||
</StyledHeaderContainer>
|
</StyledHeaderContainer>
|
||||||
),
|
),
|
||||||
formatter: ({ row }) => (
|
formatter: ({ row }: any) => (
|
||||||
<StyledDefaultContainer>{row[column.key]}</StyledDefaultContainer>
|
<StyledDefaultContainer>{row[column.key]}</StyledDefaultContainer>
|
||||||
),
|
),
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { useCallback, useMemo, useState } from 'react';
|
import { useCallback, useMemo, useState } from 'react';
|
||||||
|
// @ts-expect-error Todo: remove usage of react-data-grid
|
||||||
import { RowsChangeData } from 'react-data-grid';
|
import { RowsChangeData } from 'react-data-grid';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
|
|
||||||
@@ -105,14 +106,18 @@ export const ValidationStep = <T extends string>({
|
|||||||
rows: typeof data,
|
rows: typeof data,
|
||||||
changedData?: RowsChangeData<(typeof data)[number]>,
|
changedData?: RowsChangeData<(typeof data)[number]>,
|
||||||
) => {
|
) => {
|
||||||
const changes = changedData?.indexes.reduce((acc, index) => {
|
const changes = changedData?.indexes.reduce(
|
||||||
// when data is filtered val !== actual index in data
|
// Todo: remove usage of react-data-grid
|
||||||
const realIndex = data.findIndex(
|
(acc: any, index: any) => {
|
||||||
(value) => value.__index === rows[index].__index,
|
// when data is filtered val !== actual index in data
|
||||||
);
|
const realIndex = data.findIndex(
|
||||||
acc[realIndex] = rows[index];
|
(value) => value.__index === rows[index].__index,
|
||||||
return acc;
|
);
|
||||||
}, {} as Record<number, (typeof data)[number]>);
|
acc[realIndex] = rows[index];
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
{} as Record<number, (typeof data)[number]>,
|
||||||
|
);
|
||||||
const newData = Object.assign([], data, changes);
|
const newData = Object.assign([], data, changes);
|
||||||
updateData(newData);
|
updateData(newData);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// @ts-expect-error // Todo: remove usage of react-data-grid
|
||||||
import { Column, useRowSelection } from 'react-data-grid';
|
import { Column, useRowSelection } from 'react-data-grid';
|
||||||
import { createPortal } from 'react-dom';
|
import { createPortal } from 'react-dom';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
@@ -71,7 +72,7 @@ export const generateColumns = <T extends string>(
|
|||||||
resizable: false,
|
resizable: false,
|
||||||
sortable: false,
|
sortable: false,
|
||||||
frozen: true,
|
frozen: true,
|
||||||
formatter: (props) => {
|
formatter: (props: any) => {
|
||||||
// eslint-disable-next-line react-hooks/rules-of-hooks
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||||
const [isRowSelected, onRowSelectionChange] = useRowSelection();
|
const [isRowSelected, onRowSelectionChange] = useRowSelection();
|
||||||
|
|
||||||
@@ -116,7 +117,8 @@ export const generateColumns = <T extends string>(
|
|||||||
</StyledHeaderContainer>
|
</StyledHeaderContainer>
|
||||||
),
|
),
|
||||||
editable: column.fieldType.type !== 'checkbox',
|
editable: column.fieldType.type !== 'checkbox',
|
||||||
editor: ({ row, onRowChange, onClose }) => {
|
// Todo: remove usage of react-data-grid
|
||||||
|
editor: ({ row, onRowChange, onClose }: any) => {
|
||||||
const columnKey = column.key as keyof (Data<T> & Meta);
|
const columnKey = column.key as keyof (Data<T> & Meta);
|
||||||
let component;
|
let component;
|
||||||
|
|
||||||
@@ -162,7 +164,8 @@ export const generateColumns = <T extends string>(
|
|||||||
editorOptions: {
|
editorOptions: {
|
||||||
editOnClick: true,
|
editOnClick: true,
|
||||||
},
|
},
|
||||||
formatter: ({ row, onRowChange }) => {
|
// Todo: remove usage of react-data-grid
|
||||||
|
formatter: ({ row, onRowChange }: { row: any; onRowChange: any }) => {
|
||||||
const columnKey = column.key as keyof (Data<T> & Meta);
|
const columnKey = column.key as keyof (Data<T> & Meta);
|
||||||
let component;
|
let component;
|
||||||
|
|
||||||
|
|||||||
@@ -6,8 +6,9 @@ export const findUnmatchedRequiredFields = <T extends string>(
|
|||||||
columns: Columns<T>,
|
columns: Columns<T>,
|
||||||
) =>
|
) =>
|
||||||
fields
|
fields
|
||||||
.filter((field) =>
|
.filter(
|
||||||
field.validations?.some((validation) => validation.rule === 'required'),
|
(field) =>
|
||||||
|
field.validations?.some((validation) => validation.rule === 'required'),
|
||||||
)
|
)
|
||||||
.filter(
|
.filter(
|
||||||
(field) =>
|
(field) =>
|
||||||
|
|||||||
@@ -7,8 +7,11 @@ const titleMap: Record<Field<string>['fieldType']['type'], string> = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const generateExampleRow = <T extends string>(fields: Fields<T>) => [
|
export const generateExampleRow = <T extends string>(fields: Fields<T>) => [
|
||||||
fields.reduce((acc, field) => {
|
fields.reduce(
|
||||||
acc[field.key as T] = field.example || titleMap[field.fieldType.type];
|
(acc, field) => {
|
||||||
return acc;
|
acc[field.key as T] = field.example || titleMap[field.fieldType.type];
|
||||||
}, {} as Record<T, string>),
|
return acc;
|
||||||
|
},
|
||||||
|
{} as Record<T, string>,
|
||||||
|
),
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ const StyledContainer = styled.div<Partial<ChipProps>>`
|
|||||||
variant === ChipVariant.Highlighted
|
variant === ChipVariant.Highlighted
|
||||||
? theme.background.transparent.light
|
? theme.background.transparent.light
|
||||||
: variant === ChipVariant.Rounded
|
: variant === ChipVariant.Rounded
|
||||||
? theme.background.transparent.lighter
|
? theme.background.transparent.lighter
|
||||||
: 'transparent'};
|
: 'transparent'};
|
||||||
border-color: ${({ theme, variant }) =>
|
border-color: ${({ theme, variant }) =>
|
||||||
variant === ChipVariant.Rounded ? theme.border.color.medium : 'none'};
|
variant === ChipVariant.Rounded ? theme.border.color.medium : 'none'};
|
||||||
border-radius: ${({ theme, variant }) =>
|
border-radius: ${({ theme, variant }) =>
|
||||||
@@ -56,14 +56,14 @@ const StyledContainer = styled.div<Partial<ChipProps>>`
|
|||||||
disabled
|
disabled
|
||||||
? theme.font.color.light
|
? theme.font.color.light
|
||||||
: accent === ChipAccent.TextPrimary
|
: accent === ChipAccent.TextPrimary
|
||||||
? theme.font.color.primary
|
? theme.font.color.primary
|
||||||
: theme.font.color.secondary};
|
: theme.font.color.secondary};
|
||||||
cursor: ${({ clickable, disabled, variant }) =>
|
cursor: ${({ clickable, disabled, variant }) =>
|
||||||
disabled || variant === ChipVariant.Transparent
|
disabled || variant === ChipVariant.Transparent
|
||||||
? 'inherit'
|
? 'inherit'
|
||||||
: clickable
|
: clickable
|
||||||
? 'pointer'
|
? 'pointer'
|
||||||
: 'inherit'};
|
: 'inherit'};
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
font-weight: ${({ theme, accent }) =>
|
font-weight: ${({ theme, accent }) =>
|
||||||
accent === ChipAccent.TextSecondary ? theme.font.weight.medium : 'inherit'};
|
accent === ChipAccent.TextSecondary ? theme.font.weight.medium : 'inherit'};
|
||||||
@@ -85,8 +85,8 @@ const StyledContainer = styled.div<Partial<ChipProps>>`
|
|||||||
(variant === ChipVariant.Highlighted
|
(variant === ChipVariant.Highlighted
|
||||||
? theme.background.transparent.medium
|
? theme.background.transparent.medium
|
||||||
: variant === ChipVariant.Regular
|
: variant === ChipVariant.Regular
|
||||||
? theme.background.transparent.light
|
? theme.background.transparent.light
|
||||||
: 'transparent') +
|
: 'transparent') +
|
||||||
';'
|
';'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -100,8 +100,8 @@ const StyledContainer = styled.div<Partial<ChipProps>>`
|
|||||||
(variant === ChipVariant.Highlighted
|
(variant === ChipVariant.Highlighted
|
||||||
? theme.background.transparent.strong
|
? theme.background.transparent.strong
|
||||||
: variant === ChipVariant.Regular
|
: variant === ChipVariant.Regular
|
||||||
? theme.background.transparent.medium
|
? theme.background.transparent.medium
|
||||||
: 'transparent') +
|
: 'transparent') +
|
||||||
';'
|
';'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { TablerIconsProps } from '@/ui/display/icon';
|
import { TablerIconsProps } from '@/ui/display/icon';
|
||||||
|
|
||||||
import { ReactComponent as IconAddressBookRaw } from '../assets/address-book.svg';
|
import IconAddressBookRaw from '../assets/address-book.svg?react';
|
||||||
|
|
||||||
type IconAddressBookProps = TablerIconsProps;
|
type IconAddressBookProps = TablerIconsProps;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useTheme } from '@emotion/react';
|
import { useTheme } from '@emotion/react';
|
||||||
|
|
||||||
import { ReactComponent as IconGoogleRaw } from '../assets/google-icon.svg';
|
import IconGoogleRaw from '../assets/google-icon.svg?react';
|
||||||
|
|
||||||
interface IconGoogleProps {
|
interface IconGoogleProps {
|
||||||
size?: number;
|
size?: number;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { TablerIconsProps } from '@/ui/display/icon';
|
import { TablerIconsProps } from '@/ui/display/icon';
|
||||||
|
|
||||||
import { ReactComponent as IconTwentyStarRaw } from '../assets/twenty-star.svg';
|
import IconTwentyStarRaw from '../assets/twenty-star.svg?react';
|
||||||
|
|
||||||
type IconTwentyStarProps = TablerIconsProps;
|
type IconTwentyStarProps = TablerIconsProps;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { TablerIconsProps } from '@/ui/display/icon';
|
import { TablerIconsProps } from '@/ui/display/icon';
|
||||||
|
|
||||||
import { ReactComponent as IconTwentyStarFilledRaw } from '../assets/twenty-star-filled.svg';
|
import IconTwentyStarFilledRaw from '../assets/twenty-star-filled.svg?react';
|
||||||
|
|
||||||
type IconTwentyStarFilledProps = TablerIconsProps;
|
type IconTwentyStarFilledProps = TablerIconsProps;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { expect, jest } from '@storybook/jest';
|
|
||||||
import { Meta, StoryObj } from '@storybook/react';
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
import { userEvent, within } from '@storybook/testing-library';
|
import { expect, fn, userEvent, within } from '@storybook/test';
|
||||||
|
|
||||||
import { mainColorNames, ThemeColor } from '@/ui/theme/constants/colors';
|
import { mainColorNames, ThemeColor } from '@/ui/theme/constants/colors';
|
||||||
import { CatalogDecorator } from '~/testing/decorators/CatalogDecorator';
|
import { CatalogDecorator } from '~/testing/decorators/CatalogDecorator';
|
||||||
@@ -23,7 +22,7 @@ type Story = StoryObj<typeof Status>;
|
|||||||
export const Default: Story = {
|
export const Default: Story = {
|
||||||
args: {
|
args: {
|
||||||
color: 'red',
|
color: 'red',
|
||||||
onClick: jest.fn(),
|
onClick: fn(),
|
||||||
},
|
},
|
||||||
decorators: [ComponentDecorator],
|
decorators: [ComponentDecorator],
|
||||||
play: async ({ canvasElement, args }) => {
|
play: async ({ canvasElement, args }) => {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { expect, jest } from '@storybook/jest';
|
|
||||||
import { Meta, StoryObj } from '@storybook/react';
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
import { userEvent, within } from '@storybook/testing-library';
|
import { expect, fn, userEvent, within } from '@storybook/test';
|
||||||
|
|
||||||
import { mainColorNames, ThemeColor } from '@/ui/theme/constants/colors';
|
import { mainColorNames, ThemeColor } from '@/ui/theme/constants/colors';
|
||||||
import { CatalogDecorator } from '~/testing/decorators/CatalogDecorator';
|
import { CatalogDecorator } from '~/testing/decorators/CatalogDecorator';
|
||||||
@@ -23,7 +22,7 @@ type Story = StoryObj<typeof Tag>;
|
|||||||
export const Default: Story = {
|
export const Default: Story = {
|
||||||
args: {
|
args: {
|
||||||
color: 'red',
|
color: 'red',
|
||||||
onClick: jest.fn(),
|
onClick: fn(),
|
||||||
},
|
},
|
||||||
decorators: [ComponentDecorator],
|
decorators: [ComponentDecorator],
|
||||||
play: async ({ canvasElement, args }) => {
|
play: async ({ canvasElement, args }) => {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Meta, StoryObj } from '@storybook/react';
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
import { userEvent, within } from '@storybook/testing-library';
|
import { userEvent, within } from '@storybook/test';
|
||||||
|
|
||||||
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
||||||
|
|
||||||
|
|||||||
@@ -142,8 +142,8 @@ const StyledButton = styled.button<
|
|||||||
? theme.color.blue
|
? theme.color.blue
|
||||||
: theme.background.transparent.light
|
: theme.background.transparent.light
|
||||||
: focus
|
: focus
|
||||||
? theme.color.blue
|
? theme.color.blue
|
||||||
: 'transparent'
|
: 'transparent'
|
||||||
};
|
};
|
||||||
border-width: ${!disabled && focus ? '1px 1px !important' : 0};
|
border-width: ${!disabled && focus ? '1px 1px !important' : 0};
|
||||||
box-shadow: ${
|
box-shadow: ${
|
||||||
@@ -178,8 +178,8 @@ const StyledButton = styled.button<
|
|||||||
? theme.color.blue
|
? theme.color.blue
|
||||||
: theme.color.blue20
|
: theme.color.blue20
|
||||||
: focus
|
: focus
|
||||||
? theme.color.blue
|
? theme.color.blue
|
||||||
: 'transparent'
|
: 'transparent'
|
||||||
};
|
};
|
||||||
border-width: ${!disabled && focus ? '1px 1px !important' : 0};
|
border-width: ${!disabled && focus ? '1px 1px !important' : 0};
|
||||||
box-shadow: ${
|
box-shadow: ${
|
||||||
@@ -210,8 +210,8 @@ const StyledButton = styled.button<
|
|||||||
? theme.color.red
|
? theme.color.red
|
||||||
: theme.border.color.danger
|
: theme.border.color.danger
|
||||||
: focus
|
: focus
|
||||||
? theme.color.red
|
? theme.color.red
|
||||||
: 'transparent'
|
: 'transparent'
|
||||||
};
|
};
|
||||||
border-width: ${!disabled && focus ? '1px 1px !important' : 0};
|
border-width: ${!disabled && focus ? '1px 1px !important' : 0};
|
||||||
box-shadow: ${
|
box-shadow: ${
|
||||||
|
|||||||
@@ -40,8 +40,8 @@ const StyledButton = styled.button<
|
|||||||
focus ? `,0 0 0 3px ${theme.color.blue10}` : ''
|
focus ? `,0 0 0 3px ${theme.color.blue10}` : ''
|
||||||
}`
|
}`
|
||||||
: focus
|
: focus
|
||||||
? `0 0 0 3px ${theme.color.blue10}`
|
? `0 0 0 3px ${theme.color.blue10}`
|
||||||
: 'none'};
|
: 'none'};
|
||||||
color: ${({ theme, disabled, focus }) => {
|
color: ${({ theme, disabled, focus }) => {
|
||||||
return !disabled
|
return !disabled
|
||||||
? focus
|
? focus
|
||||||
|
|||||||
@@ -33,9 +33,7 @@ const StyledButton = styled.button<
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
backdrop-filter: ${({ applyBlur }) => (applyBlur ? 'blur(20px)' : 'none')};
|
backdrop-filter: ${({ applyBlur }) => (applyBlur ? 'blur(20px)' : 'none')};
|
||||||
background: ${({ theme, isActive }) =>
|
background: ${({ theme, isActive }) =>
|
||||||
!!isActive
|
isActive ? theme.background.transparent.medium : theme.background.primary};
|
||||||
? theme.background.transparent.medium
|
|
||||||
: theme.background.primary};
|
|
||||||
border: ${({ focus, theme }) =>
|
border: ${({ focus, theme }) =>
|
||||||
focus ? `1px solid ${theme.color.blue}` : 'transparent'};
|
focus ? `1px solid ${theme.color.blue}` : 'transparent'};
|
||||||
border-radius: ${({ position, theme }) => {
|
border-radius: ${({ position, theme }) => {
|
||||||
@@ -56,8 +54,8 @@ const StyledButton = styled.button<
|
|||||||
theme.background.transparent.medium
|
theme.background.transparent.medium
|
||||||
}${focus ? `,0 0 0 3px ${theme.color.blue10}` : ''}`
|
}${focus ? `,0 0 0 3px ${theme.color.blue10}` : ''}`
|
||||||
: focus
|
: focus
|
||||||
? `0 0 0 3px ${theme.color.blue10}`
|
? `0 0 0 3px ${theme.color.blue10}`
|
||||||
: 'none'};
|
: 'none'};
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
color: ${({ theme, disabled, focus }) => {
|
color: ${({ theme, disabled, focus }) => {
|
||||||
return !disabled
|
return !disabled
|
||||||
|
|||||||
@@ -42,10 +42,10 @@ export const FloatingIconButtonGroup = ({
|
|||||||
iconButtons.length === 1
|
iconButtons.length === 1
|
||||||
? 'standalone'
|
? 'standalone'
|
||||||
: index === 0
|
: index === 0
|
||||||
? 'left'
|
? 'left'
|
||||||
: index === iconButtons.length - 1
|
: index === iconButtons.length - 1
|
||||||
? 'right'
|
? 'right'
|
||||||
: 'middle';
|
: 'middle';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FloatingIconButton
|
<FloatingIconButton
|
||||||
|
|||||||
@@ -137,8 +137,8 @@ const StyledButton = styled.button<
|
|||||||
? theme.color.blue
|
? theme.color.blue
|
||||||
: theme.background.transparent.light
|
: theme.background.transparent.light
|
||||||
: focus
|
: focus
|
||||||
? theme.color.blue
|
? theme.color.blue
|
||||||
: 'transparent'
|
: 'transparent'
|
||||||
};
|
};
|
||||||
border-width: ${!disabled && focus ? '1px 1px !important' : 0};
|
border-width: ${!disabled && focus ? '1px 1px !important' : 0};
|
||||||
box-shadow: ${
|
box-shadow: ${
|
||||||
@@ -173,8 +173,8 @@ const StyledButton = styled.button<
|
|||||||
? theme.color.blue
|
? theme.color.blue
|
||||||
: theme.color.blue20
|
: theme.color.blue20
|
||||||
: focus
|
: focus
|
||||||
? theme.color.blue
|
? theme.color.blue
|
||||||
: 'transparent'
|
: 'transparent'
|
||||||
};
|
};
|
||||||
border-width: ${!disabled && focus ? '1px 1px !important' : 0};
|
border-width: ${!disabled && focus ? '1px 1px !important' : 0};
|
||||||
box-shadow: ${
|
box-shadow: ${
|
||||||
@@ -201,8 +201,8 @@ const StyledButton = styled.button<
|
|||||||
variant === 'secondary'
|
variant === 'secondary'
|
||||||
? theme.border.color.danger
|
? theme.border.color.danger
|
||||||
: focus
|
: focus
|
||||||
? theme.color.red
|
? theme.color.red
|
||||||
: 'transparent'
|
: 'transparent'
|
||||||
};
|
};
|
||||||
border-width: ${!disabled && focus ? '1px 1px !important' : 0};
|
border-width: ${!disabled && focus ? '1px 1px !important' : 0};
|
||||||
box-shadow: ${
|
box-shadow: ${
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ export const IconButtonGroup = ({
|
|||||||
index === 0
|
index === 0
|
||||||
? 'left'
|
? 'left'
|
||||||
: index === iconButtons.length - 1
|
: index === iconButtons.length - 1
|
||||||
? 'right'
|
? 'right'
|
||||||
: 'middle';
|
: 'middle';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<IconButton
|
<IconButton
|
||||||
|
|||||||
@@ -33,14 +33,14 @@ const StyledButton = styled.button<
|
|||||||
return active || focus
|
return active || focus
|
||||||
? theme.color.blue
|
? theme.color.blue
|
||||||
: !disabled
|
: !disabled
|
||||||
? theme.font.color.secondary
|
? theme.font.color.secondary
|
||||||
: theme.font.color.extraLight;
|
: theme.font.color.extraLight;
|
||||||
case 'tertiary':
|
case 'tertiary':
|
||||||
return active || focus
|
return active || focus
|
||||||
? theme.color.blue
|
? theme.color.blue
|
||||||
: !disabled
|
: !disabled
|
||||||
? theme.font.color.tertiary
|
? theme.font.color.tertiary
|
||||||
: theme.font.color.extraLight;
|
: theme.font.color.extraLight;
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')};
|
cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')};
|
||||||
|
|||||||
@@ -38,14 +38,14 @@ const StyledButton = styled.button<
|
|||||||
return active || focus
|
return active || focus
|
||||||
? theme.color.blue
|
? theme.color.blue
|
||||||
: !disabled
|
: !disabled
|
||||||
? theme.font.color.secondary
|
? theme.font.color.secondary
|
||||||
: theme.font.color.extraLight;
|
: theme.font.color.extraLight;
|
||||||
case 'tertiary':
|
case 'tertiary':
|
||||||
return active || focus
|
return active || focus
|
||||||
? theme.color.blue
|
? theme.color.blue
|
||||||
: !disabled
|
: !disabled
|
||||||
? theme.font.color.tertiary
|
? theme.font.color.tertiary
|
||||||
: theme.font.color.extraLight;
|
: theme.font.color.extraLight;
|
||||||
}
|
}
|
||||||
}};
|
}};
|
||||||
cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')};
|
cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')};
|
||||||
|
|||||||
@@ -19,7 +19,9 @@ const StyledIconButton = styled.button`
|
|||||||
|
|
||||||
outline: none;
|
outline: none;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
transition: color 0.1s ease-in-out, background 0.1s ease-in-out;
|
transition:
|
||||||
|
color 0.1s ease-in-out,
|
||||||
|
background 0.1s ease-in-out;
|
||||||
|
|
||||||
&:disabled {
|
&:disabled {
|
||||||
background: ${({ theme }) => theme.background.quaternary};
|
background: ${({ theme }) => theme.background.quaternary};
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
import { expect, jest } from '@storybook/jest';
|
|
||||||
import { Meta, StoryObj } from '@storybook/react';
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
import { userEvent, within } from '@storybook/testing-library';
|
import { expect, fn, userEvent, within } from '@storybook/test';
|
||||||
|
|
||||||
import { IconBrandGoogle } from '@/ui/display/icon';
|
import { IconBrandGoogle } from '@/ui/display/icon';
|
||||||
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
||||||
|
|
||||||
import { MainButton } from '../MainButton';
|
import { MainButton } from '../MainButton';
|
||||||
|
|
||||||
const clickJestFn = jest.fn();
|
const clickJestFn = fn();
|
||||||
|
|
||||||
const meta: Meta<typeof MainButton> = {
|
const meta: Meta<typeof MainButton> = {
|
||||||
title: 'UI/Input/Button/MainButton',
|
title: 'UI/Input/Button/MainButton',
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
import { expect, jest } from '@storybook/jest';
|
|
||||||
import { Meta, StoryObj } from '@storybook/react';
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
import { userEvent, within } from '@storybook/testing-library';
|
import { expect, fn, userEvent, within } from '@storybook/test';
|
||||||
|
|
||||||
import { IconArrowRight } from '@/ui/display/icon';
|
import { IconArrowRight } from '@/ui/display/icon';
|
||||||
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
||||||
|
|
||||||
import { RoundedIconButton } from '../RoundedIconButton';
|
import { RoundedIconButton } from '../RoundedIconButton';
|
||||||
|
|
||||||
const clickJestFn = jest.fn();
|
const clickJestFn = fn();
|
||||||
|
|
||||||
const meta: Meta<typeof RoundedIconButton> = {
|
const meta: Meta<typeof RoundedIconButton> = {
|
||||||
title: 'UI/Input/Button/RoundedIconButton',
|
title: 'UI/Input/Button/RoundedIconButton',
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { expect } from '@storybook/jest';
|
|
||||||
import { Meta, StoryObj } from '@storybook/react';
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
import { userEvent, within } from '@storybook/testing-library';
|
import { expect, userEvent, within } from '@storybook/test';
|
||||||
|
|
||||||
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
||||||
import { sleep } from '~/testing/sleep';
|
import { sleep } from '~/testing/sleep';
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { Meta, StoryObj } from '@storybook/react';
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
import { userEvent, within } from '@storybook/testing-library';
|
import { userEvent, within } from '@storybook/test';
|
||||||
|
|
||||||
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { expect } from '@storybook/jest';
|
|
||||||
import { Meta, StoryObj } from '@storybook/react';
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
import { userEvent, within } from '@storybook/testing-library';
|
import { expect, userEvent, within } from '@storybook/test';
|
||||||
|
|
||||||
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import styled from '@emotion/styled';
|
import styled from '@emotion/styled';
|
||||||
import { expect } from '@storybook/jest';
|
|
||||||
import { Decorator, Meta, StoryObj } from '@storybook/react';
|
import { Decorator, Meta, StoryObj } from '@storybook/react';
|
||||||
import { userEvent, waitFor, within } from '@storybook/testing-library';
|
import { expect, userEvent, waitFor, within } from '@storybook/test';
|
||||||
import { PlayFunction } from '@storybook/types';
|
import { PlayFunction } from '@storybook/types';
|
||||||
|
|
||||||
import { Button } from '@/ui/input/button/components/Button';
|
import { Button } from '@/ui/input/button/components/Button';
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ const StyledTab = styled.div<{ active?: boolean; disabled?: boolean }>`
|
|||||||
active
|
active
|
||||||
? theme.font.color.primary
|
? theme.font.color.primary
|
||||||
: disabled
|
: disabled
|
||||||
? theme.font.color.light
|
? theme.font.color.light
|
||||||
: theme.font.color.secondary};
|
: theme.font.color.secondary};
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { expect } from '@storybook/jest';
|
|
||||||
import { Meta, StoryObj } from '@storybook/react';
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
import { within } from '@storybook/testing-library';
|
import { expect, within } from '@storybook/test';
|
||||||
|
|
||||||
import { IconCheckbox } from '@/ui/display/icon';
|
import { IconCheckbox } from '@/ui/display/icon';
|
||||||
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
|
import { RecoilScope } from '@/ui/utilities/recoil-scope/components/RecoilScope';
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ const StyledTableCell = styled.div<TableCellProps>`
|
|||||||
align === 'right'
|
align === 'right'
|
||||||
? 'flex-end'
|
? 'flex-end'
|
||||||
: align === 'center'
|
: align === 'center'
|
||||||
? 'center'
|
? 'center'
|
||||||
: 'flex-start'};
|
: 'flex-start'};
|
||||||
padding: 0 ${({ theme }) => theme.spacing(2)};
|
padding: 0 ${({ theme }) => theme.spacing(2)};
|
||||||
text-align: ${({ align }) => align ?? 'left'};
|
text-align: ${({ align }) => align ?? 'left'};
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ const StyledTableHeader = styled.div<{ align?: 'left' | 'center' | 'right' }>`
|
|||||||
align === 'right'
|
align === 'right'
|
||||||
? 'flex-end'
|
? 'flex-end'
|
||||||
: align === 'center'
|
: align === 'center'
|
||||||
? 'center'
|
? 'center'
|
||||||
: 'flex-start'};
|
: 'flex-start'};
|
||||||
padding: 0 ${({ theme }) => theme.spacing(2)};
|
padding: 0 ${({ theme }) => theme.spacing(2)};
|
||||||
text-align: ${({ align }) => align ?? 'left'};
|
text-align: ${({ align }) => align ?? 'left'};
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -32,7 +32,8 @@ const StyledSection = styled.div<{ isExpanded: boolean }>`
|
|||||||
max-height: ${({ isExpanded }) => (isExpanded ? '1000px' : 0)};
|
max-height: ${({ isExpanded }) => (isExpanded ? '1000px' : 0)};
|
||||||
opacity: ${({ isExpanded }) => (isExpanded ? 1 : 0)};
|
opacity: ${({ isExpanded }) => (isExpanded ? 1 : 0)};
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
transition: max-height ${({ theme }) => theme.animation.duration.normal}s,
|
transition:
|
||||||
|
max-height ${({ theme }) => theme.animation.duration.normal}s,
|
||||||
opacity ${({ theme }) => theme.animation.duration.normal}s;
|
opacity ${({ theme }) => theme.animation.duration.normal}s;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { jest } from '@storybook/jest';
|
|
||||||
import { Meta, StoryObj } from '@storybook/react';
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
|
import { fn } from '@storybook/test';
|
||||||
|
|
||||||
import { ComponentWithRouterDecorator } from '~/testing/decorators/ComponentWithRouterDecorator';
|
import { ComponentWithRouterDecorator } from '~/testing/decorators/ComponentWithRouterDecorator';
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ const meta: Meta<typeof ContactLink> = {
|
|||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
type Story = StoryObj<typeof ContactLink>;
|
type Story = StoryObj<typeof ContactLink>;
|
||||||
const clickJestFn = jest.fn();
|
const clickJestFn = fn();
|
||||||
|
|
||||||
export const Email: Story = {
|
export const Email: Story = {
|
||||||
args: {
|
args: {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { expect, jest } from '@storybook/jest';
|
|
||||||
import { Meta, StoryObj } from '@storybook/react';
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
import { userEvent, within } from '@storybook/testing-library';
|
import { expect, fn, userEvent, within } from '@storybook/test';
|
||||||
|
|
||||||
import { ComponentWithRouterDecorator } from '~/testing/decorators/ComponentWithRouterDecorator';
|
import { ComponentWithRouterDecorator } from '~/testing/decorators/ComponentWithRouterDecorator';
|
||||||
|
|
||||||
@@ -19,7 +18,7 @@ const meta: Meta<typeof RawLink> = {
|
|||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
type Story = StoryObj<typeof RawLink>;
|
type Story = StoryObj<typeof RawLink>;
|
||||||
const clickJestFn = jest.fn();
|
const clickJestFn = fn();
|
||||||
|
|
||||||
export const Default: Story = {
|
export const Default: Story = {
|
||||||
args: {
|
args: {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { expect, jest } from '@storybook/jest';
|
|
||||||
import { Meta, StoryObj } from '@storybook/react';
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
import { userEvent, within } from '@storybook/testing-library';
|
import { expect, fn, userEvent, within } from '@storybook/test';
|
||||||
|
|
||||||
import { ComponentWithRouterDecorator } from '~/testing/decorators/ComponentWithRouterDecorator';
|
import { ComponentWithRouterDecorator } from '~/testing/decorators/ComponentWithRouterDecorator';
|
||||||
|
|
||||||
@@ -18,7 +17,7 @@ const meta: Meta<typeof RoundedLink> = {
|
|||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
type Story = StoryObj<typeof RoundedLink>;
|
type Story = StoryObj<typeof RoundedLink>;
|
||||||
const clickJestFn = jest.fn();
|
const clickJestFn = fn();
|
||||||
|
|
||||||
export const Default: Story = {
|
export const Default: Story = {
|
||||||
args: {
|
args: {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { expect, jest } from '@storybook/jest';
|
|
||||||
import { Meta, StoryObj } from '@storybook/react';
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
import { userEvent, within } from '@storybook/testing-library';
|
import { expect, fn, userEvent, within } from '@storybook/test';
|
||||||
|
|
||||||
import { ComponentWithRouterDecorator } from '~/testing/decorators/ComponentWithRouterDecorator';
|
import { ComponentWithRouterDecorator } from '~/testing/decorators/ComponentWithRouterDecorator';
|
||||||
|
|
||||||
@@ -18,7 +17,7 @@ const meta: Meta<typeof SocialLink> = {
|
|||||||
|
|
||||||
export default meta;
|
export default meta;
|
||||||
type Story = StoryObj<typeof SocialLink>;
|
type Story = StoryObj<typeof SocialLink>;
|
||||||
const clickJestFn = jest.fn();
|
const clickJestFn = fn();
|
||||||
|
|
||||||
const linkedin: LinkType = LinkType.LinkedIn;
|
const linkedin: LinkType = LinkType.LinkedIn;
|
||||||
const twitter: LinkType = LinkType.Twitter;
|
const twitter: LinkType = LinkType.Twitter;
|
||||||
|
|||||||
@@ -80,8 +80,8 @@ export const NavigationDrawer = ({
|
|||||||
const desktopWidth = !isNavigationDrawerOpen
|
const desktopWidth = !isNavigationDrawerOpen
|
||||||
? 12
|
? 12
|
||||||
: isSubMenu
|
: isSubMenu
|
||||||
? desktopNavDrawerWidths.submenu
|
? desktopNavDrawerWidths.submenu
|
||||||
: desktopNavDrawerWidths.menu;
|
: desktopNavDrawerWidths.menu;
|
||||||
|
|
||||||
const mobileWidth = isNavigationDrawerOpen ? '100%' : 0;
|
const mobileWidth = isNavigationDrawerOpen ? '100%' : 0;
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user