Merge remote-tracking branch 'origin/develop' into renovate/major-react-monorepo

This commit is contained in:
Alex Gleason 2023-01-05 16:36:49 -06:00
commit 85c25903f3
No known key found for this signature in database
GPG key ID: 7211D1F99744FBB7
31 changed files with 443 additions and 787 deletions

Binary file not shown.

View file

@ -1,16 +1,22 @@
{ {
"extends": ["stylelint-config-standard"], "extends": ["stylelint-config-standard-scss"],
"ignoreFiles": ["app/styles/reset.scss"],
"plugins": ["stylelint-scss"],
"rules": { "rules": {
"alpha-value-notation": null,
"at-rule-no-unknown": null, "at-rule-no-unknown": null,
"at-rule-empty-line-before": ["always", { "ignore": ["after-comment", "first-nested", "inside-block", "blockless-after-same-name-blockless", "blockless-after-blockless"] }], "at-rule-empty-line-before": ["always", { "ignore": ["after-comment", "first-nested", "inside-block", "blockless-after-same-name-blockless", "blockless-after-blockless"] }],
"color-function-notation": null,
"custom-property-pattern": null,
"declaration-block-no-redundant-longhand-properties": null,
"declaration-colon-newline-after": null, "declaration-colon-newline-after": null,
"declaration-empty-line-before": "never", "declaration-empty-line-before": "never",
"font-family-no-missing-generic-family-keyword": [true, { "ignoreFontFamilies": ["ForkAwesome", "Font Awesome 5 Free", "OpenDyslexic", "soapbox"] }], "font-family-no-missing-generic-family-keyword": [true, { "ignoreFontFamilies": ["ForkAwesome", "Font Awesome 5 Free", "OpenDyslexic", "soapbox"] }],
"max-line-length": null,
"no-descending-specificity": null, "no-descending-specificity": null,
"no-duplicate-selectors": null, "no-duplicate-selectors": null,
"scss/at-rule-no-unknown": [true, { "ignoreAtRules": ["/tailwind/", "layer"]}], "no-invalid-position-at-import-rule": null,
"no-invalid-position-at-import-rule": null "scss/at-rule-no-unknown": [true, { "ignoreAtRules": ["tailwind", "apply", "layer", "config"]}],
"scss/operator-no-unspaced": null,
"selector-class-pattern": null,
"string-quotes": "single"
} }
} }

View file

