blocks-dusted 0.1.11 → 0.1.12
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.
- package/package.json +5 -2
- package/src/cli.js +39 -3
- package/src/commands/shop.js +59 -0
- package/src/commands/warehouse.js +73 -0
- package/templates/blocks/DD-BookCall/Component.tsx +535 -534
- package/templates/blocks/DD-CardTemplate01/Component.tsx +140 -139
- package/templates/blocks/DD-Carousel-A/Component.tsx +1 -1
- package/templates/blocks/DD-Carousel-B/Component.tsx +1 -1
- package/templates/blocks/DD-Chip/Component.tsx +14 -14
- package/templates/blocks/DD-ComparisonTable/Component.tsx +1 -1
- package/templates/blocks/DD-Contact/Component.tsx +8 -7
- package/templates/blocks/DD-Counter/Component.tsx +10 -10
- package/templates/blocks/DD-FeatCat/Component.tsx +1 -1
- package/templates/blocks/DD-FeatStrip/Component.tsx +1 -1
- package/templates/blocks/DD-Hero/Component.tsx +297 -320
- package/templates/blocks/DD-HorizontalScroll/Component.tsx +936 -938
- package/templates/blocks/DD-IframeMedia/Component.tsx +14 -10
- package/templates/blocks/DD-MasonaryMedia/Component.tsx +8 -10
- package/templates/blocks/DD-Pricing/Component.tsx +369 -372
- package/templates/blocks/DD-Process/Component.tsx +147 -149
- package/templates/blocks/DD-Progress/Component.tsx +156 -141
- package/templates/blocks/DD-ProjSlider/config.ts +2 -2
- package/templates/blocks/DD-Section/Component.tsx +1 -1
- package/templates/blocks/DD-Services/Component.tsx +1 -1
- package/templates/blocks/DD-ShowcaseGrid/Component.tsx +13 -13
- package/templates/blocks/DD-Slider-A/Component.tsx +237 -237
- package/templates/blocks/DD-StackCards/Component.tsx +473 -473
- package/templates/blocks/DD-Team/Component.tsx +1 -1
- package/templates/blocks/DD-TechStack/Component.tsx +22 -28
- package/templates/blocks/DD-Testimonials/Component.tsx +35 -43
- package/templates/blocks/DD-TextMarq/Component.tsx +157 -157
- package/templates/blocks/DD-Thanks/Component.tsx +501 -500
- package/templates/blocks/DD-Work/Component.tsx +4 -4
- package/templates/blocks/DD-Work-B/Component.tsx +1 -1
- package/templates/blocks/DDHG-CTASection2/Component.tsx +6 -6
- package/templates/blocks/DDHG-HighlightArc/Component.tsx +243 -243
- package/templates/blocks/DDHG-LogoMarquee/Component.tsx +143 -93
- package/templates/blocks/DDHG-LogoMarquee/config.ts +154 -66
- package/templates/blocks/DDHG-NavCodeGrid/Component.tsx +227 -213
- package/templates/blocks/DDHG-ProcessSec/Component.tsx +38 -39
- package/templates/blocks/DDHG-ServiceDetails/Component.tsx +11 -11
- package/templates/blocks/DDHG-ServiceDetails/ServiceDetailCard.tsx +24 -28
- package/templates/blocks/DDHG-ServiceHero/Component.tsx +1 -1
- package/templates/blocks/DDHG-ServiceOverview/Component.tsx +23 -23
- package/templates/blocks/DDHG-StatsFAQ/Component.tsx +40 -40
- package/templates/blocks/DDHG-TeamCards/Component.tsx +169 -131
|
@@ -1,213 +1,227 @@
|
|
|
1
|
-
'use client'
|
|
2
|
-
|
|
3
|
-
import Image from 'next/image'
|
|
4
|
-
import Link from 'next/link'
|
|
5
|
-
import * as LucideIcons from 'lucide-react'
|
|
6
|
-
import React from 'react'
|
|
7
|
-
|
|
8
|
-
import { getMediaUrl } from '@/utilities/getMediaUrl'
|
|
9
|
-
import { cn } from '@/utilities/ui'
|
|
10
|
-
|
|
11
|
-
type PortableDoc = {
|
|
12
|
-
slug?: string | null
|
|
13
|
-
breadcrumbs?: Array<{ url?: string | null }> | null
|
|
14
|
-
[key: string]: unknown
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
type Media = {
|
|
18
|
-
url?: string | null
|
|
19
|
-
alt?: string | null
|
|
20
|
-
[key: string]: unknown
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
type LinkReference =
|
|
24
|
-
| { relationTo: 'pages'; value: number | PortableDoc }
|
|
25
|
-
| { relationTo: 'posts'; value: number | PortableDoc }
|
|
26
|
-
| { relationTo: 'projects'; value: number | PortableDoc }
|
|
27
|
-
| { relationTo: 'thoughts'; value: number | PortableDoc }
|
|
28
|
-
|
|
29
|
-
type NavCodeGridLink = {
|
|
30
|
-
type?: 'reference' | 'custom' | null
|
|
31
|
-
reference?: LinkReference | null
|
|
32
|
-
url?: string | null
|
|
33
|
-
label?: string | null
|
|
34
|
-
newTab?: boolean | null
|
|
35
|
-
icon?: string | null
|
|
36
|
-
iconPosition?: 'before' | 'after' | null
|
|
37
|
-
customIcon?: number | Media | null
|
|
38
|
-
} | null
|
|
39
|
-
|
|
40
|
-
export type DDHGNavCodeGridItem = {
|
|
41
|
-
id?: string | null
|
|
42
|
-
code?: string | null
|
|
43
|
-
link?: NavCodeGridLink
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export type DDHGNavCodeGridProps = {
|
|
47
|
-
items?: DDHGNavCodeGridItem[] | null
|
|
48
|
-
defaultHref?: string | null
|
|
49
|
-
containerClassName?: string | null
|
|
50
|
-
gridClassName?: string | null
|
|
51
|
-
cellClassName?: string | null
|
|
52
|
-
showIcons?: boolean | null
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const getPageURLFromDoc = (doc: PortableDoc | number): string | null => {
|
|
56
|
-
if (typeof doc === 'number') return null
|
|
57
|
-
const crumbs = Array.isArray(doc?.breadcrumbs) ? doc.breadcrumbs : []
|
|
58
|
-
if (crumbs.length) {
|
|
59
|
-
const last = crumbs[crumbs.length - 1]
|
|
60
|
-
if (typeof last?.url === 'string' && last.url) return last.url
|
|
61
|
-
}
|
|
62
|
-
const slug = doc?.slug
|
|
63
|
-
if (!slug || slug === 'home') return '/'
|
|
64
|
-
return slug.startsWith('/') ? slug : `/${slug}`
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const getDocumentSlug = (doc: PortableDoc | number): string | null => {
|
|
68
|
-
if (typeof doc === 'number') return null
|
|
69
|
-
return doc?.slug || null
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const getCollectionPath = (relationTo: LinkReference['relationTo']): string => {
|
|
73
|
-
if (relationTo === 'posts') return 'internal-docs'
|
|
74
|
-
if (relationTo === 'thoughts') return 'thoughts'
|
|
75
|
-
if (relationTo === 'projects') return 'archives'
|
|
76
|
-
return ''
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const isExternalUrl = (href: string): boolean =>
|
|
80
|
-
href.startsWith('http://') ||
|
|
81
|
-
href.startsWith('https://') ||
|
|
82
|
-
href.startsWith('mailto:') ||
|
|
83
|
-
href.startsWith('tel:')
|
|
84
|
-
|
|
85
|
-
const resolveHref = (link: NavCodeGridLink, defaultHref = '/archive'): string => {
|
|
86
|
-
if (!link) return defaultHref
|
|
87
|
-
if (link.type === 'custom' && link.url) return link.url
|
|
88
|
-
if (link.type === 'reference' && link.reference?.value) {
|
|
89
|
-
const { relationTo, value } = link.reference
|
|
90
|
-
if (relationTo === 'pages') return getPageURLFromDoc(value) || defaultHref
|
|
91
|
-
const slug = getDocumentSlug(value)
|
|
92
|
-
if (!slug) return defaultHref
|
|
93
|
-
const basePath = getCollectionPath(relationTo)
|
|
94
|
-
return basePath ? `/${basePath}/${slug}` : `/${slug}`
|
|
95
|
-
}
|
|
96
|
-
return defaultHref
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const renderIcon = (link: NavCodeGridLink, showIcons = true) => {
|
|
100
|
-
if (!showIcons || !link) return null
|
|
101
|
-
|
|
102
|
-
if (link.customIcon && typeof link.customIcon === 'object') {
|
|
103
|
-
const iconUrl = getMediaUrl(link.customIcon.url)
|
|
104
|
-
if (iconUrl) {
|
|
105
|
-
return (
|
|
106
|
-
<span className="inline-flex h-3.5 w-3.5 shrink-0 items-center justify-center overflow-hidden">
|
|
107
|
-
<Image
|
|
108
|
-
src={iconUrl}
|
|
109
|
-
alt={link.customIcon.alt || ''}
|
|
110
|
-
width={14}
|
|
111
|
-
height={14}
|
|
112
|
-
className="m-0 block h-full w-full object-contain"
|
|
113
|
-
/>
|
|
114
|
-
</span>
|
|
115
|
-
)
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
if (link.icon) {
|
|
120
|
-
const LucideIcon = LucideIcons[link.icon as keyof typeof LucideIcons] as
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
const
|
|
159
|
-
const
|
|
160
|
-
const
|
|
161
|
-
const
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
{
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import Image from 'next/image'
|
|
4
|
+
import Link from 'next/link'
|
|
5
|
+
import * as LucideIcons from 'lucide-react'
|
|
6
|
+
import React from 'react'
|
|
7
|
+
|
|
8
|
+
import { getMediaUrl } from '@/utilities/getMediaUrl'
|
|
9
|
+
import { cn } from '@/utilities/ui'
|
|
10
|
+
|
|
11
|
+
type PortableDoc = {
|
|
12
|
+
slug?: string | null
|
|
13
|
+
breadcrumbs?: Array<{ url?: string | null }> | null
|
|
14
|
+
[key: string]: unknown
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
type Media = {
|
|
18
|
+
url?: string | null
|
|
19
|
+
alt?: string | null
|
|
20
|
+
[key: string]: unknown
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
type LinkReference =
|
|
24
|
+
| { relationTo: 'pages'; value: number | PortableDoc }
|
|
25
|
+
| { relationTo: 'posts'; value: number | PortableDoc }
|
|
26
|
+
| { relationTo: 'projects'; value: number | PortableDoc }
|
|
27
|
+
| { relationTo: 'thoughts'; value: number | PortableDoc }
|
|
28
|
+
|
|
29
|
+
type NavCodeGridLink = {
|
|
30
|
+
type?: 'reference' | 'custom' | null
|
|
31
|
+
reference?: LinkReference | null
|
|
32
|
+
url?: string | null
|
|
33
|
+
label?: string | null
|
|
34
|
+
newTab?: boolean | null
|
|
35
|
+
icon?: string | null
|
|
36
|
+
iconPosition?: 'before' | 'after' | null
|
|
37
|
+
customIcon?: number | Media | null
|
|
38
|
+
} | null
|
|
39
|
+
|
|
40
|
+
export type DDHGNavCodeGridItem = {
|
|
41
|
+
id?: string | null
|
|
42
|
+
code?: string | null
|
|
43
|
+
link?: NavCodeGridLink
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export type DDHGNavCodeGridProps = {
|
|
47
|
+
items?: DDHGNavCodeGridItem[] | null
|
|
48
|
+
defaultHref?: string | null
|
|
49
|
+
containerClassName?: string | null
|
|
50
|
+
gridClassName?: string | null
|
|
51
|
+
cellClassName?: string | null
|
|
52
|
+
showIcons?: boolean | null
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const getPageURLFromDoc = (doc: PortableDoc | number): string | null => {
|
|
56
|
+
if (typeof doc === 'number') return null
|
|
57
|
+
const crumbs = Array.isArray(doc?.breadcrumbs) ? doc.breadcrumbs : []
|
|
58
|
+
if (crumbs.length) {
|
|
59
|
+
const last = crumbs[crumbs.length - 1]
|
|
60
|
+
if (typeof last?.url === 'string' && last.url) return last.url
|
|
61
|
+
}
|
|
62
|
+
const slug = doc?.slug
|
|
63
|
+
if (!slug || slug === 'home') return '/'
|
|
64
|
+
return slug.startsWith('/') ? slug : `/${slug}`
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const getDocumentSlug = (doc: PortableDoc | number): string | null => {
|
|
68
|
+
if (typeof doc === 'number') return null
|
|
69
|
+
return doc?.slug || null
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const getCollectionPath = (relationTo: LinkReference['relationTo']): string => {
|
|
73
|
+
if (relationTo === 'posts') return 'internal-docs'
|
|
74
|
+
if (relationTo === 'thoughts') return 'thoughts'
|
|
75
|
+
if (relationTo === 'projects') return 'archives'
|
|
76
|
+
return ''
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const isExternalUrl = (href: string): boolean =>
|
|
80
|
+
href.startsWith('http://') ||
|
|
81
|
+
href.startsWith('https://') ||
|
|
82
|
+
href.startsWith('mailto:') ||
|
|
83
|
+
href.startsWith('tel:')
|
|
84
|
+
|
|
85
|
+
const resolveHref = (link: NavCodeGridLink, defaultHref = '/archive'): string => {
|
|
86
|
+
if (!link) return defaultHref
|
|
87
|
+
if (link.type === 'custom' && link.url) return link.url
|
|
88
|
+
if (link.type === 'reference' && link.reference?.value) {
|
|
89
|
+
const { relationTo, value } = link.reference
|
|
90
|
+
if (relationTo === 'pages') return getPageURLFromDoc(value) || defaultHref
|
|
91
|
+
const slug = getDocumentSlug(value)
|
|
92
|
+
if (!slug) return defaultHref
|
|
93
|
+
const basePath = getCollectionPath(relationTo)
|
|
94
|
+
return basePath ? `/${basePath}/${slug}` : `/${slug}`
|
|
95
|
+
}
|
|
96
|
+
return defaultHref
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const renderIcon = (link: NavCodeGridLink, showIcons = true) => {
|
|
100
|
+
if (!showIcons || !link) return null
|
|
101
|
+
|
|
102
|
+
if (link.customIcon && typeof link.customIcon === 'object') {
|
|
103
|
+
const iconUrl = getMediaUrl(link.customIcon.url)
|
|
104
|
+
if (iconUrl) {
|
|
105
|
+
return (
|
|
106
|
+
<span className="inline-flex h-3.5 w-3.5 shrink-0 items-center justify-center overflow-hidden">
|
|
107
|
+
<Image
|
|
108
|
+
src={iconUrl}
|
|
109
|
+
alt={link.customIcon.alt || ''}
|
|
110
|
+
width={14}
|
|
111
|
+
height={14}
|
|
112
|
+
className="m-0 block h-full w-full object-contain"
|
|
113
|
+
/>
|
|
114
|
+
</span>
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (link.icon) {
|
|
120
|
+
const LucideIcon = LucideIcons[link.icon as keyof typeof LucideIcons] as
|
|
121
|
+
React.ComponentType<{ className?: string }> | undefined
|
|
122
|
+
if (LucideIcon) {
|
|
123
|
+
return (
|
|
124
|
+
<span className="inline-flex h-3.5 w-3.5 shrink-0 items-center justify-center">
|
|
125
|
+
<LucideIcon className="h-3.5 w-3.5" />
|
|
126
|
+
</span>
|
|
127
|
+
)
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return null
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const getDelayClass = (index: number) => {
|
|
135
|
+
const delay = Math.min(index * 40, 320)
|
|
136
|
+
return `[transition-delay:${delay}ms]`
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export const DDHGNavCodeGrid: React.FC<DDHGNavCodeGridProps> = ({
|
|
140
|
+
items,
|
|
141
|
+
defaultHref = '/archive',
|
|
142
|
+
containerClassName,
|
|
143
|
+
gridClassName,
|
|
144
|
+
cellClassName,
|
|
145
|
+
showIcons = true,
|
|
146
|
+
}) => {
|
|
147
|
+
if (!Array.isArray(items) || items.length === 0) return null
|
|
148
|
+
|
|
149
|
+
return (
|
|
150
|
+
<div className={cn('w-full max-w-7xl mx-auto', containerClassName, 'pt-24')}>
|
|
151
|
+
<div
|
|
152
|
+
className={cn(
|
|
153
|
+
'grid grid-cols-2 overflow-hidden bg-stone-100/50 dark:bg-stone-900/50 sm:grid-cols-4 !gap-0 shadow-lg',
|
|
154
|
+
gridClassName,
|
|
155
|
+
)}
|
|
156
|
+
>
|
|
157
|
+
{items.map((item, index) => {
|
|
158
|
+
const link = item.link || null
|
|
159
|
+
const href = resolveHref(link, defaultHref || '/archive')
|
|
160
|
+
const label = link?.label || item.code || 'Archive'
|
|
161
|
+
const icon = renderIcon(link, Boolean(showIcons))
|
|
162
|
+
const iconPosition = link?.iconPosition || 'before'
|
|
163
|
+
const target = link?.newTab ? '_blank' : undefined
|
|
164
|
+
const rel = link?.newTab ? 'noopener noreferrer' : undefined
|
|
165
|
+
const className = cn(
|
|
166
|
+
'menu-cell-hover group relative flex items-center justify-center gap-2 bg-stone-200/50 py-2.5 text-xs font-normal uppercase tracking-[0.1em] text-sm [text-shadow:0px_2px_4px_#ffffff45] backdrop-blur-2xl transition-all duration-300 hover:-translate-y-0.5 hover:bg-stone-200/80 hover:text-stone-700 dark:bg-stone-900/50 dark:text-stone-200 dark:hover:bg-stone-800/70 sm:py-3 sm:text-xs md:py-4 hover:shadow-2xl',
|
|
167
|
+
'border-r border-b border-border',
|
|
168
|
+
(index + 1) % 4 === 0 ? 'sm:border-r-0' : ' ',
|
|
169
|
+
index >= 4 ? 'sm:border-b-0' : '',
|
|
170
|
+
(index + 1) % 2 === 0 ? 'border-r-0' : 'border-r',
|
|
171
|
+
index >= 6 ? 'border-b-0' : 'border-b',
|
|
172
|
+
getDelayClass(index),
|
|
173
|
+
cellClassName,
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
const content = (
|
|
177
|
+
<>
|
|
178
|
+
{icon && iconPosition === 'before' && icon}
|
|
179
|
+
<span className="relative z-10">{label}</span>
|
|
180
|
+
{icon && iconPosition === 'after' && icon}
|
|
181
|
+
</>
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
if (isExternalUrl(href)) {
|
|
185
|
+
return (
|
|
186
|
+
<a
|
|
187
|
+
key={item.id || `${label}-${index}`}
|
|
188
|
+
href={href}
|
|
189
|
+
target={target}
|
|
190
|
+
rel={rel}
|
|
191
|
+
className={className}
|
|
192
|
+
style={{
|
|
193
|
+
fontFamily: "'Space Grotesk', sans-serif",
|
|
194
|
+
fontWeight: 400,
|
|
195
|
+
position: 'relative',
|
|
196
|
+
textDecoration: 'none',
|
|
197
|
+
}}
|
|
198
|
+
>
|
|
199
|
+
{content}
|
|
200
|
+
</a>
|
|
201
|
+
)
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
return (
|
|
205
|
+
<Link
|
|
206
|
+
key={item.id || `${label}-${index}`}
|
|
207
|
+
href={href}
|
|
208
|
+
target={target}
|
|
209
|
+
rel={rel}
|
|
210
|
+
className={className}
|
|
211
|
+
style={{
|
|
212
|
+
fontFamily: "'Space Grotesk', sans-serif",
|
|
213
|
+
fontWeight: 400,
|
|
214
|
+
position: 'relative',
|
|
215
|
+
textDecoration: 'none',
|
|
216
|
+
}}
|
|
217
|
+
>
|
|
218
|
+
{content}
|
|
219
|
+
</Link>
|
|
220
|
+
)
|
|
221
|
+
})}
|
|
222
|
+
</div>
|
|
223
|
+
</div>
|
|
224
|
+
)
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export default DDHGNavCodeGrid
|