Skip to content

Commit 401fde3

Browse files
authored
Merge branch 'main' into patch-1
2 parents 15fda56 + c405844 commit 401fde3

23 files changed

+574
-744
lines changed

.prettierignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ src/types/libdef/npm
33
docs-user/js
44
docs-user/css
55
src/test/fixtures/upgrades
6-
res/zee-worker.js
76
dist
87
coverage
98
taskcluster/

package.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,12 @@
3434
"license-check": "devtools-license-check",
3535
"preinstall": "node bin/pre-install.js",
3636
"publish": "rimraf public_html && cp -r dist public_html",
37-
"serve-static": "ws -d dist/ -s index.html -p 4242",
37+
"serve-static": "ws -d dist/ -s index.html -p 4243",
3838
"start": "yarn build:clean && cross-env NODE_ENV=development node server.js",
3939
"start-prod": "yarn build-prod && yarn serve-static",
4040
"start-l10n": "yarn build:clean && cross-env NODE_ENV=development L10N=1 node server.js",
4141
"start-l10n-prod": "yarn build-l10n-prod && yarn serve-static",
42-
"start-examples": "ws -d examples/ -s index.html -p 4242",
42+
"start-examples": "ws -d examples/ -s index.html -p 4244",
4343
"start-docs": "ws -d docs-user/ -p 3000",
4444
"start-photon": "node res/photon/server",
4545
"test": "node bin/output-fixing-commands.js cross-env LC_ALL=C TZ=UTC NODE_ENV=test jest",
@@ -76,7 +76,7 @@
7676
"classnames": "^2.5.1",
7777
"common-tags": "^1.8.2",
7878
"copy-to-clipboard": "^3.3.3",
79-
"core-js": "^3.45.0",
79+
"core-js": "^3.45.1",
8080
"escape-string-regexp": "^4.0.0",
8181
"gecko-profiler-demangle": "^0.3.3",
8282
"idb": "^8.0.3",
@@ -115,15 +115,14 @@
115115
"@babel/preset-react": "^7.27.1",
116116
"@babel/preset-typescript": "^7.27.1",
117117
"@eslint/js": "^9.34.0",
118-
"@fetch-mock/jest": "^0.2.16",
119118
"@testing-library/dom": "^10.4.1",
120-
"@testing-library/jest-dom": "^6.6.4",
119+
"@testing-library/jest-dom": "^6.8.0",
121120
"@testing-library/react": "^16.3.0",
122121
"@types/clamp": "^1.0.3",
123122
"@types/common-tags": "^1.8.4",
124123
"@types/jest": "^30.0.0",
125124
"@types/minimist": "^1.2.5",
126-
"@types/node": "^22.17.2",
125+
"@types/node": "^22.18.0",
127126
"@types/query-string": "^6.3.0",
128127
"@types/react": "^18.3.24",
129128
"@types/react-dom": "^18.3.1",
@@ -145,7 +144,7 @@
145144
"copy-webpack-plugin": "^13.0.1",
146145
"cross-env": "^10.0.0",
147146
"css-loader": "^7.1.2",
148-
"cssnano": "^7.1.0",
147+
"cssnano": "^7.1.1",
149148
"devtools-license-check": "^0.9.0",
150149
"eslint": "^9.34.0",
151150
"eslint-config-prettier": "^10.1.8",
@@ -158,6 +157,7 @@
158157
"eslint-plugin-testing-library": "^7.6.6",
159158
"espree": "^10.4.0",
160159
"fake-indexeddb": "^6.1.0",
160+
"fetch-mock": "^12.5.3",
161161
"file-loader": "^6.2.0",
162162
"glob": "^11.0.3",
163163
"globals": "^16.3.0",
@@ -207,7 +207,7 @@
207207
"tsx"
208208
],
209209
"transformIgnorePatterns": [
210-
"/node_modules/(?!(query-string|decode-uri-component|iongraph-web|split-on-first|filter-obj|@fetch-mock/jest|fetch-mock)/)"
210+
"/node_modules/(?!(query-string|decode-uri-component|iongraph-web|split-on-first|filter-obj|fetch-mock)/)"
211211
],
212212
"moduleNameMapper": {
213213
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga|ftl)$": "<rootDir>/src/test/fixtures/mocks/file-mock.ts",

