Skip to content

Commit

Permalink
feat(adapt): Adapt.Contents forwards space props when they exist
Browse files Browse the repository at this point in the history
  • Loading branch information
natew committed Dec 15, 2022
1 parent 46fae11 commit 57ca2fa
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 114 deletions.
8 changes: 5 additions & 3 deletions apps/sandbox/Sandbox.tsx
Expand Up @@ -49,7 +49,7 @@ type X = ColorTokens | ThemeValueFallback | OpaqueColorValue | undefined
const y: X = ''

// eslint-disable-next-line no-console
console.log(getMedia().sm)
console.log('[Sandbox] getMedia().sm', getMedia().sm)

const CustomButtonFrame = styled(ButtonFrame, {
variants: {
Expand Down Expand Up @@ -131,7 +131,9 @@ export const Sandbox = () => {
}}
>
{/* <AnimationsHoverDemo /> */}
<SelectDemo />
{/* <SelectDemo /> */}

<DialogDemo />

{/* <>make sure enterStyle works without scale set on defaults</>
<Square
Expand All @@ -146,7 +148,7 @@ export const Sandbox = () => {
/> */}
{/* <AnimationsPresenceDemo /> */}
{/* <Square size={100} bc="red" animation="bouncy" /> */}
<AnimationsPresenceDemo />
{/* <AnimationsPresenceDemo /> */}
{/* <SandboxExample /> */}
{/* <SelectDemo /> */}
{/* <PopoverDemo /> */}
Expand Down
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -25,6 +25,7 @@
"watch": "npm-run-all --parallel watch:ts watch:build",
"watch:ts": "tsc -b -w --preserveWatchOutput tsconfig.build.json",
"watch:build": "SKIP_TYPES_INITIAL=1 ultra -r --no-pretty --concurrency 200 watch",
"watch:js": "SKIP_TYPES=1 yarn watch:build",
"clean:build": "turbo run clean:build",
"clean:ts": "tsc -b --clean tsconfig.build.json",
"clean": "turbo run clean:build --parallel",
Expand Down
80 changes: 80 additions & 0 deletions packages/adapt/src/Adapt.tsx
@@ -0,0 +1,80 @@
import {
MediaQueryKey,
isTouchable,
isWeb,
useIsomorphicLayoutEffect,
withStaticProperties,
} from '@tamagui/core'
import { createContext, createElement, useContext, useMemo, useState } from 'react'

export type AdaptProps = {
when?: MediaQueryKey
platform?: 'native' | 'web' | 'touch'
children?: any
}

type Component = (props: any) => any
type AdaptParentContextI = {
Contents: Component
setWhen: (when: MediaQueryKey) => any
}

const AdaptParentContext = createContext<AdaptParentContextI | null>(null)

// forward props
export const AdaptContents = (props: any) => {
const context = useContext(AdaptParentContext)
if (!context || !context.Contents) {
throw new Error(`Adapt not supported by this component`)
}
return createElement(context.Contents, props)
}

AdaptContents['shouldForwardSpace'] = true

export const useAdaptParent = ({ Contents }: { Contents: AdaptParentContextI['Contents'] }) => {
const [when, setWhen] = useState<MediaQueryKey | null>(null)

const AdaptProvider = useMemo(() => {
const context: AdaptParentContextI = {
Contents,
setWhen,
}

return (props: { children?: any }) => {
return (
<AdaptParentContext.Provider value={context}>{props.children}</AdaptParentContext.Provider>
)
}
}, [Contents])

return {
AdaptProvider,
when,
}
}

export const Adapt = withStaticProperties(
function Adapt({ platform, when, children }: AdaptProps) {
const context = useContext(AdaptParentContext)

let enabled = !platform
if (platform === 'touch') enabled = isTouchable
if (platform === 'native') enabled = !isWeb
if (platform === 'web') enabled = isWeb

useIsomorphicLayoutEffect(() => {
if (!enabled) return
context?.setWhen(when as MediaQueryKey)
}, [when, context, enabled])

if (!enabled) {
return null
}

return children
},
{
Contents: AdaptContents,
}
)
76 changes: 1 addition & 75 deletions packages/adapt/src/index.tsx
@@ -1,75 +1 @@
import {
MediaQueryKey,
isTouchable,
isWeb,
useIsomorphicLayoutEffect,
withStaticProperties,
} from '@tamagui/core'
import { createContext, createElement, useContext, useMemo, useState } from 'react'

export type AdaptProps = {
when?: MediaQueryKey
platform?: 'native' | 'web' | 'touch'
children?: any
}

type Component = (props: any) => any
type AdaptParentContextI = {
Contents: Component
setWhen: (when: MediaQueryKey) => any
}

const AdaptParentContext = createContext<AdaptParentContextI | null>(null)

export const AdaptContents = () => {
const context = useContext(AdaptParentContext)
if (!context || !context.Contents) {
throw new Error(`Missing parent adapatable component, Adapt not supported here`)
}
return createElement(context.Contents)
}

export const useAdaptParent = ({ Contents }: { Contents: AdaptParentContextI['Contents'] }) => {
const [when, setWhen] = useState<MediaQueryKey | null>(null)

const AdaptProvider = useMemo(() => {
const context: AdaptParentContextI = {
Contents,
setWhen,
}

return (props: { children?: any }) => (
<AdaptParentContext.Provider value={context}>{props.children}</AdaptParentContext.Provider>
)
}, [Contents])

return {
AdaptProvider,
when,
}
}

export const Adapt = withStaticProperties(
function Adapt({ platform, when, children }: AdaptProps) {
const context = useContext(AdaptParentContext)

let enabled = !platform
if (platform === 'touch') enabled = isTouchable
if (platform === 'native') enabled = !isWeb
if (platform === 'web') enabled = isWeb

useIsomorphicLayoutEffect(() => {
if (!enabled) return
context?.setWhen(when as MediaQueryKey)
}, [when, context, enabled])

if (!enabled) {
return null
}

return children
},
{
Contents: AdaptContents,
}
)
export * from './Adapt'
5 changes: 2 additions & 3 deletions packages/core/src/createComponent.tsx
Expand Up @@ -1101,11 +1101,10 @@ export function spacedChildren({
const len = childrenList.length
if (len <= 1 && !isZStack) {
if (len === 1) {
// forward space! only when one component
// doesn't make sense to forward space to all children
// forward space! only when one component doesn't make sense to forward space to all children
const [onlyChild] = childrenList
if (React.isValidElement(onlyChild) && onlyChild.type?.['shouldForwardSpace']) {
return React.cloneElement(onlyChild, { space } as any)
return React.cloneElement(onlyChild, { space, direction, spaceFlex, separator } as any)
}
}
return childrenList
Expand Down
61 changes: 30 additions & 31 deletions packages/demos/src/DialogDemo.tsx
Expand Up @@ -12,7 +12,7 @@ export function DialogDemo() {

<Adapt when="sm" platform="touch">
<Sheet zIndex={200_000} modal dismissOnSnapToBottom>
<Sheet.Frame padding="$4">
<Sheet.Frame padding="$4" space>
<Adapt.Contents />
</Sheet.Frame>
<Sheet.Overlay />
Expand Down Expand Up @@ -45,39 +45,38 @@ export function DialogDemo() {
scale={1}
opacity={1}
y={0}
space
>
<YStack space>
<Dialog.Title>Edit profile</Dialog.Title>
<Dialog.Description>
Make changes to your profile here. Click save when you're done.
</Dialog.Description>
<Fieldset space="$4" horizontal>
<Label w={160} justifyContent="flex-end" htmlFor="name">
Name
</Label>
<Input f={1} id="name" defaultValue="Nate Wienert" />
</Fieldset>
<Fieldset space="$4" horizontal>
<Label w={160} justifyContent="flex-end" htmlFor="username">
Food
</Label>
<SelectDemo />
</Fieldset>
<Dialog.Title>Edit profile</Dialog.Title>
<Dialog.Description>
Make changes to your profile here. Click save when you're done.
</Dialog.Description>
<Fieldset space="$4" horizontal>
<Label w={160} justifyContent="flex-end" htmlFor="name">
Name
</Label>
<Input f={1} id="name" defaultValue="Nate Wienert" />
</Fieldset>
<Fieldset space="$4" horizontal>
<Label w={160} justifyContent="flex-end" htmlFor="username">
Food
</Label>
<SelectDemo />
</Fieldset>

<YStack ai="flex-end" mt="$2">
<Dialog.Close asChild>
<Button theme="alt1" aria-label="Close">
Save changes
</Button>
</Dialog.Close>
</YStack>

<Unspaced>
<Dialog.Close asChild>
<Button pos="absolute" t="$-2" r="$-2" size="$3" circular icon={X} />
</Dialog.Close>
</Unspaced>
<YStack ai="flex-end" mt="$2">
<Dialog.Close asChild>
<Button theme="alt1" aria-label="Close">
Save changes
</Button>
</Dialog.Close>
</YStack>

<Unspaced>
<Dialog.Close asChild>
<Button pos="absolute" t="$2" r="$2" size="$3" circular icon={X} />
</Dialog.Close>
</Unspaced>
</Dialog.Content>
</Dialog.Portal>
</Dialog>
Expand Down
8 changes: 6 additions & 2 deletions packages/dialog/src/Dialog.tsx
Expand Up @@ -501,9 +501,13 @@ const DialogContentImpl = React.forwardRef<TamaguiElement, DialogContentImplProp

const SHEET_CONTENTS_NAME = 'DialogSheetContents'

export const DialogSheetContents = ({ __scopeDialog }: ScopedProps<{}>) => {
export const DialogSheetContents = ({
__scopeDialog,
name,
...props
}: ScopedProps<{ name: string }>) => {
const context = useDialogContext(SHEET_CONTENTS_NAME, __scopeDialog)
return <PortalHost name={`${context.scopeKey}SheetContents`}></PortalHost>
return <PortalHost forwardProps={props} name={`${context.scopeKey}SheetContents`} />
}

DialogSheetContents.displayName = SHEET_CONTENTS_NAME
Expand Down

0 comments on commit 57ca2fa

Please sign in to comment.