@ -46,7 +46,7 @@ export default class AutosuggestInput extends ImmutablePureComponent<IAutosugges
getFirstIndex = () => { getFirstIndex = () => {
return this.props.autoSelect ? 0 : -1; return this.props.autoSelect ? 0 : -1;
} };
state = { state = {
suggestionsHidden: true, suggestionsHidden: true,
@ -76,7 +76,7 @@ export default class AutosuggestInput extends ImmutablePureComponent<IAutosugges
if (this.props.onChange) { if (this.props.onChange) {
this.props.onChange(e); this.props.onChange(e);
} }
} };
onKeyDown: React.KeyboardEventHandler<HTMLInputElement> = (e) => { onKeyDown: React.KeyboardEventHandler<HTMLInputElement> = (e) => {
const { suggestions, menu, disabled } = this.props; const { suggestions, menu, disabled } = this.props;
@ -145,15 +145,15 @@ export default class AutosuggestInput extends ImmutablePureComponent<IAutosugges
if (this.props.onKeyDown) { if (this.props.onKeyDown) {
this.props.onKeyDown(e); this.props.onKeyDown(e);
} }
} };
onBlur = () => { onBlur = () => {
this.setState({ suggestionsHidden: true, focused: false }); this.setState({ suggestionsHidden: true, focused: false });
} };
onFocus = () => { onFocus = () => {
this.setState({ focused: true }); this.setState({ focused: true });
} };
onSuggestionClick: React.EventHandler<React.MouseEvent | React.TouchEvent> = (e) => { onSuggestionClick: React.EventHandler<React.MouseEvent | React.TouchEvent> = (e) => {
const index = Number(e.currentTarget?.getAttribute('data-index')); const index = Number(e.currentTarget?.getAttribute('data-index'));
@ -161,7 +161,7 @@ export default class AutosuggestInput extends ImmutablePureComponent<IAutosugges
this.props.onSuggestionSelected(this.state.tokenStart, this.state.lastToken, suggestion); this.props.onSuggestionSelected(this.state.tokenStart, this.state.lastToken, suggestion);
this.input?.focus(); this.input?.focus();
e.preventDefault(); e.preventDefault();
} };
componentDidUpdate(prevProps: IAutosuggestInput, prevState: any) { componentDidUpdate(prevProps: IAutosuggestInput, prevState: any) {
const { suggestions } = this.props; const { suggestions } = this.props;
@ -172,7 +172,7 @@ export default class AutosuggestInput extends ImmutablePureComponent<IAutosugges
setInput = (c: HTMLInputElement) => { setInput = (c: HTMLInputElement) => {
this.input = c; this.input = c;
} };
renderSuggestion = (suggestion: AutoSuggestion, i: number) => { renderSuggestion = (suggestion: AutoSuggestion, i: number) => {
const { selectedSuggestion } = this.state; const { selectedSuggestion } = this.state;
@ -209,21 +209,21 @@ export default class AutosuggestInput extends ImmutablePureComponent<IAutosugges
{inner} {inner}
</div> </div>
); );
} };
handleMenuItemAction = (item: MenuItem | null, e: React.MouseEvent | React.KeyboardEvent) => { handleMenuItemAction = (item: MenuItem | null, e: React.MouseEvent | React.KeyboardEvent) => {
this.onBlur(); this.onBlur();
if (item?.action) { if (item?.action) {
item.action(e); item.action(e);
} }
} };
handleMenuItemClick = (item: MenuItem | null): React.MouseEventHandler => { handleMenuItemClick = (item: MenuItem | null): React.MouseEventHandler => {
return e => { return e => {
e.preventDefault(); e.preventDefault();
this.handleMenuItemAction(item, e); this.handleMenuItemAction(item, e);
}; };
} };
renderMenu = () => { renderMenu = () => {
const { menu, suggestions } = this.props; const { menu, suggestions } = this.props;

View file

@ -64,7 +64,7 @@ class AutosuggestTextarea extends ImmutablePureComponent<IAutosuggesteTextarea>
} }
this.props.onChange(e); this.props.onChange(e);
} };
onKeyDown: React.KeyboardEventHandler<HTMLTextAreaElement> = (e) => { onKeyDown: React.KeyboardEventHandler<HTMLTextAreaElement> = (e) => {
const { suggestions, disabled } = this.props; const { suggestions, disabled } = this.props;
@ -122,7 +122,7 @@ class AutosuggestTextarea extends ImmutablePureComponent<IAutosuggesteTextarea>
} }
this.props.onKeyDown(e); this.props.onKeyDown(e);
} };
onBlur = () => { onBlur = () => {
this.setState({ suggestionsHidden: true, focused: false }); this.setState({ suggestionsHidden: true, focused: false });
@ -130,7 +130,7 @@ class AutosuggestTextarea extends ImmutablePureComponent<IAutosuggesteTextarea>
if (this.props.onBlur) { if (this.props.onBlur) {
this.props.onBlur(); this.props.onBlur();
} }
} };
onFocus = () => { onFocus = () => {
this.setState({ focused: true }); this.setState({ focused: true });
@ -138,14 +138,14 @@ class AutosuggestTextarea extends ImmutablePureComponent<IAutosuggesteTextarea>
if (this.props.onFocus) { if (this.props.onFocus) {
this.props.onFocus(); this.props.onFocus();
} }
} };
onSuggestionClick: React.MouseEventHandler<HTMLDivElement> = (e) => { onSuggestionClick: React.MouseEventHandler<HTMLDivElement> = (e) => {
const suggestion = this.props.suggestions.get(e.currentTarget.getAttribute('data-index') as any); const suggestion = this.props.suggestions.get(e.currentTarget.getAttribute('data-index') as any);
e.preventDefault(); e.preventDefault();
this.props.onSuggestionSelected(this.state.tokenStart, this.state.lastToken, suggestion); this.props.onSuggestionSelected(this.state.tokenStart, this.state.lastToken, suggestion);
this.textarea?.focus(); this.textarea?.focus();
} };
shouldComponentUpdate(nextProps: IAutosuggesteTextarea, nextState: any) { shouldComponentUpdate(nextProps: IAutosuggesteTextarea, nextState: any) {
// Skip updating when only the lastToken changes so the // Skip updating when only the lastToken changes so the
@ -169,14 +169,14 @@ class AutosuggestTextarea extends ImmutablePureComponent<IAutosuggesteTextarea>
setTextarea: React.Ref<HTMLTextAreaElement> = (c) => { setTextarea: React.Ref<HTMLTextAreaElement> = (c) => {
this.textarea = c; this.textarea = c;
} };
onPaste: React.ClipboardEventHandler<HTMLTextAreaElement> = (e) => { onPaste: React.ClipboardEventHandler<HTMLTextAreaElement> = (e) => {
if (e.clipboardData && e.clipboardData.files.length === 1) { if (e.clipboardData && e.clipboardData.files.length === 1) {
this.props.onPaste(e.clipboardData.files); this.props.onPaste(e.clipboardData.files);
e.preventDefault(); e.preventDefault();
} }
} };
renderSuggestion = (suggestion: string | Emoji, i: number) => { renderSuggestion = (suggestion: string | Emoji, i: number) => {
const { selectedSuggestion } = this.state; const { selectedSuggestion } = this.state;
@ -208,7 +208,7 @@ class AutosuggestTextarea extends ImmutablePureComponent<IAutosuggesteTextarea>
{inner} {inner}
</div> </div>
); );
} };
setPortalPosition() { setPortalPosition() {
if (!this.textarea) { if (!this.textarea) {

View file

@ -64,7 +64,7 @@ class DropdownMenu extends React.PureComponent<IDropdownMenu, IDropdownMenuState
if (this.node && !this.node.contains(e.target as Node)) { if (this.node && !this.node.contains(e.target as Node)) {
this.props.onClose(); this.props.onClose();
} }
} };
componentDidMount() { componentDidMount() {
document.addEventListener('click', this.handleDocumentClick, false); document.addEventListener('click', this.handleDocumentClick, false);
@ -84,11 +84,11 @@ class DropdownMenu extends React.PureComponent<IDropdownMenu, IDropdownMenuState
setRef: React.RefCallback<HTMLDivElement> = c => { setRef: React.RefCallback<HTMLDivElement> = c => {
this.node = c; this.node = c;
} };
setFocusRef: React.RefCallback<HTMLAnchorElement> = c => { setFocusRef: React.RefCallback<HTMLAnchorElement> = c => {
this.focusedItem = c; this.focusedItem = c;
} };
handleKeyDown = (e: KeyboardEvent) => { handleKeyDown = (e: KeyboardEvent) => {
if (!this.node) return; if (!this.node) return;
@ -127,13 +127,13 @@ class DropdownMenu extends React.PureComponent<IDropdownMenu, IDropdownMenuState
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
} }
} };
handleItemKeyPress: React.EventHandler<React.KeyboardEvent> = e => { handleItemKeyPress: React.EventHandler<React.KeyboardEvent> = e => {
if (e.key === 'Enter' || e.key === ' ') { if (e.key === 'Enter' || e.key === ' ') {
this.handleClick(e); this.handleClick(e);
} }
} };
handleClick: React.EventHandler<React.MouseEvent | React.KeyboardEvent> = e => { handleClick: React.EventHandler<React.MouseEvent | React.KeyboardEvent> = e => {
const i = Number(e.currentTarget.getAttribute('data-index')); const i = Number(e.currentTarget.getAttribute('data-index'));
@ -152,7 +152,7 @@ class DropdownMenu extends React.PureComponent<IDropdownMenu, IDropdownMenuState
e.preventDefault(); e.preventDefault();
action(e); action(e);
} }
} };
handleMiddleClick: React.EventHandler<React.MouseEvent> = e => { handleMiddleClick: React.EventHandler<React.MouseEvent> = e => {
const i = Number(e.currentTarget.getAttribute('data-index')); const i = Number(e.currentTarget.getAttribute('data-index'));
@ -166,13 +166,13 @@ class DropdownMenu extends React.PureComponent<IDropdownMenu, IDropdownMenuState
e.preventDefault(); e.preventDefault();
middleClick(e); middleClick(e);
} }
} };
handleAuxClick: React.EventHandler<React.MouseEvent> = e => { handleAuxClick: React.EventHandler<React.MouseEvent> = e => {
if (e.button === 1) { if (e.button === 1) {
this.handleMiddleClick(e); this.handleMiddleClick(e);
} }
} };
renderItem(option: MenuItem | null, i: number): JSX.Element { renderItem(option: MenuItem | null, i: number): JSX.Element {
if (option === null) { if (option === null) {
@ -303,7 +303,7 @@ class Dropdown extends React.PureComponent<IDropdown, IDropdownState> {
onOpen(this.state.id, this.handleItemClick, placement, e.type !== 'click'); onOpen(this.state.id, this.handleItemClick, placement, e.type !== 'click');
} }
} };
handleClose = () => { handleClose = () => {
if (this.activeElement && this.activeElement === this.target) { if (this.activeElement && this.activeElement === this.target) {
@ -314,13 +314,13 @@ class Dropdown extends React.PureComponent<IDropdown, IDropdownState> {
if (this.props.onClose) { if (this.props.onClose) {
this.props.onClose(this.state.id); this.props.onClose(this.state.id);
} }
} };
handleMouseDown: React.EventHandler<React.MouseEvent | React.KeyboardEvent> = () => { handleMouseDown: React.EventHandler<React.MouseEvent | React.KeyboardEvent> = () => {
if (!this.state.open) { if (!this.state.open) {
this.activeElement = document.activeElement; this.activeElement = document.activeElement;
} }
} };
handleButtonKeyDown: React.EventHandler<React.KeyboardEvent> = (e) => { handleButtonKeyDown: React.EventHandler<React.KeyboardEvent> = (e) => {
switch (e.key) { switch (e.key) {
@ -329,7 +329,7 @@ class Dropdown extends React.PureComponent<IDropdown, IDropdownState> {
this.handleMouseDown(e); this.handleMouseDown(e);
break; break;
} }
} };
handleKeyPress: React.EventHandler<React.KeyboardEvent<HTMLButtonElement>> = (e) => { handleKeyPress: React.EventHandler<React.KeyboardEvent<HTMLButtonElement>> = (e) => {
switch (e.key) { switch (e.key) {
@ -340,7 +340,7 @@ class Dropdown extends React.PureComponent<IDropdown, IDropdownState> {
e.preventDefault(); e.preventDefault();
break; break;
} }
} };
handleItemClick: React.EventHandler<React.MouseEvent> = e => { handleItemClick: React.EventHandler<React.MouseEvent> = e => {
const i = Number(e.currentTarget.getAttribute('data-index')); const i = Number(e.currentTarget.getAttribute('data-index'));
@ -358,21 +358,21 @@ class Dropdown extends React.PureComponent<IDropdown, IDropdownState> {
} else if (to) { } else if (to) {
this.props.history?.push(to); this.props.history?.push(to);
} }
} };
setTargetRef: React.RefCallback<HTMLButtonElement> = c => { setTargetRef: React.RefCallback<HTMLButtonElement> = c => {
this.target = c; this.target = c;
} };
findTarget = () => { findTarget = () => {
return this.target; return this.target;
} };
componentWillUnmount = () => { componentWillUnmount = () => {
if (this.state.id === this.props.openDropdownId) { if (this.state.id === this.props.openDropdownId) {
this.handleClose(); this.handleClose();
} }
} };
render() { render() {
const { src = require('@tabler/icons/dots.svg'), items, title, disabled, dropdownPlacement, openDropdownId, openedViaKeyboard = false, pressed, text, children, dropdownMenuStyle } = this.props; const { src = require('@tabler/icons/dots.svg'), items, title, disabled, dropdownPlacement, openDropdownId, openedViaKeyboard = false, pressed, text, children, dropdownMenuStyle } = this.props;

View file

@ -28,7 +28,7 @@ class EmojiSelector extends ImmutablePureComponent<IEmojiSelector> {
onReact: () => { }, onReact: () => { },
onUnfocus: () => { }, onUnfocus: () => { },
visible: false, visible: false,
} };
node?: HTMLDivElement = undefined; node?: HTMLDivElement = undefined;
@ -38,7 +38,7 @@ class EmojiSelector extends ImmutablePureComponent<IEmojiSelector> {
if (focused && (!e.currentTarget || !e.currentTarget.classList.contains('emoji-react-selector__emoji'))) { if (focused && (!e.currentTarget || !e.currentTarget.classList.contains('emoji-react-selector__emoji'))) {
onUnfocus(); onUnfocus();
} }
} };
_selectPreviousEmoji = (i: number): void => { _selectPreviousEmoji = (i: number): void => {
if (!this.node) return; if (!this.node) return;
@ -85,7 +85,7 @@ class EmojiSelector extends ImmutablePureComponent<IEmojiSelector> {
onUnfocus(); onUnfocus();
break; break;
} }
} };
handleReact = (emoji: string) => (): void => { handleReact = (emoji: string) => (): void => {
const { onReact, focused, onUnfocus } = this.props; const { onReact, focused, onUnfocus } = this.props;
@ -95,7 +95,7 @@ class EmojiSelector extends ImmutablePureComponent<IEmojiSelector> {
if (focused) { if (focused) {
onUnfocus(); onUnfocus();
} }
} };
handlers = { handlers = {
open: () => { }, open: () => { },
@ -103,7 +103,7 @@ class EmojiSelector extends ImmutablePureComponent<IEmojiSelector> {
setRef = (c: HTMLDivElement): void => { setRef = (c: HTMLDivElement): void => {
this.node = c; this.node = c;
} };
render() { render() {
const { visible, focused, allowedEmoji, onReact } = this.props; const { visible, focused, allowedEmoji, onReact } = this.props;

View file

@ -42,7 +42,7 @@ class ErrorBoundary extends React.PureComponent<Props, State> {
error: undefined, error: undefined,
componentStack: undefined, componentStack: undefined,
browser: undefined, browser: undefined,
} };
textarea: HTMLTextAreaElement | null = null; textarea: HTMLTextAreaElement | null = null;
@ -71,7 +71,7 @@ class ErrorBoundary extends React.PureComponent<Props, State> {
setTextareaRef: React.RefCallback<HTMLTextAreaElement> = c => { setTextareaRef: React.RefCallback<HTMLTextAreaElement> = c => {
this.textarea = c; this.textarea = c;
} };
handleCopy: React.MouseEventHandler = () => { handleCopy: React.MouseEventHandler = () => {
if (!this.textarea) return; if (!this.textarea) return;
@ -80,12 +80,12 @@ class ErrorBoundary extends React.PureComponent<Props, State> {
this.textarea.setSelectionRange(0, 99999); this.textarea.setSelectionRange(0, 99999);
document.execCommand('copy'); document.execCommand('copy');
} };
getErrorText = (): string => { getErrorText = (): string => {
const { error, componentStack } = this.state; const { error, componentStack } = this.state;
return error + componentStack; return error + componentStack;
} };
clearCookies: React.MouseEventHandler = (e) => { clearCookies: React.MouseEventHandler = (e) => {
localStorage.clear(); localStorage.clear();
@ -96,7 +96,7 @@ class ErrorBoundary extends React.PureComponent<Props, State> {
e.preventDefault(); e.preventDefault();
unregisterSw().then(goHome).catch(goHome); unregisterSw().then(goHome).catch(goHome);
} }
} };
render() { render() {
const { browser, hasError } = this.state; const { browser, hasError } = this.state;

View file

@ -3,8 +3,6 @@ import React from 'react';
import { render, screen } from '../../../../jest/test-helpers'; import { render, screen } from '../../../../jest/test-helpers';
import FormGroup from '../form-group'; import FormGroup from '../form-group';
jest.mock('uuid', () => jest.requireActual('uuid'));
describe('<FormGroup />', () => { describe('<FormGroup />', () => {
it('connects the label and input', () => { it('connects the label and input', () => {
render( render(

View file

@ -15,10 +15,10 @@ const hex2rgba = (hex: string, alpha = 1) => {
export default class Visualizer { export default class Visualizer {
tickSize: number tickSize: number;
canvas?: HTMLCanvasElement canvas?: HTMLCanvasElement;
context?: CanvasRenderingContext2D context?: CanvasRenderingContext2D;
analyser?: AnalyserNode analyser?: AnalyserNode;
constructor(tickSize: number) { constructor(tickSize: number) {
this.tickSize = tickSize; this.tickSize = tickSize;

View file

@ -159,7 +159,7 @@ const FeedCarousel = () => {
<button <button
data-testid='prev-page' data-testid='prev-page'
onClick={handlePrevPage} onClick={handlePrevPage}
className='w-7 flex items-center justify-center disabled:opacity-25 transition-opacity duration-500' className='h-full w-7 flex items-center justify-center disabled:opacity-25 transition-opacity duration-500'
disabled={!hasPrevPage} disabled={!hasPrevPage}
> >
<Icon src={require('@tabler/icons/chevron-left.svg')} className='text-black dark:text-white h-5 w-5' /> <Icon src={require('@tabler/icons/chevron-left.svg')} className='text-black dark:text-white h-5 w-5' />
@ -171,7 +171,7 @@ const FeedCarousel = () => {
<div <div
className='z-10 flex items-center justify-center absolute left-0 top-0 bottom-0 bg-white dark:bg-primary-900' className='z-10 flex items-center justify-center absolute left-0 top-0 bottom-0 bg-white dark:bg-primary-900'
style={{ style={{
width: widthPerAvatar, width: widthPerAvatar || 'auto',
}} }}
> >
<CarouselItem <CarouselItem
@ -194,7 +194,11 @@ const FeedCarousel = () => {
> >
{isFetching ? ( {isFetching ? (
new Array(20).fill(0).map((_, idx) => ( new Array(20).fill(0).map((_, idx) => (
<div className='flex flex-shrink-0 justify-center' style={{ width: widthPerAvatar }} key={idx}> <div
className='flex flex-shrink-0 justify-center'
style={{ width: widthPerAvatar || 'auto' }}
key={idx}
>
<PlaceholderAvatar size={56} withText /> <PlaceholderAvatar size={56} withText />
</div> </div>
)) ))
@ -204,7 +208,7 @@ const FeedCarousel = () => {
key={avatar?.account_id || index} key={avatar?.account_id || index}
className='flex flex-shrink-0 justify-center' className='flex flex-shrink-0 justify-center'
style={{ style={{
width: widthPerAvatar, width: widthPerAvatar || 'auto',
}} }}
> >
{avatar === null ? ( {avatar === null ? (
@ -240,7 +244,7 @@ const FeedCarousel = () => {
<button <button
data-testid='next-page' data-testid='next-page'
onClick={handleNextPage} onClick={handleNextPage}
className='w-7 flex items-center justify-center disabled:opacity-25 transition-opacity duration-500' className='h-full w-7 flex items-center justify-center disabled:opacity-25 transition-opacity duration-500'
disabled={!hasNextPage} disabled={!hasNextPage}
> >
<Icon src={require('@tabler/icons/chevron-right.svg')} className='text-black dark:text-white h-5 w-5' /> <Icon src={require('@tabler/icons/chevron-right.svg')} className='text-black dark:text-white h-5 w-5' />

View file

@ -32,14 +32,14 @@ class Bundle extends React.PureComponent<BundleProps, BundleState> {
onFetch: noop, onFetch: noop,
onFetchSuccess: noop, onFetchSuccess: noop,
onFetchFail: noop, onFetchFail: noop,
} };
static cache = new Map static cache = new Map;
state = { state = {
mod: undefined, mod: undefined,
forceRender: false, forceRender: false,
} };
componentDidMount() { componentDidMount() {
this.load(this.props); this.load(this.props);
@ -91,7 +91,7 @@ class Bundle extends React.PureComponent<BundleProps, BundleState> {
this.setState({ mod: null }); this.setState({ mod: null });
onFetchFail(error); onFetchFail(error);
}); });
} };
render() { render() {
const { loading: Loading, error: Error, children, renderDelay } = this.props; const { loading: Loading, error: Error, children, renderDelay } = this.props;

View file

@ -26,7 +26,7 @@ class ImageLoader extends React.PureComponent<IImageLoader> {
loading: true, loading: true,
error: false, error: false,
width: null, width: null,
} };
removers: EventRemover[] = []; removers: EventRemover[] = [];
canvas: HTMLCanvasElement | null = null; canvas: HTMLCanvasElement | null = null;
@ -87,7 +87,7 @@ class ImageLoader extends React.PureComponent<IImageLoader> {
image.addEventListener('load', handleLoad); image.addEventListener('load', handleLoad);
image.src = previewSrc || ''; image.src = previewSrc || '';
this.removers.push(removeEventListeners); this.removers.push(removeEventListeners);
}) });
clearPreviewCanvas() { clearPreviewCanvas() {
if (this.canvas && this.canvasContext) { if (this.canvas && this.canvasContext) {
@ -129,7 +129,7 @@ class ImageLoader extends React.PureComponent<IImageLoader> {
setCanvasRef = (c: HTMLCanvasElement) => { setCanvasRef = (c: HTMLCanvasElement) => {
this.canvas = c; this.canvas = c;
if (c) this.setState({ width: c.offsetWidth }); if (c) this.setState({ width: c.offsetWidth });
} };
render() { render() {
const { alt, src, width, height, onClick } = this.props; const { alt, src, width, height, onClick } = this.props;

View file

@ -105,16 +105,16 @@ export default class ModalRoot extends React.PureComponent<IModalRoot> {
renderLoading = (modalId: string) => () => { renderLoading = (modalId: string) => () => {
return !['MEDIA', 'VIDEO', 'BOOST', 'CONFIRM', 'ACTIONS'].includes(modalId) ? <ModalLoading /> : null; return !['MEDIA', 'VIDEO', 'BOOST', 'CONFIRM', 'ACTIONS'].includes(modalId) ? <ModalLoading /> : null;
} };
renderError: React.ComponentType<{ onRetry: (props?: BundleProps) => void }> = (props) => { renderError: React.ComponentType<{ onRetry: (props?: BundleProps) => void }> = (props) => {
return <BundleModalError {...props} onClose={this.onClickClose} />; return <BundleModalError {...props} onClose={this.onClickClose} />;
} };
onClickClose = (_?: ModalType) => { onClickClose = (_?: ModalType) => {
const { onClose, type } = this.props; const { onClose, type } = this.props;
onClose(type); onClose(type);
} };
render() { render() {
const { type, props } = this.props; const { type, props } = this.props;

View file

@ -31,7 +31,7 @@ class ZoomableImage extends React.PureComponent<IZoomableImage> {
state = { state = {
scale: MIN_SCALE, scale: MIN_SCALE,
} };
container: HTMLDivElement | null = null; container: HTMLDivElement | null = null;
image: HTMLImageElement | null = null; image: HTMLImageElement | null = null;
@ -54,7 +54,7 @@ class ZoomableImage extends React.PureComponent<IZoomableImage> {
const [p1, p2] = Array.from(e.touches); const [p1, p2] = Array.from(e.touches);
this.lastDistance = getDistance(p1, p2); this.lastDistance = getDistance(p1, p2);
} };
handleTouchMove = (e: TouchEvent) => { handleTouchMove = (e: TouchEvent) => {
if (!this.container) return; if (!this.container) return;
@ -78,7 +78,7 @@ class ZoomableImage extends React.PureComponent<IZoomableImage> {
this.zoom(scale, midpoint); this.zoom(scale, midpoint);
this.lastDistance = distance; this.lastDistance = distance;
} };
zoom(nextScale: number, midpoint: Point) { zoom(nextScale: number, midpoint: Point) {
if (!this.container) return; if (!this.container) return;
@ -107,15 +107,15 @@ class ZoomableImage extends React.PureComponent<IZoomableImage> {
e.stopPropagation(); e.stopPropagation();
const handler = this.props.onClick; const handler = this.props.onClick;
if (handler) handler(e); if (handler) handler(e);
} };
setContainerRef = (c: HTMLDivElement) => { setContainerRef = (c: HTMLDivElement) => {
this.container = c; this.container = c;
} };
setImageRef = (c: HTMLImageElement) => { setImageRef = (c: HTMLImageElement) => {
this.image = c; this.image = c;
} };
render() { render() {
const { alt, src } = this.props; const { alt, src } = this.props;

View file

@ -15,9 +15,6 @@ jest.mock('soapbox/queries/client');
// https://dev.to/andyhaskell/testing-your-indexeddb-code-with-jest-2o17 // https://dev.to/andyhaskell/testing-your-indexeddb-code-with-jest-2o17
require('fake-indexeddb/auto'); require('fake-indexeddb/auto');
// Mock external dependencies
jest.mock('uuid', () => ({ v4: jest.fn(() => '1') }));
// Clear toasts after each test. // Clear toasts after each test.
afterEach(() => { afterEach(() => {
toast.remove(); toast.remove();

View file

@ -134,7 +134,12 @@ const htmlToPlainText = (html: string): string =>
/** ServiceWorker `push` event callback. */ /** ServiceWorker `push` event callback. */
const handlePush = (event: PushEvent) => { const handlePush = (event: PushEvent) => {
const { access_token, notification_id, preferred_locale, title, body, icon } = event.data?.json(); if (!event.data) {
console.error('An empty web push event was received.', { event });
return;
}
const { access_token, notification_id, preferred_locale, title, body, icon } = event.data.json();
// Placeholder until more information can be loaded // Placeholder until more information can be loaded
event.waitUntil( event.waitUntil(

View file

@ -14,23 +14,23 @@
.video-player__volume::before, .video-player__volume::before,
.video-player__seek::before { .video-player__seek::before {
background: currentColor; background: currentcolor;
opacity: 0.15; opacity: 0.15;
} }
.video-player__seek__buffer { .video-player__seek__buffer {
background: currentColor; background: currentcolor;
opacity: 0.2; opacity: 0.2;
} }
.video-player__buttons button { .video-player__buttons button {
color: currentColor; color: currentcolor;
opacity: 0.75; opacity: 0.75;
&:active, &:active,
&:hover, &:hover,
&:focus { &:focus {
color: currentColor; color: currentcolor;
opacity: 1; opacity: 1;
} }
} }
@ -38,7 +38,7 @@
.video-player__time-sep, .video-player__time-sep,
.video-player__time-total, .video-player__time-total,
.video-player__time-current { .video-player__time-current {
color: currentColor; color: currentcolor;
} }
.video-player__seek::before, .video-player__seek::before,

View file

@ -92,9 +92,6 @@ button {
button, button,
a.button { a.button {
&.standard { &.standard {
// NOTE - will define the larger standard buttons here and apply class where used.
&-small { &-small {
@include font-size(11); @include font-size(11);
@include line-height(11); @include line-height(11);

View file

@ -1,4 +1,3 @@
.column { .column {
width: 350px; width: 350px;
position: relative; position: relative;

View file

@ -10,12 +10,12 @@
} }
} }
.react-datepicker-popper[data-placement^=bottom] .react-datepicker__triangle::before, .react-datepicker-popper[data-placement^='bottom'] .react-datepicker__triangle::before,
.react-datepicker-popper[data-placement^=bottom] .react-datepicker__triangle::after { .react-datepicker-popper[data-placement^='bottom'] .react-datepicker__triangle::after {
@apply border-b-white dark:border-b-gray-900; @apply border-b-white dark:border-b-gray-900;
} }
.react-datepicker-popper[data-placement^=bottom] .react-datepicker__triangle::before { .react-datepicker-popper[data-placement^='bottom'] .react-datepicker__triangle::before {
@apply border-b-gray-200 dark:border-b-gray-700; @apply border-b-gray-200 dark:border-b-gray-700;
} }
@ -143,6 +143,6 @@
.react-datepicker__close-icon::after { .react-datepicker__close-icon::after {
@apply bg-transparent text-gray-600 dark:text-gray-400 text-base; @apply bg-transparent text-gray-600 dark:text-gray-400 text-base;
font-family: 'Font Awesome 5 Free'; font-family: 'Font Awesome 5 Free';
content: ""; content: '';
font-weight: 900; font-weight: 900;
} }

View file

@ -67,4 +67,3 @@
@apply block my-2 h-[1px] bg-gray-100 dark:bg-gray-800; @apply block my-2 h-[1px] bg-gray-100 dark:bg-gray-800;
} }
} }
// end .dropdown-menu

View file

@ -39,7 +39,7 @@
@apply static; @apply static;
} }
input[type="checkbox"] { input[type='checkbox'] {
position: absolute; position: absolute;
top: 3px; top: 3px;
left: 0; left: 0;
@ -68,12 +68,12 @@
@apply pr-1 capitalize; @apply pr-1 capitalize;
&::after { &::after {
content: ","; content: ',';
} }
&:last-of-type { &:last-of-type {
&::after { &::after {
content: ""; content: '';
} }
} }
} }

View file

@ -15,7 +15,7 @@
&--active { &--active {
&.svg-icon--home svg { &.svg-icon--home svg {
fill: currentColor; fill: currentcolor;
} }
svg.icon-tabler-search, svg.icon-tabler-search,
@ -26,14 +26,14 @@
svg.icon-tabler-bell, svg.icon-tabler-bell,
svg.icon-tabler-messages { svg.icon-tabler-messages {
path:nth-child(2) { path:nth-child(2) {
fill: currentColor; fill: currentcolor;
} }
} }
svg.icon-tabler-users { svg.icon-tabler-users {
circle, circle,
circle + path { circle + path {
fill: currentColor; fill: currentcolor;
} }
} }
@ -41,8 +41,8 @@
stroke: var(--background-color); stroke: var(--background-color);
rect { rect {
fill: currentColor; fill: currentcolor;
stroke: currentColor; stroke: currentcolor;
} }
} }
} }

View file

@ -290,7 +290,7 @@
} }
} }
button[type="button"] { button[type='button'] {
@apply w-full justify-center text-center; @apply w-full justify-center text-center;
} }
} }
@ -332,7 +332,7 @@
&::before, &::before,
&::after { &::after {
@apply border-b border-gray-300 dark:border-gray-600; @apply border-b border-gray-300 dark:border-gray-600;
content: ""; content: '';
flex: 1; flex: 1;
} }
} }

View file

@ -15,8 +15,8 @@
animation: fade 150ms linear; animation: fade 150ms linear;
} }
[column-type=filled] .status__wrapper, [column-type='filled'] .status__wrapper,
[column-type=filled] .status-placeholder { [column-type='filled'] .status-placeholder {
@apply rounded-none shadow-none p-4; @apply rounded-none shadow-none p-4;
} }

View file

@ -165,7 +165,7 @@
} }
&::before { &::before {
content: ""; content: '';
width: 50px; width: 50px;
background: rgba(#fff, 0.35); background: rgba(#fff, 0.35);
border-radius: 4px; border-radius: 4px;
@ -235,7 +235,7 @@
position: relative; position: relative;
&::before { &::before {
content: ""; content: '';
width: 100%; width: 100%;
background: rgba(#fff, 0.35); background: rgba(#fff, 0.35);
border-radius: 4px; border-radius: 4px;

View file

@ -59,7 +59,7 @@
.emoji-mart-anchors svg, .emoji-mart-anchors svg,
.emoji-mart-anchors img { .emoji-mart-anchors img {
fill: currentColor; fill: currentcolor;
height: 18px; height: 18px;
width: 18px; width: 18px;
} }

Binary file not shown.

View file

@ -91,7 +91,7 @@
"@types/redux-mock-store": "^1.0.3", "@types/redux-mock-store": "^1.0.3",
"@types/seedrandom": "^3.0.2", "@types/seedrandom": "^3.0.2",
"@types/semver": "^7.3.9", "@types/semver": "^7.3.9",
"@types/uuid": "^8.3.4", "@types/uuid": "^9.0.0",
"@types/webpack-assets-manifest": "^5.1.0", "@types/webpack-assets-manifest": "^5.1.0",
"@types/webpack-bundle-analyzer": "^4.6.0", "@types/webpack-bundle-analyzer": "^4.6.0",
"@types/webpack-deadcode-plugin": "^0.1.2", "@types/webpack-deadcode-plugin": "^0.1.2",
@ -198,7 +198,7 @@
"twemoji": "https://github.com/twitter/twemoji#v14.0.2", "twemoji": "https://github.com/twitter/twemoji#v14.0.2",
"typescript": "^4.4.4", "typescript": "^4.4.4",
"util": "^0.12.4", "util": "^0.12.4",
"uuid": "^8.3.2", "uuid": "^9.0.0",
"webpack": "^5.72.1", "webpack": "^5.72.1",
"webpack-assets-manifest": "^5.1.0", "webpack-assets-manifest": "^5.1.0",
"webpack-bundle-analyzer": "^4.5.0", "webpack-bundle-analyzer": "^4.5.0",
@ -208,6 +208,7 @@
"wicg-inert": "^3.1.1" "wicg-inert": "^3.1.1"
}, },
"devDependencies": { "devDependencies": {
"@babel/eslint-parser": "^7.19.1",
"@jedmao/redux-mock-store": "^3.0.5", "@jedmao/redux-mock-store": "^3.0.5",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.10", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.10",
"@testing-library/jest-dom": "^5.16.4", "@testing-library/jest-dom": "^5.16.4",
@ -215,20 +216,19 @@
"@testing-library/user-event": "^14.0.3", "@testing-library/user-event": "^14.0.3",
"@typescript-eslint/eslint-plugin": "^5.15.0", "@typescript-eslint/eslint-plugin": "^5.15.0",
"@typescript-eslint/parser": "^5.15.0", "@typescript-eslint/parser": "^5.15.0",
"babel-eslint": "^10.1.0",
"babel-jest": "^29.0.0", "babel-jest": "^29.0.0",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"danger": "^11.0.7", "danger": "^11.0.7",
"eslint": "^7.0.0", "eslint": "^8.0.0",
"eslint-plugin-compat": "^4.0.2", "eslint-plugin-compat": "^4.0.2",
"eslint-plugin-import": "^2.25.4", "eslint-plugin-import": "^2.25.4",
"eslint-plugin-jsdoc": "^39.6.2", "eslint-plugin-jsdoc": "^39.6.2",
"eslint-plugin-jsx-a11y": "^6.4.1", "eslint-plugin-jsx-a11y": "^6.4.1",
"eslint-plugin-promise": "^5.1.0", "eslint-plugin-promise": "^6.0.0",
"eslint-plugin-react": "^7.25.1", "eslint-plugin-react": "^7.25.1",
"eslint-plugin-react-hooks": "^4.2.0", "eslint-plugin-react-hooks": "^4.2.0",
"fake-indexeddb": "^4.0.0", "fake-indexeddb": "^4.0.0",
"husky": "^7.0.2", "husky": "^8.0.0",
"jest": "^29.0.0", "jest": "^29.0.0",
"jest-environment-jsdom": "^29.0.0", "jest-environment-jsdom": "^29.0.0",
"jest-junit": "^15.0.0", "jest-junit": "^15.0.0",
@ -236,9 +236,8 @@
"raf": "^3.4.1", "raf": "^3.4.1",
"react-intl-translations-manager": "^5.0.3", "react-intl-translations-manager": "^5.0.3",
"react-refresh": "^0.14.0", "react-refresh": "^0.14.0",
"stylelint": "^13.7.2", "stylelint": "^14.0.0",
"stylelint-config-standard": "^22.0.0", "stylelint-config-standard-scss": "^6.1.0",
"stylelint-scss": "^4.0.0",
"tailwindcss": "^3.2.1", "tailwindcss": "^3.2.1",
"ts-jest": "^29.0.0", "ts-jest": "^29.0.0",
"webpack-dev-server": "^4.9.1", "webpack-dev-server": "^4.9.1",

View file

@ -3,8 +3,5 @@
"config:base", "config:base",
":preserveSemverRanges" ":preserveSemverRanges"
], ],
"lockFileMaintenance": {
"enabled": true
},
"rebaseWhen": "conflicted" "rebaseWhen": "conflicted"
} }

985
yarn.lock

File diff suppressed because it is too large Load diff