res/zee-worker.js

Lines changed: 0 additions & 80 deletions
This file was deleted.

src/components/shared/ContextMenu.tsx

Lines changed: 7 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,52 +4,25 @@
44

55
import { PureComponent } from 'react';
66
import type { ComponentProps } from 'react';
7-
import ReactDOM from 'react-dom';
87
import { ContextMenu as ReactContextMenu } from '@firefox-devtools/react-contextmenu';
98

109
import './ContextMenu.css';
1110

1211
type Props = ComponentProps<typeof ReactContextMenu>;
1312

1413
export class ContextMenu extends PureComponent<Props> {
15-
_contextMenu: any = null;
16-
_takeContextMenuRef = (contextMenu: any) => {
17-
this._contextMenu = contextMenu;
18-
};
19-
20-
_mouseDownHandler(event: Event): void {
14+
_mouseDownHandler = (event: React.MouseEvent<HTMLDivElement>): void => {
2115
// This prevents from stealing the focus from where it was.
2216
event.preventDefault();
23-
}
24-
25-
override componentDidMount() {
26-
if (this._contextMenu) {
27-
// The context menu component does not expose a reference to its internal
28-
// DOM node so using findDOMNode is currently unavoidable.
29-
// eslint-disable-next-line react/no-find-dom-node
30-
const contextMenuNode = ReactDOM.findDOMNode(this._contextMenu);
31-
if (contextMenuNode) {
32-
// There's no need to remove this event listener since the component is
33-
// never unmounted. Duplicate event listeners will also be discarded
34-
// automatically so we don't need to handle that.
35-
contextMenuNode.addEventListener('mousedown', this._mouseDownHandler);
36-
}
37-
}
38-
}
39-
40-
override componentWillUnmount() {
41-
// eslint-disable-next-line react/no-find-dom-node
42-
const contextMenuNode = ReactDOM.findDOMNode(this._contextMenu);
43-
if (contextMenuNode) {
44-
contextMenuNode.removeEventListener('mousedown', this._mouseDownHandler);
45-
}
46-
}
17+
};
4718

4819
override render() {
4920
return (
50-
<ReactContextMenu ref={this._takeContextMenuRef} {...this.props}>
51-
{this.props.children ? this.props.children : <div />}
52-
</ReactContextMenu>
21+
<div onMouseDown={this._mouseDownHandler}>
22+
<ReactContextMenu {...this.props}>
23+
{this.props.children ? this.props.children : <div />}
24+
</ReactContextMenu>
25+
</div>
5326
);
5427
}
5528
}

src/components/shared/FilterNavigatorBar.css

Lines changed: 3 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
cursor: default;
2121
user-select: none;
2222

23-
/* Note: no overflow: hidden so that we can see the exit animation for ranges */
23+
/* Note: no overflow: hidden for historical reasons - we wanted to see
24+
an animation for items at the end while they were fading out, but
25+
we have removed this animation in the meantime */
2426
}
2527

2628
.filterNavigatorBarItem {
@@ -40,9 +42,6 @@
4042
in the forced colors media query. */
4143
forced-color-adjust: none;
4244
line-height: 24px;
43-
transition:
44-
opacity 250ms var(--animation-curve),
45-
transform 250ms var(--animation-curve);
4645
}
4746

4847
.filterNavigatorBarRootItem {
@@ -98,23 +97,12 @@
9897
}
9998

10099
.filterNavigatorBarItem:not(.filterNavigatorBarLeafItem)::after {
101-
animation: fadeIn 250ms var(--animation-curve);
102100
background-image: var(--internal-separator-img);
103101
background-position: -18px -12px;
104102
background-repeat: no-repeat;
105103
background-size: 24px 24px;
106104
}
107105

