diff --git a/cypress/support/e2e.ts b/cypress/support/e2e.ts index 8ea6dee..5e77dba 100644 --- a/cypress/support/e2e.ts +++ b/cypress/support/e2e.ts @@ -17,7 +17,7 @@ import './commands'; // Handle uncaught exceptions -Cypress.on('uncaught:exception', (err, runnable) => { +Cypress.on('uncaught:exception', (err) => { // TODO: Ignore transient network errors until either browser caching // or js fixtures are supported // https://github.com/cypress-io/cypress/issues/18335 diff --git a/src/App.tsx b/src/App.tsx index f1eabe8..6502aa6 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -4,6 +4,7 @@ import { useGoogleAnalytics } from './playground-ui/GoogleAnalyticsHook'; import PlaygroundUIThemed from './playground-ui/PlaygroundUIThemed'; import 'react-reflex/styles.css'; import { BrowserRouter } from 'react-router-dom'; +import { type ReactNode } from 'react'; import 'typeface-roboto-mono/index.css'; // Import the Roboto Mono font. import './App.css'; import { EmbeddedPlayground } from './components/EmbeddedPlayground'; @@ -13,11 +14,6 @@ import AppConfig from './services/configservice'; import { PLAYGROUND_UI_COLORS } from './theme'; export interface AppProps { - /** - * withRouter, it specified, is the router to wrap the application with. - */ - withRouter?: any; - /** * forTesting indicates whether the app is for testing. */ @@ -29,7 +25,7 @@ function ForTesting() { } function ThemedApp(props: { - withRouter?: any; + withRouter?: () => ReactNode; forTesting: boolean | undefined; }) { if (window.location.pathname.indexOf('/i/') >= 0) { @@ -55,7 +51,12 @@ function ThemedApp(props: { <ForTesting /> ); } else { - return <FullPlayground withRouter={props.withRouter} />; + return ( + // @ts-expect-error RRv5 types are jank + <BrowserRouter> +<FullPlayground /> +</BrowserRouter> + ); } } @@ -72,7 +73,6 @@ function App(props: AppProps) { <AlertProvider> <ConfirmDialogProvider> <ThemedApp - withRouter={props.withRouter} forTesting={props.forTesting} /> </ConfirmDialogProvider> diff --git a/src/components/FullPlayground.tsx b/src/components/FullPlayground.tsx index f7bd447..adbcbe2 100644 --- a/src/components/FullPlayground.tsx +++ b/src/components/FullPlayground.tsx @@ -12,7 +12,6 @@ import { useZedTerminalService } from '../spicedb-common/services/zedterminalser import { parseValidationYAML } from '../spicedb-common/validationfileformat'; import { LinearProgress, Tab, Tabs, Tooltip } from '@material-ui/core'; import AppBar from '@material-ui/core/AppBar'; -import Box from '@material-ui/core/Box'; import Button from '@material-ui/core/Button'; import ButtonGroup from '@material-ui/core/ButtonGroup'; import TextField from '@material-ui/core/TextField'; @@ -41,7 +40,7 @@ import ToggleButtonGroup from '@material-ui/lab/ToggleButtonGroup'; import clsx from 'clsx'; import { saveAs } from 'file-saver'; import { fileDialog } from 'file-select-dialog'; -import React, { useEffect, useMemo, useState } from 'react'; +import { useEffect, useMemo, useState, type ReactNode } from 'react'; import { useCookies } from 'react-cookie'; import 'react-reflex/styles.css'; import { useHistory, useLocation } from 'react-router-dom'; @@ -90,13 +89,6 @@ import { ValidationPanel, ValidationSummary } from './panels/validation'; import { VisualizerPanel, VisualizerSummary } from './panels/visualizer'; import { WatchesPanel, WatchesSummary } from './panels/watches'; -export interface AppProps { - /** - * withRouter, it specified, is the router to wrap the application with. - */ - withRouter?: any; -} - const TOOLBAR_BREAKPOINT = 1550; // pixels interface StyleProps { @@ -361,21 +353,19 @@ interface SharingState { shareReference?: string; } -export function FullPlayground(props: { withRouter?: any }) { +export function FullPlayground() { return <> <DiscordChatCrate serverId={AppConfig().discord.serverId} channelId={AppConfig().discord.channelId} /> - <ApolloedPlayground withRouter={props.withRouter} /> + <ApolloedPlayground /> </> } -function ApolloedPlayground(props: { withRouter?: any }) { +function ApolloedPlayground() { const datastore = usePlaygroundDatastore(); - const Router = props.withRouter ? props.withRouter : Box; return ( - <Router> <ShareLoader datastore={datastore} shareUrlRoot="s" @@ -383,7 +373,6 @@ function ApolloedPlayground(props: { withRouter?: any }) { > <ThemedAppView key="app" datastore={datastore} /> </ShareLoader> - </Router> ); } @@ -615,7 +604,7 @@ export function ThemedAppView(props: { datastore: DataStore }) { setPreviousValidationForDiff(undefined); validationService.conductValidation( - (validated: boolean, result: ValidationResult) => { + (_validated: boolean, result: ValidationResult) => { if (result.updatedValidationYaml) { const updatedYaml = normalizeValidationYAML( result.updatedValidationYaml @@ -670,7 +659,7 @@ export function ThemedAppView(props: { datastore: DataStore }) { const validationState = validationService.state; const handleChangeTab = ( - event: React.ChangeEvent<{}>, + _event: React.ChangeEvent<HTMLElement>, selectedTabValue: string ) => { const item = datastore.getById(selectedTabValue)!; @@ -702,8 +691,8 @@ export function ThemedAppView(props: { datastore: DataStore }) { return cookieService.relationshipsEditorType; }); const handleChangeRelationshipEditor = ( - event: React.MouseEvent<HTMLElement, MouseEvent>, - value: any + _event: React.MouseEvent<HTMLElement, MouseEvent>, + value: unknown ) => { const type = value ? value.toString() : 'grid'; if ( @@ -713,8 +702,10 @@ export function ThemedAppView(props: { datastore: DataStore }) { return; } - cookieService.setRelationshipsEditorType(type); - setRelationshipEditor(type); + if (type === 'grid' || type === 'code') { + cookieService.setRelationshipsEditorType(type); + setRelationshipEditor(type); + } }; const appConfig = AppConfig(); @@ -1081,7 +1072,7 @@ export function ThemedAppView(props: { datastore: DataStore }) { const TabLabelWithCount = (props: { problemService: ProblemService; kind: DataStoreItemKind; - icon: React.ReactChild; + icon: ReactNode; title: string; }) => { const classes = useSummaryStyles(); @@ -1262,7 +1253,7 @@ const getFileContentsAsText = async (file: File): Promise<string> => { return new Promise( ( resolve: (value: string | PromiseLike<string>) => void, - reject: (reason?: any) => void + reject: () => void ) => { const reader = new FileReader(); reader.onloadend = function (e: ProgressEvent<FileReader>) { diff --git a/src/components/GuidedTour.tsx b/src/components/GuidedTour.tsx index b1fb9a1..28b0766 100644 --- a/src/components/GuidedTour.tsx +++ b/src/components/GuidedTour.tsx @@ -1,8 +1,5 @@ import { Theme, useTheme } from '@material-ui/core/styles'; -import React from 'react'; -import Joyride, { ACTIONS, EVENTS, Step } from 'react-joyride'; - -const _ = React; +import Joyride, { ACTIONS, EVENTS, type Step } from 'react-joyride'; export const TourElementClass = { schema: 'tec-schema', @@ -92,11 +89,10 @@ const handleEvents = ( index: number; size: number; type: string; - step: any; + step: Step; }) => { - const { action, index, size, type, step } = data; + const { action, type, step } = data; - const properties = { Step: step.title, StepIndex: index, StepsCount: size }; // Tour start if (ACTIONS.START === action && EVENTS.TOUR_START === type) { // No-op @@ -107,7 +103,9 @@ const handleEvents = ( } // Tour before step if (ACTIONS.NEXT === action && EVENTS.STEP_BEFORE === type) { - onEnterStep(step.target); + if (typeof step.target === "string") { + onEnterStep(step.target); + } } // Tour step if (ACTIONS.UPDATE === action && EVENTS.TOOLTIP === type) { diff --git a/src/components/InlinePlayground.tsx b/src/components/InlinePlayground.tsx index 332af1a..2ebe27b 100644 --- a/src/components/InlinePlayground.tsx +++ b/src/components/InlinePlayground.tsx @@ -118,7 +118,7 @@ function InlinePlaygroundUI(props: { datastore: DataStore }) { ); const handleChangeTab = ( - event: React.ChangeEvent<{}>, + _event: React.ChangeEvent<HTMLElement>, selectedTabName: string ) => { setCurrentTabName(selectedTabName); diff --git a/src/components/KindIcons.tsx b/src/components/KindIcons.tsx index 911ece0..cc804b2 100644 --- a/src/components/KindIcons.tsx +++ b/src/components/KindIcons.tsx @@ -1,15 +1,14 @@ import { faDatabase } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { createStyles, makeStyles, Theme } from '@material-ui/core/styles'; +import { createStyles, makeStyles } from '@material-ui/core/styles'; import WarningIcon from '@material-ui/icons/Warning'; -import React from 'react'; import 'react-reflex/styles.css'; interface StyleProps { small?: boolean } -const useStyles = makeStyles((theme: Theme) => +const useStyles = makeStyles(() => createStyles({ ns: { fontFamily: 'Roboto Mono, monospace', diff --git a/src/components/ValidationButton.tsx b/src/components/ValidationButton.tsx index a291b6c..e52ed3c 100644 --- a/src/components/ValidationButton.tsx +++ b/src/components/ValidationButton.tsx @@ -7,14 +7,11 @@ import CheckCircleOutlineIcon from '@material-ui/icons/CheckCircleOutline'; import ErrorIcon from '@material-ui/icons/Error'; import PlayCircleFilledIcon from '@material-ui/icons/PlayCircleFilled'; import clsx from 'clsx'; -import React from 'react'; import 'react-reflex/styles.css'; import { DataStore } from '../services/datastore'; import { ValidationState, ValidationStatus } from '../services/validation'; import { TourElementClass } from './GuidedTour'; -const _ = React; - const useStyles = makeStyles((theme: Theme) => createStyles({ gcm: { diff --git a/src/components/panels/base/components.tsx b/src/components/panels/base/components.tsx index 39e103a..7e0270e 100644 --- a/src/components/panels/base/components.tsx +++ b/src/components/panels/base/components.tsx @@ -8,7 +8,7 @@ import Tabs from '@material-ui/core/Tabs'; import Toolbar from '@material-ui/core/Toolbar'; import { Theme, createStyles, makeStyles } from '@material-ui/core/styles'; import CloseIcon from '@material-ui/icons/Close'; -import React, { useCallback } from 'react'; +import { useCallback, type ReactNode } from 'react'; import { DataStore } from '../../../services/datastore'; import { Services } from '../../../services/services'; import { Panel, useSummaryStyles } from './common'; @@ -24,7 +24,7 @@ export function PanelSummaryBar<L extends string>(props: { coordinator: PanelsCoordinator<L>; services: Services; disabled?: boolean | undefined; - overrideSummaryDisplay?: React.ReactChild; + overrideSummaryDisplay?: ReactNode; }) { const classes = useSummaryStyles(); @@ -40,7 +40,7 @@ export function PanelSummaryBar<L extends string>(props: { className={classes.summaryBar} style={{ gridTemplateColumns: `${panels - .map((panel: Panel<L>) => 'auto') + .map(() => 'auto') .join(' ')} 1fr auto`, }} variant="dense" @@ -132,7 +132,7 @@ export function PanelDisplay<L extends string>( const currentTabName = coordinator.getActivePanel(props.location)?.id || ''; const handleChangeTab = useCallback( - (event: React.ChangeEvent<{}>, selectedPanelId: string) => { + (_event: React.ChangeEvent<HTMLElement>, selectedPanelId: string) => { coordinator.setActivePanel(selectedPanelId, props.location); }, [coordinator, props.location] diff --git a/src/components/panels/base/coordinator.tsx b/src/components/panels/base/coordinator.tsx index c9dc59d..7d37947 100644 --- a/src/components/panels/base/coordinator.tsx +++ b/src/components/panels/base/coordinator.tsx @@ -165,6 +165,7 @@ export function usePanelsCoordinator<L extends string>(props: PanelCoordinatorPr } } catch (e) { // Do nothing. + console.error(e) } const locations: Record<string, L> = {}; @@ -333,4 +334,4 @@ export function usePanelsCoordinator<L extends string>(props: PanelCoordinatorPr isDisplayVisible: isDisplayVisible, listLocations: listLocations, }; -} \ No newline at end of file +} diff --git a/src/components/panels/base/reflexed.tsx b/src/components/panels/base/reflexed.tsx index 3a106e5..70d39e9 100644 --- a/src/components/panels/base/reflexed.tsx +++ b/src/components/panels/base/reflexed.tsx @@ -1,7 +1,7 @@ -import { createStyles, makeStyles, Theme } from "@material-ui/core/styles"; +import { createStyles, makeStyles } from "@material-ui/core/styles"; import HorizontalSplitIcon from "@material-ui/icons/HorizontalSplit"; import VerticalSplitIcon from "@material-ui/icons/VerticalSplit"; -import React, { PropsWithChildren, useEffect, useState } from "react"; +import { PropsWithChildren, useEffect, useState, Children, isValidElement, cloneElement, type ReactNode } from "react"; import { HandlerProps, ReflexContainer, @@ -31,7 +31,7 @@ const MINIMUM_VERTICAL_FLEX = 0.2; const MINIMUM_HORIZONTAL_SIZE = 200; const MINIMUM_VERTICAL_SIZE = 200; -const useStyles = makeStyles((theme: Theme) => +const useStyles = makeStyles(() => createStyles({ noOverflow: { overflow: "hidden !important", @@ -53,7 +53,7 @@ interface PanelDefProps<E> { panels: Panel<ReflexedPanelLocation>[]; extraProps?: E | undefined; disabled?: boolean | undefined; - overrideSummaryDisplay?: React.ReactChild; + overrideSummaryDisplay?: ReactNode; } interface Dimensions { @@ -263,14 +263,14 @@ function MainDisplayAndVertical<E>( ? { width: props.dimensions.width, height: contentHeight } : undefined; - const adjustedChildren = React.Children.map(props.children, (child) => { + const adjustedChildren = Children.map(props.children, (child) => { // Based on: https://stackoverflow.com/a/55486160 - if (!React.isValidElement<EnrichedChildren>(child)) { + if (!isValidElement<EnrichedChildren>(child)) { return child; } const elementChild: React.ReactElement<EnrichedChildren> = child; - return React.cloneElement( + return cloneElement( elementChild, { dimensions: contentDimensions, ...child.props }, null diff --git a/src/components/panels/terminal.tsx b/src/components/panels/terminal.tsx index dc7275e..c55b383 100644 --- a/src/components/panels/terminal.tsx +++ b/src/components/panels/terminal.tsx @@ -14,7 +14,7 @@ import type { MouseEvent, KeyboardEvent, ChangeEvent, ReactNode } from 'react'; import 'react-reflex/styles.css'; import useDeepCompareEffect from 'use-deep-compare-effect'; import { DataStoreItemKind } from '../../services/datastore'; -import { PanelProps, PanelSummaryProps } from './base/common'; +import { PanelProps } from './base/common'; import { PlaygroundPanelLocation } from './panels'; const useStyles = makeStyles((theme: Theme) => @@ -55,10 +55,8 @@ const useStyles = makeStyles((theme: Theme) => }) ); -export function TerminalSummary( - props: PanelSummaryProps<PlaygroundPanelLocation> -) { - return ( +export function TerminalSummary() { + return ( <TabLabel icon={<FontAwesomeIcon icon={faTerminal} />} title="Zed Terminal" @@ -260,6 +258,7 @@ function convertStringOutput(convert: Convert, o: string, showLogs: boolean) { } } catch (e) { // Do nothing. + console.error(e) } } @@ -318,11 +317,11 @@ function TerminalOutputDisplay(props: { function getSelectedTextWithin(el: Element) { let selectedText = ''; if (typeof window.getSelection != 'undefined') { - let sel = window.getSelection(), - rangeCount; + const sel = window.getSelection(); + let rangeCount: number; if (sel && (rangeCount = sel.rangeCount) > 0) { const range = document.createRange(); - for (var i = 0, selRange; i < rangeCount; ++i) { + for (let i = 0, selRange: Range; i < rangeCount; ++i) { range.selectNodeContents(el); selRange = sel.getRangeAt(i); if ( diff --git a/src/components/panels/watches.tsx b/src/components/panels/watches.tsx index 8da5226..82845a0 100644 --- a/src/components/panels/watches.tsx +++ b/src/components/panels/watches.tsx @@ -42,7 +42,7 @@ import { interpolateOranges, interpolatePurples, } from 'd3-scale-chromatic'; -import { useMemo, useState } from 'react'; +import { useMemo, useState, type ChangeEvent } from 'react'; import 'react-reflex/styles.css'; import { LiveCheckItem, @@ -276,7 +276,7 @@ export function WatchesPanel(props: PanelProps<PlaygroundPanelLocation>) { )} <TableBody> {liveCheckService.items.length > 0 && - liveCheckService.items.map((item: LiveCheckItem, index: number) => { + liveCheckService.items.map((item: LiveCheckItem) => { return ( <LiveCheckRow key={item.id} @@ -339,40 +339,40 @@ function LiveCheckRow(props: { const [actionInputValue, setActionInputValue] = useState(item.action); const [subjectInputValue, setSubjectInputValue] = useState(item.subject); - const handleChangeObjectInput = (event: any, newValue: string) => { + const handleChangeObjectInput = (_event: object, newValue: string) => { setObjectInputValue(newValue); item.object = newValue; liveCheckService.itemUpdated(item); }; - const handleChangeObject = (event: any, newValue: string | null) => { + const handleChangeObject = (_event: object, newValue: string | null) => { setObject(newValue ?? ''); item.object = newValue ?? ''; }; - const handleChangeActionInput = (event: any, newValue: string) => { + const handleChangeActionInput = (_event: object, newValue: string) => { setActionInputValue(newValue); item.action = newValue; liveCheckService.itemUpdated(item); }; - const handleChangeAction = (event: any, newValue: string | null) => { + const handleChangeAction = (_event: object, newValue: string | null) => { setAction(newValue ?? ''); item.action = newValue ?? ''; }; - const handleChangeSubjectInput = (event: any, newValue: string) => { + const handleChangeSubjectInput = (_event: object, newValue: string) => { setSubjectInputValue(newValue); item.subject = newValue; liveCheckService.itemUpdated(item); }; - const handleChangeSubject = (event: any, newValue: string | null) => { + const handleChangeSubject = (_event: object, newValue: string | null) => { setSubject(newValue ?? ''); item.subject = newValue ?? ''; }; - const handleChangeContextInput = (event: any) => { + const handleChangeContextInput = (event: ChangeEvent<HTMLInputElement>) => { const newValue = event.target.value; setContext(newValue ?? ''); // NOTE: adding a dummy caveat name to support only specifying the context with checks @@ -567,7 +567,7 @@ function LiveCheckRow(props: { <Autocomplete freeSolo options={objects} - getOptionLabel={(option: any) => option} + getOptionLabel={(option: string) => option} renderOption={(option) => renderOption(option, objects, interpolatePurples) } @@ -603,7 +603,7 @@ function LiveCheckRow(props: { <Autocomplete freeSolo options={actions} - getOptionLabel={(option: any) => option} + getOptionLabel={(option: string) => option} renderOption={(option) => renderOption(option, actions, interpolateBlues) } @@ -639,7 +639,7 @@ function LiveCheckRow(props: { <Autocomplete freeSolo options={subjects} - getOptionLabel={(option: any) => option} + getOptionLabel={(option: string) => option} renderOption={(option) => renderOption(option, subjects, interpolateOranges) } diff --git a/src/components/tuplelang.ts b/src/components/tuplelang.ts index a2cc472..236d802 100644 --- a/src/components/tuplelang.ts +++ b/src/components/tuplelang.ts @@ -1,4 +1,4 @@ -import { CancellationToken, editor, Position } from 'monaco-editor'; +import { editor, Position } from 'monaco-editor'; import * as monacoEditor from 'monaco-editor'; import { LocalParseState } from '../services/localparse'; import { diff --git a/src/index.tsx b/src/index.tsx index 933b04f..04b04d1 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,7 +1,6 @@ import "@fontsource/roboto/index.css"; import React from "react"; import { createRoot } from "react-dom/client"; -import { BrowserRouter } from "react-router-dom"; import App from "./App"; import "./index.css"; @@ -11,7 +10,7 @@ createRoot( container ).render( <React.StrictMode> - <App withRouter={BrowserRouter} /> + <App /> </React.StrictMode>, ); } diff --git a/src/playground-ui/AlertDialog.tsx b/src/playground-ui/AlertDialog.tsx index 283c2e9..f6e811c 100644 --- a/src/playground-ui/AlertDialog.tsx +++ b/src/playground-ui/AlertDialog.tsx @@ -18,7 +18,7 @@ export interface AlertDialogProps { /** * handleClose sets the state that is bound to `isOpen` to false. */ - handleClose: () => any + handleClose: () => void /** * title is the title of the alert. @@ -57,4 +57,4 @@ export function AlertDialog(props: AlertDialogProps) { </Button> </DialogActions> </Dialog>; -} \ No newline at end of file +} diff --git a/src/playground-ui/AlertProvider.tsx b/src/playground-ui/AlertProvider.tsx index e28fcb3..583c052 100644 --- a/src/playground-ui/AlertProvider.tsx +++ b/src/playground-ui/AlertProvider.tsx @@ -1,8 +1,8 @@ import React, { - PropsWithChildren, useCallback, useContext, useState, + type ReactNode, } from "react"; import { AlertDialog } from "./AlertDialog"; @@ -25,14 +25,14 @@ export interface AlertProps { export type AlertCallback = () => void; -export type ShowAlert = (props: AlertProps, callback: AlertCallback) => any; +export type ShowAlert = (props: AlertProps, callback: AlertCallback) => void; const AlertContext = React.createContext<ShowAlert | undefined>(undefined); /** * AlertProvider provides the alert dialog UI. */ -export function AlertProvider(props: PropsWithChildren<any>) { +export function AlertProvider(props: { children: ReactNode }) { const [alertProps, setAlertProps] = useState<AlertProps>({ title: "", content: "", diff --git a/src/spicedb-common/components/relationshipeditor/commentcell.tsx b/src/spicedb-common/components/relationshipeditor/commentcell.tsx index 948f032..336bd7f 100644 --- a/src/spicedb-common/components/relationshipeditor/commentcell.tsx +++ b/src/spicedb-common/components/relationshipeditor/commentcell.tsx @@ -94,7 +94,7 @@ export const CommentCellRenderer = ( ) => { return { isMatch: (cell: CustomCell): cell is CommentCell => - (cell.data as any).kind === COMMENT_CELL_KIND, + cell.data.kind === COMMENT_CELL_KIND, draw: (args, cell) => { const { ctx, rect } = args; const { dataValue } = cell.data; @@ -112,7 +112,7 @@ export const CommentCellRenderer = ( ctx.restore(); return true; }, - provideEditor: (cell: any) => (p) => { + provideEditor: () => (p) => { const { onChange, value, initialValue } = p; return ( <CommentCellEditor diff --git a/src/spicedb-common/components/relationshipeditor/customcells.ts b/src/spicedb-common/components/relationshipeditor/customcells.ts index a04002e..564f405 100644 --- a/src/spicedb-common/components/relationshipeditor/customcells.ts +++ b/src/spicedb-common/components/relationshipeditor/customcells.ts @@ -245,9 +245,7 @@ export function useCustomCells( for (const r of renderers) { if (r.isMatch(cell)) { - return r.provideEditor(cell) as ReturnType< - ProvideEditorCallback<GridCell> - >; + return r.provideEditor(); } }