@hanzo/ui 0.5.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. package/assets/lux-site-icons/android-chrome-192x192.png +0 -0
  2. package/assets/lux-site-icons/android-chrome-512x512.png +0 -0
  3. package/assets/lux-site-icons/apple-touch-icon.png +0 -0
  4. package/assets/lux-site-icons/favicon-16x16.png +0 -0
  5. package/assets/lux-site-icons/favicon-32x32.png +0 -0
  6. package/assets/lux-site-icons/favicon.ico +0 -0
  7. package/assets/standard-docs/LUX-NFT-Terms-and-Conditions.pdf +0 -0
  8. package/assets/standard-docs/LUX-Privacy-Policy.pdf +0 -0
  9. package/blocks/components/accordian-block.tsx +48 -0
  10. package/blocks/components/block-component-props.ts +11 -0
  11. package/blocks/components/bullet-cards-block.tsx +43 -0
  12. package/blocks/components/card-block.tsx +213 -0
  13. package/blocks/components/carte-blanche-block/index.tsx +98 -0
  14. package/blocks/components/content.tsx +70 -0
  15. package/blocks/components/cta-block.tsx +98 -0
  16. package/blocks/components/enh-heading-block.tsx +194 -0
  17. package/blocks/components/grid-block/grid-block-mutator.ts +12 -0
  18. package/blocks/components/grid-block/index.tsx +83 -0
  19. package/blocks/components/grid-block/mutator-registry.ts +10 -0
  20. package/blocks/components/grid-block/table-borders.mutator.ts +47 -0
  21. package/blocks/components/group-block.tsx +83 -0
  22. package/blocks/components/heading-block.tsx +88 -0
  23. package/blocks/components/image-block.tsx +108 -0
  24. package/blocks/components/index.ts +30 -0
  25. package/blocks/components/screenful-block/content.tsx +115 -0
  26. package/blocks/components/screenful-block/index.tsx +77 -0
  27. package/blocks/components/screenful-block/poster-background.tsx +34 -0
  28. package/blocks/components/screenful-block/video-background.tsx +45 -0
  29. package/blocks/components/space-block.tsx +66 -0
  30. package/blocks/components/video-block.tsx +137 -0
  31. package/blocks/def/accordian-block.ts +14 -0
  32. package/blocks/def/block.ts +7 -0
  33. package/blocks/def/bullet-cards-block.ts +20 -0
  34. package/blocks/def/card-block.ts +24 -0
  35. package/blocks/def/carte-blanche-block.ts +20 -0
  36. package/blocks/def/cta-block.ts +19 -0
  37. package/blocks/def/element-block.ts +11 -0
  38. package/blocks/def/enh-heading-block.ts +45 -0
  39. package/blocks/def/grid-block.ts +16 -0
  40. package/blocks/def/group-block.ts +11 -0
  41. package/blocks/def/heading-block.ts +15 -0
  42. package/blocks/def/image-block.ts +36 -0
  43. package/blocks/def/index.ts +35 -0
  44. package/blocks/def/screenful-block.ts +51 -0
  45. package/blocks/def/space-block.ts +64 -0
  46. package/blocks/def/video-block.ts +28 -0
  47. package/blocks/index.ts +2 -0
  48. package/common/chat-widget.tsx +75 -0
  49. package/common/contact-dialog/contact-form.tsx +111 -0
  50. package/common/contact-dialog/disclaimer.tsx +13 -0
  51. package/common/contact-dialog/index.tsx +48 -0
  52. package/common/copyright.tsx +21 -0
  53. package/common/drawer-menu.tsx +51 -0
  54. package/common/footer.tsx +77 -0
  55. package/common/head-metadata/from-next/metadata-types.ts +158 -0
  56. package/common/head-metadata/from-next/opengraph-types.ts +267 -0
  57. package/common/head-metadata/from-next/twitter-types.ts +92 -0
  58. package/common/head-metadata/index.tsx +208 -0
  59. package/common/header/index.tsx +57 -0
  60. package/common/header/mobile-nav.tsx +72 -0
  61. package/common/header/theme-toggle.tsx +26 -0
  62. package/common/icons/github.tsx +14 -0
  63. package/common/icons/index.tsx +34 -0
  64. package/common/icons/lux-logo.tsx +10 -0
  65. package/common/icons/secure-delivery.tsx +13 -0
  66. package/common/icons/social-icon.tsx +35 -0
  67. package/common/icons/youtube-logo.tsx +59 -0
  68. package/common/index.ts +14 -0
  69. package/common/logo.tsx +71 -0
  70. package/common/mini-chart/index.tsx +8 -0
  71. package/common/mini-chart/mini-chart-props.ts +44 -0
  72. package/common/mini-chart/mini-chart.tsx +76 -0
  73. package/common/mini-chart/wrapper.tsx +23 -0
  74. package/context-providers/index.ts +1 -0
  75. package/context-providers/theme-provider.tsx +20 -0
  76. package/next/README.md +11 -0
  77. package/next/determine-device-middleware.ts +16 -0
  78. package/next/fonts/DrukTextWide-Bold-Trial.otf +0 -0
  79. package/next/fonts/DrukTextWide-Heavy-Trial.otf +0 -0
  80. package/next/fonts/DrukTextWide-Medium-Trial.otf +0 -0
  81. package/next/get-app-router-font-classes.ts +12 -0
  82. package/next/load-and-return-lux-next-fonts-on-import.ts +68 -0
  83. package/next/next-font-desc.ts +28 -0
  84. package/next/not-found-content.mdx +4 -0
  85. package/next/not-found.tsx +23 -0
  86. package/next/pages-router-font-vars.tsx +18 -0
  87. package/next/root-layout.tsx +53 -0
  88. package/package.json +105 -0
  89. package/primitives/accordion.tsx +61 -0
  90. package/primitives/action-button.tsx +46 -0
  91. package/primitives/apply-typography.tsx +55 -0
  92. package/primitives/avatar.tsx +49 -0
  93. package/primitives/badge.tsx +36 -0
  94. package/primitives/button.tsx +73 -0
  95. package/primitives/calendar.tsx +72 -0
  96. package/primitives/card.tsx +83 -0
  97. package/primitives/checkbox.tsx +32 -0
  98. package/primitives/command.tsx +155 -0
  99. package/primitives/dialog-video-controller.tsx +38 -0
  100. package/primitives/dialog.tsx +152 -0
  101. package/primitives/form.tsx +179 -0
  102. package/primitives/index.ts +144 -0
  103. package/primitives/inline-icon.tsx +37 -0
  104. package/primitives/input.tsx +30 -0
  105. package/primitives/label.tsx +28 -0
  106. package/primitives/link-element.tsx +104 -0
  107. package/primitives/main.tsx +17 -0
  108. package/primitives/mdx-link.tsx +22 -0
  109. package/primitives/nav-items.tsx +48 -0
  110. package/primitives/popover.tsx +35 -0
  111. package/primitives/progress.tsx +27 -0
  112. package/primitives/scroll-area.tsx +47 -0
  113. package/primitives/select.tsx +169 -0
  114. package/primitives/separator.tsx +29 -0
  115. package/primitives/sheet.tsx +175 -0
  116. package/primitives/skeleton.tsx +15 -0
  117. package/primitives/switch.tsx +33 -0
  118. package/primitives/table.tsx +117 -0
  119. package/primitives/tabs.tsx +60 -0
  120. package/primitives/tailwind-indicator.tsx +19 -0
  121. package/primitives/text-area.tsx +26 -0
  122. package/primitives/toast.tsx +129 -0
  123. package/primitives/toaster.tsx +37 -0
  124. package/primitives/use-toast.ts +192 -0
  125. package/primitives/video-player.tsx +26 -0
  126. package/primitives/youtube-embed.tsx +83 -0
  127. package/siteDef/footer/community.tsx +67 -0
  128. package/siteDef/footer/company.ts +37 -0
  129. package/siteDef/footer/ecosystem.ts +37 -0
  130. package/siteDef/footer/index.tsx +26 -0
  131. package/siteDef/footer/legal.ts +28 -0
  132. package/siteDef/footer/network.ts +33 -0
  133. package/siteDef/footer/svg/warpcast-logo.svg +12 -0
  134. package/siteDef/main-nav.ts +35 -0
  135. package/style/globals.css +13 -0
  136. package/style/hanzo-common.css +32 -0
  137. package/style/hanzo-default-colors.css +79 -0
  138. package/style/social-svg.css +3 -0
  139. package/tailwind/colors.tailwind.js +46 -0
  140. package/tailwind/fonts.tailwind.ts +31 -0
  141. package/tailwind/index.ts +18 -0
  142. package/tailwind/lux-tw-fonts.ts +32 -0
  143. package/tailwind/safelist.tailwind.js +26 -0
  144. package/tailwind/screens.tailwind.js +8 -0
  145. package/tailwind/spacing.tailwind.js +57 -0
  146. package/tailwind/tailwind.config.base.js +905 -0
  147. package/tailwind/tw-font-desc.ts +15 -0
  148. package/tailwind/typo-plugin/get-plugin-styles.js +676 -0
  149. package/tailwind/typo-plugin/index.d.ts +9 -0
  150. package/tailwind/typo-plugin/index.js +141 -0
  151. package/tailwind/typo-plugin/utils.js +60 -0
  152. package/tailwind/typography-test.mdx +36 -0
  153. package/types/breakpoints.ts +11 -0
  154. package/types/bullet-item.ts +10 -0
  155. package/types/button-def.ts +39 -0
  156. package/types/contact-info.ts +11 -0
  157. package/types/dimensions.ts +20 -0
  158. package/types/grid-def.ts +37 -0
  159. package/types/icon.ts +10 -0
  160. package/types/image-def.ts +28 -0
  161. package/types/index.ts +29 -0
  162. package/types/link-def.ts +59 -0
  163. package/types/site-def.ts +31 -0
  164. package/types/t-shirt-size.ts +5 -0
  165. package/util/index.ts +76 -0
  166. package/util/specifier.ts +43 -0