108-
@keyframes fadeIn {
109-
from {
110-
opacity: 0;
111-
}
112-
113-
to {
114-
opacity: 1;
115-
}
116-
}
117-
118106
.filterNavigatorBarItem:not(
119107
.filterNavigatorBarRootItem,
120108
.filterNavigatorBarLeafItem
@@ -163,46 +151,6 @@
163151
opacity: 0.65;
164152
}
165153

166-
/* Animation */
167-
168-
.filterNavigatorBarUncommittedTransition-exit {
169-
/* Because of the underlying transition library, this element is still here
170-
* while the new "committed" element is created, which pushes it further
171-
* right. By using display: none here, we prevent this bad effect. */
172-
display: none;
173-
}
174-
175-
.filterNavigatorBarTransition-enter {
176-
color: inherit;
177-
178-
/* We use the same value as the uncommitted item.
179-
* Note that the "uncommitted item" won't have this "enter" class when
180-
* committing, because of how we insert it (it's not part of the same loop). */
181-
opacity: 0.65;
182-
}
183-
184-
.filterNavigatorBarTransition-enter.filterNavigatorBarTransition-enter-active {
185-
color: var(--internal-selected-color);
186-
opacity: 1;
187-
}
188-
189-
.filterNavigatorBarTransition-exit {
190-
opacity: 1;
191-
}
192-
193-
.filterNavigatorBarTransition-exit.filterNavigatorBarTransition-exit-active {
194-
opacity: 0;
195-
transform: translateX(50%);
196-
}
197-
198-
/* Do not animate the filter navigator bar items when user prefers reduced motion */
199-
@media (prefers-reduced-motion) {
200-
.filterNavigatorBarItem {
201-
animation: none;
202-
transition: none;
203-
}
204-
}
205-
206154
@media (forced-colors: active) {
207155
.filterNavigatorBar {
208156
--internal-background-color: ButtonFace;

src/components/shared/FilterNavigatorBar.tsx

Lines changed: 17 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44

55
import * as React from 'react';
66
import classNames from 'classnames';
7-
import { CSSTransition, TransitionGroup } from 'react-transition-group';
87
import './FilterNavigatorBar.css';
98

109
type FilterNavigatorBarListItemProps = {
@@ -71,31 +70,21 @@ export class FilterNavigatorBar extends React.PureComponent<Props> {
7170
const { className, items, selectedItem, uncommittedItem, onPop } =
7271
this.props;
7372

74-
const transitions = items.map((item, i) => (
75-
<CSSTransition
76-
key={i}
77-
classNames="filterNavigatorBarTransition"
78-
timeout={250}
79-
>
80-
<FilterNavigatorBarListItem
81-
index={i}
82-
onClick={i === items.length - 1 && !uncommittedItem ? null : onPop}
83-
isFirstItem={i === 0}
84-
isLastItem={i === items.length - 1}
85-
isSelectedItem={i === selectedItem}
86-
>
87-
{item}
88-
</FilterNavigatorBarListItem>
89-
</CSSTransition>
90-
));
91-
92-
if (uncommittedItem) {
93-
transitions.push(
94-
<CSSTransition
95-
key={items.length}
96-
classNames="filterNavigatorBarUncommittedTransition"
97-
timeout={0}
98-
>
73+
return (
74+
<ol className={classNames('filterNavigatorBar', className)}>
75+
{items.map((item, i) => (
76+
<FilterNavigatorBarListItem
77+
key={i}
78+
index={i}
79+
onClick={i === items.length - 1 && !uncommittedItem ? null : onPop}
80+
isFirstItem={i === 0}
81+
isLastItem={i === items.length - 1}
82+
isSelectedItem={i === selectedItem}
83+
>
84+
{item}
85+
</FilterNavigatorBarListItem>
86+
))}
87+
{uncommittedItem ? (
9988
<FilterNavigatorBarListItem
10089
index={items.length}
10190
isFirstItem={false}
@@ -106,17 +95,8 @@ export class FilterNavigatorBar extends React.PureComponent<Props> {
10695
>
10796
{uncommittedItem}
10897
</FilterNavigatorBarListItem>
109-
</CSSTransition>
110-
);
111-
}
112-
113-
return (
114-
<TransitionGroup
115-
component="ol"
116-
className={classNames('filterNavigatorBar', className)}
117-
>
118-
{transitions}
119-
</TransitionGroup>
98+
) : null}
99+
</ol>
120100
);
121101
}
122102
}

src/test/components/AppLocalizationProvider.test.tsx

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -161,17 +161,23 @@ describe('AppLocalizationProvider', () => {
161161

162162
expect(await screen.findByText(translatedText('de'))).toBeInTheDocument();
163163
expect(document.documentElement).toHaveAttribute('lang', 'de');
164-
expect(window.fetch).toHaveFetched('/locales/de/app.ftl', {
165-
// @ts-expect-error fetch-mock's TypeScript types for toHaveFetched don't know about `credentials`, not sure why
166-
credentials: 'include',
167-
mode: 'no-cors',
168-
});
169-
expect(window.fetch).toHaveFetched('/locales/en-US/app.ftl', {
170-
// @ts-expect-error fetch-mock's TypeScript types for toHaveFetched don't know about `credentials`, not sure why
171-
credentials: 'include',
172-
mode: 'no-cors',
173-
});
174-
expect(window.fetch).toHaveFetchedTimes(2);
164+
expect(
165+
window.fetchMock.callHistory.lastCall('/locales/de/app.ftl')?.options
166+
).toEqual(
167+
expect.objectContaining({
168+
credentials: 'include',
169+
mode: 'no-cors',
170+
})
171+
);
172+
expect(
173+
window.fetchMock.callHistory.lastCall('/locales/en-US/app.ftl')?.options
174+
).toEqual(
175+
expect.objectContaining({
176+
credentials: 'include',
177+
mode: 'no-cors',
178+
})
179+
);
180+
expect(window.fetchMock.callHistory.callLogs.length).toBe(2);
175181
});
176182

177183
it('falls back properly on en-US if the primary locale lacks a string', async () => {
@@ -193,16 +199,22 @@ describe('AppLocalizationProvider', () => {
193199
await screen.findByText(translatedText('en-US'))
194200
).toBeInTheDocument();
195201
expect(document.documentElement).toHaveAttribute('lang', 'de');
196-
expect(window.fetch).toHaveFetched('/locales/de/app.ftl', {
197-
// @ts-expect-error fetch-mock's TypeScript types for toHaveFetched don't know about `credentials`, not sure why
198-
credentials: 'include',
199-
mode: 'no-cors',
200-
});
201-
expect(window.fetch).toHaveFetched('/locales/en-US/app.ftl', {
202-
// @ts-expect-error fetch-mock's TypeScript types for toHaveFetched don't know about `credentials`, not sure why
203-
credentials: 'include',
204-
mode: 'no-cors',
205-
});
206-
expect(window.fetch).toHaveFetchedTimes(2);
202+
expect(
203+
window.fetchMock.callHistory.lastCall('/locales/de/app.ftl')?.options
204+
).toEqual(
205+
expect.objectContaining({
206+
credentials: 'include',
207+
mode: 'no-cors',
208+
})
209+
);
210+
expect(
211+
window.fetchMock.callHistory.lastCall('/locales/en-US/app.ftl')?.options
212+
).toEqual(
213+
expect.objectContaining({
214+
credentials: 'include',
215+
mode: 'no-cors',
216+
})
217+
);
218+
expect(window.fetchMock.callHistory.callLogs.length).toBe(2);
207219
});
208220
});

0 commit comments

Comments
 (0)