@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,48 @@
1
+ import React from 'react'
2
+
3
+ import {
4
+ Accordion,
5
+ AccordionContent,
6
+ AccordionItem,
7
+ AccordionTrigger,
8
+ ApplyTypography
9
+ } from '../../primitives'
10
+
11
+ import { cn } from '../../util'
12
+
13
+ import type { AccordianBlock } from '../def'
14
+ import type BlockComponentProps from './block-component-props'
15
+
16
+ const AccordianBlockComponent: React.FC<BlockComponentProps> = ({
17
+ block,
18
+ className=''
19
+ }) => {
20
+
21
+ if (block.blockType !== 'accordian') {
22
+ return <>accordian block required</>
23
+ }
24
+
25
+ const accordian = block as AccordianBlock
26
+
27
+ return (
28
+ <Accordion type="single" collapsible className={cn('w-full border rounded-xl overflow-hidden', className)}>
29
+ {accordian.items.map((item, index) => (
30
+ <AccordionItem className='border-b last:border-0 overflow-hidden' value={`value-${index}`} key={index}>
31
+ <AccordionTrigger className='px-3 md:px-4 lg:px-6 hover:no-underline hover:bg-level-3' >
32
+ <ApplyTypography>
33
+ {/* styles specific to accordion. From old site */}
34
+ <h6 className='leading-[1.2] text-[1.05rem] font-semibold ' >{item.trigger}</h6>
35
+ </ApplyTypography>
36
+ </AccordionTrigger>
37
+ <AccordionContent className='p-4 border-t bg-level-1'>
38
+ <ApplyTypography className='flex flex-col justify-start items-start '>
39
+ {(typeof item.content === 'string') ? (<p>{item.content}</p>) : item.content}
40
+ </ApplyTypography>
41
+ </AccordionContent>
42
+ </AccordionItem>
43
+ ))}
44
+ </Accordion>
45
+ )
46
+ }
47
+
48
+ export default AccordianBlockComponent
@@ -0,0 +1,11 @@
1
+ import type { Block } from "../def";
2
+
3
+ interface BlockComponentProps {
4
+ block: Block
5
+ className?: string
6
+ agent?: string
7
+ }
8
+
9
+ export {
10
+ type BlockComponentProps as default
11
+ }
@@ -0,0 +1,43 @@
1
+ import React from 'react'
2
+
3
+ import { containsToken, cn } from '../../util'
4
+ import type { Block, BulletCardsBlock } from '../def'
5
+ import InlineIcon from '../../primitives/inline-icon'
6
+
7
+ import type BlockComponentProps from './block-component-props'
8
+ import GridBlockComponent from './grid-block'
9
+
10
+ const BulletCardsBlockComponent: React.FC<BlockComponentProps> = ({
11
+ block,
12
+ className='',
13
+ agent
14
+ }) => {
15
+
16
+ if (block.blockType !== 'bullet-cards') {
17
+ return <>bullet cards block required</>
18
+ }
19
+ const b = block as BulletCardsBlock
20
+ const specified = (s: string) => (containsToken(b.specifiers, s))
21
+
22
+ const borderclx = specified('border-muted-3') ?
23
+ 'md:border-muted-3'
24
+ :
25
+ (specified('border-muted-1') ? 'md:border-muted-1' : 'md:border-muted-2')
26
+
27
+
28
+ return (
29
+ <GridBlockComponent block={{blockType: 'grid', grid: b.grid} as Block} className={className} agent={agent}>
30
+ {b.cards.map((card, index) => (
31
+ <div key={index} className={cn('px-0 sm:px-4 py-1 md:py-4 md:border rounded ' +
32
+ 'flex flex-row justify-start items-center not-typography text-foreground',
33
+ borderclx
34
+ )}>
35
+ <InlineIcon icon={card.icon} size={b.iconSize ?? 28} agent={agent} className='shrink-0 mr-2 w-6 md:mr-4 md:w-7 '/>
36
+ <p className='m-0 text-sm sm:text-base'>{card.text}</p>
37
+ </div>
38
+ ))}
39
+ </GridBlockComponent>
40
+ )
41
+ }
42
+
43
+ export default BulletCardsBlockComponent
@@ -0,0 +1,213 @@
1
+ import React from 'react'
2
+
3
+ import type { Dimensions, LinkDef, TShirtDimensions } from '../../types'
4
+
5
+ import {
6
+ ApplyTypography,
7
+ Card,
8
+ CardContent,
9
+ CardDescription,
10
+ CardFooter,
11
+ CardHeader,
12
+ CardTitle,
13
+ LinkElement,
14
+ type TypographySize
15
+ } from '../../primitives'
16
+
17
+ import { Icons } from '../../common'
18
+
19
+ import {
20
+ getSpecifierData,
21
+ getPrimaryStartingWith,
22
+ getDim,
23
+ } from '../../util/specifier'
24
+
25
+ import type { Block, CardBlock } from '../def'
26
+
27
+
28
+ import ImageBlockComponent from './image-block'
29
+ import VideoBlockComponent from './video-block'
30
+ import CTABlockComponent from './cta-block'
31
+ import type BlockComponentProps from './block-component-props'
32
+ import { cn } from '../../util'
33
+
34
+ const ArrowLinkElement: React.FC<{
35
+ def: LinkDef,
36
+ }> = ({
37
+ def
38
+ }) => (
39
+ <LinkElement
40
+ def={def}
41
+ className='justify-between'
42
+ variant='link'
43
+ icon={<Icons.linkOut className='w-[18px] h-[18px]' />}
44
+ iconAfter
45
+ />
46
+ )
47
+
48
+ const getTypographySize = (s: string): TypographySize => (
49
+ getSpecifierData<TypographySize>(
50
+ s,
51
+ (s: string) => (getPrimaryStartingWith(s, 'typography')),
52
+ (s: string): TypographySize | undefined => {
53
+ const subTokenArray = s.split('-')
54
+ return subTokenArray[subTokenArray.length - 1] as TypographySize
55
+ },
56
+ 'responsive'
57
+ ) as TypographySize
58
+ )
59
+
60
+ const getSmallIconDim = (s: string): Dimensions | undefined => (
61
+ getSpecifierData<Dimensions>(
62
+ s,
63
+ (s: string) => (getPrimaryStartingWith(s, 'small-icon')),
64
+ getDim,
65
+ )
66
+ )
67
+
68
+ const CardBlockComponent: React.FC<
69
+ BlockComponentProps & {
70
+ contentClassName?: string
71
+ }> = ({
72
+ block,
73
+ className='',
74
+ contentClassName=''
75
+ }) => {
76
+
77
+ if (block.blockType !== 'card') {
78
+ return <>card block required</>
79
+ }
80
+
81
+ const card = block as CardBlock
82
+ const has = (s: string) => (card.specifiers?.includes(s))
83
+
84
+ const ghost = has('ghost') // no outer padding, no borders, larger title, all left-aligned bg is same (default)
85
+
86
+ const contentclx = (has('content-left') ? 'items-start ' : 'items-center ') + contentClassName
87
+ const disabledBorder = (has('appear-disabled' ) ? ' border-muted-4' : ' border-muted-3')
88
+ const outerBorder = ((has('no-outer-border') || ghost) ? ' border-0' : '')
89
+ const innerBorder = (ghost ? ' border-0' : '')
90
+ const paddingclx = ghost ? ' px-0 py-0' : ' px-6 py-3'
91
+ const mainGap = ghost ? ' gap-2' : ''
92
+ const disabledText = (has('appear-disabled') ? ' text-muted-2' : '')
93
+ const disabledTypoText = (has('appear-disabled') ? ' typography-p:text-muted-2' : '')
94
+ const bgclx = (has('bg-card') ? ' bg-level-1' : '')
95
+ const titleclx = (has('heading-style-title') ? ' font-heading text-base leading-tight' : '') +
96
+ (ghost ? ' text-left md:text-xl' : '')
97
+
98
+ const typoSize: TypographySize = (card.specifiers) ? getTypographySize(card.specifiers) : 'responsive'
99
+ const typoclx = (typoSize === 'sm') ? 'typography-sm typography-p:text-sm ' : (typoSize === 'lg') ? 'typography-lg ' : ''
100
+
101
+ const contentBefore = has('content-before')
102
+ const iconInline = has('icon-inline')
103
+ const contentOnHover = has('reveal-content-on-hover')
104
+ //const smallIconDim = (contentOnHover && card.specifiers) ? getSmallIconDim(card.specifiers) : undefined
105
+
106
+ const Header: React.FC<{
107
+ inContent?: boolean
108
+ className?: string
109
+ }> = ({
110
+ inContent=false,
111
+ className=''
112
+ }) => (
113
+ (card.title || card.byline || card.icon) ? (
114
+ <CardHeader className={'not-typography' + ' text-accent' + disabledText + paddingclx + innerBorder + className}>
115
+ <div className={(iconInline || inContent) ? 'flex flex-row justify-start items-end my-3' : ''}>
116
+ {(card.icon && !card.iconAfter ) && (<div className={iconInline ? 'mr-1' : 'mb-2'}>{card.icon}</div>)}
117
+ {card.title && (
118
+ <CardTitle className={'text-center text-lg font-medium' + titleclx + (iconInline ? ' md:text-xl/none' : '') }>
119
+ {card.title}
120
+ </CardTitle>
121
+ )}
122
+ {(card.icon && card.iconAfter) && (<div className={iconInline ? 'ml-1' : 'my-1'}>{card.icon}</div>)}
123
+ </div>
124
+ {card.byline && (<CardDescription>{card.byline}</CardDescription>)}
125
+ </CardHeader>
126
+ ) : null
127
+ )
128
+
129
+ const MediaAndContent: React.FC<{
130
+ className?: string
131
+ }> = ({
132
+ className=''
133
+ }) => (has('media-left') ? (
134
+ // media left layout
135
+ <CardContent className={'flex flex-row justify-start items-stretch p-0 grow ' + disabledBorder + bgclx + contentclx + className}>
136
+ {card.media && (
137
+ <div className={'box-content grow-0 not-typography' + paddingclx} style={{
138
+ // If this layout has been specified, assume video, and that the 'sm' variant is there.
139
+ width: (card.media.dim as TShirtDimensions).sm!.w
140
+ }}>
141
+ <VideoBlockComponent
142
+ block={card.media}
143
+ usePoster={has('video-use-poster')}
144
+ size='sm'
145
+ className={has('appear-disabled') ? 'opacity-[0.6]' : ''}
146
+ />
147
+ </div>
148
+ )}
149
+ {card.content && (
150
+ <ApplyTypography className={'grow border-l flex flex-col justify-center ' + disabledTypoText + paddingclx + disabledBorder + contentclx} size={typoSize}>
151
+ {(typeof card.content === 'string') ? (<p>{card.content}</p>) : card.content}
152
+ </ApplyTypography>
153
+ )}
154
+ </CardContent>
155
+ ) : ( // default layout
156
+ <CardContent className={
157
+ 'grow typography flex flex-col justify-center ' +
158
+ typoclx + disabledTypoText + bgclx + paddingclx + contentclx + (has('full-width') ? ' p-0 ' : ' ') +
159
+ className
160
+ }>
161
+ {contentOnHover && (<Header inContent/>)}
162
+ {card.content && contentBefore && (
163
+ (typeof card.content === 'string') ? (<p>{card.content}</p>) : card.content
164
+ )}
165
+ {card.media && (card.media.blockType === 'image' ? (
166
+ <ImageBlockComponent block={card.media} />
167
+ ) : (
168
+ <VideoBlockComponent block={card.media} />
169
+ ))}
170
+ {card.content && !contentBefore && (
171
+ (typeof card.content === 'string') ? (<p>{card.content}</p>) : card.content
172
+ )}
173
+ </CardContent>
174
+ ))
175
+
176
+ const Footer: React.FC = () => ( !card.cta ? null : (has('links-w-arrow') ? (
177
+ // links w arrow
178
+ <CardFooter className={
179
+ 'typography typography-a:text-muted-2 typography-a:hover:text-muted-1 typography-a:text-xs typography-a:no-underline typography-a:hover:underline ' +
180
+ 'flex flex-col justify-start items-stretch ' + paddingclx
181
+ }>
182
+ <CTABlockComponent
183
+ block={card.cta}
184
+ renderLink={(def: LinkDef, key: any) => (<ArrowLinkElement def={def} key={key} />)}
185
+ />
186
+ </CardFooter>
187
+ ) : ( // default
188
+ <CardFooter className={'grid grid-cols-1 gap-2 md:flex md:flex-row md:justify-center ' + paddingclx} >
189
+ <CTABlockComponent block={card.cta} />
190
+ </CardFooter>
191
+ )))
192
+
193
+ return (
194
+ <Card className={cn(
195
+ 'flex flex-col self-stretch ' +
196
+ (contentOnHover ? 'group relative' : '') +
197
+ disabledBorder +
198
+ outerBorder +
199
+ bgclx +
200
+ mainGap,
201
+ className
202
+ )}>
203
+ <Header className={(contentOnHover ? ' absolute top-[0px] left-[0px] w-full hidden ' : '')}/>
204
+ <MediaAndContent className={(contentOnHover ?
205
+ ' bg-gradient-to-t from-secondary to-65%' +
206
+ ' items-start justify-start rounded-lg p-4' +
207
+ ' transition-opacity duration-500 ease-out opacity-100 ' : '')}/>
208
+ <Footer />
209
+ </Card>
210
+ )
211
+ }
212
+
213
+ export default CardBlockComponent
@@ -0,0 +1,98 @@
1
+ import React from 'react'
2
+
3
+ import {
4
+ Card,
5
+ CardContent,
6
+ CardFooter,
7
+ CardHeader,
8
+ } from '../../../primitives'
9
+
10
+ import { cn, containsToken } from '../../../util'
11
+
12
+ import {
13
+ getSpecifierData,
14
+ getPrimaryStartingWith,
15
+ getDim,
16
+ } from '../../../util/specifier'
17
+
18
+ import type CarteBlancheBlock from '../../def/carte-blanche-block'
19
+
20
+ import CTABlockComponent from '../cta-block'
21
+ import Content from '../content'
22
+ import type BlockComponentProps from '../block-component-props'
23
+ import { EnhHeadingBlockComponent } from '..'
24
+
25
+ type CardSection = 'entire' | 'header' | 'content' | 'footer'
26
+
27
+ const _getClx = (specifier: string, section: CardSection): string => {
28
+ let result = ''
29
+ if (specifier === 'big-padding') {
30
+ switch (section) {
31
+ // defaults: p-4 lg:p-6 xl:p-8
32
+ case 'header': {
33
+ result = 'md:p-8 lg:p-12 xl:p-16'
34
+ } break
35
+ }
36
+ }
37
+ else if (specifier === 'no-inner-borders') {
38
+ switch (section) {
39
+ case 'header': {
40
+ result = 'border-none'
41
+ } break
42
+ }
43
+ }
44
+
45
+ return result
46
+ }
47
+
48
+ const CarteBlancheBlockComponent: React.FC<
49
+ BlockComponentProps
50
+ > = ({
51
+ block,
52
+ className='',
53
+ agent,
54
+ }) => {
55
+
56
+ if (block.blockType !== 'carte-blanche') {
57
+ return <>carte blanche block required</>
58
+ }
59
+
60
+ const b = block as CarteBlancheBlock
61
+
62
+ const specified = (s: string): boolean => (containsToken(b.specifiers, s))
63
+ const getClx = (specifier: string, section: CardSection): string => (
64
+ (specified(specifier)) ? _getClx(specifier, section) : ''
65
+ )
66
+
67
+ //const bigPadding = specified('big-padding')
68
+
69
+ const headingclx = [
70
+ getClx('big-padding', 'header'),
71
+ getClx('no-inner-borders', 'header'),
72
+ ].join(' ')
73
+
74
+ return (
75
+ <Card className={cn('flex flex-col ', className)} >
76
+ {b.heading && (
77
+ <CardHeader className={cn('typography-img:m-0', headingclx)} >
78
+ {b.topContent && (
79
+ <Content blocks={b.topContent} agent={agent} className=''/>
80
+ )}
81
+ <EnhHeadingBlockComponent block={b.heading} className='text-accent' agent={agent}/>
82
+ </CardHeader>
83
+ )}
84
+ {b.content && (
85
+ <CardContent className={cn('typography flex flex-col justify-center', className)}>
86
+ <Content blocks={b.content} agent={agent}/>
87
+ </CardContent>
88
+ )}
89
+ {b.cta && (
90
+ <CardFooter className={'grid grid-cols-1 gap-2 md:flex md:flex-row md:justify-center ' /*+ paddingclx*/} >
91
+ <CTABlockComponent block={b.cta} agent={agent}/>
92
+ </CardFooter>
93
+ )}
94
+ </Card>
95
+ )
96
+ }
97
+
98
+ export default CarteBlancheBlockComponent
@@ -0,0 +1,70 @@
1
+ import React, { type ComponentType, type ReactNode} from 'react'
2
+
3
+ import type * as B from '../def'
4
+
5
+ import AccordianBlockComponent from './accordian-block'
6
+ import BulletCardsBlockComponent from './bullet-cards-block'
7
+ import CTABlockComponent from './cta-block'
8
+ import CardBlockComponent from './card-block'
9
+ import CarteBlancheBlockComponent from './carte-blanche-block'
10
+ import EnhHeadingBlockComponent from './enh-heading-block'
11
+ import HeadingBlockComponent from './heading-block'
12
+ import GroupBlockComponent from './group-block'
13
+ import GridBlockComponent from './grid-block'
14
+ import ImageBlockComponent from './image-block'
15
+ import SpaceBlockComponent from './space-block'
16
+ import VideoBlockComponent from './video-block'
17
+
18
+ import type BlockComponentProps from './block-component-props'
19
+
20
+ const map = new Map<string, ComponentType<BlockComponentProps>>()
21
+ map.set('accordian', AccordianBlockComponent)
22
+ map.set('bullet-cards', BulletCardsBlockComponent)
23
+ map.set('card', CardBlockComponent)
24
+ map.set('carte-blanche', CarteBlancheBlockComponent)
25
+ map.set('cta', CTABlockComponent)
26
+ map.set('heading', HeadingBlockComponent)
27
+ map.set('enh-heading', EnhHeadingBlockComponent as ComponentType<BlockComponentProps>)
28
+ map.set('space', SpaceBlockComponent)
29
+ map.set('image', ImageBlockComponent)
30
+ map.set('video', VideoBlockComponent)
31
+ map.set('group', GroupBlockComponent)
32
+ map.set('grid', GridBlockComponent)
33
+
34
+ const registerBlockType = (key: string, type: ComponentType<BlockComponentProps>): void => {
35
+ map.set(key, type)
36
+ }
37
+
38
+ const renderBlock = (block: B.Block, className: string, agent?: string, keyStr?: string): ReactNode => {
39
+ if (block.blockType === 'element') {
40
+ return (block as B.ElementBlock).element
41
+ }
42
+ const CompType = map.get(block.blockType)
43
+ if (!CompType) return null
44
+ return <CompType block={block} className={className} agent={agent} key={keyStr ?? ''} />
45
+ }
46
+
47
+ const ContentComponent: React.FC<{
48
+ blocks: B.Block | B.Block[] | undefined
49
+ className?: string
50
+ agent?: string
51
+ }> = ({
52
+ blocks,
53
+ className='',
54
+ agent
55
+ }) => {
56
+ if (!blocks) return null
57
+ if (Array.isArray(blocks)) {
58
+ return (
59
+ blocks.map((block, index) => (
60
+ renderBlock(block, className, agent, `content-block-${block.blockType}-${index}`)
61
+ ))
62
+ )
63
+ }
64
+ return renderBlock(blocks, className, agent)
65
+ }
66
+
67
+ export {
68
+ ContentComponent as default,
69
+ registerBlockType
70
+ }
@@ -0,0 +1,98 @@
1
+ import React from 'react'
2
+
3
+ import type { LinkDef, ButtonDef} from '../../types'
4
+ import { type ButtonSizes, ActionButton, LinkElement } from '../../primitives'
5
+ import type { CTABlock } from '../def'
6
+ import { cn, containsToken } from '../../util'
7
+
8
+ import type BlockComponentProps from './block-component-props'
9
+
10
+ const CtaBlockComponent: React.FC<BlockComponentProps & {
11
+ itemClasses?: string
12
+ itemSize?: ButtonSizes,
13
+ renderLink?: (def: LinkDef, key: any) => JSX.Element
14
+ renderButton?: (def: ButtonDef, key: any) => JSX.Element
15
+ }> = ({
16
+ block,
17
+ className='', // assigned to each item
18
+ itemClasses='',
19
+ itemSize, // do not provide default. this is an override to the def
20
+ renderLink,
21
+ renderButton,
22
+ agent
23
+ }) => {
24
+
25
+ if (block.blockType !== 'cta') {
26
+ return <>cta block required</>
27
+ }
28
+
29
+ const { elements, specifiers } = block as CTABlock
30
+ let wrapperClasses = ''
31
+ let itemclx = ''
32
+ if (containsToken(specifiers, 'fill')) {
33
+ wrapperClasses += 'w-full '
34
+ itemclx += 'grow shrink !min-w-0'
35
+ }
36
+ else if (containsToken(specifiers, 'left')) {
37
+ wrapperClasses += 'md:justify-start '
38
+ }
39
+ else if (containsToken(specifiers, 'right')) {
40
+ wrapperClasses += 'md:justify-end '
41
+ }
42
+ else {
43
+ wrapperClasses += 'md:justify-center '
44
+ }
45
+
46
+ const mobile2Columns = containsToken(specifiers, 'mobile-2-columns')
47
+ const mobileCenterFirstIfOdd = containsToken(specifiers, 'mobile-center-first-if-odd')
48
+ const mobileOddFullWidth = containsToken(specifiers, 'mobile-odd-full-width')
49
+
50
+ const layoutclx = (mobile2Columns && elements.length > 1) ?
51
+ 'grid grid-cols-2 gap-2 self-stretch md:flex md:flex-sm md:justify-center '
52
+ :
53
+ 'flex flex-col items-stretch gap-2 self-stretch md:flex-row sm:justify-center '
54
+
55
+ const getMobileColSpanClx = (index: number, total: number) => {
56
+ const indexToCenter = (total % 2 === 0) ? -1 : (mobileCenterFirstIfOdd) ? 0 : total - 1
57
+ const widthclx = mobileOddFullWidth ? 'w-full ' : 'w-3/5 mx-auto '
58
+ return (
59
+ (agent === 'phone' && mobile2Columns && (index === indexToCenter)) ? ('col-span-2 ' + widthclx) : ''
60
+ )
61
+ }
62
+
63
+ return (
64
+ <div className={cn(
65
+ layoutclx,
66
+ wrapperClasses,
67
+ className
68
+ )}>
69
+ {elements.map((element, index) => {
70
+ const twoColClx = getMobileColSpanClx(index, elements.length)
71
+ if ((element as any).title) {
72
+ const def = element as LinkDef
73
+ return renderLink ? renderLink(def, index) : (
74
+ <LinkElement
75
+ def={def}
76
+ key={index}
77
+ size={itemSize}
78
+ className={cn(itemclx, itemClasses, twoColClx)}
79
+ />
80
+ )
81
+ }
82
+ else {
83
+ const def = element as ButtonDef
84
+ return renderButton ? renderButton(def, index) : (
85
+ <ActionButton
86
+ def={def}
87
+ key={index}
88
+ size={itemSize}
89
+ className={cn(itemclx, itemClasses, twoColClx)}
90
+ />
91
+ )
92
+ }
93
+ })}
94
+ </div>
95
+ )
96
+ }
97
+
98
+ export default CtaBlockComponent