#@wethecurious/wtc-exhibit-base-lib
Shared library for WTC Treatments using React. Used for both BrightSign device exhibits and PC-based web exhibits.
The recommended way to use this library is to create a new app using wtc-react-app-template
.
We don't recommend starting from scratch and using this library.
##Usage
All items are exported from the index:
import {BodyA, AppIcons /* etc */} from '@wethecurious/wtc-exhibit-base-libs'
Don't import from files 'inside' the library, only from the root
##See the full API documentation for all items
##AppText
Default typography for the app.
import {
Heading, // capitalized text for title at top
Header1A, // huge title
Header2A, // medium title
Header3A, // normal ittle
BodyA, // normal text
BodyB, // small text
} from '#@wethecurious/wtc-exhibit-base-lib';
Use for in-app Typography. Sizes automatically scales for 2k and 4k screens.
Note due to a limitation on the BrightSign, we need to manually import the font to use in the index.html file.
<head>
<link href="https://fonts.googleapis.com/css?family=Barlow:regular,medium&display=swap" rel="stylesheet">
</head>
##AppIcons
Common SVG icons for use in apps, stored as dataURLs.
Be sure to add quotes when using in background-image, e.g.
background-image: url("${AppIcons.back}")
.
import {
AppIcons
} from '#@wethecurious/wtc-exhibit-base-lib';
const Item = styled.div`
background-image: url("${AppIcons.back}")
background-size: 100%;
`;
const Img = () => {
return <img src={AppIcons.cross}/>
}
const FooterButtons = () => {
return <FooterButtonsWrapper center>
<FooterIconButton large src={AppIcons.tick}/>
</FooterButtonsWrapper>
}
##Footer Buttons
In these apps, footer buttons are circular buttons centered on the footer 'line'.
To make it easier to lay these out, use , , . These can be used inside the 'Page' component. The layout will work only if the 'page' component fills the space on the screen left after the footer, and not if the page goes 'under' the footer.
const MyPage = () => {
return (<>
{/* my page content */}
<FooterButtonsWrapper center>
<FooterIconButton large src={AppIcons.tick} onClick={()=>{}}/>
</FooterButtonsWrapper>
<FooterButtonsWrapper leftPadding rightPadding>
<FooterIconButton src={AppIcons.home} onClick={()=>{}}/>
<div style={{flex:1}}/>
<FooterIconButton src={AppIcons.next} onClick={()=>{}}/>
</FooterButtonsWrapper>
</>);
}
const CONTAINER_FLEX_STYLE = {display: 'flex', flex: 1, zIndex: 1};
const Main = () => {
return (<>
<Fade
show={currentPage === 'myPage'}
containerStyle={CONTAINER_FLEX_STYLE}
onFadeOutComplete={handleFadeOutComplete}
>
<MyPage/>
</Fade>
<FooterLandscape/>
</>);
}
##Navigation with usePageNavigation
Used for animated transitions between pages.
Use with a string enum of all the page names in the app:
import {usePageNavigation, Fade} from '#@wethecurious/wtc-exhibit-base-lib';
type Page = 'attract' | 'results' | 'outro';
export const Main = () => {
const {currentPage, navigateTo, handleFadeOutComplete} = usePageNavigation<Page>('attract' /* initial page */);
const handleNext = () => {
navigateTo('outro'); // Call navigateTo to go to other pages
}
// To be animated, each page should be wrapped in a <Fade/> component
return <>
<Fade
show={currentPage === 'attract'} // where 'attract' is a value in Page
containerStyle={CONTAINER_ABS_STYLE} // e.g. full screen or flexed
onFadeOutComplete={handleFadeOutComplete} // handleFadeOutComplete is returned by this usePageNavigation hook
> .. your page here .. </Fade>
</>
};
##Analytics
Features:
- In-app viewer for recent redux messages
- Automatic analytics for page changes (see
usePageNavigation
) - Automatic analytics for Media Controls usage (play/pause/replay) (see
MediaControls
) - Automatic analytics for Restart Screen (see
RestartScreen
)
Some useful hooks:
-
usePrevious
: When you need the previous value of a prop, use this -
useTheme
: To grab the styled-components theme
##CMSAppDataProvider
download, validates, and provides access to data from the Treatment CMS
Place at the root of your application to enable the useCMSAppData
.
Also:
- Makes the styled-components theme available to child items via
useTheme
. - Validates many aspects of the exhibits's data.
- Catch errors during rendering, in lifecycle methods, and in constructors of the whole tree bellow CMSAppDataProvider, note that it won't catch errors in a callback for example. A custom error screen is displayed where a member of the Staff can unlock and see the log screen, the default password to do that is
115599
but it can be customized by definingREACT_APP_ADMIN_PIN
in the .env file.
Additional Promise-based steps to complete before running the app can be passed in as startupTasks
- staticTheme: To maintain the theme within your app source, pass in the theme here (can use e.g.
import myTheme from './themes/json'
) - startupTasks: Promise for additional tasks to complete during startup. You're passed redux's
dispatch
prop if you want to dispatch actions to redux.
Example:
<MainWindow size="2k" orientation="landscape">
<ReduxProvider store={store}>
<CMSAppDataProvider<CMSContent> staticTheme={staticTheme} resolution="2k">
{/* Now components in here can use `useCMSAppData` */}
</CMSAppDataProvider>
</ReduxProvider>
</MainWindow>
Note, in the above CMSContent is a generated TS type for the actual CMS content. We pass as a generic type parameter to allows the
startupTasks
to have strongly-typed access to the CMS content entries (e.g.object_glass_title
).
Place at the root of the app to force a specific screensize
- size: 2k, 4k
- orientation: 'landscape' | 'portrait' | 'portraitUpsideDown'
Example:
<MainWindow size="2k" orientation="landscape">
<ReduxProvider store={store}>
<CMSAppDataProvider staticTheme={staticTheme} contentSchema={contentSchema}>
<BrowserRouter>
<>
{/* actual routes are here */}
</>
</BrowserRouter>
</CMSAppDataProvider>
</ReduxProvider>
<CustomMouseCursor />
</MainWindow>