diff --git a/__tests__/integration/mirador/thumbnail-navigation.test.js b/__tests__/integration/mirador/thumbnail-navigation.test.js index 35de953cca..82502cbd53 100644 --- a/__tests__/integration/mirador/thumbnail-navigation.test.js +++ b/__tests__/integration/mirador/thumbnail-navigation.test.js @@ -6,7 +6,8 @@ describe('Thumbnail navigation', () => { await expect(page).toMatchElement('.mirador-window', { polling: 'mutation', timeout: 5000 }); }); - it('navigates a manifest using thumbnail navigation', async () => { + // TODO: pick a new url; this Harvard one is 404 + xit('navigates a manifest using thumbnail navigation', async () => { await expect(page).toMatchElement('.mirador-thumb-navigation'); let windows = await page.evaluate(() => ( miradorInstance.store.getState().windows @@ -20,7 +21,7 @@ describe('Thumbnail navigation', () => { )); expect(Object.values(windows)[0].canvasId).toBe('https://iiif.harvardartmuseums.org/manifests/object/299843/canvas/canvas-18737483'); // canvas @ index 1 }); - it('displays on right side', async () => { + xit('displays on right side', async () => { await expect(page).toMatchElement('.mirador-thumb-navigation'); await expect(page).toMatchElement('.mirador-companion-area-far-bottom .mirador-thumb-navigation'); const windowId = await page.evaluate(() => { diff --git a/__tests__/src/components/AppProviders.test.js b/__tests__/src/components/AppProviders.test.js index 82e2f981e3..ae97556638 100644 --- a/__tests__/src/components/AppProviders.test.js +++ b/__tests__/src/components/AppProviders.test.js @@ -1,4 +1,4 @@ -import Button from '@material-ui/core/Button'; +import Button from '@mui/material/Button'; import { render, screen } from 'test-utils'; import { useTranslation } from 'react-i18next'; import { useDrop } from 'react-dnd'; diff --git a/__tests__/src/components/CollapsibleSection.test.js b/__tests__/src/components/CollapsibleSection.test.js index 9e3ee8757c..aad2dd0f4c 100644 --- a/__tests__/src/components/CollapsibleSection.test.js +++ b/__tests__/src/components/CollapsibleSection.test.js @@ -34,9 +34,9 @@ describe('CollapsibleSection', () => { expect(screen.getByRole('button')).toHaveAttribute('aria-label', 'expandSection'); }); - it('renders children based on the open state', async () => { - expect(screen.getByTestId('child')).toBeInTheDocument(); + it('displays children based on the open state', async () => { + expect(screen.getByTestId('child')).toBeVisible(); await userEvent.click(screen.getByRole('button')); - expect(screen.queryByTestId('child')).not.toBeInTheDocument(); + expect(screen.queryByTestId('child')).not.toBeVisible(); }); }); diff --git a/__tests__/src/components/CompanionArea.test.js b/__tests__/src/components/CompanionArea.test.js index 404359b6af..53e7bcdb0a 100644 --- a/__tests__/src/components/CompanionArea.test.js +++ b/__tests__/src/components/CompanionArea.test.js @@ -30,7 +30,7 @@ describe('CompanionArea', () => { it('should add the appropriate classes when the companion area fills the full width', () => { const { container } = createWrapper({ position: 'bottom' }); - expect(container.querySelector('.mirador-companion-area-bottom')).toHaveClass('horizontal'); // eslint-disable-line testing-library/no-node-access, testing-library/no-container + expect(container.querySelector('.mirador-companion-area-bottom')).toBeInTheDocument(); // eslint-disable-line testing-library/no-node-access, testing-library/no-container }); it('renders the appropriate components', () => { diff --git a/__tests__/src/components/CompanionWindow.test.js b/__tests__/src/components/CompanionWindow.test.js index 60343426fe..a7fe7b71ef 100644 --- a/__tests__/src/components/CompanionWindow.test.js +++ b/__tests__/src/components/CompanionWindow.test.js @@ -11,7 +11,6 @@ function createWrapper(props) { isDisplayed direction="ltr" windowId="x" - classes={{ horizontal: 'horizontal', small: 'small', vertical: 'vertical' }} companionWindow={{}} position="right" {...props} @@ -96,9 +95,10 @@ describe('CompanionWindow', () => { updateCompanionWindow, }); - expect(screen.getByRole('complementary')).toHaveClass('vertical'); + expect(screen.getByRole('complementary')).toHaveClass('mirador-companion-window-right'); await user.click(screen.getByRole('button', { name: 'moveCompanionWindowToBottom' })); + expect(updateCompanionWindow).toHaveBeenCalledWith({ position: 'bottom' }); }); }); @@ -113,7 +113,7 @@ describe('CompanionWindow', () => { updateCompanionWindow, }); - expect(screen.getByRole('complementary')).toHaveClass('horizontal'); + expect(screen.getByRole('complementary')).toHaveClass('mirador-companion-window-bottom '); await user.click(screen.getByRole('button', { name: 'moveCompanionWindowToRight' })); @@ -127,12 +127,6 @@ describe('CompanionWindow', () => { expect(screen.getByTestId('xyz')).toBeInTheDocument(); }); - it('adds a small class when the component width is small', () => { - const { container } = createWrapper({ size: { width: 369 } }); - - expect(container.querySelector('.MuiToolbar-root')).toHaveClass('small'); // eslint-disable-line testing-library/no-node-access, testing-library/no-container - }); - it('has a resize handler', () => { const { container } = createWrapper(); diff --git a/__tests__/src/components/GalleryViewThumbnail.test.js b/__tests__/src/components/GalleryViewThumbnail.test.js index 3ff910b086..bad9e3098e 100644 --- a/__tests__/src/components/GalleryViewThumbnail.test.js +++ b/__tests__/src/components/GalleryViewThumbnail.test.js @@ -11,7 +11,6 @@ function createWrapper(props) { return render( {}} setCanvas={() => {}} {...props} @@ -23,26 +22,6 @@ describe('GalleryView', () => { beforeEach(() => { window.HTMLElement.prototype.scrollIntoView = jest.fn(); }); - it('sets a mirador-current-canvas-grouping class when the canvas is selected', () => { - createWrapper({ selected: true }); - expect(screen.getByRole('button')).toBeInTheDocument(); - expect(screen.getByRole('button')).toHaveClass('selected'); - }); - it('does not set a mirador-current-canvas-grouping class when the canvas is not selected', () => { - createWrapper({ selected: false }); - expect(screen.getByRole('button')).toBeInTheDocument(); - expect(screen.getByRole('button')).not.toHaveClass('selected'); - }); - it('sets a mirador-current-canvas-grouping class when the canvas is selected', () => { - createWrapper({ selected: true }); - expect(screen.getByRole('button')).toBeInTheDocument(); - expect(screen.getByRole('button')).toHaveClass('selected'); - }); - it('does not set a mirador-current-canvas-grouping class when the canvas is not selected', () => { - createWrapper({ selected: false }); - expect(screen.getByRole('button')).toBeInTheDocument(); - expect(screen.getByRole('button')).not.toHaveClass('selected'); - }); it('renders the thumbnail', () => { createWrapper({ config: { height: 55 } }); expect(screen.getByRole('presentation')).toBeInTheDocument(); diff --git a/__tests__/src/components/IIIFAuthentication.test.js b/__tests__/src/components/IIIFAuthentication.test.js index d9be920ac9..d49d5e712d 100644 --- a/__tests__/src/components/IIIFAuthentication.test.js +++ b/__tests__/src/components/IIIFAuthentication.test.js @@ -33,7 +33,7 @@ describe('IIIFAuthentication', () => { describe('without an auth service', () => { it('renders nothing', () => { createWrapper({ authServiceId: null }); - expect(screen.queryByText('login', { selector: 'span' })).not.toBeInTheDocument(); + expect(screen.queryByRole('button', { name: 'login' })).not.toBeInTheDocument(); expect(screen.queryByRole('button')).not.toBeInTheDocument(); }); }); @@ -41,9 +41,7 @@ describe('IIIFAuthentication', () => { it('renders a login bar', async () => { const handleAuthInteraction = jest.fn(); createWrapper({ handleAuthInteraction }); - const confirmBtn = screen.getByText('login', { selector: 'span' }); - expect(confirmBtn).toBeInTheDocument(); - await user.click(confirmBtn); + await user.click(screen.getByRole('button', { name: 'login' })); expect(handleAuthInteraction).toHaveBeenCalledWith('w', 'http://example.com/auth'); }); it('renders nothing for a non-interactive login', () => { @@ -55,7 +53,8 @@ describe('IIIFAuthentication', () => { it('renders with an error message', async () => { const handleAuthInteraction = jest.fn(); createWrapper({ handleAuthInteraction, status: 'failed' }); - const confirmBtn = await screen.findByText('retry', { selector: 'span' }); + await user.click(screen.getByRole('button', { name: 'continue' })); + const confirmBtn = screen.getByRole('button', { name: /retry/ }); expect(screen.getByText('Login failed')).toBeInTheDocument(); expect(screen.getByText('cancel')).toBeInTheDocument(); expect(screen.getByText('... and this is why.')).toBeInTheDocument(); @@ -71,7 +70,7 @@ describe('IIIFAuthentication', () => { window.open = mockWindowOpen; const resolveCookieMock = jest.fn(); createWrapper({ resolveAuthenticationRequest: resolveCookieMock, status: 'cookie' }); - expect(screen.getByText('login', { selector: 'span' })).toBeInTheDocument(); + expect(screen.getByRole('button', { name: 'login' })).toBeInTheDocument(); expect(mockWindowOpen).toHaveBeenCalledWith(`http://example.com/auth?origin=${window.origin}`, 'IiifLoginSender', 'centerscreen'); mockWindow.closed = true; jest.runOnlyPendingTimers(); @@ -81,7 +80,7 @@ describe('IIIFAuthentication', () => { it('does the IIIF access token behavior', async () => { const resolveTokenMock = jest.fn(); createWrapper({ resolveAccessTokenRequest: resolveTokenMock, status: 'token' }); - expect(screen.getByText('login', { selector: 'span' })).toBeInTheDocument(); + expect(screen.getByRole('button', { name: 'login' })).toBeInTheDocument(); window.dispatchEvent(new MessageEvent('message', { data: { messageId: 'http://example.com/token' }, })); @@ -100,7 +99,7 @@ describe('IIIFAuthentication', () => { resetAuthenticationState, status: 'ok', }); - const confirmBtn = await screen.findByText('exit', { selector: 'span' }); + const confirmBtn = await screen.findByRole('button', { name: 'exit' }); await user.click(confirmBtn); await waitFor(() => expect(resetAuthenticationState).toHaveBeenCalledWith({ authServiceId: 'http://example.com/auth', tokenServiceId: 'http://example.com/token', diff --git a/__tests__/src/components/LanguageSettings.test.js b/__tests__/src/components/LanguageSettings.test.js index 0cddf8b5db..98b0a82f6d 100644 --- a/__tests__/src/components/LanguageSettings.test.js +++ b/__tests__/src/components/LanguageSettings.test.js @@ -35,13 +35,6 @@ describe('LanguageSettings', () => { expect(screen.getAllByRole('menuitem')).toHaveLength(2); }); - it('non-active list items are buttons (and active are not)', () => { - createWrapper({ languages }); - - expect(screen.getByRole('menuitem', { name: 'Deutsch' })).not.toHaveClass('MuiButtonBase-root'); - expect(screen.getByRole('menuitem', { name: 'English' })).toHaveClass('MuiButtonBase-root'); - }); - it('renders the check icon when the active prop returns true', () => { createWrapper({ languages }); diff --git a/__tests__/src/components/LocalePicker.test.js b/__tests__/src/components/LocalePicker.test.js index a37bdb4bd9..2ff1b2ceef 100644 --- a/__tests__/src/components/LocalePicker.test.js +++ b/__tests__/src/components/LocalePicker.test.js @@ -3,7 +3,7 @@ import userEvent from '@testing-library/user-event'; import { LocalePicker } from '../../../src/components/LocalePicker'; /** - * Helper function to create a shallow wrapper around LanguageSettings + * Helper function to create a shallow wrapper around LocalePicker */ function createWrapper(props) { return render( @@ -24,36 +24,42 @@ describe('LocalePicker', () => { }); it('renders a select with the current value', () => { - createWrapper({ availableLocales: ['en', 'de'], locale: 'en' }); - - expect(screen.getByRole('button')).toHaveTextContent('en'); + createWrapper({ availableLocales: ['en', 'de'], locale: 'de' }); + // The option to expand the dropdown menu is rendered by a CompanionWindow titleControls prop in WindowSideBarInfoPanel, which is a combobox + const dropdownTitle = screen.getByRole('combobox'); + expect(dropdownTitle).toHaveTextContent('de'); }); - it('renders a select with a list item for each language passed in props', async () => { + it('renders a select with both options and sets the current value', async () => { const user = userEvent.setup(); - - createWrapper({ availableLocales: ['en', 'de'], locale: 'en' }); - - await user.click(screen.getByRole('button')); - - expect(screen.getAllByRole('option')).toHaveLength(2); + createWrapper({ availableLocales: ['en', 'de'], locale: 'de' }); + const dropdownTitle = screen.getByRole('combobox'); + // Open the menu + await user.click(dropdownTitle); + // The dropddown menu is not nested within the combobox, it is a sibling in the DOM, an MuiMenu + const menu = screen.getByRole('listbox'); + // Assert that the menu element has 2 children (2 options) + expect(menu.children).toHaveLength(2); // eslint-disable-line testing-library/no-node-access + // Verify that the select element has the correct value ('de') + const deOption = screen.getByRole('option', { name: 'de' }); + expect(deOption).toHaveAttribute('aria-selected', 'true'); + // Verify en is also an option expect(screen.getByRole('option', { name: 'en' })).toBeInTheDocument(); - expect(screen.getByRole('option', { name: 'de' })).toBeInTheDocument(); }); it('triggers setLocale prop when clicking a list item', async () => { const user = userEvent.setup(); const setLocale = jest.fn(); - createWrapper({ availableLocales: ['en', 'de'], locale: 'en', setLocale, }); - - await user.click(screen.getByRole('button')); + const dropdownTitle = screen.getByRole('combobox'); + // Open the Select component + await user.click(dropdownTitle); + // Change the locale to 'de' await user.click(screen.getByRole('option', { name: 'de' })); - expect(setLocale).toHaveBeenCalledTimes(1); expect(setLocale).toHaveBeenCalledWith('de'); }); diff --git a/__tests__/src/components/ManifestListItem.test.js b/__tests__/src/components/ManifestListItem.test.js index ac40ea4586..bd444de915 100644 --- a/__tests__/src/components/ManifestListItem.test.js +++ b/__tests__/src/components/ManifestListItem.test.js @@ -23,18 +23,23 @@ describe('ManifestListItem', () => { createWrapper({ buttonRef: 'ref' }); expect(screen.getByRole('listitem')).toHaveAttribute('data-manifestid', 'http://example.com'); + expect(screen.getByRole('listitem')).toHaveClass('MuiListItem-root'); expect(screen.getByRole('button')).toHaveTextContent('xyz'); }); it('adds a class when the item is active', () => { createWrapper({ active: true, classes: { active: 'active' } }); + // If this is true, we can assume the proper styling classes are being applied + expect(screen.getByRole('listitem')).toHaveAttribute('data-active', 'true'); + expect(screen.getByRole('listitem')).toHaveClass('active'); + expect(screen.getByRole('listitem')).toHaveClass('Mui-selected'); }); it('renders a placeholder element until real data is available', () => { const { container } = createWrapper({ ready: false }); expect(screen.queryByRole('button')).not.toBeInTheDocument(); - expect(container.querySelectorAll('.MuiSkeleton-rect').length).toBeGreaterThan(0); // eslint-disable-line testing-library/no-node-access, testing-library/no-container + expect(container.querySelectorAll('.MuiSkeleton-rectangular').length).toBeGreaterThan(0); // eslint-disable-line testing-library/no-node-access, testing-library/no-container }); it('renders an error message if fetching the manifest failed', () => { createWrapper({ error: 'This is an error message' }); diff --git a/__tests__/src/components/PrimaryWindow.test.js b/__tests__/src/components/PrimaryWindow.test.js index 52ca6c86b8..ad78ebf4b5 100644 --- a/__tests__/src/components/PrimaryWindow.test.js +++ b/__tests__/src/components/PrimaryWindow.test.js @@ -16,7 +16,7 @@ function createWrapper(props) { describe('PrimaryWindow', () => { it('should render expected elements', async () => { createWrapper({ isFetching: false }); - await screen.findByRole('region', { accessibleName: 'item' }); + await screen.findByTestId('test-window'); expect(document.querySelector('.mirador-primary-window')).toBeInTheDocument(); // eslint-disable-line testing-library/no-node-access expect(document.querySelector('.mirador-companion-area-left')).toBeInTheDocument(); // eslint-disable-line testing-library/no-node-access }); @@ -30,7 +30,7 @@ describe('PrimaryWindow', () => { }); it('should render if fetching is complete and view is gallery', async () => { createWrapper({ isFetching: false, view: 'gallery' }); - await screen.findByRole('region', { accessibleName: 'gallery section' }); + await screen.findByTestId('test-window'); expect(document.querySelector('#xyz-gallery')).toBeInTheDocument(); // eslint-disable-line testing-library/no-node-access }); it('should render and if manifest is collection and isCollectionDialogVisible', async () => { diff --git a/__tests__/src/components/SanitizedHtml.test.js b/__tests__/src/components/SanitizedHtml.test.js index 37c09f96c1..382b90570e 100644 --- a/__tests__/src/components/SanitizedHtml.test.js +++ b/__tests__/src/components/SanitizedHtml.test.js @@ -6,7 +6,6 @@ describe('SanitizedHtml', () => { render( , @@ -18,7 +17,6 @@ describe('SanitizedHtml', () => { }); it('should pass correct class name to root element', () => { - expect(screen.getByTestId('subject')).toHaveClass('root'); expect(screen.getByTestId('subject')).toHaveClass('mirador-third-party-html'); }); diff --git a/__tests__/src/components/ScrollIndicatedDialogContent.test.js b/__tests__/src/components/ScrollIndicatedDialogContent.test.js index 4c76018dca..ae84979485 100644 --- a/__tests__/src/components/ScrollIndicatedDialogContent.test.js +++ b/__tests__/src/components/ScrollIndicatedDialogContent.test.js @@ -6,7 +6,6 @@ function createWrapper(props) { return render( , ); @@ -19,16 +18,8 @@ describe('ScrollIndicatedDialogContent', () => { expect(screen.getByTestId('subject')).toHaveAttribute('randomprop', 'randomPropValue'); }); - it('provides a className to the DialogContent prop to style it', () => { - createWrapper(); - - expect(screen.getByTestId('subject')).toHaveClass('shadowScrollDialog'); - }); - it('joins an incoming className prop with our className', () => { createWrapper({ className: 'upstreamClassName' }); - - expect(screen.getByTestId('subject')).toHaveClass('shadowScrollDialog'); expect(screen.getByTestId('subject')).toHaveClass('upstreamClassName'); }); }); diff --git a/__tests__/src/components/ScrollTo.test.js b/__tests__/src/components/ScrollTo.test.js index eb2f38c157..fd4f34f087 100644 --- a/__tests__/src/components/ScrollTo.test.js +++ b/__tests__/src/components/ScrollTo.test.js @@ -1,4 +1,4 @@ -import { render, screen } from 'test-utils'; +import { render } from 'test-utils'; import { createRef } from 'react'; import { ScrollTo } from '../../../src/components/ScrollTo'; @@ -12,7 +12,7 @@ describe('ScrollTo', () => { containerRef = createRef(); render(
); - containerRef.current.domEl = { + containerRef.current = { getBoundingClientRect: () => containerBoundingRect, getElementsByClassName: () => [{ scrollTo }], }; @@ -22,12 +22,6 @@ describe('ScrollTo', () => { const scrollToElBelowBoundingRect = { bottom: 601, top: 501 }; const visibleScrollToElBoundingRect = { bottom: 300, top: 200 }; - it('wraps the given children in a div element', () => { - render(Child Prop); - - expect(screen.getByTestId('subject')).toHaveTextContent('Child Prop'); - }); - describe('when updating the scrollTo prop', () => { beforeEach(() => { jest.spyOn(ScrollTo.prototype, 'elementToScrollTo').mockImplementation(() => ({ offsetTop: 450 })); @@ -38,13 +32,13 @@ describe('ScrollTo', () => { ...scrollToElAboveBoundingRect, })); - const { rerender } = render(Child); + const { rerender } = render(
Child
); // It is called once when initially rendered w/ true expect(scrollTo).toHaveBeenCalled(); scrollTo.mockReset(); - rerender(Child); + rerender(
Child
); // But it is not called on the re-render w/ false expect(scrollTo).not.toHaveBeenCalled(); @@ -56,9 +50,9 @@ describe('ScrollTo', () => { jest.spyOn(ScrollTo.prototype, 'scrollToBoundingRect').mockImplementation(() => ({ ...scrollToElAboveBoundingRect, })); - const { rerender } = render(Child); + const { rerender } = render(
Child
); - rerender(Child); + rerender(
Child
); expect(scrollTo).toHaveBeenCalledWith(0, 230); }); @@ -68,9 +62,9 @@ describe('ScrollTo', () => { ...scrollToElBelowBoundingRect, })); - const { rerender } = render(Child); + const { rerender } = render(
Child
); - rerender(Child); + rerender(
Child
); expect(scrollTo).toHaveBeenCalledWith(0, 230); }); @@ -80,9 +74,9 @@ describe('ScrollTo', () => { ...visibleScrollToElBoundingRect, })); - const { rerender } = render(Child); + const { rerender } = render(
Child
); - rerender(Child); + rerender(
Child
); expect(scrollTo).not.toHaveBeenCalled(); }); diff --git a/__tests__/src/components/SearchHit.test.js b/__tests__/src/components/SearchHit.test.js index 3db42a226f..e999a8b1e8 100644 --- a/__tests__/src/components/SearchHit.test.js +++ b/__tests__/src/components/SearchHit.test.js @@ -24,7 +24,6 @@ const Subject = (props) => ( announcer={() => {}} annotation={{ targetId: 'x' }} annotationId="foo" - classes={{ windowSelected: 'windowSelected' }} hit={{ after: ', and start the chainsaw', annotations: ['foo'], @@ -46,7 +45,6 @@ describe('SearchHit', () => { render(); expect(screen.getByRole('listitem')).toHaveClass('Mui-selected'); - expect(screen.getByRole('listitem')).toHaveClass('windowSelected'); expect(screen.getByRole('listitem')).toHaveTextContent('1Light up the moose , and start the chai more'); await user.click(screen.getByRole('button')); @@ -69,14 +67,13 @@ describe('SearchHit', () => { it('renders the annotationLabel if present', () => { render(); - expect(screen.getAllByRole('heading', { level: 6 })).toHaveLength(2); - expect(screen.getByRole('heading', { level: 6, name: 'The Anno Label' })).toHaveClass('MuiTypography-subtitle2'); + expect(screen.getByRole('heading', { level: 4, name: 'The Anno Label' })).toBeInTheDocument(); }); it('does not render the typography if no annotation label is present', () => { render(); - expect(screen.getByRole('heading', { level: 6 })).toBeInTheDocument(); + expect(screen.getByRole('heading', { level: 4 })).toBeInTheDocument(); }); }); diff --git a/__tests__/src/components/SearchPanel.test.js b/__tests__/src/components/SearchPanel.test.js index 8b4fb3a304..cd7b50ee01 100644 --- a/__tests__/src/components/SearchPanel.test.js +++ b/__tests__/src/components/SearchPanel.test.js @@ -54,7 +54,7 @@ describe('SearchPanel', () => { it('has the SearchPanelControls component', () => { createWrapper(); - expect(screen.getByRole('textbox', { name: 'searchInputLabel' })).toBeInTheDocument(); + expect(screen.getByRole('combobox', { name: 'searchInputLabel' })).toBeInTheDocument(); expect(screen.getByRole('button', { name: 'searchSubmitAria' })).toBeInTheDocument(); }); diff --git a/__tests__/src/components/SearchPanelControls.test.js b/__tests__/src/components/SearchPanelControls.test.js index e2ab065c27..0b01891240 100644 --- a/__tests__/src/components/SearchPanelControls.test.js +++ b/__tests__/src/components/SearchPanelControls.test.js @@ -33,7 +33,7 @@ describe('SearchPanelControls', () => { searchService: { id: 'http://example.com/search', options: { resource: { id: 'abc' } } }, }); - await user.click(screen.getByRole('textbox')); + await user.click(screen.getByRole('combobox')); await user.keyboard('somestring'); await user.click(await screen.findByText('somestring 12345')); expect(fetchSearch).toHaveBeenCalledWith('window', 'cw', 'http://example.com/search?q=somestring+12345', 'somestring 12345'); @@ -44,7 +44,7 @@ describe('SearchPanelControls', () => { it('renders a text input through the renderInput prop', () => { createWrapper(); - expect(screen.getByRole('textbox')).toHaveAttribute('id', 'search-cw'); + expect(screen.getByRole('combobox')).toHaveAttribute('id', 'search-cw'); }); it('endAdornment is a SearchIcon (with no CircularProgress indicator)', () => { createWrapper(); @@ -67,7 +67,7 @@ describe('SearchPanelControls', () => { }; createWrapper({ fetchSearch, query: 'asdf', searchService }); - await user.clear(screen.getByRole('textbox')); + await user.clear(screen.getByRole('combobox')); await user.keyboard('yolo'); await user.click(screen.getByRole('button')); @@ -84,7 +84,7 @@ describe('SearchPanelControls', () => { createWrapper({ fetchSearch, query: '', searchService }); - await user.clear(screen.getByRole('textbox')); + await user.clear(screen.getByRole('combobox')); await user.click(screen.getByRole('button', { name: 'searchSubmitAria' })); expect(fetchSearch).not.toHaveBeenCalled(); }); @@ -92,12 +92,12 @@ describe('SearchPanelControls', () => { describe('input', () => { it('has the query prop has the input value on intial render', () => { createWrapper({ query: 'Wolpertinger' }); - expect(screen.getByRole('textbox')).toHaveValue('Wolpertinger'); + expect(screen.getByRole('combobox')).toHaveValue('Wolpertinger'); }); it('clears the local search state/input when the incoming query prop has been cleared', () => { const wrapper = createWrapper({ query: 'Wolpertinger' }); - expect(screen.getByRole('textbox')).toHaveValue('Wolpertinger'); + expect(screen.getByRole('combobox')).toHaveValue('Wolpertinger'); wrapper.rerender(( { /> )); - expect(screen.getByRole('textbox')).toHaveValue(''); + expect(screen.getByRole('combobox')).toHaveValue(''); }); }); }); diff --git a/__tests__/src/components/SearchResults.test.js b/__tests__/src/components/SearchResults.test.js index 14a906cb6b..3579a9789a 100644 --- a/__tests__/src/components/SearchResults.test.js +++ b/__tests__/src/components/SearchResults.test.js @@ -95,8 +95,8 @@ describe('SearchResults', () => { searchHits: [], }); - expect(screen.getByRole('heading', { level: 6, name: 'The Anno Label' })).toBeInTheDocument(); - expect(screen.getByRole('heading', { level: 6, name: 'Annother Anno Label' })).toBeInTheDocument(); + expect(screen.getByRole('heading', { level: 4, name: 'The Anno Label' })).toBeInTheDocument(); + expect(screen.getByRole('heading', { level: 4, name: 'Annother Anno Label' })).toBeInTheDocument(); }); }); diff --git a/__tests__/src/components/ThumbnailCanvasGrouping.test.js b/__tests__/src/components/ThumbnailCanvasGrouping.test.js index 96895ba47f..8bfff1d6d0 100644 --- a/__tests__/src/components/ThumbnailCanvasGrouping.test.js +++ b/__tests__/src/components/ThumbnailCanvasGrouping.test.js @@ -36,12 +36,13 @@ describe('ThumbnailCanvasGrouping', () => { setCanvas = jest.fn(); wrapper = createWrapper({ data, setCanvas }); }); + const spyCurrentCanvasClass = jest.spyOn(ThumbnailCanvasGrouping.prototype, 'currentCanvasClass'); + afterEach(() => { + spyCurrentCanvasClass.mockClear(); + }); it('renders', () => { expect(screen.getByRole('gridcell')).toBeInTheDocument(); }); - it('sets a mirador-current-canvas-grouping class on current canvas', () => { - expect(screen.getByRole('button')).toHaveClass('mirador-current-canvas-grouping'); - }); it('renders a CaptionedIIIFThumbnail', () => { expect(screen.getByText('Image 1')).toBeInTheDocument(); }); @@ -49,9 +50,9 @@ describe('ThumbnailCanvasGrouping', () => { wrapper.unmount(); const user = userEvent.setup(); wrapper = createWrapper({ data, index: 0, setCanvas }); - await user.click(wrapper.container.querySelector('.mirador-thumbnail-nav-canvas-0')); // eslint-disable-line testing-library/no-node-access - + expect(spyCurrentCanvasClass).toHaveBeenCalledWith([0]); + expect(spyCurrentCanvasClass).toHaveReturnedWith('current-canvas-grouping'); expect(setCanvas).toHaveBeenCalledWith('http://iiif.io/api/presentation/2.0/example/fixtures/canvas/24/c1.json'); }); describe('attributes based off far-bottom position', () => { diff --git a/__tests__/src/components/WindowAuthenticationBar.test.js b/__tests__/src/components/WindowAuthenticationBar.test.js index b47771b1d0..c4368b8113 100644 --- a/__tests__/src/components/WindowAuthenticationBar.test.js +++ b/__tests__/src/components/WindowAuthenticationBar.test.js @@ -37,38 +37,36 @@ describe('AuthenticationControl', () => { it('renders a non-collapsing version if there is no description', () => { createWrapper({ description: undefined, header: undefined }); expect(screen.getByText('Log in to see more', { selector: 'span' })).toBeInTheDocument(); - expect(screen.getByText('Login', { selector: 'span' })).toBeInTheDocument(); + expect(screen.getByRole('button')).toHaveTextContent('Login'); }); it('renders a collapsable version if there is a description', async () => { createWrapper({ description: 'long description', header: 'Login to Example Institution' }); const continueBtn = document.querySelectorAll('.MuiButtonBase-root')[0]; - const cancelBtn = screen.getByText('cancel', { selector: 'span' }).closest('button'); - const loginBtn = screen.getByText('Login', { selector: 'span' }); const collapseEl = document.querySelector('.MuiCollapse-hidden'); // disable transition animations for easier testing of the Mui Collapse open/close state config.disabled = true; // initial collapsed state: Presence of continue button text. Hidden cancelBtn, loginBtn, and description expect(screen.getByText('continue')).toBeInTheDocument(); - expect(cancelBtn).not.toBeVisible(); - expect(loginBtn).not.toBeVisible(); + expect(screen.queryByRole('button', { name: 'cancel' })).not.toBeInTheDocument(); + expect(screen.queryByRole('button', { name: 'Login' })).not.toBeInTheDocument(); expect(within(collapseEl).getByText('long description')).not.toBeVisible(); // click to expand await user.click(continueBtn); // expanded state: Removal of continue button text from DOM. Visible cancelBtn, loginBtn, and description expect(screen.queryByText('continue')).not.toBeInTheDocument(); - expect(cancelBtn).toBeVisible(); - expect(loginBtn).toBeVisible(); + expect(screen.getByRole('button', { name: 'cancel' })).toBeVisible(); + expect(screen.getByRole('button', { name: 'Login' })).toBeVisible(); expect(within(collapseEl).getByText('long description')).toBeVisible(); expect(collapseEl).toHaveClass('MuiCollapse-entered'); // click the cancel button to collapse - await user.click(cancelBtn); + await user.click(screen.getByRole('button', { name: 'cancel' })); // collapsed state: Presence of continue button text. Hidden cancelBtn, loginBtn, and description expect(screen.getByText('continue')).toBeInTheDocument(); - expect(cancelBtn).not.toBeVisible(); - expect(loginBtn).not.toBeVisible(); + expect(screen.queryByRole('button', { name: 'cancel' })).not.toBeInTheDocument(); + expect(screen.queryByRole('button', { name: 'Login' })).not.toBeInTheDocument(); expect(within(collapseEl).getByText('long description')).not.toBeVisible(); // re-enable transition animation config.disabled = false; @@ -77,7 +75,7 @@ describe('AuthenticationControl', () => { it('triggers an action when the confirm button is clicked', async () => { const onConfirm = jest.fn(); createWrapper({ onConfirm }); - await user.click(screen.getByText('Login', { selector: 'span' }).closest('button')); + await user.click(screen.getByRole('button', { name: 'Login' })); expect(onConfirm).toHaveBeenCalled(); }); diff --git a/__tests__/src/components/WindowCanvasNavigationControls.test.js b/__tests__/src/components/WindowCanvasNavigationControls.test.js index d089de2915..de08147cc3 100644 --- a/__tests__/src/components/WindowCanvasNavigationControls.test.js +++ b/__tests__/src/components/WindowCanvasNavigationControls.test.js @@ -28,7 +28,7 @@ describe('WindowCanvasNavigationControls', () => { it('renders only a screen-reader accessibile version when visible=false', () => { const { container } = render(); - expect(container.firstChild.classList[1]).toMatch(/srOnly/); // eslint-disable-line testing-library/no-node-access + expect(container.firstChild).toHaveStyle({ height: '1px', margin: '-1px', width: '1px' }); // eslint-disable-line testing-library/no-node-access }); it('stacks the nav controls on small width screens', () => { @@ -37,10 +37,7 @@ describe('WindowCanvasNavigationControls', () => { }); it('shows the zoom control component when specified', () => { - render( - , - { preloadedState: { workspace: { showZoomControls: true } } }, - ); + render(); expect(screen.getByRole('button', { name: 'zoomIn' })).toBeInTheDocument(); expect(screen.getByRole('button', { name: 'zoomOut' })).toBeInTheDocument(); expect(screen.getByRole('button', { name: 'zoomReset' })).toBeInTheDocument(); diff --git a/__tests__/src/components/WindowSideBar.test.js b/__tests__/src/components/WindowSideBar.test.js index 895e20fb35..0fa75243cf 100644 --- a/__tests__/src/components/WindowSideBar.test.js +++ b/__tests__/src/components/WindowSideBar.test.js @@ -5,7 +5,6 @@ import { WindowSideBar } from '../../../src/components/WindowSideBar'; function createWrapper({ ...props }) { return render( k} windowId="xyz" {...props} @@ -26,7 +25,6 @@ function createWrapper({ ...props }) { describe('WindowSideBar when closed', () => { it('renders without an error', () => { createWrapper({}); - expect(document.querySelector('.test-drawer')).toBeInTheDocument(); // eslint-disable-line testing-library/no-node-access expect(screen.queryByRole('navigation', { accessibleName: 'sidebarPanelsNavigation' })).not.toBeInTheDocument(); }); }); diff --git a/__tests__/src/components/WindowSideBarCanvasPanel.test.js b/__tests__/src/components/WindowSideBarCanvasPanel.test.js index 9ad3ce6cca..9c3c48ca0a 100644 --- a/__tests__/src/components/WindowSideBarCanvasPanel.test.js +++ b/__tests__/src/components/WindowSideBarCanvasPanel.test.js @@ -65,7 +65,7 @@ describe('WindowSideBarCanvasPanel', () => { createWrapper({ multipleSequences: true, updateSequence }); expect(screen.getByTestId('sequence-select')).toHaveTextContent('a'); - await user.click(within(screen.getByTestId('sequence-select')).getByRole('button')); + await user.click(within(screen.getByTestId('sequence-select')).getByRole('combobox')); const listbox = within(screen.getByRole('listbox')); expect(listbox.getAllByRole('option')).toHaveLength(2); diff --git a/__tests__/src/components/WindowTopMenuButton.test.js b/__tests__/src/components/WindowTopMenuButton.test.js index 86ef9584d4..15d4b65f42 100644 --- a/__tests__/src/components/WindowTopMenuButton.test.js +++ b/__tests__/src/components/WindowTopMenuButton.test.js @@ -38,9 +38,16 @@ describe('WindowTopMenuButton', () => { expect(screen.queryByRole('menu')).not.toBeInTheDocument(); }); - it('the button has a class indicating that it is "selected" once it is clicked', async () => { + it('the open attribute of the button is null without being clicked', async () => { + render(); + // without a click, the button is not open and therefore doesn't have aria-owns attr + expect(screen.getByLabelText('windowMenu')).not.toHaveAttribute('aria-owns'); // eslint-disable-line testing-library/no-node-access + }); + + it('the open attribute of the button is applied once it is clicked', async () => { render(); await user.click(screen.getByLabelText('windowMenu')); - expect(screen.getByLabelText('windowMenu')).toHaveClass('ctrlBtnSelected'); // eslint-disable-line testing-library/no-node-access + // when 'open' is true, aria-owns is set to the id of the window + expect(screen.getByLabelText('windowMenu')).toHaveAttribute('aria-owns', 'window-menu_xyz'); // eslint-disable-line testing-library/no-node-access }); }); diff --git a/__tests__/src/components/Workspace.test.js b/__tests__/src/components/Workspace.test.js index 3f1fd853e7..493598f751 100644 --- a/__tests__/src/components/Workspace.test.js +++ b/__tests__/src/components/Workspace.test.js @@ -83,22 +83,6 @@ describe('Workspace', () => { }); }); - describe('when the workspace control panel is displayed', () => { - it('has the *-with-control-panel class applied', () => { - const { container } = createWrapper(); - - expect(container.querySelector('.mirador-workspace-with-control-panel')).toBeInTheDocument(); - }); - }); - - describe('when the workspace control panel is not displayed', () => { - it('does not have the *-with-control-panel class applied', () => { - const { container } = createWrapper({ isWorkspaceControlPanelVisible: false }); - - expect(container.querySelector('.mirador-workspace-with-control-panel')).not.toBeInTheDocument(); - }); - }); - describe('drag and drop', () => { it('adds a new catalog entry from a manifest', async () => { const manifestJson = '{ "data": "123" }'; @@ -106,7 +90,7 @@ describe('Workspace', () => { const addWindow = jest.fn(); const { container } = createWrapper({ addWindow }); - const dropTarget = container.querySelector('.mirador-workspace-with-control-panel'); + const dropTarget = container.querySelector('.mirador-workspace-viewport'); const file = new File([manifestJson], 'manifest.json', { type: 'application/json' }); const dataTransfer = { @@ -129,7 +113,7 @@ describe('Workspace', () => { const { container } = createWrapper({ addWindow, allowNewWindows: false }); - const dropTarget = container.querySelector('.mirador-workspace-with-control-panel'); + const dropTarget = container.querySelector('.mirador-workspace-viewport'); const file = new File([manifestJson], 'manifest.json', { type: 'application/json' }); const dataTransfer = { diff --git a/__tests__/src/components/WorkspaceElasticWindow.test.js b/__tests__/src/components/WorkspaceElasticWindow.test.js index 5d8982ea6b..03f565afd1 100644 --- a/__tests__/src/components/WorkspaceElasticWindow.test.js +++ b/__tests__/src/components/WorkspaceElasticWindow.test.js @@ -46,18 +46,13 @@ describe('WorkspaceElasticWindow', () => { expect(el).toHaveStyle({ height: '200px', transform: 'translate(5040px,5040px)', width: '200px' }); }); describe('focuses the window', () => { - it('adds class to focused window', () => { - const { container } = createWrapper({ classes: { focused: 'focused-window' }, focused: true, layout }); - const el = container.firstChild; - - expect(el).toHaveClass('focused-window'); - }); it('calls focusWindow when clicked', async () => { const user = userEvent.setup(); const mockFocusWindow = jest.fn(); const { container } = createWrapper({ focusWindow: mockFocusWindow, layout }); - const el = container.querySelector('.mirador-window-top-bar'); - await user.click(el); + const topBar = container.querySelector('.mirador-window-top-bar'); + await user.click(topBar); + expect(mockFocusWindow).toHaveBeenCalled(); }); }); diff --git a/__tests__/src/components/ZoomControls.test.js b/__tests__/src/components/ZoomControls.test.js index 6f7be5e3ad..41a562513e 100644 --- a/__tests__/src/components/ZoomControls.test.js +++ b/__tests__/src/components/ZoomControls.test.js @@ -6,74 +6,47 @@ import { ZoomControls } from '../../../src/components/ZoomControls'; function createWrapper(props) { return render( {}} {...props} - />, ); } describe('ZoomControls', () => { const viewer = { x: 100, y: 100, zoom: 1 }; - const showZoomControls = false; let updateViewport; - describe('with showZoomControls=false', () => { - it('renders nothing unless asked', () => { - const { container } = createWrapper({ showZoomControls, updateViewport, viewer }); - expect(container).toBeEmptyDOMElement(); + const zoomToWorld = jest.fn(); + let user; + beforeEach(() => { + user = userEvent.setup(); + updateViewport = jest.fn(); + createWrapper({ + updateViewport, viewer, zoomToWorld, }); }); - describe('with showZoomControls=true', () => { - const zoomToWorld = jest.fn(); - let user; - beforeEach(() => { - user = userEvent.setup(); - updateViewport = jest.fn(); - createWrapper({ - showZoomControls: true, updateViewport, viewer, zoomToWorld, - }); - }); - - it('renders a couple buttons', () => { - expect(screen.getByRole('button', { name: 'zoomIn' })).toBeInTheDocument(); - expect(screen.getByRole('button', { name: 'zoomOut' })).toBeInTheDocument(); - expect(screen.getByRole('button', { name: 'zoomReset' })).toBeInTheDocument(); - }); - - it('has a zoom-in button', async () => { - await user.click(screen.getByRole('button', { name: 'zoomIn' })); - - expect(updateViewport).toHaveBeenCalledWith('xyz', { zoom: 2 }); - }); - - it('has a zoom-out button', async () => { - await user.click(screen.getByRole('button', { name: 'zoomOut' })); - expect(updateViewport).toHaveBeenCalledWith('xyz', { zoom: 0.5 }); - }); + it('renders a couple buttons', () => { + expect(screen.getByRole('button', { name: 'zoomIn' })).toBeInTheDocument(); + expect(screen.getByRole('button', { name: 'zoomOut' })).toBeInTheDocument(); + expect(screen.getByRole('button', { name: 'zoomReset' })).toBeInTheDocument(); + }); - it('has a zoom reset button', async () => { - await user.click(screen.getByRole('button', { name: 'zoomReset' })); + it('has a zoom-in button', async () => { + await user.click(screen.getByRole('button', { name: 'zoomIn' })); - expect(zoomToWorld).toHaveBeenCalledWith(false); - }); + expect(updateViewport).toHaveBeenCalledWith('xyz', { zoom: 2 }); }); - /* eslint-disable testing-library/no-container, testing-library/no-node-access */ - describe('responsive divider', () => { - it('is present when the displayDivider prop is true (default)', () => { - const { container } = createWrapper({ showZoomControls: true, viewer }); - - expect(container.querySelector('.divider')).toBeInTheDocument(); - }); + it('has a zoom-out button', async () => { + await user.click(screen.getByRole('button', { name: 'zoomOut' })); + expect(updateViewport).toHaveBeenCalledWith('xyz', { zoom: 0.5 }); + }); - it('is not present when the displayDivider prop is false', () => { - const { container } = createWrapper({ displayDivider: false, showZoomControls: true, viewer }); + it('has a zoom reset button', async () => { + await user.click(screen.getByRole('button', { name: 'zoomReset' })); - expect(container.querySelector('.divider')).not.toBeInTheDocument(); - }); + expect(zoomToWorld).toHaveBeenCalledWith(false); }); }); diff --git a/__tests__/utils/test-utils.js b/__tests__/utils/test-utils.js index 7bc1adf23f..7104dec6b0 100644 --- a/__tests__/utils/test-utils.js +++ b/__tests__/utils/test-utils.js @@ -3,9 +3,12 @@ import { render } from '@testing-library/react'; import PropTypes from 'prop-types'; import { createStore, applyMiddleware } from 'redux'; import thunkMiddleware from 'redux-thunk'; +import { createTheme, ThemeProvider } from '@mui/material/styles'; import createRootReducer from '../../src/state/reducers/rootReducer'; +import settings from '../../src/config/settings'; const rootReducer = createRootReducer(); +const theme = createTheme(settings.theme); /** * Hook up our rendered object to redux @@ -21,7 +24,7 @@ function renderWithProviders( ) { /** :nodoc: */ function Wrapper({ children }) { - return {children}; + return {children}; } Wrapper.propTypes = { diff --git a/jest-puppeteer.config.js b/jest-puppeteer.config.js index b7f3d29270..31bf265ad4 100644 --- a/jest-puppeteer.config.js +++ b/jest-puppeteer.config.js @@ -1,6 +1,6 @@ module.exports = { launch: { - headless: process.env.HEADLESS !== 'false', + headless: process.env.HEADLESS !== 'false' ? 'new' : false, }, server: [{ command: 'npm run server -- -p 4488', diff --git a/jest.json b/jest.json index b5713a9dc7..947d95cd44 100644 --- a/jest.json +++ b/jest.json @@ -33,7 +33,7 @@ "/__tests__/utils" ], "preset": "jest-puppeteer", - "setupFilesAfterEnv": ["@testing-library/jest-dom/extend-expect"], + "setupFilesAfterEnv": ["@testing-library/jest-dom/jest-globals"], "transformIgnorePatterns": [ "/node_modules/(?!@react-dnd|react-dnd|dnd-core|react-dnd-html5-backend|dnd-multi-backend|rdndmb-html5-to-touch)" ], @@ -58,7 +58,7 @@ "preset": "jest-puppeteer", "setupFilesAfterEnv": [ "/setupJestIntegration.js", - "@testing-library/jest-dom/extend-expect" + "@testing-library/jest-dom/jest-globals" ], "transformIgnorePatterns": [ "/node_modules/(?!@react-dnd|react-dnd|dnd-core|react-dnd-html5-backend|dnd-multi-backend|rdndmb-html5-to-touch)" diff --git a/package.json b/package.json index 567470b7f7..d77b1f238a 100644 --- a/package.json +++ b/package.json @@ -33,18 +33,21 @@ ], "repository": "https://github.com/ProjectMirador/mirador", "dependencies": { + "@emotion/cache": "^11.11.0", + "@emotion/react": "^11.10.6", + "@emotion/styled": "^11.10.6", "@hello-pangea/dnd": "^16.0.1", - "@material-ui/core": "^4.12.3", - "@material-ui/icons": "^4.9.1", - "@material-ui/lab": "^4.0.0-alpha.53", + "@mui/icons-material": "^5.11.16", + "@mui/lab": "^5.0.0-alpha.134", + "@mui/material": "^5.13.5", + "@mui/utils": "^5.13.1", + "@mui/x-tree-view": "^6.17.0", "@react-aria/live-announcer": "^3.1.2", + "@redux-devtools/extension": "^3.3.0", "classnames": "^2.2.6", - "clsx": "^1.0.4", "deepmerge": "^4.2.2", "dompurify": "^3.0.0", - "i18next": "^21.0.0 || ^22.0.0", - "jss": "^10.3.0", - "jss-rtl": "^0.3.0", + "i18next": "^21.0.0 || ^22.0.0 || ^23.0.0", "lodash": "^4.17.11", "manifesto.js": "^4.2.0", "normalize-url": "^4.5.0", @@ -58,7 +61,7 @@ "react-dnd-multi-backend": "^8.0.0", "react-dnd-touch-backend": "^16.0.0", "react-full-screen": "^1.1.1", - "react-i18next": "^11.7.0 || ^12.0.0", + "react-i18next": "^11.7.0 || ^12.0.0 || ^13.0.0", "react-image": "^4.0.1", "react-intersection-observer": "^9.0.0", "react-mosaic-component": "^6.0.0", @@ -73,6 +76,8 @@ "redux-saga": "^1.1.3", "redux-thunk": "^2.3.0", "reselect": "^4.0.0", + "stylis": "^4.3.0", + "stylis-plugin-rtl": "^2.1.1", "url": "^0.11.0", "uuid": "^8.1.0 || ^9.0.0" }, @@ -88,7 +93,7 @@ "@babel/preset-react": "^7.16.7", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.4", "@testing-library/dom": "^9.2.0", - "@testing-library/jest-dom": "^5.16.5", + "@testing-library/jest-dom": "^6.1.5", "@testing-library/react": "^12.1.5", "@testing-library/user-event": "^14.4.3", "@typescript-eslint/eslint-plugin": "^5.15.0", @@ -108,19 +113,19 @@ "eslint-plugin-flowtype": "^8.0.3", "eslint-plugin-import": "^2.25.4", "eslint-plugin-jest": "^27.1.5", - "eslint-plugin-jest-dom": "^4.0.3", + "eslint-plugin-jest-dom": "^5.1.0", "eslint-plugin-jsx-a11y": "^6.4.1", "eslint-plugin-react": "^7.29.4", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-testing-library": "^5.10.2", - "glob": "^9.3.0", + "glob": "^10.3.0", "http-server": "^14.1.0", "jest": "^29.3.1", "jest-environment-jsdom": "^29.4.3", "jest-fetch-mock": "^3.0.0", - "jest-puppeteer": "^8.0.0", - "jsdom": "^21.0.0", - "puppeteer": "^19.0.0", + "jest-puppeteer": "^9.0.2", + "jsdom": "^23.0.0", + "puppeteer": "^21.0.0", "react": "^17.0.0", "react-dnd-test-backend": "^16.0.1", "react-dom": "^17.0.0", diff --git a/src/components/AnnotationSettings.js b/src/components/AnnotationSettings.js index dd91bdc754..f6fec27ad7 100644 --- a/src/components/AnnotationSettings.js +++ b/src/components/AnnotationSettings.js @@ -1,7 +1,7 @@ import { Component } from 'react'; import PropTypes from 'prop-types'; -import VisibilityIcon from '@material-ui/icons/VisibilitySharp'; -import VisibilityOffIcon from '@material-ui/icons/VisibilityOffSharp'; +import VisibilityIcon from '@mui/icons-material/VisibilitySharp'; +import VisibilityOffIcon from '@mui/icons-material/VisibilityOffSharp'; import MiradorMenuButton from '../containers/MiradorMenuButton'; /** diff --git a/src/components/AppProviders.js b/src/components/AppProviders.js index e4bcddeac7..f39aae6098 100644 --- a/src/components/AppProviders.js +++ b/src/components/AppProviders.js @@ -3,13 +3,15 @@ import PropTypes from 'prop-types'; import { FullScreen, useFullScreenHandle } from 'react-full-screen'; import { I18nextProvider } from 'react-i18next'; import { - ThemeProvider, StylesProvider, createTheme, jssPreset, createGenerateClassName, -} from '@material-ui/core/styles'; + ThemeProvider, StyledEngineProvider, createTheme, +} from '@mui/material/styles'; import { DndContext, DndProvider } from 'react-dnd'; import { MultiBackend } from 'react-dnd-multi-backend'; import { HTML5toTouch } from 'rdndmb-html5-to-touch'; -import { create } from 'jss'; -import rtl from 'jss-rtl'; +import rtlPlugin from 'stylis-plugin-rtl'; +import { prefixer } from 'stylis'; +import { CacheProvider } from '@emotion/react'; +import createCache from '@emotion/cache'; import createI18nInstance from '../i18n'; import FullScreenContext from '../contexts/FullScreenContext'; @@ -92,12 +94,25 @@ export class AppProviders extends Component { /** */ render() { const { - children, createGenerateClassNameOptions, + children, theme, translations, dndManager, } = this.props; - const generateClassName = createGenerateClassName(createGenerateClassNameOptions); + /** + * Create rtl emotion cache + */ + const cacheRtl = createCache({ + key: 'muirtl', + stylisPlugins: [prefixer, rtlPlugin], + }); + + /** + * Create default emotion cache + */ + const cacheDefault = createCache({ + key: 'mui', + }); Object.keys(translations).forEach((lng) => { this.i18n.addResourceBundle(lng, 'translation', translations[lng], true, true); @@ -106,18 +121,15 @@ export class AppProviders extends Component { return ( - - - - {children} - - - + + + + + {children} + + + + ); @@ -126,7 +138,6 @@ export class AppProviders extends Component { AppProviders.propTypes = { children: PropTypes.node, - createGenerateClassNameOptions: PropTypes.object, // eslint-disable-line react/forbid-prop-types dndManager: PropTypes.object, // eslint-disable-line react/forbid-prop-types language: PropTypes.string.isRequired, theme: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types @@ -135,6 +146,5 @@ AppProviders.propTypes = { AppProviders.defaultProps = { children: null, - createGenerateClassNameOptions: {}, dndManager: undefined, }; diff --git a/src/components/AttributionPanel.js b/src/components/AttributionPanel.js index c2d8cc6979..b1d9c6ebec 100644 --- a/src/components/AttributionPanel.js +++ b/src/components/AttributionPanel.js @@ -1,14 +1,24 @@ import { Component } from 'react'; import PropTypes from 'prop-types'; -import Typography from '@material-ui/core/Typography'; -import Link from '@material-ui/core/Link'; -import Skeleton from '@material-ui/lab/Skeleton'; +import { styled } from '@mui/material/styles'; +import Typography from '@mui/material/Typography'; +import Link from '@mui/material/Link'; +import Skeleton from '@mui/material/Skeleton'; import { Img } from 'react-image'; import CompanionWindow from '../containers/CompanionWindow'; +import { CompanionWindowSection } from './CompanionWindowSection'; import { LabelValueMetadata } from './LabelValueMetadata'; import ns from '../config/css-ns'; import { PluginHook } from './PluginHook'; +const StyledLogo = styled(Img)(() => ({ + maxWidth: '100%', +})); + +const StyledPlaceholder = styled(Skeleton)(({ theme }) => ({ + backgroundColor: theme.palette.grey[300], +})); + /** * WindowSideBarInfoPanel */ @@ -24,7 +34,6 @@ export class AttributionPanel extends Component { rights, windowId, id, - classes, t, } = this.props; @@ -35,7 +44,7 @@ export class AttributionPanel extends Component { windowId={windowId} id={id} > -
+ { requiredStatement && ( )} @@ -53,20 +62,19 @@ export class AttributionPanel extends Component { ) } -
+ { manifestLogo && ( -
- + + } /> -
+ )} @@ -76,7 +84,6 @@ export class AttributionPanel extends Component { } AttributionPanel.propTypes = { - classes: PropTypes.objectOf(PropTypes.string), id: PropTypes.string.isRequired, manifestLogo: PropTypes.string, requiredStatement: PropTypes.arrayOf(PropTypes.shape({ @@ -89,7 +96,6 @@ AttributionPanel.propTypes = { }; AttributionPanel.defaultProps = { - classes: {}, manifestLogo: null, requiredStatement: null, rights: null, diff --git a/src/components/AudioViewer.js b/src/components/AudioViewer.js index ab7b9d6883..9ceb07d788 100644 --- a/src/components/AudioViewer.js +++ b/src/components/AudioViewer.js @@ -1,40 +1,48 @@ -import { Component, Fragment } from 'react'; +import { Fragment } from 'react'; import PropTypes from 'prop-types'; +import { styled } from '@mui/material/styles'; + +const StyledContainer = styled('div')({ + alignItems: 'center', + display: 'flex', + width: '100%', +}); + +const StyledAudio = styled('audio')({ + width: '100%', +}); /** */ -export class AudioViewer extends Component { +export function AudioViewer(props) { /* eslint-disable jsx-a11y/media-has-caption */ /** */ - render() { - const { - captions, classes, audioOptions, audioResources, - } = this.props; + const { + captions, audioOptions, audioResources, + } = props; - return ( -
- -
- ); - } - /* eslint-enable jsx-a11y/media-has-caption */ + return ( + + + {audioResources.map((audio) => ( + + + + ))} + {captions.map((caption) => ( + + + + ))} + + + ); } +/* eslint-enable jsx-a11y/media-has-caption */ AudioViewer.propTypes = { audioOptions: PropTypes.object, // eslint-disable-line react/forbid-prop-types audioResources: PropTypes.arrayOf(PropTypes.object), // eslint-disable-line react/forbid-prop-types captions: PropTypes.arrayOf(PropTypes.object), // eslint-disable-line react/forbid-prop-types - classes: PropTypes.objectOf(PropTypes.string).isRequired, }; AudioViewer.defaultProps = { diff --git a/src/components/Branding.js b/src/components/Branding.js index d2f4d4f9e1..9b3af649cc 100644 --- a/src/components/Branding.js +++ b/src/components/Branding.js @@ -1,7 +1,8 @@ import { Component } from 'react'; import PropTypes from 'prop-types'; -import IconButton from '@material-ui/core/IconButton'; -import Typography from '@material-ui/core/Typography'; +import IconButton from '@mui/material/IconButton'; +import Typography from '@mui/material/Typography'; +import Stack from '@mui/material/Stack'; import MiradorIcon from './icons/MiradorIcon'; /** @@ -13,7 +14,7 @@ export class Branding extends Component { const { t, variant, ...ContainerProps } = this.props; return ( -
+ { variant === 'wide' && (
{t('mirador')} @@ -25,11 +26,12 @@ export class Branding extends Component { href="https://projectmirador.org" target="_blank" rel="noopener" + size="large" > -
+
); } } diff --git a/src/components/CanvasAnnotations.js b/src/components/CanvasAnnotations.js index 544e135d78..8b4993c3e2 100644 --- a/src/components/CanvasAnnotations.js +++ b/src/components/CanvasAnnotations.js @@ -1,11 +1,10 @@ import { Component } from 'react'; import PropTypes from 'prop-types'; -import clsx from 'clsx'; -import Chip from '@material-ui/core/Chip'; -import MenuList from '@material-ui/core/MenuList'; -import MenuItem from '@material-ui/core/MenuItem'; -import ListItemText from '@material-ui/core/ListItemText'; -import Typography from '@material-ui/core/Typography'; +import Chip from '@mui/material/Chip'; +import MenuList from '@mui/material/MenuList'; +import MenuItem from '@mui/material/MenuItem'; +import ListItemText from '@mui/material/ListItemText'; +import Typography from '@mui/material/Typography'; import SanitizedHtml from '../containers/SanitizedHtml'; import { ScrollTo } from './ScrollTo'; @@ -58,7 +57,7 @@ export class CanvasAnnotations extends Component { */ render() { const { - annotations, classes, index, label, selectedAnnotationId, t, totalSize, + annotations, index, label, selectedAnnotationId, t, totalSize, listContainerComponent, htmlSanitizationRuleSet, hoveredAnnotationIds, containerRef, } = this.props; @@ -66,53 +65,50 @@ export class CanvasAnnotations extends Component { return ( <> - + {t('annotationCanvasLabel', { context: `${index + 1}/${totalSize}`, label })} - { - annotations.map(annotation => ( + {annotations.map((annotation) => ( + this.handleClick(e, annotation)} + onClick={(e) => this.handleClick(e, annotation)} onFocus={() => this.handleAnnotationHover(annotation)} onBlur={this.handleAnnotationBlur} onMouseEnter={() => this.handleAnnotationHover(annotation)} onMouseLeave={this.handleAnnotationBlur} > - - - -
- { - annotation.tags.map(tag => ( - - )) - } -
-
-
+ + } + secondary={ + annotation.tags.map((tag) => ( + + )) + } + />
- )) - } +
+ ))}
); @@ -126,7 +122,6 @@ CanvasAnnotations.propTypes = { id: PropTypes.string.isRequired, }), ), - classes: PropTypes.objectOf(PropTypes.string), containerRef: PropTypes.oneOfType([ PropTypes.func, PropTypes.shape({ current: PropTypes.instanceOf(Element) }), @@ -146,7 +141,6 @@ CanvasAnnotations.propTypes = { }; CanvasAnnotations.defaultProps = { annotations: [], - classes: {}, containerRef: undefined, hoveredAnnotationIds: [], htmlSanitizationRuleSet: 'iiif', diff --git a/src/components/CanvasInfo.js b/src/components/CanvasInfo.js index 93f4b31243..39ec1a03fd 100644 --- a/src/components/CanvasInfo.js +++ b/src/components/CanvasInfo.js @@ -1,6 +1,6 @@ import { Component } from 'react'; import PropTypes from 'prop-types'; -import Typography from '@material-ui/core/Typography'; +import Typography from '@mui/material/Typography'; import CollapsibleSection from '../containers/CollapsibleSection'; import SanitizedHtml from '../containers/SanitizedHtml'; import { LabelValueMetadata } from './LabelValueMetadata'; diff --git a/src/components/CanvasLayers.js b/src/components/CanvasLayers.js index 99e400ca25..87f7849004 100644 --- a/src/components/CanvasLayers.js +++ b/src/components/CanvasLayers.js @@ -1,23 +1,36 @@ import { Component } from 'react'; import PropTypes from 'prop-types'; -import clsx from 'clsx'; +import { styled } from '@mui/material/styles'; import { v4 as uuid } from 'uuid'; -import Input from '@material-ui/core/Input'; -import InputAdornment from '@material-ui/core/InputAdornment'; -import List from '@material-ui/core/List'; -import ListItem from '@material-ui/core/ListItem'; -import Slider from '@material-ui/core/Slider'; -import Tooltip from '@material-ui/core/Tooltip'; -import DragHandleIcon from '@material-ui/icons/DragHandleSharp'; -import MoveToTopIcon from '@material-ui/icons/VerticalAlignTopSharp'; -import VisibilityIcon from '@material-ui/icons/VisibilitySharp'; -import VisibilityOffIcon from '@material-ui/icons/VisibilityOffSharp'; -import OpacityIcon from '@material-ui/icons/OpacitySharp'; -import Typography from '@material-ui/core/Typography'; +import Input from '@mui/material/Input'; +import InputAdornment from '@mui/material/InputAdornment'; +import List from '@mui/material/List'; +import ListItem from '@mui/material/ListItem'; +import Slider from '@mui/material/Slider'; +import Tooltip from '@mui/material/Tooltip'; +import DragHandleIcon from '@mui/icons-material/DragHandleSharp'; +import MoveToTopIcon from '@mui/icons-material/VerticalAlignTopSharp'; +import VisibilityIcon from '@mui/icons-material/VisibilitySharp'; +import VisibilityOffIcon from '@mui/icons-material/VisibilityOffSharp'; +import OpacityIcon from '@mui/icons-material/OpacitySharp'; +import Typography from '@mui/material/Typography'; import { DragDropContext, Droppable, Draggable } from '@hello-pangea/dnd'; import MiradorMenuButton from '../containers/MiradorMenuButton'; import IIIFThumbnail from '../containers/IIIFThumbnail'; +const StyledDragHandle = styled('div')(({ theme }) => ({ + alignItems: 'center', + borderRight: `0.5px solid ${theme.palette.divider}`, + display: 'flex', + flex: 1, + flexDirection: 'row', + marginBottom: theme.spacing(-2), + marginRight: theme.spacing(1), + marginTop: theme.spacing(-2), + maxWidth: theme.spacing(3), + width: theme.spacing(3), +})); + /** */ const reorder = (list, startIndex, endIndex) => { const result = Array.from(list); @@ -116,7 +129,6 @@ export class CanvasLayers extends Component { /** @private */ renderLayer(resource, index) { const { - classes, layerMetadata, t, } = this.props; @@ -136,10 +148,12 @@ export class CanvasLayers extends Component { maxHeight={height} maxWidth={width} resource={resource} - classes={{ image: classes.image, root: classes.thumbnail }} + border /> @@ -158,10 +172,21 @@ export class CanvasLayers extends Component {
- + this.handleOpacityChange(resource.id, value)} @@ -187,7 +216,6 @@ export class CanvasLayers extends Component { /** @private */ renderDraggableLayer(resource, index) { const { - classes, t, } = this.props; @@ -198,20 +226,33 @@ export class CanvasLayers extends Component { ref={provided.innerRef} {...provided.draggableProps} component="li" - className={clsx( - classes.listItem, - { - [classes.dragging]: snapshot.isDragging, - }, - )} + divider + sx={{ + alignItems: 'stretch', + cursor: 'pointer', + paddingBottom: 2, + paddingRight: 2, + paddingTop: 2, + ...(snapshot.isDragging && { + backgroundColor: 'action.hover', + }), + }} disableGutters key={resource.id} > -
+ -
+ {this.renderLayer(resource, index)} )} @@ -222,7 +263,6 @@ export class CanvasLayers extends Component { /** */ render() { const { - classes, index, label, layers, @@ -233,7 +273,14 @@ export class CanvasLayers extends Component { return ( <> { totalSize > 1 && ( - + {t('annotationCanvasLabel', { context: `${index + 1}/${totalSize}`, label })} )} @@ -241,7 +288,9 @@ export class CanvasLayers extends Component { {(provided, snapshot) => ( @@ -262,7 +311,6 @@ export class CanvasLayers extends Component { CanvasLayers.propTypes = { canvasId: PropTypes.string.isRequired, - classes: PropTypes.objectOf(PropTypes.string), index: PropTypes.number.isRequired, label: PropTypes.string.isRequired, layerMetadata: PropTypes.objectOf(PropTypes.shape({ @@ -277,6 +325,5 @@ CanvasLayers.propTypes = { }; CanvasLayers.defaultProps = { - classes: {}, layerMetadata: undefined, }; diff --git a/src/components/ChangeThemeDialog.js b/src/components/ChangeThemeDialog.js index 146071b855..17bd83171a 100644 --- a/src/components/ChangeThemeDialog.js +++ b/src/components/ChangeThemeDialog.js @@ -1,16 +1,20 @@ import { Component } from 'react'; import { - Dialog, DialogTitle, ListItemIcon, ListItemText, MenuList, MenuItem, - Typography, DialogContent, -} from '@material-ui/core'; -import PaletteIcon from '@material-ui/icons/PaletteSharp'; +} from '@mui/material'; +import PaletteIcon from '@mui/icons-material/PaletteSharp'; import PropTypes from 'prop-types'; +import { styled } from '@mui/material/styles'; +import { WorkspaceDialog } from './WorkspaceDialog'; + +const ThemeIcon = styled(PaletteIcon, { name: 'ThemeIcon', slot: 'icon' })(({ theme }) => ({ + color: '#BDBDBD', +})); /** * a simple dialog providing the possibility to switch the theme @@ -36,7 +40,6 @@ export class ChangeThemeDialog extends Component { /** */ render() { const { - classes, handleClose, open, selectedTheme, @@ -44,42 +47,34 @@ export class ChangeThemeDialog extends Component { themeIds, } = this.props; return ( - - - - {t('changeTheme')} - + + + {t('changeTheme')} - + - { - themeIds.map(value => ( - { this.handleThemeChange(value); }} - selected={value === selectedTheme} - value={value} - > - - - - {t(value)} - - )) - } + {themeIds.map((value) => ( + this.handleThemeChange(value)} + selected={value === selectedTheme} + value={value} + > + + + + {t(value)} + + ))} - + ); } } ChangeThemeDialog.propTypes = { - classes: PropTypes.objectOf(PropTypes.string).isRequired, handleClose: PropTypes.func.isRequired, open: PropTypes.bool, selectedTheme: PropTypes.string.isRequired, diff --git a/src/components/CollapsibleSection.js b/src/components/CollapsibleSection.js index 8773c9b6d9..04c5f7d513 100644 --- a/src/components/CollapsibleSection.js +++ b/src/components/CollapsibleSection.js @@ -1,9 +1,10 @@ import { Component } from 'react'; import PropTypes from 'prop-types'; -import Typography from '@material-ui/core/Typography'; -import KeyboardArrowDown from '@material-ui/icons/KeyboardArrowDownSharp'; -import KeyboardArrowUp from '@material-ui/icons/KeyboardArrowUpSharp'; -import MiradorMenuButton from '../containers/MiradorMenuButton'; +import Typography from '@mui/material/Typography'; +import Accordion from '@mui/material/Accordion'; +import AccordionDetails from '@mui/material/AccordionDetails'; +import AccordionSummary from '@mui/material/AccordionSummary'; +import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; /** * CollapsableSection ~ @@ -14,14 +15,12 @@ export class CollapsibleSection extends Component { super(props); this.state = { open: true }; - this.toggleSection = this.toggleSection.bind(this); + this.handleChange = this.handleChange.bind(this); } - /** */ - toggleSection() { - const { open } = this.state; - - this.setState({ open: !open }); + /** Control the accordion state so we can provide aria labeling */ + handleChange(event, isExpanded) { + this.setState({ open: isExpanded }); } /** @@ -29,45 +28,28 @@ export class CollapsibleSection extends Component { */ render() { const { - children, classes, id, label, t, + children, id, label, t, } = this.props; const { open } = this.state; return ( - <> -
- + + }> + {label} - - {open ? : } - -
- {open && children} - + + + {children} + + ); } } CollapsibleSection.propTypes = { children: PropTypes.node.isRequired, - classes: PropTypes.objectOf(PropTypes.string).isRequired, + id: PropTypes.string.isRequired, label: PropTypes.string.isRequired, t: PropTypes.func.isRequired, diff --git a/src/components/CollectionDialog.js b/src/components/CollectionDialog.js index 3dc335ba9b..75fa641f14 100644 --- a/src/components/CollectionDialog.js +++ b/src/components/CollectionDialog.js @@ -10,15 +10,32 @@ import { MenuList, MenuItem, Typography, -} from '@material-ui/core'; -import ArrowBackIcon from '@material-ui/icons/ArrowBackSharp'; -import Skeleton from '@material-ui/lab/Skeleton'; +} from '@mui/material'; +import ArrowBackIcon from '@mui/icons-material/ArrowBackSharp'; +import Skeleton from '@mui/material/Skeleton'; +import { styled } from '@mui/material/styles'; import asArray from '../lib/asArray'; import { LabelValueMetadata } from './LabelValueMetadata'; import CollapsibleSection from '../containers/CollapsibleSection'; import ScrollIndicatedDialogContent from '../containers/ScrollIndicatedDialogContent'; import ManifestInfo from '../containers/ManifestInfo'; +const StyledScrollIndicatedDialogContent = styled(ScrollIndicatedDialogContent)(() => ({ + padding: (theme) => theme.spacing(1), +})); + +const StyledCollectionMetadata = styled('div')(() => ({ + '& .MuiPaper-root': { + background: 'transparent', + }, + padding: (theme) => theme.spacing(2), +})); + +const StyledCollectionFilter = styled('div')(() => ({ + padding: (theme) => theme.spacing(2), + paddingTop: 0, +})); + /** * a dialog providing the possibility to select the collection */ @@ -108,37 +125,27 @@ export class CollectionDialog extends Component { /** */ placeholder() { - const { classes } = this.props; - return ( - - + + - - + + ); } - /** */ - backdropProps() { - const { classes } = this.props; - return { classes: { root: classes.dialog } }; - } - /** */ render() { const { - classes, collection, error, isMultipart, @@ -173,21 +180,20 @@ export class CollectionDialog extends Component { return ( - + { t(isMultipart ? 'multipartCollection' : 'collection') } - + {CollectionDialog.getUseableLabel(manifest)} - + { collection && ( )} -
+ -
-
+ + {manifest.getTotalCollections() > 0 && ( this.setFilter('collections')} label={t('totalCollections', { count: manifest.getTotalCollections() })} /> )} {manifest.getTotalManifests() > 0 && ( this.setFilter('manifests')} label={t('totalManifests', { count: manifest.getTotalManifests() })} /> )} -
+ { currentFilter === 'collections' && ( { @@ -237,7 +243,7 @@ export class CollectionDialog extends Component { { this.selectCollection(c); }} - className={classes.collectionItem} + variant="multiline" > {CollectionDialog.getUseableLabel(c)} @@ -252,7 +258,7 @@ export class CollectionDialog extends Component { { this.selectManifest(m); }} - className={classes.collectionItem} + variant="multiline" > {CollectionDialog.getUseableLabel(m)} @@ -260,7 +266,7 @@ export class CollectionDialog extends Component { } )} -
+
+ ); } } IIIFThumbnail.propTypes = { + border: PropTypes.bool, children: PropTypes.node, - classes: PropTypes.objectOf(PropTypes.string), imagePlaceholder: PropTypes.string, label: PropTypes.string, labelled: PropTypes.bool, @@ -197,12 +212,12 @@ IIIFThumbnail.propTypes = { width: PropTypes.number, }), thumbnailsConfig: PropTypes.object, // eslint-disable-line react/forbid-prop-types - variant: PropTypes.oneOf(['inside', 'outside']), + variant: PropTypes.oneOf(['inside', 'outside']), // eslint-disable-line react/no-unused-prop-types }; IIIFThumbnail.defaultProps = { + border: false, children: null, - classes: {}, // Transparent "gray" imagePlaceholder: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mMMDQmtBwADgwF/Op8FmAAAAABJRU5ErkJggg==', label: undefined, diff --git a/src/components/LabelValueMetadata.js b/src/components/LabelValueMetadata.js index 9cb73df271..b1fe6c9a29 100644 --- a/src/components/LabelValueMetadata.js +++ b/src/components/LabelValueMetadata.js @@ -1,6 +1,6 @@ import { Component } from 'react'; import PropTypes from 'prop-types'; -import Typography from '@material-ui/core/Typography'; +import Typography from '@mui/material/Typography'; import SanitizedHtml from '../containers/SanitizedHtml'; import ns from '../config/css-ns'; diff --git a/src/components/LanguageSettings.js b/src/components/LanguageSettings.js index 7901c4e440..f0048c4788 100644 --- a/src/components/LanguageSettings.js +++ b/src/components/LanguageSettings.js @@ -1,8 +1,8 @@ import { Component } from 'react'; -import ListItemIcon from '@material-ui/core/ListItemIcon'; -import ListItemText from '@material-ui/core/ListItemText'; -import MenuItem from '@material-ui/core/MenuItem'; -import CheckIcon from '@material-ui/icons/CheckSharp'; +import ListItemIcon from '@mui/material/ListItemIcon'; +import ListItemText from '@mui/material/ListItemText'; +import MenuItem from '@mui/material/MenuItem'; +import CheckIcon from '@mui/icons-material/CheckSharp'; import PropTypes from 'prop-types'; /** @@ -23,7 +23,6 @@ export class LanguageSettings extends Component { { languages.map(language => ( { handleClick(language.locale); }} > diff --git a/src/components/LocalePicker.js b/src/components/LocalePicker.js index beb212324e..a1f9d8593d 100644 --- a/src/components/LocalePicker.js +++ b/src/components/LocalePicker.js @@ -1,9 +1,9 @@ import { Component } from 'react'; import PropTypes from 'prop-types'; -import MenuItem from '@material-ui/core/MenuItem'; -import FormControl from '@material-ui/core/FormControl'; -import Select from '@material-ui/core/Select'; -import Typography from '@material-ui/core/Typography'; +import MenuItem from '@mui/material/MenuItem'; +import FormControl from '@mui/material/FormControl'; +import Select from '@mui/material/Select'; +import Typography from '@mui/material/Typography'; /** * Provide a locale picker @@ -16,7 +16,6 @@ export class LocalePicker extends Component { render() { const { availableLocales, - classes, locale, setLocale, } = this.props; @@ -30,14 +29,11 @@ export class LocalePicker extends Component { horizontal: 'left', vertical: 'bottom', }, - getContentAnchorEl: null, }} displayEmpty value={locale} onChange={(e) => { setLocale(e.target.value); }} name="locale" - classes={{ select: classes.select }} - className={classes.selectEmpty} > { availableLocales.map(l => ( @@ -52,14 +48,12 @@ export class LocalePicker extends Component { LocalePicker.propTypes = { availableLocales: PropTypes.arrayOf(PropTypes.string), - classes: PropTypes.objectOf(PropTypes.string), locale: PropTypes.string, setLocale: PropTypes.func, }; LocalePicker.defaultProps = { availableLocales: [], - classes: {}, locale: '', setLocale: undefined, }; diff --git a/src/components/ManifestForm.js b/src/components/ManifestForm.js index 18d304cd6d..2266db77c9 100644 --- a/src/components/ManifestForm.js +++ b/src/components/ManifestForm.js @@ -1,8 +1,8 @@ import { Component } from 'react'; import PropTypes from 'prop-types'; -import Button from '@material-ui/core/Button'; -import Grid from '@material-ui/core/Grid'; -import TextField from '@material-ui/core/TextField'; +import Button from '@mui/material/Button'; +import Grid from '@mui/material/Grid'; +import TextField from '@mui/material/TextField'; /** * Provides a form for user input of a manifest url @@ -68,7 +68,6 @@ export class ManifestForm extends Component { const { formValue } = this.state; const { addResourcesOpen, - classes, onCancel, t, } = this.props; @@ -92,11 +91,19 @@ export class ManifestForm extends Component { shrink: true, }} InputProps={{ - className: classes.input, + style: { typography: 'body1' }, }} /> - + { onCancel && ( + {hit && ( + <> + + {' '} + + + + {' '} + + {' '} + {truncated && !focused && ( + + )} + )} + {!hit && annotation && } )} - {!hit && annotation && } - - + /> + ); } @@ -162,7 +219,6 @@ SearchHit.propTypes = { annotationLabel: PropTypes.string, announcer: PropTypes.func, canvasLabel: PropTypes.string, - classes: PropTypes.objectOf(PropTypes.string), companionWindowId: PropTypes.string, containerRef: PropTypes.oneOfType([ PropTypes.func, @@ -191,7 +247,6 @@ SearchHit.defaultProps = { annotationLabel: undefined, announcer: undefined, canvasLabel: undefined, - classes: {}, companionWindowId: undefined, containerRef: undefined, focused: false, diff --git a/src/components/SearchPanel.js b/src/components/SearchPanel.js index 6806376464..42550dddf3 100644 --- a/src/components/SearchPanel.js +++ b/src/components/SearchPanel.js @@ -1,8 +1,8 @@ import { createRef, Component } from 'react'; import PropTypes from 'prop-types'; -import Button from '@material-ui/core/Button'; -import Chip from '@material-ui/core/Chip'; -import Typography from '@material-ui/core/Typography'; +import Button from '@mui/material/Button'; +import Chip from '@mui/material/Chip'; +import Typography from '@mui/material/Typography'; import CompanionWindow from '../containers/CompanionWindow'; import SearchPanelControls from '../containers/SearchPanelControls'; import SearchResults from '../containers/SearchResults'; @@ -19,7 +19,6 @@ export class SearchPanel extends Component { /** */ render() { const { - classes, fetchSearch, windowId, id, @@ -40,7 +39,7 @@ export class SearchPanel extends Component { query && query !== '' && ( { fetchSearch && suggestedSearches && query === '' && suggestedSearches.map(search => ( - - @@ -78,10 +81,6 @@ export class SearchPanel extends Component { } SearchPanel.propTypes = { - classes: PropTypes.shape({ - clearChip: PropTypes.string, - inlineButton: PropTypes.string, - }), fetchSearch: PropTypes.func, id: PropTypes.string.isRequired, query: PropTypes.string, @@ -95,7 +94,6 @@ SearchPanel.propTypes = { }; SearchPanel.defaultProps = { - classes: {}, fetchSearch: undefined, query: '', suggestedSearches: [], diff --git a/src/components/SearchPanelControls.js b/src/components/SearchPanelControls.js index f16939757a..0ebdc7185a 100644 --- a/src/components/SearchPanelControls.js +++ b/src/components/SearchPanelControls.js @@ -1,15 +1,23 @@ import { Component } from 'react'; import PropTypes from 'prop-types'; +import { styled } from '@mui/material/styles'; import deburr from 'lodash/deburr'; import debounce from 'lodash/debounce'; import isObject from 'lodash/isObject'; -import Autocomplete from '@material-ui/lab/Autocomplete'; -import CircularProgress from '@material-ui/core/CircularProgress'; -import TextField from '@material-ui/core/TextField'; -import SearchIcon from '@material-ui/icons/SearchSharp'; +import Autocomplete from '@mui/material/Autocomplete'; +import CircularProgress from '@mui/material/CircularProgress'; +import TextField from '@mui/material/TextField'; +import InputAdornment from '@mui/material/InputAdornment'; +import SearchIcon from '@mui/icons-material/SearchSharp'; import MiradorMenuButton from '../containers/MiradorMenuButton'; import SearchPanelNavigation from '../containers/SearchPanelNavigation'; +const StyledForm = styled('form', { name: 'SearchPanelControls', slot: 'form' })(({ theme }) => ({ + paddingBottom: theme.spacing(1), + paddingRight: theme.spacing(1.5), + width: '100%', +})); + /** Sometimes an autocomplete match can be a simple string, other times an object with a `match` property, this function abstracts that away */ const getMatch = (option) => (isObject(option) ? option.match : option); @@ -117,48 +125,62 @@ export class SearchPanelControls extends Component { /** */ render() { const { - classes, companionWindowId, searchIsFetching, t, windowId, + companionWindowId, searchIsFetching, t, windowId, } = this.props; const { search, suggestions } = this.state; const id = `search-${companionWindowId}`; return ( <> -
+ ( + isOptionEqualToValue={(option, value) => ( deburr(getMatch(option).trim()).toLowerCase() - === deburr(getMatch(value).trim()).toLowerCase() + === deburr(getMatch(value).trim()).toLowerCase() )} noOptionsText="" onChange={this.selectItem} onInputChange={this.handleChange} freeSolo + disableClearable renderInput={params => ( + {Boolean(searchIsFetching) && ( - + )} -
+ ), }} /> )} /> - + ); @@ -169,7 +191,6 @@ SearchPanelControls.propTypes = { autocompleteService: PropTypes.shape({ id: PropTypes.string, }), - classes: PropTypes.objectOf(PropTypes.string), companionWindowId: PropTypes.string.isRequired, fetchSearch: PropTypes.func.isRequired, query: PropTypes.string, @@ -183,7 +204,6 @@ SearchPanelControls.propTypes = { SearchPanelControls.defaultProps = { autocompleteService: undefined, - classes: {}, query: '', t: key => key, }; diff --git a/src/components/SearchPanelNavigation.js b/src/components/SearchPanelNavigation.js index 72eb84e1fe..3ddf2c49b5 100644 --- a/src/components/SearchPanelNavigation.js +++ b/src/components/SearchPanelNavigation.js @@ -1,8 +1,8 @@ import { Component } from 'react'; import PropTypes from 'prop-types'; -import ChevronLeftIcon from '@material-ui/icons/ChevronLeftSharp'; -import ChevronRightIcon from '@material-ui/icons/ChevronRightSharp'; -import Typography from '@material-ui/core/Typography'; +import ChevronLeftIcon from '@mui/icons-material/ChevronLeftSharp'; +import ChevronRightIcon from '@mui/icons-material/ChevronRightSharp'; +import Typography from '@mui/material/Typography'; import MiradorMenuButton from '../containers/MiradorMenuButton'; /** @@ -42,7 +42,7 @@ export class SearchPanelNavigation extends Component { */ render() { const { - numTotal, searchHits, selectedContentSearchAnnotation, classes, t, direction, + numTotal, searchHits, selectedContentSearchAnnotation, t, direction, } = this.props; const iconStyle = direction === 'rtl' ? { transform: 'rotate(180deg)' } : {}; @@ -57,7 +57,7 @@ export class SearchPanelNavigation extends Component { if (searchHits.length === 0) return null; return ( - + key, diff --git a/src/components/SearchResults.js b/src/components/SearchResults.js index c38e5c082a..15263db3ba 100644 --- a/src/components/SearchResults.js +++ b/src/components/SearchResults.js @@ -1,9 +1,9 @@ import { Component } from 'react'; import PropTypes from 'prop-types'; -import Button from '@material-ui/core/Button'; -import List from '@material-ui/core/List'; -import Typography from '@material-ui/core/Typography'; -import BackIcon from '@material-ui/icons/ArrowBackSharp'; +import Button from '@mui/material/Button'; +import List from '@mui/material/List'; +import Typography from '@mui/material/Typography'; +import BackIcon from '@mui/icons-material/ArrowBackSharp'; import { announce } from '@react-aria/live-announcer'; import SearchHit from '../containers/SearchHit'; import { ScrollTo } from './ScrollTo'; @@ -80,7 +80,6 @@ export class SearchResults extends Component { /** */ render() { const { - classes, companionWindowId, containerRef, isFetching, @@ -106,14 +105,18 @@ export class SearchResults extends Component { <> { focused && ( - )} {noResultsState && ( - + {t('searchNoResults')} )} @@ -122,7 +125,7 @@ export class SearchResults extends Component { { nextSearch && ( ); if (!description && !header) { return ( - -
- { icon || } - + + + { icon || ( + + ) } + { ruleSet ? : label } { button } -
+
); } return ( - - ({ + backgroundColor: theme.palette.secondary.main, + color: theme.palette.secondary.contrastText, + paddingInlineEnd: theme.spacing(1), + paddingInlineStart: theme.spacing(1), + })} in={open} onClose={() => this.setOpen(false)} > - + { ruleSet ? : header } { header && description ? ': ' : '' } { ruleSet ? : description } @@ -104,7 +159,6 @@ export class WindowAuthenticationBar extends Component { } WindowAuthenticationBar.propTypes = { - classes: PropTypes.objectOf(PropTypes.string).isRequired, confirmButton: PropTypes.string, ConfirmProps: PropTypes.object, // eslint-disable-line react/forbid-prop-types continueLabel: PropTypes.string, diff --git a/src/components/WindowCanvasNavigationControls.js b/src/components/WindowCanvasNavigationControls.js index eaee4dc152..df9e3ae737 100644 --- a/src/components/WindowCanvasNavigationControls.js +++ b/src/components/WindowCanvasNavigationControls.js @@ -1,14 +1,33 @@ import { Component } from 'react'; import PropTypes from 'prop-types'; +import { alpha, styled } from '@mui/material/styles'; import classNames from 'classnames'; -import Paper from '@material-ui/core/Paper'; -import Typography from '@material-ui/core/Typography'; +import Paper from '@mui/material/Paper'; +import Stack from '@mui/material/Stack'; +import Divider from '@mui/material/Divider'; +import Typography from '@mui/material/Typography'; +import { visuallyHidden } from '@mui/utils'; import ZoomControls from '../containers/ZoomControls'; import ViewerInfo from '../containers/ViewerInfo'; import ViewerNavigation from '../containers/ViewerNavigation'; import ns from '../config/css-ns'; import { PluginHook } from './PluginHook'; +const Root = styled(Paper, { name: 'WindowCanvasNavigationControls', slot: 'root' })(({ theme }) => ({ + alignItems: 'center', + backgroundColor: alpha(theme.palette.background.paper, 0.5), + bottom: 0, + cursor: 'default', + display: 'flex', + flexDirection: 'column', + flexWrap: 'wrap', + justifyContent: 'center', + position: 'absolute', + textAlign: 'center', + width: '100%', + zIndex: 50, +})); + /** * Represents the viewer controls in the mirador workspace. */ @@ -25,41 +44,40 @@ export class WindowCanvasNavigationControls extends Component { /** */ render() { const { - classes, visible, windowId, zoomToWorld, + showZoomControls, visible, windowId, zoomToWorld, } = this.props; - if (!visible) return (); + if (!visible) return (); return ( - - - + } + spacing={0} + > + { showZoomControls && } + + - + ); } } WindowCanvasNavigationControls.propTypes = { - classes: PropTypes.objectOf(PropTypes.string), + showZoomControls: PropTypes.bool, size: PropTypes.shape({ width: PropTypes.number }).isRequired, visible: PropTypes.bool, windowId: PropTypes.string.isRequired, @@ -67,6 +85,6 @@ WindowCanvasNavigationControls.propTypes = { }; WindowCanvasNavigationControls.defaultProps = { - classes: {}, + showZoomControls: false, visible: true, }; diff --git a/src/components/WindowList.js b/src/components/WindowList.js index 8ed83f402c..2db96ba42b 100644 --- a/src/components/WindowList.js +++ b/src/components/WindowList.js @@ -1,8 +1,8 @@ import { Component } from 'react'; -import Menu from '@material-ui/core/Menu'; -import MenuItem from '@material-ui/core/MenuItem'; -import ListItemText from '@material-ui/core/ListItemText'; -import ListSubheader from '@material-ui/core/ListSubheader'; +import Menu from '@mui/material/Menu'; +import MenuItem from '@mui/material/MenuItem'; +import ListItemText from '@mui/material/ListItemText'; +import ListSubheader from '@mui/material/ListSubheader'; import PropTypes from 'prop-types'; /** diff --git a/src/components/WindowListButton.js b/src/components/WindowListButton.js index 68a9bd2ac9..758e227ac7 100644 --- a/src/components/WindowListButton.js +++ b/src/components/WindowListButton.js @@ -1,7 +1,6 @@ import { Component } from 'react'; -import BookmarksIcon from '@material-ui/icons/BookmarksSharp'; +import BookmarksIcon from '@mui/icons-material/BookmarksSharp'; import PropTypes from 'prop-types'; -import classNames from 'classnames'; import WindowList from '../containers/WindowList'; import MiradorMenuButton from '../containers/MiradorMenuButton'; @@ -33,7 +32,7 @@ export class WindowListButton extends Component { */ render() { const { - classes, disabled, t, windowCount, + disabled, t, windowCount, } = this.props; const { windowListAnchor } = this.state; @@ -43,24 +42,29 @@ export class WindowListButton extends Component { aria-haspopup="true" aria-label={t('listAllOpenWindows')} aria-owns={windowListAnchor ? 'window-list' : null} - className={ - classNames(classes.ctrlBtn, (windowListAnchor ? classes.ctrlBtnSelected : null)) - } + selected={Boolean(windowListAnchor)} disabled={disabled} badge - BadgeProps={{ badgeContent: windowCount, classes: { badge: classes.badge } }} - onClick={e => this.handleOpen(e)} + BadgeProps={{ + badgeContent: windowCount, + sx: { + '.MuiBadge-badge': { + paddingLeft: 1.5, + }, + }, + }} + onClick={(e) => this.handleOpen(e)} >
{Boolean(windowListAnchor) && ( - + )} ); @@ -68,12 +72,10 @@ export class WindowListButton extends Component { } WindowListButton.propTypes = { - classes: PropTypes.objectOf(PropTypes.string), disabled: PropTypes.bool, t: PropTypes.func.isRequired, windowCount: PropTypes.number.isRequired, }; WindowListButton.defaultProps = { - classes: {}, disabled: false, }; diff --git a/src/components/WindowSideBar.js b/src/components/WindowSideBar.js index c6fbc6ef3f..7750eeb294 100644 --- a/src/components/WindowSideBar.js +++ b/src/components/WindowSideBar.js @@ -1,9 +1,20 @@ import { Component } from 'react'; import PropTypes from 'prop-types'; -import classNames from 'classnames'; -import Drawer from '@material-ui/core/Drawer'; +import { styled } from '@mui/material/styles'; +import Drawer from '@mui/material/Drawer'; import WindowSideBarButtons from '../containers/WindowSideBarButtons'; +const Root = styled(Drawer, { name: 'WindowSideBar', slot: 'root' })(({ theme }) => ({ + flexShrink: 0, + order: -1000, + zIndex: theme.zIndex.appBar - 1, +})); + +const Nav = styled('nav', { name: 'WindowSideBar', slot: 'nav' })({ + position: 'relative !important', + width: 48, +}); + /** * WindowSideBar */ @@ -18,27 +29,26 @@ export class WindowSideBar extends Component { } = this.props; return ( - - + ); } } WindowSideBar.propTypes = { - classes: PropTypes.objectOf(PropTypes.string).isRequired, + classes: PropTypes.objectOf(PropTypes.string), direction: PropTypes.string.isRequired, sideBarOpen: PropTypes.bool, t: PropTypes.func.isRequired, @@ -46,5 +56,6 @@ WindowSideBar.propTypes = { }; WindowSideBar.defaultProps = { + classes: {}, sideBarOpen: false, }; diff --git a/src/components/WindowSideBarAnnotationsPanel.js b/src/components/WindowSideBarAnnotationsPanel.js index f5182e6443..d2e6f781d0 100644 --- a/src/components/WindowSideBarAnnotationsPanel.js +++ b/src/components/WindowSideBarAnnotationsPanel.js @@ -1,9 +1,10 @@ import { createRef, Component } from 'react'; import PropTypes from 'prop-types'; -import Typography from '@material-ui/core/Typography'; +import Typography from '@mui/material/Typography'; import AnnotationSettings from '../containers/AnnotationSettings'; import CanvasAnnotations from '../containers/CanvasAnnotations'; import CompanionWindow from '../containers/CompanionWindow'; +import { CompanionWindowSection } from './CompanionWindowSection'; import ns from '../config/css-ns'; /** @@ -22,7 +23,7 @@ export class WindowSideBarAnnotationsPanel extends Component { */ render() { const { - annotationCount, classes, canvasIds, t, windowId, id, + annotationCount, canvasIds, t, windowId, id, } = this.props; return ( } > -
+ {t('showingNumAnnotations', { count: annotationCount, number: annotationCount })} -
+ {canvasIds.map((canvasId, index) => ( ({ + '&.Mui-selected': { + borderRight: '2px solid', + borderRightColor: theme.palette.primary.main, + }, + '&.MuiTab-root': { + '&:active': { + backgroundColor: theme.palette.action.active, + }, + '&:focus': { + '@media (hover: none)': { + backgroundColor: 'transparent', + }, + backgroundColor: theme.palette.action.hover, + textDecoration: 'none', + // Reset on touch devices, it doesn't add specificity + }, + '&:hover': { + '@media (hover: none)': { + backgroundColor: 'transparent', + }, + backgroundColor: theme.palette.action.hover, + textDecoration: 'none', + // Reset on touch devices, it doesn't add specificity + }, + borderRight: '2px solid transparent', + minWidth: 'auto', + }, + fill: 'currentcolor', +})); + /** */ function TabButton({ t, value, ...tabProps }) { return ( - )} /> @@ -97,7 +135,6 @@ export class WindowSideBarButtons extends Component { )} /> @@ -106,7 +143,6 @@ export class WindowSideBarButtons extends Component { )} /> @@ -115,10 +151,9 @@ export class WindowSideBarButtons extends Component { + )} @@ -128,10 +163,9 @@ export class WindowSideBarButtons extends Component { + )} @@ -141,10 +175,9 @@ export class WindowSideBarButtons extends Component { + )} @@ -154,21 +187,19 @@ export class WindowSideBarButtons extends Component { && PluginComponents.map(PluginComponent => ( } /> ))} - + ); } } WindowSideBarButtons.propTypes = { addCompanionWindow: PropTypes.func.isRequired, - classes: PropTypes.objectOf(PropTypes.string), hasAnnotations: PropTypes.bool, hasAnyAnnotations: PropTypes.bool, hasAnyLayers: PropTypes.bool, @@ -182,7 +213,6 @@ WindowSideBarButtons.propTypes = { }; WindowSideBarButtons.defaultProps = { - classes: {}, hasAnnotations: false, hasAnyAnnotations: false, hasAnyLayers: false, diff --git a/src/components/WindowSideBarCanvasPanel.js b/src/components/WindowSideBarCanvasPanel.js index d785b5abe2..768f8c65d5 100644 --- a/src/components/WindowSideBarCanvasPanel.js +++ b/src/components/WindowSideBarCanvasPanel.js @@ -1,21 +1,26 @@ import { createRef, Component } from 'react'; import PropTypes from 'prop-types'; -import Tabs from '@material-ui/core/Tabs'; -import Tab from '@material-ui/core/Tab'; -import Tooltip from '@material-ui/core/Tooltip'; -import Button from '@material-ui/core/Button'; -import ItemListIcon from '@material-ui/icons/ReorderSharp'; -import TocIcon from '@material-ui/icons/SortSharp'; -import ThumbnailListIcon from '@material-ui/icons/ViewListSharp'; -import Typography from '@material-ui/core/Typography'; -import ArrowForwardIcon from '@material-ui/icons/ArrowForwardSharp'; -import FormControl from '@material-ui/core/FormControl'; -import Select from '@material-ui/core/Select'; -import MenuItem from '@material-ui/core/MenuItem'; +import { styled } from '@mui/material/styles'; +import Tabs from '@mui/material/Tabs'; +import Tab from '@mui/material/Tab'; +import Tooltip from '@mui/material/Tooltip'; +import Button from '@mui/material/Button'; +import ItemListIcon from '@mui/icons-material/ReorderSharp'; +import TocIcon from '@mui/icons-material/SortSharp'; +import ThumbnailListIcon from '@mui/icons-material/ViewListSharp'; +import Typography from '@mui/material/Typography'; +import ArrowForwardIcon from '@mui/icons-material/ArrowForwardSharp'; +import FormControl from '@mui/material/FormControl'; +import Select from '@mui/material/Select'; +import MenuItem from '@mui/material/MenuItem'; import CompanionWindow from '../containers/CompanionWindow'; import SidebarIndexList from '../containers/SidebarIndexList'; import SidebarIndexTableOfContents from '../containers/SidebarIndexTableOfContents'; +const StyledBreak = styled('div')(() => ({ + flexBasis: '100%', + height: 0, +})); /** * a panel showing the canvases for a given manifest */ @@ -57,7 +62,6 @@ export class WindowSideBarCanvasPanel extends Component { */ render() { const { - classes, collection, id, showMultipart, @@ -95,7 +99,6 @@ export class WindowSideBarCanvasPanel extends Component { id={id} windowId={windowId} ref={this.containerRef} - otherRef={this.containerRef} titleControls={( <> { @@ -107,14 +110,19 @@ export class WindowSideBarCanvasPanel extends Component { horizontal: 'left', vertical: 'bottom', }, - getContentAnchorEl: null, }} displayEmpty value={sequenceId} onChange={this.handleSequenceChange} name="sequenceId" - classes={{ select: classes.select }} - className={classes.selectEmpty} + sx={{ + '&.MuiSelect-select': { + '&:focus': { + backgroundColor: 'background.paper', + }, + }, + backgroundColor: 'background.paper', + }} data-testid="sequence-select" > { sequences.map((s, i) => { WindowSideBarCanvasPanel.getUseableLabel(s, i) }) } @@ -122,7 +130,7 @@ export class WindowSideBarCanvasPanel extends Component { ) } -
+ {showToc && ( - } /> + } /> )} - } /> - } /> + } /> + } /> )} @@ -146,7 +154,7 @@ export class WindowSideBarCanvasPanel extends Component { onClick={showMultipart} endIcon={} > - + {WindowSideBarCanvasPanel.getUseableLabel(collection)} @@ -159,7 +167,6 @@ export class WindowSideBarCanvasPanel extends Component { } WindowSideBarCanvasPanel.propTypes = { - classes: PropTypes.objectOf(PropTypes.string).isRequired, collection: PropTypes.object, // eslint-disable-line react/forbid-prop-types id: PropTypes.string.isRequired, sequenceId: PropTypes.string, diff --git a/src/components/WindowSideBarCollectionPanel.js b/src/components/WindowSideBarCollectionPanel.js index a6964ca777..f55a2dbdef 100644 --- a/src/components/WindowSideBarCollectionPanel.js +++ b/src/components/WindowSideBarCollectionPanel.js @@ -1,14 +1,14 @@ import { Component } from 'react'; import PropTypes from 'prop-types'; -import List from '@material-ui/core/List'; -import ListItem from '@material-ui/core/ListItem'; -import ListItemIcon from '@material-ui/core/ListItemIcon'; -import ListItemText from '@material-ui/core/ListItemText'; -import MenuList from '@material-ui/core/MenuList'; -import MenuItem from '@material-ui/core/MenuItem'; -import Typography from '@material-ui/core/Typography'; -import Skeleton from '@material-ui/lab/Skeleton'; -import ArrowUpwardIcon from '@material-ui/icons/ArrowUpwardSharp'; +import List from '@mui/material/List'; +import ListItem from '@mui/material/ListItem'; +import ListItemIcon from '@mui/material/ListItemIcon'; +import ListItemText from '@mui/material/ListItemText'; +import MenuList from '@mui/material/MenuList'; +import MenuItem from '@mui/material/MenuItem'; +import Typography from '@mui/material/Typography'; +import Skeleton from '@mui/material/Skeleton'; +import ArrowUpwardIcon from '@mui/icons-material/ArrowUpwardSharp'; import CompanionWindow from '../containers/CompanionWindow'; import IIIFThumbnail from '../containers/IIIFThumbnail'; @@ -20,7 +20,12 @@ function Item({ { variant === 'thumbnail' && ( @@ -74,7 +79,6 @@ export class WindowSideBarCollectionPanel extends Component { render() { const { canvasNavigation, - classes, collectionPath, collection, id, @@ -114,7 +118,7 @@ export class WindowSideBarCollectionPanel extends Component { )} { collection && WindowSideBarCollectionPanel.getUseableLabel(collection)} - { isFetching && } + { isFetching && } )} @@ -123,9 +127,9 @@ export class WindowSideBarCollectionPanel extends Component { { isFetching && ( - - - + + + )} @@ -144,7 +148,6 @@ export class WindowSideBarCollectionPanel extends Component { canvasNavigation={canvasNavigation} manifest={manifest} variant={variant} - className={classes.menuItem} selected={manifestId === manifest.id} /> ); @@ -167,7 +170,6 @@ export class WindowSideBarCollectionPanel extends Component { canvasNavigation={canvasNavigation} manifest={manifest} variant={variant} - className={classes.menuItem} selected={manifestId === manifest.id} /> ); @@ -184,7 +186,6 @@ WindowSideBarCollectionPanel.propTypes = { height: PropTypes.number, width: PropTypes.number, }).isRequired, - classes: PropTypes.objectOf(PropTypes.string).isRequired, collection: PropTypes.object, // eslint-disable-line react/forbid-prop-types collectionPath: PropTypes.arrayOf(PropTypes.string), id: PropTypes.string.isRequired, diff --git a/src/components/WindowSideBarInfoPanel.js b/src/components/WindowSideBarInfoPanel.js index e2931f70e3..3261679503 100644 --- a/src/components/WindowSideBarInfoPanel.js +++ b/src/components/WindowSideBarInfoPanel.js @@ -1,6 +1,7 @@ import { Component } from 'react'; import PropTypes from 'prop-types'; import CompanionWindow from '../containers/CompanionWindow'; +import { CompanionWindowSection } from './CompanionWindowSection'; import CanvasInfo from '../containers/CanvasInfo'; import LocalePicker from '../containers/LocalePicker'; import ManifestInfo from '../containers/ManifestInfo'; @@ -21,7 +22,6 @@ export class WindowSideBarInfoPanel extends Component { windowId, id, canvasIds, - classes, collectionPath, t, locale, @@ -49,7 +49,9 @@ export class WindowSideBarInfoPanel extends Component { > { canvasIds.map((canvasId, index) => ( -
+ -
+ )) } { collectionPath.length > 0 && ( -
+ -
+ )} -
+ -
+ -
+ -
+ ); } @@ -81,7 +83,6 @@ export class WindowSideBarInfoPanel extends Component { WindowSideBarInfoPanel.propTypes = { availableLocales: PropTypes.arrayOf(PropTypes.string), canvasIds: PropTypes.arrayOf(PropTypes.string), - classes: PropTypes.objectOf(PropTypes.string), collectionPath: PropTypes.arrayOf(PropTypes.string), id: PropTypes.string.isRequired, locale: PropTypes.string, @@ -94,7 +95,6 @@ WindowSideBarInfoPanel.propTypes = { WindowSideBarInfoPanel.defaultProps = { availableLocales: [], canvasIds: [], - classes: {}, collectionPath: [], locale: '', setLocale: undefined, diff --git a/src/components/WindowThumbnailSettings.js b/src/components/WindowThumbnailSettings.js index 22b7eb57db..042355e4d0 100644 --- a/src/components/WindowThumbnailSettings.js +++ b/src/components/WindowThumbnailSettings.js @@ -1,11 +1,25 @@ import { Component } from 'react'; -import FormControlLabel from '@material-ui/core/FormControlLabel'; -import ListSubheader from '@material-ui/core/ListSubheader'; -import MenuItem from '@material-ui/core/MenuItem'; -import ThumbnailsOffIcon from '@material-ui/icons/CropDinSharp'; +import { styled } from '@mui/material/styles'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import ListSubheader from '@mui/material/ListSubheader'; +import MenuItem from '@mui/material/MenuItem'; +import ThumbnailsOffIcon from '@mui/icons-material/CropDinSharp'; import PropTypes from 'prop-types'; import ThumbnailNavigationBottomIcon from './icons/ThumbnailNavigationBottomIcon'; import ThumbnailNavigationRightIcon from './icons/ThumbnailNavigationRightIcon'; + +const ThumbnailOption = styled(MenuItem, { name: 'WindowThumbnailSettings', slot: 'option' })(({ selected, theme }) => ({ + '& .MuiFormControlLabel-label': { + borderBottom: '2px solid transparent', + ...(selected && { + borderBottomColor: theme.palette.secondary.main, + }), + }, + backgroundColor: 'transparent !important', + color: selected ? theme.palette.secondary.main : undefined, + display: 'inline-block', +})); + /** * */ @@ -34,56 +48,53 @@ export class WindowThumbnailSettings extends Component { */ render() { const { - classes, handleClose, t, thumbnailNavigationPosition, direction, + handleClose, t, thumbnailNavigationPosition, direction, } = this.props; return ( <> - {t('thumbnails')} + {t('thumbnails')} - { this.handleChange('off'); handleClose(); }}> + { this.handleChange('off'); handleClose(); }}> + } label={t('off')} labelPlacement="bottom" /> - - { this.handleChange('far-bottom'); handleClose(); }}> + + { this.handleChange('far-bottom'); handleClose(); }}> + } label={t('bottom')} labelPlacement="bottom" /> - - { this.handleChange('far-right'); handleClose(); }}> + + { this.handleChange('far-right'); handleClose(); }}> )} label={t('right')} labelPlacement="bottom" /> - + ); } } WindowThumbnailSettings.propTypes = { - classes: PropTypes.objectOf(PropTypes.string).isRequired, direction: PropTypes.string.isRequired, handleClose: PropTypes.func, setWindowThumbnailPosition: PropTypes.func.isRequired, diff --git a/src/components/WindowTopBar.js b/src/components/WindowTopBar.js index cf204b2f88..5e32f8cd07 100644 --- a/src/components/WindowTopBar.js +++ b/src/components/WindowTopBar.js @@ -1,9 +1,10 @@ import { Component } from 'react'; import PropTypes from 'prop-types'; -import MenuIcon from '@material-ui/icons/MenuSharp'; -import CloseIcon from '@material-ui/icons/CloseSharp'; -import Toolbar from '@material-ui/core/Toolbar'; -import AppBar from '@material-ui/core/AppBar'; +import { styled } from '@mui/material/styles'; +import MenuIcon from '@mui/icons-material/MenuSharp'; +import CloseIcon from '@mui/icons-material/CloseSharp'; +import Toolbar from '@mui/material/Toolbar'; +import AppBar from '@mui/material/AppBar'; import classNames from 'classnames'; import WindowTopMenuButton from '../containers/WindowTopMenuButton'; import WindowTopBarPluginArea from '../containers/WindowTopBarPluginArea'; @@ -15,6 +16,22 @@ import WindowMaxIcon from './icons/WindowMaxIcon'; import WindowMinIcon from './icons/WindowMinIcon'; import ns from '../config/css-ns'; +const Root = styled(AppBar, { name: 'WindowTopBar', slot: 'root' })(() => ({ + zIndex: 1100, +})); + +const StyledToolbar = styled(Toolbar, { name: 'WindowTopBar', slot: 'toolbar' })(({ ownerState, theme }) => ({ + backgroundColor: theme.palette.shades?.main, + borderTop: '2px solid', + borderTopColor: ownerState?.focused ? theme.palette.primary.main : 'transparent', + minHeight: 32, + paddingLeft: theme.spacing(0.5), + paddingRight: theme.spacing(0.5), + ...(ownerState?.windowDraggable && { + cursor: 'move', + }), +})); + /** * WindowTopBar */ @@ -25,66 +42,61 @@ export class WindowTopBar extends Component { */ render() { const { - removeWindow, windowId, classes, toggleWindowSideBar, t, windowDraggable, - maximizeWindow, maximized, minimizeWindow, focused, allowClose, allowMaximize, + removeWindow, windowId, toggleWindowSideBar, t, + maximizeWindow, maximized, minimizeWindow, allowClose, allowMaximize, focusWindow, allowFullscreen, allowTopMenuButton, allowWindowSideBar, + component, } = this.props; return ( - - - + + + {allowWindowSideBar && ( + + + + )} + + {allowTopMenuButton && ( + + )} + + + {allowMaximize && ( + + {(maximized ? : )} + + )} + {allowFullscreen && ( + + )} + {allowClose && ( + + + + )} + + ); } } @@ -95,8 +107,8 @@ WindowTopBar.propTypes = { allowMaximize: PropTypes.bool, allowTopMenuButton: PropTypes.bool, allowWindowSideBar: PropTypes.bool, - classes: PropTypes.objectOf(PropTypes.string).isRequired, - focused: PropTypes.bool, + component: PropTypes.elementType, + focused: PropTypes.bool, // eslint-disable-line react/no-unused-prop-types focusWindow: PropTypes.func, maximized: PropTypes.bool, maximizeWindow: PropTypes.func, @@ -104,7 +116,7 @@ WindowTopBar.propTypes = { removeWindow: PropTypes.func.isRequired, t: PropTypes.func, toggleWindowSideBar: PropTypes.func.isRequired, - windowDraggable: PropTypes.bool, + windowDraggable: PropTypes.bool, // eslint-disable-line react/no-unused-prop-types windowId: PropTypes.string.isRequired, }; @@ -114,6 +126,7 @@ WindowTopBar.defaultProps = { allowMaximize: true, allowTopMenuButton: true, allowWindowSideBar: true, + component: 'nav', focused: false, focusWindow: () => {}, maximized: false, diff --git a/src/components/WindowTopBarPluginMenu.js b/src/components/WindowTopBarPluginMenu.js index 78f95a73ec..972cbf544b 100644 --- a/src/components/WindowTopBarPluginMenu.js +++ b/src/components/WindowTopBarPluginMenu.js @@ -1,7 +1,7 @@ import { Component } from 'react'; import PropTypes from 'prop-types'; -import MoreVertIcon from '@material-ui/icons/MoreVertSharp'; -import Menu from '@material-ui/core/Menu'; +import MoreVertIcon from '@mui/icons-material/MoreVertSharp'; +import Menu from '@mui/material/Menu'; import MiradorMenuButton from '../containers/MiradorMenuButton'; import { PluginHook } from './PluginHook'; @@ -47,7 +47,7 @@ export class WindowTopBarPluginMenu extends Component { */ render() { const { - classes, container, PluginComponents, t, windowId, menuIcon, + container, PluginComponents, t, windowId, menuIcon, } = this.props; const { anchorEl, open } = this.state; const windowPluginMenuId = `window-plugin-menu_${windowId}`; @@ -59,7 +59,7 @@ export class WindowTopBarPluginMenu extends Component { aria-haspopup="true" aria-label={t('windowPluginMenu')} aria-owns={open ? windowPluginMenuId : undefined} - className={open ? classes.ctrlBtnSelected : null} + selected={open} onClick={this.handleMenuClick} > {menuIcon} @@ -77,7 +77,6 @@ export class WindowTopBarPluginMenu extends Component { horizontal: 'right', vertical: 'top', }} - getContentAnchorEl={null} open={open} onClose={() => this.handleMenuClose()} > @@ -90,9 +89,6 @@ export class WindowTopBarPluginMenu extends Component { WindowTopBarPluginMenu.propTypes = { anchorEl: PropTypes.object, // eslint-disable-line react/forbid-prop-types - classes: PropTypes.shape({ - ctrlBtnSelected: PropTypes.string, - }), container: PropTypes.shape({ current: PropTypes.instanceOf(Element) }), menuIcon: PropTypes.element, open: PropTypes.bool, @@ -105,7 +101,6 @@ WindowTopBarPluginMenu.propTypes = { WindowTopBarPluginMenu.defaultProps = { anchorEl: null, - classes: {}, container: null, menuIcon: , open: false, diff --git a/src/components/WindowTopBarTitle.js b/src/components/WindowTopBarTitle.js index b47f00c2c2..5c91250e12 100644 --- a/src/components/WindowTopBarTitle.js +++ b/src/components/WindowTopBarTitle.js @@ -1,9 +1,21 @@ import { Component } from 'react'; import PropTypes from 'prop-types'; -import Typography from '@material-ui/core/Typography'; -import Skeleton from '@material-ui/lab/Skeleton'; -import ErrorIcon from '@material-ui/icons/ErrorOutlineSharp'; +import { styled } from '@mui/material/styles'; +import Typography from '@mui/material/Typography'; +import Skeleton from '@mui/material/Skeleton'; +import ErrorIcon from '@mui/icons-material/ErrorOutlineSharp'; +const StyledTitleTypography = styled(TitleTypography)(({ theme }) => ({ + ...theme.typography.h6, + flexGrow: 1, + paddingLeft: theme.spacing(0.5), +})); + +const StyledTitle = styled('div')(({ theme }) => ({ + ...theme.typography.h6, + flexGrow: 1, + paddingLeft: theme.spacing(0.5), +})); /** */ function TitleTypography({ children, ...props }) { return ( @@ -27,32 +39,32 @@ export class WindowTopBarTitle extends Component { */ render() { const { - classes, error, hideWindowTitle, isFetching, manifestTitle, + error, hideWindowTitle, isFetching, manifestTitle, } = this.props; let title = null; if (isFetching) { title = ( - + - + ); } else if (error) { title = ( <> - + {error} - + ); } else if (hideWindowTitle) { - title = (
); + title = (); } else { title = ( - + {manifestTitle} - + ); } return title; @@ -60,7 +72,6 @@ export class WindowTopBarTitle extends Component { } WindowTopBarTitle.propTypes = { - classes: PropTypes.objectOf(PropTypes.string).isRequired, error: PropTypes.string, hideWindowTitle: PropTypes.bool, isFetching: PropTypes.bool, diff --git a/src/components/WindowTopMenu.js b/src/components/WindowTopMenu.js index d978876a33..feb45377bd 100644 --- a/src/components/WindowTopMenu.js +++ b/src/components/WindowTopMenu.js @@ -1,6 +1,6 @@ import { Component } from 'react'; -import Menu from '@material-ui/core//Menu'; -import ListSubheader from '@material-ui/core/ListSubheader'; +import Menu from '@mui/material//Menu'; +import ListSubheader from '@mui/material/ListSubheader'; import PropTypes from 'prop-types'; import WindowThumbnailSettings from '../containers/WindowThumbnailSettings'; import WindowViewSettings from '../containers/WindowViewSettings'; @@ -11,7 +11,7 @@ function PluginHookWithHeader(props) { const { PluginComponents, t } = props; // eslint-disable-line react/prop-types return PluginComponents ? ( <> - {t('windowPluginButtons')} + {t('windowPluginButtons')} ) : null; @@ -47,7 +47,6 @@ export class WindowTopMenu extends Component { onExit: toggleDraggingEnabled, }} orientation="horizontal" - getContentAnchorEl={null} anchorEl={anchorEl} open={open} > diff --git a/src/components/WindowTopMenuButton.js b/src/components/WindowTopMenuButton.js index ca9ab8db01..e48bd84d2c 100644 --- a/src/components/WindowTopMenuButton.js +++ b/src/components/WindowTopMenuButton.js @@ -1,6 +1,5 @@ import { Component } from 'react'; import PropTypes from 'prop-types'; -import classNames from 'classnames'; import WindowTopMenu from '../containers/WindowTopMenu'; import MiradorMenuButton from '../containers/MiradorMenuButton'; import WindowOptionsIcon from './icons/WindowOptionsIcon'; @@ -47,7 +46,7 @@ export class WindowTopMenuButton extends Component { */ render() { const { - classes, className, t, windowId, + classes, t, windowId, } = this.props; const { open, anchorEl } = this.state; const menuId = `window-menu_${windowId}`; @@ -57,7 +56,8 @@ export class WindowTopMenuButton extends Component { aria-haspopup="true" aria-label={t('windowMenu')} aria-owns={open ? menuId : undefined} - className={classNames(className, open ? classes.ctrlBtnSelected : null)} + className={open ? classes.ctrlBtnSelected : undefined} + selected={open} onClick={this.handleMenuClick} > @@ -75,13 +75,12 @@ export class WindowTopMenuButton extends Component { } WindowTopMenuButton.propTypes = { - classes: PropTypes.objectOf(PropTypes.string).isRequired, - className: PropTypes.string, + classes: PropTypes.objectOf(PropTypes.string), t: PropTypes.func, windowId: PropTypes.string.isRequired, }; WindowTopMenuButton.defaultProps = { - className: '', + classes: {}, t: key => key, }; diff --git a/src/components/WindowViewSettings.js b/src/components/WindowViewSettings.js index 90c56b8232..e693b2ffcd 100644 --- a/src/components/WindowViewSettings.js +++ b/src/components/WindowViewSettings.js @@ -1,13 +1,26 @@ import { Component } from 'react'; -import FormControlLabel from '@material-ui/core/FormControlLabel'; -import MenuItem from '@material-ui/core/MenuItem'; -import ListSubheader from '@material-ui/core/ListSubheader'; -import SingleIcon from '@material-ui/icons/CropOriginalSharp'; -import ScrollViewIcon from '@material-ui/icons/ViewColumn'; +import { styled } from '@mui/material/styles'; +import FormControlLabel from '@mui/material/FormControlLabel'; +import MenuItem from '@mui/material/MenuItem'; +import ListSubheader from '@mui/material/ListSubheader'; +import SingleIcon from '@mui/icons-material/CropOriginalSharp'; +import ScrollViewIcon from '@mui/icons-material/ViewColumn'; import PropTypes from 'prop-types'; import BookViewIcon from './icons/BookViewIcon'; import GalleryViewIcon from './icons/GalleryViewIcon'; +const ViewOption = styled(MenuItem, { name: 'WindowViewSettings', slot: 'option' })(({ selected, theme }) => ({ + '& .MuiFormControlLabel-label': { + borderBottom: '2px solid transparent', + ...(selected && { + borderBottomColor: theme.palette.secondary.main, + }), + }, + backgroundColor: 'transparent !important', + color: selected ? theme.palette.secondary.main : undefined, + display: 'inline-block', +})); + /** * */ @@ -36,7 +49,7 @@ export class WindowViewSettings extends Component { */ render() { const { - classes, handleClose, t, windowViewType, viewTypes, + handleClose, t, windowViewType, viewTypes, } = this.props; const iconMap = { @@ -49,26 +62,25 @@ export class WindowViewSettings extends Component { /** Suspiciously similar to a component, yet if it is invoked through JSX none of the click handlers work? */ const menuItem = ({ value, Icon }) => ( - { this.handleChange(value); handleClose(); }} > } + control={} label={t(value)} labelPlacement="bottom" /> - + ); if (viewTypes.length === 0) return null; return ( <> - {t('view')} + {t('view')} { viewTypes.map(value => menuItem({ Icon: iconMap[value], value })) } ); @@ -76,7 +88,6 @@ export class WindowViewSettings extends Component { } WindowViewSettings.propTypes = { - classes: PropTypes.objectOf(PropTypes.string).isRequired, handleClose: PropTypes.func, setWindowViewType: PropTypes.func.isRequired, t: PropTypes.func, diff --git a/src/components/Workspace.js b/src/components/Workspace.js index f99f61d4e4..c94f8a30b3 100644 --- a/src/components/Workspace.js +++ b/src/components/Workspace.js @@ -1,14 +1,22 @@ import { Component } from 'react'; import PropTypes from 'prop-types'; +import { styled } from '@mui/material/styles'; import classNames from 'classnames'; -import Grid from '@material-ui/core/Grid'; -import Typography from '@material-ui/core/Typography'; +import Grid from '@mui/material/Grid'; +import Typography from '@mui/material/Typography'; +import { visuallyHidden } from '@mui/utils'; import Window from '../containers/Window'; import WorkspaceMosaic from '../containers/WorkspaceMosaic'; import WorkspaceElastic from '../containers/WorkspaceElastic'; import ns from '../config/css-ns'; import { IIIFDropTarget } from './IIIFDropTarget'; +const Root = styled('div', { name: 'Workspace', slot: 'root' })(() => ({ + height: '100%', + position: 'relative', + width: '100%', +})); + /** * Represents a work area that contains any number of windows * @memberof Workspace @@ -62,26 +70,28 @@ export class Workspace extends Component { const { t } = this.props; return ( - + - - {t('welcome')} - + + {t('welcome')} + + - + ); } @@ -107,23 +117,21 @@ export class Workspace extends Component { * render */ render() { - const { classes, isWorkspaceControlPanelVisible, t } = this.props; + const { t } = this.props; return ( -
- {t('miradorViewer')} + {t('miradorViewer')} {this.workspaceByType()} -
+
); } @@ -132,8 +140,6 @@ export class Workspace extends Component { Workspace.propTypes = { addWindow: PropTypes.func, allowNewWindows: PropTypes.bool, - classes: PropTypes.objectOf(PropTypes.string).isRequired, - isWorkspaceControlPanelVisible: PropTypes.bool.isRequired, maximizedWindowIds: PropTypes.arrayOf(PropTypes.string), t: PropTypes.func.isRequired, windowIds: PropTypes.arrayOf(PropTypes.string), diff --git a/src/components/WorkspaceAdd.js b/src/components/WorkspaceAdd.js index 172c8d3474..6e744878c4 100644 --- a/src/components/WorkspaceAdd.js +++ b/src/components/WorkspaceAdd.js @@ -1,16 +1,18 @@ import { createRef, Component } from 'react'; import PropTypes from 'prop-types'; +import { styled } from '@mui/material/styles'; import classNames from 'classnames'; -import AddIcon from '@material-ui/icons/AddSharp'; -import ExpandMoreIcon from '@material-ui/icons/ExpandMoreSharp'; -import AppBar from '@material-ui/core/AppBar'; -import Drawer from '@material-ui/core/Drawer'; -import Grid from '@material-ui/core/Grid'; -import Fab from '@material-ui/core/Fab'; -import List from '@material-ui/core/List'; -import Paper from '@material-ui/core/Paper'; -import Toolbar from '@material-ui/core/Toolbar'; -import Typography from '@material-ui/core/Typography'; +import AddIcon from '@mui/icons-material/AddSharp'; +import ExpandMoreIcon from '@mui/icons-material/ExpandMoreSharp'; +import AppBar from '@mui/material/AppBar'; +import Drawer from '@mui/material/Drawer'; +import Grid from '@mui/material/Grid'; +import Fab from '@mui/material/Fab'; +import List from '@mui/material/List'; +import Paper from '@mui/material/Paper'; +import Toolbar from '@mui/material/Toolbar'; +import Typography from '@mui/material/Typography'; +import { visuallyHidden } from '@mui/utils'; import ns from '../config/css-ns'; import ManifestForm from '../containers/ManifestForm'; import ManifestListItem from '../containers/ManifestListItem'; @@ -18,6 +20,17 @@ import MiradorMenuButton from '../containers/MiradorMenuButton'; import { IIIFDropTarget } from './IIIFDropTarget'; import { PluginHook } from './PluginHook'; +const StyledWorkspaceAdd = styled('div')(() => ({ + boxSizing: 'border-box', + height: '100%', + overflowX: 'hidden', + overflowY: 'auto', +})); + +const StyledMiradorMenuButton = styled(MiradorMenuButton)(() => ({ + marginLeft: -12, + marginRight: 20, +})); /** * An area for managing manifests and adding them to workspace * @memberof Workspace @@ -75,7 +88,7 @@ export class WorkspaceAdd extends Component { */ render() { const { - catalog, setWorkspaceAddVisibility, t, classes, + catalog, setWorkspaceAddVisibility, t, } = this.props; const { addResourcesOpen } = this.state; @@ -91,7 +104,7 @@ export class WorkspaceAdd extends Component { return ( -
+ {catalog.length < 1 ? ( ) : ( - - {t('miradorResources')} + + {t('miradorResources')} {manifestList} @@ -125,7 +138,12 @@ export class WorkspaceAdd extends Component { ({ + bottom: theme.spacing(2), + position: 'absolute', + right: theme.spacing(2), + })} + className={classNames(ns('add-resource-button'))} color="primary" onClick={() => (this.setAddResourcesVisibility(true))} > @@ -134,10 +152,18 @@ export class WorkspaceAdd extends Component { ({ + '.MuiDrawer-paper': { + borderTop: '0', + left: '0', + [theme.breakpoints.up('sm')]: { + left: '65px', + }, + }, + ...(!addResourcesOpen && { + display: 'none', + }), })} - classes={{ paper: classes.paper }} variant="persistent" anchor="bottom" open={addResourcesOpen} @@ -148,18 +174,25 @@ export class WorkspaceAdd extends Component { }} > - (this.setAddResourcesVisibility(false))}> + (this.setAddResourcesVisibility(false))}> - - - + + {t('addResource')} @@ -171,7 +204,7 @@ export class WorkspaceAdd extends Component { /> -
+
); } @@ -183,7 +216,6 @@ WorkspaceAdd.propTypes = { manifestId: PropTypes.string.isRequired, provider: PropTypes.string, })), - classes: PropTypes.objectOf(PropTypes.string), setWorkspaceAddVisibility: PropTypes.func.isRequired, t: PropTypes.func, }; @@ -191,6 +223,5 @@ WorkspaceAdd.propTypes = { WorkspaceAdd.defaultProps = { addResource: () => {}, catalog: [], - classes: {}, t: key => key, }; diff --git a/src/components/WorkspaceAddButton.js b/src/components/WorkspaceAddButton.js index b80ec81369..b50679226e 100644 --- a/src/components/WorkspaceAddButton.js +++ b/src/components/WorkspaceAddButton.js @@ -1,9 +1,14 @@ import { Component } from 'react'; import PropTypes from 'prop-types'; -import Fab from '@material-ui/core/Fab'; -import Tooltip from '@material-ui/core/Tooltip'; -import AddIcon from '@material-ui/icons/AddSharp'; -import CloseIcon from '@material-ui/icons/CloseSharp'; +import Fab from '@mui/material/Fab'; +import Tooltip from '@mui/material/Tooltip'; +import AddIcon from '@mui/icons-material/AddSharp'; +import CloseIcon from '@mui/icons-material/CloseSharp'; +import { styled } from '@mui/material/styles'; + +const Root = styled(Fab, { name: 'WorkspaceAddButton', slot: 'root' })(({ theme }) => ({ + marginBottom: theme.spacing(1), +})); /** */ @@ -14,22 +19,19 @@ export class WorkspaceAddButton extends Component { */ render() { const { - classes, t, setWorkspaceAddVisibility, isWorkspaceAddVisible, useExtendedFab, + t, setWorkspaceAddVisibility, isWorkspaceAddVisible, useExtendedFab, } = this.props; return ( - { setWorkspaceAddVisibility(!isWorkspaceAddVisible); }} > @@ -39,14 +41,13 @@ export class WorkspaceAddButton extends Component { : } { useExtendedFab && t('startHere') } - + ); } } WorkspaceAddButton.propTypes = { - classes: PropTypes.objectOf(PropTypes.string).isRequired, isWorkspaceAddVisible: PropTypes.bool, setWorkspaceAddVisibility: PropTypes.func.isRequired, t: PropTypes.func, diff --git a/src/components/WorkspaceArea.js b/src/components/WorkspaceArea.js index b6e2d10ba7..16200f8d81 100644 --- a/src/components/WorkspaceArea.js +++ b/src/components/WorkspaceArea.js @@ -1,6 +1,6 @@ import { Component } from 'react'; import PropTypes from 'prop-types'; -import classNames from 'classnames'; +import { styled, lighten, darken } from '@mui/material/styles'; import ErrorDialog from '../containers/ErrorDialog'; import WorkspaceControlPanel from '../containers/WorkspaceControlPanel'; import Workspace from '../containers/Workspace'; @@ -8,6 +8,29 @@ import WorkspaceAdd from '../containers/WorkspaceAdd'; import BackgroundPluginArea from '../containers/BackgroundPluginArea'; import ns from '../config/css-ns'; +const Root = styled('div', { name: 'WorkspaceArea', slot: 'root' })(({ theme }) => { + const getBackgroundColor = theme.palette.mode === 'light' ? darken : lighten; + + return { + background: getBackgroundColor(theme.palette.shades.light, 0.1), + bottom: 0, + display: 'flex', + flexDirection: 'column', + left: 0, + position: 'absolute', + right: 0, + top: 0, + [theme.breakpoints.up('sm')]: { + flexDirection: 'row', + }, + }; +}); + +const ViewerArea = styled('main', { name: 'WorkspaceArea', slot: 'viewer' })(() => ({ + flexGrow: 1, + position: 'relative', +})); + /** * This is the top level Mirador component. * @prop {Object} manifests @@ -20,7 +43,6 @@ export class WorkspaceArea extends Component { render() { const { areaRef, - classes, controlPanelVariant, isWorkspaceAddVisible, isWorkspaceControlPanelVisible, @@ -29,13 +51,13 @@ export class WorkspaceArea extends Component { } = this.props; return ( - <> + { isWorkspaceControlPanelVisible && } -
-
- + +
); } } WorkspaceArea.propTypes = { areaRef: PropTypes.shape({ current: PropTypes.instanceOf(Element) }), - classes: PropTypes.objectOf(PropTypes.string).isRequired, controlPanelVariant: PropTypes.string, isWorkspaceAddVisible: PropTypes.bool, isWorkspaceControlPanelVisible: PropTypes.bool.isRequired, diff --git a/src/components/WorkspaceControlPanel.js b/src/components/WorkspaceControlPanel.js index 376558285d..1331341330 100644 --- a/src/components/WorkspaceControlPanel.js +++ b/src/components/WorkspaceControlPanel.js @@ -1,13 +1,59 @@ import { Component } from 'react'; import PropTypes from 'prop-types'; +import { styled } from '@mui/material/styles'; import classNames from 'classnames'; -import AppBar from '@material-ui/core/AppBar'; -import Toolbar from '@material-ui/core/Toolbar'; +import AppBar from '@mui/material/AppBar'; +import Toolbar from '@mui/material/Toolbar'; import WorkspaceAddButton from '../containers/WorkspaceAddButton'; import WorkspaceControlPanelButtons from '../containers/WorkspaceControlPanelButtons'; import Branding from '../containers/Branding'; import ns from '../config/css-ns'; +const Root = styled(AppBar, { name: 'WorkspaceControlPanel', slot: 'root' })(({ ownerState, theme }) => ({ + display: 'flex', + height: 64, + padding: theme.spacing(1), + paddingBottom: 0, + position: 'relative', + [theme.breakpoints.up('sm')]: { + height: 'auto', + width: ownerState.variant === 'wide' ? 'auto' : 64, + }, + ...(ownerState.variant === 'wide' && { + width: 'auto', + }), +})); + +const StyledToolbar = styled(Toolbar, { name: 'WorkspaceControlPanel', slot: 'toolbar' })(({ theme }) => ({ + display: 'flex', + flexGrow: 1, + justifyContent: 'space-between', + [theme.breakpoints.up('sm')]: { + flexDirection: 'column', + justifyContent: 'flex-start', + minHeight: 0, + }, +})); + +const StyledWorkspaceButtons = styled('div', { name: 'WorkspaceControlPanel', slot: 'buttonArea' })(({ theme }) => ({ + [theme.breakpoints.up('sm')]: { + display: 'flex', + flexDirection: 'column', + gap: theme.spacing(2), + marginBottom: theme.spacing(1), + marginTop: theme.spacing(1), + }, +})); + +const StyledBranding = styled(Branding, { name: 'WorkspaceControlPanel', slot: 'branding' })(({ theme }) => ({ + [theme.breakpoints.up('xs')]: { + display: 'none', + }, + [theme.breakpoints.up('sm')]: { + display: 'flex', + }, +})); + /** * Provides the panel responsible for controlling the entire workspace */ @@ -17,34 +63,36 @@ export class WorkspaceControlPanel extends Component { * @return {String} - HTML markup for the component */ render() { - const { classes, t, variant } = this.props; + const { t, variant } = this.props; return ( - - + -
+ -
-
- -
+ + + + ); } } WorkspaceControlPanel.propTypes = { - classes: PropTypes.objectOf(PropTypes.string), t: PropTypes.func.isRequired, variant: PropTypes.oneOf(['default', 'wide']), }; WorkspaceControlPanel.defaultProps = { - classes: {}, variant: 'default', }; diff --git a/src/components/WorkspaceControlPanelButtons.js b/src/components/WorkspaceControlPanelButtons.js index b07adfc542..34cbf840ea 100644 --- a/src/components/WorkspaceControlPanelButtons.js +++ b/src/components/WorkspaceControlPanelButtons.js @@ -1,5 +1,4 @@ import { Component } from 'react'; -import PropTypes from 'prop-types'; import FullScreenButton from '../containers/FullScreenButton'; import WorkspaceMenuButton from '../containers/WorkspaceMenuButton'; import WorkspaceOptionsButton from '../containers/WorkspaceOptionsButton'; @@ -16,23 +15,14 @@ export class WorkspaceControlPanelButtons extends Component { * @return {type} description */ render() { - const { classes } = this.props; return ( <> - + ); } } - -WorkspaceControlPanelButtons.propTypes = { - classes: PropTypes.objectOf(PropTypes.string), -}; - -WorkspaceControlPanelButtons.defaultProps = { - classes: {}, -}; diff --git a/src/components/WorkspaceDialog.js b/src/components/WorkspaceDialog.js new file mode 100644 index 0000000000..0928db6502 --- /dev/null +++ b/src/components/WorkspaceDialog.js @@ -0,0 +1,13 @@ +import { + Dialog, +} from '@mui/material'; +import { styled } from '@mui/material/styles'; + +export const WorkspaceDialog = styled(Dialog, { name: 'WorkspaceDialog', slot: 'root' })(({ theme, variant }) => ({ + '& .MuiDialogTitle-root': theme.unstable_sx({ typography: 'h2' }), + ...(variant === 'menu' && { + '& .MuiDialogContent-root': { + padding: 0, + }, + }), +})); diff --git a/src/components/WorkspaceElastic.js b/src/components/WorkspaceElastic.js index 01c2e79d2b..f871ab9983 100644 --- a/src/components/WorkspaceElastic.js +++ b/src/components/WorkspaceElastic.js @@ -1,11 +1,29 @@ import { Component } from 'react'; import PropTypes from 'prop-types'; +import { styled } from '@mui/material/styles'; import { Rnd } from 'react-rnd'; import ResizeObserver from 'react-resize-observer'; -import classNames from 'classnames'; import WorkspaceElasticWindow from '../containers/WorkspaceElasticWindow'; import ns from '../config/css-ns'; +const Root = styled('div', { name: 'WorkspaceElastic', slot: 'root' })({ + height: '100%', + position: 'relative', + width: '100%', +}); + +const StyledRnd = styled(Rnd)({ + boxSizing: 'border-box', + margin: 0, + position: 'absolute', + transitionDuration: '.7s', + // order matters + // eslint-disable-next-line sort-keys + '&.react-draggable-dragging': { + transitionDuration: 'unset', + }, +}); + /** * Represents a work area that contains any number of windows * @memberof Workspace @@ -16,7 +34,6 @@ class WorkspaceElastic extends Component { */ render() { const { - classes, workspace, elasticLayout, setWorkspaceViewportDimensions, @@ -28,13 +45,13 @@ class WorkspaceElastic extends Component { const offsetY = workspace.height / 2; return ( -
+ {}} onResize={(rect) => { setWorkspaceViewportDimensions(rect); }} /> - { @@ -67,14 +84,13 @@ class WorkspaceElastic extends Component { /> )) } - -
+ + ); } } WorkspaceElastic.propTypes = { - classes: PropTypes.objectOf(PropTypes.string).isRequired, elasticLayout: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types setWorkspaceViewportDimensions: PropTypes.func.isRequired, setWorkspaceViewportPosition: PropTypes.func.isRequired, diff --git a/src/components/WorkspaceElasticWindow.js b/src/components/WorkspaceElasticWindow.js index 54224913c4..dea8c87b6a 100644 --- a/src/components/WorkspaceElasticWindow.js +++ b/src/components/WorkspaceElasticWindow.js @@ -1,9 +1,14 @@ import { Component } from 'react'; import PropTypes from 'prop-types'; +import { styled } from '@mui/material/styles'; import { Rnd } from 'react-rnd'; import Window from '../containers/Window'; import ns from '../config/css-ns'; +const StyledRnd = styled(Rnd)(({ focused, theme }) => ({ + zIndex: focused ? theme.zIndex.modal - 1 : 'auto', +})); + /** * Represents a work area that contains any number of windows * @memberof Workspace @@ -27,7 +32,9 @@ class WorkspaceElasticWindow extends Component { const offsetY = workspace.height / 2; return ( - - + ); } } diff --git a/src/components/WorkspaceExport.js b/src/components/WorkspaceExport.js index 6e2a1b18a6..d6a7962bd3 100644 --- a/src/components/WorkspaceExport.js +++ b/src/components/WorkspaceExport.js @@ -1,19 +1,19 @@ import { Component } from 'react'; -import Button from '@material-ui/core/Button'; -import Dialog from '@material-ui/core/Dialog'; -import DialogActions from '@material-ui/core/DialogActions'; -import DialogTitle from '@material-ui/core/DialogTitle'; -import DialogContent from '@material-ui/core/DialogContent'; -import Typography from '@material-ui/core/Typography'; -import Snackbar from '@material-ui/core/Snackbar'; -import IconButton from '@material-ui/core/IconButton'; -import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; -import CloseIcon from '@material-ui/icons/Close'; -import Accordion from '@material-ui/core/Accordion'; -import AccordionSummary from '@material-ui/core/AccordionSummary'; -import AccordionDetails from '@material-ui/core/AccordionDetails'; +import Button from '@mui/material/Button'; +import DialogActions from '@mui/material/DialogActions'; +import DialogTitle from '@mui/material/DialogTitle'; +import DialogContent from '@mui/material/DialogContent'; +import Typography from '@mui/material/Typography'; +import Snackbar from '@mui/material/Snackbar'; +import IconButton from '@mui/material/IconButton'; +import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; +import CloseIcon from '@mui/icons-material/Close'; +import Accordion from '@mui/material/Accordion'; +import AccordionSummary from '@mui/material/AccordionSummary'; +import AccordionDetails from '@mui/material/AccordionDetails'; import PropTypes from 'prop-types'; import { CopyToClipboard } from 'react-copy-to-clipboard'; +import { WorkspaceDialog } from './WorkspaceDialog'; /** */ @@ -54,7 +54,7 @@ export class WorkspaceExport extends Component { */ render() { const { - children, classes, container, open, t, + children, container, open, t, } = this.props; const { copied } = this.state; @@ -79,7 +79,7 @@ export class WorkspaceExport extends Component { } return ( - - - {t('downloadExport')} + + {t('downloadExport')} - + } > {t('viewWorkspaceConfiguration')} - + {children}
                 {this.exportedState()}
@@ -118,14 +117,13 @@ export class WorkspaceExport extends Component {
             
           
         
-      
+ ); } } WorkspaceExport.propTypes = { children: PropTypes.node, - classes: PropTypes.objectOf(PropTypes.string), container: PropTypes.object, // eslint-disable-line react/forbid-prop-types exportableState: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types handleClose: PropTypes.func.isRequired, @@ -135,7 +133,6 @@ WorkspaceExport.propTypes = { WorkspaceExport.defaultProps = { children: null, - classes: {}, container: null, open: false, t: key => key, diff --git a/src/components/WorkspaceImport.js b/src/components/WorkspaceImport.js index b0f2c34727..3a50c48287 100644 --- a/src/components/WorkspaceImport.js +++ b/src/components/WorkspaceImport.js @@ -1,13 +1,12 @@ import { Component } from 'react'; -import Dialog from '@material-ui/core/Dialog'; -import DialogTitle from '@material-ui/core/DialogTitle'; +import DialogTitle from '@mui/material/DialogTitle'; import PropTypes from 'prop-types'; import { DialogActions, TextField, - Typography, -} from '@material-ui/core'; -import Button from '@material-ui/core/Button'; +} from '@mui/material'; +import Button from '@mui/material/Button'; +import { WorkspaceDialog } from './WorkspaceDialog'; import ScrollIndicatedDialogContent from '../containers/ScrollIndicatedDialogContent'; /** @@ -65,7 +64,7 @@ export class WorkspaceImport extends Component { } = this.props; return ( - - - {t('importWorkspace')} + + {t('importWorkspace')} - - + ); } } diff --git a/src/components/WorkspaceMenu.js b/src/components/WorkspaceMenu.js index 65e01ba2ed..c6e9a191a6 100644 --- a/src/components/WorkspaceMenu.js +++ b/src/components/WorkspaceMenu.js @@ -1,7 +1,7 @@ import { Component } from 'react'; -import Menu from '@material-ui/core/Menu'; -import MenuItem from '@material-ui/core/MenuItem'; -import Typography from '@material-ui/core/Typography'; +import Menu from '@mui/material/Menu'; +import MenuItem from '@mui/material/MenuItem'; +import Typography from '@mui/material/Typography'; import PropTypes from 'prop-types'; import LanguageSettings from '../containers/LanguageSettings'; import { NestedMenu } from './NestedMenu'; @@ -71,8 +71,10 @@ export class WorkspaceMenu extends Component { t, showZoomControls, toggleZoomControls, - ...menuProps + ...rest } = this.props; + const menuProps = { ...rest }; + delete menuProps.tReady; const { changeTheme, diff --git a/src/components/WorkspaceMenuButton.js b/src/components/WorkspaceMenuButton.js index 71d8db245f..1ff0078651 100644 --- a/src/components/WorkspaceMenuButton.js +++ b/src/components/WorkspaceMenuButton.js @@ -1,7 +1,6 @@ import { Component } from 'react'; -import SettingsIcon from '@material-ui/icons/SettingsSharp'; +import SettingsIcon from '@mui/icons-material/SettingsSharp'; import PropTypes from 'prop-types'; -import classNames from 'classnames'; import WorkspaceMenu from '../containers/WorkspaceMenu'; import MiradorMenuButton from '../containers/MiradorMenuButton'; @@ -46,7 +45,7 @@ export class WorkspaceMenuButton extends Component { * @return */ render() { - const { classes, t } = this.props; + const { t } = this.props; const { anchorEl, open } = this.state; return ( @@ -55,7 +54,7 @@ export class WorkspaceMenuButton extends Component { aria-haspopup="true" aria-label={t('workspaceMenu')} aria-owns={open ? 'workspace-menu' : undefined} - className={classNames(classes.ctrlBtn, (open ? classes.ctrlBtnSelected : null))} + selected={open} id="menuBtn" onClick={this.handleMenuClick} > @@ -73,7 +72,6 @@ export class WorkspaceMenuButton extends Component { } WorkspaceMenuButton.propTypes = { - classes: PropTypes.objectOf(PropTypes.string).isRequired, t: PropTypes.func, }; diff --git a/src/components/WorkspaceMosaic.js b/src/components/WorkspaceMosaic.js index aad63fe501..0ac4faa572 100644 --- a/src/components/WorkspaceMosaic.js +++ b/src/components/WorkspaceMosaic.js @@ -1,5 +1,7 @@ import { Component } from 'react'; import PropTypes from 'prop-types'; +import { styled } from '@mui/material/styles'; +import GlobalStyles from '@mui/material/GlobalStyles'; import { DndContext } from 'react-dnd'; import { Mosaic, MosaicWindow, getLeaves, createBalancedTreeFromLeaves, @@ -10,6 +12,22 @@ import classNames from 'classnames'; import MosaicRenderPreview from '../containers/MosaicRenderPreview'; import Window from '../containers/Window'; import MosaicLayout from '../lib/MosaicLayout'; +import globalReactMosaicStyles from '../styles/react-mosaic-component'; + +const StyledMosaic = styled(Mosaic)({ + '& .mosaic-preview': { + boxShadow: 'none', + }, + '& .mosaic-tile': { + boxShadow: '0 1px 3px 0 rgba(0, 0, 0, .2), 0 1px 1px 0 rgba(0, 0, 0, .2), 0 2px 1px -1px rgba(0, 0, 0, .2)', + }, + '& .mosaic-window': { + boxShadow: 'none', + }, + '& .mosaic-window-toolbar': { + display: 'none !important', + }, +}); /** * Represents a work area that contains any number of windows @@ -143,18 +161,21 @@ export class WorkspaceMosaic extends Component { /** */ render() { - const { layout, classes } = this.props; + const { layout } = this.props; return ( {(ctx) => ( - + <> + + + )} ); @@ -162,7 +183,6 @@ export class WorkspaceMosaic extends Component { } WorkspaceMosaic.propTypes = { - classes: PropTypes.objectOf(PropTypes.string).isRequired, layout: PropTypes.oneOfType( [PropTypes.object, PropTypes.string], ), // eslint-disable-line react/forbid-prop-types diff --git a/src/components/WorkspaceOptionsButton.js b/src/components/WorkspaceOptionsButton.js index bfde64bfb7..ad549551f2 100644 --- a/src/components/WorkspaceOptionsButton.js +++ b/src/components/WorkspaceOptionsButton.js @@ -1,7 +1,6 @@ import { Component } from 'react'; import PropTypes from 'prop-types'; -import classNames from 'classnames'; -import MoreHorizontalIcon from '@material-ui/icons/MoreHorizSharp'; +import MoreHorizontalIcon from '@mui/icons-material/MoreHorizSharp'; import MiradorMenuButton from '../containers/MiradorMenuButton'; import WorkspaceOptionsMenu from '../containers/WorkspaceOptionsMenu'; @@ -46,21 +45,18 @@ export class WorkspaceOptionsButton extends Component { * Returns the rendered component */ render() { - const { classes, t } = this.props; + const { t } = this.props; const { anchorEl, open } = this.state; return ( <> - ({ + display: 'flex', + flexDirection: 'column', +})); /** */ export class WorkspaceSelectionDialog extends Component { @@ -42,80 +47,133 @@ export class WorkspaceSelectionDialog extends Component { */ render() { const { - classes, container, handleClose, open, children, t, workspaceType, + container, handleClose, open, children, t, workspaceType, } = this.props; return ( - - - {t('workspaceSelectionTitle')} + + {t('workspaceSelectionTitle')} {children} this.handleWorkspaceTypeChange('elastic')} selected={workspaceType === 'elastic'} value="elastic" > - + -
+ - {t('elastic')} + {t('elastic')} {t('elasticDescription')} -
+
this.handleWorkspaceTypeChange('mosaic')} selected={workspaceType === 'mosaic'} value="mosaic" > - + -
+ - {t('mosaic')} + {t('mosaic')} {t('mosaicDescription')} -
+
-
+ ); } } WorkspaceSelectionDialog.propTypes = { children: PropTypes.node, - classes: PropTypes.objectOf(PropTypes.string).isRequired, container: PropTypes.object, // eslint-disable-line react/forbid-prop-types handleClose: PropTypes.func.isRequired, open: PropTypes.bool, diff --git a/src/components/ZoomControls.js b/src/components/ZoomControls.js index 133c9950a8..19dc000229 100644 --- a/src/components/ZoomControls.js +++ b/src/components/ZoomControls.js @@ -1,10 +1,17 @@ import { Component } from 'react'; -import AddCircleIcon from '@material-ui/icons/AddCircleOutlineSharp'; -import RemoveCircleIcon from '@material-ui/icons/RemoveCircleOutlineSharp'; +import AddCircleIcon from '@mui/icons-material/AddCircleOutlineSharp'; +import RemoveCircleIcon from '@mui/icons-material/RemoveCircleOutlineSharp'; +import { styled } from '@mui/material/styles'; import PropTypes from 'prop-types'; import RestoreZoomIcon from './icons/RestoreZoomIcon'; import MiradorMenuButton from '../containers/MiradorMenuButton'; +const StyledZoomControlsWrapper = styled('div')({ + display: 'flex', + flexDirection: 'row', + justifyContent: 'center', +}); + /** */ export class ZoomControls extends Component { @@ -46,17 +53,11 @@ export class ZoomControls extends Component { */ render() { const { - displayDivider, showZoomControls, classes, t, zoomToWorld, + t, zoomToWorld, } = this.props; - if (!showZoomControls) { - return ( - <> - - ); - } return ( -
+ @@ -66,16 +67,12 @@ export class ZoomControls extends Component { zoomToWorld(false)}> - {displayDivider && } -
+ ); } } ZoomControls.propTypes = { - classes: PropTypes.objectOf(PropTypes.string).isRequired, - displayDivider: PropTypes.bool, - showZoomControls: PropTypes.bool, t: PropTypes.func, updateViewport: PropTypes.func, viewer: PropTypes.shape({ @@ -88,8 +85,6 @@ ZoomControls.propTypes = { }; ZoomControls.defaultProps = { - displayDivider: true, - showZoomControls: false, t: key => key, updateViewport: () => {}, viewer: {}, diff --git a/src/components/icons/BookViewIcon.js b/src/components/icons/BookViewIcon.js index a6668b1f30..d26b9fe3cc 100644 --- a/src/components/icons/BookViewIcon.js +++ b/src/components/icons/BookViewIcon.js @@ -1,4 +1,4 @@ -import SvgIcon from '@material-ui/core/SvgIcon'; +import SvgIcon from '@mui/material/SvgIcon'; /** * BookViewIcon ~ diff --git a/src/components/icons/CanvasIndexIcon.js b/src/components/icons/CanvasIndexIcon.js index 8d5af98b10..2bac4808d0 100644 --- a/src/components/icons/CanvasIndexIcon.js +++ b/src/components/icons/CanvasIndexIcon.js @@ -1,4 +1,4 @@ -import SvgIcon from '@material-ui/core/SvgIcon'; +import SvgIcon from '@mui/material/SvgIcon'; /** * Render the canvas index svg diff --git a/src/components/icons/GalleryViewIcon.js b/src/components/icons/GalleryViewIcon.js index 9a41003340..cccd9d2c71 100644 --- a/src/components/icons/GalleryViewIcon.js +++ b/src/components/icons/GalleryViewIcon.js @@ -1,4 +1,4 @@ -import SvgIcon from '@material-ui/core/SvgIcon'; +import SvgIcon from '@mui/material/SvgIcon'; /** * GalleryViewIcon ~ diff --git a/src/components/icons/MiradorIcon.js b/src/components/icons/MiradorIcon.js index 920256dd9b..43301fe4cb 100644 --- a/src/components/icons/MiradorIcon.js +++ b/src/components/icons/MiradorIcon.js @@ -1,4 +1,4 @@ -import SvgIcon from '@material-ui/core/SvgIcon'; +import SvgIcon from '@mui/material/SvgIcon'; /** * ThumbnailNavigationRightIcon ~ diff --git a/src/components/icons/RestoreZoomIcon.js b/src/components/icons/RestoreZoomIcon.js index 2005e6e89c..f1cf1e2d1e 100644 --- a/src/components/icons/RestoreZoomIcon.js +++ b/src/components/icons/RestoreZoomIcon.js @@ -1,4 +1,4 @@ -import SvgIcon from '@material-ui/core/SvgIcon'; +import SvgIcon from '@mui/material/SvgIcon'; /** * RestoreZoomIcon ~ diff --git a/src/components/icons/ThumbnailNavigationBottomIcon.js b/src/components/icons/ThumbnailNavigationBottomIcon.js index 5c7080a787..4ef2b95448 100644 --- a/src/components/icons/ThumbnailNavigationBottomIcon.js +++ b/src/components/icons/ThumbnailNavigationBottomIcon.js @@ -1,4 +1,4 @@ -import SvgIcon from '@material-ui/core/SvgIcon'; +import SvgIcon from '@mui/material/SvgIcon'; /** * ThumbnailNavigationBottomIcon ~ diff --git a/src/components/icons/ThumbnailNavigationRightIcon.js b/src/components/icons/ThumbnailNavigationRightIcon.js index 8f22b31d00..6690b01d28 100644 --- a/src/components/icons/ThumbnailNavigationRightIcon.js +++ b/src/components/icons/ThumbnailNavigationRightIcon.js @@ -1,4 +1,4 @@ -import SvgIcon from '@material-ui/core/SvgIcon'; +import SvgIcon from '@mui/material/SvgIcon'; /** * ThumbnailNavigationRightIcon ~ diff --git a/src/components/icons/WindowMaxIcon.js b/src/components/icons/WindowMaxIcon.js index 9590bbb180..3de34b6bf5 100644 --- a/src/components/icons/WindowMaxIcon.js +++ b/src/components/icons/WindowMaxIcon.js @@ -1,4 +1,4 @@ -import SvgIcon from '@material-ui/core/SvgIcon'; +import SvgIcon from '@mui/material/SvgIcon'; /** * WindowMaxIcon ~ diff --git a/src/components/icons/WindowMinIcon.js b/src/components/icons/WindowMinIcon.js index 7a2ef3be9c..3118b915f7 100644 --- a/src/components/icons/WindowMinIcon.js +++ b/src/components/icons/WindowMinIcon.js @@ -1,4 +1,4 @@ -import SvgIcon from '@material-ui/core/SvgIcon'; +import SvgIcon from '@mui/material/SvgIcon'; /** * WindowMinIcon ~ diff --git a/src/components/icons/WindowOptionsIcon.js b/src/components/icons/WindowOptionsIcon.js index 3e365c2930..e87dd28253 100644 --- a/src/components/icons/WindowOptionsIcon.js +++ b/src/components/icons/WindowOptionsIcon.js @@ -1,4 +1,4 @@ -import SvgIcon from '@material-ui/core/SvgIcon'; +import SvgIcon from '@mui/material/SvgIcon'; /** * WindowMinIcon ~ diff --git a/src/components/icons/WorkspaceTypeElasticIcon.js b/src/components/icons/WorkspaceTypeElasticIcon.js index c817330897..e1ee53918a 100644 --- a/src/components/icons/WorkspaceTypeElasticIcon.js +++ b/src/components/icons/WorkspaceTypeElasticIcon.js @@ -1,4 +1,4 @@ -import SvgIcon from '@material-ui/core/SvgIcon'; +import SvgIcon from '@mui/material/SvgIcon'; /** * ElasticWorkspaceIcon ~ diff --git a/src/components/icons/WorkspaceTypeMosaicIcon.js b/src/components/icons/WorkspaceTypeMosaicIcon.js index 5cdb0c34a1..c1724ee7e8 100644 --- a/src/components/icons/WorkspaceTypeMosaicIcon.js +++ b/src/components/icons/WorkspaceTypeMosaicIcon.js @@ -1,4 +1,4 @@ -import SvgIcon from '@material-ui/core/SvgIcon'; +import SvgIcon from '@mui/material/SvgIcon'; /** * WorkspaceTypeMosaicIcon ~ diff --git a/src/config/settings.js b/src/config/settings.js index 5aa08c8f99..caaebe2e15 100644 --- a/src/config/settings.js +++ b/src/config/settings.js @@ -12,7 +12,7 @@ export default { themes: { dark: { palette: { - type: 'dark', + mode: 'dark', primary: { main: '#4db6ac', }, @@ -28,13 +28,13 @@ export default { }, light: { palette: { - type: 'light', + mode: 'light', } } }, theme: { // Sets up a MaterialUI theme. See https://material-ui.com/customization/default-theme/ palette: { - type: 'light', + mode: 'light', primary: { main: '#1967d2', // Controls the color of the Add button and current window indicator }, @@ -61,6 +61,7 @@ export default { }, section_divider: 'rgba(0, 0, 0, 0.25)', annotations: { + chipBackground: '#e0e0e0', hidden: { globalAlpha: 0 }, default: { strokeStyle: '#00BFFF', globalAlpha: 1 }, hovered: { strokeStyle: '#BF00FF', globalAlpha: 1 }, @@ -167,51 +168,248 @@ export default { }, useNextVariants: true // set so that console deprecation warning is removed }, - overrides: { - MuiListSubheader: { - root: { - '&[role="presentation"]:focus': { - outline: 0, + components: { + MuiMenuItem: { + variants: [ + { + props: { variant: 'multiline' }, + style: { whiteSpace: 'normal' } }, - }, + ] }, - MuiTooltip: { // Overridden from https://github.com/mui-org/material-ui/blob/master/packages/material-ui/src/Tooltip/Tooltip.js#L40-L70 - tooltipPlacementLeft: { - ['@media (min-width:600px)']: { - margin: 0, + CompanionWindow: { + styleOverrides: { + closeButton: { + order: 4, }, - }, - tooltipPlacementRight: { - ['@media (min-width:600px)']: { - margin: 0, + contents: { + overflowY: 'auto', + wordBreak: 'break-word', }, - }, - tooltipPlacementTop: { - ['@media (min-width:600px)']: { - margin: 0, + controls: ({ ownerState }) => ({ + alignItems: 'center', + display: 'flex', + flexFlow: 'row wrap', + flexGrow: 1, + justifyContent: (ownerState?.position === 'bottom' || ownerState?.position === 'far-bottom') ? 'flex-end' : 'flex-start', + minHeight: 48, + order: 3 + }), + positionButton: { + marginLeft: -16, + order: -100, + width: 24, }, + resize: ({ ownerState }) => ({ + display: 'flex', + flexDirection: 'column', + minHeight: 50, + minWidth: (ownerState?.position === 'left') ? 235 : 100, + position: 'relative', + }), + root: ({ ownerState }) => ({ + boxShadow: 'none', + boxSizing: 'border-box', + display: 'flex', + flexDirection: 'column', + minHeight: 0, + ...(ownerState?.position === 'right' && { + borderLeft: '0.5px solid rgba(0, 0, 0, 0.125)' + }), + ...(ownerState?.position === 'left' && { + borderRight: '0.5px solid rgba(0, 0, 0, 0.125)' + }), + ...(ownerState?.position === 'bottom' && { + borderTop: '0.5px solid rgba(0, 0, 0, 0.125)' + }), + }), + title: ({ theme }) => ({ + ...theme.typography.subtitle1, + alignSelf: 'center', + flexGrow: 1, + width: 160 + }), + toolbar: ({ theme }) => ({ + alignItems: 'flex-start', + backgroundColor: theme.palette.shades.light, + flexWrap: 'wrap', + justifyContent: 'space-between', + minHeight: 'max-content', + paddingInlineStart: '1rem', + }), }, - tooltipPlacementBottom: { - ['@media (min-width:600px)']: { - margin: 0, + }, + CompanionWindowSection: { + styleOverrides: { + root: { + borderBlockEnd: '.5px solid rgba(0, 0, 0, 0.25)' }, }, }, - MuiTouchRipple: { - childPulsate: { - animation: 'none', + IIIFHtmlContent: { + styleOverrides: { + root: ({ theme }) => ({ + '& a': { + color: theme.palette.primary.main, + textDecoration: 'underline', + }, + }), }, - rippleVisible: { - animation: 'none', + }, + IIIFThumbnail: { + styleOverrides: { + root: ({ ownerState }) => ({ + ...(ownerState?.variant === 'inside' && { + display: 'inline-block', + height: 'inherit', + position: 'relative', + }), + }), + label: ({ ownerState }) => ({ + overflow: 'hidden', + textOverflow: 'ellipsis', + lineHeight: '1.5em', + wordBreak: 'break-word', + ...(ownerState?.variant === 'inside' && { + color: '#ffffff', + WebkitLineClamp: 1, + whiteSpace: 'nowrap', + }), + ...(ownerState?.variant === 'outside' && { + display: '-webkit-box', + maxHeight: '3em', + MozBoxOrient: 'vertical', + WebkitLineClamp: 2, + }), + ...(ownerState?.variant === 'inside' && { + background: 'linear-gradient(to top, rgba(0,0,0,0.7) 0%, rgba(0,0,0,0.3) 70%, rgba(0,0,0,0) 100%)', + bottom: '5px', + boxSizing: 'border-box', + left: '0px', + padding: '4px', + position: 'absolute', + width: '100%', + }), + }), + image: ({ ownerState }) => ({ + ...(ownerState?.border && { + border: '1px solid rgba(0, 0, 0, 0.125)', + }), + }) + } + }, + ThemeIcon: { + styleOverrides: { + icon: ({ ownerState }) => ({ + color: (ownerState?.value === 'dark' ? '#000000' : undefined) + }), }, }, - }, - props: { + MuiAccordion: { + variants: [ + { + props: { variant: 'compact' }, + style: { + '& .MuiAccordionSummary-root': { + minHeight: 'unset', + padding: 0, + }, + '& .MuiAccordionSummary-content': { + margin: 0, + }, + '& .MuiAccordionDetails-root': { + padding: 0, + }, + }, + }, + ], + }, + MuiButton: { + styleOverrides: { + inlineText: { + lineHeight: '1.5em', + padding: 0, + textAlign: 'inherit', + textTransform: 'none', + + }, + inlineTextSecondary: ({ theme }) => ({ + color: theme.palette.secondary.main, + }), + } + }, MuiButtonBase: { - disableTouchRipple: true, + defaultProps: { + disableTouchRipple: true, + }, + }, + MuiDialog: { + variants: [ + { + props: { variant: 'contained' }, + style: { + position: 'absolute', + '& .MuiBackdrop-root': { + position: 'absolute' + } + }, + } + ] + }, + MuiFab: { + styleOverrides: { + root: { + transition: 'none', + } + }, }, MuiLink: { - underline: 'always' + defaultProps: { + underline: 'always' + }, + }, + MuiListSubheader: { + styleOverrides: { + root: { + '&[role="presentation"]:focus': { + outline: 0, + }, + }, + }, + }, + MuiTooltip: { // Overridden from https://github.com/mui-org/material-ui/blob/master/packages/material-ui/src/Tooltip/Tooltip.js#L40-L70 + styleOverrides: { + tooltipPlacementLeft: { + ['@media (min-width:600px)']: { + margin: '0 !important', + }, + }, + tooltipPlacementRight: { + ['@media (min-width:600px)']: { + margin: '0 !important', + }, + }, + tooltipPlacementTop: { + ['@media (min-width:600px)']: { + margin: '0 !important', + }, + }, + tooltipPlacementBottom: { + ['@media (min-width:600px)']: { + margin: '0 !important', + }, + }, + }, + }, + MuiTouchRipple: { + styleOverrides: { + childPulsate: { + animation: 'none', + }, + rippleVisible: { + animation: 'none', + }, + }, }, }, }, diff --git a/src/containers/AppProviders.js b/src/containers/AppProviders.js index 22e8a3a06d..1ad1c6784d 100644 --- a/src/containers/AppProviders.js +++ b/src/containers/AppProviders.js @@ -11,7 +11,6 @@ import { AppProviders } from '../components/AppProviders'; */ const mapStateToProps = state => ( { - createGenerateClassNameOptions: getConfig(state).createGenerateClassNameOptions, language: getConfig(state).language, theme: getTheme(state), translations: getConfig(state).translations, diff --git a/src/containers/AttributionPanel.js b/src/containers/AttributionPanel.js index 8e0801444d..94ae930e0f 100644 --- a/src/containers/AttributionPanel.js +++ b/src/containers/AttributionPanel.js @@ -1,13 +1,12 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; -import { withPlugins } from '../extend/withPlugins'; import { getManifestLogo, getRequiredStatement, getRights, } from '../state/selectors'; +import { withPlugins } from '../extend/withPlugins'; import { AttributionPanel } from '../components/AttributionPanel'; /** @@ -21,29 +20,7 @@ const mapStateToProps = (state, { id, windowId }) => ({ rights: getRights(state, { windowId }), }); -/** - * - * @param theme - * @returns {label: {paddingLeft: number}}} - */ -const styles = theme => ({ - logo: { - maxWidth: '100%', - }, - placeholder: { - backgroundColor: theme.palette.grey[300], - }, - section: { - borderBottom: `.5px solid ${theme.palette.section_divider}`, - paddingBottom: theme.spacing(1), - paddingLeft: theme.spacing(2), - paddingRight: theme.spacing(1), - paddingTop: theme.spacing(2), - }, -}); - const enhance = compose( - withStyles(styles), withTranslation(), connect(mapStateToProps), withPlugins('AttributionPanel'), diff --git a/src/containers/AudioViewer.js b/src/containers/AudioViewer.js index e422c6d6b6..2bcd274096 100644 --- a/src/containers/AudioViewer.js +++ b/src/containers/AudioViewer.js @@ -1,7 +1,6 @@ import { connect } from 'react-redux'; import { compose } from 'redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core'; import { withPlugins } from '../extend/withPlugins'; import { AudioViewer } from '../components/AudioViewer'; import { getConfig, getVisibleCanvasAudioResources, getVisibleCanvasCaptions } from '../state/selectors'; @@ -15,21 +14,8 @@ const mapStateToProps = (state, { windowId }) => ( } ); -/** */ -const styles = () => ({ - audio: { - width: '100%', - }, - container: { - alignItems: 'center', - display: 'flex', - width: '100%', - }, -}); - const enhance = compose( withTranslation(), - withStyles(styles), connect(mapStateToProps, null), withPlugins('AudioViewer'), ); diff --git a/src/containers/CanvasAnnotations.js b/src/containers/CanvasAnnotations.js index 5bebeae788..5d420e745d 100644 --- a/src/containers/CanvasAnnotations.js +++ b/src/containers/CanvasAnnotations.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; import { withPlugins } from '../extend/withPlugins'; import * as actions from '../state/actions'; import { @@ -49,35 +48,8 @@ const mapDispatchToProps = { selectAnnotation: actions.selectAnnotation, }; -/** For withStlyes */ -const styles = theme => ({ - annotationListItem: { - '&$hovered': { - backgroundColor: theme.palette.action.hover, - }, - '&:hover,&:focus': { - backgroundColor: theme.palette.action.hover, - }, - borderBottom: `0.5px solid ${theme.palette.divider}`, - cursor: 'pointer', - whiteSpace: 'normal', - }, - chip: { - backgroundColor: theme.palette.background.paper, - marginRight: theme.spacing(0.5), - marginTop: theme.spacing(1), - }, - hovered: {}, - sectionHeading: { - paddingLeft: theme.spacing(2), - paddingRight: theme.spacing(1), - paddingTop: theme.spacing(2), - }, -}); - const enhance = compose( withTranslation(), - withStyles(styles), connect(mapStateToProps, mapDispatchToProps), withPlugins('CanvasAnnotations'), ); diff --git a/src/containers/CanvasLayers.js b/src/containers/CanvasLayers.js index 87041bed96..1b5baf2ffb 100644 --- a/src/containers/CanvasLayers.js +++ b/src/containers/CanvasLayers.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; import * as actions from '../state/actions'; import { getCanvasLabel, @@ -26,81 +25,8 @@ const mapDispatchToProps = { updateLayers: actions.updateLayers, }; -/** For withStlyes */ -const styles = theme => ({ - dragging: {}, - dragHandle: { - alignItems: 'center', - borderRight: `0.5px solid ${theme.palette.divider}`, - display: 'flex', - flex: 1, - flexDirection: 'row', - marginBottom: -1 * theme.spacing(2) + 0.5, - marginRight: theme.spacing(1), - marginTop: -1 * theme.spacing(2), - maxWidth: theme.spacing(3), - width: theme.spacing(3), - }, - image: { - borderBottom: `1px solid ${theme.palette.divider}`, - }, - label: { - paddingLeft: theme.spacing(1), - }, - list: { - paddingTop: 0, - }, - listItem: { - '& $dragHandle': { - '&:hover': { - backgroundColor: theme.palette.action.hover, - }, - backgroundColor: theme.palette.shades?.light, - }, - '&$dragging': { - '& $dragHandle, & $dragHandle:hover': { - backgroundColor: theme.palette.action.selected, - }, - backgroundColor: theme.palette.action.hover, - }, - alignItems: 'stretch', - borderBottom: `0.5px solid ${theme.palette.divider}`, - cursor: 'pointer', - paddingBottom: theme.spacing(2), - paddingRight: theme.spacing(1), - paddingTop: theme.spacing(2), - }, - opacityIcon: { - marginRight: theme.spacing(0.5), - }, - opacityInput: { - ...theme.typography.caption, - '&::-webkit-outer-spin-button,&::-webkit-inner-spin-button': { - '-webkit-appearance': 'none', - margin: 0, - }, - '-moz-appearance': 'textfield', - textAlign: 'right', - width: '3ch', - }, - sectionHeading: { - paddingLeft: theme.spacing(2), - paddingRight: theme.spacing(1), - paddingTop: theme.spacing(2), - }, - slider: { - marginLeft: theme.spacing(2), - marginRight: theme.spacing(2), - maxWidth: 150, - }, - thumbnail: { - minWidth: 50, - }, -}); - const enhance = compose( withTranslation(), - withStyles(styles), connect(mapStateToProps, mapDispatchToProps), ); diff --git a/src/containers/ChangeThemeDialog.js b/src/containers/ChangeThemeDialog.js index ade8c4eeeb..a473f22f1b 100644 --- a/src/containers/ChangeThemeDialog.js +++ b/src/containers/ChangeThemeDialog.js @@ -1,6 +1,5 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; -import { withStyles } from '@material-ui/core'; import { withTranslation } from 'react-i18next'; import { withPlugins } from '../extend/withPlugins'; import * as actions from '../state/actions'; @@ -26,31 +25,8 @@ const mapStateToProps = state => ({ themeIds: getThemeIds(state), }); -/** */ -const styles = theme => ({ - dark: { - color: '#000000', - }, - dialogContent: { - padding: 0, - }, - light: { - color: '#BDBDBD', - }, - listitem: { - '&:focus': { - backgroundColor: theme.palette.action.focus, - }, - '&:hover': { - backgroundColor: theme.palette.action.hover, - }, - cursor: 'pointer', - }, -}); - const enhance = compose( withTranslation(), - withStyles(styles), connect(mapStateToProps, mapDispatchToProps), withPlugins('ChangeThemeDialog'), ); diff --git a/src/containers/CollapsibleSection.js b/src/containers/CollapsibleSection.js index 3daa9258b1..9e32b49c24 100644 --- a/src/containers/CollapsibleSection.js +++ b/src/containers/CollapsibleSection.js @@ -1,24 +1,9 @@ import { compose } from 'redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; import { CollapsibleSection } from '../components/CollapsibleSection'; -const styles = { - button: { - padding: 0, - }, - container: { - display: 'flex', - justifyContent: 'space-between', - }, - heading: { - cursor: 'pointer', - }, -}; - const enhance = compose( withTranslation(), - withStyles(styles), ); export default enhance(CollapsibleSection); diff --git a/src/containers/CollectionDialog.js b/src/containers/CollectionDialog.js index 1920dee3cd..02297bccbc 100644 --- a/src/containers/CollectionDialog.js +++ b/src/containers/CollectionDialog.js @@ -1,6 +1,5 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; -import { withStyles } from '@material-ui/core'; import { withTranslation } from 'react-i18next'; import { withPlugins } from '../extend/withPlugins'; import * as actions from '../state/actions'; @@ -48,44 +47,8 @@ const mapStateToProps = (state, { windowId }) => { }; }; -/** */ -const styles = theme => ({ - collectionFilter: { - padding: '16px', - paddingTop: 0, - }, - collectionItem: { - whiteSpace: 'normal', - }, - collectionMetadata: { - padding: '16px', - }, - dark: { - color: '#000000', - }, - dialog: { - position: 'absolute !important', - }, - dialogContent: { - padding: theme.spacing(1), - }, - light: { - color: theme.palette.grey[400], - }, - listitem: { - '&:focus': { - backgroundColor: theme.palette.action.focus, - }, - '&:hover': { - backgroundColor: theme.palette.action.hover, - }, - cursor: 'pointer', - }, -}); - const enhance = compose( withTranslation(), - withStyles(styles), withWorkspaceContext, connect(mapStateToProps, mapDispatchToProps), withPlugins('CollectionDialog'), diff --git a/src/containers/CompanionArea.js b/src/containers/CompanionArea.js index 8ff8b9cb62..f403a90849 100644 --- a/src/containers/CompanionArea.js +++ b/src/containers/CompanionArea.js @@ -1,6 +1,5 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; -import { withStyles } from '@material-ui/core'; import { withTranslation } from 'react-i18next'; import { withPlugins } from '../extend/withPlugins'; import { @@ -21,43 +20,8 @@ const mapDispatchToProps = ({ setCompanionAreaOpen: actions.setCompanionAreaOpen, }); -/** */ -const styles = theme => ({ - horizontal: { - flexDirection: 'column', - width: '100%', - }, - left: { - minWidth: 235, - }, - root: { - display: 'flex', - minHeight: 0, - position: 'relative', - zIndex: theme.zIndex.appBar - 2, - }, - toggle: { - backgroundColor: theme.palette.background.paper, - border: `1px solid ${theme.palette.shades?.dark}`, - borderRadius: 0, - height: '48px', - left: '100%', - marginTop: '1rem', - padding: 2, - position: 'absolute', - width: '23px', - zIndex: theme.zIndex.drawer, - }, - toggleButton: { - marginBottom: 12, - marginTop: 12, - padding: 0, - }, -}); - const enhance = compose( withTranslation(), - withStyles(styles), connect(mapStateToProps, mapDispatchToProps), withPlugins('CompanionArea'), ); diff --git a/src/containers/CompanionWindow.js b/src/containers/CompanionWindow.js index 9def7a3c3c..64a1806440 100644 --- a/src/containers/CompanionWindow.js +++ b/src/containers/CompanionWindow.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core'; import { withSize } from 'react-sizeme'; import { withPlugins } from '../extend/withPlugins'; import { withRef } from '../extend/withRef'; @@ -45,95 +44,9 @@ const mapDispatchToProps = (dispatch, { windowId, id }) => ({ ), }); -/** - * - * @param theme - * @returns {{closeButton: {top: number, position: string, right: number}, - * root: {overflowY: string, width: string}}} - */ -const styles = theme => ({ - closeButton: { - order: 4, - }, - 'companionWindow-bottom': { - borderTop: `0.5px solid ${theme.palette.divider}`, - }, - 'companionWindow-left': { - borderRight: `0.5px solid ${theme.palette.divider}`, - }, - 'companionWindow-right': { - borderLeft: `0.5px solid ${theme.palette.divider}`, - }, - companionWindowHeader: { - flexWrap: 'wrap', - }, - companionWindowTitleControls: { - flexGrow: 1, - order: 1000, - }, - companionWindowTitleControlsBottom: { - order: 'unset', - }, - content: { - overflowY: 'auto', - wordBreak: 'break-word', - }, - horizontal: { - }, - positionButton: { - marginLeft: -16, - order: -100, - width: 24, - }, - rnd: { - display: 'flex', - flexDirection: 'column', - minHeight: 0, - }, - root: { - boxShadow: 'none', - boxSizing: 'border-box', - display: 'flex', - flexDirection: 'column', - minHeight: 0, - }, - small: {}, - titleControls: { - alignItems: 'center', - display: 'flex', - flexFlow: 'row wrap', - minHeight: 48, - order: 3, - }, - toolbar: { - '&$small': { - '& $closeButton': { - order: 'unset', - }, - '& $titleControls': { - order: 'unset', - }, - }, - alignItems: 'flex-start', - background: theme.palette.shades?.light, - justifyContent: 'space-between', - minHeight: 'max-content', - paddingLeft: theme.spacing(2), - }, - vertical: { - }, - windowSideBarTitle: { - ...theme.typography.subtitle1, - alignSelf: 'center', - flexGrow: 1, - width: 160, - }, -}); - const enhance = compose( withRef(), withTranslation(), - withStyles(styles), withSize(), connect(mapStateToProps, mapDispatchToProps), withPlugins('CompanionWindow'), diff --git a/src/containers/CustomPanel.js b/src/containers/CustomPanel.js index 493ad14633..3f83547018 100644 --- a/src/containers/CustomPanel.js +++ b/src/containers/CustomPanel.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; import { withPlugins } from '../extend/withPlugins'; import { CustomPanel } from '../components/CustomPanel'; @@ -11,17 +10,8 @@ import { CustomPanel } from '../components/CustomPanel'; const mapStateToProps = (state, { id, windowId }) => ({ }); -/** - * - * @param theme - * @returns {label: {paddingLeft: number}}} - */ -const styles = theme => ({ -}); - const enhance = compose( withTranslation(), - withStyles(styles), connect(mapStateToProps), withPlugins('CustomPanel'), ); diff --git a/src/containers/ErrorContent.js b/src/containers/ErrorContent.js index ce3089f9d0..8544356209 100644 --- a/src/containers/ErrorContent.js +++ b/src/containers/ErrorContent.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; import { withPlugins } from '../extend/withPlugins'; import { ErrorContent } from '../components/ErrorContent'; import { @@ -23,29 +22,8 @@ const mapStateToProps = (state, { companionWindowId, windowId }) => ({ showJsError: getConfig(state).window.showJsError, }); -/** - * @param theme - * @returns {{typographyBody: {flexGrow: number, fontSize: number|string}, - * windowTopBarStyle: {minHeight: number, paddingLeft: number, backgroundColor: string}}} - */ -const styles = theme => ({ - alert: { - backgroundColor: theme.palette.error.main, - color: '#fff', - fontWeight: theme.typography.fontWeightMedium, - }, - details: { - '& pre': { - height: '100px', - overflowY: 'scroll', - }, - flexDirection: 'column', - }, -}); - const enhance = compose( withTranslation(), - withStyles(styles), connect(mapStateToProps), withPlugins('ErrorContent'), ); diff --git a/src/containers/GalleryView.js b/src/containers/GalleryView.js index 6b916d755a..9c54be5a4b 100644 --- a/src/containers/GalleryView.js +++ b/src/containers/GalleryView.js @@ -1,6 +1,5 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; -import { withStyles } from '@material-ui/core/styles'; import { withPlugins } from '../extend/withPlugins'; import { GalleryView } from '../components/GalleryView'; import { getCanvases, getSequenceViewingDirection } from '../state/selectors'; @@ -17,24 +16,7 @@ const mapStateToProps = (state, { windowId }) => ( } ); -/** - * Styles to be passed to the withStyles HOC - */ -const styles = theme => ({ - galleryContainer: { - alignItems: 'flex-start', - display: 'flex', - flexDirection: 'row', - flexWrap: 'wrap', - overflowX: 'hidden', - overflowY: 'scroll', - padding: '50px 0 50px 20px', - width: '100%', - }, -}); - const enhance = compose( - withStyles(styles), connect(mapStateToProps), withPlugins('GalleryView'), // further HOC go here diff --git a/src/containers/GalleryViewThumbnail.js b/src/containers/GalleryViewThumbnail.js index 66d6a94a62..c0306777ce 100644 --- a/src/containers/GalleryViewThumbnail.js +++ b/src/containers/GalleryViewThumbnail.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import flatten from 'lodash/flatten'; -import { withStyles } from '@material-ui/core/styles'; import * as actions from '../state/actions'; import { GalleryViewThumbnail } from '../components/GalleryViewThumbnail'; import { @@ -12,62 +11,6 @@ import { getCompanionWindowsForContent, } from '../state/selectors'; -/** - * Styles to be passed to the withStyles HOC - */ -const styles = theme => ({ - annotationIcon: { - height: '1rem', - width: '1rem', - }, - annotationsChip: { - ...theme.typography.caption, - }, - avatar: { - backgroundColor: 'transparent', - }, - chips: { - opacity: 0.875, - position: 'absolute', - right: 0, - textAlign: 'right', - top: 0, - }, - galleryViewItem: { - '&$hasAnnotations': { - border: `2px solid ${theme.palette.action.selected}`, - }, - '&$selected,&$selected$hasAnnotations': { - border: `2px solid ${theme.palette.primary.main}`, - }, - '&:focus': { - outline: 'none', - }, - '&:hover': { - backgroundColor: theme.palette.action.hover, - }, - border: '2px solid transparent', - cursor: 'pointer', - display: 'inline-block', - margin: `${theme.spacing(1)}px ${theme.spacing(0.5)}px`, - maxHeight: props => props.config.height + 45, - minWidth: '60px', - overflow: 'hidden', - padding: theme.spacing(0.5), - position: 'relative', - width: 'min-content', - }, - hasAnnotations: {}, - searchChip: { - ...theme.typography.caption, - '&$selected $avatar': { - backgroundColor: theme.palette.highlights?.primary, - }, - marginTop: 2, - }, - selected: {}, -}); - /** */ const mapStateToProps = (state, { canvas, windowId }) => { const currentCanvas = getCurrentCanvas(state, { windowId }); @@ -115,7 +58,6 @@ const mapDispatchToProps = (dispatch, { canvas, id, windowId }) => ({ const enhance = compose( connect(mapStateToProps, mapDispatchToProps), - withStyles(styles), // further HOC go here ); diff --git a/src/containers/IIIFThumbnail.js b/src/containers/IIIFThumbnail.js index c596b508cd..6631a8deb3 100644 --- a/src/containers/IIIFThumbnail.js +++ b/src/containers/IIIFThumbnail.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; import { withPlugins } from '../extend/withPlugins'; import { getConfig, @@ -16,51 +15,7 @@ const mapStateToProps = (state) => ({ thumbnailsConfig: getConfig(state).thumbnails, }); -/** - * Styles for withStyles HOC - */ -const styles = theme => ({ - caption: { - lineHeight: '1.5em', - wordBreak: 'break-word', - }, - image: {}, - insideCaption: { - color: '#ffffff', - lineClamp: '1', - whiteSpace: 'nowrap', - }, - insideLabel: { - background: 'linear-gradient(to top, rgba(0,0,0,0.7) 0%, rgba(0,0,0,0.3) 70%, rgba(0,0,0,0) 100%)', - bottom: '5px', - boxSizing: 'border-box', - left: '0px', - padding: '4px', - position: 'absolute', - width: '100%', - }, - insideRoot: { - display: 'inline-block', - height: 'inherit', - position: 'relative', - }, - label: { - overflow: 'hidden', - textOverflow: 'ellipsis', - }, - outsideCaption: { - boxOrient: 'vertical', - display: '-webkit-box', - lineClamp: '2', - maxHeight: '3em', - }, - outsideLabel: {}, - outsideRoot: {}, - root: {}, -}); - const enhance = compose( - withStyles(styles), withTranslation(), connect(mapStateToProps), withPlugins('IIIFThumbnail'), diff --git a/src/containers/LayersPanel.js b/src/containers/LayersPanel.js index 16a1a9b01b..2d7352f4eb 100644 --- a/src/containers/LayersPanel.js +++ b/src/containers/LayersPanel.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; import { withPlugins } from '../extend/withPlugins'; import { LayersPanel } from '../components/LayersPanel'; import { @@ -15,17 +14,8 @@ const mapStateToProps = (state, { id, windowId }) => ({ canvasIds: getVisibleCanvasIds(state, { windowId }), }); -/** - * - * @param theme - * @returns {label: {paddingLeft: number}}} - */ -const styles = theme => ({ -}); - const enhance = compose( withTranslation(), - withStyles(styles), connect(mapStateToProps), withPlugins('LayersPanel'), ); diff --git a/src/containers/LocalePicker.js b/src/containers/LocalePicker.js index 509fef4e36..2edb53b784 100644 --- a/src/containers/LocalePicker.js +++ b/src/containers/LocalePicker.js @@ -1,27 +1,9 @@ import { compose } from 'redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; import { LocalePicker } from '../components/LocalePicker'; -/** - * - * @param theme - * @returns {label: {paddingLeft: number}}} - */ -const styles = theme => ({ - select: { - '&:focus': { - backgroundColor: theme.palette.background.paper, - }, - }, - selectEmpty: { - backgroundColor: theme.palette.background.paper, - }, -}); - const enhance = compose( withTranslation(), - withStyles(styles), ); export default enhance(LocalePicker); diff --git a/src/containers/ManifestForm.js b/src/containers/ManifestForm.js index e64b68d68c..02a3262144 100644 --- a/src/containers/ManifestForm.js +++ b/src/containers/ManifestForm.js @@ -1,7 +1,6 @@ import { connect } from 'react-redux'; import { compose } from 'redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core'; import { withPlugins } from '../extend/withPlugins'; import * as actions from '../state/actions'; import { ManifestForm } from '../components/ManifestForm'; @@ -12,24 +11,8 @@ import { ManifestForm } from '../components/ManifestForm'; * @private */ const mapDispatchToProps = { addResource: actions.addResource }; -/** - * - * @param theme - */ -const styles = theme => ({ - buttons: { - textAlign: 'right', - [theme.breakpoints.up('sm')]: { - textAlign: 'inherit', - }, - }, - input: { - ...theme.typography.body1, - }, -}); const enhance = compose( - withStyles(styles), withTranslation(), connect(null, mapDispatchToProps), withPlugins('ManifestForm'), diff --git a/src/containers/ManifestListItem.js b/src/containers/ManifestListItem.js index 6553a9cfa2..55f5c43e90 100644 --- a/src/containers/ManifestListItem.js +++ b/src/containers/ManifestListItem.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core'; import { withPlugins } from '../extend/withPlugins'; import { getManifest, @@ -50,56 +49,8 @@ const mapDispatchToProps = { fetchManifest: actions.fetchManifest, }; -/** - * - * @param theme - * @returns {{root: {}, label: {textAlign: string, textTransform: string}}} - */ -const styles = theme => ({ - active: {}, - buttonGrid: { - }, - label: { - textAlign: 'left', - textTransform: 'initial', - }, - logo: { - height: '2.5rem', - maxWidth: '100%', - objectFit: 'contain', - paddingRight: 8, - }, - placeholder: { - backgroundColor: theme.palette.grey[300], - }, - root: { - '&$active': { - borderLeft: `4px solid ${theme.palette.primary.main}`, - }, - '&:hover,&:focus-within': { - '&$active': { - borderLeft: `4px solid ${theme.palette.primary.main}`, - }, - backgroundColor: theme.palette.action.hover, - borderLeft: `4px solid ${theme.palette.action.hover}`, - }, - borderLeft: '4px solid transparent', - paddingLeft: theme.spacing(2), - paddingRight: theme.spacing(2), - [theme.breakpoints.up('sm')]: { - paddingLeft: theme.spacing(3), - paddingRight: theme.spacing(3), - }, - }, - thumbnail: { - maxWidth: '100%', - objectFit: 'contain', - }, -}); - const enhance = compose( withTranslation(), - withStyles(styles), connect(mapStateToProps, mapDispatchToProps), withPlugins('ManifestListItem'), ); diff --git a/src/containers/ManifestListItemError.js b/src/containers/ManifestListItemError.js index 001d98750b..40d9f5f14d 100644 --- a/src/containers/ManifestListItemError.js +++ b/src/containers/ManifestListItemError.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; import { withPlugins } from '../extend/withPlugins'; import { fetchManifest, removeResource } from '../state/actions'; import { ManifestListItemError } from '../components/ManifestListItemError'; @@ -12,26 +11,8 @@ const mapDispatchToProps = { onTryAgainClick: fetchManifest, }; -/** - * - * @param theme - * @returns {{manifestIdText: {wordBreak: string}, - * errorIcon: {color: string, width: string, height: string}}} - */ -const styles = theme => ({ - errorIcon: { - color: theme.palette.error.main, - height: '2rem', - width: '2rem', - }, - manifestIdText: { - wordBreak: 'break-all', - }, -}); - const enhance = compose( withTranslation(), - withStyles(styles), connect(null, mapDispatchToProps), withPlugins('ManifestListItemError'), ); diff --git a/src/containers/ManifestRelatedLinks.js b/src/containers/ManifestRelatedLinks.js index 6bcc356778..a3f1edf9e0 100644 --- a/src/containers/ManifestRelatedLinks.js +++ b/src/containers/ManifestRelatedLinks.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; import { withPlugins } from '../extend/withPlugins'; import { getManifestHomepage, @@ -25,17 +24,7 @@ const mapStateToProps = (state, { id, windowId }) => ({ seeAlso: getManifestSeeAlso(state, { windowId }), }); -const styles = { - labelValueMetadata: { - '& dd': { - marginBottom: '.5em', - marginLeft: '0', - }, - }, -}; - const enhance = compose( - withStyles(styles), withTranslation(), connect(mapStateToProps), withPlugins('ManifestRelatedLinks'), diff --git a/src/containers/MinimalWindow.js b/src/containers/MinimalWindow.js index 5ed8aec777..d4e57cb75b 100644 --- a/src/containers/MinimalWindow.js +++ b/src/containers/MinimalWindow.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; import { withPlugins } from '../extend/withPlugins'; import * as actions from '../state/actions'; import { MinimalWindow } from '../components/MinimalWindow'; @@ -22,42 +21,8 @@ const mapDispatchToProps = (dispatch, { windowId }) => ({ removeWindow: () => dispatch(actions.removeWindow(windowId)), }); -/** - * @param theme - * @returns {{typographyBody: {flexGrow: number, fontSize: number|string}, - * windowTopBarStyle: {minHeight: number, paddingLeft: number, backgroundColor: string}}} - */ -const styles = theme => ({ - button: { - marginLeft: 'auto', - }, - title: { - ...theme.typography.h6, - flexGrow: 1, - paddingLeft: theme.spacing(0.5), - }, - window: { - backgroundColor: theme.palette.shades?.dark, - borderRadius: 0, - display: 'flex', - flexDirection: 'column', - height: '100%', - minHeight: 0, - overflow: 'hidden', - width: '100%', - }, - windowTopBarStyle: { - backgroundColor: theme.palette.shades?.main, - borderTop: '2px solid transparent', - minHeight: 32, - paddingLeft: theme.spacing(0.5), - paddingRight: theme.spacing(0.5), - }, -}); - const enhance = compose( withTranslation(), - withStyles(styles), connect(mapStateToProps, mapDispatchToProps), withPlugins('MinimalWindow'), ); diff --git a/src/containers/MosaicRenderPreview.js b/src/containers/MosaicRenderPreview.js index 0103bab9c5..149861f89f 100644 --- a/src/containers/MosaicRenderPreview.js +++ b/src/containers/MosaicRenderPreview.js @@ -1,6 +1,5 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; -import { withStyles } from '@material-ui/core/styles'; import { withTranslation } from 'react-i18next'; import { withPlugins } from '../extend/withPlugins'; import { getManifestTitle } from '../state/selectors'; @@ -13,18 +12,7 @@ const mapStateToProps = (state, { windowId }) => ( } ); -/** - * - * @param theme - */ -const styles = theme => ({ - preview: { - ...theme.typography.h4, - }, -}); - const enhance = compose( - withStyles(styles), withTranslation(), connect(mapStateToProps, null), withPlugins('MosaicRenderPreview'), diff --git a/src/containers/OpenSeadragonViewer.js b/src/containers/OpenSeadragonViewer.js index b5c59dff19..adc01cf90c 100644 --- a/src/containers/OpenSeadragonViewer.js +++ b/src/containers/OpenSeadragonViewer.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; import flatten from 'lodash/flatten'; import { withPlugins } from '../extend/withPlugins'; import { OpenSeadragonViewer } from '../components/OpenSeadragonViewer'; @@ -55,16 +54,7 @@ const mapDispatchToProps = { updateViewport: actions.updateViewport, }; -const styles = { - osdContainer: { - cursor: 'grab', - flex: 1, - position: 'relative', - }, -}; - const enhance = compose( - withStyles(styles), withTranslation(), connect(mapStateToProps, mapDispatchToProps), withPlugins('OpenSeadragonViewer'), diff --git a/src/containers/PrimaryWindow.js b/src/containers/PrimaryWindow.js index 336894235f..1895e80539 100644 --- a/src/containers/PrimaryWindow.js +++ b/src/containers/PrimaryWindow.js @@ -1,6 +1,5 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; -import { withStyles } from '@material-ui/core/styles'; import { withPlugins } from '../extend/withPlugins'; import { getManifestoInstance, getVisibleCanvasAudioResources, getVisibleCanvasVideoResources, getWindow, @@ -18,16 +17,7 @@ const mapStateToProps = (state, { windowId }) => { }; }; -const styles = { - primaryWindow: { - display: 'flex', - flex: 1, - position: 'relative', - }, -}; - const enhance = compose( - withStyles(styles), connect(mapStateToProps, null), withPlugins('PrimaryWindow'), ); diff --git a/src/containers/SanitizedHtml.js b/src/containers/SanitizedHtml.js index 932bfa0c0a..b6771d0d9e 100644 --- a/src/containers/SanitizedHtml.js +++ b/src/containers/SanitizedHtml.js @@ -1,16 +1,3 @@ -import { withStyles } from '@material-ui/core/styles'; import { SanitizedHtml } from '../components/SanitizedHtml'; -/** - * Styles for withStyles HOC - */ -const styles = theme => ({ - root: { - '& a': { - color: theme.palette.primary.main, - textDecoration: 'underline', - }, - }, -}); - -export default withStyles(styles)(SanitizedHtml); +export default SanitizedHtml; diff --git a/src/containers/ScrollIndicatedDialogContent.js b/src/containers/ScrollIndicatedDialogContent.js index 66ec29e1ab..aad0df3d57 100644 --- a/src/containers/ScrollIndicatedDialogContent.js +++ b/src/containers/ScrollIndicatedDialogContent.js @@ -1,29 +1,3 @@ -import { withStyles } from '@material-ui/core/styles'; import { ScrollIndicatedDialogContent } from '../components/ScrollIndicatedDialogContent'; -/** - * Styles for the withStyles HOC - */ -const styles = theme => ({ - shadowScrollDialog: { - /* Shadow covers */ - background: `linear-gradient(${theme.palette.background.paper} 30%, rgba(255, 255, 255, 0)), ` - + `linear-gradient(rgba(255, 255, 255, 0), ${theme.palette.background.paper} 70%) 0 100%, ` - // Shaddows - + 'radial-gradient(50% 0, farthest-side, rgba(0, 0, 0, .2), rgba(0, 0, 0, 0)), ' - + 'radial-gradient(50% 100%, farthest-side, rgba(0, 0, 0, .2), rgba(0, 0, 0, 0)) 0 100%,', - /* Shadow covers */ - background: `linear-gradient(${theme.palette.background.paper} 30%, rgba(255, 255, 255, 0)), ` // eslint-disable-line no-dupe-keys - + `linear-gradient(rgba(255, 255, 255, 0), ${theme.palette.background.paper} 70%) 0 100%, ` - // Shaddows - + 'radial-gradient(farthest-side at 50% 0, rgba(0, 0, 0, .2), rgba(0, 0, 0, 0)), ' - + 'radial-gradient(farthest-side at 50% 100%, rgba(0, 0, 0, .2), rgba(0, 0, 0, 0)) 0 100%;', - - backgroundAttachment: 'local, local, scroll, scroll', - backgroundRepeat: 'no-repeat', - backgroundSize: '100% 40px, 100% 40px, 100% 14px, 100% 14px', - overflowY: 'auto', - }, -}); - -export default withStyles(styles)(ScrollIndicatedDialogContent); +export default ScrollIndicatedDialogContent; diff --git a/src/containers/SearchHit.js b/src/containers/SearchHit.js index 009f44903e..7e67df152f 100644 --- a/src/containers/SearchHit.js +++ b/src/containers/SearchHit.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; import { withPlugins } from '../extend/withPlugins'; import { SearchHit } from '../components/SearchHit'; import * as actions from '../state/actions'; @@ -70,60 +69,8 @@ const mapDispatchToProps = (dispatch, { windowId }) => ({ ), }); -/** */ -const styles = theme => ({ - adjacent: {}, - focused: {}, - hitCounter: { - ...theme.typography.subtitle2, - backgroundColor: theme.palette.hitCounter?.default, - height: 30, - marginRight: theme.spacing(1), - verticalAlign: 'inherit', - }, - inlineButton: { - '& span': { - lineHeight: '1.5em', - }, - margin: 0, - padding: 0, - textTransform: 'none', - }, - listItem: { - '&$adjacent': { - '& $hitCounter': { - backgroundColor: theme.palette.highlights?.secondary, - }, - '&$windowSelected': { - '& $hitCounter': { - backgroundColor: theme.palette.highlights?.primary, - }, - }, - }, - '&$windowSelected': { - '& $hitCounter': { - backgroundColor: theme.palette.highlights?.primary, - }, - '&$focused': { - '&:hover': { - backgroundColor: 'inherit', - }, - backgroundColor: 'inherit', - }, - }, - borderBottom: `0.5px solid ${theme.palette.divider}`, - paddingRight: 8, - }, - selected: {}, - subtitle: { - marginBottom: theme.spacing(1.5), - }, - windowSelected: {}, -}); - const enhance = compose( connect(mapStateToProps, mapDispatchToProps), - withStyles(styles), withTranslation(), withPlugins('SearchHit'), ); diff --git a/src/containers/SearchPanel.js b/src/containers/SearchPanel.js index 64461b48c8..5a5f4aa408 100644 --- a/src/containers/SearchPanel.js +++ b/src/containers/SearchPanel.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; import * as actions from '../state/actions'; import { withPlugins } from '../extend/withPlugins'; import { SearchPanel } from '../components/SearchPanel'; @@ -22,27 +21,8 @@ const mapDispatchToProps = (dispatch, props) => ({ removeSearch: () => dispatch(actions.removeSearch(props.windowId, props.id)), }); -/** -* Styles for withStyles HOC -*/ -const styles = theme => ({ - clearChip: { - marginLeft: theme.spacing(1), - }, - inlineButton: { - '& span': { - lineHeight: '1.5em', - }, - margin: theme.spacing(2), - padding: 0, - textAlign: 'inherit', - textTransform: 'none', - }, -}); - const enhance = compose( connect(mapStateToProps, mapDispatchToProps), - withStyles(styles), withTranslation(), withPlugins('SearchPanel'), ); diff --git a/src/containers/SearchPanelControls.js b/src/containers/SearchPanelControls.js index e81d46a4f3..e2f718ae07 100644 --- a/src/containers/SearchPanelControls.js +++ b/src/containers/SearchPanelControls.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; import { withPlugins } from '../extend/withPlugins'; import { SearchPanelControls } from '../components/SearchPanelControls'; import * as actions from '../state/actions'; @@ -33,26 +32,8 @@ const mapDispatchToProps = { fetchSearch: actions.fetchSearch, }; -/** */ -const styles = theme => ({ - endAdornment: { - position: 'absolute', - right: 0, - }, - form: { - paddingBottom: theme.spacing(1), - paddingRight: theme.spacing(1.5), - width: '100%', - }, - searchProgress: { - position: 'absolute', - right: 0, - }, -}); - const enhance = compose( connect(mapStateToProps, mapDispatchToProps), - withStyles(styles), withTranslation(), withPlugins('SearchPanelControls'), ); diff --git a/src/containers/SearchPanelNavigation.js b/src/containers/SearchPanelNavigation.js index 614b241920..83b421ac3b 100644 --- a/src/containers/SearchPanelNavigation.js +++ b/src/containers/SearchPanelNavigation.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; import { withPlugins } from '../extend/withPlugins'; import { SearchPanelNavigation } from '../components/SearchPanelNavigation'; import * as actions from '../state/actions'; @@ -37,17 +36,8 @@ const mapDispatchToProps = (dispatch, { windowId }) => ({ ), }); -/** */ -const styles = theme => ({ - body2: { - marginLeft: '-16px', - width: '100%', - }, -}); - const enhance = compose( connect(mapStateToProps, mapDispatchToProps), - withStyles(styles), withTranslation(), withPlugins('SearchPanelNavigation'), ); diff --git a/src/containers/SearchResults.js b/src/containers/SearchResults.js index 15e660d99a..0684e36b8e 100644 --- a/src/containers/SearchResults.js +++ b/src/containers/SearchResults.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; import { withPlugins } from '../extend/withPlugins'; import { SearchResults } from '../components/SearchResults'; import * as actions from '../state/actions'; @@ -33,26 +32,8 @@ const mapDispatchToProps = { fetchSearch: actions.fetchSearch, }; -/** */ -const styles = theme => ({ - moreButton: { - width: '100%', - }, - navigation: { - textTransform: 'none', - }, - noResults: { - ...theme.typography.h6, - padding: theme.spacing(2), - }, - toggleFocus: { - ...theme.typography.subtitle1, - }, -}); - const enhance = compose( connect(mapStateToProps, mapDispatchToProps), - withStyles(styles), withTranslation(), withPlugins('SearchResults'), ); diff --git a/src/containers/SelectCollection.js b/src/containers/SelectCollection.js index 446c32711f..e711f53708 100644 --- a/src/containers/SelectCollection.js +++ b/src/containers/SelectCollection.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; import * as actions from '../state/actions'; import { withPlugins } from '../extend/withPlugins'; import { @@ -22,13 +21,9 @@ const mapStateToProps = (state, { windowId }) => { const mapDispatchToProps = { showCollectionDialog: actions.showCollectionDialog, }; -/** */ -const styles = (theme) => ({ -}); const enhance = compose( withTranslation(), - withStyles(styles), connect(mapStateToProps, mapDispatchToProps), withPlugins('SelectCollection'), ); diff --git a/src/containers/SidebarIndexItem.js b/src/containers/SidebarIndexItem.js index e58afff81c..bc8a19001e 100644 --- a/src/containers/SidebarIndexItem.js +++ b/src/containers/SidebarIndexItem.js @@ -1,21 +1,10 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; import { withPlugins } from '../extend/withPlugins'; import { SidebarIndexItem } from '../components/SidebarIndexItem'; -/** - * Styles for withStyles HOC - */ -const styles = theme => ({ - label: { - paddingLeft: theme.spacing(1), - }, -}); - const enhance = compose( - withStyles(styles), withTranslation(), connect(null, null), withPlugins('SidebarIndexItem'), diff --git a/src/containers/SidebarIndexList.js b/src/containers/SidebarIndexList.js index 866e7d61d7..de46a88939 100644 --- a/src/containers/SidebarIndexList.js +++ b/src/containers/SidebarIndexList.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; import { withPlugins } from '../extend/withPlugins'; import * as actions from '../state/actions'; import { @@ -29,21 +28,7 @@ const mapDispatchToProps = (dispatch, { id, windowId }) => ({ setCanvas: (...args) => dispatch(actions.setCanvas(...args)), }); -/** - * Styles for withStyles HOC - */ -const styles = theme => ({ - label: { - paddingLeft: theme.spacing(1), - }, - listItem: { - borderBottom: `0.5px solid ${theme.palette.divider}`, - paddingRight: theme.spacing(1), - }, -}); - const enhance = compose( - withStyles(styles), withTranslation(), connect(mapStateToProps, mapDispatchToProps), withPlugins('SidebarIndexList'), diff --git a/src/containers/SidebarIndexTableOfContents.js b/src/containers/SidebarIndexTableOfContents.js index a626981f34..870f0c4087 100644 --- a/src/containers/SidebarIndexTableOfContents.js +++ b/src/containers/SidebarIndexTableOfContents.js @@ -1,8 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; -import { alpha } from '@material-ui/core/styles/colorManipulator'; import { withPlugins } from '../extend/withPlugins'; import { SidebarIndexTableOfContents } from '../components/SidebarIndexTableOfContents'; import { @@ -34,45 +32,7 @@ const mapDispatchToProps = (dispatch, { id, windowId }) => ({ toggleNode: nodeId => dispatch(actions.toggleNode(windowId, id, nodeId)), }); -/** - * Styles for withStyles HOC - */ -const styles = theme => ({ - content: { - alignItems: 'flex-start', - borderLeft: '1px solid transparent', - padding: '8px 16px 8px 0', - width: 'auto', - }, - group: { - borderLeft: `1px solid ${theme.palette.grey[300]}`, - }, - label: { - paddingLeft: 0, - }, // needed for pseudo $label class - root: { - flexGrow: 1, - }, - selected: {}, // needed for pseudo $selected class - treeItemRoot: { - '&:focus > $content': { - backgroundColor: theme.palette.action.selected, - }, - '&:hover > $content': { - backgroundColor: theme.palette.action.hover, - }, - '&:hover >$content $label, &:focus > $content $label, &$selected > $content $label, &$selected > $content $label:hover, &$selected:focus > $content $label': { - backgroundColor: 'transparent', - }, - }, - visibleNode: { - backgroundColor: alpha(theme.palette.highlights?.primary || theme.palette.action.selected, 0.35), - display: 'inline', - }, -}); - const enhance = compose( - withStyles(styles), withTranslation(), connect(mapStateToProps, mapDispatchToProps), withPlugins('SidebarIndexTableOfContents'), diff --git a/src/containers/SidebarIndexThumbnail.js b/src/containers/SidebarIndexThumbnail.js index 9f582dc464..74c831814f 100644 --- a/src/containers/SidebarIndexThumbnail.js +++ b/src/containers/SidebarIndexThumbnail.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; import { withPlugins } from '../extend/withPlugins'; import { SidebarIndexThumbnail } from '../components/SidebarIndexThumbnail'; import { getConfig } from '../state/selectors'; @@ -15,17 +14,7 @@ const mapStateToProps = (state, { data }) => ({ ...(getConfig(state).canvasNavigation || {}), }); -/** - * Styles for withStyles HOC - */ -const styles = theme => ({ - label: { - paddingLeft: theme.spacing(1), - }, -}); - const enhance = compose( - withStyles(styles), withTranslation(), connect(mapStateToProps, null), withPlugins('SidebarIndexThumbnail'), diff --git a/src/containers/ThumbnailCanvasGrouping.js b/src/containers/ThumbnailCanvasGrouping.js index 0804cee2d5..548c941ba9 100644 --- a/src/containers/ThumbnailCanvasGrouping.js +++ b/src/containers/ThumbnailCanvasGrouping.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; import { withPlugins } from '../extend/withPlugins'; import * as actions from '../state/actions'; import { getCurrentCanvas } from '../state/selectors'; @@ -25,33 +24,8 @@ const mapStateToProps = (state, { data }) => ({ currentCanvasId: (getCurrentCanvas(state, { windowId: data.windowId }) || {}).id, }); -/** - * Styles for withStyles HOC - */ -const styles = theme => ({ - canvas: { - '&$currentCanvas': { - outline: `2px solid ${theme.palette.primary.main}`, - outlineOffset: '3px', - }, - '&:hover': { - outline: `9px solid ${theme.palette.action.hover}`, - outlineOffset: '-2px', - }, - boxSizing: 'border-box', - color: theme.palette.common.white, - cursor: 'pointer', - display: 'inline-block', - outline: 0, - whiteSpace: 'nowrap', - }, - currentCanvas: { - }, -}); - const enhance = compose( withTranslation(), - withStyles(styles), connect(mapStateToProps, mapDispatchToProps), withPlugins('ThumbnailCanvasGrouping'), ); diff --git a/src/containers/ThumbnailNavigation.js b/src/containers/ThumbnailNavigation.js index e3be9a8f33..bf7c3490aa 100644 --- a/src/containers/ThumbnailNavigation.js +++ b/src/containers/ThumbnailNavigation.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; import { withPlugins } from '../extend/withPlugins'; import * as actions from '../state/actions'; import { ThumbnailNavigation } from '../components/ThumbnailNavigation'; @@ -40,20 +39,7 @@ const mapDispatchToProps = (dispatch, { windowId }) => ({ setPreviousCanvas: (...args) => dispatch(actions.setPreviousCanvas(windowId)), }); -/** - * Styles for withStyles HOC - */ -const styles = theme => ({ - thumbNavigation: { - '&:focus': { - boxShadow: 0, - outline: 0, - }, - }, -}); - const enhance = compose( - withStyles(styles), withTranslation(), connect(mapStateToProps, mapDispatchToProps), withPlugins('ThumbnailNavigation'), diff --git a/src/containers/VideoViewer.js b/src/containers/VideoViewer.js index 70e8ebc083..3c868940a2 100644 --- a/src/containers/VideoViewer.js +++ b/src/containers/VideoViewer.js @@ -1,7 +1,6 @@ import { connect } from 'react-redux'; import { compose } from 'redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core'; import { withPlugins } from '../extend/withPlugins'; import { VideoViewer } from '../components/VideoViewer'; import { getConfig, getVisibleCanvasCaptions, getVisibleCanvasVideoResources } from '../state/selectors'; @@ -15,22 +14,8 @@ const mapStateToProps = (state, { windowId }) => ( } ); -/** */ -const styles = () => ({ - container: { - alignItems: 'center', - display: 'flex', - width: '100%', - }, - video: { - maxHeight: '100%', - width: '100%', - }, -}); - const enhance = compose( withTranslation(), - withStyles(styles), connect(mapStateToProps, null), withPlugins('VideoViewer'), ); diff --git a/src/containers/ViewerInfo.js b/src/containers/ViewerInfo.js index 7e2714d9b7..6757102f98 100644 --- a/src/containers/ViewerInfo.js +++ b/src/containers/ViewerInfo.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; import { withPlugins } from '../extend/withPlugins'; import { ViewerInfo } from '../components/ViewerInfo'; import { @@ -29,20 +28,7 @@ const mapStateToProps = (state, props) => { }; }; -const styles = { - osdInfo: { - order: 2, - overflow: 'hidden', - paddingBottom: 3, - textOverflow: 'ellipsis', - unicodeBidi: 'plaintext', - whiteSpace: 'nowrap', - width: '100%', - }, -}; - const enhance = compose( - withStyles(styles), withTranslation(), connect(mapStateToProps, null), withPlugins('ViewerInfo'), diff --git a/src/containers/ViewerNavigation.js b/src/containers/ViewerNavigation.js index 38fb8d4602..3f142de431 100644 --- a/src/containers/ViewerNavigation.js +++ b/src/containers/ViewerNavigation.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; import { withPlugins } from '../extend/withPlugins'; import * as actions from '../state/actions'; import { @@ -28,14 +27,7 @@ const mapDispatchToProps = (dispatch, { windowId }) => ({ setPreviousCanvas: (...args) => dispatch(actions.setPreviousCanvas(windowId)), }); -const styles = { - osdNavigation: { - order: 1, - }, -}; - const enhance = compose( - withStyles(styles), withTranslation(), connect(mapStateToProps, mapDispatchToProps), withPlugins('ViewerNavigation'), diff --git a/src/containers/Window.js b/src/containers/Window.js index a06801e2a4..36cd4e14e1 100644 --- a/src/containers/Window.js +++ b/src/containers/Window.js @@ -1,6 +1,5 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; -import { withStyles } from '@material-ui/core'; import { withTranslation } from 'react-i18next'; import { withPlugins } from '../extend/withPlugins'; import * as actions from '../state/actions'; @@ -36,70 +35,8 @@ const mapDispatchToProps = (dispatch, { windowId }) => ({ focusWindow: () => dispatch(actions.focusWindow(windowId)), }); -/** - * @param theme - */ -const styles = theme => ({ - companionAreaBottom: { - display: 'flex', - flex: '0', - flexBasis: 'auto', - minHeight: 0, - }, - companionAreaRight: { - display: 'flex', - flex: '0 1 auto', - minHeight: 0, - }, - maximized: {}, - middle: { - display: 'flex', - flex: '1', - flexDirection: 'row', - minHeight: 0, - }, - middleLeft: { - display: 'flex', - flex: '1', - flexDirection: 'column', - minHeight: 0, - }, - primaryWindow: { - display: 'flex', - flex: '1', - height: '300px', - minHeight: 0, - position: 'relative', - }, - thumbnailArea: { - backgroundColor: theme.palette.shades?.dark, - }, - thumbnailAreaBottom: { - }, - thumbnailAreaRight: { - minWidth: 100, - }, - window: { - '&$maximized': { - left: 0, - position: 'absolute', - top: 0, - zIndex: theme.zIndex.modal - 1, - }, - backgroundColor: theme.palette.shades?.dark, - borderRadius: 0, - display: 'flex', - flexDirection: 'column', - height: '100%', - minHeight: 0, - overflow: 'hidden', - width: '100%', - }, -}); - const enhance = compose( withTranslation(), - withStyles(styles), connect(mapStateToProps, mapDispatchToProps), withPlugins('Window'), ); diff --git a/src/containers/WindowAuthenticationBar.js b/src/containers/WindowAuthenticationBar.js index f3b7f87333..b38a244aa8 100644 --- a/src/containers/WindowAuthenticationBar.js +++ b/src/containers/WindowAuthenticationBar.js @@ -1,62 +1,10 @@ import { compose } from 'redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; -import { alpha } from '@material-ui/core/styles/colorManipulator'; import { withPlugins } from '../extend/withPlugins'; import { WindowAuthenticationBar } from '../components/WindowAuthenticationBar'; -/** - * @param theme - * @returns {{typographyBody: {flexGrow: number, fontSize: number|string}, - * windowTopBarStyle: {minHeight: number, paddingLeft: number, backgroundColor: string}}} - */ -const styles = theme => ({ - buttonInvert: { - '&:hover': { - backgroundColor: alpha(theme.palette.secondary.contrastText, 1 - theme.palette.action.hoverOpacity), - }, - backgroundColor: theme.palette.secondary.contrastText, - marginLeft: theme.spacing(5), - paddingBottom: 0, - paddingTop: 0, - }, - expanded: { - paddingLeft: theme.spacing(), - paddingRight: theme.spacing(), - }, - failure: { - backgroundColor: theme.palette.error.dark, - }, - fauxButton: { - marginLeft: theme.spacing(2.5), - }, - icon: { - marginRight: theme.spacing(1.5), - verticalAlign: 'text-bottom', - }, - label: { - lineHeight: 2.25, - }, - paper: { - backgroundColor: theme.palette.secondary.main, - color: theme.palette.secondary.contrastText, - cursor: 'pointer', - }, - topBar: { - '&:hover': { - backgroundColor: theme.palette.secondary.main, - }, - alignItems: 'center', - display: 'flex', - justifyContent: 'inherit', - padding: theme.spacing(1), - textTransform: 'none', - }, -}); - const enhance = compose( withTranslation(), - withStyles(styles), withPlugins('WindowAuthenticationBar'), ); diff --git a/src/containers/WindowCanvasNavigationControls.js b/src/containers/WindowCanvasNavigationControls.js index f1f17053f8..ca5088f34b 100644 --- a/src/containers/WindowCanvasNavigationControls.js +++ b/src/containers/WindowCanvasNavigationControls.js @@ -1,45 +1,18 @@ import { connect } from 'react-redux'; import { compose } from 'redux'; import { withSize } from 'react-sizeme'; -import { withStyles } from '@material-ui/core'; -import { alpha } from '@material-ui/core/styles/colorManipulator'; import { withPlugins } from '../extend/withPlugins'; -import { getWorkspace } from '../state/selectors'; +import { getShowZoomControlsConfig, getWorkspace } from '../state/selectors'; import { WindowCanvasNavigationControls } from '../components/WindowCanvasNavigationControls'; /** */ const mapStateToProps = (state, { windowId }) => ({ + showZoomControls: getShowZoomControlsConfig(state), visible: getWorkspace(state).focusedWindowId === windowId, }); -/** - * - * @param theme - */ -const styles = theme => ({ - canvasNav: { - cursor: 'default', - display: 'flex', - flexDirection: 'row', - flexWrap: 'wrap', - justifyContent: 'center', - textAlign: 'center', - }, - canvasNavStacked: { - flexDirection: 'column', - }, - controls: { - backgroundColor: alpha(theme.palette.background.paper, 0.5), - bottom: 0, - position: 'absolute', - width: '100%', - zIndex: 50, - }, -}); - const enhance = compose( connect(mapStateToProps), - withStyles(styles), withSize(), withPlugins('WindowCanvasNavigationControls'), ); diff --git a/src/containers/WindowListButton.js b/src/containers/WindowListButton.js index 74506d9dba..68e984e497 100644 --- a/src/containers/WindowListButton.js +++ b/src/containers/WindowListButton.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; import { withPlugins } from '../extend/withPlugins'; import { getWindowIds, getWorkspace } from '../state/selectors'; import { WindowListButton } from '../components/WindowListButton'; @@ -12,26 +11,8 @@ const mapStateToProps = (state) => ({ windowCount: getWindowIds(state).length, }); -/** - * - * @param theme - * @returns {{background: {background: string}}} - */ -const styles = theme => ({ - badge: { - paddingLeft: 12, - }, - ctrlBtn: { - margin: theme.spacing(1), - }, - ctrlBtnSelected: { - backgroundColor: theme.palette.action.selected, - }, -}); - const enhance = compose( withTranslation(), - withStyles(styles), connect(mapStateToProps, null), withPlugins('WindowListButton'), ); diff --git a/src/containers/WindowSideBar.js b/src/containers/WindowSideBar.js index 012b2fd5d5..022e34f310 100644 --- a/src/containers/WindowSideBar.js +++ b/src/containers/WindowSideBar.js @@ -1,6 +1,5 @@ import { connect } from 'react-redux'; import { compose } from 'redux'; -import { withStyles } from '@material-ui/core'; import { withTranslation } from 'react-i18next'; import { withPlugins } from '../extend/withPlugins'; import { WindowSideBar } from '../components/WindowSideBar'; @@ -19,32 +18,7 @@ const mapStateToProps = (state, { windowId }) => ( } ); -/** - * - * @param theme - * @returns {{toolbar: CSSProperties | toolbar | {minHeight}, grow: {flexGrow: number}, - * drawer: {overflowX: string, left: number, flexShrink: number, width: number, height: string}}} - */ -const styles = theme => ({ - drawer: { - flexShrink: 0, - height: '100%', - order: -1000, - zIndex: theme.zIndex.appBar - 1, - }, - grow: { - flexGrow: 1, - }, - paper: { - borderInlineEnd: `1px solid ${theme.palette.divider}`, - overflowX: 'hidden', - width: 48, - }, - toolbar: theme.mixins.toolbar, -}); - const enhance = compose( - withStyles(styles), withTranslation(), connect(mapStateToProps, null), withPlugins('WindowSideBar'), diff --git a/src/containers/WindowSideBarAnnotationsPanel.js b/src/containers/WindowSideBarAnnotationsPanel.js index 904cea2f93..8370a0c375 100644 --- a/src/containers/WindowSideBarAnnotationsPanel.js +++ b/src/containers/WindowSideBarAnnotationsPanel.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; import { withPlugins } from '../extend/withPlugins'; import { getVisibleCanvasIds, @@ -22,20 +21,8 @@ const mapStateToProps = (state, { windowId }) => ({ canvasIds: getVisibleCanvasIds(state, { windowId }), }); -/** */ -const styles = theme => ({ - section: { - borderBottom: `.5px solid ${theme.palette.section_divider}`, - paddingBottom: theme.spacing(1), - paddingLeft: theme.spacing(2), - paddingRight: theme.spacing(1), - paddingTop: theme.spacing(2), - }, -}); - const enhance = compose( withTranslation(), - withStyles(styles), connect(mapStateToProps, null), withPlugins('WindowSideBarAnnotationsPanel'), // further HOC diff --git a/src/containers/WindowSideBarButtons.js b/src/containers/WindowSideBarButtons.js index 8449e9b6a2..3b0511ae0f 100644 --- a/src/containers/WindowSideBarButtons.js +++ b/src/containers/WindowSideBarButtons.js @@ -1,6 +1,5 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; -import { withStyles } from '@material-ui/core'; import { withTranslation } from 'react-i18next'; import { withPlugins } from '../extend/withPlugins'; import * as actions from '../state/actions'; @@ -65,49 +64,8 @@ const mapStateToProps = (state, { windowId }) => ({ sideBarPanel: ((getCompanionWindowsForPosition(state, { position: 'left', windowId }))[0] || {}).content, }); -/** */ -const style = theme => ({ - badge: { - backgroundColor: theme.palette.notification?.main, - }, - tab: { - '&:active': { - backgroundColor: theme.palette.action?.active, - }, - '&:focus': { - '@media (hover: none)': { - backgroundColor: 'transparent', - }, - backgroundColor: theme.palette.action?.hover, - textDecoration: 'none', - // Reset on touch devices, it doesn't add specificity - }, - '&:hover': { - '@media (hover: none)': { - backgroundColor: 'transparent', - }, - backgroundColor: theme.palette.action?.hover, - textDecoration: 'none', - // Reset on touch devices, it doesn't add specificity - }, - - borderRight: '2px solid transparent', - minWidth: 'auto', - }, - tabSelected: { - borderRight: `2px solid ${theme.palette.primary?.main}`, - }, - tabsFlexContainer: { - flexDirection: 'column', - }, - tabsIndicator: { - display: 'none', - }, -}); - const enhance = compose( withTranslation(), - withStyles(style), connect(mapStateToProps, mapDispatchToProps), withPlugins('WindowSideBarButtons'), ); diff --git a/src/containers/WindowSideBarCanvasPanel.js b/src/containers/WindowSideBarCanvasPanel.js index 24324d2538..e6b4befc73 100644 --- a/src/containers/WindowSideBarCanvasPanel.js +++ b/src/containers/WindowSideBarCanvasPanel.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; import { withPlugins } from '../extend/withPlugins'; import * as actions from '../state/actions'; import { WindowSideBarCanvasPanel } from '../components/WindowSideBarCanvasPanel'; @@ -53,37 +52,8 @@ const mapDispatchToProps = (dispatch, { id, windowId }) => ({ ), }); -/** - * - * @param theme - */ -const styles = theme => ({ - break: { - flexBasis: '100%', - height: 0, - }, - collectionNavigationButton: { - textTransform: 'none', - }, - label: { - paddingLeft: theme.spacing(1), - }, - select: { - '&:focus': { - backgroundColor: theme.palette.background.paper, - }, - }, - selectEmpty: { - backgroundColor: theme.palette.background.paper, - }, - variantTab: { - minWidth: 'auto', - }, -}); - const enhance = compose( withTranslation(), - withStyles(styles), connect(mapStateToProps, mapDispatchToProps), withPlugins('WindowSideBarCanvasPanel'), ); diff --git a/src/containers/WindowSideBarCollectionPanel.js b/src/containers/WindowSideBarCollectionPanel.js index 32b31a77b2..738c11125a 100644 --- a/src/containers/WindowSideBarCollectionPanel.js +++ b/src/containers/WindowSideBarCollectionPanel.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; import { withPlugins } from '../extend/withPlugins'; import * as actions from '../state/actions'; import { @@ -56,22 +55,7 @@ const mapDispatchToProps = (dispatch, { id, windowId }) => ({ updateWindow: (...args) => dispatch(actions.updateWindow(windowId, ...args)), }); -/** - * Styles for withStyles HOC - */ -const styles = theme => ({ - label: { - paddingLeft: theme.spacing(1), - }, - menuItem: { - borderBottom: `0.5px solid ${theme.palette.divider}`, - paddingRight: theme.spacing(1), - whiteSpace: 'normal', - }, -}); - const enhance = compose( - withStyles(styles), withTranslation(), connect(mapStateToProps, mapDispatchToProps), withPlugins('WindowSideBarCollectionPanel'), diff --git a/src/containers/WindowSideBarInfoPanel.js b/src/containers/WindowSideBarInfoPanel.js index 9fc498ce11..19de86776b 100644 --- a/src/containers/WindowSideBarInfoPanel.js +++ b/src/containers/WindowSideBarInfoPanel.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; import { withPlugins } from '../extend/withPlugins'; import * as actions from '../state/actions'; import { @@ -33,24 +32,8 @@ const mapDispatchToProps = (dispatch, { windowId, id }) => ({ setLocale: locale => dispatch(actions.updateCompanionWindow(windowId, id, { locale })), }); -/** - * - * @param theme - * @returns {label: {paddingLeft: number}}} - */ -const styles = theme => ({ - section: { - borderBottom: `.5px solid ${theme.palette.section_divider}`, - paddingBottom: theme.spacing(1), - paddingLeft: theme.spacing(2), - paddingRight: theme.spacing(1), - paddingTop: theme.spacing(2), - }, -}); - const enhance = compose( withTranslation(), - withStyles(styles), connect(mapStateToProps, mapDispatchToProps), withPlugins('WindowSideBarInfoPanel'), ); diff --git a/src/containers/WindowThumbnailSettings.js b/src/containers/WindowThumbnailSettings.js index 24878457a7..d773247fee 100644 --- a/src/containers/WindowThumbnailSettings.js +++ b/src/containers/WindowThumbnailSettings.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; import { withPlugins } from '../extend/withPlugins'; import * as actions from '../state/actions'; import { getThumbnailNavigationPosition, getThemeDirection } from '../state/selectors'; @@ -26,22 +25,7 @@ const mapStateToProps = (state, { windowId }) => ( } ); -/** */ -const styles = theme => ({ - label: { - borderBottom: '2px solid transparent', - }, - MenuItem: { - display: 'inline-block', - }, - selectedLabel: { - borderBottom: `2px solid ${theme.palette.secondary.main}`, - color: theme.palette.secondary.main, - }, -}); - const enhance = compose( - withStyles(styles), withTranslation(null, { withRef: true }), connect(mapStateToProps, mapDispatchToProps, null, { forwardRef: true }), withPlugins('WindowThumbnailSettings'), diff --git a/src/containers/WindowTopBar.js b/src/containers/WindowTopBar.js index 27dd9b8324..ae9fc34b90 100644 --- a/src/containers/WindowTopBar.js +++ b/src/containers/WindowTopBar.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core'; import { withPlugins } from '../extend/withPlugins'; import * as actions from '../state/actions'; import { getWindowConfig, isFocused } from '../state/selectors'; @@ -35,31 +34,8 @@ const mapDispatchToProps = (dispatch, { windowId }) => ({ toggleWindowSideBar: () => dispatch(actions.toggleWindowSideBar(windowId)), }); -/** - * @param theme - * @returns {{typographyBody: {flexGrow: number, fontSize: number|string}, - * windowTopBarStyle: {minHeight: number, paddingLeft: number, backgroundColor: string}}} - */ -const styles = theme => ({ - focused: {}, - windowTopBarStyle: { - '&$focused': { - borderTop: `2px solid ${theme.palette.primary.main}`, - }, - backgroundColor: theme.palette.shades?.main, - borderTop: '2px solid transparent', - minHeight: 32, - paddingLeft: theme.spacing(0.5), - paddingRight: theme.spacing(0.5), - }, - windowTopBarStyleDraggable: { - cursor: 'move', - }, -}); - const enhance = compose( withTranslation(), - withStyles(styles), connect(mapStateToProps, mapDispatchToProps), withPlugins('WindowTopBar'), ); diff --git a/src/containers/WindowTopBarPluginArea.js b/src/containers/WindowTopBarPluginArea.js index 4bcdc88f5a..cf05b64af3 100644 --- a/src/containers/WindowTopBarPluginArea.js +++ b/src/containers/WindowTopBarPluginArea.js @@ -1,17 +1,11 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core'; import { withPlugins } from '../extend/withPlugins'; import { WindowTopBarPluginArea } from '../components/WindowTopBarPluginArea'; -/** - */ -const styles = {}; - const enhance = compose( withTranslation(), - withStyles(styles), connect(null, null), withPlugins('WindowTopBarPluginArea'), ); diff --git a/src/containers/WindowTopBarPluginMenu.js b/src/containers/WindowTopBarPluginMenu.js index 510d7a35de..4900528e9f 100644 --- a/src/containers/WindowTopBarPluginMenu.js +++ b/src/containers/WindowTopBarPluginMenu.js @@ -1,25 +1,12 @@ import { compose } from 'redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core'; import { withPlugins } from '../extend/withPlugins'; import { WindowTopBarPluginMenu } from '../components/WindowTopBarPluginMenu'; import { withWorkspaceContext } from '../contexts/WorkspaceContext'; -/** - * - * @param theme - * @returns {{ctrlBtn: {margin: (number|string)}}} - */ -const styles = theme => ({ - ctrlBtnSelected: { - backgroundColor: theme.palette.action.selected, - }, -}); - const enhance = compose( withTranslation(), withWorkspaceContext, - withStyles(styles), withPlugins('WindowTopBarPluginMenu'), ); diff --git a/src/containers/WindowTopBarTitle.js b/src/containers/WindowTopBarTitle.js index 5cb51b8274..fbdf31288b 100644 --- a/src/containers/WindowTopBarTitle.js +++ b/src/containers/WindowTopBarTitle.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core'; import { withPlugins } from '../extend/withPlugins'; import { getManifestStatus, getManifestTitle, getWindowConfig } from '../state/selectors'; import { WindowTopBarTitle } from '../components/WindowTopBarTitle'; @@ -14,20 +13,8 @@ const mapStateToProps = (state, { windowId }) => ({ manifestTitle: getManifestTitle(state, { windowId }), }); -/** - * @param theme - */ -const styles = theme => ({ - title: { - ...theme.typography.h6, - flexGrow: 1, - paddingLeft: theme.spacing(0.5), - }, -}); - const enhance = compose( withTranslation(), - withStyles(styles), connect(mapStateToProps, null), withPlugins('WindowTopBarTitle'), ); diff --git a/src/containers/WindowTopMenuButton.js b/src/containers/WindowTopMenuButton.js index 54d863e2b6..8a114a8dea 100644 --- a/src/containers/WindowTopMenuButton.js +++ b/src/containers/WindowTopMenuButton.js @@ -1,23 +1,10 @@ import { compose } from 'redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core'; import { withPlugins } from '../extend/withPlugins'; import { WindowTopMenuButton } from '../components/WindowTopMenuButton'; -/** - * - * @param theme - * @returns {{ctrlBtn: {margin: (number|string)}}} - */ -const styles = theme => ({ - ctrlBtnSelected: { - backgroundColor: theme.palette.action.selected, - }, -}); - const enhance = compose( withTranslation(), - withStyles(styles), withPlugins('WindowTopMenuButton'), ); diff --git a/src/containers/WindowViewSettings.js b/src/containers/WindowViewSettings.js index 6fc417f284..3e34e5949b 100644 --- a/src/containers/WindowViewSettings.js +++ b/src/containers/WindowViewSettings.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; import { withPlugins } from '../extend/withPlugins'; import * as actions from '../state/actions'; import { getAllowedWindowViewTypes, getWindowViewType } from '../state/selectors'; @@ -26,22 +25,7 @@ const mapStateToProps = (state, { windowId }) => ( } ); -/** */ -const styles = theme => ({ - label: { - borderBottom: '2px solid transparent', - }, - MenuItem: { - display: 'inline-block', - }, - selectedLabel: { - borderBottom: `2px solid ${theme.palette.secondary.main}`, - color: theme.palette.secondary.main, - }, -}); - const enhance = compose( - withStyles(styles), withTranslation(null, { withRef: true }), connect(mapStateToProps, mapDispatchToProps, null, { forwardRef: true }), withPlugins('WindowViewSettings'), diff --git a/src/containers/Workspace.js b/src/containers/Workspace.js index 6eac59013b..f9288e8d94 100644 --- a/src/containers/Workspace.js +++ b/src/containers/Workspace.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; import { withPlugins } from '../extend/withPlugins'; import { Workspace } from '../components/Workspace'; import { @@ -18,7 +17,6 @@ import * as actions from '../state/actions'; const mapStateToProps = state => ( { allowNewWindows: getConfig(state).workspace.allowNewWindows, - isWorkspaceControlPanelVisible: getConfig(state).workspaceControlPanel.enabled, maximizedWindowIds: getMaximizedWindowsIds(state), windowIds: getWindowIds(state), workspaceId: getWorkspace(state).id, @@ -35,35 +33,8 @@ const mapDispatchToProps = { addWindow: actions.addWindow, }; -/** - * @param theme - */ -const styles = theme => ({ - workspaceViewport: { - bottom: 0, - left: 0, - margin: 0, - overflow: 'hidden', - position: 'absolute', - right: 0, - top: 0, - }, - workspaceWithControlPanel: { - paddingTop: 74, - }, - // injection order matters here - // eslint-disable-next-line sort-keys - '@media (min-width: 600px)': { - workspaceWithControlPanel: { - paddingLeft: 68, - paddingTop: 0, - }, - }, -}); - const enhance = compose( withTranslation(), - withStyles(styles), connect(mapStateToProps, mapDispatchToProps), withPlugins('Workspace'), // further HOC go here diff --git a/src/containers/WorkspaceAdd.js b/src/containers/WorkspaceAdd.js index 25f8903234..0c0883945d 100644 --- a/src/containers/WorkspaceAdd.js +++ b/src/containers/WorkspaceAdd.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core'; import { withPlugins } from '../extend/withPlugins'; import * as actions from '../state/actions'; import { WorkspaceAdd } from '../components/WorkspaceAdd'; @@ -24,73 +23,8 @@ const mapDispatchToProps = { setWorkspaceAddVisibility: actions.setWorkspaceAddVisibility, }; -/** - * - * @param theme - * @returns {{typographyBody: {flexGrow: number, fontSize: string}, - * form: {paddingBottom: number, paddingTop: number, marginTop: number}, - * fab: {bottom: number, position: string, right: number}, - * menuButton: {marginRight: number, marginLeft: number}}} - */ -const styles = theme => ({ - displayNone: { - display: 'none', - }, - fab: { - bottom: theme.spacing(2), - position: 'absolute', - right: theme.spacing(2), - }, - form: { - left: '0', - marginTop: 48, - paddingBottom: theme.spacing(2), - paddingLeft: theme.spacing(2), - paddingRight: theme.spacing(2), - [theme.breakpoints.up('sm')]: { - paddingLeft: theme.spacing(3), - paddingRight: theme.spacing(3), - }, - paddingTop: theme.spacing(2), - right: '0', - }, - list: { - margin: '16px', - }, - menuButton: { - marginLeft: -12, - marginRight: 20, - }, - paper: { - borderTop: '0', - left: '0', - [theme.breakpoints.up('sm')]: { - left: '65px', - }, - }, - typographyBody: { - flexGrow: 1, - }, - workspaceAdd: { - boxSizing: 'border-box', - height: '100%', - overflowX: 'hidden', - overflowY: 'auto', - paddingTop: 68, - }, - // injection order matters - // eslint-disable-next-line sort-keys - '@media (min-width: 600px)': { - workspaceAdd: { - paddingLeft: 68, - paddingTop: 0, - }, - }, -}); - const enhance = compose( withTranslation(), - withStyles(styles), connect(mapStateToProps, mapDispatchToProps), withPlugins('WorkspaceAdd'), ); diff --git a/src/containers/WorkspaceAddButton.js b/src/containers/WorkspaceAddButton.js index 427676b481..cec63fcb4a 100644 --- a/src/containers/WorkspaceAddButton.js +++ b/src/containers/WorkspaceAddButton.js @@ -1,13 +1,37 @@ import { connect } from 'react-redux'; import { compose } from 'redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core'; -import withWidth from '@material-ui/core/withWidth'; +import { useTheme } from '@mui/material/styles'; +import useMediaQuery from '@mui/material/useMediaQuery'; import { withPlugins } from '../extend/withPlugins'; import * as actions from '../state/actions'; import { getWindowIds, getWorkspace } from '../state/selectors'; import { WorkspaceAddButton } from '../components/WorkspaceAddButton'; +/** + * Be careful using this hook. It only works because the number of + * breakpoints in theme is static. It will break once you change the number of + * breakpoints. See https://legacy.reactjs.org/docs/hooks-rules.html#only-call-hooks-at-the-top-level + */ +function useWidth() { + const theme = useTheme(); + const keys = [...theme.breakpoints.keys].reverse(); + return ( + keys.reduce((output, key) => { + // eslint-disable-next-line react-hooks/rules-of-hooks + const matches = useMediaQuery(theme.breakpoints.up(key)); + return !output && matches ? key : output; + }, null) || 'xs' + ); +} + +/** + * withWidth + * @memberof WorkspaceControlPanel + * @private + */ +const withWidth = () => (WrappedComponent) => (props) => ; + /** * mapStateToProps - to hook up connect * @memberof WorkspaceControlPanel @@ -32,30 +56,8 @@ const mapStateToProps = (state, { width }) => { */ const mapDispatchToProps = { setWorkspaceAddVisibility: actions.setWorkspaceAddVisibility }; -/** - * - * @param theme - * @returns {{ctrlBtn: {margin: (number|string)}}} - */ -const styles = theme => ({ - fab: { - margin: theme.spacing(1), - }, - fabPrimary: { - '&:focus': { - backgroundColor: theme.palette.primary.dark, - }, - }, - fabSecondary: { - '&:focus': { - backgroundColor: theme.palette.secondary.dark, - }, - }, -}); - const enhance = compose( withTranslation(), - withStyles(styles), withWidth({ initialWidth: 'xs' }), connect(mapStateToProps, mapDispatchToProps), withPlugins('WorkspaceAddButton'), diff --git a/src/containers/WorkspaceArea.js b/src/containers/WorkspaceArea.js index c2655978c9..f58fa21317 100644 --- a/src/containers/WorkspaceArea.js +++ b/src/containers/WorkspaceArea.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles, lighten, darken } from '@material-ui/core/styles'; import { withPlugins } from '../extend/withPlugins'; import { WorkspaceArea } from '../components/WorkspaceArea'; import { getConfig, getWindowIds, getWorkspace } from '../state/selectors'; @@ -20,30 +19,8 @@ const mapStateToProps = state => ( } ); -/** - * - * @param theme - * @returns {{background: {background: string}}} - */ -const styles = (theme) => { - const getBackgroundColor = theme.palette.type === 'light' ? darken : lighten; - - return { - viewer: { - background: getBackgroundColor(theme.palette.shades.light, 0.1), - bottom: 0, - left: 0, - overflow: 'hidden', - position: 'absolute', - right: 0, - top: 0, - }, - }; -}; - const enhance = compose( withTranslation(), - withStyles(styles), connect(mapStateToProps), withPlugins('WorkspaceArea'), ); diff --git a/src/containers/WorkspaceControlPanel.js b/src/containers/WorkspaceControlPanel.js index 88f482e91d..e23bb417a9 100644 --- a/src/containers/WorkspaceControlPanel.js +++ b/src/containers/WorkspaceControlPanel.js @@ -1,69 +1,10 @@ import { compose } from 'redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; import { withPlugins } from '../extend/withPlugins'; import { WorkspaceControlPanel } from '../components/WorkspaceControlPanel'; -/** - * - * @param theme - * @returns {{ctrlBtn: {margin: (number|string)}, - * drawer: {overflowX: string, height: string}}} - */ -const styles = theme => ({ - branding: { - display: 'flex', - position: 'absolute', - [theme.breakpoints.up('xs')]: { - display: 'none', - }, - [theme.breakpoints.up('sm')]: { - bottom: 0, - display: 'block', - float: 'none', - right: 'auto', - width: '100%', - }, - right: 0, - }, - ctrlBtn: { - margin: theme.spacing(1), - }, - drawer: { - overflowX: 'hidden', - }, - root: { - height: 64, - [theme.breakpoints.up('sm')]: { - height: '100%', - left: 0, - right: 'auto', - width: 64, - }, - }, - toolbar: { - display: 'flex', - justifyContent: 'space-between', - [theme.breakpoints.up('sm')]: { - flexDirection: 'column', - justifyContent: 'flex-start', - minHeight: 0, - }, - }, - wide: { - width: 'auto', - }, - workspaceButtons: { - [theme.breakpoints.up('sm')]: { - display: 'flex', - flexDirection: 'column', - }, - }, -}); - const enhance = compose( withTranslation(), - withStyles(styles), withPlugins('WorkspaceControlPanel'), // further HOC go here ); diff --git a/src/containers/WorkspaceControlPanelButtons.js b/src/containers/WorkspaceControlPanelButtons.js index eaef08bd77..9d500357b4 100644 --- a/src/containers/WorkspaceControlPanelButtons.js +++ b/src/containers/WorkspaceControlPanelButtons.js @@ -1,21 +1,8 @@ import { compose } from 'redux'; -import { withStyles } from '@material-ui/core/styles'; import { withPlugins } from '../extend/withPlugins'; import { WorkspaceControlPanelButtons } from '../components/WorkspaceControlPanelButtons'; -/** - * - * @param theme - * @returns {{ctrlBtn: {margin: (number|string)}}} - */ -const styles = theme => ({ - ctrlBtn: { - margin: theme.spacing(1), - }, -}); - const enhance = compose( - withStyles(styles), withPlugins('WorkspaceControlPanelButtons'), ); diff --git a/src/containers/WorkspaceElastic.js b/src/containers/WorkspaceElastic.js index 9badc4614b..5cc72f5756 100644 --- a/src/containers/WorkspaceElastic.js +++ b/src/containers/WorkspaceElastic.js @@ -1,6 +1,5 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; -import { withStyles } from '@material-ui/core/styles'; import { withPlugins } from '../extend/withPlugins'; import * as actions from '../state/actions'; import WorkspaceElastic from '../components/WorkspaceElastic'; @@ -44,22 +43,7 @@ const mapDispatchToProps = (dispatch, props) => ({ }, }); -const styles = { - workspace: { - boxSizing: 'border-box', - margin: 0, - position: 'absolute', - transitionDuration: '.7s', - // order matters - // eslint-disable-next-line sort-keys - '& .react-draggable-dragging': { - transitionDuration: 'unset', - }, - }, -}; - const enhance = compose( - withStyles(styles), connect(mapStateToProps, mapDispatchToProps), withPlugins('WorkspaceElastic'), // further HOC go here diff --git a/src/containers/WorkspaceElasticWindow.js b/src/containers/WorkspaceElasticWindow.js index 1c071396f7..7e6b5ccac2 100644 --- a/src/containers/WorkspaceElasticWindow.js +++ b/src/containers/WorkspaceElasticWindow.js @@ -1,6 +1,5 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; -import { withStyles } from '@material-ui/core'; import * as actions from '../state/actions'; import WorkspaceElasticWindow from '../components/WorkspaceElasticWindow'; import { @@ -36,17 +35,7 @@ const mapDispatchToProps = (dispatch, props) => ({ }, }); -/** - * @param theme - */ -const styles = theme => ({ - focused: { - zIndex: theme.zIndex.modal - 1, - }, -}); - const enhance = compose( - withStyles(styles), connect(mapStateToProps, mapDispatchToProps), // further HOC go here ); diff --git a/src/containers/WorkspaceExport.js b/src/containers/WorkspaceExport.js index e1ac982c10..069a525428 100644 --- a/src/containers/WorkspaceExport.js +++ b/src/containers/WorkspaceExport.js @@ -1,6 +1,5 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; -import { withStyles } from '@material-ui/core/styles'; import { withTranslation } from 'react-i18next'; import { withPlugins } from '../extend/withPlugins'; import { WorkspaceExport } from '../components/WorkspaceExport'; @@ -17,18 +16,8 @@ const mapStateToProps = state => ({ exportableState: getExportableState(state), }); -/** - * Styles for the withStyles HOC - */ -const styles = theme => ({ - accordionTitle: { - padding: 0, - }, -}); - const enhance = compose( withTranslation(), - withStyles(styles), connect(mapStateToProps, {}), withPlugins('WorkspaceExport'), ); diff --git a/src/containers/WorkspaceImport.js b/src/containers/WorkspaceImport.js index 01c22d1547..c529bca89a 100644 --- a/src/containers/WorkspaceImport.js +++ b/src/containers/WorkspaceImport.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core'; import { withPlugins } from '../extend/withPlugins'; import { WorkspaceImport } from '../components/WorkspaceImport'; import * as actions from '../state/actions'; @@ -16,22 +15,8 @@ const mapDispatchToProps = { importConfig: actions.importMiradorState, }; -/** */ -const styles = theme => ({ - cancelBtn: { - color: theme.palette.text.primary, - }, - textField: { - width: '100%', - }, - textInput: { - fontFamily: 'monospace', - }, -}); - const enhance = compose( withTranslation(), - withStyles(styles), connect(null, mapDispatchToProps), withPlugins('WorkspaceImport'), ); diff --git a/src/containers/WorkspaceMenuButton.js b/src/containers/WorkspaceMenuButton.js index 16e10d569b..b5f2518eb2 100644 --- a/src/containers/WorkspaceMenuButton.js +++ b/src/containers/WorkspaceMenuButton.js @@ -1,26 +1,10 @@ import { compose } from 'redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core'; import { withPlugins } from '../extend/withPlugins'; import { WorkspaceMenuButton } from '../components/WorkspaceMenuButton'; -/** - * - * @param theme - * @returns {{ctrlBtn: {margin: (number|string)}}} - */ -const styles = theme => ({ - ctrlBtn: { - margin: theme.spacing(1), - }, - ctrlBtnSelected: { - backgroundColor: theme.palette.action.selected, - }, -}); - const enhance = compose( withTranslation(), - withStyles(styles), withPlugins('WorkspaceMenuButton'), // further HOC ); diff --git a/src/containers/WorkspaceMosaic.js b/src/containers/WorkspaceMosaic.js index b66e2f4aa6..4ab6529d05 100644 --- a/src/containers/WorkspaceMosaic.js +++ b/src/containers/WorkspaceMosaic.js @@ -1,11 +1,9 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; -import { withStyles } from '@material-ui/core/styles'; import { withPlugins } from '../extend/withPlugins'; import { getWorkspace } from '../state/selectors'; import * as actions from '../state/actions'; import { WorkspaceMosaic } from '../components/WorkspaceMosaic'; -import globalReactMosaicStyles from '../styles/react-mosaic-component'; /** * mapStateToProps - to hook up connect @@ -27,26 +25,7 @@ const mapStateToProps = state => ( */ const mapDispatchToProps = { updateWorkspaceMosaicLayout: actions.updateWorkspaceMosaicLayout }; -const styles = { - root: { - '& .mosaic-preview': { - boxShadow: 'none', - }, - '& .mosaic-tile': { - boxShadow: '0 1px 3px 0 rgba(0, 0, 0, .2), 0 1px 1px 0 rgba(0, 0, 0, .2), 0 2px 1px -1px rgba(0, 0, 0, .2)', - }, - '& .mosaic-window': { - boxShadow: 'none', - }, - '& .mosaic-window-toolbar': { - display: 'none !important', - }, - }, - ...globalReactMosaicStyles, -}; - const enhance = compose( - withStyles(styles), connect(mapStateToProps, mapDispatchToProps), withPlugins('WorkspaceMosaic'), // further HOC go here diff --git a/src/containers/WorkspaceOptionsButton.js b/src/containers/WorkspaceOptionsButton.js index f17b51310f..5768c4cd2a 100644 --- a/src/containers/WorkspaceOptionsButton.js +++ b/src/containers/WorkspaceOptionsButton.js @@ -1,24 +1,9 @@ import { compose } from 'redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core/styles'; import { withPlugins } from '../extend/withPlugins'; import { WorkspaceOptionsButton } from '../components/WorkspaceOptionsButton'; -/** - * - * @param theme - */ -const styles = theme => ({ - ctrlBtn: { - margin: theme.spacing(1), - }, - ctrlBtnSelected: { - backgroundColor: theme.palette.action.selected, - }, -}); - const enhance = compose( - withStyles(styles), withTranslation(), withPlugins('WorkspaceOptionsButton'), ); diff --git a/src/containers/WorkspaceSelectionDialog.js b/src/containers/WorkspaceSelectionDialog.js index d14881af77..3305e53216 100644 --- a/src/containers/WorkspaceSelectionDialog.js +++ b/src/containers/WorkspaceSelectionDialog.js @@ -1,7 +1,6 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core'; import { withPlugins } from '../extend/withPlugins'; import { WorkspaceSelectionDialog } from '../components/WorkspaceSelectionDialog'; import * as actions from '../state/actions'; @@ -23,60 +22,8 @@ const mapDispatchToProps = { */ const mapStateToProps = state => ({ workspaceType: getWorkspaceType(state) }); -/** */ -const styles = theme => ({ - card: { - backgroundColor: 'transparent', - borderRadius: '0', - boxShadow: '0 0 transparent', - display: 'flex', - }, - content: { - flex: '1 0 auto', - }, - details: { - display: 'flex', - flexDirection: 'column', - }, - headline: { - paddingBottom: '6px', - }, - list: { - '&active': { - outline: 'none', - }, - '&focus': { - outline: 'none', - }, - outline: 'none', - }, - media: { - flex: '0 0 120px', - height: '90px', - }, - menuItem: { - height: 'auto', - overflow: 'auto', - whiteSpace: 'inherit', - }, - root: { - '&:last-child': { - paddingBottom: '12px', - }, - paddingBottom: 0, - paddingTop: 0, - textAlign: 'left', - }, - svgIcon: { - flexShrink: 0, - height: '90px', - width: '120px', - }, -}); - const enhance = compose( withTranslation(), - withStyles(styles), connect(mapStateToProps, mapDispatchToProps), withPlugins('WorkspaceSelectionDialog'), ); diff --git a/src/containers/ZoomControls.js b/src/containers/ZoomControls.js index 512ce860cb..1cc85d5455 100644 --- a/src/containers/ZoomControls.js +++ b/src/containers/ZoomControls.js @@ -1,10 +1,9 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withTranslation } from 'react-i18next'; -import { withStyles } from '@material-ui/core'; import { withPlugins } from '../extend/withPlugins'; import * as actions from '../state/actions'; -import { getShowZoomControlsConfig, getViewer } from '../state/selectors'; +import { getViewer } from '../state/selectors'; import { ZoomControls } from '../components/ZoomControls'; /** @@ -14,7 +13,6 @@ import { ZoomControls } from '../components/ZoomControls'; */ const mapStateToProps = (state, { windowId }) => ( { - showZoomControls: getShowZoomControlsConfig(state), viewer: getViewer(state, { windowId }), } ); @@ -26,33 +24,8 @@ const mapStateToProps = (state, { windowId }) => ( */ const mapDispatchToProps = { updateViewport: actions.updateViewport }; -/** - * - * @param theme - * @returns {{zoom_controls: {position: string, right: number}, - * ListItem: {paddingBottom: number, paddingTop: number}}} - */ -const styles = theme => ({ - divider: { - borderRight: '1px solid #808080', - display: 'inline-block', - height: '24px', - margin: '12px 6px', - }, - ListItem: { - paddingBottom: 0, - paddingTop: 0, - }, - zoom_controls: { - display: 'flex', - flexDirection: 'row', - justifyContent: 'center', - }, -}); - const enhance = compose( withTranslation(), - withStyles(styles), connect(mapStateToProps, mapDispatchToProps), withPlugins('ZoomControls'), ); diff --git a/src/extend/pluginMapping.js b/src/extend/pluginMapping.js index efc449252a..7ddeefd6bb 100644 --- a/src/extend/pluginMapping.js +++ b/src/extend/pluginMapping.js @@ -18,7 +18,7 @@ import CompanionWindowRegistry from '../lib/CompanionWindowRegistry'; */ export function createTargetToPluginMapping(plugins) { return plugins.reduce((map, plugin) => ( - update(map, [plugin.target, plugin.mode], x => [...x || [], plugin]) + update(map, [plugin.target, plugin.mode], x => [...(x || []), plugin]) ), {}); } diff --git a/src/state/createStore.js b/src/state/createStore.js index 9467f322c5..c115859260 100644 --- a/src/state/createStore.js +++ b/src/state/createStore.js @@ -6,7 +6,7 @@ import thunkMiddleware from 'redux-thunk'; import createSagaMiddleware from 'redux-saga'; import { combineReducers, createStore, applyMiddleware } from 'redux'; -import { composeWithDevTools } from 'redux-devtools-extension'; +import { composeWithDevTools } from '@redux-devtools/extension'; import createRootReducer from './reducers/rootReducer'; import getRootSaga from './sagas'; import settings from '../config/settings'; diff --git a/src/styles/react-mosaic-component.js b/src/styles/react-mosaic-component.js index 23d46a4fb2..2f6885ea12 100644 --- a/src/styles/react-mosaic-component.js +++ b/src/styles/react-mosaic-component.js @@ -1,285 +1,283 @@ // Generated using jss convert node_modules/react-mosaic-component/react-mosaic-component.css > src/styles/react-mosaic-component.js // .mosaic-blueprint-theme styles have also been removed const globalReactMosaicStyles = { - '@global': { - '.mosaic': { - height: '100%', - width: '100%', - }, - '.mosaic, .mosaic > *': { - boxSizing: 'border-box', - }, - '.mosaic .mosaic-zero-state': { - position: 'absolute', - top: 6, - right: 6, - bottom: 6, - left: 6, - width: 'auto', - height: 'auto', - zIndex: '1', - }, - '.mosaic-root': { - position: 'absolute', - top: 3, - right: 3, - bottom: 3, - left: 3, - }, - '.mosaic-split': { - position: 'absolute', - zIndex: '1', - touchAction: 'none', - }, - '.mosaic-split:hover': { - background: 'black', - }, - '.mosaic-split .mosaic-split-line': { - position: 'absolute', - }, - '.mosaic-split.-row': { - marginLeft: -3, - width: 6, - cursor: 'ew-resize', - }, - '.mosaic-split.-row .mosaic-split-line': { - top: '0', - bottom: '0', - left: 3, - right: 3, - }, - '.mosaic-split.-column': { - marginTop: -3, - height: 6, - cursor: 'ns-resize', - }, - '.mosaic-split.-column .mosaic-split-line': { - top: 3, - bottom: 3, - left: '0', - right: '0', - }, - '.mosaic-tile': { - position: 'absolute', - margin: 3, - }, - '.mosaic-tile > *': { - height: '100%', - width: '100%', - }, - '.mosaic-drop-target': { - position: 'relative', - }, - '.mosaic-drop-target.drop-target-hover .drop-target-container': { - display: 'block', - }, - '.mosaic-drop-target.mosaic > .drop-target-container .drop-target.left': { - right: 'calc(100% - 10px )', - }, - '.mosaic-drop-target.mosaic > .drop-target-container .drop-target.right': { - left: 'calc(100% - 10px )', - }, - '.mosaic-drop-target.mosaic > .drop-target-container .drop-target.bottom': { - top: 'calc(100% - 10px )', - }, - '.mosaic-drop-target.mosaic > .drop-target-container .drop-target.top': { - bottom: 'calc(100% - 10px )', - }, - '.mosaic-drop-target .drop-target-container': { - position: 'absolute', - top: '0', - right: '0', - bottom: '0', - left: '0', - display: 'none', - }, - '.mosaic-drop-target .drop-target-container.-dragging': { - display: 'block', - }, - '.mosaic-drop-target .drop-target-container .drop-target': { - position: 'absolute', - top: '0', - right: '0', - bottom: '0', - left: '0', - background: 'rgba(0, 0, 0, 0.2)', - border: '2px solid black', - opacity: '0', - zIndex: '5', - }, - '.mosaic-drop-target .drop-target-container .drop-target.left': { - right: 'calc(100% - 30% )', - }, - '.mosaic-drop-target .drop-target-container .drop-target.right': { - left: 'calc(100% - 30% )', - }, - '.mosaic-drop-target .drop-target-container .drop-target.bottom': { - top: 'calc(100% - 30% )', - }, - '.mosaic-drop-target .drop-target-container .drop-target.top': { - bottom: 'calc(100% - 30% )', - }, - '.mosaic-drop-target .drop-target-container .drop-target.drop-target-hover': { - opacity: '1', - }, - '.mosaic-drop-target .drop-target-container .drop-target.drop-target-hover.left': { - right: 'calc(100% - 50% )', - }, - '.mosaic-drop-target .drop-target-container .drop-target.drop-target-hover.right': { - left: 'calc(100% - 50% )', - }, - '.mosaic-drop-target .drop-target-container .drop-target.drop-target-hover.bottom': { - top: 'calc(100% - 50% )', - }, - '.mosaic-drop-target .drop-target-container .drop-target.drop-target-hover.top': { - bottom: 'calc(100% - 50% )', - }, - '.mosaic-window, .mosaic-preview': { - position: 'relative', - display: 'flex', - fallbacks: [ - { - display: '-webkit-box', - }, - ], - webkitBoxOrient: 'vertical', - webkitBoxDirection: 'normal', - flexDirection: 'column', - overflow: 'hidden', - boxShadow: '0 0 1px rgba(0, 0, 0, 0.2)', - }, - '.mosaic-window .mosaic-window-toolbar, .mosaic-preview .mosaic-window-toolbar': { - zIndex: '4', - display: 'flex', - fallbacks: [ - { - display: '-webkit-box', - }, - ], - webkitBoxPack: 'justify', - justifyContent: 'space-between', - webkitBoxAlign: 'center', - alignItems: 'center', - flexShrink: '0', - height: 30, - background: 'white', - boxShadow: '0 1px 1px rgba(0, 0, 0, 0.2)', - }, - '.mosaic-window .mosaic-window-toolbar.draggable, .mosaic-preview .mosaic-window-toolbar.draggable': { - cursor: 'move', - }, - '.mosaic-window .mosaic-window-title, .mosaic-preview .mosaic-window-title': { - paddingLeft: 15, - webkitBoxFlex: '1', - flex: '1', - textOverflow: 'ellipsis', - whiteSpace: 'nowrap', - overflow: 'hidden', - minHeight: 18, - }, - '.mosaic-window .mosaic-window-controls, .mosaic-preview .mosaic-window-controls': { - display: 'flex', - fallbacks: [ - { - display: '-webkit-box', - }, - ], - height: '100%', - }, - '.mosaic-window .mosaic-window-controls .separator, .mosaic-preview .mosaic-window-controls .separator': { - height: 20, - borderLeft: '1px solid black', - margin: '5px 4px', - }, - '.mosaic-window .mosaic-window-body, .mosaic-preview .mosaic-window-body': { - position: 'relative', - webkitBoxFlex: '1', - flex: '1', - height: '0', - background: 'white', - zIndex: '1', - overflow: 'hidden', - }, - '.mosaic-window .mosaic-window-additional-actions-bar, .mosaic-preview .mosaic-window-additional-actions-bar': { - position: 'absolute', - top: 30, - right: '0', - bottom: 'initial', - left: '0', - height: '0', - overflow: 'hidden', - background: 'white', - webkitBoxPack: 'end', - justifyContent: 'flex-end', - display: 'flex', - fallbacks: [ - { - display: '-webkit-box', - }, - ], - zIndex: '3', - }, - '.mosaic-window .mosaic-window-additional-actions-bar .bp3-button, .mosaic-preview .mosaic-window-additional-actions-bar .bp3-button': { - margin: '0', - }, - '.mosaic-window .mosaic-window-additional-actions-bar .bp3-button:after, .mosaic-preview .mosaic-window-additional-actions-bar .bp3-button:after': { - display: 'none', - }, - '.mosaic-window .mosaic-window-body-overlay, .mosaic-preview .mosaic-window-body-overlay': { - position: 'absolute', - top: '0', - right: '0', - bottom: '0', - left: '0', - opacity: '0', - background: 'white', - display: 'none', - zIndex: '2', - }, - '.mosaic-window.additional-controls-open .mosaic-window-additional-actions-bar, .mosaic-preview.additional-controls-open .mosaic-window-additional-actions-bar': { - height: 30, - }, - '.mosaic-window.additional-controls-open .mosaic-window-body-overlay, .mosaic-preview.additional-controls-open .mosaic-window-body-overlay': { - display: 'block', - }, - '.mosaic-window .mosaic-preview, .mosaic-preview .mosaic-preview': { - height: '100%', - width: '100%', - position: 'absolute', - zIndex: '0', - border: '1px solid black', - maxHeight: 400, - }, - '.mosaic-window .mosaic-preview .mosaic-window-body, .mosaic-preview .mosaic-preview .mosaic-window-body': { - display: 'flex', - fallbacks: [ - { - display: '-webkit-box', - }, - ], - webkitBoxOrient: 'vertical', - webkitBoxDirection: 'normal', - flexDirection: 'column', - webkitBoxAlign: 'center', - alignItems: 'center', - webkitBoxPack: 'center', - justifyContent: 'center', - }, - '.mosaic-window .mosaic-preview h4, .mosaic-preview .mosaic-preview h4': { - marginBottom: 10, - }, - '.mosaic:not(.mosaic-blueprint-theme) .mosaic-default-control.close-button:before': { - content: '\'Close\'', - }, - '.mosaic:not(.mosaic-blueprint-theme) .mosaic-default-control.split-button:before': { - content: '\'Split\'', - }, - '.mosaic:not(.mosaic-blueprint-theme) .mosaic-default-control.replace-button:before': { - content: '\'Replace\'', - }, - '.mosaic:not(.mosaic-blueprint-theme) .mosaic-default-control.expand-button:before': { - content: '\'Expand\'', - }, + '.mosaic': { + height: '100%', + width: '100%', + }, + '.mosaic, .mosaic > *': { + boxSizing: 'border-box', + }, + '.mosaic .mosaic-zero-state': { + position: 'absolute', + top: 6, + right: 6, + bottom: 6, + left: 6, + width: 'auto', + height: 'auto', + zIndex: '1', + }, + '.mosaic-root': { + position: 'absolute', + top: 3, + right: 3, + bottom: 3, + left: 3, + }, + '.mosaic-split': { + position: 'absolute', + zIndex: '1', + touchAction: 'none', + }, + '.mosaic-split:hover': { + background: 'black', + }, + '.mosaic-split .mosaic-split-line': { + position: 'absolute', + }, + '.mosaic-split.-row': { + marginLeft: -3, + width: 6, + cursor: 'ew-resize', + }, + '.mosaic-split.-row .mosaic-split-line': { + top: '0', + bottom: '0', + left: 3, + right: 3, + }, + '.mosaic-split.-column': { + marginTop: -3, + height: 6, + cursor: 'ns-resize', + }, + '.mosaic-split.-column .mosaic-split-line': { + top: 3, + bottom: 3, + left: '0', + right: '0', + }, + '.mosaic-tile': { + position: 'absolute', + margin: 3, + }, + '.mosaic-tile > *': { + height: '100%', + width: '100%', + }, + '.mosaic-drop-target': { + position: 'relative', + }, + '.mosaic-drop-target.drop-target-hover .drop-target-container': { + display: 'block', + }, + '.mosaic-drop-target.mosaic > .drop-target-container .drop-target.left': { + right: 'calc(100% - 10px )', + }, + '.mosaic-drop-target.mosaic > .drop-target-container .drop-target.right': { + left: 'calc(100% - 10px )', + }, + '.mosaic-drop-target.mosaic > .drop-target-container .drop-target.bottom': { + top: 'calc(100% - 10px )', + }, + '.mosaic-drop-target.mosaic > .drop-target-container .drop-target.top': { + bottom: 'calc(100% - 10px )', + }, + '.mosaic-drop-target .drop-target-container': { + position: 'absolute', + top: '0', + right: '0', + bottom: '0', + left: '0', + display: 'none', + }, + '.mosaic-drop-target .drop-target-container.-dragging': { + display: 'block', + }, + '.mosaic-drop-target .drop-target-container .drop-target': { + position: 'absolute', + top: '0', + right: '0', + bottom: '0', + left: '0', + background: 'rgba(0, 0, 0, 0.2)', + border: '2px solid black', + opacity: '0', + zIndex: '5', + }, + '.mosaic-drop-target .drop-target-container .drop-target.left': { + right: 'calc(100% - 30% )', + }, + '.mosaic-drop-target .drop-target-container .drop-target.right': { + left: 'calc(100% - 30% )', + }, + '.mosaic-drop-target .drop-target-container .drop-target.bottom': { + top: 'calc(100% - 30% )', + }, + '.mosaic-drop-target .drop-target-container .drop-target.top': { + bottom: 'calc(100% - 30% )', + }, + '.mosaic-drop-target .drop-target-container .drop-target.drop-target-hover': { + opacity: '1', + }, + '.mosaic-drop-target .drop-target-container .drop-target.drop-target-hover.left': { + right: 'calc(100% - 50% )', + }, + '.mosaic-drop-target .drop-target-container .drop-target.drop-target-hover.right': { + left: 'calc(100% - 50% )', + }, + '.mosaic-drop-target .drop-target-container .drop-target.drop-target-hover.bottom': { + top: 'calc(100% - 50% )', + }, + '.mosaic-drop-target .drop-target-container .drop-target.drop-target-hover.top': { + bottom: 'calc(100% - 50% )', + }, + '.mosaic-window, .mosaic-preview': { + position: 'relative', + display: 'flex', + fallbacks: [ + { + display: '-webkit-box', + }, + ], + webkitBoxOrient: 'vertical', + webkitBoxDirection: 'normal', + flexDirection: 'column', + overflow: 'hidden', + boxShadow: '0 0 1px rgba(0, 0, 0, 0.2)', + }, + '.mosaic-window .mosaic-window-toolbar, .mosaic-preview .mosaic-window-toolbar': { + zIndex: '4', + display: 'flex', + fallbacks: [ + { + display: '-webkit-box', + }, + ], + webkitBoxPack: 'justify', + justifyContent: 'space-between', + webkitBoxAlign: 'center', + alignItems: 'center', + flexShrink: '0', + height: 30, + background: 'white', + boxShadow: '0 1px 1px rgba(0, 0, 0, 0.2)', + }, + '.mosaic-window .mosaic-window-toolbar.draggable, .mosaic-preview .mosaic-window-toolbar.draggable': { + cursor: 'move', + }, + '.mosaic-window .mosaic-window-title, .mosaic-preview .mosaic-window-title': { + paddingLeft: 15, + webkitBoxFlex: '1', + flex: '1', + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', + overflow: 'hidden', + minHeight: 18, + }, + '.mosaic-window .mosaic-window-controls, .mosaic-preview .mosaic-window-controls': { + display: 'flex', + fallbacks: [ + { + display: '-webkit-box', + }, + ], + height: '100%', + }, + '.mosaic-window .mosaic-window-controls .separator, .mosaic-preview .mosaic-window-controls .separator': { + height: 20, + borderLeft: '1px solid black', + margin: '5px 4px', + }, + '.mosaic-window .mosaic-window-body, .mosaic-preview .mosaic-window-body': { + position: 'relative', + webkitBoxFlex: '1', + flex: '1', + height: '0', + background: 'white', + zIndex: '1', + overflow: 'hidden', + }, + '.mosaic-window .mosaic-window-additional-actions-bar, .mosaic-preview .mosaic-window-additional-actions-bar': { + position: 'absolute', + top: 30, + right: '0', + bottom: 'initial', + left: '0', + height: '0', + overflow: 'hidden', + background: 'white', + webkitBoxPack: 'end', + justifyContent: 'flex-end', + display: 'flex', + fallbacks: [ + { + display: '-webkit-box', + }, + ], + zIndex: '3', + }, + '.mosaic-window .mosaic-window-additional-actions-bar .bp3-button, .mosaic-preview .mosaic-window-additional-actions-bar .bp3-button': { + margin: '0', + }, + '.mosaic-window .mosaic-window-additional-actions-bar .bp3-button:after, .mosaic-preview .mosaic-window-additional-actions-bar .bp3-button:after': { + display: 'none', + }, + '.mosaic-window .mosaic-window-body-overlay, .mosaic-preview .mosaic-window-body-overlay': { + position: 'absolute', + top: '0', + right: '0', + bottom: '0', + left: '0', + opacity: '0', + background: 'white', + display: 'none', + zIndex: '2', + }, + '.mosaic-window.additional-controls-open .mosaic-window-additional-actions-bar, .mosaic-preview.additional-controls-open .mosaic-window-additional-actions-bar': { + height: 30, + }, + '.mosaic-window.additional-controls-open .mosaic-window-body-overlay, .mosaic-preview.additional-controls-open .mosaic-window-body-overlay': { + display: 'block', + }, + '.mosaic-window .mosaic-preview, .mosaic-preview .mosaic-preview': { + height: '100%', + width: '100%', + position: 'absolute', + zIndex: '0', + border: '1px solid black', + maxHeight: 400, + }, + '.mosaic-window .mosaic-preview .mosaic-window-body, .mosaic-preview .mosaic-preview .mosaic-window-body': { + display: 'flex', + fallbacks: [ + { + display: '-webkit-box', + }, + ], + webkitBoxOrient: 'vertical', + webkitBoxDirection: 'normal', + flexDirection: 'column', + webkitBoxAlign: 'center', + alignItems: 'center', + webkitBoxPack: 'center', + justifyContent: 'center', + }, + '.mosaic-window .mosaic-preview h4, .mosaic-preview .mosaic-preview h4': { + marginBottom: 10, + }, + '.mosaic:not(.mosaic-blueprint-theme) .mosaic-default-control.close-button:before': { + content: '\'Close\'', + }, + '.mosaic:not(.mosaic-blueprint-theme) .mosaic-default-control.split-button:before': { + content: '\'Split\'', + }, + '.mosaic:not(.mosaic-blueprint-theme) .mosaic-default-control.replace-button:before': { + content: '\'Replace\'', + }, + '.mosaic:not(.mosaic-blueprint-theme) .mosaic-default-control.expand-button:before': { + content: '\'Expand\'', }, };