@wakastellar/ui 2.1.2 → 2.3.2
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/apm-overview/index.d.ts +58 -0
- package/dist/blocks/cicd-builder/index.d.ts +47 -0
- package/dist/blocks/cloud-cost-dashboard/index.d.ts +49 -0
- package/dist/blocks/container-orchestrator/index.d.ts +63 -0
- package/dist/blocks/database-admin/index.d.ts +84 -0
- package/dist/blocks/gitops-sync-status/index.d.ts +45 -0
- package/dist/blocks/incident-manager/index.d.ts +44 -0
- package/dist/blocks/index.d.ts +10 -0
- package/dist/blocks/infrastructure-map/index.d.ts +32 -0
- package/dist/blocks/on-call-schedule/index.d.ts +43 -0
- package/dist/blocks/release-notes/index.d.ts +49 -0
- package/dist/components/index.d.ts +34 -0
- package/dist/components/waka-ad-banner/index.d.ts +36 -0
- package/dist/components/waka-ad-fallback/index.d.ts +33 -0
- package/dist/components/waka-ad-inline/index.d.ts +15 -0
- package/dist/components/waka-ad-interstitial/index.d.ts +26 -0
- package/dist/components/waka-ad-placeholder/index.d.ts +17 -0
- package/dist/components/waka-ad-provider/index.d.ts +103 -0
- package/dist/components/waka-ad-sidebar/index.d.ts +18 -0
- package/dist/components/waka-ad-sticky-footer/index.d.ts +17 -0
- package/dist/components/waka-alert-panel/index.d.ts +45 -0
- package/dist/components/waka-artifact-list/index.d.ts +32 -0
- package/dist/components/waka-build-matrix/index.d.ts +36 -0
- package/dist/components/waka-config-comparator/index.d.ts +37 -0
- package/dist/components/waka-container-list/index.d.ts +51 -0
- package/dist/components/waka-content-recommendation/index.d.ts +23 -0
- package/dist/components/waka-database-card/index.d.ts +46 -0
- package/dist/components/waka-dependency-tree/index.d.ts +38 -0
- package/dist/components/waka-env-var-editor/index.d.ts +30 -0
- package/dist/components/waka-feature-flag-row/index.d.ts +45 -0
- package/dist/components/waka-kubernetes-overview/index.d.ts +98 -0
- package/dist/components/waka-log-viewer/index.d.ts +38 -0
- package/dist/components/waka-migration-list/index.d.ts +36 -0
- package/dist/components/waka-outstream-video/index.d.ts +24 -0
- package/dist/components/waka-pod-card/index.d.ts +73 -0
- package/dist/components/waka-query-explain/index.d.ts +48 -0
- package/dist/components/waka-secret-card/index.d.ts +43 -0
- package/dist/components/waka-security-scan-result/index.d.ts +45 -0
- package/dist/components/waka-service-graph/index.d.ts +44 -0
- package/dist/components/waka-sponsored-badge/index.d.ts +20 -0
- package/dist/components/waka-sponsored-card/index.d.ts +25 -0
- package/dist/components/waka-sponsored-feed/index.d.ts +31 -0
- package/dist/components/waka-test-report/index.d.ts +60 -0
- package/dist/components/waka-trace-viewer/index.d.ts +36 -0
- package/dist/components/waka-video-ad/index.d.ts +32 -0
- package/dist/components/waka-video-overlay/index.d.ts +26 -0
- package/dist/index.cjs.js +251 -200
- package/dist/index.d.ts +1 -0
- package/dist/index.es.js +47315 -35823
- package/dist/utils/security.d.ts +96 -0
- package/package.json +4 -4
- package/src/blocks/apm-overview/index.tsx +672 -0
- package/src/blocks/cicd-builder/index.tsx +738 -0
- package/src/blocks/cloud-cost-dashboard/index.tsx +597 -0
- package/src/blocks/container-orchestrator/index.tsx +729 -0
- package/src/blocks/database-admin/index.tsx +679 -0
- package/src/blocks/gitops-sync-status/index.tsx +557 -0
- package/src/blocks/incident-manager/index.tsx +586 -0
- package/src/blocks/index.ts +119 -0
- package/src/blocks/infrastructure-map/index.tsx +638 -0
- package/src/blocks/on-call-schedule/index.tsx +615 -0
- package/src/blocks/release-notes/index.tsx +643 -0
- package/src/blocks/sidebar/index.tsx +6 -6
- package/src/components/DataTable/templates/index.tsx +3 -2
- package/src/components/index.ts +283 -0
- package/src/components/waka-3d-pie-chart/index.tsx +11 -11
- package/src/components/waka-achievement-unlock/index.tsx +16 -16
- package/src/components/waka-ad-banner/index.tsx +275 -0
- package/src/components/waka-ad-fallback/index.tsx +181 -0
- package/src/components/waka-ad-inline/index.tsx +103 -0
- package/src/components/waka-ad-interstitial/index.tsx +278 -0
- package/src/components/waka-ad-placeholder/index.tsx +84 -0
- package/src/components/waka-ad-provider/index.tsx +329 -0
- package/src/components/waka-ad-sidebar/index.tsx +113 -0
- package/src/components/waka-ad-sticky-footer/index.tsx +125 -0
- package/src/components/waka-alert-panel/index.tsx +493 -0
- package/src/components/waka-artifact-list/index.tsx +416 -0
- package/src/components/waka-badge-showcase/index.tsx +12 -11
- package/src/components/waka-build-matrix/index.tsx +396 -0
- package/src/components/waka-command-bar/index.tsx +2 -1
- package/src/components/waka-config-comparator/index.tsx +416 -0
- package/src/components/waka-container-list/index.tsx +475 -0
- package/src/components/waka-content-recommendation/index.tsx +294 -0
- package/src/components/waka-cost-breakdown/index.tsx +10 -10
- package/src/components/waka-database-card/index.tsx +473 -0
- package/src/components/waka-dependency-tree/index.tsx +542 -0
- package/src/components/waka-env-var-editor/index.tsx +417 -0
- package/src/components/waka-feature-flag-row/index.tsx +386 -0
- package/src/components/waka-funnel-chart/index.tsx +8 -8
- package/src/components/waka-health-pulse/index.tsx +6 -6
- package/src/components/waka-kubernetes-overview/index.tsx +536 -0
- package/src/components/waka-leaderboard/index.tsx +9 -9
- package/src/components/waka-log-viewer/index.tsx +386 -0
- package/src/components/waka-loot-box/index.tsx +20 -20
- package/src/components/waka-migration-list/index.tsx +487 -0
- package/src/components/waka-outstream-video/index.tsx +240 -0
- package/src/components/waka-player-card/index.tsx +5 -5
- package/src/components/waka-pod-card/index.tsx +528 -0
- package/src/components/waka-query-explain/index.tsx +657 -0
- package/src/components/waka-quota-bar/index.tsx +4 -4
- package/src/components/waka-radar-score/index.tsx +10 -10
- package/src/components/waka-scratch-card/index.tsx +5 -4
- package/src/components/waka-secret-card/index.tsx +371 -0
- package/src/components/waka-security-scan-result/index.tsx +473 -0
- package/src/components/waka-server-rack/index.tsx +28 -27
- package/src/components/waka-service-graph/index.tsx +445 -0
- package/src/components/waka-sponsored-badge/index.tsx +97 -0
- package/src/components/waka-sponsored-card/index.tsx +275 -0
- package/src/components/waka-sponsored-feed/index.tsx +127 -0
- package/src/components/waka-spotlight/index.tsx +2 -1
- package/src/components/waka-success-explosion/index.tsx +4 -4
- package/src/components/waka-test-report/index.tsx +469 -0
- package/src/components/waka-trace-viewer/index.tsx +490 -0
- package/src/components/waka-video-ad/index.tsx +406 -0
- package/src/components/waka-video-overlay/index.tsx +257 -0
- package/src/components/waka-xp-bar/index.tsx +13 -13
- package/src/styles/base.css +16 -0
- package/src/styles/tailwind.preset.js +12 -0
- package/src/styles/themes/forest.css +16 -0
- package/src/styles/themes/monochrome.css +16 -0
- package/src/styles/themes/perpetuity.css +16 -0
- package/src/styles/themes/sunset.css +16 -0
- package/src/styles/themes/twilight.css +16 -0
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import { useRef, useEffect, useState } from "react"
|
|
5
|
+
import { cn } from "../../utils/cn"
|
|
6
|
+
import { useAdContext, useAdVisibility, type CustomAd } from "../waka-ad-provider"
|
|
7
|
+
import { WakaSponsoredBadge } from "../waka-sponsored-badge"
|
|
8
|
+
import { ExternalLink, ChevronLeft, ChevronRight } from "lucide-react"
|
|
9
|
+
|
|
10
|
+
export type RecommendationLayout = "grid" | "carousel" | "list"
|
|
11
|
+
|
|
12
|
+
export interface WakaContentRecommendationProps {
|
|
13
|
+
/** Widget title */
|
|
14
|
+
title?: string
|
|
15
|
+
/** Slot IDs for recommendations */
|
|
16
|
+
slotIds: string[]
|
|
17
|
+
/** Layout style */
|
|
18
|
+
layout?: RecommendationLayout
|
|
19
|
+
/** Number of columns for grid layout */
|
|
20
|
+
columns?: 2 | 3 | 4
|
|
21
|
+
/** Show navigation arrows for carousel */
|
|
22
|
+
showArrows?: boolean
|
|
23
|
+
/** Auto-scroll carousel */
|
|
24
|
+
autoScroll?: boolean
|
|
25
|
+
/** Auto-scroll interval (seconds) */
|
|
26
|
+
autoScrollInterval?: number
|
|
27
|
+
/** Custom class name */
|
|
28
|
+
className?: string
|
|
29
|
+
/** Callback when item is clicked */
|
|
30
|
+
onItemClick?: (slotId: string) => void
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function WakaContentRecommendation({
|
|
34
|
+
title = "You May Also Like",
|
|
35
|
+
slotIds,
|
|
36
|
+
layout = "grid",
|
|
37
|
+
columns = 3,
|
|
38
|
+
showArrows = true,
|
|
39
|
+
autoScroll = false,
|
|
40
|
+
autoScrollInterval = 5,
|
|
41
|
+
className,
|
|
42
|
+
onItemClick,
|
|
43
|
+
}: WakaContentRecommendationProps) {
|
|
44
|
+
const containerRef = useRef<HTMLDivElement>(null)
|
|
45
|
+
const carouselRef = useRef<HTMLDivElement>(null)
|
|
46
|
+
const { config, isReady, hasConsent, getCustomAd, trackEvent } = useAdContext()
|
|
47
|
+
const { isVisible } = useAdVisibility(containerRef)
|
|
48
|
+
|
|
49
|
+
const [ads, setAds] = useState<Map<string, CustomAd>>(new Map())
|
|
50
|
+
const [isLoading, setIsLoading] = useState(true)
|
|
51
|
+
const [currentSlide, setCurrentSlide] = useState(0)
|
|
52
|
+
|
|
53
|
+
// Load all ads
|
|
54
|
+
useEffect(() => {
|
|
55
|
+
if (!isReady || !isVisible || hasConsent === false) return
|
|
56
|
+
|
|
57
|
+
const loadAds = async () => {
|
|
58
|
+
setIsLoading(true)
|
|
59
|
+
const loadedAds = new Map<string, CustomAd>()
|
|
60
|
+
|
|
61
|
+
await Promise.all(
|
|
62
|
+
slotIds.map(async (slotId) => {
|
|
63
|
+
try {
|
|
64
|
+
const ad = await getCustomAd(slotId)
|
|
65
|
+
if (ad) {
|
|
66
|
+
loadedAds.set(slotId, ad)
|
|
67
|
+
trackEvent({ type: "loaded", slotId, timestamp: new Date() })
|
|
68
|
+
|
|
69
|
+
// Fire impression tracking
|
|
70
|
+
if (ad.impressionUrl) {
|
|
71
|
+
fetch(ad.impressionUrl, { mode: "no-cors" }).catch(() => {})
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
} catch {
|
|
75
|
+
// Ignore errors for individual slots
|
|
76
|
+
}
|
|
77
|
+
})
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
setAds(loadedAds)
|
|
81
|
+
setIsLoading(false)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
loadAds()
|
|
85
|
+
}, [isReady, isVisible, hasConsent, slotIds, getCustomAd, trackEvent])
|
|
86
|
+
|
|
87
|
+
// Track viewability for loaded ads
|
|
88
|
+
useEffect(() => {
|
|
89
|
+
if (isVisible && ads.size > 0) {
|
|
90
|
+
ads.forEach((_, slotId) => {
|
|
91
|
+
trackEvent({ type: "viewable", slotId, timestamp: new Date() })
|
|
92
|
+
})
|
|
93
|
+
}
|
|
94
|
+
}, [isVisible, ads, trackEvent])
|
|
95
|
+
|
|
96
|
+
// Auto-scroll for carousel
|
|
97
|
+
useEffect(() => {
|
|
98
|
+
if (layout !== "carousel" || !autoScroll || ads.size === 0) return
|
|
99
|
+
|
|
100
|
+
const interval = setInterval(() => {
|
|
101
|
+
setCurrentSlide((prev) => (prev + 1) % ads.size)
|
|
102
|
+
}, autoScrollInterval * 1000)
|
|
103
|
+
|
|
104
|
+
return () => clearInterval(interval)
|
|
105
|
+
}, [layout, autoScroll, autoScrollInterval, ads.size])
|
|
106
|
+
|
|
107
|
+
// Scroll carousel to current slide
|
|
108
|
+
useEffect(() => {
|
|
109
|
+
if (layout !== "carousel" || !carouselRef.current) return
|
|
110
|
+
|
|
111
|
+
const slideWidth = carouselRef.current.offsetWidth / Math.min(columns, ads.size)
|
|
112
|
+
carouselRef.current.scrollTo({
|
|
113
|
+
left: currentSlide * slideWidth,
|
|
114
|
+
behavior: "smooth",
|
|
115
|
+
})
|
|
116
|
+
}, [currentSlide, layout, columns, ads.size])
|
|
117
|
+
|
|
118
|
+
const handleItemClick = (slotId: string, ad: CustomAd) => {
|
|
119
|
+
trackEvent({ type: "click", slotId, timestamp: new Date() })
|
|
120
|
+
onItemClick?.(slotId)
|
|
121
|
+
|
|
122
|
+
if (ad.clickUrl) {
|
|
123
|
+
fetch(ad.clickUrl, { mode: "no-cors" }).catch(() => {})
|
|
124
|
+
}
|
|
125
|
+
if (ad.targetUrl) {
|
|
126
|
+
window.open(ad.targetUrl, "_blank", "noopener,noreferrer")
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const handlePrev = () => {
|
|
131
|
+
setCurrentSlide((prev) => (prev - 1 + ads.size) % ads.size)
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const handleNext = () => {
|
|
135
|
+
setCurrentSlide((prev) => (prev + 1) % ads.size)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (ads.size === 0 && !isLoading) {
|
|
139
|
+
return null
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const columnClasses = {
|
|
143
|
+
2: "grid-cols-1 sm:grid-cols-2",
|
|
144
|
+
3: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3",
|
|
145
|
+
4: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4",
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const renderItem = (slotId: string, ad: CustomAd) => (
|
|
149
|
+
<button
|
|
150
|
+
key={slotId}
|
|
151
|
+
onClick={() => handleItemClick(slotId, ad)}
|
|
152
|
+
className="group flex-shrink-0 w-full text-left rounded-lg overflow-hidden bg-card border hover:shadow-md transition-shadow"
|
|
153
|
+
>
|
|
154
|
+
{ad.imageUrl && (
|
|
155
|
+
<div className="relative aspect-video bg-muted overflow-hidden">
|
|
156
|
+
<img
|
|
157
|
+
src={ad.imageUrl}
|
|
158
|
+
alt=""
|
|
159
|
+
className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300"
|
|
160
|
+
/>
|
|
161
|
+
</div>
|
|
162
|
+
)}
|
|
163
|
+
|
|
164
|
+
<div className="p-3">
|
|
165
|
+
<h4 className="font-medium text-sm line-clamp-2 mb-1 group-hover:text-primary transition-colors">
|
|
166
|
+
{ad.title}
|
|
167
|
+
</h4>
|
|
168
|
+
|
|
169
|
+
<div className="flex items-center justify-between">
|
|
170
|
+
<span className="text-xs text-muted-foreground">
|
|
171
|
+
{ad.sponsor || "Sponsored"}
|
|
172
|
+
</span>
|
|
173
|
+
<ExternalLink className="h-3 w-3 text-muted-foreground" />
|
|
174
|
+
</div>
|
|
175
|
+
</div>
|
|
176
|
+
</button>
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
return (
|
|
180
|
+
<div
|
|
181
|
+
ref={containerRef}
|
|
182
|
+
className={cn("relative", className)}
|
|
183
|
+
>
|
|
184
|
+
{/* Header */}
|
|
185
|
+
<div className="flex items-center justify-between mb-4">
|
|
186
|
+
<div className="flex items-center gap-3">
|
|
187
|
+
<h3 className="font-semibold text-lg">{title}</h3>
|
|
188
|
+
<WakaSponsoredBadge size="sm" showIcon={false} />
|
|
189
|
+
</div>
|
|
190
|
+
|
|
191
|
+
{layout === "carousel" && showArrows && ads.size > columns && (
|
|
192
|
+
<div className="flex items-center gap-2">
|
|
193
|
+
<button
|
|
194
|
+
onClick={handlePrev}
|
|
195
|
+
className="p-1.5 rounded-full bg-muted hover:bg-muted-foreground/20 transition-colors"
|
|
196
|
+
aria-label="Previous"
|
|
197
|
+
>
|
|
198
|
+
<ChevronLeft className="h-4 w-4" />
|
|
199
|
+
</button>
|
|
200
|
+
<button
|
|
201
|
+
onClick={handleNext}
|
|
202
|
+
className="p-1.5 rounded-full bg-muted hover:bg-muted-foreground/20 transition-colors"
|
|
203
|
+
aria-label="Next"
|
|
204
|
+
>
|
|
205
|
+
<ChevronRight className="h-4 w-4" />
|
|
206
|
+
</button>
|
|
207
|
+
</div>
|
|
208
|
+
)}
|
|
209
|
+
</div>
|
|
210
|
+
|
|
211
|
+
{/* Content */}
|
|
212
|
+
{isLoading ? (
|
|
213
|
+
<div className={cn("grid gap-4", columnClasses[columns])}>
|
|
214
|
+
{slotIds.slice(0, columns).map((_, i) => (
|
|
215
|
+
<div
|
|
216
|
+
key={i}
|
|
217
|
+
className="rounded-lg border bg-muted animate-pulse aspect-[4/3]"
|
|
218
|
+
/>
|
|
219
|
+
))}
|
|
220
|
+
</div>
|
|
221
|
+
) : layout === "grid" ? (
|
|
222
|
+
<div className={cn("grid gap-4", columnClasses[columns])}>
|
|
223
|
+
{Array.from(ads.entries()).map(([slotId, ad]) => renderItem(slotId, ad))}
|
|
224
|
+
</div>
|
|
225
|
+
) : layout === "carousel" ? (
|
|
226
|
+
<div
|
|
227
|
+
ref={carouselRef}
|
|
228
|
+
className="flex gap-4 overflow-x-auto scrollbar-hide snap-x snap-mandatory"
|
|
229
|
+
style={{ scrollbarWidth: "none", msOverflowStyle: "none" }}
|
|
230
|
+
>
|
|
231
|
+
{Array.from(ads.entries()).map(([slotId, ad]) => (
|
|
232
|
+
<div
|
|
233
|
+
key={slotId}
|
|
234
|
+
className="snap-start"
|
|
235
|
+
style={{ minWidth: `calc((100% - ${(columns - 1) * 16}px) / ${columns})` }}
|
|
236
|
+
>
|
|
237
|
+
{renderItem(slotId, ad)}
|
|
238
|
+
</div>
|
|
239
|
+
))}
|
|
240
|
+
</div>
|
|
241
|
+
) : (
|
|
242
|
+
<div className="space-y-3">
|
|
243
|
+
{Array.from(ads.entries()).map(([slotId, ad]) => (
|
|
244
|
+
<button
|
|
245
|
+
key={slotId}
|
|
246
|
+
onClick={() => handleItemClick(slotId, ad)}
|
|
247
|
+
className="group w-full flex gap-3 p-2 rounded-lg border hover:bg-accent/50 transition-colors text-left"
|
|
248
|
+
>
|
|
249
|
+
{ad.imageUrl && (
|
|
250
|
+
<div className="w-20 h-20 flex-shrink-0 rounded-md overflow-hidden bg-muted">
|
|
251
|
+
<img
|
|
252
|
+
src={ad.imageUrl}
|
|
253
|
+
alt=""
|
|
254
|
+
className="w-full h-full object-cover"
|
|
255
|
+
/>
|
|
256
|
+
</div>
|
|
257
|
+
)}
|
|
258
|
+
|
|
259
|
+
<div className="flex-1 min-w-0">
|
|
260
|
+
<h4 className="font-medium text-sm line-clamp-2 mb-1 group-hover:text-primary transition-colors">
|
|
261
|
+
{ad.title}
|
|
262
|
+
</h4>
|
|
263
|
+
<span className="text-xs text-muted-foreground">
|
|
264
|
+
{ad.sponsor || "Sponsored"}
|
|
265
|
+
</span>
|
|
266
|
+
</div>
|
|
267
|
+
</button>
|
|
268
|
+
))}
|
|
269
|
+
</div>
|
|
270
|
+
)}
|
|
271
|
+
|
|
272
|
+
{/* Pagination dots for carousel */}
|
|
273
|
+
{layout === "carousel" && ads.size > columns && (
|
|
274
|
+
<div className="flex justify-center gap-1.5 mt-4">
|
|
275
|
+
{Array.from({ length: Math.ceil(ads.size / columns) }).map((_, i) => (
|
|
276
|
+
<button
|
|
277
|
+
key={i}
|
|
278
|
+
onClick={() => setCurrentSlide(i * columns)}
|
|
279
|
+
className={cn(
|
|
280
|
+
"w-2 h-2 rounded-full transition-colors",
|
|
281
|
+
Math.floor(currentSlide / columns) === i
|
|
282
|
+
? "bg-primary"
|
|
283
|
+
: "bg-muted-foreground/30"
|
|
284
|
+
)}
|
|
285
|
+
aria-label={`Go to slide ${i + 1}`}
|
|
286
|
+
/>
|
|
287
|
+
))}
|
|
288
|
+
</div>
|
|
289
|
+
)}
|
|
290
|
+
</div>
|
|
291
|
+
)
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
export default WakaContentRecommendation
|
|
@@ -48,16 +48,16 @@ export interface WakaCostBreakdownProps {
|
|
|
48
48
|
// ============================================================================
|
|
49
49
|
|
|
50
50
|
const defaultColors = [
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
51
|
+
"hsl(var(--chart-1))",
|
|
52
|
+
"hsl(var(--chart-2))",
|
|
53
|
+
"hsl(var(--chart-3))",
|
|
54
|
+
"hsl(var(--chart-4))",
|
|
55
|
+
"hsl(var(--chart-5))",
|
|
56
|
+
"hsl(var(--primary))",
|
|
57
|
+
"hsl(var(--info))",
|
|
58
|
+
"hsl(var(--warning))",
|
|
59
|
+
"hsl(var(--success))",
|
|
60
|
+
"hsl(var(--destructive))",
|
|
61
61
|
]
|
|
62
62
|
|
|
63
63
|
// ============================================================================
|