@wakastellar/ui 2.3.2 → 2.3.5
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/dist/blocks/dashboard/index.d.ts +4 -1
- package/dist/blocks/empty-states/index.d.ts +4 -1
- package/dist/blocks/error-pages/index.d.ts +4 -1
- package/dist/blocks/index.d.ts +1 -1
- package/dist/blocks/landing/index.d.ts +4 -1
- package/dist/blocks/pricing/index.d.ts +5 -1
- package/dist/blocks/sidebar/index.d.ts +5 -1
- package/dist/index.cjs.js +130 -130
- package/dist/index.d.ts +1 -0
- package/dist/index.es.js +7906 -7857
- package/dist/types/index.d.ts +1 -0
- package/dist/types/link.d.ts +23 -0
- package/package.json +1 -1
- package/src/blocks/dashboard/index.tsx +68 -27
- package/src/blocks/empty-states/index.tsx +26 -8
- package/src/blocks/error-pages/index.tsx +26 -8
- package/src/blocks/index.ts +1 -1
- package/src/blocks/landing/index.tsx +125 -66
- package/src/blocks/pricing/index.tsx +38 -4
- package/src/blocks/sidebar/index.tsx +50 -21
- package/src/styles/base.css +18 -0
- package/src/styles/themes/forest.css +18 -0
- package/src/styles/themes/monochrome.css +18 -0
- package/src/styles/themes/perpetuity.css +18 -0
- package/src/styles/themes/sunset.css +18 -0
- package/src/styles/themes/twilight.css +18 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type { LinkComponentProps } from './link';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Props du composant de lien personnalisé pour navigation SPA
|
|
4
|
+
* Permet d'injecter next/link ou tout autre composant de routing
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```tsx
|
|
8
|
+
* import Link from 'next/link'
|
|
9
|
+
* import type { LinkComponentProps } from '@wakastellar/ui'
|
|
10
|
+
*
|
|
11
|
+
* const NextLink = ({ href, className, onClick, children }: LinkComponentProps) => (
|
|
12
|
+
* <Link href={href} className={className} onClick={onClick}>
|
|
13
|
+
* {children}
|
|
14
|
+
* </Link>
|
|
15
|
+
* )
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export interface LinkComponentProps {
|
|
19
|
+
href: string;
|
|
20
|
+
className?: string;
|
|
21
|
+
onClick?: (e: React.MouseEvent) => void;
|
|
22
|
+
children: React.ReactNode;
|
|
23
|
+
}
|
package/package.json
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import * as React from "react"
|
|
4
4
|
import { cn } from "../../utils"
|
|
5
|
+
import type { LinkComponentProps } from "../../types/link"
|
|
5
6
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../../components/card"
|
|
6
7
|
import { Button } from "../../components/button"
|
|
7
8
|
import { Badge } from "../../components/badge"
|
|
@@ -119,6 +120,22 @@ export interface WakaDashboardProps {
|
|
|
119
120
|
statsColumns?: 2 | 3 | 4
|
|
120
121
|
/** Classes CSS additionnelles */
|
|
121
122
|
className?: string
|
|
123
|
+
/** Composant de lien personnalisé (ex: next/link) pour navigation SPA */
|
|
124
|
+
LinkComponent?: React.ComponentType<LinkComponentProps>
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// ============================================
|
|
128
|
+
// CONTEXT
|
|
129
|
+
// ============================================
|
|
130
|
+
|
|
131
|
+
interface DashboardContextValue {
|
|
132
|
+
LinkComponent?: React.ComponentType<LinkComponentProps>
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const DashboardContext = React.createContext<DashboardContextValue>({})
|
|
136
|
+
|
|
137
|
+
function useDashboardContext() {
|
|
138
|
+
return React.useContext(DashboardContext)
|
|
122
139
|
}
|
|
123
140
|
|
|
124
141
|
// ============================================
|
|
@@ -196,27 +213,37 @@ function DashboardHeader({
|
|
|
196
213
|
)}
|
|
197
214
|
|
|
198
215
|
{/* Actions rapides */}
|
|
199
|
-
{quickActions?.map((action) =>
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
216
|
+
{quickActions?.map((action) => {
|
|
217
|
+
const { LinkComponent } = useDashboardContext()
|
|
218
|
+
return (
|
|
219
|
+
<Button
|
|
220
|
+
key={action.id}
|
|
221
|
+
variant={action.variant || "default"}
|
|
222
|
+
size="sm"
|
|
223
|
+
onClick={action.onClick}
|
|
224
|
+
asChild={!!action.href}
|
|
225
|
+
>
|
|
226
|
+
{action.href ? (
|
|
227
|
+
LinkComponent ? (
|
|
228
|
+
<LinkComponent href={action.href}>
|
|
229
|
+
{action.icon && <span className="mr-2">{action.icon}</span>}
|
|
230
|
+
{action.label}
|
|
231
|
+
</LinkComponent>
|
|
232
|
+
) : (
|
|
233
|
+
<a href={action.href}>
|
|
234
|
+
{action.icon && <span className="mr-2">{action.icon}</span>}
|
|
235
|
+
{action.label}
|
|
236
|
+
</a>
|
|
237
|
+
)
|
|
238
|
+
) : (
|
|
239
|
+
<>
|
|
240
|
+
{action.icon && <span className="mr-2">{action.icon}</span>}
|
|
241
|
+
{action.label}
|
|
242
|
+
</>
|
|
243
|
+
)}
|
|
244
|
+
</Button>
|
|
245
|
+
)
|
|
246
|
+
})}
|
|
220
247
|
</div>
|
|
221
248
|
</div>
|
|
222
249
|
)
|
|
@@ -296,6 +323,8 @@ interface DashboardTableCardProps {
|
|
|
296
323
|
}
|
|
297
324
|
|
|
298
325
|
function DashboardTableCard({ config }: DashboardTableCardProps) {
|
|
326
|
+
const { LinkComponent } = useDashboardContext()
|
|
327
|
+
|
|
299
328
|
return (
|
|
300
329
|
<Card>
|
|
301
330
|
<CardHeader className="flex flex-row items-center justify-between pb-2">
|
|
@@ -316,10 +345,17 @@ function DashboardTableCard({ config }: DashboardTableCardProps) {
|
|
|
316
345
|
asChild={!!action.href}
|
|
317
346
|
>
|
|
318
347
|
{action.href ? (
|
|
319
|
-
|
|
320
|
-
{action.
|
|
321
|
-
|
|
322
|
-
|
|
348
|
+
LinkComponent ? (
|
|
349
|
+
<LinkComponent href={action.href}>
|
|
350
|
+
{action.label}
|
|
351
|
+
<ArrowUpRight className="ml-1 h-3 w-3" />
|
|
352
|
+
</LinkComponent>
|
|
353
|
+
) : (
|
|
354
|
+
<a href={action.href}>
|
|
355
|
+
{action.label}
|
|
356
|
+
<ArrowUpRight className="ml-1 h-3 w-3" />
|
|
357
|
+
</a>
|
|
358
|
+
)
|
|
323
359
|
) : (
|
|
324
360
|
action.label
|
|
325
361
|
)}
|
|
@@ -415,9 +451,13 @@ export function WakaDashboard({
|
|
|
415
451
|
statsLayout = "grid",
|
|
416
452
|
statsColumns = 4,
|
|
417
453
|
className,
|
|
454
|
+
LinkComponent,
|
|
418
455
|
}: WakaDashboardProps) {
|
|
456
|
+
const contextValue = React.useMemo(() => ({ LinkComponent }), [LinkComponent])
|
|
457
|
+
|
|
419
458
|
return (
|
|
420
|
-
<
|
|
459
|
+
<DashboardContext.Provider value={contextValue}>
|
|
460
|
+
<div className={cn("space-y-6", className)}>
|
|
421
461
|
{/* Header */}
|
|
422
462
|
{showHeader && (
|
|
423
463
|
<DashboardHeader
|
|
@@ -469,7 +509,8 @@ export function WakaDashboard({
|
|
|
469
509
|
</div>
|
|
470
510
|
)}
|
|
471
511
|
</div>
|
|
472
|
-
|
|
512
|
+
</div>
|
|
513
|
+
</DashboardContext.Provider>
|
|
473
514
|
)
|
|
474
515
|
}
|
|
475
516
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import * as React from "react"
|
|
4
4
|
import { cn } from "../../utils"
|
|
5
|
+
import type { LinkComponentProps } from "../../types/link"
|
|
5
6
|
import { Button } from "../../components/button"
|
|
6
7
|
import {
|
|
7
8
|
FileQuestion,
|
|
@@ -78,6 +79,8 @@ export interface WakaEmptyStateProps {
|
|
|
78
79
|
children?: React.ReactNode
|
|
79
80
|
/** Classes CSS additionnelles */
|
|
80
81
|
className?: string
|
|
82
|
+
/** Composant de lien personnalisé (ex: next/link) pour navigation SPA */
|
|
83
|
+
LinkComponent?: React.ComponentType<LinkComponentProps>
|
|
81
84
|
}
|
|
82
85
|
|
|
83
86
|
// ============================================
|
|
@@ -238,6 +241,7 @@ export function WakaEmptyState({
|
|
|
238
241
|
centered = true,
|
|
239
242
|
children,
|
|
240
243
|
className,
|
|
244
|
+
LinkComponent,
|
|
241
245
|
}: WakaEmptyStateProps) {
|
|
242
246
|
const config = emptyStateConfigs[type]
|
|
243
247
|
const displayTitle = title ?? config.title
|
|
@@ -325,10 +329,17 @@ export function WakaEmptyState({
|
|
|
325
329
|
asChild={!!action.href}
|
|
326
330
|
>
|
|
327
331
|
{action.href ? (
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
+
LinkComponent ? (
|
|
333
|
+
<LinkComponent href={action.href}>
|
|
334
|
+
{action.icon && <span className="mr-2">{action.icon}</span>}
|
|
335
|
+
{action.label}
|
|
336
|
+
</LinkComponent>
|
|
337
|
+
) : (
|
|
338
|
+
<a href={action.href}>
|
|
339
|
+
{action.icon && <span className="mr-2">{action.icon}</span>}
|
|
340
|
+
{action.label}
|
|
341
|
+
</a>
|
|
342
|
+
)
|
|
332
343
|
) : (
|
|
333
344
|
<>
|
|
334
345
|
{action.icon && <span className="mr-2">{action.icon}</span>}
|
|
@@ -399,10 +410,17 @@ export function WakaEmptyState({
|
|
|
399
410
|
asChild={!!action.href}
|
|
400
411
|
>
|
|
401
412
|
{action.href ? (
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
413
|
+
LinkComponent ? (
|
|
414
|
+
<LinkComponent href={action.href}>
|
|
415
|
+
{action.icon && <span className="mr-2">{action.icon}</span>}
|
|
416
|
+
{action.label}
|
|
417
|
+
</LinkComponent>
|
|
418
|
+
) : (
|
|
419
|
+
<a href={action.href}>
|
|
420
|
+
{action.icon && <span className="mr-2">{action.icon}</span>}
|
|
421
|
+
{action.label}
|
|
422
|
+
</a>
|
|
423
|
+
)
|
|
406
424
|
) : (
|
|
407
425
|
<>
|
|
408
426
|
{action.icon && <span className="mr-2">{action.icon}</span>}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import * as React from "react"
|
|
4
4
|
import { cn } from "../../utils"
|
|
5
|
+
import type { LinkComponentProps } from "../../types/link"
|
|
5
6
|
import { Button } from "../../components/button"
|
|
6
7
|
import {
|
|
7
8
|
Home,
|
|
@@ -65,6 +66,8 @@ export interface WakaErrorPageProps {
|
|
|
65
66
|
size?: "sm" | "md" | "lg"
|
|
66
67
|
/** Classes CSS additionnelles */
|
|
67
68
|
className?: string
|
|
69
|
+
/** Composant de lien personnalisé (ex: next/link) pour navigation SPA */
|
|
70
|
+
LinkComponent?: React.ComponentType<LinkComponentProps>
|
|
68
71
|
}
|
|
69
72
|
|
|
70
73
|
// ============================================
|
|
@@ -186,6 +189,7 @@ export function WakaErrorPage({
|
|
|
186
189
|
layout = "centered",
|
|
187
190
|
size = "md",
|
|
188
191
|
className,
|
|
192
|
+
LinkComponent,
|
|
189
193
|
}: WakaErrorPageProps) {
|
|
190
194
|
const config = errorConfigs[type]
|
|
191
195
|
const displayCode = code ?? config.code
|
|
@@ -297,10 +301,17 @@ export function WakaErrorPage({
|
|
|
297
301
|
asChild={!!action.href}
|
|
298
302
|
>
|
|
299
303
|
{action.href ? (
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
+
LinkComponent ? (
|
|
305
|
+
<LinkComponent href={action.href}>
|
|
306
|
+
{action.icon && <span className="mr-2">{action.icon}</span>}
|
|
307
|
+
{action.label}
|
|
308
|
+
</LinkComponent>
|
|
309
|
+
) : (
|
|
310
|
+
<a href={action.href}>
|
|
311
|
+
{action.icon && <span className="mr-2">{action.icon}</span>}
|
|
312
|
+
{action.label}
|
|
313
|
+
</a>
|
|
314
|
+
)
|
|
304
315
|
) : (
|
|
305
316
|
<>
|
|
306
317
|
{action.icon && <span className="mr-2">{action.icon}</span>}
|
|
@@ -359,10 +370,17 @@ export function WakaErrorPage({
|
|
|
359
370
|
asChild={!!action.href}
|
|
360
371
|
>
|
|
361
372
|
{action.href ? (
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
373
|
+
LinkComponent ? (
|
|
374
|
+
<LinkComponent href={action.href}>
|
|
375
|
+
{action.icon && <span className="mr-2">{action.icon}</span>}
|
|
376
|
+
{action.label}
|
|
377
|
+
</LinkComponent>
|
|
378
|
+
) : (
|
|
379
|
+
<a href={action.href}>
|
|
380
|
+
{action.icon && <span className="mr-2">{action.icon}</span>}
|
|
381
|
+
{action.label}
|
|
382
|
+
</a>
|
|
383
|
+
)
|
|
366
384
|
) : (
|
|
367
385
|
<>
|
|
368
386
|
{action.icon && <span className="mr-2">{action.icon}</span>}
|
package/src/blocks/index.ts
CHANGED
|
@@ -23,7 +23,7 @@ export type { LoginProps, LoginConfig, LoginColorConfig, LoginThemeConfig, Login
|
|
|
23
23
|
|
|
24
24
|
// Sidebar
|
|
25
25
|
export { WakaSidebar, useSidebar, SidebarLayout } from './sidebar'
|
|
26
|
-
export type { WakaSidebarProps, SidebarMenuItem, SidebarUserConfig, SidebarLogoConfig, SidebarLayoutProps } from './sidebar'
|
|
26
|
+
export type { WakaSidebarProps, SidebarMenuItem, SidebarUserConfig, SidebarLogoConfig, SidebarLayoutProps, LinkComponentProps } from './sidebar'
|
|
27
27
|
|
|
28
28
|
// Header
|
|
29
29
|
export { WakaHeader } from './header'
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import * as React from "react"
|
|
4
4
|
import { cn } from "../../utils"
|
|
5
|
+
import type { LinkComponentProps } from "../../types/link"
|
|
5
6
|
import { Button } from "../../components/button"
|
|
6
7
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../../components/card"
|
|
7
8
|
import { Badge } from "../../components/badge"
|
|
@@ -117,6 +118,22 @@ export interface WakaLandingProps {
|
|
|
117
118
|
footer?: React.ReactNode
|
|
118
119
|
/** Classes CSS additionnelles */
|
|
119
120
|
className?: string
|
|
121
|
+
/** Composant de lien personnalisé (ex: next/link) pour navigation SPA */
|
|
122
|
+
LinkComponent?: React.ComponentType<LinkComponentProps>
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// ============================================
|
|
126
|
+
// CONTEXT
|
|
127
|
+
// ============================================
|
|
128
|
+
|
|
129
|
+
interface LandingContextValue {
|
|
130
|
+
LinkComponent?: React.ComponentType<LinkComponentProps>
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const LandingContext = React.createContext<LandingContextValue>({})
|
|
134
|
+
|
|
135
|
+
function useLandingContext() {
|
|
136
|
+
return React.useContext(LandingContext)
|
|
120
137
|
}
|
|
121
138
|
|
|
122
139
|
// ============================================
|
|
@@ -143,29 +160,35 @@ function LandingNavbar({
|
|
|
143
160
|
loginHref,
|
|
144
161
|
}: LandingNavbarProps) {
|
|
145
162
|
const [isOpen, setIsOpen] = React.useState(false)
|
|
163
|
+
const { LinkComponent } = useLandingContext()
|
|
164
|
+
|
|
165
|
+
const renderLink = (href: string, className: string, children: React.ReactNode, onClick?: () => void) => {
|
|
166
|
+
if (LinkComponent) {
|
|
167
|
+
return <LinkComponent href={href} className={className} onClick={onClick}>{children}</LinkComponent>
|
|
168
|
+
}
|
|
169
|
+
return <a href={href} className={className} onClick={onClick}>{children}</a>
|
|
170
|
+
}
|
|
146
171
|
|
|
147
172
|
return (
|
|
148
173
|
<nav className="sticky top-0 z-50 w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
|
|
149
174
|
<div className="container flex h-16 items-center justify-between">
|
|
150
175
|
{/* Logo */}
|
|
151
|
-
|
|
176
|
+
{renderLink("/", "flex items-center gap-2 font-bold text-xl", <>
|
|
152
177
|
{logo}
|
|
153
178
|
<span>{brandName}</span>
|
|
154
|
-
|
|
179
|
+
</>)}
|
|
155
180
|
|
|
156
181
|
{/* Desktop Nav */}
|
|
157
182
|
<div className="hidden md:flex items-center gap-6">
|
|
158
183
|
{navItems.map((item) => (
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
className={cn(
|
|
184
|
+
renderLink(
|
|
185
|
+
item.href,
|
|
186
|
+
cn(
|
|
163
187
|
"text-sm font-medium transition-colors hover:text-primary",
|
|
164
188
|
item.isActive ? "text-primary" : "text-muted-foreground"
|
|
165
|
-
)
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
</a>
|
|
189
|
+
),
|
|
190
|
+
item.label
|
|
191
|
+
)
|
|
169
192
|
))}
|
|
170
193
|
</div>
|
|
171
194
|
|
|
@@ -178,7 +201,11 @@ function LandingNavbar({
|
|
|
178
201
|
asChild={!!loginHref}
|
|
179
202
|
>
|
|
180
203
|
{loginHref ? (
|
|
181
|
-
|
|
204
|
+
LinkComponent ? (
|
|
205
|
+
<LinkComponent href={loginHref}>{loginButtonText}</LinkComponent>
|
|
206
|
+
) : (
|
|
207
|
+
<a href={loginHref}>{loginButtonText}</a>
|
|
208
|
+
)
|
|
182
209
|
) : (
|
|
183
210
|
loginButtonText
|
|
184
211
|
)}
|
|
@@ -202,19 +229,21 @@ function LandingNavbar({
|
|
|
202
229
|
<div className="md:hidden border-t bg-background p-4">
|
|
203
230
|
<div className="flex flex-col gap-4">
|
|
204
231
|
{navItems.map((item) => (
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
{item.label}
|
|
212
|
-
</a>
|
|
232
|
+
renderLink(
|
|
233
|
+
item.href,
|
|
234
|
+
"text-sm font-medium",
|
|
235
|
+
item.label,
|
|
236
|
+
() => setIsOpen(false)
|
|
237
|
+
)
|
|
213
238
|
))}
|
|
214
239
|
{showLoginButton && (
|
|
215
240
|
<Button onClick={onLogin} asChild={!!loginHref}>
|
|
216
241
|
{loginHref ? (
|
|
217
|
-
|
|
242
|
+
LinkComponent ? (
|
|
243
|
+
<LinkComponent href={loginHref}>{loginButtonText}</LinkComponent>
|
|
244
|
+
) : (
|
|
245
|
+
<a href={loginHref}>{loginButtonText}</a>
|
|
246
|
+
)
|
|
218
247
|
) : (
|
|
219
248
|
loginButtonText
|
|
220
249
|
)}
|
|
@@ -243,6 +272,8 @@ function LandingHeroSection({
|
|
|
243
272
|
image,
|
|
244
273
|
stats,
|
|
245
274
|
}: LandingHeroSectionProps) {
|
|
275
|
+
const { LinkComponent } = useLandingContext()
|
|
276
|
+
|
|
246
277
|
return (
|
|
247
278
|
<section className="container py-24 md:py-32">
|
|
248
279
|
<div className="flex flex-col lg:flex-row items-center gap-12">
|
|
@@ -272,10 +303,17 @@ function LandingHeroSection({
|
|
|
272
303
|
asChild={!!primaryButtonHref}
|
|
273
304
|
>
|
|
274
305
|
{primaryButtonHref ? (
|
|
275
|
-
|
|
276
|
-
{
|
|
277
|
-
|
|
278
|
-
|
|
306
|
+
LinkComponent ? (
|
|
307
|
+
<LinkComponent href={primaryButtonHref}>
|
|
308
|
+
{primaryButtonText}
|
|
309
|
+
<ArrowRight className="ml-2 h-4 w-4" />
|
|
310
|
+
</LinkComponent>
|
|
311
|
+
) : (
|
|
312
|
+
<a href={primaryButtonHref}>
|
|
313
|
+
{primaryButtonText}
|
|
314
|
+
<ArrowRight className="ml-2 h-4 w-4" />
|
|
315
|
+
</a>
|
|
316
|
+
)
|
|
279
317
|
) : (
|
|
280
318
|
<>
|
|
281
319
|
{primaryButtonText}
|
|
@@ -292,10 +330,17 @@ function LandingHeroSection({
|
|
|
292
330
|
asChild={!!secondaryButtonHref}
|
|
293
331
|
>
|
|
294
332
|
{secondaryButtonHref ? (
|
|
295
|
-
|
|
296
|
-
<
|
|
297
|
-
|
|
298
|
-
|
|
333
|
+
LinkComponent ? (
|
|
334
|
+
<LinkComponent href={secondaryButtonHref}>
|
|
335
|
+
<Play className="mr-2 h-4 w-4" />
|
|
336
|
+
{secondaryButtonText}
|
|
337
|
+
</LinkComponent>
|
|
338
|
+
) : (
|
|
339
|
+
<a href={secondaryButtonHref}>
|
|
340
|
+
<Play className="mr-2 h-4 w-4" />
|
|
341
|
+
{secondaryButtonText}
|
|
342
|
+
</a>
|
|
343
|
+
)
|
|
299
344
|
) : (
|
|
300
345
|
<>
|
|
301
346
|
<Play className="mr-2 h-4 w-4" />
|
|
@@ -459,6 +504,8 @@ function LandingCTASection({
|
|
|
459
504
|
secondaryButtonAction,
|
|
460
505
|
variant = "default",
|
|
461
506
|
}: LandingCTASectionProps) {
|
|
507
|
+
const { LinkComponent } = useLandingContext()
|
|
508
|
+
|
|
462
509
|
const variantClasses = {
|
|
463
510
|
default: "bg-muted/50",
|
|
464
511
|
gradient: "bg-gradient-to-r from-primary/10 via-primary/5 to-background",
|
|
@@ -495,10 +542,17 @@ function LandingCTASection({
|
|
|
495
542
|
asChild={!!buttonHref}
|
|
496
543
|
>
|
|
497
544
|
{buttonHref ? (
|
|
498
|
-
|
|
499
|
-
{
|
|
500
|
-
|
|
501
|
-
|
|
545
|
+
LinkComponent ? (
|
|
546
|
+
<LinkComponent href={buttonHref}>
|
|
547
|
+
{buttonText}
|
|
548
|
+
<ChevronRight className="ml-2 h-4 w-4" />
|
|
549
|
+
</LinkComponent>
|
|
550
|
+
) : (
|
|
551
|
+
<a href={buttonHref}>
|
|
552
|
+
{buttonText}
|
|
553
|
+
<ChevronRight className="ml-2 h-4 w-4" />
|
|
554
|
+
</a>
|
|
555
|
+
)
|
|
502
556
|
) : (
|
|
503
557
|
<>
|
|
504
558
|
{buttonText}
|
|
@@ -544,46 +598,51 @@ export function WakaLanding({
|
|
|
544
598
|
cta,
|
|
545
599
|
footer,
|
|
546
600
|
className,
|
|
601
|
+
LinkComponent,
|
|
547
602
|
}: WakaLandingProps) {
|
|
603
|
+
const contextValue = React.useMemo(() => ({ LinkComponent }), [LinkComponent])
|
|
604
|
+
|
|
548
605
|
return (
|
|
549
|
-
<
|
|
550
|
-
{
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
{/* Hero */}
|
|
562
|
-
{hero && <LandingHeroSection {...hero} />}
|
|
563
|
-
|
|
564
|
-
{/* Features */}
|
|
565
|
-
{features && features.length > 0 && (
|
|
566
|
-
<LandingFeaturesSection
|
|
567
|
-
title={featuresTitle}
|
|
568
|
-
description={featuresDescription}
|
|
569
|
-
features={features}
|
|
606
|
+
<LandingContext.Provider value={contextValue}>
|
|
607
|
+
<div className={cn("min-h-screen", className)}>
|
|
608
|
+
{/* Navbar */}
|
|
609
|
+
<LandingNavbar
|
|
610
|
+
logo={logo}
|
|
611
|
+
brandName={brandName}
|
|
612
|
+
navItems={navItems}
|
|
613
|
+
showLoginButton={showLoginButton}
|
|
614
|
+
loginButtonText={loginButtonText}
|
|
615
|
+
onLogin={onLogin}
|
|
616
|
+
loginHref={loginHref}
|
|
570
617
|
/>
|
|
571
|
-
)}
|
|
572
618
|
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
<LandingTestimonialsSection
|
|
576
|
-
title={testimonialsTitle}
|
|
577
|
-
testimonials={testimonials}
|
|
578
|
-
/>
|
|
579
|
-
)}
|
|
619
|
+
{/* Hero */}
|
|
620
|
+
{hero && <LandingHeroSection {...hero} />}
|
|
580
621
|
|
|
581
|
-
|
|
582
|
-
|
|
622
|
+
{/* Features */}
|
|
623
|
+
{features && features.length > 0 && (
|
|
624
|
+
<LandingFeaturesSection
|
|
625
|
+
title={featuresTitle}
|
|
626
|
+
description={featuresDescription}
|
|
627
|
+
features={features}
|
|
628
|
+
/>
|
|
629
|
+
)}
|
|
583
630
|
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
631
|
+
{/* Testimonials */}
|
|
632
|
+
{testimonials && testimonials.length > 0 && (
|
|
633
|
+
<LandingTestimonialsSection
|
|
634
|
+
title={testimonialsTitle}
|
|
635
|
+
testimonials={testimonials}
|
|
636
|
+
/>
|
|
637
|
+
)}
|
|
638
|
+
|
|
639
|
+
{/* CTA */}
|
|
640
|
+
{cta && <LandingCTASection {...cta} />}
|
|
641
|
+
|
|
642
|
+
{/* Footer */}
|
|
643
|
+
{footer}
|
|
644
|
+
</div>
|
|
645
|
+
</LandingContext.Provider>
|
|
587
646
|
)
|
|
588
647
|
}
|
|
589
648
|
|