feat: pre-compile ui and richtext-lexical with react compiler (#7688)
This noticeably improves performance in the admin panel, for example
when there are multiple richtext editors on one page (& likely
performance in other areas too, though I mainly tested rich text).
The babel plugin currently only optimizes files with a 'use client'
directive at the top - thus we have to make sure to add use client
wherever possible, even if it's imported by a parent client component.
There's one single component that broke when it was compiled using the
React compiler (it stopped being reactive and failed one of our admin
e2e tests):
150808f608
opting out of it completely fixed that issue
Fixes https://github.com/payloadcms/payload/issues/7366
This commit is contained in:
14
.github/workflows/main.yml
vendored
14
.github/workflows/main.yml
vendored
@@ -18,7 +18,7 @@ concurrency:
|
||||
|
||||
env:
|
||||
NODE_VERSION: 18.20.2
|
||||
PNPM_VERSION: 9.7.0
|
||||
PNPM_VERSION: 9.7.1
|
||||
DO_NOT_TRACK: 1 # Disable Turbopack telemetry
|
||||
NEXT_TELEMETRY_DISABLED: 1 # Disable Next telemetry
|
||||
|
||||
@@ -207,6 +207,9 @@ jobs:
|
||||
AWS_REGION: us-east-1
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 25
|
||||
# https://github.com/actions/virtual-environments/issues/1187
|
||||
- name: tune linux network
|
||||
run: sudo ethtool -K eth0 tx off rx off
|
||||
@@ -222,12 +225,7 @@ jobs:
|
||||
version: ${{ env.PNPM_VERSION }}
|
||||
run_install: false
|
||||
|
||||
- name: Restore build
|
||||
uses: actions/cache@v4
|
||||
timeout-minutes: 10
|
||||
with:
|
||||
path: ./*
|
||||
key: ${{ github.sha }}-${{ github.run_number }}
|
||||
- run: pnpm install
|
||||
|
||||
- name: Start LocalStack
|
||||
run: pnpm docker:start
|
||||
@@ -371,7 +369,7 @@ jobs:
|
||||
run: pnpm exec playwright install-deps chromium
|
||||
|
||||
- name: E2E Tests
|
||||
run: PLAYWRIGHT_JSON_OUTPUT_NAME=results_${{ matrix.suite }}.json pnpm test:e2e ${{ matrix.suite }}
|
||||
run: PLAYWRIGHT_JSON_OUTPUT_NAME=results_${{ matrix.suite }}.json pnpm test:e2e:prod:ci ${{ matrix.suite }}
|
||||
env:
|
||||
PLAYWRIGHT_JSON_OUTPUT_NAME: results_${{ matrix.suite }}.json
|
||||
NEXT_TELEMETRY_DISABLED: 1
|
||||
|
||||
2
.github/workflows/release-canary.yml
vendored
2
.github/workflows/release-canary.yml
vendored
@@ -7,7 +7,7 @@ on:
|
||||
|
||||
env:
|
||||
NODE_VERSION: 18.20.2
|
||||
PNPM_VERSION: 9.7.0
|
||||
PNPM_VERSION: 9.7.1
|
||||
DO_NOT_TRACK: 1 # Disable Turbopack telemetry
|
||||
NEXT_TELEMETRY_DISABLED: 1 # Disable Next telemetry
|
||||
|
||||
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -5,7 +5,7 @@ dist
|
||||
!/.idea/runConfigurations
|
||||
!/.idea/payload.iml
|
||||
|
||||
|
||||
test/packed
|
||||
test-results
|
||||
.devcontainer
|
||||
.localstack
|
||||
@@ -306,3 +306,6 @@ test/live-preview/app/(payload)/admin/importMap.js
|
||||
/test/live-preview/app/(payload)/admin/importMap.js
|
||||
test/admin-root/app/(payload)/admin/importMap.js
|
||||
/test/admin-root/app/(payload)/admin/importMap.js
|
||||
test/app/(payload)/admin/importMap.js
|
||||
/test/app/(payload)/admin/importMap.js
|
||||
test/pnpm-lock.yaml
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
"clean:all": "node ./scripts/delete-recursively.js '@node_modules' 'media/*' '**/dist/' '**/.cache/*' '**/.next/*' '**/.turbo/*' '**/tsconfig.tsbuildinfo' '**/payload*.tgz' '**/meta_*.json'",
|
||||
"clean:build": "node ./scripts/delete-recursively.js 'media/' '**/dist/' '**/.cache/' '**/.next/' '**/.turbo/' '**/tsconfig.tsbuildinfo' '**/payload*.tgz' '**/meta_*.json'",
|
||||
"clean:cache": "node ./scripts/delete-recursively.js node_modules/.cache! packages/payload/node_modules/.cache! .next/*",
|
||||
"dev": "pnpm runts ./test/dev.ts",
|
||||
"dev": "tsx ./test/dev.ts",
|
||||
"dev:generate-graphql-schema": "pnpm runts ./test/generateGraphQLSchema.ts",
|
||||
"dev:generate-importmap": "pnpm runts ./test/generateImportMap.ts",
|
||||
"dev:generate-types": "pnpm runts ./test/generateTypes.ts",
|
||||
@@ -81,6 +81,8 @@
|
||||
"test:e2e": "pnpm runts ./test/runE2E.ts",
|
||||
"test:e2e:debug": "cross-env NODE_OPTIONS=--no-deprecation NODE_NO_WARNINGS=1 PWDEBUG=1 DISABLE_LOGGING=true playwright test",
|
||||
"test:e2e:headed": "cross-env NODE_OPTIONS=--no-deprecation NODE_NO_WARNINGS=1 DISABLE_LOGGING=true playwright test --headed",
|
||||
"test:e2e:prod": "pnpm bf && rm -rf test/packed && rm -rf test/node_modules && rm -f test/pnpm-lock.yaml && pnpm run script:pack --all --no-build --dest test/packed && pnpm runts test/setupProd.ts && cd test && pnpm i --ignore-workspace && cd .. && pnpm runts ./test/runE2E.ts --prod",
|
||||
"test:e2e:prod:ci": "rm -rf test/node_modules && rm -f test/pnpm-lock.yaml && pnpm run script:pack --all --no-build --dest test/packed && pnpm runts test/setupProd.ts && cd test && pnpm i --ignore-workspace && cd .. && pnpm runts ./test/runE2E.ts --prod",
|
||||
"test:int": "cross-env NODE_OPTIONS=\"--no-deprecation\" NODE_NO_WARNINGS=1 DISABLE_LOGGING=true jest --forceExit --detectOpenHandles --config=test/jest.config.js --runInBand",
|
||||
"test:int:postgres": "cross-env NODE_OPTIONS=\"--no-deprecation\" NODE_NO_WARNINGS=1 PAYLOAD_DATABASE=postgres DISABLE_LOGGING=true jest --forceExit --detectOpenHandles --config=test/jest.config.js --runInBand",
|
||||
"test:unit": "cross-env NODE_OPTIONS=\"--no-deprecation\" NODE_NO_WARNINGS=1 DISABLE_LOGGING=true jest --forceExit --detectOpenHandles --config=jest.config.js --runInBand",
|
||||
@@ -162,7 +164,6 @@
|
||||
"react": "^19.0.0 || ^19.0.0-rc-06d0b89e-20240801",
|
||||
"react-dom": "^19.0.0 || ^19.0.0-rc-06d0b89e-20240801"
|
||||
},
|
||||
"packageManager": "pnpm@9.7.0",
|
||||
"engines": {
|
||||
"node": "^18.20.2 || >=20.9.0",
|
||||
"pnpm": "^9.7.0"
|
||||
|
||||
@@ -14,7 +14,11 @@ if (!cached) {
|
||||
cached = global._payload = { payload: null, promise: null, reload: false, ws: null }
|
||||
}
|
||||
|
||||
export const reload = async (config: SanitizedConfig, payload: Payload): Promise<void> => {
|
||||
export const reload = async (
|
||||
config: SanitizedConfig,
|
||||
payload: Payload,
|
||||
skipImportMapGeneration?: boolean,
|
||||
): Promise<void> => {
|
||||
if (typeof payload.db.destroy === 'function') {
|
||||
await payload.db.destroy()
|
||||
}
|
||||
@@ -46,7 +50,7 @@ export const reload = async (config: SanitizedConfig, payload: Payload): Promise
|
||||
}
|
||||
|
||||
// Generate component map
|
||||
if (config.admin?.importMap?.autoGenerate !== false) {
|
||||
if (skipImportMapGeneration !== true && config.admin?.importMap?.autoGenerate !== false) {
|
||||
await generateImportMap(config, {
|
||||
log: true,
|
||||
})
|
||||
@@ -87,6 +91,7 @@ export const getPayloadHMR = async (options: InitOptions): Promise<Payload> => {
|
||||
return cached.payload
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
if (!cached.promise) {
|
||||
// no need to await options.config here, as it's already awaited in the BasePayload.init
|
||||
cached.promise = new BasePayload().init(options)
|
||||
|
||||
@@ -42,7 +42,6 @@ export {
|
||||
export { fieldSchemaToJSON } from '../utilities/fieldSchemaToJSON.js'
|
||||
|
||||
export { getDataByPath } from '../utilities/getDataByPath.js'
|
||||
|
||||
export { getSiblingData } from '../utilities/getSiblingData.js'
|
||||
|
||||
export { getUniqueListBy } from '../utilities/getUniqueListBy.js'
|
||||
|
||||
36
packages/richtext-lexical/babel.config.cjs
Normal file
36
packages/richtext-lexical/babel.config.cjs
Normal file
@@ -0,0 +1,36 @@
|
||||
const fs = require('fs')
|
||||
|
||||
// Plugin options can be found here: https://github.com/facebook/react/blob/main/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Options.ts#L38
|
||||
const ReactCompilerConfig = {
|
||||
sources: (filename) => {
|
||||
const isInNodeModules = filename.includes('node_modules')
|
||||
if (isInNodeModules || ( !filename.endsWith('.tsx') && !filename.endsWith('.jsx') && !filename.endsWith('.js'))) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Only compile files with 'use client' directives. We do not want to
|
||||
// accidentally compile React Server Components
|
||||
const file = fs.readFileSync(filename, 'utf8')
|
||||
if (file.includes("'use client'")) {
|
||||
return true
|
||||
}
|
||||
console.log('React compiler - skipping file: ' + filename)
|
||||
return false
|
||||
},
|
||||
}
|
||||
|
||||
module.exports = function (api) {
|
||||
api.cache(false)
|
||||
|
||||
return {
|
||||
plugins: [
|
||||
['babel-plugin-react-compiler', ReactCompilerConfig], // must run first!
|
||||
/* [
|
||||
'babel-plugin-transform-remove-imports',
|
||||
{
|
||||
test: '\\.(scss|css)$',
|
||||
},
|
||||
],*/
|
||||
],
|
||||
}
|
||||
}
|
||||
@@ -24,15 +24,20 @@ async function build() {
|
||||
entryPoints: ['src/exports/client/index.ts'],
|
||||
bundle: true,
|
||||
minify: true,
|
||||
outdir: 'dist/field',
|
||||
outdir: 'dist/bundled_scss',
|
||||
loader: { '.svg': 'dataurl' },
|
||||
packages: 'external',
|
||||
//external: ['*.svg'],
|
||||
plugins: [sassPlugin({ css: 'external' })],
|
||||
})
|
||||
|
||||
//create empty dist/exports/client_optimized dir
|
||||
fs.mkdirSync('dist/exports/client_optimized')
|
||||
|
||||
try {
|
||||
fs.renameSync('dist/field/index.css', 'dist/exports/client/bundled.css')
|
||||
fs.renameSync('dist/bundled_scss/index.css', 'dist/field/bundled.css')
|
||||
fs.copyFileSync('dist/field/bundled.css', 'dist/exports/client_optimized/bundled.css')
|
||||
fs.rmSync('dist/bundled_scss', { recursive: true })
|
||||
} catch (err) {
|
||||
console.error(`Error while renaming index.css: ${err}`)
|
||||
throw err
|
||||
@@ -42,11 +47,11 @@ async function build() {
|
||||
|
||||
// Bundle `client.ts`
|
||||
const resultClient = await esbuild.build({
|
||||
entryPoints: ['src/exports/client/index.ts'],
|
||||
entryPoints: ['dist/exports/client/index.js'],
|
||||
bundle: true,
|
||||
platform: 'browser',
|
||||
format: 'esm',
|
||||
outdir: 'dist/exports/client',
|
||||
outdir: 'dist/exports/client_optimized',
|
||||
//outfile: 'index.js',
|
||||
// IMPORTANT: splitting the client bundle means that the `use client` directive will be lost for every chunk
|
||||
splitting: true,
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import lexical from '@lexical/eslint-plugin'
|
||||
import { rootEslintConfig, rootParserOptions } from '../../eslint.config.js'
|
||||
import reactCompiler from 'eslint-plugin-react-compiler'
|
||||
const { rules } = reactCompiler
|
||||
|
||||
/** @typedef {import('eslint').Linter.FlatConfig} */
|
||||
let FlatConfig
|
||||
@@ -20,6 +22,16 @@ export const index = [
|
||||
},
|
||||
rules: lexical.configs.recommended.rules,
|
||||
},
|
||||
{
|
||||
plugins: {
|
||||
'react-compiler': {
|
||||
rules,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
'react-compiler/react-compiler': 'error',
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export default index
|
||||
|
||||
@@ -36,11 +36,14 @@
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "rm -rf dist && rm -rf tsconfig.tsbuildinfo && pnpm copyfiles && pnpm build:types && pnpm build:swc && pnpm build:esbuild",
|
||||
"build": "pnpm build:reactcompiler",
|
||||
"build:babel": "rm -rf dist_optimized && babel dist --out-dir dist_optimized --source-maps --extensions .ts,.js,.tsx,.jsx,.cjs,.mjs && rm -rf dist && mv dist_optimized dist",
|
||||
"build:clean": "find . \\( -type d \\( -name build -o -name dist -o -name .cache \\) -o -type f -name tsconfig.tsbuildinfo \\) -exec rm -rf {} + && pnpm build",
|
||||
"build:esbuild": "node bundle.js",
|
||||
"build:esbuild": "node bundle.js && rm -rf dist/exports/client && mv dist/exports/client_optimized dist/exports/client",
|
||||
"build:reactcompiler": "rm -rf dist && rm -rf tsconfig.tsbuildinfo && pnpm build:swc && pnpm build:babel && pnpm copyfiles && pnpm build:esbuild && pnpm build:types",
|
||||
"build:swc": "swc ./src -d ./dist --config-file .swcrc --strip-leading-paths",
|
||||
"build:types": "tsc --emitDeclarationOnly --outDir dist",
|
||||
"build_without_reactcompiler": "rm -rf dist && rm -rf tsconfig.tsbuildinfo && pnpm copyfiles && pnpm build:types && pnpm build:swc && pnpm build:esbuild && rm -rf dist/exports/client && mv dist/exports/client_unoptimized dist/exports/client",
|
||||
"clean": "rimraf {dist,*.tsbuildinfo}",
|
||||
"copyfiles": "copyfiles -u 1 \"src/**/*.{html,css,ttf,woff,woff2,eot,svg,jpg,png,json}\" dist/",
|
||||
"prepublishOnly": "pnpm clean && pnpm turbo build",
|
||||
@@ -64,6 +67,11 @@
|
||||
"uuid": "10.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.24.5",
|
||||
"@babel/core": "^7.24.5",
|
||||
"@babel/preset-env": "^7.24.5",
|
||||
"@babel/preset-react": "^7.24.1",
|
||||
"@babel/preset-typescript": "^7.24.1",
|
||||
"@lexical/eslint-plugin": "0.17.0",
|
||||
"@payloadcms/eslint-config": "workspace:*",
|
||||
"@payloadcms/next": "workspace:*",
|
||||
@@ -73,8 +81,11 @@
|
||||
"@types/node": "20.12.5",
|
||||
"@types/react": "npm:types-react@19.0.0-rc.0",
|
||||
"@types/react-dom": "npm:types-react-dom@19.0.0-rc.0",
|
||||
"babel-plugin-react-compiler": "0.0.0-experimental-1cd8995-20240814",
|
||||
"babel-plugin-transform-remove-imports": "^1.8.0",
|
||||
"esbuild": "0.23.0",
|
||||
"esbuild-sass-plugin": "3.3.1",
|
||||
"eslint-plugin-react-compiler": "0.0.0-experimental-d0e920e-20240815",
|
||||
"payload": "workspace:*",
|
||||
"swc-plugin-transform-remove-imports": "1.15.0"
|
||||
},
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import type { ToolbarGroup, ToolbarGroupItem } from '../../toolbars/types.js'
|
||||
|
||||
import { AlignLeftIcon } from '../../../lexical/ui/icons/AlignLeft/index.js'
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import type { ClientBlock, ClientField, CollapsedPreferences, FormState } from 'payload'
|
||||
|
||||
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext.js'
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import type { Data, FormState } from 'payload'
|
||||
import type React from 'react'
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import type { FormState } from 'payload'
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import type { EditorConfig, LexicalEditor, LexicalNode } from 'lexical'
|
||||
|
||||
import ObjectID from 'bson-objectid'
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import type {
|
||||
EditorConfig,
|
||||
LexicalEditor,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import type { LexicalCommand } from 'lexical'
|
||||
|
||||
import { createCommand } from 'lexical'
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
*/
|
||||
'use client'
|
||||
|
||||
import type { TableCellNode, TableRowNode } from '@lexical/table'
|
||||
import type { EditorConfig, NodeKey } from 'lexical'
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
// Copied & modified from https://github.com/lodash/lodash/blob/main/src/debounce.ts
|
||||
/*
|
||||
The MIT License
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import { useMemo, useRef } from 'react'
|
||||
|
||||
import debounce from './debounce.js'
|
||||
|
||||
@@ -1,243 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
*/
|
||||
|
||||
import type { TableCellNode, TableRowNode } from '@lexical/table'
|
||||
import type { EditorConfig, NodeKey } from 'lexical'
|
||||
import type { JSX } from 'react'
|
||||
|
||||
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
|
||||
import {
|
||||
$getTableColumnIndexFromTableCellNode,
|
||||
$getTableRowIndexFromTableCellNode,
|
||||
$insertTableColumn__EXPERIMENTAL,
|
||||
$insertTableRow__EXPERIMENTAL,
|
||||
$isTableCellNode,
|
||||
$isTableNode,
|
||||
TableNode,
|
||||
} from '@lexical/table'
|
||||
import { $findMatchingParent, mergeRegister } from '@lexical/utils'
|
||||
import { $getNearestNodeFromDOMNode } from 'lexical'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import * as React from 'react'
|
||||
import { createPortal } from 'react-dom'
|
||||
|
||||
import { useEditorConfigContext } from '../../../../lexical/config/client/EditorConfigProvider.js'
|
||||
import { useDebounce } from '../../client/utils/useDebounce.js'
|
||||
|
||||
const BUTTON_WIDTH_PX = 20
|
||||
|
||||
function TableHoverActionsContainer({ anchorElem }: { anchorElem: HTMLElement }): JSX.Element {
|
||||
const [editor] = useLexicalComposerContext()
|
||||
const editorConfig = useEditorConfigContext()
|
||||
const [isShownRow, setShownRow] = useState<boolean>(false)
|
||||
const [isShownColumn, setShownColumn] = useState<boolean>(false)
|
||||
const [shouldListenMouseMove, setShouldListenMouseMove] = useState<boolean>(false)
|
||||
const [position, setPosition] = useState({})
|
||||
const codeSetRef = useRef<Set<NodeKey>>(new Set())
|
||||
const tableDOMNodeRef = useRef<HTMLElement | null>(null)
|
||||
|
||||
const debouncedOnMouseMove = useDebounce(
|
||||
(event: MouseEvent) => {
|
||||
const { isOutside, tableDOMNode } = getMouseInfo(event, editorConfig.editorConfig?.lexical)
|
||||
|
||||
if (isOutside) {
|
||||
setShownRow(false)
|
||||
setShownColumn(false)
|
||||
return
|
||||
}
|
||||
|
||||
if (!tableDOMNode) {
|
||||
return
|
||||
}
|
||||
|
||||
tableDOMNodeRef.current = tableDOMNode
|
||||
|
||||
let hoveredRowNode: TableCellNode | null = null
|
||||
let hoveredColumnNode: TableCellNode | null = null
|
||||
let tableDOMElement: HTMLElement | null = null
|
||||
|
||||
editor.update(() => {
|
||||
const maybeTableCell = $getNearestNodeFromDOMNode(tableDOMNode)
|
||||
|
||||
if ($isTableCellNode(maybeTableCell)) {
|
||||
const table = $findMatchingParent(maybeTableCell, (node) => $isTableNode(node))
|
||||
if (!$isTableNode(table)) {
|
||||
return
|
||||
}
|
||||
|
||||
tableDOMElement = editor.getElementByKey(table?.getKey())
|
||||
|
||||
if (tableDOMElement) {
|
||||
const rowCount = table.getChildrenSize()
|
||||
const colCount =
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
((table as TableNode).getChildAtIndex(0) as TableRowNode)?.getChildrenSize()
|
||||
|
||||
const rowIndex = $getTableRowIndexFromTableCellNode(maybeTableCell)
|
||||
const colIndex = $getTableColumnIndexFromTableCellNode(maybeTableCell)
|
||||
|
||||
if (rowIndex === rowCount - 1) {
|
||||
hoveredRowNode = maybeTableCell
|
||||
} else if (colIndex === colCount - 1) {
|
||||
hoveredColumnNode = maybeTableCell
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
if (tableDOMElement) {
|
||||
const {
|
||||
bottom: tableElemBottom,
|
||||
height: tableElemHeight,
|
||||
right: tableElemRight,
|
||||
width: tableElemWidth,
|
||||
x: tableElemX,
|
||||
y: tableElemY,
|
||||
} = (tableDOMElement as HTMLTableElement).getBoundingClientRect()
|
||||
|
||||
const { left: editorElemLeft, y: editorElemY } = anchorElem.getBoundingClientRect()
|
||||
|
||||
if (hoveredRowNode) {
|
||||
setShownColumn(false)
|
||||
setShownRow(true)
|
||||
setPosition({
|
||||
height: BUTTON_WIDTH_PX,
|
||||
left: tableElemX - editorElemLeft,
|
||||
top: tableElemBottom - editorElemY + 5,
|
||||
width: tableElemWidth,
|
||||
})
|
||||
} else if (hoveredColumnNode) {
|
||||
setShownColumn(true)
|
||||
setShownRow(false)
|
||||
setPosition({
|
||||
height: tableElemHeight,
|
||||
left: tableElemRight - editorElemLeft + 5,
|
||||
top: tableElemY - editorElemY,
|
||||
width: BUTTON_WIDTH_PX,
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
50,
|
||||
250,
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (!shouldListenMouseMove) {
|
||||
return
|
||||
}
|
||||
|
||||
document.addEventListener('mousemove', debouncedOnMouseMove)
|
||||
|
||||
return () => {
|
||||
setShownRow(false)
|
||||
setShownColumn(false)
|
||||
|
||||
document.removeEventListener('mousemove', debouncedOnMouseMove)
|
||||
}
|
||||
}, [shouldListenMouseMove, debouncedOnMouseMove])
|
||||
|
||||
useEffect(() => {
|
||||
return mergeRegister(
|
||||
editor.registerMutationListener(
|
||||
TableNode,
|
||||
(mutations) => {
|
||||
editor.getEditorState().read(() => {
|
||||
for (const [key, type] of mutations) {
|
||||
switch (type) {
|
||||
case 'created':
|
||||
codeSetRef.current.add(key)
|
||||
setShouldListenMouseMove(codeSetRef.current.size > 0)
|
||||
break
|
||||
|
||||
case 'destroyed':
|
||||
codeSetRef.current.delete(key)
|
||||
setShouldListenMouseMove(codeSetRef.current.size > 0)
|
||||
break
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
{ skipInitialization: false },
|
||||
),
|
||||
)
|
||||
}, [editor])
|
||||
|
||||
const insertAction = (insertRow: boolean) => {
|
||||
editor.update(() => {
|
||||
if (tableDOMNodeRef.current) {
|
||||
const maybeTableNode = $getNearestNodeFromDOMNode(tableDOMNodeRef.current)
|
||||
maybeTableNode?.selectEnd()
|
||||
if (insertRow) {
|
||||
$insertTableRow__EXPERIMENTAL()
|
||||
setShownRow(false)
|
||||
} else {
|
||||
$insertTableColumn__EXPERIMENTAL()
|
||||
setShownColumn(false)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{isShownRow && (
|
||||
<button
|
||||
className={editorConfig.editorConfig.lexical.theme.tableAddRows}
|
||||
onClick={() => insertAction(true)}
|
||||
style={{ ...position }}
|
||||
/>
|
||||
)}
|
||||
{isShownColumn && (
|
||||
<button
|
||||
className={editorConfig.editorConfig.lexical.theme.tableAddColumns}
|
||||
onClick={() => insertAction(false)}
|
||||
style={{ ...position }}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function getMouseInfo(
|
||||
event: MouseEvent,
|
||||
editorConfig: EditorConfig,
|
||||
): {
|
||||
isOutside: boolean
|
||||
tableDOMNode: HTMLElement | null
|
||||
} {
|
||||
const target = event.target
|
||||
|
||||
if (target && target instanceof HTMLElement) {
|
||||
const tableDOMNode = target.closest<HTMLElement>(
|
||||
`td.${editorConfig.theme.tableCell}, th.${editorConfig.theme.tableCell}`,
|
||||
)
|
||||
|
||||
const isOutside = !(
|
||||
tableDOMNode ||
|
||||
target.closest<HTMLElement>(`button.${editorConfig.theme.tableAddRows}`) ||
|
||||
target.closest<HTMLElement>(`button.${editorConfig.theme.tableAddColumns}`) ||
|
||||
target.closest<HTMLElement>(`div.${editorConfig.theme.tableCellResizer}`)
|
||||
)
|
||||
|
||||
return { isOutside, tableDOMNode }
|
||||
} else {
|
||||
return { isOutside: true, tableDOMNode: null }
|
||||
}
|
||||
}
|
||||
|
||||
export function TableHoverActionsPlugin({
|
||||
anchorElem = document.body,
|
||||
}: {
|
||||
anchorElem?: HTMLElement
|
||||
}): React.ReactPortal | null {
|
||||
return createPortal(<TableHoverActionsContainer anchorElem={anchorElem} />, anchorElem)
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import type { ToolbarGroup, ToolbarGroupItem } from '../../toolbars/types.js'
|
||||
|
||||
export const toolbarFormatGroupWithItems = (items: ToolbarGroupItem[]): ToolbarGroup => {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import type { DOMConversionOutput, LexicalNode, SerializedLexicalNode } from 'lexical'
|
||||
|
||||
import { $applyNodeReplacement } from 'lexical'
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import type { ToolbarGroup, ToolbarGroupItem } from '../../toolbars/types.js'
|
||||
|
||||
export const toolbarIndentGroupWithItems = (items: ToolbarGroupItem[]): ToolbarGroup => {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import type { LexicalCommand } from 'lexical'
|
||||
|
||||
import { createCommand } from 'lexical'
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
import type { UnknownConvertedNodeData } from './index.js'
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
import type { UnknownConvertedNodeData } from './index.js'
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import type {
|
||||
DOMConversionMap,
|
||||
DOMConversionOutput,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import type { ClientCollectionConfig, ClientUser, VisibleEntities } from 'payload'
|
||||
|
||||
import { useAuth, useConfig, useEntityVisibility } from '@payloadcms/ui'
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import type { SerializedDecoratorBlockNode } from '@lexical/react/LexicalDecoratorBlockNode.js'
|
||||
import type { DOMConversionMap, DOMConversionOutput, LexicalNode, Spread } from 'lexical'
|
||||
import type { JSX } from 'react'
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
import type { SanitizedPlugin } from '../features/typesClient.js'
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import type { LexicalEditor } from 'lexical'
|
||||
|
||||
import { useCallback } from 'react'
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
export function debounce(func: Function, wait: number) {
|
||||
let timeout: null | number = null
|
||||
return function (...args: any[]) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
export function getBoundingClientRectWithoutTransform(elem: HTMLElement): DOMRect {
|
||||
const rect = elem.getBoundingClientRect()
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import type React from 'react'
|
||||
|
||||
import { getBoundingClientRectWithoutTransform } from './getBoundingRectWithoutTransform.js'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
'use client'
|
||||
import { getCollapsedMargins } from '../utils/getCollapsedMargins.js'
|
||||
import { getBoundingClientRectWithoutTransform } from './getBoundingRectWithoutTransform.js'
|
||||
import { highlightElemOriginalPosition } from './highlightElemOriginalPosition.js'
|
||||
const TARGET_LINE_HALF_HEIGHT = 25
|
||||
const TEXT_BOX_HORIZONTAL_PADDING = -24
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
/**
|
||||
* Calculate distance between scrollerElem and target if target is not in scrollerElem
|
||||
*/
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
const replacedElements = [
|
||||
'IMG',
|
||||
'INPUT',
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
export function getCollapsedMargins(elem: HTMLElement): {
|
||||
marginBottom: number
|
||||
marginTop: number
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import type { LexicalEditor, LexicalNode } from 'lexical'
|
||||
|
||||
import { $getNodeByKey } from 'lexical'
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import type { LexicalEditor } from 'lexical'
|
||||
|
||||
import { $getRoot } from 'lexical'
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
export function isOnHandleElement(element: HTMLElement, handleElementClassName: string): boolean {
|
||||
return !!element.closest(`.${handleElementClassName}`)
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import { doesLineHeightAffectElement } from './doesLineHeightAffectElement.js'
|
||||
|
||||
export function setHandlePosition(
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import type { EditorThemeClasses } from 'lexical'
|
||||
|
||||
export const LexicalEditorTheme: EditorThemeClasses = {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import type { JSX } from 'react'
|
||||
|
||||
import { ContentEditable } from '@lexical/react/LexicalContentEditable.js'
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
export const AIIcon: React.FC = () => (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
export const AddIcon: React.FC = () => (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
export const AlignCenterIcon: React.FC = () => (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
export const AlignJustifyIcon: React.FC = () => (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
export const AlignLeftIcon: React.FC = () => (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
export const AlignRightIcon: React.FC = () => (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
export const BlockIcon: React.FC = () => (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
export const BlockquoteIcon: React.FC = () => (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
export const BoldIcon: React.FC = () => (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
export const ChecklistIcon: React.FC = () => (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
export const CodeIcon: React.FC = () => (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
export const CodeBlockIcon: React.FC = () => (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
export const H1Icon: React.FC = () => (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
export const H2Icon: React.FC = () => (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
export const H3Icon: React.FC = () => (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
export const H4Icon: React.FC = () => (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
export const H5Icon: React.FC = () => (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
export const H6Icon: React.FC = () => (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
export const HorizontalRuleIcon: React.FC = () => (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
export const IndentDecreaseIcon: React.FC = () => (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
export const IndentIncreaseIcon: React.FC = () => (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
export const InlineBlocksIcon: React.FC = () => (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
export const ItalicIcon: React.FC = () => (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
export const LinkIcon: React.FC = () => (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
export const MeatballsIcon: React.FC = () => (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
export const OrderedListIcon: React.FC = () => (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
export const RelationshipIcon: React.FC = () => (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
export const StrikethroughIcon: React.FC = () => (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
export const SubscriptIcon: React.FC = () => (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
export const SuperscriptIcon: React.FC = () => (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
export const TableIcon: React.FC = () => {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
export const TextIcon: React.FC = () => (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
export const UnderlineIcon: React.FC = () => (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
export const UnorderedListIcon: React.FC = () => (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React from 'react'
|
||||
|
||||
export const UploadIcon: React.FC = () => (
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
export const CAN_USE_DOM: boolean =
|
||||
typeof window !== 'undefined' &&
|
||||
typeof window.document !== 'undefined' &&
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import { CAN_USE_DOM } from './canUseDOM.js'
|
||||
|
||||
declare global {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
export function getDOMRangeRect(nativeSelection: Selection, rootElement: HTMLElement): DOMRect {
|
||||
const domRange = nativeSelection.getRangeAt(0)
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import type { ElementNode, RangeSelection, TextNode } from 'lexical'
|
||||
|
||||
import { $isAtNodeEnd } from '@lexical/selection'
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
export function isHTMLElement(x: unknown): x is HTMLElement {
|
||||
return x instanceof HTMLElement
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
export function joinClasses(...args: Array<boolean | null | string | undefined>): string {
|
||||
return args.filter(Boolean).join(' ')
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
export class Point {
|
||||
private readonly _x: number
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import { type Point, isPoint } from './point.js'
|
||||
|
||||
interface ContainsPointReturn {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
const VERTICAL_GAP = 10
|
||||
const HORIZONTAL_OFFSET = 5
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
const VERTICAL_GAP = 10
|
||||
const HORIZONTAL_OFFSET = 5
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
type Force = [number, number]
|
||||
type Listener = (force: Force, e: TouchEvent) => void
|
||||
interface ElementValues {
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
"composite": true, // Make sure typescript knows that this module depends on their references
|
||||
"noEmit": false /* Do not emit outputs. */,
|
||||
"emitDeclarationOnly": true,
|
||||
"esModuleInterop": true,
|
||||
"outDir": "./dist" /* Specify an output folder for all emitted files. */,
|
||||
"rootDir": "./src" /* Specify the root folder within your source files. */,
|
||||
"jsx": "react-jsx"
|
||||
},
|
||||
"exclude": [
|
||||
"dist",
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
const fs = require('fs')
|
||||
|
||||
// Plugin options can be found here: https://github.com/facebook/react/blob/main/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Options.ts#L38
|
||||
const ReactCompilerConfig = {
|
||||
sources: (filename) => {
|
||||
if (!filename.endsWith('.tsx') && !filename.endsWith('.jsx')) {
|
||||
const isInNodeModules = filename.includes('node_modules')
|
||||
if (isInNodeModules || ( !filename.endsWith('.tsx') && !filename.endsWith('.jsx') && !filename.endsWith('.js'))) {
|
||||
return false
|
||||
}
|
||||
|
||||
// read file and check if 'use client' is at top. if not, return false
|
||||
// if it is, return true
|
||||
// Only compile files with 'use client' directives. We do not want to
|
||||
// accidentally compile React Server Components
|
||||
const file = fs.readFileSync(filename, 'utf8')
|
||||
if (file.includes("'use client'")) {
|
||||
//console.log("Compiling: " + filename)
|
||||
return true
|
||||
}
|
||||
console.log('Skipping: ' + filename)
|
||||
console.log('React compiler - skipping file: ' + filename)
|
||||
return false
|
||||
},
|
||||
//runtimeModule: "react"
|
||||
}
|
||||
|
||||
module.exports = function (api) {
|
||||
@@ -25,30 +25,12 @@ module.exports = function (api) {
|
||||
return {
|
||||
plugins: [
|
||||
['babel-plugin-react-compiler', ReactCompilerConfig], // must run first!
|
||||
[
|
||||
'babel-plugin-transform-remove-imports',
|
||||
{
|
||||
test: '\\.(scss|css)$',
|
||||
},
|
||||
],
|
||||
],
|
||||
presets: [
|
||||
[
|
||||
'@babel/preset-env',
|
||||
{
|
||||
modules: false,
|
||||
useBuiltIns: 'usage',
|
||||
corejs: '3.22',
|
||||
},
|
||||
],
|
||||
[
|
||||
'@babel/preset-react',
|
||||
{
|
||||
throwIfNamespace: false,
|
||||
runtime: 'automatic',
|
||||
},
|
||||
],
|
||||
'@babel/preset-typescript',
|
||||
/* [
|
||||
'babel-plugin-transform-remove-imports',
|
||||
{
|
||||
test: '\\.(scss|css)$',
|
||||
},
|
||||
],*/
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,33 +64,27 @@ async function build() {
|
||||
entryPoints: ['src/exports/client/index.ts'],
|
||||
bundle: true,
|
||||
minify: true,
|
||||
outdir: 'dist',
|
||||
outdir: 'dist-styles',
|
||||
packages: 'external',
|
||||
plugins: [sassPlugin({ css: 'external' })],
|
||||
})
|
||||
|
||||
try {
|
||||
fs.renameSync('dist/index.css', 'dist/styles.css')
|
||||
fs.renameSync('dist-styles/index.css', 'dist/styles.css')
|
||||
fs.rmdirSync('dist-styles', { recursive: true })
|
||||
} catch (err) {
|
||||
console.error(`Error while renaming index.css: ${err}`)
|
||||
throw err
|
||||
}
|
||||
|
||||
try {
|
||||
fs.unlinkSync('dist/index.js')
|
||||
} catch (err) {
|
||||
console.error(`Error while deleting index.js: ${err}`)
|
||||
console.error(`Error while renaming index.css and dist-styles: ${err}`)
|
||||
throw err
|
||||
}
|
||||
|
||||
console.log('styles.css bundled successfully')
|
||||
// Bundle `client.ts`
|
||||
const resultClient = await esbuild.build({
|
||||
entryPoints: ['src/exports/client/index.ts'],
|
||||
entryPoints: ['dist/exports/client/index.js'],
|
||||
bundle: true,
|
||||
platform: 'browser',
|
||||
format: 'esm',
|
||||
outdir: 'dist/exports/client',
|
||||
outdir: 'dist/exports/client_optimized',
|
||||
//outfile: 'index.js',
|
||||
// IMPORTANT: splitting the client bundle means that the `use client` directive will be lost for every chunk
|
||||
splitting: true,
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { rootEslintConfig, rootParserOptions } from '../../eslint.config.js'
|
||||
|
||||
import reactCompiler from 'eslint-plugin-react-compiler'
|
||||
const { rules } = reactCompiler
|
||||
/** @typedef {import('eslint').Linter.FlatConfig} */
|
||||
let FlatConfig
|
||||
|
||||
@@ -15,6 +16,16 @@ export const index = [
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
plugins: {
|
||||
'react-compiler': {
|
||||
rules,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
'react-compiler/react-compiler': 'error',
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
export default index
|
||||
|
||||
@@ -57,13 +57,14 @@
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "rm -rf dist && rm -rf tsconfig.tsbuildinfo && pnpm copyfiles && pnpm build:types && pnpm build:swc && pnpm build:esbuild",
|
||||
"build:babel": "babel src --out-dir dist --source-maps --extensions .ts,.js,.tsx,.jsx,.cjs,.mjs",
|
||||
"build:esbuild": "node bundle.js",
|
||||
"build:reactcompiler": "pnpm copyfiles && pnpm build:babel && pnpm build:types",
|
||||
"build": "pnpm build:reactcompiler",
|
||||
"build:babel": "rm -rf dist_optimized && babel dist --out-dir dist_optimized --source-maps --extensions .ts,.js,.tsx,.jsx,.cjs,.mjs && rm -rf dist && mv dist_optimized dist",
|
||||
"build:esbuild": "node bundle.js && rm -rf dist/exports/client && mv dist/exports/client_optimized dist/exports/client",
|
||||
"build:reactcompiler": "rm -rf dist && rm -rf tsconfig.tsbuildinfo && pnpm build:swc && pnpm build:babel && pnpm copyfiles && pnpm build:esbuild && pnpm build:types",
|
||||
"build:remove-artifact": "rm dist/prod/index.js",
|
||||
"build:swc": "swc ./src -d dist --config-file .swcrc --strip-leading-paths",
|
||||
"build:types": "tsc --emitDeclarationOnly --outDir dist",
|
||||
"build_without_reactcompiler": "rm -rf dist && rm -rf tsconfig.tsbuildinfo && pnpm copyfiles && pnpm build:types && pnpm build:swc",
|
||||
"clean": "rimraf {dist,*.tsbuildinfo}",
|
||||
"copyfiles": "copyfiles -u 1 \"src/**/*.{html,css,scss,ttf,woff,woff2,eot,svg,jpg,png,json}\" dist/",
|
||||
"fix": "eslint \"src/**/*.{ts,tsx}\" --fix",
|
||||
@@ -108,9 +109,10 @@
|
||||
"@types/react-datepicker": "6.2.0",
|
||||
"@types/react-dom": "npm:types-react-dom@19.0.0-rc.0",
|
||||
"@types/uuid": "10.0.0",
|
||||
"babel-plugin-react-compiler": "0.0.0-experimental-592953e-20240517",
|
||||
"babel-plugin-react-compiler": "0.0.0-experimental-1cd8995-20240814",
|
||||
"esbuild": "0.23.0",
|
||||
"esbuild-sass-plugin": "3.3.1",
|
||||
"eslint-plugin-react-compiler": "0.0.0-experimental-d0e920e-20240815",
|
||||
"payload": "workspace:*"
|
||||
},
|
||||
"peerDependencies": {
|
||||
@@ -140,8 +142,8 @@
|
||||
"default": "./dist/providers/Config/createClientConfig/index.js"
|
||||
},
|
||||
"./css": {
|
||||
"import": "./dist/prod/styles.css",
|
||||
"default": "./dist/prod/styles.css"
|
||||
"import": "./dist/styles.css",
|
||||
"default": "./dist/styles.css"
|
||||
},
|
||||
"./scss": {
|
||||
"import": "./dist/scss/styles.scss",
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
export const getFormattedLocale = (language = 'enUS') => {
|
||||
const formattedLocales = {
|
||||
en: 'enUS',
|
||||
|
||||
@@ -35,8 +35,8 @@ export const DuplicateDocument: React.FC<Props> = ({ id, slug, singularLabel })
|
||||
|
||||
const {
|
||||
config: {
|
||||
serverURL,
|
||||
routes: { admin: adminRoute, api: apiRoute },
|
||||
serverURL,
|
||||
},
|
||||
} = useConfig()
|
||||
|
||||
@@ -113,7 +113,7 @@ export const DuplicateDocument: React.FC<Props> = ({ id, slug, singularLabel })
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<PopupList.Button id="action-duplicate" onClick={() => handleClick(false)}>
|
||||
<PopupList.Button id="action-duplicate" onClick={() => void handleClick(false)}>
|
||||
{t('general:duplicate')}
|
||||
</PopupList.Button>
|
||||
{modified && hasClicked && (
|
||||
@@ -129,7 +129,7 @@ export const DuplicateDocument: React.FC<Props> = ({ id, slug, singularLabel })
|
||||
>
|
||||
{t('general:cancel')}
|
||||
</Button>
|
||||
<Button id="confirm-duplicate" onClick={confirm}>
|
||||
<Button id="confirm-duplicate" onClick={() => void confirm()}>
|
||||
{t('general:duplicateWithoutSaving')}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import React, { forwardRef } from 'react'
|
||||
|
||||
import './index.scss'
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
'use client'
|
||||
import type { ClientField } from 'payload'
|
||||
|
||||
import { fieldAffectsData } from 'payload/shared'
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user