-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #691 from contember/feat/dimensions
dimensions switcher and renderer
- Loading branch information
Showing
26 changed files
with
765 additions
and
20 deletions.
There are no files selected for viewing
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
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
1 change: 0 additions & 1 deletion
1
packages/admin/src/components/bindingFacade/environment/index.ts
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,3 +1,2 @@ | ||
export * from './SideDimensions' | ||
export * from './DimensionsSwitcher' | ||
export * from './Variable' |
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
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,39 @@ | ||
import { Slots } from '../../lib/components/slots' | ||
import { Binding, PersistButton } from '../../lib/components/binding' | ||
import * as React from 'react' | ||
import { DimensionsSwitcher, SideDimensions } from '../../lib/components/dimensions' | ||
import { EntitySubTree, Field, Variable } from '@contember/interface' | ||
import { InputField, TextareaField } from '../../lib/components/form' | ||
import { Card, CardContent, CardHeader, CardTitle } from '../../lib/components/ui/card' | ||
|
||
export default () => { | ||
return <> | ||
<Binding> | ||
<DimensionsSwitcher | ||
options="DimensionsLocale" | ||
slugField="code" | ||
dimension="locale" | ||
isMulti | ||
> | ||
<Field field="label" /> | ||
</DimensionsSwitcher> | ||
</Binding> | ||
|
||
<Binding> | ||
<Slots.Actions><PersistButton /></Slots.Actions> | ||
<EntitySubTree entity="DimensionsItem(unique=unique)"> | ||
<SideDimensions dimension="locale" as="currentLocale" field="locales(locale.code=$currentLocale)"> | ||
<Card> | ||
<CardHeader> | ||
<CardTitle><Variable name="currentLocale" /></CardTitle> | ||
</CardHeader> | ||
<CardContent> | ||
<InputField field="title" /> | ||
<TextareaField field="content" /> | ||
</CardContent> | ||
</Card> | ||
</SideDimensions> | ||
</EntitySubTree> | ||
</Binding> | ||
</> | ||
} |
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,7 +1,5 @@ | ||
import * as React from 'react' | ||
|
||
export default () => { | ||
debugger | ||
const foo = React.useMemo(() => 1, []) | ||
return <>Hello!</> | ||
} |
135 changes: 135 additions & 0 deletions
135
packages/playground/admin/lib/components/dimensions.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,135 @@ | ||
import { | ||
Component, | ||
DimensionLink, | ||
DimensionRenderer, | ||
Entity, | ||
EntityAccessor, | ||
Field, | ||
HasOne, | ||
StaticRender, | ||
SugaredQualifiedEntityList, | ||
SugaredRelativeSingleEntity, | ||
SugaredRelativeSingleField, | ||
useDimensionState, | ||
useEntity, | ||
} from '@contember/interface' | ||
import { DataView, DataViewEachRow, DataViewLoaderState, DataViewSortingDirections, useDataViewEntityListAccessor } from '@contember/react-dataview' | ||
import * as React from 'react' | ||
import { ReactNode, useMemo } from 'react' | ||
import { CheckIcon } from 'lucide-react' | ||
import { Loader } from './ui/loader' | ||
import { Popover, PopoverContent, PopoverTrigger } from './ui/popover' | ||
import { Button } from './ui/button' | ||
|
||
export interface DimensionsSwitcherProps { | ||
options: SugaredQualifiedEntityList['entities'] | ||
orderBy?: DataViewSortingDirections | ||
dimension: string | ||
children: ReactNode | ||
slugField: SugaredRelativeSingleField['field'] | ||
isMulti?: boolean | ||
} | ||
|
||
export const DimensionsSwitcher = Component(({ options, dimension, children, slugField, orderBy, isMulti }: DimensionsSwitcherProps) => { | ||
return ( | ||
<DataView entities={options} initialSorting={orderBy}> | ||
<DataViewLoaderState initial refreshing> | ||
<Loader position={'static'} /> | ||
</DataViewLoaderState> | ||
<DataViewLoaderState loaded> | ||
|
||
<Popover> | ||
<PopoverTrigger> | ||
<Button variant={'outline'} size="sm"> | ||
<DimensionSwitcherCurrentValues dimension={dimension} slugField={slugField}> | ||
{children} | ||
</DimensionSwitcherCurrentValues> | ||
</Button> | ||
</PopoverTrigger> | ||
<PopoverContent className="p-2" align="start"> | ||
<div className="flex flex-col gap-1"> | ||
<DataViewEachRow> | ||
<DimensionSwitcherItem dimension={dimension} slugField={slugField} isMulti={isMulti}> | ||
{children} | ||
<StaticRender> | ||
<Field field={slugField} /> | ||
</StaticRender> | ||
</DimensionSwitcherItem> | ||
</DataViewEachRow> | ||
</div> | ||
</PopoverContent> | ||
</Popover> | ||
</DataViewLoaderState> | ||
</DataView> | ||
) | ||
}) | ||
|
||
const DimensionSwitcherCurrentValues = ({ children, dimension, slugField }: { children: ReactNode, dimension: string, slugField: SugaredRelativeSingleField['field'] }) => { | ||
const entitiesBySlug = useDimensionEntitiesBySlug(slugField) | ||
|
||
const currentDimensionValue = useDimensionState({ | ||
dimension, | ||
defaultValue: Object.keys(entitiesBySlug)[0], | ||
storage: 'local', | ||
}) | ||
|
||
const values = useMemo(() => currentDimensionValue.map(it => entitiesBySlug[it]).filter(Boolean), [currentDimensionValue, entitiesBySlug]) | ||
|
||
return ( | ||
<div className="flex gap-1"> | ||
{values.map(it => ( | ||
<Entity key={it.key} accessor={it}> | ||
<div className={'gap-1 group text-black text-left inline-flex items-center px-1 text-sm border-b'}> | ||
<span>{children}</span> | ||
</div> | ||
</Entity> | ||
))} | ||
</div> | ||
) | ||
} | ||
|
||
|
||
const DimensionSwitcherItem = ({ children, dimension, slugField, isMulti }: { children: ReactNode, dimension: string, slugField: SugaredRelativeSingleField['field'], isMulti?: boolean }) => { | ||
const entity = useEntity() | ||
const slugValue = entity.getField<string>(slugField).value | ||
if (!slugValue) { | ||
return null | ||
} | ||
|
||
return ( | ||
<DimensionLink dimension={dimension} value={slugValue} action={isMulti ? 'toggle' : 'set'}> | ||
<a className={'gap-1 group text-gray-800 text-left inline-flex items-center px-1 py-1 text-sm rounded transition-all hover:bg-accent hover:text-accent-foreground group data-[active]:text-black'}> | ||
<CheckIcon className={'w-3 h-3 hidden group-data-[active]:block'} /> | ||
<span className={'w-3 h-3 group-data-[active]:hidden'} /> | ||
<span>{children}</span> | ||
</a> | ||
</DimensionLink> | ||
) | ||
} | ||
|
||
export interface SideDimensionsProps { | ||
dimension: string | ||
as: string | ||
field: SugaredRelativeSingleEntity['field'] | ||
children: ReactNode | ||
} | ||
|
||
export const SideDimensions = Component<SideDimensionsProps>(({ dimension, children, as, field }) => { | ||
return ( | ||
<div className="flex mt-4 gap-4"> | ||
<DimensionRenderer dimension={dimension} as={as}> | ||
<HasOne field={field}> | ||
<div className="flex-1"> | ||
{children} | ||
</div> | ||
</HasOne> | ||
</DimensionRenderer> | ||
</div> | ||
) | ||
}) | ||
|
||
|
||
const useDimensionEntitiesBySlug = (slugField: SugaredRelativeSingleField['field']): Record<string, EntityAccessor> => { | ||
const accessor = useDataViewEntityListAccessor() | ||
return useMemo(() => Object.fromEntries(Array.from(accessor ?? []).map(it => [it.getField<string>(slugField).value, it])), [accessor, slugField]) | ||
} |
Oops, something went wrong.