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
|
@@ -121,8 +121,8 @@ const defaultSteps: ProcessStep[] = [
|
|
|
121
121
|
substeps: [
|
|
122
122
|
{ label: 'Site analysis' },
|
|
123
123
|
{ label: 'User research' },
|
|
124
|
-
{ label: 'Brief definition' }
|
|
125
|
-
]
|
|
124
|
+
{ label: 'Brief definition' },
|
|
125
|
+
],
|
|
126
126
|
},
|
|
127
127
|
{
|
|
128
128
|
num: '02',
|
|
@@ -132,8 +132,8 @@ const defaultSteps: ProcessStep[] = [
|
|
|
132
132
|
substeps: [
|
|
133
133
|
{ label: 'Spatial planning' },
|
|
134
134
|
{ label: 'Material selection' },
|
|
135
|
-
{ label: 'Mood boards' }
|
|
136
|
-
]
|
|
135
|
+
{ label: 'Mood boards' },
|
|
136
|
+
],
|
|
137
137
|
},
|
|
138
138
|
{
|
|
139
139
|
num: '03',
|
|
@@ -143,8 +143,8 @@ const defaultSteps: ProcessStep[] = [
|
|
|
143
143
|
substeps: [
|
|
144
144
|
{ label: 'Technical drawings' },
|
|
145
145
|
{ label: '3D visualization' },
|
|
146
|
-
{ label: 'Specification' }
|
|
147
|
-
]
|
|
146
|
+
{ label: 'Specification' },
|
|
147
|
+
],
|
|
148
148
|
},
|
|
149
149
|
{
|
|
150
150
|
num: '04',
|
|
@@ -154,9 +154,9 @@ const defaultSteps: ProcessStep[] = [
|
|
|
154
154
|
substeps: [
|
|
155
155
|
{ label: 'Construction oversight' },
|
|
156
156
|
{ label: 'Quality assurance' },
|
|
157
|
-
{ label: 'Final handover' }
|
|
158
|
-
]
|
|
159
|
-
}
|
|
157
|
+
{ label: 'Final handover' },
|
|
158
|
+
],
|
|
159
|
+
},
|
|
160
160
|
]
|
|
161
161
|
|
|
162
162
|
let globalInstanceCounter = 0
|
|
@@ -164,7 +164,7 @@ let globalInstanceCounter = 0
|
|
|
164
164
|
function FadeUpOnInView({
|
|
165
165
|
children,
|
|
166
166
|
className = '',
|
|
167
|
-
delay = 0
|
|
167
|
+
delay = 0,
|
|
168
168
|
}: {
|
|
169
169
|
children: React.ReactNode
|
|
170
170
|
className?: string
|
|
@@ -188,7 +188,7 @@ function FadeUpOnInView({
|
|
|
188
188
|
node.style.transitionDelay = '0s'
|
|
189
189
|
}
|
|
190
190
|
},
|
|
191
|
-
{ threshold: 0.25 }
|
|
191
|
+
{ threshold: 0.25 },
|
|
192
192
|
)
|
|
193
193
|
|
|
194
194
|
observer.observe(node)
|
|
@@ -203,7 +203,7 @@ function FadeUpOnInView({
|
|
|
203
203
|
display: 'inline-block',
|
|
204
204
|
opacity: 0,
|
|
205
205
|
transform: 'translateY(24px)',
|
|
206
|
-
transition: 'opacity 700ms ease, transform 700ms ease'
|
|
206
|
+
transition: 'opacity 700ms ease, transform 700ms ease',
|
|
207
207
|
}}
|
|
208
208
|
>
|
|
209
209
|
{children}
|
|
@@ -214,7 +214,7 @@ function FadeUpOnInView({
|
|
|
214
214
|
function RevealText({
|
|
215
215
|
text,
|
|
216
216
|
className = '',
|
|
217
|
-
instanceIndex
|
|
217
|
+
instanceIndex,
|
|
218
218
|
}: {
|
|
219
219
|
text: string[]
|
|
220
220
|
className?: string
|
|
@@ -243,7 +243,7 @@ function RevealText({
|
|
|
243
243
|
setIsVisible(false)
|
|
244
244
|
}
|
|
245
245
|
},
|
|
246
|
-
{ threshold: 0.3 }
|
|
246
|
+
{ threshold: 0.3 },
|
|
247
247
|
)
|
|
248
248
|
|
|
249
249
|
observer.observe(node)
|
|
@@ -271,7 +271,7 @@ function RevealText({
|
|
|
271
271
|
ref={textRef}
|
|
272
272
|
className={cn(
|
|
273
273
|
'process-section-reveal-text reveal-text animation inline-block h-auto bg-transparent text-left font-bold uppercase leading-none tracking-[1px]',
|
|
274
|
-
className
|
|
274
|
+
className,
|
|
275
275
|
)}
|
|
276
276
|
>
|
|
277
277
|
{words.map((word, wordIndex) => {
|
|
@@ -297,7 +297,7 @@ function RevealText({
|
|
|
297
297
|
animationDuration: '1s',
|
|
298
298
|
animationFillMode: 'forwards',
|
|
299
299
|
animationDelay: `${baseDelay + index * 0.05}s`,
|
|
300
|
-
transitionTimingFunction: 'cubic-bezier(0.075, 0.82, 0.165, 1)'
|
|
300
|
+
transitionTimingFunction: 'cubic-bezier(0.075, 0.82, 0.165, 1)',
|
|
301
301
|
}}
|
|
302
302
|
>
|
|
303
303
|
{char}
|
|
@@ -321,7 +321,7 @@ function StaggerFadeUp({
|
|
|
321
321
|
className = '',
|
|
322
322
|
delay = 0,
|
|
323
323
|
as: Tag = 'div',
|
|
324
|
-
style
|
|
324
|
+
style,
|
|
325
325
|
}: {
|
|
326
326
|
children: React.ReactNode
|
|
327
327
|
className?: string
|
|
@@ -344,7 +344,7 @@ function StaggerFadeUp({
|
|
|
344
344
|
node.style.transitionDelay = `${delay}s`
|
|
345
345
|
observer.unobserve(node)
|
|
346
346
|
},
|
|
347
|
-
{ threshold: 0.18 }
|
|
347
|
+
{ threshold: 0.18 },
|
|
348
348
|
)
|
|
349
349
|
|
|
350
350
|
observer.observe(node)
|
|
@@ -361,7 +361,7 @@ function StaggerFadeUp({
|
|
|
361
361
|
filter: 'blur(6px)',
|
|
362
362
|
transition:
|
|
363
363
|
'opacity 820ms ease, transform 820ms cubic-bezier(0.22, 1, 0.36, 1), filter 820ms ease',
|
|
364
|
-
...style
|
|
364
|
+
...style,
|
|
365
365
|
}}
|
|
366
366
|
>
|
|
367
367
|
{children}
|
|
@@ -395,25 +395,24 @@ function ProcessDiagram({ label, content }: { label?: string | null; content?: a
|
|
|
395
395
|
transition={{ duration: 0.9, delay: 0.3, ease: [0.22, 1, 0.36, 1] }}
|
|
396
396
|
>
|
|
397
397
|
<div className="ProcessSectionDiagram02 z-plane-0 p-5 md:p-8">
|
|
398
|
-
<p className="ProcessSectionDiagram03 mb-4 flex items-center gap-2 font-mono text-
|
|
398
|
+
<p className="ProcessSectionDiagram03 mb-4 flex items-center gap-2 font-mono text-xs uppercase tracking-[0.15em] text-stone-600 dark:text-stone-300">
|
|
399
399
|
<Workflow className="ProcessSectionDiagram04 h-3.5 w-3.5" strokeWidth={1.5} />
|
|
400
400
|
{label || 'Process Flow Diagram'}
|
|
401
401
|
</p>
|
|
402
402
|
|
|
403
403
|
{hasRichTextContent(content) ? (
|
|
404
|
-
<div className="ProcessSectionDiagram05 relative min-h-
|
|
404
|
+
<div className="ProcessSectionDiagram05 relative min-h-75 w-full overflow-hidden">
|
|
405
405
|
<RichText
|
|
406
406
|
data={content}
|
|
407
407
|
enableGutter={false}
|
|
408
408
|
enableProse={false}
|
|
409
|
-
className="ProcessSectionDiagram06 ProcessSectionRichTextVisual h-full min-h-
|
|
409
|
+
className="ProcessSectionDiagram06 ProcessSectionRichTextVisual h-full min-h-75 w-full bg-stone-100/50 p-4 dark:bg-stone-900/50 *:m-0 [&_.media-block]:m-0 [&_img]:m-0"
|
|
410
410
|
/>
|
|
411
411
|
</div>
|
|
412
412
|
) : (
|
|
413
|
-
<div className="ProcessSectionDiagram07 flex min-h-
|
|
414
|
-
<span className="ProcessSectionDiagram08 inline-flex items-center gap-2 text-
|
|
415
|
-
<InlineLogoIcon className="ProcessSectionDiagram09 h-auto w-
|
|
416
|
-
|{' '}
|
|
413
|
+
<div className="ProcessSectionDiagram07 flex min-h-75 w-full bg-linear-to-br from-[#838383] to-[#8e887c] dark:from-[#838383] dark:to-[#8e887c] items-center justify-center">
|
|
414
|
+
<span className="ProcessSectionDiagram08 inline-flex items-center gap-2 text-xs uppercase tracking-[0.15em] text-stone-600 dark:text-stone-300">
|
|
415
|
+
<InlineLogoIcon className="ProcessSectionDiagram09 h-auto w-24 opacity-90" />|{' '}
|
|
417
416
|
</span>
|
|
418
417
|
</div>
|
|
419
418
|
)}
|
|
@@ -435,7 +434,7 @@ export const DDHGProcessSec: React.FC<DDHGProcessSecProps> = ({
|
|
|
435
434
|
diagramLabel = 'Process Flow Diagram',
|
|
436
435
|
diagramContent,
|
|
437
436
|
diagramVisualContent,
|
|
438
|
-
steps
|
|
437
|
+
steps,
|
|
439
438
|
}) => {
|
|
440
439
|
const processSteps = getSteps(steps)
|
|
441
440
|
const visualContent = diagramContent || diagramVisualContent
|
|
@@ -461,7 +460,7 @@ export const DDHGProcessSec: React.FC<DDHGProcessSecProps> = ({
|
|
|
461
460
|
<StaggerFadeUp
|
|
462
461
|
as="p"
|
|
463
462
|
delay={0.05}
|
|
464
|
-
className="ProcessSection04 eyebrowPrefix eyebrowEmphasis mb-2 origin-left
|
|
463
|
+
className="ProcessSection04 eyebrowPrefix eyebrowEmphasis mb-2 origin-left text-xs uppercase tracking-[0.2em] text-stone-400 dark:text-stone-400"
|
|
465
464
|
>
|
|
466
465
|
{eyebrowPrefix && (
|
|
467
466
|
<span className="ProcessSection05 eyebrowPrefix font-light">{eyebrowPrefix} </span>
|
|
@@ -503,37 +502,37 @@ export const DDHGProcessSec: React.FC<DDHGProcessSecProps> = ({
|
|
|
503
502
|
transition={{ duration: 0.9, delay: i * 0.1, ease: [0.22, 1, 0.36, 1] }}
|
|
504
503
|
>
|
|
505
504
|
<div className="ProcessSection13 flex gap-6">
|
|
506
|
-
<div className="ProcessSection14 flex
|
|
507
|
-
<div className="ProcessSection15 z-plane-1 flex h-14 w-14 items-center justify-center border border-
|
|
505
|
+
<div className="ProcessSection14 flex shrink-0 flex-col items-center">
|
|
506
|
+
<div className="ProcessSection15 bg-stone-200 dark:bg-zinc-900 z-plane-1 flex h-14 w-14 items-center justify-center rounded-md squircle border border-stone-100 dark:border-zinc-800">
|
|
508
507
|
<span className="ProcessSection16 text-lg font-semibold text-stone-700 dark:text-stone-200">
|
|
509
508
|
{step.num || String(i + 1).padStart(2, '0')}
|
|
510
509
|
</span>
|
|
511
510
|
</div>
|
|
512
511
|
{i < processSteps.length - 1 && (
|
|
513
512
|
<motion.div
|
|
514
|
-
className="ProcessSection17 mb-2 mt-2 w-px
|
|
513
|
+
className="ProcessSection17 mb-2 mt-2 w-px grow bg-indigo-500"
|
|
515
514
|
initial={{ scaleY: 0, opacity: 0 }}
|
|
516
515
|
whileInView={{ scaleY: 1, opacity: 1 }}
|
|
517
516
|
viewport={{ once: true, amount: 0.2 }}
|
|
518
517
|
transition={{
|
|
519
518
|
duration: 0.8,
|
|
520
519
|
delay: i * 0.1 + 0.2,
|
|
521
|
-
ease: [0.22, 1, 0.36, 1]
|
|
520
|
+
ease: [0.22, 1, 0.36, 1],
|
|
522
521
|
}}
|
|
523
522
|
style={{ minHeight: 40, transformOrigin: 'top' }}
|
|
524
523
|
/>
|
|
525
524
|
)}
|
|
526
525
|
</div>
|
|
527
526
|
|
|
528
|
-
<div className="ProcessSection18
|
|
529
|
-
<div className="ProcessSection19
|
|
527
|
+
<div className="ProcessSection18 grow pb-2">
|
|
528
|
+
<div className="ProcessSection19 bg-stone-200 dark:bg-zinc-900 rounded-md squircle border-border border p-5 transition-all duration-300 z-depth-hover hover:shadow-2xl hover:-translate-y-2 md:p-6">
|
|
530
529
|
{step.title && (
|
|
531
|
-
<
|
|
530
|
+
<h2 className="ProcessSection20 mb-2 text-2xl font-semibold text-indigo-700 dark:text-indigo-500 md:text-3xl">
|
|
532
531
|
{step.title}
|
|
533
|
-
</
|
|
532
|
+
</h2>
|
|
534
533
|
)}
|
|
535
534
|
{getStepDescription(step) && (
|
|
536
|
-
<p className="ProcessSection21 mb-4 text-
|
|
535
|
+
<p className="ProcessSection21 mb-4 text-base font-light leading-relaxed text-stone-700 dark:text-stone-200">
|
|
537
536
|
{getStepDescription(step)}
|
|
538
537
|
</p>
|
|
539
538
|
)}
|
|
@@ -545,8 +544,8 @@ export const DDHGProcessSec: React.FC<DDHGProcessSecProps> = ({
|
|
|
545
544
|
<span
|
|
546
545
|
key={substep.id || `${substep.label}-${subIndex}`}
|
|
547
546
|
className={cn(
|
|
548
|
-
'ProcessSection23 arch-edge-sm border border-
|
|
549
|
-
`ProcessSectionSubstep${i + 1}-${subIndex + 1}
|
|
547
|
+
'ProcessSection23 arch-edge-sm rounded-md squircle border border-stone-300 px-2 py-1 text-xs text-stone-600 dark:border-stone-700 dark:text-stone-300',
|
|
548
|
+
`ProcessSectionSubstep${i + 1}-${subIndex + 1}`,
|
|
550
549
|
)}
|
|
551
550
|
>
|
|
552
551
|
{substep.label}
|
|
@@ -6,7 +6,7 @@ import { cn } from '@/utilities/ui'
|
|
|
6
6
|
import {
|
|
7
7
|
ServiceDetailCard,
|
|
8
8
|
type ServiceDetailItem,
|
|
9
|
-
type ServiceDetailLayout
|
|
9
|
+
type ServiceDetailLayout,
|
|
10
10
|
} from './ServiceDetailCard'
|
|
11
11
|
|
|
12
12
|
export type DDHGServiceDetailsProps = {
|
|
@@ -35,8 +35,8 @@ const defaultServices: ServiceDetailItem[] = [
|
|
|
35
35
|
{ label: 'Brief development' },
|
|
36
36
|
{ label: 'Space audit' },
|
|
37
37
|
{ label: 'Stakeholder alignment' },
|
|
38
|
-
{ label: 'Design direction' }
|
|
39
|
-
]
|
|
38
|
+
{ label: 'Design direction' },
|
|
39
|
+
],
|
|
40
40
|
},
|
|
41
41
|
{
|
|
42
42
|
code: 'SVC-02',
|
|
@@ -49,8 +49,8 @@ const defaultServices: ServiceDetailItem[] = [
|
|
|
49
49
|
{ label: 'Concept strategy' },
|
|
50
50
|
{ label: 'Mood and material direction' },
|
|
51
51
|
{ label: 'Spatial planning' },
|
|
52
|
-
{ label: 'Preliminary visualisation' }
|
|
53
|
-
]
|
|
52
|
+
{ label: 'Preliminary visualisation' },
|
|
53
|
+
],
|
|
54
54
|
},
|
|
55
55
|
{
|
|
56
56
|
code: 'SVC-03',
|
|
@@ -63,9 +63,9 @@ const defaultServices: ServiceDetailItem[] = [
|
|
|
63
63
|
{ label: 'Interior detailing' },
|
|
64
64
|
{ label: 'Material schedules' },
|
|
65
65
|
{ label: 'Furniture direction' },
|
|
66
|
-
{ label: 'Lighting coordination' }
|
|
67
|
-
]
|
|
68
|
-
}
|
|
66
|
+
{ label: 'Lighting coordination' },
|
|
67
|
+
],
|
|
68
|
+
},
|
|
69
69
|
]
|
|
70
70
|
|
|
71
71
|
function getServices(services?: ServiceDetailItem[] | null) {
|
|
@@ -75,7 +75,7 @@ function getServices(services?: ServiceDetailItem[] | null) {
|
|
|
75
75
|
function getLayout(
|
|
76
76
|
service: ServiceDetailItem,
|
|
77
77
|
index: number,
|
|
78
|
-
layoutMode?: 'cycle' | 'manual' | null
|
|
78
|
+
layoutMode?: 'cycle' | 'manual' | null,
|
|
79
79
|
): ServiceDetailLayout {
|
|
80
80
|
if (layoutMode === 'manual' && service.layout && service.layout !== 'auto') return service.layout
|
|
81
81
|
return layoutCycle[index % layoutCycle.length]
|
|
@@ -100,7 +100,7 @@ export const DDHGServiceDetails: React.FC<DDHGServiceDetailsProps> = ({
|
|
|
100
100
|
eyebrowPrefix = 'detailed',
|
|
101
101
|
eyebrowEmphasis = 'breakdown',
|
|
102
102
|
layoutMode = 'cycle',
|
|
103
|
-
services
|
|
103
|
+
services,
|
|
104
104
|
}) => {
|
|
105
105
|
const serviceItems = useMemo(() => getServices(services), [services])
|
|
106
106
|
const [expanded, setExpanded] = useState<number | null>(null)
|
|
@@ -123,7 +123,7 @@ export const DDHGServiceDetails: React.FC<DDHGServiceDetailsProps> = ({
|
|
|
123
123
|
transition={{ duration: 0.9, ease: [0.22, 1, 0.36, 1] }}
|
|
124
124
|
>
|
|
125
125
|
{(eyebrowPrefix || eyebrowEmphasis) && (
|
|
126
|
-
<p className="ServiceDetails04 mb-2 text-
|
|
126
|
+
<p className="ServiceDetails04 mb-2 text-xs uppercase tracking-[0.2em] text-stone-600 dark:text-stone-200">
|
|
127
127
|
{eyebrowPrefix && <span className="font-light">{eyebrowPrefix} </span>}
|
|
128
128
|
{eyebrowEmphasis && <span className="font-medium">{eyebrowEmphasis}</span>}
|
|
129
129
|
</p>
|
|
@@ -183,18 +183,18 @@ function VisualContent({ service }: { service: ServiceDetailItem }) {
|
|
|
183
183
|
const content = service.visualContent || service.mediaContent || null
|
|
184
184
|
if (hasRichTextContent(content)) {
|
|
185
185
|
return (
|
|
186
|
-
<div className="relative h-full min-h-
|
|
186
|
+
<div className="relative h-full min-h-75 w-full overflow-hidden rounded-md squircle border border-stone-300/10 bg-stone-100/50 p-4 dark:border-stone-700/10 dark:bg-stone-900/50 hover:shadow-xl transition-all duration-300">
|
|
187
187
|
<RichText
|
|
188
188
|
data={content}
|
|
189
189
|
enableGutter={false}
|
|
190
190
|
enableProse={false}
|
|
191
|
-
className="h-full min-h-
|
|
191
|
+
className="h-full min-h-75 w-full *:m-0 [&_.media-block]:m-0 [&_img]:m-0"
|
|
192
192
|
/>
|
|
193
193
|
</div>
|
|
194
194
|
)
|
|
195
195
|
}
|
|
196
196
|
return (
|
|
197
|
-
<div className="min-h-
|
|
197
|
+
<div className="min-h-75 w-full rounded-md squircle bg-linear-to-br from-[#838383] to-[#8e887c] m-auto flex items-center justify-center">
|
|
198
198
|
<InlineLogoIcon />
|
|
199
199
|
</div>
|
|
200
200
|
)
|
|
@@ -206,7 +206,7 @@ function ToggleButton({ isExpanded, onToggle }: { isExpanded: boolean; onToggle:
|
|
|
206
206
|
<button
|
|
207
207
|
type="button"
|
|
208
208
|
onClick={onToggle}
|
|
209
|
-
className="btn-outline
|
|
209
|
+
className="btn-outline inline-flex items-center gap-2 self-start rounded-md squircle border border-stone-300 bg-stone-100/50 px-4 py-2 text-base transition-all duration-300 hover:brightness-105 dark:border-stone-700/10 dark:bg-stone-900/50"
|
|
210
210
|
>
|
|
211
211
|
{isExpanded ? 'Close Details' : 'View Details'}
|
|
212
212
|
<Icon className="h-3.5 w-3.5" strokeWidth={1.8} />
|
|
@@ -225,7 +225,7 @@ function ExpandPanel({ isExpanded, children }: { isExpanded: boolean; children:
|
|
|
225
225
|
variants={{
|
|
226
226
|
hidden: {
|
|
227
227
|
height: 0,
|
|
228
|
-
opacity: 0
|
|
228
|
+
opacity: 0,
|
|
229
229
|
},
|
|
230
230
|
visible: {
|
|
231
231
|
height: 'auto',
|
|
@@ -234,8 +234,8 @@ function ExpandPanel({ isExpanded, children }: { isExpanded: boolean; children:
|
|
|
234
234
|
duration: 0.5,
|
|
235
235
|
ease: [0.22, 1, 0.36, 1],
|
|
236
236
|
staggerChildren: 0.08,
|
|
237
|
-
delayChildren: 0.1
|
|
238
|
-
}
|
|
237
|
+
delayChildren: 0.1,
|
|
238
|
+
},
|
|
239
239
|
},
|
|
240
240
|
exit: {
|
|
241
241
|
height: 0,
|
|
@@ -243,9 +243,9 @@ function ExpandPanel({ isExpanded, children }: { isExpanded: boolean; children:
|
|
|
243
243
|
transition: {
|
|
244
244
|
duration: 0.35,
|
|
245
245
|
staggerChildren: 0.05,
|
|
246
|
-
staggerDirection: -1
|
|
247
|
-
}
|
|
248
|
-
}
|
|
246
|
+
staggerDirection: -1,
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
249
|
}}
|
|
250
250
|
className="overflow-hidden"
|
|
251
251
|
>
|
|
@@ -254,20 +254,20 @@ function ExpandPanel({ isExpanded, children }: { isExpanded: boolean; children:
|
|
|
254
254
|
variants={{
|
|
255
255
|
hidden: {
|
|
256
256
|
opacity: 0,
|
|
257
|
-
y: 10
|
|
257
|
+
y: 10,
|
|
258
258
|
},
|
|
259
259
|
visible: {
|
|
260
260
|
opacity: 1,
|
|
261
261
|
y: 0,
|
|
262
262
|
transition: {
|
|
263
263
|
duration: 0.3,
|
|
264
|
-
ease: [0.22, 1, 0.36, 1]
|
|
265
|
-
}
|
|
264
|
+
ease: [0.22, 1, 0.36, 1],
|
|
265
|
+
},
|
|
266
266
|
},
|
|
267
267
|
exit: {
|
|
268
268
|
opacity: 0,
|
|
269
|
-
y: 6
|
|
270
|
-
}
|
|
269
|
+
y: 6,
|
|
270
|
+
},
|
|
271
271
|
}}
|
|
272
272
|
>
|
|
273
273
|
{child}
|
|
@@ -283,13 +283,13 @@ function DetailContent({
|
|
|
283
283
|
service,
|
|
284
284
|
index,
|
|
285
285
|
isExpanded,
|
|
286
|
-
onToggle
|
|
286
|
+
onToggle,
|
|
287
287
|
}: Omit<ServiceDetailCardProps, 'layout'>) {
|
|
288
288
|
const points = getPoints(service)
|
|
289
289
|
return (
|
|
290
290
|
<div className="flex h-full flex-col justify-center p-4 md:p-6">
|
|
291
291
|
{service.code && (
|
|
292
|
-
<span className="mb-3 block font-mono text-
|
|
292
|
+
<span className="mb-3 block font-mono text-xs tracking-[0.15em] text-stone-600 dark:text-stone-300">
|
|
293
293
|
{service.code}
|
|
294
294
|
</span>
|
|
295
295
|
)}
|
|
@@ -316,12 +316,12 @@ function DetailContent({
|
|
|
316
316
|
</div>
|
|
317
317
|
<ToggleButton isExpanded={isExpanded} onToggle={onToggle} />
|
|
318
318
|
<ExpandPanel isExpanded={isExpanded}>
|
|
319
|
-
<div className="mt-4 border-t border-
|
|
319
|
+
<div className="mt-4 border-t border-stone-300 dark:border-stone-700/10 pt-4">
|
|
320
320
|
<div className="flex flex-wrap gap-2">
|
|
321
321
|
{points.map((detail) => (
|
|
322
322
|
<span
|
|
323
323
|
key={detail}
|
|
324
|
-
className="arch-edge-sm border border-
|
|
324
|
+
className="arch-edge-sm rounded-md squircle border border-stone-300 px-3 py-1.5 text-xs text-stone-700 dark:border-stone-700/10 dark:text-stone-200"
|
|
325
325
|
>
|
|
326
326
|
{detail}
|
|
327
327
|
</span>
|
|
@@ -337,7 +337,7 @@ export function ServiceDetailCard(props: ServiceDetailCardProps) {
|
|
|
337
337
|
const { service, layout } = props
|
|
338
338
|
if (layout === 'center') {
|
|
339
339
|
return (
|
|
340
|
-
<div className="z-plane-2 chamfer-accent relative overflow-hidden">
|
|
340
|
+
<div className="z-plane-2 chamfer-accent relative overflow-hidden rounded-md squircle border border-stone-300 bg-stone-100/50 transition-all duration-300 dark:border-stone-700/10 dark:bg-stone-900/50">
|
|
341
341
|
<div className="pointer-events-none absolute inset-0 opacity-30">
|
|
342
342
|
<VisualContent service={service} />
|
|
343
343
|
</div>
|
|
@@ -350,8 +350,8 @@ export function ServiceDetailCard(props: ServiceDetailCardProps) {
|
|
|
350
350
|
|
|
351
351
|
if (layout === 'bleed') {
|
|
352
352
|
return (
|
|
353
|
-
<div className="z-plane-2 chamfer-accent relative overflow-hidden">
|
|
354
|
-
<div className="pointer-events-none absolute right-0 top-0 hidden h-full min-h-
|
|
353
|
+
<div className="z-plane-2 chamfer-accent relative overflow-hidden rounded-md squircle border border-stone-300 bg-stone-100/50 transition-all duration-300 dark:border-stone-700/10 dark:bg-stone-900/50">
|
|
354
|
+
<div className="pointer-events-none absolute right-0 top-0 hidden h-full min-h-75 w-1/2 opacity-30 lg:block">
|
|
355
355
|
<VisualContent service={service} />
|
|
356
356
|
</div>
|
|
357
357
|
<div className="relative max-w-2xl">
|
|
@@ -370,9 +370,7 @@ export function ServiceDetailCard(props: ServiceDetailCardProps) {
|
|
|
370
370
|
<div className="z-plane-2 chamfer-accent">
|
|
371
371
|
<div className={cn('grid grid-cols-1 gap-0', gridClass)}>
|
|
372
372
|
{visualFirst && (
|
|
373
|
-
<div
|
|
374
|
-
className={cn('flex min-h-[300px] items-center justify-center p-4 md:p-6', visualClass)}
|
|
375
|
-
>
|
|
373
|
+
<div className={cn('flex min-h-75 items-center justify-center p-4 md:p-6', visualClass)}>
|
|
376
374
|
<VisualContent service={service} />
|
|
377
375
|
</div>
|
|
378
376
|
)}
|
|
@@ -380,9 +378,7 @@ export function ServiceDetailCard(props: ServiceDetailCardProps) {
|
|
|
380
378
|
<DetailContent {...props} />
|
|
381
379
|
</div>
|
|
382
380
|
{!visualFirst && (
|
|
383
|
-
<div
|
|
384
|
-
className={cn('flex min-h-[300px] items-center justify-center p-4 md:p-6', visualClass)}
|
|
385
|
-
>
|
|
381
|
+
<div className={cn('flex min-h-75 items-center justify-center p-4 md:p-6', visualClass)}>
|
|
386
382
|
<VisualContent service={service} />
|
|
387
383
|
</div>
|
|
388
384
|
)}
|
|
@@ -182,7 +182,7 @@ export const DDHGServiceHero: React.FC<DDHGServiceHeroProps> = ({
|
|
|
182
182
|
>
|
|
183
183
|
{customCSS && <style dangerouslySetInnerHTML={{ __html: customCSS }} />}
|
|
184
184
|
<motion.div
|
|
185
|
-
className="ServiceHeroCard relative z-10 mx-auto max-w-4xl overflow-clip"
|
|
185
|
+
className="ServiceHeroCard relative z-10 mx-auto max-w-4xl overflow-clip rounded-md squircle bg-stone-100/50 p-6 dark:bg-stone-900/50 md:p-8"
|
|
186
186
|
initial={{ opacity: 0, y: 20 }}
|
|
187
187
|
whileInView={{ opacity: 1, y: 0 }}
|
|
188
188
|
viewport={{ once: true, amount: 0.35 }}
|
|
@@ -33,7 +33,7 @@ const defaultServices: ServiceOverviewItem[] = [
|
|
|
33
33
|
description:
|
|
34
34
|
'We begin by understanding the brief, the existing space, operational needs, and the people who will use it every day.',
|
|
35
35
|
timeline: '8-12 weeks',
|
|
36
|
-
engagement: 'Fixed Fee'
|
|
36
|
+
engagement: 'Fixed Fee',
|
|
37
37
|
},
|
|
38
38
|
{
|
|
39
39
|
code: 'SVC-02',
|
|
@@ -41,7 +41,7 @@ const defaultServices: ServiceOverviewItem[] = [
|
|
|
41
41
|
description:
|
|
42
42
|
'We translate business goals into a clear spatial direction, balancing brand, movement, function, and atmosphere.',
|
|
43
43
|
timeline: '12-16 weeks',
|
|
44
|
-
engagement: 'Project-based'
|
|
44
|
+
engagement: 'Project-based',
|
|
45
45
|
},
|
|
46
46
|
{
|
|
47
47
|
code: 'SVC-03',
|
|
@@ -49,7 +49,7 @@ const defaultServices: ServiceOverviewItem[] = [
|
|
|
49
49
|
description:
|
|
50
50
|
'We develop the interior architecture, material language, lighting, furniture strategy, and practical user experience.',
|
|
51
51
|
timeline: '16-24 weeks',
|
|
52
|
-
engagement: 'Fixed Fee'
|
|
52
|
+
engagement: 'Fixed Fee',
|
|
53
53
|
},
|
|
54
54
|
{
|
|
55
55
|
code: 'SVC-04',
|
|
@@ -57,7 +57,7 @@ const defaultServices: ServiceOverviewItem[] = [
|
|
|
57
57
|
description:
|
|
58
58
|
'We prepare the technical drawings, schedules, and coordination notes required for approval, pricing, and buildability.',
|
|
59
59
|
timeline: '8-12 weeks',
|
|
60
|
-
engagement: 'Project-based'
|
|
60
|
+
engagement: 'Project-based',
|
|
61
61
|
},
|
|
62
62
|
{
|
|
63
63
|
code: 'SVC-05',
|
|
@@ -65,7 +65,7 @@ const defaultServices: ServiceOverviewItem[] = [
|
|
|
65
65
|
description:
|
|
66
66
|
'We support selection, specification, and sourcing so the design intent remains consistent through delivery.',
|
|
67
67
|
timeline: '12-16 weeks',
|
|
68
|
-
engagement: 'Fixed Fee'
|
|
68
|
+
engagement: 'Fixed Fee',
|
|
69
69
|
},
|
|
70
70
|
{
|
|
71
71
|
code: 'SVC-06',
|
|
@@ -73,8 +73,8 @@ const defaultServices: ServiceOverviewItem[] = [
|
|
|
73
73
|
description:
|
|
74
74
|
'We help close the project with practical review, refinements, and alignment between the completed space and the original intent.',
|
|
75
75
|
timeline: '16-24 weeks',
|
|
76
|
-
engagement: 'Project-based'
|
|
77
|
-
}
|
|
76
|
+
engagement: 'Project-based',
|
|
77
|
+
},
|
|
78
78
|
]
|
|
79
79
|
|
|
80
80
|
function getServices(services?: ServiceOverviewItem[] | null) {
|
|
@@ -116,7 +116,7 @@ export const DDHGServiceOverview: React.FC<DDHGServiceOverviewProps> = ({
|
|
|
116
116
|
scrollSpeed,
|
|
117
117
|
eyebrowPrefix = 'service',
|
|
118
118
|
eyebrowEmphasis = 'catalog',
|
|
119
|
-
services
|
|
119
|
+
services,
|
|
120
120
|
}) => {
|
|
121
121
|
const serviceItems = useMemo(() => getServices(services), [services])
|
|
122
122
|
const [activeIndex, setActiveIndex] = useState(0)
|
|
@@ -141,7 +141,7 @@ export const DDHGServiceOverview: React.FC<DDHGServiceOverviewProps> = ({
|
|
|
141
141
|
transition={{ duration: 0.9, ease: [0.22, 1, 0.36, 1] }}
|
|
142
142
|
>
|
|
143
143
|
{(eyebrowPrefix || eyebrowEmphasis) && (
|
|
144
|
-
<p className="ServiceOverview03 mb-2 text-
|
|
144
|
+
<p className="ServiceOverview03 mb-2 text-xs uppercase tracking-[0.2em] text-stone-600 dark:text-stone-300">
|
|
145
145
|
{eyebrowPrefix && <span className="font-light">{eyebrowPrefix} </span>}
|
|
146
146
|
{eyebrowEmphasis && <span className="font-medium">{eyebrowEmphasis}</span>}
|
|
147
147
|
</p>
|
|
@@ -168,17 +168,17 @@ export const DDHGServiceOverview: React.FC<DDHGServiceOverviewProps> = ({
|
|
|
168
168
|
<div className="ServiceOverview08 flex flex-col items-center text-center">
|
|
169
169
|
<div
|
|
170
170
|
className={cn(
|
|
171
|
-
'ServiceOverview09 mb-3 flex h-12 w-12 items-center justify-center border transition-all duration-500',
|
|
171
|
+
'ServiceOverview09 mb-3 flex h-12 w-12 items-center justify-center rounded-md squircle border transition-all duration-500',
|
|
172
172
|
isActive
|
|
173
173
|
? 'border-[#444444] bg-[#444444]'
|
|
174
|
-
: 'border-[#444444] bg-[#e5e7eb] group-hover:border-[#A8A29E]'
|
|
174
|
+
: 'border-[#444444] bg-[#e5e7eb] group-hover:border-[#A8A29E]',
|
|
175
175
|
)}
|
|
176
|
-
style={{ borderRadius: '
|
|
176
|
+
style={{ borderRadius: '6px' }}
|
|
177
177
|
>
|
|
178
178
|
<span
|
|
179
179
|
className={cn(
|
|
180
180
|
'ServiceOverview10 text-xs font-semibold transition-colors duration-500',
|
|
181
|
-
isActive ? 'text-[#F5F3EF]' : 'text-stone-600 dark:text-stone-300'
|
|
181
|
+
isActive ? 'text-[#F5F3EF]' : 'text-stone-600 dark:text-stone-300',
|
|
182
182
|
)}
|
|
183
183
|
>
|
|
184
184
|
{String(i + 1).padStart(2, '0')}
|
|
@@ -186,16 +186,16 @@ export const DDHGServiceOverview: React.FC<DDHGServiceOverviewProps> = ({
|
|
|
186
186
|
</div>
|
|
187
187
|
<span
|
|
188
188
|
className={cn(
|
|
189
|
-
'ServiceOverview11 text-
|
|
189
|
+
'ServiceOverview11 text-base font-medium uppercase tracking-widest transition-colors duration-500',
|
|
190
190
|
isActive
|
|
191
191
|
? 'text-stone-700 dark:text-stone-200'
|
|
192
|
-
: 'text-stone-600 dark:text-stone-300 group-hover:text-stone-700'
|
|
192
|
+
: 'text-stone-600 dark:text-stone-300 group-hover:text-stone-700',
|
|
193
193
|
)}
|
|
194
194
|
>
|
|
195
195
|
{service.title}
|
|
196
196
|
</span>
|
|
197
197
|
{service.code && (
|
|
198
|
-
<span className="ServiceOverview12 mt-1 font-mono text-
|
|
198
|
+
<span className="ServiceOverview12 mt-1 font-mono text-xs text-stone-600 dark:text-stone-300">
|
|
199
199
|
{service.code}
|
|
200
200
|
</span>
|
|
201
201
|
)}
|
|
@@ -213,15 +213,15 @@ export const DDHGServiceOverview: React.FC<DDHGServiceOverviewProps> = ({
|
|
|
213
213
|
transition={{ duration: 0.2, delay: 0.05, ease: [0.22, 1, 0.36, 1] }}
|
|
214
214
|
>
|
|
215
215
|
<motion.div
|
|
216
|
-
className="ServiceOverview14 z-plane-1 p-6 md:p-8"
|
|
216
|
+
className="ServiceOverview14 z-plane-1 rounded-md squircle border border-stone-300 bg-stone-100/50 p-6 transition-all duration-300 dark:border-stone-700/10 dark:bg-stone-900/50 md:p-8"
|
|
217
217
|
initial={{ x: -40, filter: 'blur(20px)', opacity: 0 }}
|
|
218
218
|
animate={{ x: 0, filter: 'blur(0px)', opacity: 1 }}
|
|
219
219
|
transition={{ duration: 0.2, delay: 0.08, ease: [0.22, 1, 0.36, 1] }}
|
|
220
220
|
>
|
|
221
221
|
<div className="flex flex-col gap-6 md:flex-row md:gap-10">
|
|
222
|
-
<div className="
|
|
222
|
+
<div className="shrink-0">
|
|
223
223
|
{activeService.code && (
|
|
224
|
-
<span className="mb-2 block font-mono text-
|
|
224
|
+
<span className="mb-2 block font-mono text-xs uppercase tracking-[0.15em] text-stone-600 dark:text-stone-300">
|
|
225
225
|
{activeService.code}
|
|
226
226
|
</span>
|
|
227
227
|
)}
|
|
@@ -237,9 +237,9 @@ export const DDHGServiceOverview: React.FC<DDHGServiceOverviewProps> = ({
|
|
|
237
237
|
</p>
|
|
238
238
|
)}
|
|
239
239
|
</div>
|
|
240
|
-
<div className="flex
|
|
240
|
+
<div className="flex grow flex-col gap-5 md:flex-row md:items-center md:gap-8">
|
|
241
241
|
<div className="text-center">
|
|
242
|
-
<p className="mb-1 text-
|
|
242
|
+
<p className="mb-1 text-xs uppercase tracking-[0.15em] text-stone-600 dark:text-stone-300">
|
|
243
243
|
Typical Timeline
|
|
244
244
|
</p>
|
|
245
245
|
<p className="text-md font-semibold text-stone-700 dark:text-stone-200">
|
|
@@ -248,7 +248,7 @@ export const DDHGServiceOverview: React.FC<DDHGServiceOverviewProps> = ({
|
|
|
248
248
|
</div>
|
|
249
249
|
<div className="hidden h-10 w-px bg-stone-500 md:block" />
|
|
250
250
|
<div className="text-center">
|
|
251
|
-
<p className="mb-1 text-
|
|
251
|
+
<p className="mb-1 text-xs uppercase tracking-[0.15em] text-stone-600 dark:text-stone-300">
|
|
252
252
|
Deliverables
|
|
253
253
|
</p>
|
|
254
254
|
<p className="inline-flex items-center gap-2 text-md font-semibold text-stone-700 dark:text-stone-200">
|
|
@@ -258,7 +258,7 @@ export const DDHGServiceOverview: React.FC<DDHGServiceOverviewProps> = ({
|
|
|
258
258
|
</div>
|
|
259
259
|
<div className="hidden h-10 w-px bg-stone-500 md:block" />
|
|
260
260
|
<div className="text-center">
|
|
261
|
-
<p className="mb-1 text-
|
|
261
|
+
<p className="mb-1 text-xs uppercase tracking-[0.15em] text-stone-600 dark:text-stone-300">
|
|
262
262
|
Engagement
|
|
263
263
|
</p>
|
|
264
264
|
<p className="text-md font-semibold text-stone-700 dark:text-stone-200">
|