diff --git a/.distignore b/.distignore
index 2b85c7775612..99e10329d4bb 100644
--- a/.distignore
+++ b/.distignore
@@ -40,6 +40,7 @@ web-stories-scraper
.npmpackagejsonlintrc.json
.npmrc
.nvmrc
+.oxlintrc.json
.phpstorm.config.js
.phpstorm.meta.php
.phpunit.result.cache
diff --git a/.eslintrc b/.eslintrc
index d687e90727ae..657a0ef25401 100644
--- a/.eslintrc
+++ b/.eslintrc
@@ -20,6 +20,7 @@
"jsx-a11y",
"markdown",
"react",
+ "react-compiler",
"react-hooks",
"styled-components-a11y"
],
@@ -214,6 +215,15 @@
"react/no-unused-prop-types": "error",
"react/react-in-jsx-scope": "off",
"react/self-closing-comp": "error",
+ "react-compiler/react-compiler": [
+ "error",
+ {
+ "environment": {
+ "enableTreatRefLikeIdentifiersAsRefs": true,
+ "validateRefAccessDuringRender": false
+ }
+ }
+ ],
"import/no-extraneous-dependencies": "error",
"import/no-unresolved": "error",
"import/order": [
@@ -422,6 +432,7 @@
"rules": {
"@eslint-community/eslint-comments/require-description": "off",
"react/prop-types": "off",
+ "react-compiler/react-compiler": "off",
"jest/no-hooks": "off",
"jest/no-untyped-mock-factory": "off",
"jest/max-expects": "off",
diff --git a/.oxlintrc.json b/.oxlintrc.json
new file mode 100644
index 000000000000..a2713a8f92ec
--- /dev/null
+++ b/.oxlintrc.json
@@ -0,0 +1,13 @@
+{
+ "settings": {
+ "jsdoc": {
+ "tagNamePreference": {
+ "returns": "return",
+ "yields": "yield"
+ }
+ }
+ },
+ "rules": {
+ "no-unused-vars": "off"
+ }
+}
diff --git a/.storybook/stories/playground/dashboard/index.js b/.storybook/stories/playground/dashboard/index.js
index e0424d9b601f..3ae89f7047dd 100644
--- a/.storybook/stories/playground/dashboard/index.js
+++ b/.storybook/stories/playground/dashboard/index.js
@@ -17,7 +17,7 @@
/**
* External dependencies
*/
-import { useRef } from 'react';
+import { useRef, useEffect } from 'react';
import { toId } from '@storybook/csf';
import { Dashboard, InterfaceSkeleton } from '@googleforcreators/dashboard';
@@ -102,10 +102,12 @@ const getAuthors = () => Promise.resolve([{ name: 'Author', id: 1 }]);
const useClearHash = () => {
const isHashCleaned = useRef(false);
- if (!isHashCleaned.current) {
- window.location.hash = '/';
- isHashCleaned.current = true;
- }
+ useEffect(() => {
+ if (!isHashCleaned.current) {
+ window.location.hash = '/';
+ isHashCleaned.current = true;
+ }
+ }, []);
};
export const _default = {
diff --git a/.storybook/stories/playground/story-editor/header/buttons/preview.js b/.storybook/stories/playground/story-editor/header/buttons/preview.js
index ddd0f452ef52..83c99ff27bed 100644
--- a/.storybook/stories/playground/story-editor/header/buttons/preview.js
+++ b/.storybook/stories/playground/story-editor/header/buttons/preview.js
@@ -68,7 +68,7 @@ function PreviewButton() {
`
);
}
- } catch (e) {
+ } catch {
// Not interested in the error.
}
};
diff --git a/babel.config.cjs b/babel.config.cjs
index 9f3e1d3dbc00..7ecd390b8d10 100644
--- a/babel.config.cjs
+++ b/babel.config.cjs
@@ -46,6 +46,7 @@ module.exports = function (api) {
'@babel/preset-typescript',
],
plugins: [
+ ['babel-plugin-react-compiler', { target: '17' }],
'@wordpress/babel-plugin-import-jsx-pragma',
[
'babel-plugin-styled-components',
diff --git a/package-lock.json b/package-lock.json
index 5413d0477047..c515372011ee 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -76,6 +76,7 @@
"ajv-formats": "^3.0.1",
"babel-jest": "^29.6.1",
"babel-loader": "^9.2.1",
+ "babel-plugin-react-compiler": "0.0.0-experimental-63cca73-20250106",
"babel-plugin-styled-components": "^2.1.4",
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
"browserslist": "^4.24.4",
@@ -100,6 +101,7 @@
"eslint-plugin-oxlint": "^0.15.5",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-react": "^7.37.3",
+ "eslint-plugin-react-compiler": "0.0.0-experimental-63cca73-20250106",
"eslint-plugin-react-hooks": "^5.1.0",
"eslint-plugin-security": "^3.0.1",
"eslint-plugin-styled-components-a11y": "^2.2.0",
@@ -135,6 +137,7 @@
"postcss-syntax": "^0.36.2",
"prettier": "^3.4.2",
"puppeteer": "^23.11.1",
+ "react-compiler-runtime": "0.0.0-experimental-63cca73-20250106",
"react-refresh": "^0.16.0",
"react-test-renderer": "^17.0.2",
"rollup": "^2.79.2",
@@ -1017,6 +1020,24 @@
"@babel/core": "^7.0.0-0"
}
},
+ "node_modules/@babel/plugin-proposal-private-methods": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz",
+ "integrity": "sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==",
+ "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-methods instead.",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
"node_modules/@babel/plugin-syntax-async-generators": {
"version": "7.8.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
@@ -11878,6 +11899,16 @@
"@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
}
},
+ "node_modules/babel-plugin-react-compiler": {
+ "version": "0.0.0-experimental-63cca73-20250106",
+ "resolved": "https://registry.npmjs.org/babel-plugin-react-compiler/-/babel-plugin-react-compiler-0.0.0-experimental-63cca73-20250106.tgz",
+ "integrity": "sha512-XYdCAnSJbMGLlrbxI9jCKsM+pIVJnbeHkNJxqIT8jTzw1aHXO6Udv/WCsIQvGdwpKsl4gcDdtRYTTgpoeeOSJw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.19.0"
+ }
+ },
"node_modules/babel-plugin-styled-components": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.1.4.tgz",
@@ -15987,6 +16018,27 @@
"eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7"
}
},
+ "node_modules/eslint-plugin-react-compiler": {
+ "version": "0.0.0-experimental-63cca73-20250106",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-compiler/-/eslint-plugin-react-compiler-0.0.0-experimental-63cca73-20250106.tgz",
+ "integrity": "sha512-lhEPJoBlmTJvcezxc+nqHGFm9l7ZKZlWQ/sZR7tBYtRSdTB4et+Js8OVYIGAfPoDwY2za/v9A/3gVM2ZXb7Fzw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/core": "^7.24.4",
+ "@babel/parser": "^7.24.4",
+ "@babel/plugin-proposal-private-methods": "^7.18.6",
+ "hermes-parser": "^0.25.1",
+ "zod": "^3.22.4",
+ "zod-validation-error": "^3.0.3"
+ },
+ "engines": {
+ "node": "^14.17.0 || ^16.0.0 || >= 18.0.0"
+ },
+ "peerDependencies": {
+ "eslint": ">=7"
+ }
+ },
"node_modules/eslint-plugin-react-hooks": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.1.0.tgz",
@@ -19319,6 +19371,23 @@
"tslib": "^2.0.3"
}
},
+ "node_modules/hermes-estree": {
+ "version": "0.25.1",
+ "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz",
+ "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/hermes-parser": {
+ "version": "0.25.1",
+ "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz",
+ "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hermes-estree": "0.25.1"
+ }
+ },
"node_modules/highlight-words-core": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/highlight-words-core/-/highlight-words-core-1.2.2.tgz",
@@ -29541,6 +29610,16 @@
"react-dom": ">=16.8.0"
}
},
+ "node_modules/react-compiler-runtime": {
+ "version": "0.0.0-experimental-63cca73-20250106",
+ "resolved": "https://registry.npmjs.org/react-compiler-runtime/-/react-compiler-runtime-0.0.0-experimental-63cca73-20250106.tgz",
+ "integrity": "sha512-u26xZxhdUTaA3/A/9nT/fbQ8iBQ3sAxJN+8Cspe06YERZHEJd4H81RITuKBfdYjyv6VYYWRkBMXo9ES1odbiZw==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "react": "^17.0.0 || ^18.0.0 || ^19.0.0 || ^0.0.0-experimental"
+ }
+ },
"node_modules/react-css-styled": {
"version": "1.1.9",
"resolved": "https://registry.npmjs.org/react-css-styled/-/react-css-styled-1.1.9.tgz",
@@ -36461,6 +36540,19 @@
"url": "https://github.com/sponsors/colinhacks"
}
},
+ "node_modules/zod-validation-error": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-3.4.0.tgz",
+ "integrity": "sha512-ZOPR9SVY6Pb2qqO5XHt+MkkTRxGXb4EVtnjc9JpXUOtUB1T9Ru7mZOT361AN3MsetVe7R0a1KZshJDZdgp9miQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "zod": "^3.18.0"
+ }
+ },
"packages/activation-notice": {
"name": "@web-stories-wp/activation-notice",
"license": "Apache-2.0",
diff --git a/package.json b/package.json
index 85c5e50a4362..5318ae57eff8 100644
--- a/package.json
+++ b/package.json
@@ -100,6 +100,7 @@
"ajv-formats": "^3.0.1",
"babel-jest": "^29.6.1",
"babel-loader": "^9.2.1",
+ "babel-plugin-react-compiler": "0.0.0-experimental-63cca73-20250106",
"babel-plugin-styled-components": "^2.1.4",
"babel-plugin-transform-react-remove-prop-types": "^0.4.24",
"browserslist": "^4.24.4",
@@ -124,6 +125,7 @@
"eslint-plugin-oxlint": "^0.15.5",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-react": "^7.37.3",
+ "eslint-plugin-react-compiler": "0.0.0-experimental-63cca73-20250106",
"eslint-plugin-react-hooks": "^5.1.0",
"eslint-plugin-security": "^3.0.1",
"eslint-plugin-styled-components-a11y": "^2.2.0",
@@ -159,6 +161,7 @@
"postcss-syntax": "^0.36.2",
"prettier": "^3.4.2",
"puppeteer": "^23.11.1",
+ "react-compiler-runtime": "0.0.0-experimental-63cca73-20250106",
"react-refresh": "^0.16.0",
"react-test-renderer": "^17.0.2",
"rollup": "^2.79.2",
@@ -221,9 +224,9 @@
"lint:css:js:fix": "stylelint \"**/*.js\" --fix",
"lint:css:css": "stylelint \"**/*.css\"",
"lint:css:css:fix": "stylelint \"**/*.css\" --fix",
- "lint:js": "oxlint && eslint .",
- "lint:js:fix": "oxlint --fix && eslint --fix .",
- "lint:js:report": "oxlint && eslint --output-file build/lint-js-report.json --format json .",
+ "lint:js": "oxlint -c=.oxlintrc.json --tsconfig=tsconfig.json --ignore-pattern=@types --react-perf-plugin && eslint .",
+ "lint:js:fix": "oxlint --fix -c=.oxlintrc.json --tsconfig=tsconfig.json --ignore-pattern=@types --react-perf-plugin && eslint --fix .",
+ "lint:js:report": "oxlint -c=.oxlintrc.json --tsconfig=tsconfig.json --ignore-pattern=@types --react-perf-plugin && eslint --output-file build/lint-js-report.json --format json .",
"lint:package-json": "npmPkgJsonLint .",
"lint:php": "composer phpcs",
"lint:php:fix": "composer phpcbf",
diff --git a/packages/dashboard/src/app/api/useStoryApi.js b/packages/dashboard/src/app/api/useStoryApi.js
index 9cca0e5c039a..1428842f945c 100644
--- a/packages/dashboard/src/app/api/useStoryApi.js
+++ b/packages/dashboard/src/app/api/useStoryApi.js
@@ -51,13 +51,13 @@ const useStoryApi = () => {
const [state, dispatch] = useReducer(storyReducer, defaultStoriesState);
const { apiCallbacks } = useConfig();
- const isMounted = useRef(false);
+ const isMountedRef = useRef(false);
useEffect(() => {
- isMounted.current = true;
+ isMountedRef.current = true;
return () => {
- isMounted.current = false;
+ isMountedRef.current = false;
};
}, []);
@@ -78,7 +78,7 @@ const useStoryApi = () => {
const { stories, fetchedStoryIds, totalPages, totalStoriesByStatus } =
await apiCallbacks.fetchStories(queryParams);
- if (!isMounted.current) {
+ if (!isMountedRef.current) {
return;
}
diff --git a/packages/dashboard/src/app/views/exploreTemplates/content/templateGridView.js b/packages/dashboard/src/app/views/exploreTemplates/content/templateGridView.js
index 4a37c7882317..194c9b9ee3e6 100644
--- a/packages/dashboard/src/app/views/exploreTemplates/content/templateGridView.js
+++ b/packages/dashboard/src/app/views/exploreTemplates/content/templateGridView.js
@@ -48,7 +48,7 @@ function TemplateGridView({
const { isRTL, apiCallbacks } = useConfig();
const containerRef = useRef();
const gridRef = useRef();
- const itemRefs = useRef({});
+ const itemsRef = useRef({});
const [activeGridItemId, setActiveGridItemId] = useState(null);
const { handleDetailsToggle, createStoryFromTemplate } =
templateActions || {};
@@ -58,7 +58,7 @@ function TemplateGridView({
useGridViewKeys({
containerRef,
gridRef,
- itemRefs,
+ itemRefs: itemsRef,
isRTL,
currentItemId: activeGridItemId,
items: filteredTemplates,
@@ -69,7 +69,7 @@ function TemplateGridView({
// for legibility, it's based on the FOCUS_TEMPLATE_CLASS
useEffect(() => {
if (activeGridItemId) {
- itemRefs.current?.[activeGridItemId]
+ itemsRef.current?.[activeGridItemId]
?.querySelector(`.${FOCUS_TEMPLATE_CLASS}`)
?.focus();
}
@@ -97,7 +97,7 @@ function TemplateGridView({
key={slug}
posterSrc={posterSrc}
ref={(el) => {
- itemRefs.current[id] = el;
+ itemsRef.current[id] = el;
}}
slug={slug}
status={status}
diff --git a/packages/dashboard/src/app/views/myStories/content/storiesView/index.js b/packages/dashboard/src/app/views/myStories/content/storiesView/index.js
index 0c27f6868694..b5c6caea41a7 100644
--- a/packages/dashboard/src/app/views/myStories/content/storiesView/index.js
+++ b/packages/dashboard/src/app/views/myStories/content/storiesView/index.js
@@ -113,7 +113,7 @@ function StoriesView({ loading, storyActions, stories, view }) {
const handleOnDeleteStory = useCallback(() => {
trackEvent('delete_story');
storyActions.trashStory(activeStory);
- setFocusedStory({ id: activeStory.id, isDeleted: true });
+ setFocusedStory({ id: activeStory?.id, isDeleted: true });
setActiveDialog('');
}, [storyActions, activeStory]);
@@ -162,6 +162,11 @@ function StoriesView({ loading, storyActions, stories, view }) {
[showSnackbar]
);
+ const handleCloseConfirmDialog = useCallback(() => {
+ setFocusedStory({ id: activeStory?.id });
+ setActiveDialog('');
+ }, [activeStory]);
+
const menuItems = STORY_CONTEXT_MENU_ITEMS.map((item) => {
switch (item?.value) {
case STORY_CONTEXT_MENU_ACTIONS.COPY_STORY_LINK:
@@ -257,10 +262,7 @@ function StoriesView({ loading, storyActions, stories, view }) {
isOpen
contentLabel={__('Dialog to confirm deleting a story', 'web-stories')}
title={__('Delete Story', 'web-stories')}
- onClose={() => {
- setFocusedStory({ id: activeStory.id });
- setActiveDialog('');
- }}
+ onClose={handleCloseConfirmDialog}
secondaryText={__('Cancel', 'web-stories')}
secondaryRest={{
['aria-label']: sprintf(
diff --git a/packages/dashboard/src/app/views/myStories/content/storyGridView/index.js b/packages/dashboard/src/app/views/myStories/content/storyGridView/index.js
index 606044a686d3..9cc3fc3d0733 100644
--- a/packages/dashboard/src/app/views/myStories/content/storyGridView/index.js
+++ b/packages/dashboard/src/app/views/myStories/content/storyGridView/index.js
@@ -62,7 +62,7 @@ const StoryGridView = ({
const { isRTL } = useConfig();
const containerRef = useRef();
const gridRef = useRef();
- const itemRefs = useRef({});
+ const itemsRef = useRef({});
const [activeGridItemId, setActiveGridItemId] = useState();
const activeGridItemIdRef = useRef();
const gridItemIds = useMemo(() => stories.map(({ id }) => id), [stories]);
@@ -70,7 +70,7 @@ const StoryGridView = ({
useGridViewKeys({
containerRef,
gridRef,
- itemRefs,
+ itemRefs: itemsRef,
isRTL,
currentItemId: activeGridItemId,
items: stories,
@@ -90,7 +90,7 @@ const StoryGridView = ({
const newFocusId = returnStoryFocusId?.value;
setActiveGridItemId(newFocusId);
// grab the menu button and refocus
- const firstFocusableElement = itemRefs.current?.[
+ const firstFocusableElement = itemsRef.current?.[
newFocusId
]?.querySelectorAll(['button', 'a'])?.[0];
@@ -171,7 +171,7 @@ const StoryGridView = ({
onFocus={() => setActiveGridItemId(story.id)}
isActive={activeGridItemId === story.id}
ref={(el) => {
- itemRefs.current[story.id] = el;
+ itemsRef.current[story.id] = el;
}}
key={story.id}
pageSize={pageSize}
diff --git a/packages/dashboard/src/app/views/myStories/index.js b/packages/dashboard/src/app/views/myStories/index.js
index 0797034ff964..97b1a5228b4f 100644
--- a/packages/dashboard/src/app/views/myStories/index.js
+++ b/packages/dashboard/src/app/views/myStories/index.js
@@ -79,13 +79,13 @@ function MyStoriesView() {
);
const { apiCallbacks, canViewDefaultTemplates } = useConfig();
- const isMounted = useRef(false);
+ const isMountedRef = useRef(false);
useEffect(() => {
- isMounted.current = true;
+ isMountedRef.current = true;
return () => {
- isMounted.current = false;
+ isMountedRef.current = false;
};
}, []);
diff --git a/packages/dashboard/src/components/cardGallery/index.js b/packages/dashboard/src/components/cardGallery/index.js
index 8810f7e108b6..47386b21c433 100644
--- a/packages/dashboard/src/components/cardGallery/index.js
+++ b/packages/dashboard/src/components/cardGallery/index.js
@@ -55,7 +55,7 @@ function CardGallery({ galleryPosters, isRTL, galleryLabel }) {
const [focusedGridItemIndex, setFocusedGridItemIndex] = useState();
const containerRef = useRef();
const gridRef = useRef();
- const posterRefs = useRef({});
+ const postersRef = useRef({});
const handleMiniCardClick = useCallback((index) => {
setSelectedGridItemIndex(index);
@@ -77,7 +77,7 @@ function CardGallery({ galleryPosters, isRTL, galleryLabel }) {
useGridViewKeys({
containerRef,
gridRef,
- itemRefs: posterRefs,
+ itemRefs: postersRef,
isRTL,
currentItemId: focusedGridItemIndex,
items: galleryPosters,
@@ -96,7 +96,7 @@ function CardGallery({ galleryPosters, isRTL, galleryLabel }) {
{
- posterRefs.current[index] = el;
+ postersRef.current[index] = el;
}}
onFocus={() => handleGalleryItemFocus(index)}
>
diff --git a/packages/dashboard/src/components/interfaceSkeleton/index.js b/packages/dashboard/src/components/interfaceSkeleton/index.js
index b0779e19ef02..811e839ad5d1 100644
--- a/packages/dashboard/src/components/interfaceSkeleton/index.js
+++ b/packages/dashboard/src/components/interfaceSkeleton/index.js
@@ -72,9 +72,11 @@ const InterfaceSkeleton = ({ additionalRoutes }) => {
addInitialFetchListener,
})
);
- const isFirstLoadOnMyStories = useRef(currentPath === APP_ROUTES.DASHBOARD);
+ const isFirstLoadOnMyStoriesRef = useRef(
+ currentPath === APP_ROUTES.DASHBOARD
+ );
const [isRedirectComplete, setIsRedirectComplete] = useState(
- !isFirstLoadOnMyStories.current
+ !isFirstLoadOnMyStoriesRef.current
);
// Direct user to templates on first load if they
@@ -83,11 +85,11 @@ const InterfaceSkeleton = ({ additionalRoutes }) => {
return addInitialFetchListener?.((storyStatuses) => {
if (
storyStatuses?.all <= 0 &&
- isFirstLoadOnMyStories.current &&
+ isFirstLoadOnMyStoriesRef.current &&
canViewDefaultTemplates
) {
push(APP_ROUTES.TEMPLATES_GALLERY);
- isFirstLoadOnMyStories.current = false;
+ isFirstLoadOnMyStoriesRef.current = false;
}
setIsRedirectComplete(true);
});
diff --git a/packages/dashboard/src/karma/integrationLayerTesting/config.karma.js b/packages/dashboard/src/karma/integrationLayerTesting/config.karma.js
index f8d5854aac4b..94930da53c69 100644
--- a/packages/dashboard/src/karma/integrationLayerTesting/config.karma.js
+++ b/packages/dashboard/src/karma/integrationLayerTesting/config.karma.js
@@ -31,7 +31,7 @@ describe('Integration Layer tests : EditorConfig Params :', () => {
MINIMUM_CONFIG[key] = undefined;
}
MINIMUM_CONFIG.apiCallbacks = {
- fetchStories: () => new Promise.resolve({}),
+ fetchStories: () => Promise.resolve({}),
};
});
diff --git a/packages/dashboard/src/utils/useStoryView.js b/packages/dashboard/src/utils/useStoryView.js
index 9ba2a8f5c1d8..6ad2b96c9be3 100644
--- a/packages/dashboard/src/utils/useStoryView.js
+++ b/packages/dashboard/src/utils/useStoryView.js
@@ -50,7 +50,7 @@ export default function useStoryView({
const [sort, _setSort] = useState(sortObject);
const [filters, _setFilters] = useState(filtersObject);
const [page, setPage] = useState(1);
- const showStoriesWhileLoading = useRef(false);
+ const showStoriesWhileLoadingRef = useRef(false);
const [initialPageReady, setInitialPageReady] = useState(false);
const { pageSize } = usePagePreviewSize({
@@ -90,7 +90,7 @@ export default function useStoryView({
}, [viewStyle, setViewStyle]);
const requestNextPage = useCallback(() => {
- showStoriesWhileLoading.current = true;
+ showStoriesWhileLoadingRef.current = true;
setPageClamped(page + 1);
}, [page, setPageClamped]);
@@ -111,7 +111,7 @@ export default function useStoryView({
useEffect(() => {
// reset ref state after request is finished
if (!isLoading) {
- showStoriesWhileLoading.current = false;
+ showStoriesWhileLoadingRef.current = false;
}
}, [isLoading]);
@@ -156,7 +156,7 @@ export default function useStoryView({
requestNextPage,
},
initialPageReady,
- showStoriesWhileLoading,
+ showStoriesWhileLoading: showStoriesWhileLoadingRef,
}),
[
viewStyle,
diff --git a/packages/design-system/src/components/contextMenu/components/subMenuTrigger.tsx b/packages/design-system/src/components/contextMenu/components/subMenuTrigger.tsx
index 283aaf8ff327..aece08f26e3e 100644
--- a/packages/design-system/src/components/contextMenu/components/subMenuTrigger.tsx
+++ b/packages/design-system/src/components/contextMenu/components/subMenuTrigger.tsx
@@ -62,7 +62,7 @@ function SubMenuTrigger({
...buttonProps
}: SubMenuTriggerProps) {
const ref = useRef
(null);
- const pointerTracker = useRef<{ x?: number; y?: number }>({});
+ const pointerTrackerRef = useRef<{ x?: number; y?: number }>({});
const { setFocusedId } = useContextMenu(({ actions }) => ({
setFocusedId: actions.setFocusedId,
@@ -70,7 +70,7 @@ function SubMenuTrigger({
const pointerIsOutside = (node: Element) => {
const { x, y, width, height } = node.getBoundingClientRect();
- const { x: pointerX, y: pointerY } = pointerTracker.current;
+ const { x: pointerX, y: pointerY } = pointerTrackerRef.current;
if (pointerX === undefined || pointerY === undefined) {
return true;
}
@@ -118,8 +118,8 @@ function SubMenuTrigger({
const onPointerMove = (e: Event) => {
if (e instanceof PointerEvent) {
// Track the pointer when moving inside the menu while the submenu is open.
- pointerTracker.current.x = e.clientX;
- pointerTracker.current.y = e.clientY;
+ pointerTrackerRef.current.x = e.clientX;
+ pointerTrackerRef.current.y = e.clientY;
maybeCloseSubMenu();
}
};
@@ -162,7 +162,7 @@ function SubMenuTrigger({
onPointerEnter={openSubMenu}
onPointerLeave={() => {
// Reset tracker in case we moved out of the menu fully.
- pointerTracker.current = {};
+ pointerTrackerRef.current = {};
maybeCloseSubMenu();
}}
onClick={(e: MouseEvent) => e.preventDefault()}
diff --git a/packages/design-system/src/components/contextMenu/menu.tsx b/packages/design-system/src/components/contextMenu/menu.tsx
index c6faf29416d4..99402aafeaee 100644
--- a/packages/design-system/src/components/contextMenu/menu.tsx
+++ b/packages/design-system/src/components/contextMenu/menu.tsx
@@ -240,7 +240,7 @@ const Menu = forwardRef<
const keyOut = isHorizontal ? KEYS.UP : isRTL ? KEYS.RIGHT : KEYS.LEFT;
// Maybe move from submenu to parent menu.
- if (isSubMenu && keyOut === key && parentMenuRef.current) {
+ if (isSubMenu && keyOut === key && parentMenuRef?.current) {
// Get the button with expanded popup.
const parentButton = parentMenuRef.current.querySelector(
'button[aria-expanded="true"]'
diff --git a/packages/design-system/src/components/datalist/list/list.tsx b/packages/design-system/src/components/datalist/list/list.tsx
index 713512c56b8d..b39a1777beae 100644
--- a/packages/design-system/src/components/datalist/list/list.tsx
+++ b/packages/design-system/src/components/datalist/list/list.tsx
@@ -81,7 +81,7 @@ function OptionListWithRef(
const listRef = useForwardedRef(forwardedListRef);
const optionsRef = useRef<(HTMLLIElement | null)[]>([]);
const [focusIndex, setFocusIndex] = useState(-1);
- const userSeenOptions = useRef([]);
+ const userSeenOptionsRef = useRef([]);
/*
* KEYWORD FILTERING
@@ -134,11 +134,11 @@ function OptionListWithRef(
.filter((t): t is HTMLElement => t instanceof HTMLElement)
.map((target) => target.dataset.option)
.filter((o): o is string => Boolean(o));
- userSeenOptions.current = addUniqueEntries(
- userSeenOptions.current,
+ userSeenOptionsRef.current = addUniqueEntries(
+ userSeenOptionsRef.current,
...newlySeenOptions
);
- onObserve(userSeenOptions.current);
+ onObserve(userSeenOptionsRef.current);
}
},
{
diff --git a/packages/design-system/src/components/input/useNumericInput.tsx b/packages/design-system/src/components/input/useNumericInput.tsx
index 7829d7835717..eb6da40d2044 100644
--- a/packages/design-system/src/components/input/useNumericInput.tsx
+++ b/packages/design-system/src/components/input/useNumericInput.tsx
@@ -16,7 +16,7 @@
/**
* External dependencies
*/
-import Big from 'big.js';
+import { Big } from 'big.js';
import {
useCallback,
useEffect,
@@ -45,8 +45,8 @@ const useNumericInput = ({
}: UseNumericInputProps) => {
const _inputRef = useRef(null);
const inputRef = ref && 'current' in ref ? ref : _inputRef;
- const oldValue = useRef(value);
- const revertToOriginal = useRef(false);
+ const oldValueRef = useRef(value);
+ const revertToOriginalRef = useRef(false);
const [currentValue, setCurrentValue] = useState(value);
const options = useMemo(
() => ({ allowEmpty, isFloat, padZero, max, min }),
@@ -58,9 +58,9 @@ const useNumericInput = ({
*/
const handleBlur = useCallback(
(ev: unknown) => {
- let newValue = parseInput(oldValue.current, options);
+ let newValue = parseInput(oldValueRef.current, options);
- if (!revertToOriginal.current && newValue !== null) {
+ if (!revertToOriginalRef.current && newValue !== null) {
const parsedValue = parseInput(currentValue, options);
if (parsedValue !== null) {
@@ -70,11 +70,11 @@ const useNumericInput = ({
newValue = parseInput(currentValue, options);
}
- revertToOriginal.current = false;
+ revertToOriginalRef.current = false;
if (newValue !== null) {
// Set newly updated value.
setCurrentValue(newValue);
- if (newValue !== oldValue.current) {
+ if (newValue !== oldValueRef.current) {
onChange(ev, newValue);
}
} else if (min !== undefined) {
@@ -205,14 +205,14 @@ const useNumericInput = ({
* Blur input and revert value to original value
*/
const handleEsc = useCallback(() => {
- setCurrentValue(oldValue.current);
- revertToOriginal.current = true;
+ setCurrentValue(oldValueRef.current);
+ revertToOriginalRef.current = true;
inputRef?.current?.blur();
}, [inputRef]);
useEffect(() => {
// update internal value when `value` prop changes
- oldValue.current = value;
+ oldValueRef.current = value;
setCurrentValue(value);
}, [value]);
@@ -225,7 +225,7 @@ const useNumericInput = ({
handleChange,
handleEsc,
handleKeyUpAndDown,
- isIndeterminate: oldValue.current === currentValue,
+ isIndeterminate: oldValueRef.current === currentValue,
};
};
diff --git a/packages/design-system/src/components/popup/popup.tsx b/packages/design-system/src/components/popup/popup.tsx
index 36f11985b70e..cb3e8b3b0495 100644
--- a/packages/design-system/src/components/popup/popup.tsx
+++ b/packages/design-system/src/components/popup/popup.tsx
@@ -82,12 +82,12 @@ function Popup({
offset: Offset;
height: number | null;
} | null>(null);
- const isMounted = useRef(false);
+ const isMountedRef = useRef(false);
const popup = useRef(null);
const positionPopup = useCallback(
(evt?: unknown) => {
- if (!isMounted.current || !anchor?.current) {
+ if (!isMountedRef.current || !anchor?.current) {
return;
}
// If scrolling within the popup, ignore.
@@ -182,9 +182,9 @@ function Popup({
);
useEffect(() => {
- isMounted.current = true;
+ isMountedRef.current = true;
return () => {
- isMounted.current = false;
+ isMountedRef.current = false;
};
}, []);
@@ -202,18 +202,18 @@ function Popup({
if (!isOpen) {
return undefined;
}
- isMounted.current = true;
+ isMountedRef.current = true;
positionPopup();
// Adjust the position when scrolling.
document.addEventListener('scroll', positionPopup, true);
return () => {
document.removeEventListener('scroll', positionPopup, true);
- isMounted.current = false;
+ isMountedRef.current = false;
};
}, [isOpen, positionPopup]);
useLayoutEffect(() => {
- if (!isMounted.current) {
+ if (!isMountedRef.current) {
return;
}
diff --git a/packages/design-system/src/components/tooltip/tooltip.tsx b/packages/design-system/src/components/tooltip/tooltip.tsx
index a68bae5db5c0..63dc37688a05 100644
--- a/packages/design-system/src/components/tooltip/tooltip.tsx
+++ b/packages/design-system/src/components/tooltip/tooltip.tsx
@@ -131,11 +131,11 @@ function Tooltip({
const tooltipRef = useRef(null);
const placementRef = useRef(placement);
const [dynamicPlacement, setDynamicPlacement] = useState(placement);
- const isMounted = useRef(false);
+ const isMountedRef = useRef(false);
const [popupState, setPopupState] = useState<{ offset?: Offset }>({});
- const isPopupMounted = useRef(false);
- const popup = useRef(null);
+ const isPopupMountedRef = useRef(false);
+ const popupRef = useRef(null);
const isOpen = Boolean(shown && (shortcut || title));
const [dynamicOffset, setDynamicOffset] = useState<{ x?: number }>({});
@@ -160,7 +160,7 @@ function Tooltip({
);
const positionPopup = useCallback(() => {
- if (!isPopupMounted.current || !anchorRef?.current) {
+ if (!isPopupMountedRef.current || !anchorRef?.current) {
return;
}
setPopupState({
@@ -169,7 +169,7 @@ function Tooltip({
placement: dynamicPlacement,
spacing,
anchor: getAnchor(),
- popup,
+ popup: popupRef,
isRTL,
ignoreMaxOffsetY: true,
})
@@ -191,7 +191,7 @@ function Tooltip({
const shouldMoveToTop =
dynamicPlacement.startsWith('bottom') &&
neededVerticalSpace >= window.innerHeight;
- // We can sometimes render a tooltip too far to the left, ie. in RTL mode, or with the wp-admin sidenav.
+ // We can sometimes render a tooltip too far to the left, i.e. in RTL mode, or with the wp-admin sidenav.
// When that is the case, let's update the offset.
const isOverFlowingLeft = Math.trunc(left) < (isRTL ? 0 : leftOffset);
// The getOffset util has a maxOffset that prevents the tooltip from being render too far to the right. However, when
@@ -239,10 +239,10 @@ function Tooltip({
const resetPlacement = useDebouncedCallback(() => {
setDynamicPlacement(placementRef.current);
}, 100);
- const delay = useRef | null>(null);
+ const delayRef = useRef | null>(null);
const onHover = useCallback(() => {
const handle = () => {
- if (!isMounted.current) {
+ if (!isMountedRef.current) {
return;
}
@@ -255,11 +255,11 @@ function Tooltip({
// Show instantly
handle();
}
- if (delay.current) {
- clearTimeout(delay.current);
+ if (delayRef.current) {
+ clearTimeout(delayRef.current);
}
// Invoke in DELAY_MS
- delay.current = setTimeout(handle, DELAY_MS);
+ delayRef.current = setTimeout(handle, DELAY_MS);
} else {
handle();
}
@@ -267,8 +267,8 @@ function Tooltip({
const onHoverOut = useCallback(() => {
setShown(false);
resetPlacement();
- if (isDelayed && delay.current) {
- clearTimeout(delay.current);
+ if (isDelayed && delayRef.current) {
+ clearTimeout(delayRef.current);
if (shown) {
lastVisibleDelayedTooltip = performance.now();
}
@@ -276,18 +276,18 @@ function Tooltip({
}, [resetPlacement, isDelayed, shown]);
useEffect(() => {
- isMounted.current = true;
+ isMountedRef.current = true;
return () => {
- isMounted.current = false;
+ isMountedRef.current = false;
};
}, []);
useEffect(() => {
- isPopupMounted.current = true;
+ isPopupMountedRef.current = true;
return () => {
- isPopupMounted.current = false;
+ isPopupMountedRef.current = false;
};
}, []);
@@ -295,19 +295,19 @@ function Tooltip({
if (!isOpen) {
return undefined;
}
- isPopupMounted.current = true;
+ isPopupMountedRef.current = true;
positionPopup();
// Adjust the position when scrolling.
document.addEventListener('scroll', positionPopup, true);
return () => {
document.removeEventListener('scroll', positionPopup, true);
- isPopupMounted.current = false;
+ isPopupMountedRef.current = false;
};
}, [isOpen, positionPopup]);
useLayoutEffect(() => {
- if (!isPopupMounted.current) {
+ if (!isPopupMountedRef.current) {
return;
}
@@ -339,7 +339,7 @@ function Tooltip({
{popupState?.offset && isOpen
? createPortal(
(ref: React.ForwardedRef) {
const wrappedRef = useRef<{ current: T | null }>({ current: null });
- const reference = useRef(null);
+ const referenceRef = useRef(null);
Object.defineProperty(wrappedRef.current, 'current', {
- get: () => reference.current,
+ get: () => referenceRef.current,
set: (value: T | null) => {
- if (!Object.is(reference.current, value)) {
- reference.current = value;
+ if (!Object.is(referenceRef.current, value)) {
+ referenceRef.current = value;
if (!ref) {
return;
}
if (typeof ref === 'function') {
- ref(reference.current);
+ ref(referenceRef.current);
} else {
- ref.current = reference.current;
+ ref.current = referenceRef.current;
}
}
},
diff --git a/packages/e2e-test-utils/src/customFonts.js b/packages/e2e-test-utils/src/customFonts.js
index 1fa34217a4ba..cf026178e222 100644
--- a/packages/e2e-test-utils/src/customFonts.js
+++ b/packages/e2e-test-utils/src/customFonts.js
@@ -59,7 +59,7 @@ export const getFontList = async () => {
)
);
return parseText(optionsText);
- } catch (e) {
+ } catch {
return [];
}
};
diff --git a/packages/element-library/src/media/edit.tsx b/packages/element-library/src/media/edit.tsx
index bf1eaf8f6b73..e3c7dded8b00 100644
--- a/packages/element-library/src/media/edit.tsx
+++ b/packages/element-library/src/media/edit.tsx
@@ -153,29 +153,29 @@ function MediaEdit({
const [cropBox, setCropBox] = useState(null);
const elementRef = useRef(null);
- const isUpdatedLocally = useRef(false);
- const lastLocalProperties = useRef>({ scale } as Partial);
+ const isUpdatedLocallyRef = useRef(false);
+ const lastLocalPropertiesRef = useRef>({ scale } as Partial);
const updateLocalProperties = useCallback(
(properties: Partial | ((p: Partial) => Partial)) => {
- lastLocalProperties.current = {
- ...lastLocalProperties.current,
+ lastLocalPropertiesRef.current = {
+ ...lastLocalPropertiesRef.current,
...(typeof properties === 'function'
- ? properties(lastLocalProperties.current)
+ ? properties(lastLocalPropertiesRef.current)
: properties),
};
- isUpdatedLocally.current = true;
- setLocalProperties(lastLocalProperties.current);
+ isUpdatedLocallyRef.current = true;
+ setLocalProperties(lastLocalPropertiesRef.current);
},
[setLocalProperties]
);
const updateProperties = useCallback(() => {
- if (!isUpdatedLocally.current) {
+ if (!isUpdatedLocallyRef.current) {
return;
}
- isUpdatedLocally.current = false;
- const properties: Partial = lastLocalProperties.current;
+ isUpdatedLocallyRef.current = false;
+ const properties: Partial = lastLocalPropertiesRef.current;
updateElementById({ elementId: id, properties });
}, [id, updateElementById]);
diff --git a/packages/karma-puppeteer-client/src/client.js b/packages/karma-puppeteer-client/src/client.js
index e7cdd6c4452a..6547baacc108 100644
--- a/packages/karma-puppeteer-client/src/client.js
+++ b/packages/karma-puppeteer-client/src/client.js
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-(function (global) {
+(function () {
'use strict';
function noCleanup() {}
diff --git a/packages/rich-text/src/provider.tsx b/packages/rich-text/src/provider.tsx
index 4acd951f7ed3..cd936797e301 100644
--- a/packages/rich-text/src/provider.tsx
+++ b/packages/rich-text/src/provider.tsx
@@ -58,7 +58,7 @@ export interface RichTextProviderProps {
}
function RichTextProvider({ children, editingState }: RichTextProviderProps) {
const [editorState, setEditorState] = useState(null);
- const lastKnownStyle = useRef(null);
+ const lastKnownStyleRef = useRef(null);
const selectionInfo = useMemo(() => {
if (editorState) {
@@ -81,7 +81,7 @@ function RichTextProvider({ children, editingState }: RichTextProviderProps) {
if (selection) {
state = EditorState.forceSelection(state, selection);
}
- lastKnownStyle.current = state.getCurrentInlineStyle();
+ lastKnownStyleRef.current = state.getCurrentInlineStyle();
setEditorState(state);
},
[editingState, setEditorState]
@@ -100,14 +100,14 @@ function RichTextProvider({ children, editingState }: RichTextProviderProps) {
let filteredState = getFilteredState(newEditorState, editorState);
const isEmpty =
filteredState?.getCurrentContent().getPlainText('') === '';
- if (isEmpty && lastKnownStyle.current) {
+ if (isEmpty && lastKnownStyleRef.current) {
// Copy last known current style as inline style
filteredState = EditorState.setInlineStyleOverride(
filteredState,
- lastKnownStyle.current
+ lastKnownStyleRef.current
);
} else {
- lastKnownStyle.current = filteredState.getCurrentInlineStyle();
+ lastKnownStyleRef.current = filteredState.getCurrentInlineStyle();
}
setEditorState(filteredState);
},
diff --git a/packages/rich-text/src/useSelectionManipulation.ts b/packages/rich-text/src/useSelectionManipulation.ts
index 21710136c05d..481a3e8e9cc5 100644
--- a/packages/rich-text/src/useSelectionManipulation.ts
+++ b/packages/rich-text/src/useSelectionManipulation.ts
@@ -37,14 +37,14 @@ function useSelectionManipulation(
editorState: EditorState | null,
setEditorState: Dispatch>
): Record {
- const lastKnownState = useRef(null);
- const lastKnownSelection = useRef(null);
+ const lastKnownStateRef = useRef(null);
+ const lastKnownSelectionRef = useRef(null);
useEffect(() => {
- lastKnownState.current = editorState;
+ lastKnownStateRef.current = editorState;
if (!editorState) {
- lastKnownSelection.current = null;
+ lastKnownSelectionRef.current = null;
} else if (editorState.getSelection().getHasFocus()) {
- lastKnownSelection.current = editorState.getSelection();
+ lastKnownSelectionRef.current = editorState.getSelection();
}
}, [editorState]);
@@ -53,8 +53,8 @@ function useSelectionManipulation(
updater: (state: EditorState | null) => EditorState,
shouldForceFocus = true
) => {
- const oldState = lastKnownState.current;
- const selection = lastKnownSelection.current;
+ const oldState = lastKnownStateRef.current;
+ const selection = lastKnownSelectionRef.current;
const workingState =
shouldForceFocus && oldState && selection
? EditorState.forceSelection(oldState, selection)
diff --git a/packages/stories-block/src/block/block-types/single-story/edit.js b/packages/stories-block/src/block/block-types/single-story/edit.js
index 0c4c515f702b..0a771e0ece77 100644
--- a/packages/stories-block/src/block/block-types/single-story/edit.js
+++ b/packages/stories-block/src/block/block-types/single-story/edit.js
@@ -28,8 +28,7 @@ import { trackEvent } from '@googleforcreators/tracking';
import { useCallback, useEffect, useRef, useState } from '@wordpress/element';
import apiFetch from '@wordpress/api-fetch';
import { ResizableBox } from '@wordpress/components';
-import * as compose from '@wordpress/compose';
-import { withViewportMatch } from '@wordpress/viewport';
+import { useViewportMatch } from '@wordpress/compose';
import { useDispatch, useSelect } from '@wordpress/data';
import { __ } from '@wordpress/i18n';
import { store as blockEditorStore } from '@wordpress/block-editor';
@@ -53,7 +52,6 @@ function StoryEmbedEdit({
setAttributes,
className,
isSelected,
- _isResizable,
context = {},
}) {
const {
@@ -86,9 +84,7 @@ function StoryEmbedEdit({
const showLoadingIndicator = isFetchingData;
const showPlaceholder = !localURL || !outerURL || editingURL || cannotEmbed;
- const isResizable = compose.useViewportMatch
- ? compose.useViewportMatch('medium')
- : _isResizable;
+ const isResizable = useViewportMatch('medium');
const ref = useRef();
@@ -390,11 +386,10 @@ StoryEmbedEdit.propTypes = {
setAttributes: PropTypes.func.isRequired,
className: PropTypes.string.isRequired,
isSelected: PropTypes.bool,
- _isResizable: PropTypes.bool,
context: PropTypes.shape({
postType: PropTypes.string,
postId: PropTypes.number,
}),
};
-export default withViewportMatch({ _isResizable: 'medium' })(StoryEmbedEdit);
+export default StoryEmbedEdit;
diff --git a/packages/stories-block/src/block/block-types/single-story/editInLoop.js b/packages/stories-block/src/block/block-types/single-story/editInLoop.js
index fbca4998eba3..4f1e67e53237 100644
--- a/packages/stories-block/src/block/block-types/single-story/editInLoop.js
+++ b/packages/stories-block/src/block/block-types/single-story/editInLoop.js
@@ -25,8 +25,7 @@ import classNames from 'classnames';
*/
import { useEffect, useRef } from '@wordpress/element';
import { Placeholder, ResizableBox } from '@wordpress/components';
-import * as compose from '@wordpress/compose';
-import { withViewportMatch } from '@wordpress/viewport';
+import { useViewportMatch } from '@wordpress/compose';
import { useDispatch, useSelect } from '@wordpress/data';
import { __ } from '@wordpress/i18n';
import { store as blockEditorStore, BlockIcon } from '@wordpress/block-editor';
@@ -50,7 +49,6 @@ function StoryEmbedEditInLoop({
setAttributes,
className,
isSelected,
- _isResizable,
context = {},
}) {
const {
@@ -95,9 +93,7 @@ function StoryEmbedEditInLoop({
};
}, []);
- const isResizable = compose.useViewportMatch
- ? compose.useViewportMatch('medium')
- : _isResizable;
+ const isResizable = useViewportMatch('medium');
const ref = useRef();
@@ -271,13 +267,10 @@ StoryEmbedEditInLoop.propTypes = {
setAttributes: PropTypes.func.isRequired,
className: PropTypes.string.isRequired,
isSelected: PropTypes.bool,
- _isResizable: PropTypes.bool,
context: PropTypes.shape({
postType: PropTypes.string,
postId: PropTypes.number,
}),
};
-export default withViewportMatch({ _isResizable: 'medium' })(
- StoryEmbedEditInLoop
-);
+export default StoryEmbedEditInLoop;
diff --git a/packages/stories-block/src/block/components/storyPicker/selectStories.js b/packages/stories-block/src/block/components/storyPicker/selectStories.js
index cee6bb9e72a0..ec3e75743d7b 100644
--- a/packages/stories-block/src/block/components/storyPicker/selectStories.js
+++ b/packages/stories-block/src/block/components/storyPicker/selectStories.js
@@ -134,7 +134,7 @@ function SelectStories({
const [authorKeyword, setAuthorKeyword] = useState('');
const [order, setOrder] = useState('desc');
const [orderBy, setOrderBy] = useState('modified');
- const nextPage = useRef(1);
+ const nextPageRef = useRef(1);
const { authors } = useSelect(
(select) => {
@@ -160,17 +160,17 @@ function SelectStories({
search: searchKeyword || undefined,
order,
orderby: orderBy,
- page: nextPage.current,
+ page: nextPageRef.current,
});
}, [searchKeyword, currentAuthor, fetchStories, order, orderBy]);
useEffect(() => {
- nextPage.current = 1;
+ nextPageRef.current = 1;
fetchSelectedStories();
}, [searchKeyword, currentAuthor, order, orderBy, fetchSelectedStories]);
const onLoadMoreClick = useCallback(() => {
- nextPage.current++;
+ nextPageRef.current++;
fetchSelectedStories();
}, [fetchSelectedStories]);
diff --git a/packages/stories-block/src/block/components/storyPicker/storyPicker.js b/packages/stories-block/src/block/components/storyPicker/storyPicker.js
index 3a548347f319..f6fd6e057c72 100644
--- a/packages/stories-block/src/block/components/storyPicker/storyPicker.js
+++ b/packages/stories-block/src/block/components/storyPicker/storyPicker.js
@@ -99,7 +99,7 @@ function StoryPicker({
setStories((existingStories) =>
page === 1 ? response.body : [...existingStories, ...response.body]
);
- } catch (err) {
+ } catch {
setLoadingState('error');
createErrorNotice(__('Unable to load stories', 'web-stories'), {
type: 'snackbar',
diff --git a/packages/story-editor/src/app/api/apiProvider.tsx b/packages/story-editor/src/app/api/apiProvider.tsx
index e23580815446..e90cb7bf8199 100644
--- a/packages/story-editor/src/app/api/apiProvider.tsx
+++ b/packages/story-editor/src/app/api/apiProvider.tsx
@@ -44,25 +44,32 @@ const filterTemplates = (templates: Template[], search: string): Template[] => {
function APIProvider({ children }: PropsWithChildren>) {
const { apiCallbacks: actions, cdnURL } = useConfig();
- const pageTemplates = useRef([]);
+ const pageTemplatesRef = useRef([]);
- actions.getPageTemplates = useCallback(
- async (search: string) => {
- // check if pageTemplates have been loaded yet
- if (pageTemplates.current.length === 0) {
- pageTemplates.current = filterTemplates(
- await getAllTemplates({
- cdnURL,
- }),
- search
- );
- }
- return filterTemplates(pageTemplates.current, search);
- },
- [cdnURL]
- );
+ const newActions = {
+ ...actions,
+ getPageTemplates: useCallback(
+ async (search: string) => {
+ // check if pageTemplates have been loaded yet
+ if (pageTemplatesRef.current.length === 0) {
+ pageTemplatesRef.current = filterTemplates(
+ await getAllTemplates({
+ cdnURL,
+ }),
+ search
+ );
+ }
+ return filterTemplates(pageTemplatesRef.current, search);
+ },
+ [cdnURL]
+ ),
+ };
- return {children};
+ return (
+
+ {children}
+
+ );
}
export default APIProvider;
diff --git a/packages/story-editor/src/app/canvas/canvasProvider.tsx b/packages/story-editor/src/app/canvas/canvasProvider.tsx
index 18e1471330c6..e5f513fb8aeb 100644
--- a/packages/story-editor/src/app/canvas/canvasProvider.tsx
+++ b/packages/story-editor/src/app/canvas/canvasProvider.tsx
@@ -56,7 +56,7 @@ function CanvasProvider({ children }: PropsWithChildren) {
const [boundingBoxes, setBoundingBoxes] = useState({});
const [lastSelectionEvent, setLastSelectionEvent] =
useState(null);
- const lastSelectedElementId = useRef(null);
+ const lastSelectedElementIdRef = useRef(null);
const [canvasContainer, setCanvasContainer] = useState(null);
const [pageContainer, setPageContainer] = useState(null);
const [fullbleedContainer, setFullbleedContainer] = useState(
@@ -158,10 +158,10 @@ function CanvasProvider({ children }: PropsWithChildren) {
// Skip the focus that immediately follows mouse event.
// Use the reference to the latest element because the events come in the
// sequence in the same event loop.
- if (lastSelectedElementId.current === elId && evt.type === 'focus') {
+ if (lastSelectedElementIdRef.current === elId && evt.type === 'focus') {
return;
}
- lastSelectedElementId.current = elId;
+ lastSelectedElementIdRef.current = elId;
if (evt.shiftKey) {
toggleElementInSelection({ elementId: elId, withLinked: !evt.altKey });
} else {
@@ -210,10 +210,10 @@ function CanvasProvider({ children }: PropsWithChildren) {
clearEditing();
}
if (
- lastSelectedElementId.current &&
- !selectedElementIds.includes(lastSelectedElementId.current)
+ lastSelectedElementIdRef.current &&
+ !selectedElementIds.includes(lastSelectedElementIdRef.current)
) {
- lastSelectedElementId.current = null;
+ lastSelectedElementIdRef.current = null;
}
}, [editingElement, selectedElementIds, clearEditing]);
diff --git a/packages/story-editor/src/app/font/fontProvider.tsx b/packages/story-editor/src/app/font/fontProvider.tsx
index 048df3a9764c..b507bbe8795f 100644
--- a/packages/story-editor/src/app/font/fontProvider.tsx
+++ b/packages/story-editor/src/app/font/fontProvider.tsx
@@ -167,22 +167,22 @@ function FontProvider({ children }: PropsWithChildren) {
[recentFonts]
);
- const menuFonts = useRef([]);
+ const menuFontsRef = useRef([]);
const ensureMenuFontsLoaded = useCallback((fontsToLoad: string[]) => {
const newMenuFonts = fontsToLoad.filter(
- (fontName) => !menuFonts.current.includes(fontName)
+ (fontName) => !menuFontsRef.current.includes(fontName)
);
if (!newMenuFonts?.length) {
return;
}
- menuFonts.current = menuFonts.current.concat(newMenuFonts);
+ menuFontsRef.current = menuFontsRef.current.concat(newMenuFonts);
// Create new in head with ref to new font families
const families = encodeURIComponent(newMenuFonts.join('|'));
const url = `${GOOGLE_MENU_FONT_URL}?family=${families}&subset=menu&display=swap`;
loadStylesheet(url, 'web-stories-google-fonts-menu-css').catch(() => {
// If they failed to load, remove from array again!
- menuFonts.current = menuFonts.current.filter(
+ menuFontsRef.current = menuFontsRef.current.filter(
(font) => !newMenuFonts.includes(font)
);
});
diff --git a/packages/story-editor/src/app/history/historyProvider.tsx b/packages/story-editor/src/app/history/historyProvider.tsx
index 1bd4e9d6c764..1fed04faf733 100644
--- a/packages/story-editor/src/app/history/historyProvider.tsx
+++ b/packages/story-editor/src/app/history/historyProvider.tsx
@@ -52,7 +52,7 @@ function HistoryProvider({
const [hasNewChanges, setHasNewChanges] = useState(false);
const setPreventUnload = usePreventWindowUnload();
// The version number for the initially loaded (saved) state is 1.
- const savedVersionNumber = useRef(1);
+ const savedVersionNumberRef = useRef(1);
useEffect(() => {
setPreventUnload('history', hasNewChanges);
@@ -60,12 +60,12 @@ function HistoryProvider({
}, [setPreventUnload, hasNewChanges]);
useEffect(() => {
- setHasNewChanges(versionNumber !== savedVersionNumber.current);
+ setHasNewChanges(versionNumber !== savedVersionNumberRef.current);
}, [versionNumber]);
const resetNewChanges = useCallback(() => {
// When new changes are saved, let's track which version was saved.
- savedVersionNumber.current = versionNumber;
+ savedVersionNumberRef.current = versionNumber;
setHasNewChanges(false);
}, [versionNumber]);
diff --git a/packages/story-editor/src/app/media/local/useContextValueProvider.js b/packages/story-editor/src/app/media/local/useContextValueProvider.js
index e36a511f709e..04be9324f227 100644
--- a/packages/story-editor/src/app/media/local/useContextValueProvider.js
+++ b/packages/story-editor/src/app/media/local/useContextValueProvider.js
@@ -72,13 +72,13 @@ export default function useContextValueProvider(reducerState, reducerActions) {
actions: { getMedia, updateMedia },
} = useAPI();
- const isMounted = useRef(false);
+ const isMountedRef = useRef(false);
useEffect(() => {
- isMounted.current = true;
+ isMountedRef.current = true;
return () => {
- isMounted.current = false;
+ isMountedRef.current = false;
};
}, []);
@@ -104,7 +104,7 @@ export default function useContextValueProvider(reducerState, reducerActions) {
pagingNum: p,
})
.then(({ data, headers }) => {
- if (!isMounted.current) {
+ if (!isMountedRef.current) {
return;
}
diff --git a/packages/story-editor/src/app/media/media3p/test/useContextValueProvider.js b/packages/story-editor/src/app/media/media3p/test/useContextValueProvider.js
index 6b04eb8829de..80e4bc728f12 100644
--- a/packages/story-editor/src/app/media/media3p/test/useContextValueProvider.js
+++ b/packages/story-editor/src/app/media/media3p/test/useContextValueProvider.js
@@ -14,6 +14,11 @@
* limitations under the License.
*/
+/**
+ * External dependencies
+ */
+import { renderHook } from '@testing-library/react-hooks';
+
/**
* Internal dependencies
*/
@@ -28,16 +33,18 @@ describe('useContextValueProvider', () => {
state: { media: [] },
});
- const value = useContextValueProvider(
- {
- selectedProvider: 'unsplash',
- searchTerm: '',
- unsplash: {},
- },
- { setSelectedProvider: () => {}, setSearchTerm: () => {} }
+ const { result } = renderHook(() =>
+ useContextValueProvider(
+ {
+ selectedProvider: 'unsplash',
+ searchTerm: '',
+ unsplash: {},
+ },
+ { setSelectedProvider: () => {}, setSearchTerm: () => {} }
+ )
);
- expect(value).toStrictEqual(
+ expect(result.current).toStrictEqual(
expect.objectContaining({
state: { selectedProvider: 'unsplash', searchTerm: '' },
actions: {
diff --git a/packages/story-editor/src/app/media/media3p/useFetchCategoriesEffect.js b/packages/story-editor/src/app/media/media3p/useFetchCategoriesEffect.js
index 993068bf7054..c5bc753224b4 100644
--- a/packages/story-editor/src/app/media/media3p/useFetchCategoriesEffect.js
+++ b/packages/story-editor/src/app/media/media3p/useFetchCategoriesEffect.js
@@ -63,7 +63,7 @@ export default function useFetchCategoriesEffect({
provider: PROVIDERS[provider].provider,
});
fetchCategoriesSuccess({ provider, categories: newCategories });
- } catch (e) {
+ } catch {
fetchCategoriesError({ provider });
showSnackbar({
message: PROVIDERS[provider].fetchCategoriesErrorMessage,
diff --git a/packages/story-editor/src/app/media/uploadQueue/useMediaUploadQueue.ts b/packages/story-editor/src/app/media/uploadQueue/useMediaUploadQueue.ts
index 81f319cc1b75..f4ae0d2354e0 100644
--- a/packages/story-editor/src/app/media/uploadQueue/useMediaUploadQueue.ts
+++ b/packages/story-editor/src/app/media/uploadQueue/useMediaUploadQueue.ts
@@ -105,7 +105,7 @@ function useMediaUploadQueue() {
const { uploadVideoPoster } = useUploadVideoFrame({});
- const isMounted = useRef(false);
+ const isMountedRef = useRef(false);
const currentTranscodingItem = useRef(null);
const currentPosterGenerationItem = useRef(null);
@@ -150,7 +150,7 @@ function useMediaUploadQueue() {
const { resource: newResource, posterFile } =
await getResourceFromLocalFile(file);
- if (!isMounted.current) {
+ if (!isMountedRef.current) {
return;
}
@@ -204,7 +204,7 @@ function useMediaUploadQueue() {
height,
};
- if (!isMounted.current) {
+ if (!isMountedRef.current) {
return;
}
@@ -270,7 +270,7 @@ function useMediaUploadQueue() {
try {
const newFile = await convertGifToVideo(file);
- if (!isMounted.current) {
+ if (!isMountedRef.current) {
return;
}
@@ -304,7 +304,7 @@ function useMediaUploadQueue() {
const { start, end } = trimData;
const newFile = await trimVideo(file, start, end);
- if (!isMounted.current) {
+ if (!isMountedRef.current) {
return;
}
@@ -331,7 +331,7 @@ function useMediaUploadQueue() {
try {
const newFile = await stripAudioFromVideo(file);
- if (!isMounted.current) {
+ if (!isMountedRef.current) {
return;
}
@@ -364,7 +364,7 @@ function useMediaUploadQueue() {
const newFile = await cropResource(file, additionalData.cropParams);
const posterFile = await getFirstFrameOfVideo(newFile);
- if (!isMounted.current) {
+ if (!isMountedRef.current) {
return;
}
@@ -397,7 +397,7 @@ function useMediaUploadQueue() {
try {
const newFile = await transcodeVideo(file);
- if (!isMounted.current) {
+ if (!isMountedRef.current) {
return;
}
@@ -435,7 +435,7 @@ function useMediaUploadQueue() {
additionalData
)) as QueueItemResource;
- if (!isMounted.current) {
+ if (!isMountedRef.current) {
return;
}
@@ -455,7 +455,7 @@ function useMediaUploadQueue() {
posterFile
);
- if (!isMounted.current) {
+ if (!isMountedRef.current) {
return;
}
@@ -483,7 +483,7 @@ function useMediaUploadQueue() {
additionalData
)) as ImageResource;
- if (!isMounted.current) {
+ if (!isMountedRef.current) {
return;
}
@@ -674,10 +674,10 @@ function useMediaUploadQueue() {
}, [state.queue, uploadItem]);
useEffect(() => {
- isMounted.current = true;
+ isMountedRef.current = true;
return () => {
- isMounted.current = false;
+ isMountedRef.current = false;
};
}, []);
diff --git a/packages/story-editor/src/app/media/useMediaReducer.js b/packages/story-editor/src/app/media/useMediaReducer.js
index 494d00595d6d..7d2bd509adb0 100644
--- a/packages/story-editor/src/app/media/useMediaReducer.js
+++ b/packages/story-editor/src/app/media/useMediaReducer.js
@@ -84,7 +84,7 @@ function useMediaReducer(reducer = rootReducer, actionsToWrap) {
() => ({ local: localActionsToWrap, media3p: media3pActionsToWrap }),
[]
);
- actionsToWrap = actionsToWrap ?? defaultActionsToWrap;
+ const newActionsToWrap = actionsToWrap ?? defaultActionsToWrap;
const initialValue = useMemo(
() => reducer(undefined, { type: types.INITIAL_STATE }),
@@ -93,8 +93,8 @@ function useMediaReducer(reducer = rootReducer, actionsToWrap) {
const [state, dispatch] = useReducer(reducer, initialValue);
const wrappedActions = useMemo(
- () => wrapWithDispatch(actionsToWrap, dispatch),
- [actionsToWrap]
+ () => wrapWithDispatch(newActionsToWrap, dispatch),
+ [newActionsToWrap]
);
return {
diff --git a/packages/story-editor/src/app/media/utils/useDetectBlurhash.js b/packages/story-editor/src/app/media/utils/useDetectBlurhash.js
index c7d3fb77c6b7..6a3421735cc7 100644
--- a/packages/story-editor/src/app/media/utils/useDetectBlurhash.js
+++ b/packages/story-editor/src/app/media/utils/useDetectBlurhash.js
@@ -101,7 +101,7 @@ function useDetectBlurHash({ updateMediaElement }) {
blurHash,
});
}
- } catch (error) {
+ } catch {
// This might happen as an author when trying to updateMedia() that
// was uploaded by someone else.
// Do nothing with the error for now.
@@ -130,7 +130,7 @@ function useDetectBlurHash({ updateMediaElement }) {
if (posterResource) {
imageSrc = getSmallestUrlForWidth(300, posterResource);
}
- } catch (error) {
+ } catch {
// The user might not have the permission to access the video with context=edit.
// This might happen as an author when the video
// was uploaded by someone else.
diff --git a/packages/story-editor/src/app/story/effects/useHashState.ts b/packages/story-editor/src/app/story/effects/useHashState.ts
index 9e8d417b14f3..c1377b5b1945 100644
--- a/packages/story-editor/src/app/story/effects/useHashState.ts
+++ b/packages/story-editor/src/app/story/effects/useHashState.ts
@@ -64,7 +64,7 @@ function useHashState(
_value = JSON.parse(decodeURI(paramValue)) as string;
}
} catch {
- // @TODO Add some error handling
+ /* empty */
}
return _value;
});
diff --git a/packages/story-editor/src/components/autoSaveHandler/index.js b/packages/story-editor/src/components/autoSaveHandler/index.js
index 9ca4a9b2b489..adbf758c732c 100644
--- a/packages/story-editor/src/components/autoSaveHandler/index.js
+++ b/packages/story-editor/src/components/autoSaveHandler/index.js
@@ -37,9 +37,9 @@ function AutoSaveHandler() {
const isUploading = useIsUploadingToStory();
// Cache it to make it stable in terms of the below timeout
- const cachedSaveStory = useRef(autoSave);
+ const cachedSaveStoryRef = useRef(autoSave);
useEffect(() => {
- cachedSaveStory.current = autoSave;
+ cachedSaveStoryRef.current = autoSave;
}, [autoSave]);
useEffect(() => {
@@ -50,7 +50,7 @@ function AutoSaveHandler() {
// back false after the save.
// This timeout will thus be re-started when some new change occurs after an autosave.
const timeout = setTimeout(
- () => cachedSaveStory.current(),
+ () => cachedSaveStoryRef.current(),
autoSaveInterval * 1000
);
diff --git a/packages/story-editor/src/components/canvas/editLayer.js b/packages/story-editor/src/components/canvas/editLayer.js
index e344b673848b..b7b0c78af79e 100644
--- a/packages/story-editor/src/components/canvas/editLayer.js
+++ b/packages/story-editor/src/components/canvas/editLayer.js
@@ -106,19 +106,19 @@ function EditLayerForElement({ element, showOverflow }) {
return () => focusCanvas(/* force */ false);
}, [focusCanvas]);
- const moveable = useRef(null);
+ const moveableRef = useRef(null);
const setRef = useCallback(
- (moveableRef) => {
- moveable.current = moveableRef;
- onMoveableMount?.(moveableRef);
+ (newMoveable) => {
+ moveableRef.current = newMoveable;
+ onMoveableMount?.(newMoveable);
},
[onMoveableMount]
);
const onResize = useCallback(() => {
// Update moveable when resizing.
- if (moveable.current) {
- moveable.current.updateRect();
+ if (moveableRef.current) {
+ moveableRef.current.updateRect();
}
}, []);
diff --git a/packages/story-editor/src/components/canvas/eyedropperLayer.js b/packages/story-editor/src/components/canvas/eyedropperLayer.js
index eff556ca9de1..8c7cf1833a16 100644
--- a/packages/story-editor/src/components/canvas/eyedropperLayer.js
+++ b/packages/story-editor/src/components/canvas/eyedropperLayer.js
@@ -151,10 +151,10 @@ function EyedropperLayer() {
const fullHeight = pageWidth / FULLBLEED_RATIO;
const img = eyedropperImg;
const imgRef = useRef();
- const magnifier = useRef();
- const magnifierInfo = useRef();
- const magnifierColor = useRef();
- const eyedropperCanvas = useRef();
+ const magnifierRef = useRef();
+ const magnifierInfoRef = useRef();
+ const magnifierColorRef = useRef();
+ const eyedropperCanvasRef = useRef();
const closeEyedropper = () => {
setIsEyedropperActive(false);
@@ -162,7 +162,7 @@ function EyedropperLayer() {
setEyedropperPixelData(null);
};
- useFocusOut(eyedropperCanvas, closeEyedropper, [isEyedropperActive, img]);
+ useFocusOut(eyedropperCanvasRef, closeEyedropper, [isEyedropperActive, img]);
useGlobalKeyDownEffect('esc', closeEyedropper);
@@ -185,7 +185,7 @@ function EyedropperLayer() {
}
const magnify = (x, y) => {
- const canvas = magnifier.current;
+ const canvas = magnifierRef.current;
if (canvas) {
const ctx = canvas.getContext('2d');
@@ -227,14 +227,14 @@ function EyedropperLayer() {
const y = (e.clientY - top) * (fullHeight / height);
if (x < 0 || y < 0 || x > width || y > height) {
- magnifierInfo.current.style.display = 'none';
+ magnifierInfoRef.current.style.display = 'none';
return;
} else {
- magnifierInfo.current.style.display = 'block';
+ magnifierInfoRef.current.style.display = 'block';
}
// Move magnifier canvas.
- magnifierInfo.current.style.transform = `translate(${
+ magnifierInfoRef.current.style.transform = `translate(${
x - MAGNIFIER_SIZE / 2
}px, ${y}px)`;
@@ -245,14 +245,14 @@ function EyedropperLayer() {
const rgbaObject = getColorFromPixelData(eyedropperPixelData, x, y, width);
const { r, g, b, a } = rgbaObject;
const hex = rgba(r, g, b, a);
- magnifierColor.current.style.background = `rgba(${r},${g},${b},${a})`;
- magnifierColor.current.style.color = readableColor(
+ magnifierColorRef.current.style.background = `rgba(${r},${g},${b},${a})`;
+ magnifierColorRef.current.style.color = readableColor(
hex,
'#333',
'#EDEDED',
false
);
- magnifierColor.current.innerText = hex;
+ magnifierColorRef.current.innerText = hex;
};
const onClick = (e) => {
@@ -278,17 +278,17 @@ function EyedropperLayer() {
{/* Remove the safe zone so we don't have to move the canvas image up (we have fullbleed image). */}
{/* eslint-disable-next-line styled-components-a11y/click-events-have-key-events, styled-components-a11y/no-static-element-interactions -- No pixel-by-pixel keyboard navigation. */}
-
+
-
+
-
+
diff --git a/packages/story-editor/src/components/canvas/layout.js b/packages/story-editor/src/components/canvas/layout.js
index dfb5ea75f78a..0f31354d156b 100644
--- a/packages/story-editor/src/components/canvas/layout.js
+++ b/packages/story-editor/src/components/canvas/layout.js
@@ -408,13 +408,13 @@ const PageArea = forwardRef(function PageArea(
);
// We need to ref scroll, because scroll changes should not update a non-controlled layer
- const scroll = useRef();
- scroll.current = { top: scrollTop, left: scrollLeft };
+ const scrollRef = useRef();
+ scrollRef.current = { top: scrollTop, left: scrollLeft };
// If zoom setting changes for a non-controlled layer, make sure to reset actual scroll inside container
useEffect(() => {
if (!isControlled) {
- fullbleedRef.current.scrollTop = scroll.current.top;
- fullbleedRef.current.scrollLeft = scroll.current.left;
+ fullbleedRef.current.scrollTop = scrollRef.current.top;
+ fullbleedRef.current.scrollLeft = scrollRef.current.left;
}
}, [isControlled, zoomSetting, fullbleedRef]);
diff --git a/packages/story-editor/src/components/colorPicker/colorPicker.js b/packages/story-editor/src/components/colorPicker/colorPicker.js
index 351cde0dee81..6cf6aa49de52 100644
--- a/packages/story-editor/src/components/colorPicker/colorPicker.js
+++ b/packages/story-editor/src/components/colorPicker/colorPicker.js
@@ -124,16 +124,16 @@ function ColorPicker({
// So, if the eyedropper is used from inside a floating menu color picker
// the debounced onChange can never be seen.
// this gives us a way to process that change when no longer mounted
- const isMounted = useRef(true);
+ const isMountedRef = useRef(true);
useEffect(() => {
return () => {
- isMounted.current = false;
+ isMountedRef.current = false;
};
}, []);
const handleColorChange = useCallback(
(newColor) => {
- if (isMounted.current) {
+ if (isMountedRef.current) {
onDebouncedChange(newColor);
} else {
onChange(newColor);
diff --git a/packages/story-editor/src/components/colorPicker/currentColorPicker.js b/packages/story-editor/src/components/colorPicker/currentColorPicker.js
index 5075f922f17e..40fb54a90813 100644
--- a/packages/story-editor/src/components/colorPicker/currentColorPicker.js
+++ b/packages/story-editor/src/components/colorPicker/currentColorPicker.js
@@ -259,23 +259,23 @@ const CurrentColorPickerContext = createContext([false, false]);
const DynamicImportWrapper = () => {
return (...args) => {
function DynamicFetcher({ showOpacity, hasEyedropper, ...props }) {
- const isMounted = useRef(false);
+ const isMountedRef = useRef(false);
const [Picker, setPicker] = useState(null);
useEffect(() => {
- isMounted.current = true;
+ isMountedRef.current = true;
import(
/* webpackChunkName: "chunk-react-color" */
/* webpackExports: "CustomPicker" */
'@hello-pangea/color-picker'
).then(({ CustomPicker }) => {
- if (isMounted.current) {
+ if (isMountedRef.current) {
setPicker({ component: CustomPicker(...args) });
}
});
return () => {
- isMounted.current = false;
+ isMountedRef.current = false;
};
}, []);
diff --git a/packages/story-editor/src/components/colorPicker/customColorPicker.js b/packages/story-editor/src/components/colorPicker/customColorPicker.js
index d2b67aecfdd9..880805b348bc 100644
--- a/packages/story-editor/src/components/colorPicker/customColorPicker.js
+++ b/packages/story-editor/src/components/colorPicker/customColorPicker.js
@@ -65,10 +65,10 @@ function CustomColorPicker({
},
} = useColor();
- const isMounted = useRef(true);
+ const isMountedRef = useRef(true);
useEffect(() => {
return () => {
- isMounted.current = false;
+ isMountedRef.current = false;
};
}, []);
@@ -96,7 +96,7 @@ function CustomColorPicker({
// check for unmount and if so, we know this change event
// is from the eyedropper so we can just grab the rgb and
// trigger the rest of the change for the element.
- if (!isMounted.current && e?.rgb) {
+ if (!isMountedRef.current && e?.rgb) {
handleColorChange({ color: e.rgb });
}
},
diff --git a/packages/story-editor/src/components/colorPicker/gradientLine.js b/packages/story-editor/src/components/colorPicker/gradientLine.js
index 83189b12850b..132adb14b1c9 100644
--- a/packages/story-editor/src/components/colorPicker/gradientLine.js
+++ b/packages/story-editor/src/components/colorPicker/gradientLine.js
@@ -96,7 +96,7 @@ function GradientLine({
useKeyMoveStop(line, onMove);
useKeyAddStop(line, onAdd, stops, currentStopIndex);
useKeyDeleteStop(line, onDelete);
- const stopRefs = useKeyFocus(line, stops, currentStopIndex);
+ const stopsRef = useKeyFocus(line, stops, currentStopIndex);
usePointerMoveStop(line, onMove);
const tempPointerPosition = usePointerAddStop(line, onAdd);
@@ -109,7 +109,8 @@ function GradientLine({
{stops.map(({ position, color }, index) => (
(stopRefs[index].current = ref)}
+ // eslint-disable-next-line react-compiler/react-compiler -- FIXME
+ ref={(ref) => (stopsRef[index].current = ref)}
key={
// eslint-disable-next-line react/no-array-index-key -- Should be OK here.
index
diff --git a/packages/story-editor/src/components/colorPicker/usePointerMoveStop.js b/packages/story-editor/src/components/colorPicker/usePointerMoveStop.js
index 0d69ae0fe3c5..6dd5e1d36072 100644
--- a/packages/story-editor/src/components/colorPicker/usePointerMoveStop.js
+++ b/packages/story-editor/src/components/colorPicker/usePointerMoveStop.js
@@ -26,17 +26,17 @@ import { LINE_LENGTH } from './constants';
import { getPageX, setPointerCapture, releasePointerCapture } from './utils';
function usePointerMoveStop(ref, onMove) {
- const lastPageX = useRef(null);
+ const lastPageXRef = useRef(null);
useLayoutEffect(() => {
const node = ref.current;
const onPointerMove = (evt) => {
- const relativeDeltaX = getPageX(evt) - lastPageX.current;
- lastPageX.current = getPageX(evt);
+ const relativeDeltaX = getPageX(evt) - lastPageXRef.current;
+ lastPageXRef.current = getPageX(evt);
onMove(-relativeDeltaX / LINE_LENGTH);
};
const onPointerUp = (evt) => {
- lastPageX.current = null;
+ lastPageXRef.current = null;
releasePointerCapture(evt);
evt.target.removeEventListener('pointermove', onPointerMove);
evt.target.removeEventListener('pointerup', onPointerUp);
@@ -46,7 +46,7 @@ function usePointerMoveStop(ref, onMove) {
if (evt.target === node) {
return;
}
- lastPageX.current = getPageX(evt);
+ lastPageXRef.current = getPageX(evt);
setPointerCapture(evt);
evt.target.addEventListener('pointermove', onPointerMove);
evt.target.addEventListener('pointerup', onPointerUp);
diff --git a/packages/story-editor/src/components/errorBoundary/copyStoryDataToClipboard.js b/packages/story-editor/src/components/errorBoundary/copyStoryDataToClipboard.js
index 23bb6e3512ef..fefaa2fae968 100644
--- a/packages/story-editor/src/components/errorBoundary/copyStoryDataToClipboard.js
+++ b/packages/story-editor/src/components/errorBoundary/copyStoryDataToClipboard.js
@@ -48,7 +48,7 @@ function CopyStoryDataToClipboard() {
try {
await navigator.clipboard.writeText(jsonStr);
alert(__('Copied to clipboard', 'web-stories'));
- } catch (err) {
+ } catch {
alert(__('Failed to copy story data', 'web-stories'));
}
}, [pages, current, selection, story]);
diff --git a/packages/story-editor/src/components/floatingMenu/elements/settings.js b/packages/story-editor/src/components/floatingMenu/elements/settings.js
index 038aba9dea67..16ba6f81a3bf 100644
--- a/packages/story-editor/src/components/floatingMenu/elements/settings.js
+++ b/packages/story-editor/src/components/floatingMenu/elements/settings.js
@@ -87,7 +87,7 @@ function Settings() {
// Record left position of this button in the parent design menu
useEffect(
- () => setOffsetLeft(buttonRef.current.parentNode.offsetLeft + OFFSET_X),
+ () => setOffsetLeft(buttonRef.current?.parentNode.offsetLeft + OFFSET_X),
[]
);
diff --git a/packages/story-editor/src/components/floatingMenu/elements/textAlign.js b/packages/story-editor/src/components/floatingMenu/elements/textAlign.js
index fd8eb90dd566..4681a33ee4e0 100644
--- a/packages/story-editor/src/components/floatingMenu/elements/textAlign.js
+++ b/packages/story-editor/src/components/floatingMenu/elements/textAlign.js
@@ -105,10 +105,13 @@ function TextAlign() {
const [offsetLeft, setOffsetLeft] = useState(0);
// Record left position of this button in the parent design menu
- useEffect(
- () => setOffsetLeft(buttonRef.current.parentNode.offsetLeft + OFFSET_X),
- []
- );
+ useEffect(() => {
+ if (buttonRef.current) {
+ setOffsetLeft(buttonRef.current?.parentNode.offsetLeft + OFFSET_X);
+ } else {
+ setOffsetLeft(OFFSET_X);
+ }
+ }, []);
// When menu has just opened, focus the current button in submenu
const currentIconMounted = (node) => {
diff --git a/packages/story-editor/src/components/floatingMenu/karma/utils.js b/packages/story-editor/src/components/floatingMenu/karma/utils.js
index 5ccc3b5a536b..fd9562442629 100644
--- a/packages/story-editor/src/components/floatingMenu/karma/utils.js
+++ b/packages/story-editor/src/components/floatingMenu/karma/utils.js
@@ -21,7 +21,7 @@ export async function tabToCanvasFocusContainer(focusContainer, fixture) {
// tab until focus reaches the canvas container
let count = 0;
- while (count < 15) {
+ while (count < 20) {
// eslint-disable-next-line no-await-in-loop -- need to await key press
await fixture.events.keyboard.press('tab');
@@ -32,7 +32,7 @@ export async function tabToCanvasFocusContainer(focusContainer, fixture) {
count++;
}
- if (count >= 15) {
+ if (count >= 20) {
throw new Error('Could not find focus container.');
}
}
diff --git a/packages/story-editor/src/components/floatingMenu/layer.js b/packages/story-editor/src/components/floatingMenu/layer.js
index 2899dbe281b2..7d1fb194451f 100644
--- a/packages/story-editor/src/components/floatingMenu/layer.js
+++ b/packages/story-editor/src/components/floatingMenu/layer.js
@@ -76,7 +76,7 @@ function FloatingMenuLayer() {
const [moveable, setMoveable] = useState(null);
const menuRef = useRef();
- const workspaceSize = useRef();
+ const workspaceSizeRef = useRef();
const [isDismissed, setDismissed] = useState(false);
const handleDismiss = useCallback(() => setDismissed(true), []);
@@ -102,7 +102,10 @@ function FloatingMenuLayer() {
// Whenever the workspace resizes, update size
useEffect(() => {
- workspaceSize.current = { width: workspaceWidth, height: workspaceHeight };
+ workspaceSizeRef.current = {
+ width: workspaceWidth,
+ height: workspaceHeight,
+ };
// Note that we don't have to manually update our position, because the selection
// frame will already be updating because of the resize, so a DOM mutation is incoming.
}, [workspaceWidth, workspaceHeight]);
@@ -125,7 +128,7 @@ function FloatingMenuLayer() {
// If the toolbar is positioned to the top, we keep it in a fixed position.
const updatePosition = () => {
const frameRect = moveable.getRect();
- const { width, height } = workspaceSize.current;
+ const { width, height } = workspaceSizeRef.current;
if (floatingMenuPosition === TOOLBAR_POSITIONS.TOP) {
menu.style.left = `clamp(0px, ${
width / 2
diff --git a/packages/story-editor/src/components/footer/carousel/carouselContext/carouselProvider.tsx b/packages/story-editor/src/components/footer/carousel/carouselContext/carouselProvider.tsx
index 37e2149b61a2..bf9654caf652 100644
--- a/packages/story-editor/src/components/footer/carousel/carouselContext/carouselProvider.tsx
+++ b/packages/story-editor/src/components/footer/carousel/carouselContext/carouselProvider.tsx
@@ -52,7 +52,7 @@ function CarouselProvider({
);
const [listElement, setListElement] = useState(null);
- const pageRefs = useRef>({});
+ const pagesRef = useRef>({});
const numPages = pages.length;
@@ -86,10 +86,10 @@ function CarouselProvider({
pageThumbMargin,
});
- useCarouselKeys({ listElement, pageRefs });
+ useCarouselKeys({ listElement, pageRefs: pagesRef });
const setPageRef = useCallback((page: Page, el: HTMLElement) => {
- pageRefs.current[page.id] = el;
+ pagesRef.current[page.id] = el;
}, []);
const clickPage = useCallback(
diff --git a/packages/story-editor/src/components/footer/gridview/gridView.js b/packages/story-editor/src/components/footer/gridview/gridView.js
index 8654d0c09e98..ea9802e755ce 100644
--- a/packages/story-editor/src/components/footer/gridview/gridView.js
+++ b/packages/story-editor/src/components/footer/gridview/gridView.js
@@ -182,7 +182,7 @@ function GridView({ onClose }) {
const handleClickPage = (page) => () => setCurrentPage({ pageId: page.id });
const gridRef = useRef();
- const pageRefs = useRef({});
+ const pagesRef = useRef({});
const arrangeItem = useCallback(
(focusedPageId, nextIndex) => {
@@ -194,7 +194,7 @@ function GridView({ onClose }) {
useGridViewKeys({
containerRef: wrapperRef,
gridRef,
- itemRefs: pageRefs,
+ itemRefs: pagesRef,
isRTL,
currentItemId: currentPageId,
items: pages,
@@ -254,7 +254,7 @@ function GridView({ onClose }) {
{
- pageRefs.current[page.id] = el;
+ pagesRef.current[page.id] = el;
}}
>
`hierarchical_term_${name}`;
* @param {string} option.label The label of the checkbox
* @param {Function} option.onChange Change event handler
* @param {boolean} option.checked The value of the checkbox
- * @param {Object} option.optionRefs Ref used to store refs to checkboxes.
+ * @param {Object} option.optionRef Ref used to store refs to checkboxes.
* @param {number} option.$level The indentation level.
* @return {Node} The rendered option and children.
*/
-const Option = ({ optionRefs = { current: {} }, $level = 0, ...option }) => {
+const Option = ({ optionRef = { current: {} }, $level = 0, ...option }) => {
const { id, label, onBlur, onChange, onFocus, checked, value } = option;
const optionId = buildOptionId(option.id);
@@ -122,7 +122,7 @@ const Option = ({ optionRefs = { current: {} }, $level = 0, ...option }) => {
{
- optionRefs.current[id] = node;
+ optionRef.current[id] = node;
}}
value={value}
checked={checked}
@@ -141,7 +141,7 @@ const OptionPropType = {
checked: PropTypes.bool,
label: PropTypes.string.isRequired,
$level: PropTypes.number,
- optionRefs: PropTypes.shape({
+ optionRef: PropTypes.shape({
current: PropTypes.shape({
[PropTypes.string.isRequired]: PropTypes.node,
}),
@@ -179,7 +179,7 @@ const HierarchicalInput = ({
// Focus handling
const [focusedCheckboxId, setFocusedCheckboxId] = useState(-1);
- const optionRefs = useRef({});
+ const optionRef = useRef({});
/**
* Handles listbox and checkbox focus.
@@ -211,7 +211,7 @@ const HierarchicalInput = ({
setFocusedCheckboxId(firstCheckedOption ? firstCheckedOption : 0);
} else {
// else focus the previously focused option
- optionRefs.current[focusedCheckboxId]?.focus();
+ optionRef.current[focusedCheckboxId]?.focus();
}
}
},
@@ -295,7 +295,7 @@ const HierarchicalInput = ({
useEffect(() => {
// only focus checkbox if focus is in the list
if (checkboxListRef.current?.contains(document.activeElement)) {
- optionRefs.current[focusedCheckboxId]?.focus();
+ optionRef.current[focusedCheckboxId]?.focus();
}
}, [focusedCheckboxId]);
@@ -334,7 +334,7 @@ const HierarchicalInput = ({
key={option.id}
{...option}
onChange={handleCheckboxChange}
- optionRefs={optionRefs}
+ optionRef={optionRef}
/>
))
) : (
diff --git a/packages/story-editor/src/components/header/buttons/preview.js b/packages/story-editor/src/components/header/buttons/preview.js
index 9c5f2750f6a4..2878a1d19fad 100644
--- a/packages/story-editor/src/components/header/buttons/preview.js
+++ b/packages/story-editor/src/components/header/buttons/preview.js
@@ -103,7 +103,7 @@ function PreviewButton({ forceIsSaving = false }) {
`
);
}
- } catch (e) {
+ } catch {
// Ignore errors. Anything can happen with a popup. The errors
// will be resolved after the story is saved.
}
diff --git a/packages/story-editor/src/components/header/buttons/publish.js b/packages/story-editor/src/components/header/buttons/publish.js
index f44623417d06..10d21468af72 100644
--- a/packages/story-editor/src/components/header/buttons/publish.js
+++ b/packages/story-editor/src/components/header/buttons/publish.js
@@ -36,22 +36,23 @@ import { PublishModal } from '../../publishModal';
import ButtonWithChecklistWarning from './buttonWithChecklistWarning';
function PublishButton({ forceIsSaving }) {
- const { date, storyId, saveStory, title, editLink, canPublish } = useStory(
- ({
- state: {
- story: { date, storyId, title, editLink },
- capabilities,
- },
- actions: { saveStory },
- }) => ({
- date,
- storyId,
- saveStory,
- title,
- editLink,
- canPublish: Boolean(capabilities?.publish),
- })
- );
+ const { date, storyId, saveStory, titleLength, editLink, canPublish } =
+ useStory(
+ ({
+ state: {
+ story: { date, storyId, title, editLink },
+ capabilities,
+ },
+ actions: { saveStory },
+ }) => ({
+ date,
+ storyId,
+ saveStory,
+ titleLength: title?.length || 0,
+ editLink,
+ canPublish: Boolean(capabilities?.publish),
+ })
+ );
const showPriorityIssues = useCheckpoint(
({ actions: { showPriorityIssues } }) => showPriorityIssues
@@ -80,13 +81,13 @@ function PublishButton({ forceIsSaving }) {
trackEvent('publish_story', {
status: newStatus,
- title_length: title.length,
+ title_length: titleLength,
});
setShowDialog(false);
saveStory({ status: newStatus });
refreshPostEditURL();
- }, [refreshPostEditURL, saveStory, hasFutureDate, title, canPublish]);
+ }, [refreshPostEditURL, saveStory, hasFutureDate, titleLength, canPublish]);
const handlePublish = useCallback(() => {
showPriorityIssues();
@@ -97,7 +98,7 @@ function PublishButton({ forceIsSaving }) {
setShowDialog(false);
if (focusPublishButton) {
- publishButtonRef.current.focus();
+ publishButtonRef.current?.focus();
}
}, []);
diff --git a/packages/story-editor/src/components/library/panes/media/common/innerElement.js b/packages/story-editor/src/components/library/panes/media/common/innerElement.js
index 7f4fe3455852..7488a9d6cb4f 100644
--- a/packages/story-editor/src/components/library/panes/media/common/innerElement.js
+++ b/packages/story-editor/src/components/library/panes/media/common/innerElement.js
@@ -98,13 +98,13 @@ function InnerElement({
onClick,
onLoad = noop,
showVideoDetail,
- mediaElement,
+ mediaElementRef,
active,
isMuted,
}) {
const newVideoPosterRef = useRef(null);
// Track if we have already set the dragging resource.
- const hasSetResourceTracker = useRef(null);
+ const hasSetResourceRef = useRef(null);
// Note: This `useDropTargets` is purposefully separated from the one below since it
// uses a custom function for checking for equality and is meant for `handleDrag` and `handleDrop` only.
@@ -117,11 +117,11 @@ function InnerElement({
}),
(prev, curr) => {
// If we're dragging this element, always update the actions.
- if (hasSetResourceTracker.current) {
+ if (hasSetResourceRef.current) {
return false;
// If we're rendering the first time, init `handleDrag` and `handleDrop`.
- } else if (hasSetResourceTracker.current === null) {
- hasSetResourceTracker.current = false;
+ } else if (hasSetResourceRef.current === null) {
+ hasSetResourceRef.current = false;
return false;
}
// If the drop targets updated meanwhile, also update the actions, otherwise `handleDrag` won't consider those.
@@ -156,8 +156,8 @@ function InnerElement({
}, [resource.poster]);
const makeMediaVisible = () => {
- if (mediaElement.current) {
- mediaElement.current.style.opacity = 1;
+ if (mediaElementRef.current) {
+ mediaElementRef.current.style.opacity = 1;
}
onLoad();
};
@@ -206,17 +206,17 @@ function InnerElement({
if (type === ContentType.Image || type === ContentType.Sticker) {
// eslint-disable-next-line styled-components-a11y/alt-text -- False positive.
- media = ;
+ media = ;
cloneProps.src = thumbnailURL;
} else if ([ContentType.Video, ContentType.Gif].includes(type)) {
media = (
<>
{poster && !active ? (
/* eslint-disable-next-line styled-components-a11y/alt-text -- False positive. */
-
+
) : (
// eslint-disable-next-line jsx-a11y/media-has-caption,styled-components-a11y/media-has-caption -- No captions/tracks because video is muted.
-