@@ -0,0 +1,115 @@
1
+ import React, { type PropsWithChildren } from 'react'
2
+
3
+ import type { Block, ScreenfulBlock} from '../../def'
4
+ import { containsToken, cn } from '../../../util'
5
+ import ContentComponent from '../content'
6
+
7
+ const ContentColumn: React.FC<{
8
+ blocks: Block[]
9
+ specifiers?: string
10
+ agent?: string
11
+ className?: string
12
+ }> = ({
13
+ blocks,
14
+ specifiers,
15
+ agent,
16
+ className='',
17
+ }) => {
18
+
19
+ const specified = (s: string) => (containsToken(specifiers, s))
20
+
21
+ let modifiers = ''
22
+
23
+ if (agent !== 'phone') {
24
+ if (specified('right')) {
25
+ modifiers += 'items-end '
26
+
27
+ }
28
+ else if (specified('center')) {
29
+ modifiers += 'items-center '
30
+ }
31
+ // default to left
32
+ else {
33
+ modifiers += 'items-start '
34
+ }
35
+ }
36
+ // default to left
37
+ else {
38
+ modifiers += 'items-start '
39
+ }
40
+
41
+ if (agent !== 'phone') {
42
+ if (specified('bottom')) {
43
+ modifiers += 'justify-end '
44
+ }
45
+ else if (specified('vert-center')) {
46
+ modifiers += 'justify-center '
47
+ }
48
+ // default to top
49
+ else {
50
+ modifiers += 'justify-start '
51
+ }
52
+ // right aligned text looks shitty on mobile
53
+ if (specified('text-align-right')) {
54
+ modifiers += 'text-right '
55
+ }
56
+ else {
57
+ modifiers += 'text-left '
58
+ }
59
+ }
60
+ else {
61
+ modifiers += 'justify-start '
62
+ }
63
+
64
+ if (agent === 'phone' && specified('mobile-center-headings')) {
65
+ modifiers += 'typography-headings:text-center '
66
+ }
67
+
68
+ return (
69
+ <div className={cn('flex flex-col justify-center ' + modifiers, className)} >
70
+ <ContentComponent blocks={blocks} agent={agent} />
71
+ </div>
72
+ )
73
+ }
74
+
75
+ const Content: React.FC<{
76
+ block: ScreenfulBlock
77
+ agent?: string
78
+ className?: string
79
+ }> = ({
80
+ block: b,
81
+ agent,
82
+ className='',
83
+ }) => {
84
+
85
+
86
+ const layoutClx = 'flex flex-col gap-6 ' + ((agent !== 'phone') ? ('md:grid md:gap-8 ' + `md:grid-cols-${b.contentColumns.length} `) : '')
87
+
88
+ const orderclx = (columnIndex: number): string => {
89
+ const orderIndex = b.mobileOrder?.indexOf(columnIndex)
90
+ return (orderIndex && orderIndex >= 0) ? `order-${orderIndex} md:order-none` : '' // one-based in flexbox slec
91
+ }
92
+
93
+ return b.contentColumns.length == 1 ? (
94
+ <ContentColumn
95
+ blocks={b.contentColumns[0]}
96
+ specifiers={b.columnSpecifiers?.[0]}
97
+ agent={agent}
98
+ className={cn(className)}
99
+ />
100
+ ) : (
101
+ <div className={cn(layoutClx, className)}>
102
+ {b.contentColumns.map((column, index) => (
103
+ <ContentColumn
104
+ blocks={column}
105
+ specifiers={b.columnSpecifiers?.[index]}
106
+ agent={agent}
107
+ className={orderclx(index)}
108
+ key={index}
109
+ />
110
+ ))}
111
+ </div>
112
+ )
113
+ }
114
+
115
+ export default Content
@@ -0,0 +1,77 @@
1
+ import React from 'react'
2
+ import dynamic from 'next/dynamic'
3
+
4
+ import type { Block, ScreenfulBlock, VideoBlock } from '../../def'
5
+ import { containsToken, cn } from '../../../util'
6
+ import { ApplyTypography } from '../../../primitives'
7
+
8
+ import Poster from './poster-background'
9
+ import Content from './content'
10
+ const Video = dynamic(() => (import('./video-background')), {ssr: false, loading: () => (<></>)})
11
+
12
+ const ScreenfulComponent: React.FC<{
13
+ block: Block
14
+ agent?: string
15
+ initialInView?: boolean
16
+ snapTile?: boolean
17
+ className?: string
18
+ }> = ({
19
+ block,
20
+ agent,
21
+ initialInView=false,
22
+ snapTile=false,
23
+ className=''
24
+ }) => {
25
+
26
+ if (block.blockType !== 'screenful') {
27
+ return <>screenful block required</>
28
+ }
29
+ const b = block as ScreenfulBlock
30
+
31
+ const hasBannerVideo = (): boolean => (!!b.banner && (typeof b.banner === 'object'))
32
+
33
+ const tileHeight = (agent === 'desktop') ? 'h-full ' : 'h-[100svh] '
34
+
35
+ const specified = (s: string) => (containsToken(b.specifiers, s))
36
+ const narrowGutters = specified('narrow-gutters') // eg, for a table object that is large
37
+
38
+ // content wrapper clx:
39
+ // [
40
+ // positioning,
41
+ // p&m,
42
+ // p&m-modifiers
43
+ // ]
44
+ const cwclx = [
45
+ 'z-10 absolute left-0 right-0 top-0 bottom-0 xl:mx-auto max-w-screen-xl overflow-y-hidden ',
46
+ // desktop header: 80px / pt-20
47
+ // mobile header: 44px / pt-11
48
+ narrowGutters ?
49
+ 'px-6 lg:px-8 2xl:px-2 pb-6 pt-15 md:pt-26 lg:pt-28 '
50
+ :
51
+ 'px-[8vw] xl:px-[1vw] pb-[8vh] pt-[calc(44px+4vh)] md:pt-[calc(80px+6vh)] ',
52
+
53
+ (agent && agent !== 'desktop') ? 'pt-15 sm:pt-17 pb-0 px-3 sm:px-8' : ''
54
+ ]
55
+
56
+ return (
57
+ <section className={cn('h-[100vh]', (snapTile ? 'snap-start snap-always' : ''), className)}>
58
+ <ApplyTypography className={tileHeight + 'w-full flex flex-row justify-center self-stretch'} >
59
+ <Poster banner={b.banner}>
60
+ {hasBannerVideo() && (
61
+ <Video
62
+ block={b.banner! as VideoBlock}
63
+ className='z-0 absolute top-0 left-0 bottom-0 right-0'
64
+ initialInView={initialInView}
65
+ />
66
+ )}
67
+ <div className={cn(...cwclx)} >
68
+ <Content block={b} agent={agent} className='w-full'/>
69
+ {b.footer}
70
+ </div>
71
+ </Poster>
72
+ </ApplyTypography>
73
+ </section>
74
+ )
75
+ }
76
+
77
+ export default ScreenfulComponent
@@ -0,0 +1,34 @@
1
+ import React, { type PropsWithChildren } from 'react'
2
+
3
+ import type { VideoBlock } from '../../def'
4
+ import { cn } from '../../../util'
5
+
6
+ const Poster: React.FC<{
7
+ banner: VideoBlock | string | undefined,
8
+ className?: string
9
+ } & PropsWithChildren> = ({
10
+ children,
11
+ banner,
12
+ className=''
13
+ }) => (
14
+ banner ? (
15
+ <div
16
+ className={cn('relative', className)}
17
+ style={{
18
+ height: '100%',
19
+ width: '100%',
20
+ backgroundImage: `url(${(typeof banner === 'string') ? banner : banner.poster!})`,
21
+ backgroundSize: 'cover',
22
+ backgroundRepeat: 'no-repeat',
23
+ }}
24
+ >
25
+ {children}
26
+ </div>
27
+ ) : (
28
+ <div className={cn('bg-transparent h-full w-full relative', className)}>
29
+ {children}
30
+ </div>
31
+ )
32
+ )
33
+
34
+ export default Poster
@@ -0,0 +1,45 @@
1
+ 'use client'
2
+ import React from 'react'
3
+
4
+ import { useInView } from 'react-intersection-observer'
5
+
6
+ import type { VideoBlock } from '../../def'
7
+
8
+ const VideoBG: React.FC<{
9
+ block: VideoBlock,
10
+ className?: string,
11
+ initialInView: boolean
12
+ }> = ({
13
+ block,
14
+ className='',
15
+ initialInView
16
+ }) => {
17
+ const { ref, inView } = useInView({
18
+ threshold: 0.75,
19
+ initialInView,
20
+ })
21
+
22
+ return block ? (
23
+ <div ref={ref} className={className}>
24
+ {inView && (
25
+ <video
26
+ autoPlay
27
+ loop
28
+ muted
29
+ style={{
30
+ margin: 0,
31
+ height: '100%',
32
+ width: '100%',
33
+ objectFit: 'cover',
34
+ }}
35
+ >
36
+ {block.sources?.map((src, index) => (
37
+ <source key={index} src={src} />
38
+ ))}
39
+ </video>
40
+ )}
41
+ </div>
42
+ ) : null
43
+ }
44
+
45
+ export default VideoBG
@@ -0,0 +1,66 @@
1
+ import React from 'react'
2
+
3
+ import { ldMerge } from '../../util'
4
+
5
+ import type { Breakpoint } from '../../types'
6
+ import { SPACE_DEFAULTS , type TWSpaceUnit, type HeadingLevel} from '../def/space-block'
7
+ import type SpaceBlock from '../def/space-block'
8
+ import { ApplyTypography } from '../../primitives'
9
+
10
+ import type BlockComponentProps from './block-component-props'
11
+
12
+ const TAGS = [
13
+ 'div',
14
+ 'h1',
15
+ 'h2',
16
+ 'h3',
17
+ 'h4',
18
+ 'h5',
19
+ 'h6',
20
+ ] satisfies React.ElementType[]
21
+
22
+ const SpaceBlockComponent: React.FC<BlockComponentProps> = ({
23
+ block,
24
+ className=''
25
+ }) => {
26
+
27
+ if (block && block.blockType !== 'space') {
28
+ return <>space block required</>
29
+ }
30
+
31
+ const b = block as SpaceBlock
32
+
33
+ // This code path should handle a undefined or empty sizes field.
34
+ if (!b.level) {
35
+ if (typeof b.sizes == 'number') {
36
+ return <div className={`invisible w-[1px] h-${b.sizes}` } />
37
+ }
38
+ const _sizes: {
39
+ [key in (Breakpoint)]?: TWSpaceUnit
40
+ } = {}
41
+ ldMerge(_sizes, SPACE_DEFAULTS, b.sizes)
42
+
43
+ let clx = ''
44
+ for (const [key, value] of Object.entries(_sizes)) {
45
+ // ts brain fart!
46
+ clx += `${key}:h-${value as TWSpaceUnit} `
47
+ }
48
+
49
+ if (b.test) {
50
+ console.log(clx)
51
+ }
52
+
53
+ return <div className={'invisible w-[1px] ' + clx} />
54
+ }
55
+
56
+ const Tag = TAGS[b.level]
57
+ const heightClx = (b.level === (0 satisfies HeadingLevel as HeadingLevel)) ? 'h-4' : ''
58
+
59
+ return (
60
+ <ApplyTypography>
61
+ <Tag className={'invisible m-0 ' + heightClx} >&nbsp;</Tag>
62
+ </ApplyTypography>
63
+ )
64
+ }
65
+
66
+ export default SpaceBlockComponent
@@ -0,0 +1,137 @@
1
+ 'use client'
2
+ import React, { useEffect, useLayoutEffect, useState } from 'react'
3
+
4
+ import Image from 'next/image'
5
+
6
+ import type { Dimensions, TShirtSize, TShirtDimensions } from '../../types'
7
+ import { constrain, asNum, cn } from '../../util'
8
+ import type { VideoBlock } from '../def'
9
+ import { VideoPlayer } from '../../primitives'
10
+
11
+ import type BlockComponentProps from './block-component-props'
12
+
13
+ const VideoBlockComponent: React.FC<BlockComponentProps & {
14
+ usePoster?: boolean
15
+ size?: TShirtSize
16
+ constraint?: Dimensions
17
+ }> = ({
18
+ block,
19
+ className='',
20
+ agent,
21
+ usePoster=false,
22
+ size='md',
23
+ constraint
24
+ }) => {
25
+
26
+ const [_dim, setDim] = useState<Dimensions | undefined>(undefined)
27
+
28
+ const onResize = () => {
29
+ setDim({
30
+ w: window.innerWidth,
31
+ h: window.innerHeight
32
+ })
33
+ }
34
+
35
+ const windowDefined = typeof window !== 'undefined'
36
+
37
+ useEffect(() => {
38
+ if (window && agent === 'desktop') {
39
+ window.addEventListener('resize', onResize)
40
+ return () => window.removeEventListener('resize', onResize)
41
+ }
42
+ }, [windowDefined])
43
+
44
+ useLayoutEffect(() => {
45
+ onResize()
46
+ }, [])
47
+
48
+
49
+ if (block.blockType !== 'video') {
50
+ return <>video block required</>
51
+ }
52
+
53
+ const b = block as VideoBlock
54
+ const ar = asNum(b.dim.md.w) / asNum(b.dim.md.h)
55
+ if (agent === 'phone') {
56
+ if (b.sizing?.mobile?.vw) {
57
+ // serverside, or at least while the video is loading,
58
+ // generate the css for the correctly sized poster image
59
+ if (!_dim) {
60
+ const width = `${b.sizing.mobile.vw}vw`
61
+ return <div className='dummy-div' style={{
62
+ maxWidth: '100%',
63
+ maxHeight: '100%',
64
+ width,
65
+ height: `calc(${width}/${ar})`,
66
+ backgroundImage: `url(${b.poster!})`,
67
+ backgroundSize: 'contain',
68
+ backgroundRepeat: 'no-repeat',
69
+ }} />
70
+ }
71
+ else {
72
+ const width = ((b.sizing.mobile.vw / 100) * asNum(_dim.w))
73
+ const dim = {
74
+ h: width / ar,
75
+ w: width
76
+ }
77
+ return ((
78
+ <VideoPlayer
79
+ className={cn('mx-auto', className)}
80
+ sources={b.sources}
81
+ width={dim.w}
82
+ height={dim.h}
83
+ {...b.videoProps}
84
+ />
85
+ ))
86
+ }
87
+ }
88
+ }
89
+ else if (b.sizing?.vh) {
90
+ // serverside, generate the css for the correctly sized poster image
91
+ if (!_dim) {
92
+ const height = `${b.sizing.vh}vh`
93
+ return <div className='dummy-div' style={{
94
+ maxWidth: '100%',
95
+ maxHeight: '100%',
96
+ height: height,
97
+ width: `calc(${height}*${ar})`,
98
+ backgroundImage: `url(${b.poster!})`,
99
+ backgroundSize: 'contain',
100
+ backgroundRepeat: 'no-repeat',
101
+ }} />
102
+ }
103
+ else {
104
+ const height = ((b.sizing.vh / 100) * asNum(_dim.h))
105
+ const dim = {
106
+ h: height,
107
+ w: height * ar
108
+ }
109
+ return ((
110
+ <VideoPlayer
111
+ className={className}
112
+ sources={b.sources}
113
+ width={dim.w}
114
+ height={dim.h}
115
+ {...b.videoProps}
116
+ />
117
+ ))
118
+ }
119
+ }
120
+
121
+ const videoDims = b.dim as TShirtDimensions
122
+ const dim = ((size && size in videoDims) ? videoDims[size] : videoDims.md) as Dimensions
123
+ const conDim = (constraint ? constrain(dim, constraint) : dim)
124
+ return usePoster ? (
125
+ <Image src={b.poster!} alt='image' width={conDim.w} height={conDim.h} className={className}/>
126
+ ) : (
127
+ <VideoPlayer
128
+ className={className}
129
+ sources={b.sources}
130
+ width={conDim.w}
131
+ height={conDim.h}
132
+ {...b.videoProps}
133
+ />
134
+ )
135
+ }
136
+
137
+ export default VideoBlockComponent
@@ -0,0 +1,14 @@
1
+ import React from 'react'
2
+ import type Block from './block'
3
+
4
+ interface AccordianBlock extends Block {
5
+ blockType: 'accordian'
6
+ items: {
7
+ trigger: string
8
+ content: React.ReactNode
9
+ }[]
10
+ }
11
+
12
+ export {
13
+ type AccordianBlock as default
14
+ }
@@ -0,0 +1,7 @@
1
+ interface Block {
2
+ blockType: string
3
+ }
4
+
5
+ export {
6
+ type Block as default
7
+ }
@@ -0,0 +1,20 @@
1
+ import type Block from './block'
2
+
3
+ import type { BulletItem, GridDef } from '../../types'
4
+
5
+ interface BulletCardsBlock extends Block {
6
+ blockType: 'bullet-cards'
7
+ /**
8
+ * borders-muted-1 / borders-muted-3
9
+ * default: 2
10
+ */
11
+ specifiers?: string
12
+ grid: GridDef
13
+ cards: BulletItem[]
14
+ /** in px */
15
+ iconSize?: number
16
+ }
17
+
18
+ export {
19
+ type BulletCardsBlock as default
20
+ }
@@ -0,0 +1,24 @@
1
+ import React from 'react'
2
+
3
+ import { type Icon } from '../../types'
4
+
5
+ import type CTABlock from './cta-block'
6
+ import type Block from './block'
7
+ import type ImageBlock from './image-block'
8
+ import type VideoBlock from './video-block'
9
+
10
+ interface CardBlock extends Block {
11
+ blockType: 'card'
12
+ specifiers?: string // 'media-left' or 'appear-disabled' or 'no-borders', etc... can be combined
13
+ title?: string
14
+ byline?: string
15
+ icon?: Icon // for title area
16
+ iconAfter?: boolean
17
+ media?: ImageBlock | VideoBlock
18
+ content?: React.ReactNode
19
+ cta?: CTABlock
20
+ }
21
+
22
+ export {
23
+ type CardBlock as default
24
+ }
@@ -0,0 +1,20 @@
1
+
2
+ import type Block from './block'
3
+ import type CTABlock from './cta-block'
4
+ import type EnhHeadingBlock from './enh-heading-block'
5
+
6
+ interface CarteBlancheBlock extends Block {
7
+ blockType: 'carte-blanche'
8
+ // big-padding
9
+ // no-internal-borders
10
+ // style-ghost (no-internal-borders, no outer border, no padding)
11
+ specifiers?: string
12
+ topContent?: Block[]
13
+ heading?: EnhHeadingBlock
14
+ content?: Block[]
15
+ cta?: CTABlock
16
+ }
17
+
18
+ export {
19
+ type CarteBlancheBlock as default
20
+ }
@@ -0,0 +1,19 @@
1
+ import type { LinkDef, ButtonDef } from '../../types'
2
+ import type Block from './block'
3
+
4
+ interface CTABlock extends Block {
5
+ blockType: 'cta'
6
+ // fill: fills the parent width with the elements
7
+ // left / right: (>= md) left or right justify the elements (default is center)
8
+ // mobile-2-columns: mobile defaults to rendering each element full width,
9
+ // on it's own line. This renders them in two columns instead.
10
+ // mobile-center-first-if-odd: if (mobile-2-columns) and length is odd,
11
+ // default is to center last
12
+ // mobile-odd-full-width: fills the full two columns w the centered element
13
+ specifiers?: string
14
+ elements: (LinkDef | ButtonDef)[]
15
+ }
16
+
17
+ export {
18
+ type CTABlock as default
19
+ }
@@ -0,0 +1,11 @@
1
+ import React from 'react'
2
+ import type Block from './block'
3
+
4
+ interface ElementBlock extends Block {
5
+ blockType: 'element'
6
+ element: React.ReactNode | JSX.Element
7
+ }
8
+
9
+ export {
10
+ type ElementBlock as default
11
+ }
@@ -0,0 +1,45 @@
1
+ import type Icon from '../../types/icon'
2
+ import type Block from './block'
3
+
4
+ // level is heading tag level. 1 renders as <h1>, etc... 0 renders as <p>
5
+ //
6
+ // mb: is bottom margin in tw units. 'mb-1' produces 0.25rem, so a value of 4 would produce 1rem
7
+ // These are dynamically generated from a template string. mb-1 --> mb-12 have been safelisted.
8
+ // Any higher values used would have to explicitly safelisted in tailwind config.
9
+ // The margin will only be applied if the next element down is present.
10
+ // (eg, heading mb applies only if there is a byline.)
11
+
12
+ interface EnhHeadingBlock extends Block {
13
+ blockType: 'enh-heading'
14
+ // tbd: icon-w-heading (if preheading is present),
15
+ // tbd: icon-w-byline (if preheading and heading is present),
16
+ // tbd: icon-above: above first element
17
+ // tbd: icon-to-right: to right of corresponding element or right justified if 'icon-above'
18
+ // mobile-heading-centered
19
+ // left / right / center for preheading and heading (byline stays left)
20
+ // byline-left / byline-right / byline-center
21
+ // preheading-heading-font
22
+ specifiers?: string
23
+ // By default, appears inline to left of first element (preheading or heading)
24
+ // unless indicated otherwise in specifiers
25
+ icon?: Icon | string // ReactNode or url string to asset
26
+ iconSize?: number // if url string, this sets the size
27
+ preheading?: {
28
+ text: string
29
+ level?: number // default: 4
30
+ mb?: number // default: 2
31
+ }
32
+ heading: {
33
+ text: string
34
+ level?: number // default: 1
35
+ mb?: number // default: 2
36
+ }
37
+ byline?: {
38
+ text: string
39
+ level?: number // default: 6
40
+ }
41
+ }
42
+
43
+ export {
44
+ type EnhHeadingBlock as default
45
+ }
@@ -0,0 +1,16 @@
1
+ import type Block from "./block"
2
+ import type GridDef from "../../types/grid-def"
3
+
4
+ interface GridBlock {
5
+ blockType: 'grid'
6
+ specifiers?: string
7
+ grid: GridDef
8
+ /**
9
+ * Ignored if children are supplied to the GridBlockComp
10
+ */
11
+ cells?: Block[]
12
+ }
13
+
14
+ export {
15
+ type GridBlock as default
16
+ }
@@ -0,0 +1,11 @@
1
+ import type Block from './block'
2
+
3
+ interface GroupBlock extends Block {
4
+ blockType: 'group'
5
+ specifiers?: string // grid-2 slider disabled or whatever
6
+ elements: Block[]
7
+ }
8
+
9
+ export {
10
+ type GroupBlock as default
11
+ }
@@ -0,0 +1,15 @@
1
+ import type Block from './block'
2
+
3
+ interface HeadingBlock extends Block {
4
+ blockType: 'heading'
5
+ heading: string
6
+ byline?: string
7
+ level?: number
8
+ bylineLevel?: number
9
+ spaceBetween?: number
10
+ spaceAfter?: number
11
+ }
12
+
13
+ export {
14
+ type HeadingBlock as default
15
+ }