-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
19 changed files
with
1,571 additions
and
1,064 deletions.
There are no files selected for viewing
25 changes: 13 additions & 12 deletions
25
docs/reference/admin/layouts/_Example/components/Directives.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,18 +1,19 @@ | ||
import { createDirectiveContext } from '@contember/layout'; | ||
import * as React from 'react'; | ||
import { Directives } from '@contember/layout'; | ||
|
||
type DirectivesType = { | ||
'title': string | null | undefined; | ||
export type DirectivesType = { | ||
'full-width': boolean | ||
} | ||
|
||
const directivesDefaultValues: DirectivesType = Object.freeze({ | ||
'title': undefined, | ||
export const initialDirectives: DirectivesType = Object.freeze({ | ||
'full-width': false, | ||
}) | ||
|
||
export const directivesList = Object.keys(directivesDefaultValues) as (keyof DirectivesType)[] | ||
export const [DirectivesProvider, Directive, DirectivesConsumer, useDirectives] = createDirectiveContext<DirectivesType>('Directives', directivesDefaultValues) | ||
// Local export with current DirectivesType specific to the project | ||
export const Directive = Directives.Directive as unknown as Directives.DirectiveComponentType<DirectivesType> | ||
|
||
// Short-hand for <Directive name="title" content={children} /> | ||
export const Title = React.memo<{ children: string | null | undefined }>(({ children }) => ( | ||
<Directive name="title" content={children} /> | ||
)) | ||
// Local export with current DirectivesType specific to the project | ||
export const useDirectives = Directives.useDirectives<DirectivesType> | ||
|
||
export function FullWidth() { | ||
return <Directive name={'full-width'} content={true} /> | ||
} |
4 changes: 4 additions & 0 deletions
4
docs/reference/admin/layouts/_Example/components/EditOrCreateForm.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
// Dummy component to make the example work | ||
export function EditOrCreateForm() { | ||
return null | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
43 changes: 43 additions & 0 deletions
43
docs/reference/admin/layouts/_Example/components/Slots.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import { CommonSlotSources, CommonSlotTargets, Slots, commonSlots } from '@contember/layout' | ||
import { useDocumentTitle } from '@contember/react-utils' | ||
import { memo } from 'react' | ||
|
||
// 1. Defining your own slots: | ||
// highlight-start | ||
const [ | ||
mySlots, // 👈 same array as the argument (for convenience) | ||
MySlotSources, // 👈 components that "portal" their children to other DOM nodes | ||
MySlotTargets, // 👈 components that "receive" children from slot sources | ||
] = Slots.createSlotComponents([ | ||
'Subtitle', | ||
]) | ||
// highlight-end | ||
|
||
// 2. Exporting your slots together with the common ones: | ||
export const slots = [ | ||
...commonSlots, | ||
// highlight-next-line | ||
...mySlots, | ||
] | ||
|
||
export const SlotSources = { | ||
...CommonSlotSources, | ||
// highlight-next-line | ||
...MySlotSources, | ||
} | ||
|
||
export const SlotTargets = { | ||
...CommonSlotTargets, | ||
// highlight-next-line | ||
...MySlotTargets, | ||
} | ||
|
||
export const Title = memo<{ children: string | null | undefined }>(({ children }) => { | ||
// Hook that will update the document title in browser tab: | ||
useDocumentTitle(children) | ||
|
||
return ( | ||
// Title is already defined in CommonSlotSources, so we can use it: | ||
<SlotSources.Title>{children}</SlotSources.Title> | ||
) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,28 +1,23 @@ | ||
import { ApplicationEntrypoint, DataBindingProvider, FeedbackRenderer, PageModule, Pages, runReactApp } from '@contember/admin' | ||
import { LayoutSlotsProvider } from '@contember/layout' | ||
import { ApplicationEntrypoint, PageModule, Pages, runReactApp } from '@contember/admin' | ||
import { Directives, Slots } from '@contember/layout' | ||
import { createRoot } from 'react-dom/client' | ||
import { DirectivesProvider } from './components/Directives' | ||
import { initialDirectives } from './components/Directives' | ||
import { Layout } from './components/Layout' | ||
import './index.css' | ||
|
||
runReactApp( | ||
<DirectivesProvider> | ||
<LayoutSlotsProvider> | ||
<Directives.Provider value={initialDirectives}> | ||
<Slots.Provider> | ||
<ApplicationEntrypoint | ||
apiBaseUrl={import.meta.env.VITE_CONTEMBER_ADMIN_API_BASE_URL as string} | ||
sessionToken={import.meta.env.VITE_CONTEMBER_ADMIN_SESSION_TOKEN as string} | ||
project={'admin-sandbox'} | ||
stage={'live'} | ||
basePath={import.meta.env.BASE_URL} | ||
apiBaseUrl={import.meta.env.VITE_CONTEMBER_ADMIN_API_BASE_URL} | ||
sessionToken={import.meta.env.VITE_CONTEMBER_ADMIN_SESSION_TOKEN} | ||
project={import.meta.env.VITE_CONTEMBER_ADMIN_PROJECT_NAME} | ||
stage="live" | ||
envVariables={{ WEB_URL: import.meta.env.VITE_CONTEMBER_ADMIN_WEB_URL }} | ||
children={ | ||
<DataBindingProvider stateComponent={FeedbackRenderer}> | ||
<Pages children={import.meta.glob<PageModule>('./pages/**/*.tsx')} layout={Layout} /> | ||
</DataBindingProvider> | ||
} | ||
children={<Pages layout={Layout} children={import.meta.glob<PageModule>('./pages/**/*.tsx', { eager: true })} />} | ||
/> | ||
</LayoutSlotsProvider> | ||
</DirectivesProvider>, | ||
</Slots.Provider> | ||
</Directives.Provider>, | ||
null, | ||
(dom, react, onRecoverableError) => createRoot(dom, { onRecoverableError }).render(react), | ||
) |
79 changes: 50 additions & 29 deletions
79
docs/reference/admin/layouts/_Example/my-custom-layout.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,39 +1,60 @@ | ||
import { DropdownContentContainerProvider } from "@contember/admin" | ||
import { | ||
commonSlotTargets, | ||
CommonSlotTargets, | ||
useDocumentTitle, | ||
useLayoutSlotRegistryContext, | ||
} from "@contember/layout" | ||
import { Slots } from "@contember/layout" | ||
import { PropsWithChildren } from "react" | ||
import { useDirectives } from "./components/Directives" | ||
import { SlotTargets, slotTargets } from "./components/Slots" | ||
import { SlotTargets } from "./components/Slots" | ||
|
||
export function MyCustomLayout() { | ||
const { activeSlots } = useLayoutSlotRegistryContext() | ||
const directives = useDirectives() | ||
const { Actions, Back, Logo, Navigation, Sidebar, Title, Profile, Subtitle, Switchers, ...rest } = SlotTargets | ||
|
||
// Make sure we implement all the slots: | ||
if (import.meta.env.DEV) { | ||
const __EMPTY_REST_GUARD: { [key: string]: never } = rest | ||
} | ||
|
||
export function MyCustomLayout({ children }: PropsWithChildren) { | ||
const slotTargetsIfActive = Slots.useTargetsIfActiveFactory(SlotTargets) | ||
|
||
useDocumentTitle(directives.title) | ||
const directives = useDirectives() | ||
|
||
return ( | ||
<div className="layout"> | ||
<header className="layout__header"> | ||
{activeSlots.has(commonSlotTargets.Back) ? <CommonSlotTargets.Back /> : null} | ||
{activeSlots.has(commonSlotTargets.Logo) ? <CommonSlotTargets.Logo /> : null} | ||
{activeSlots.has(commonSlotTargets.Actions) ? <CommonSlotTargets.Actions /> : null} | ||
</header> | ||
<div className="layout" data-full-width={directives ? true : undefined}> | ||
{slotTargetsIfActive(['Logo', 'Actions'], ( | ||
<header className="layout__header"> | ||
<Logo /> | ||
<Actions /> | ||
<Profile /> | ||
</header> | ||
))} | ||
{slotTargetsIfActive(['Navigation'], ( | ||
<aside className="layout__aside"> | ||
<Navigation /> | ||
</aside> | ||
))} | ||
<main className="layout__main"> | ||
<h1>{directives.title}</h1> | ||
{activeSlots.has(slotTargets.Subtitle) ? <SlotTargets.Subtitle /> : null} | ||
{activeSlots.has(commonSlotTargets.Content) ? <CommonSlotTargets.Content /> : null} | ||
<section className="layout__main__content"> | ||
{slotTargetsIfActive(['Back', 'Title'], ( | ||
<> | ||
<Back /> | ||
<Title as="h1" /> | ||
</> | ||
))} | ||
{slotTargetsIfActive(['Subtitle'])} | ||
{children} | ||
</section> | ||
|
||
{slotTargetsIfActive(['Sidebar'], ( | ||
<section className="layout__main__sidebar"> | ||
<Sidebar /> | ||
</section> | ||
))} | ||
</main> | ||
<aside className="layout__aside"> | ||
{activeSlots.has(commonSlotTargets.Navigation) ? <CommonSlotTargets.Navigation /> : null} | ||
{activeSlots.has(commonSlotTargets.Sidebar) ? <CommonSlotTargets.Sidebar /> : null} | ||
</aside> | ||
<footer className="layout__footer"> | ||
</footer> | ||
<DropdownContentContainerProvider /> | ||
<div id="portal-root" /> | ||
|
||
|
||
{slotTargetsIfActive(['Profile', 'Switchers'], ( | ||
<footer className="layout__footer"> | ||
<Switchers /> | ||
<Profile /> | ||
</footer> | ||
))} | ||
</div> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,22 @@ | ||
import { CommonSlots } from '@contember/layout' | ||
import { Title } from '../components/Directives' | ||
import { Slots } from '../components/Slots' | ||
import { EditScope, FieldView, PersistButton } from '@contember/admin' | ||
import { Directive } from '../components/Directives' | ||
import { EditOrCreateForm } from '../components/EditOrCreateForm' | ||
import { SlotSources, Title } from '../components/Slots' | ||
|
||
export default () => ( | ||
<> | ||
<Title>My page title</Title> | ||
<Directive name="full-width" content={true} /> | ||
|
||
<Slots.Subtitle>This is a subtitle</Slots.Subtitle> | ||
<EditScope entity="Article(id = $id)"> | ||
<FieldView field="title" render={title => ( | ||
<Title>{`Edit ${title.getAccessor().value ? title.getAccessor().value : 'Article'}`}</Title> | ||
)} /> | ||
|
||
<CommonSlots.Content> | ||
<p>My page content</p> | ||
</CommonSlots.Content> | ||
<EditOrCreateForm /> | ||
|
||
<SlotSources.Actions> | ||
<PersistButton /> | ||
</SlotSources.Actions> | ||
</EditScope> | ||
</> | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.