Skip to content

Commit

Permalink
@0.3.2: ScreenfulBlock and minor ImageBlock changes (#6)
Browse files Browse the repository at this point in the history
Implementation of ScreenfulBlock: see src/blocks/dev/screenful-block.ts for notes
Minor ImageBlock changes that deprecate with Next
  • Loading branch information
artemis-prime authored Feb 7, 2024
1 parent 73d81ec commit eb2fe26
Show file tree
Hide file tree
Showing 14 changed files with 348 additions and 30 deletions.
10 changes: 8 additions & 2 deletions pkgs/luxdefi-ui/blocks/components/cta-block.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,14 @@ const CtaBlockComponent: React.FC<BlockComponentProps & {
wrapperClasses += 'sm:justify-end '
}

const twoColsOnMobile = containsToken(specifiers, '2-cols-on-mobile') && elements.length === 2
const containerclx = (twoColsOnMobile && agent === 'phone') ?
const containerclx = (
agent === 'phone'
&&
containsToken(specifiers, 'mobile-2-columns')
&&
elements.length > 1
)
?
'grid grid-cols-2 gap-2 self-stretch'
:
'flex flex-col items-stretch gap-2 self-stretch sm:flex-row sm:justify-center '
Expand Down
20 changes: 0 additions & 20 deletions pkgs/luxdefi-ui/blocks/components/image-block.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,26 +29,6 @@ const ImageBlockComponent: React.FC<BlockComponentProps & {
toSpread.height = dimCon.h
}

// This are deprecated as props, and should be added as element styles instead.
// https://nextjs.org/docs/messages/next-image-upgrade-to-13
if (props?.objectFit) {
toSpread.style = {
objectFit: props.objectFit
}
delete props.objectFit
}
if (props?.objectPosition) {
if (toSpread.style) {
toSpread.style.objectPosition = props.objectPosition
}
else {
toSpread.style = {
objectPosition: props.objectPosition
}
}
delete props.objectPosition
}

// https://nextjs.org/docs/app/building-your-application/optimizing/images#responsive
if (agent === 'phone' && fullWidthOnMobile) {
const toSpread: any = {
Expand Down
2 changes: 2 additions & 0 deletions pkgs/luxdefi-ui/blocks/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import HeadingBlock from './heading-block'
import ImageBlock from './image-block'
import VideoBlock from './video-block'
import SpaceBlock from './space-block'
import ScreenfulBlock from './screenful-block'
import type BlockComponentProps from './block-component-props'

export {
Expand All @@ -22,5 +23,6 @@ export {
ImageBlock as ImageBlockComponent,
VideoBlock as VideoBlockComponent,
SpaceBlock as SpaceBlockComponent,
ScreenfulBlock as ScreenfulBlockComponent,
type BlockComponentProps
}
133 changes: 133 additions & 0 deletions pkgs/luxdefi-ui/blocks/components/screenful-block/content.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import React from 'react'

import type { Block, ScreenfulBlock} from '../../def'
import { containsToken, cn } from '../../../util'
import ContentComponent from '../content'

const ContentColumn: React.FC<{
blocks: Block[]
specifiers?: string
agent?: string
className?: string
}> = ({
blocks,
specifiers,
agent,
className=''
}) => {

const specified = (s: string) => (containsToken(specifiers, s))

let modifiers = ''

if (agent !== 'phone') {
if (specified('right')) {
modifiers += 'items-end '

}
else if (specified('center')) {
modifiers += 'items-center '
}
// default to left
else {
modifiers += 'items-start '
}
}
// default to left
else {
modifiers += 'items-start '
}

if (agent !== 'phone') {
if (specified('bottom')) {
modifiers += 'justify-end '
}
// default to top
else {
modifiers += 'justify-start '
}
// right aligned text looks shitty on mobile
if (specified('text-align-right')) {
modifiers += 'text-right '
}
else {
modifiers += 'text-left '
}
}
else {
modifiers += 'justify-start '
}

if (agent === 'phone' && specified('mobile-center-headings')) {
modifiers += 'typography-headings:text-center '
}

return (
<div className={cn('flex flex-col justify-center ' + modifiers, className)} >
<ContentComponent blocks={blocks} agent={agent} />
</div>
)
}

const Content: React.FC<{
block: ScreenfulBlock
agent?: string
className?: string
}> = ({
block: b,
agent,
className=''
}) => {

const specified = (s: string) => (containsToken(b.specifiers, s))
const narrowGutters = specified('narrow-gutters') // eg, for a table object that is large

let outerClasses = (narrowGutters ?
// 44 + 24 = 68, 80 + 32 = 104
'px-6 lg:px-8 2xl:px-2 pb-6 pt-[68px] md:pt-[104px] lg:pt-[112px] '
:
'px-[8vw] xl:px-[1vw] pb-[8vh] pt-[calc(44px+8vh)] md:pt-[calc(80px+8vh)] ')
// + 'border border-accent ' // debug
+ ' overflow-y-hidden' // safety valve

let moreModifiers = ''
// 40px + 32px
if (agent && agent !== 'desktop') {
moreModifiers += 'pt-[72px] pb-0 px-4 '
}

const multiColumnLayoutClx = (agent === 'phone') ?
'flex flex-col gap-6'
:
`grid grid-cols-${b.contentColumns.length} gap-8`

const orderclx = (columnIndex: number): string => {
if ((agent !== 'phone') || !b.mobileOrder || !b.mobileOrder.includes(columnIndex)) return ''
const orderIndex = b.mobileOrder.indexOf(columnIndex)
return (orderIndex >= 0) ? `order-${orderIndex}` : '' // one-based in flexbox slec
}


return b.contentColumns.length == 1 ? (
<ContentColumn
blocks={b.contentColumns[0]}
specifiers={b.columnSpecifiers?.[0]}
agent={agent}
className={cn(outerClasses, moreModifiers, className)}
/>
) : (
<div className={cn(multiColumnLayoutClx, outerClasses, moreModifiers, className)}>
{b.contentColumns.map((column, index) => (
<ContentColumn
blocks={column}
specifiers={b.columnSpecifiers?.[index]}
agent={agent}
className={orderclx(index)}
key={index}
/>
))}
</div>
)
}

export default Content
54 changes: 54 additions & 0 deletions pkgs/luxdefi-ui/blocks/components/screenful-block/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React from 'react'
import dynamic from 'next/dynamic'

import type { Block, ScreenfulBlock, VideoBlock } from '../../def'
import { cn } from '../../../util'
import { ApplyTypography } from '../../../primitives'

import Poster from './poster-background'
import Content from './content'
const Video = dynamic(() => (import('./video-background')), {ssr: false, loading: () => (<></>)})

const ScreenfulComponent: React.FC<{
block: Block
agent?: string
initialInView?: boolean
snapTile?: boolean
className?: string
}> = ({
block,
agent,
initialInView=false,
snapTile=false,
className=''
}) => {

if (block.blockType !== 'screenful') {
return <>screenful block required</>
}
const b = block as ScreenfulBlock

const hasBannerVideo = (): boolean => (!!b.banner && (typeof b.banner === 'object'))

const contentclx = 'z-10 absolute left-0 right-0 top-0 bottom-0 xl:mx-auto max-w-screen-xl'
const tileHeight = (agent === 'desktop') ? 'h-full ' : 'h-[100svh] '

return (
<section className={cn('h-[100vh]', (snapTile ? 'snap-start snap-always' : ''), className)}>
<ApplyTypography className={tileHeight + 'w-full flex flex-row justify-center self-stretch'} >
<Poster banner={b.banner}>
{hasBannerVideo() && (
<Video
block={b.banner! as VideoBlock}
className='z-0 absolute top-0 left-0 bottom-0 right-0'
initialInView={initialInView}
/>
)}
<Content block={b} agent={agent} className={contentclx} />
</Poster>
</ApplyTypography>
</section>
)
}

export default ScreenfulComponent
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React, { type PropsWithChildren } from 'react'

import type { VideoBlock } from '../../def'
import { cn } from '../../../util'

const Poster: React.FC<{
banner: VideoBlock | string | undefined,
className?: string
} & PropsWithChildren> = ({
children,
banner,
className=''
}) => (
banner ? (
<div
className={cn('relative', className)}
style={{
height: '100%',
width: '100%',
backgroundImage: `url(${(typeof banner === 'string') ? banner : banner.poster!})`,
backgroundSize: 'cover',
backgroundRepeat: 'no-repeat',
}}
>
{children}
</div>
) : (
<div className={cn('bg-transparent h-full v-full relative', className)}>
{children}
</div>
)
)

export default Poster
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
'use client'
import React from 'react'

import { useInView } from 'react-intersection-observer'

import type { VideoBlock } from '../../def'

const VideoBG: React.FC<{
block: VideoBlock,
className?: string,
initialInView: boolean
}> = ({
block,
className='',
initialInView
}) => {
const { ref, inView } = useInView({
threshold: 0.75,
initialInView,
})

return block ? (
<div ref={ref} className={className}>
{inView && (
<video
autoPlay
loop
muted
style={{
margin: 0,
height: '100%',
width: '100%',
objectFit: 'cover',
}}
>
{block.sources?.map((src, index) => (
<source key={index} src={src} />
))}
</video>
)}
</div>
) : null
}

export default VideoBG
2 changes: 1 addition & 1 deletion pkgs/luxdefi-ui/blocks/components/space-block.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const SpaceBlockComponent: React.FC<BlockComponentProps> = ({

return (
<ApplyTypography>
<Tag className={`invisible m-0 ${Tag === 'div' ? 'h-[1px]' : ''} ${className}`} >&nbsp;</Tag>
<Tag className={`invisible m-0 ${Tag === 'div' ? 'h-4' : ''} ${className}`} >&nbsp;</Tag>
</ApplyTypography>
)
}
Expand Down
8 changes: 6 additions & 2 deletions pkgs/luxdefi-ui/blocks/def/image-block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,12 @@ interface ImageBlock extends Block {
props?: {
sizes?: string
fill?: boolean
objectFit?: string
objectPosition?: string
style?: {
objectFit?: string
objectPosition?: string
width?: number | string
height?: number | string
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions pkgs/luxdefi-ui/blocks/def/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type HeadingBlock from './heading-block'
import type ImageBlock from './image-block'
import type VideoBlock from './video-block'
import type SpaceBlock from './space-block'
import type ScreenfulBlock from './screenful-block'

export {
type AccordianBlock,
Expand All @@ -20,4 +21,5 @@ export {
type ImageBlock,
type VideoBlock,
type SpaceBlock,
type ScreenfulBlock,
}
Loading

0 comments on commit eb2fe26

Please sign in to comment.