@opensite/ui 0.7.7 → 0.7.8
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/carousel-gallery-thumbnails.cjs +17 -2
- package/dist/carousel-gallery-thumbnails.d.cts +5 -1
- package/dist/carousel-gallery-thumbnails.d.ts +5 -1
- package/dist/carousel-gallery-thumbnails.js +17 -2
- package/dist/carousel-horizontal-cards.cjs +7 -7
- package/dist/carousel-horizontal-cards.js +7 -7
- package/dist/carousel-image-hero.cjs +4 -4
- package/dist/carousel-image-hero.js +4 -4
- package/dist/carousel-multi-step-showcase.cjs +30 -26
- package/dist/carousel-multi-step-showcase.js +30 -26
- package/dist/carousel-portfolio-hero.cjs +29 -17
- package/dist/carousel-portfolio-hero.d.cts +5 -1
- package/dist/carousel-portfolio-hero.d.ts +5 -1
- package/dist/carousel-portfolio-hero.js +29 -17
- package/dist/carousel-product-feature-showcase.cjs +7 -7
- package/dist/carousel-product-feature-showcase.js +7 -7
- package/dist/carousel-progress-slider.cjs +591 -40
- package/dist/carousel-progress-slider.js +591 -40
- package/dist/carousel-scrolling-feature-showcase.cjs +45 -38
- package/dist/carousel-scrolling-feature-showcase.js +46 -39
- package/dist/registry.cjs +171 -126
- package/dist/registry.js +172 -127
- package/package.json +1 -1
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var
|
|
4
|
+
var React6 = require('react');
|
|
5
5
|
var framerMotion = require('framer-motion');
|
|
6
6
|
var clsx = require('clsx');
|
|
7
7
|
var tailwindMerge = require('tailwind-merge');
|
|
8
|
-
var
|
|
8
|
+
var classVarianceAuthority = require('class-variance-authority');
|
|
9
9
|
var jsxRuntime = require('react/jsx-runtime');
|
|
10
|
+
var img = require('@page-speed/img');
|
|
10
11
|
|
|
11
12
|
function _interopNamespace(e) {
|
|
12
13
|
if (e && e.__esModule) return e;
|
|
@@ -26,12 +27,535 @@ function _interopNamespace(e) {
|
|
|
26
27
|
return Object.freeze(n);
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
var
|
|
30
|
+
var React6__namespace = /*#__PURE__*/_interopNamespace(React6);
|
|
30
31
|
|
|
31
32
|
// components/blocks/carousel/carousel-progress-slider.tsx
|
|
32
33
|
function cn(...inputs) {
|
|
33
34
|
return tailwindMerge.twMerge(clsx.clsx(inputs));
|
|
34
35
|
}
|
|
36
|
+
function normalizePhoneNumber(input) {
|
|
37
|
+
const trimmed = input.trim();
|
|
38
|
+
if (trimmed.toLowerCase().startsWith("tel:")) {
|
|
39
|
+
return trimmed;
|
|
40
|
+
}
|
|
41
|
+
const match = trimmed.match(/^[\s\+\-\(\)]*(\d[\d\s\-\(\)\.]*\d)[\s\-]*(x|ext\.?|extension)?[\s\-]*(\d+)?$/i);
|
|
42
|
+
if (match) {
|
|
43
|
+
const mainNumber = match[1].replace(/[\s\-\(\)\.]/g, "");
|
|
44
|
+
const extension = match[3];
|
|
45
|
+
const normalized = mainNumber.length >= 10 && !trimmed.startsWith("+") ? `+${mainNumber}` : mainNumber;
|
|
46
|
+
const withExtension = extension ? `${normalized};ext=${extension}` : normalized;
|
|
47
|
+
return `tel:${withExtension}`;
|
|
48
|
+
}
|
|
49
|
+
const cleaned = trimmed.replace(/[\s\-\(\)\.]/g, "");
|
|
50
|
+
return `tel:${cleaned}`;
|
|
51
|
+
}
|
|
52
|
+
function normalizeEmail(input) {
|
|
53
|
+
const trimmed = input.trim();
|
|
54
|
+
if (trimmed.toLowerCase().startsWith("mailto:")) {
|
|
55
|
+
return trimmed;
|
|
56
|
+
}
|
|
57
|
+
return `mailto:${trimmed}`;
|
|
58
|
+
}
|
|
59
|
+
function isEmail(input) {
|
|
60
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
61
|
+
return emailRegex.test(input.trim());
|
|
62
|
+
}
|
|
63
|
+
function isPhoneNumber(input) {
|
|
64
|
+
const trimmed = input.trim();
|
|
65
|
+
if (trimmed.toLowerCase().startsWith("tel:")) {
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
const phoneRegex = /^[\s\+\-\(\)]*\d[\d\s\-\(\)\.]*\d[\s\-]*(x|ext\.?|extension)?[\s\-]*\d*$/i;
|
|
69
|
+
return phoneRegex.test(trimmed);
|
|
70
|
+
}
|
|
71
|
+
function isInternalUrl(href) {
|
|
72
|
+
if (typeof window === "undefined") {
|
|
73
|
+
return href.startsWith("/") && !href.startsWith("//");
|
|
74
|
+
}
|
|
75
|
+
const trimmed = href.trim();
|
|
76
|
+
if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
const url = new URL(trimmed, window.location.href);
|
|
81
|
+
const currentOrigin = window.location.origin;
|
|
82
|
+
const normalizeOrigin = (origin) => origin.replace(/^(https?:\/\/)(www\.)?/, "$1");
|
|
83
|
+
return normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin);
|
|
84
|
+
} catch {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function toRelativePath(href) {
|
|
89
|
+
if (typeof window === "undefined") {
|
|
90
|
+
return href;
|
|
91
|
+
}
|
|
92
|
+
const trimmed = href.trim();
|
|
93
|
+
if (trimmed.startsWith("/") && !trimmed.startsWith("//")) {
|
|
94
|
+
return trimmed;
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
const url = new URL(trimmed, window.location.href);
|
|
98
|
+
const currentOrigin = window.location.origin;
|
|
99
|
+
const normalizeOrigin = (origin) => origin.replace(/^(https?:\/\/)(www\.)?/, "$1");
|
|
100
|
+
if (normalizeOrigin(url.origin) === normalizeOrigin(currentOrigin)) {
|
|
101
|
+
return url.pathname + url.search + url.hash;
|
|
102
|
+
}
|
|
103
|
+
} catch {
|
|
104
|
+
}
|
|
105
|
+
return trimmed;
|
|
106
|
+
}
|
|
107
|
+
function useNavigation({
|
|
108
|
+
href,
|
|
109
|
+
onClick
|
|
110
|
+
} = {}) {
|
|
111
|
+
const linkType = React6__namespace.useMemo(() => {
|
|
112
|
+
if (!href || href.trim() === "") {
|
|
113
|
+
return onClick ? "none" : "none";
|
|
114
|
+
}
|
|
115
|
+
const trimmed = href.trim();
|
|
116
|
+
if (trimmed.toLowerCase().startsWith("mailto:") || isEmail(trimmed)) {
|
|
117
|
+
return "mailto";
|
|
118
|
+
}
|
|
119
|
+
if (trimmed.toLowerCase().startsWith("tel:") || isPhoneNumber(trimmed)) {
|
|
120
|
+
return "tel";
|
|
121
|
+
}
|
|
122
|
+
if (isInternalUrl(trimmed)) {
|
|
123
|
+
return "internal";
|
|
124
|
+
}
|
|
125
|
+
try {
|
|
126
|
+
new URL(trimmed, typeof window !== "undefined" ? window.location.href : "http://localhost");
|
|
127
|
+
return "external";
|
|
128
|
+
} catch {
|
|
129
|
+
return "internal";
|
|
130
|
+
}
|
|
131
|
+
}, [href, onClick]);
|
|
132
|
+
const normalizedHref = React6__namespace.useMemo(() => {
|
|
133
|
+
if (!href || href.trim() === "") {
|
|
134
|
+
return void 0;
|
|
135
|
+
}
|
|
136
|
+
const trimmed = href.trim();
|
|
137
|
+
switch (linkType) {
|
|
138
|
+
case "tel":
|
|
139
|
+
return normalizePhoneNumber(trimmed);
|
|
140
|
+
case "mailto":
|
|
141
|
+
return normalizeEmail(trimmed);
|
|
142
|
+
case "internal":
|
|
143
|
+
return toRelativePath(trimmed);
|
|
144
|
+
case "external":
|
|
145
|
+
return trimmed;
|
|
146
|
+
default:
|
|
147
|
+
return trimmed;
|
|
148
|
+
}
|
|
149
|
+
}, [href, linkType]);
|
|
150
|
+
const target = React6__namespace.useMemo(() => {
|
|
151
|
+
switch (linkType) {
|
|
152
|
+
case "external":
|
|
153
|
+
return "_blank";
|
|
154
|
+
case "internal":
|
|
155
|
+
return "_self";
|
|
156
|
+
case "mailto":
|
|
157
|
+
case "tel":
|
|
158
|
+
return void 0;
|
|
159
|
+
default:
|
|
160
|
+
return void 0;
|
|
161
|
+
}
|
|
162
|
+
}, [linkType]);
|
|
163
|
+
const rel = React6__namespace.useMemo(() => {
|
|
164
|
+
if (linkType === "external") {
|
|
165
|
+
return "noopener noreferrer";
|
|
166
|
+
}
|
|
167
|
+
return void 0;
|
|
168
|
+
}, [linkType]);
|
|
169
|
+
const isExternal = linkType === "external";
|
|
170
|
+
const isInternal = linkType === "internal";
|
|
171
|
+
const shouldUseRouter = isInternal && typeof normalizedHref === "string" && normalizedHref.startsWith("/");
|
|
172
|
+
const handleClick = React6__namespace.useCallback(
|
|
173
|
+
(event) => {
|
|
174
|
+
if (onClick) {
|
|
175
|
+
try {
|
|
176
|
+
onClick(event);
|
|
177
|
+
} catch (error) {
|
|
178
|
+
console.error("Error in user onClick handler:", error);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
if (event.defaultPrevented) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
if (shouldUseRouter && normalizedHref && event.button === 0 && // left-click only
|
|
185
|
+
!event.metaKey && !event.altKey && !event.ctrlKey && !event.shiftKey) {
|
|
186
|
+
if (typeof window !== "undefined") {
|
|
187
|
+
const handler = window.__opensiteNavigationHandler;
|
|
188
|
+
if (typeof handler === "function") {
|
|
189
|
+
try {
|
|
190
|
+
const handled = handler(normalizedHref, event.nativeEvent || event);
|
|
191
|
+
if (handled !== false) {
|
|
192
|
+
event.preventDefault();
|
|
193
|
+
}
|
|
194
|
+
} catch (error) {
|
|
195
|
+
console.error("Error in navigation handler:", error);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
[onClick, shouldUseRouter, normalizedHref]
|
|
202
|
+
);
|
|
203
|
+
return {
|
|
204
|
+
linkType,
|
|
205
|
+
normalizedHref,
|
|
206
|
+
target,
|
|
207
|
+
rel,
|
|
208
|
+
isExternal,
|
|
209
|
+
isInternal,
|
|
210
|
+
shouldUseRouter,
|
|
211
|
+
handleClick
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
var baseStyles = [
|
|
215
|
+
// Layout
|
|
216
|
+
"inline-flex items-center justify-center gap-2 whitespace-nowrap shrink-0",
|
|
217
|
+
// Typography - using CSS variables with sensible defaults
|
|
218
|
+
"font-[var(--button-font-family,inherit)]",
|
|
219
|
+
"font-[var(--button-font-weight,500)]",
|
|
220
|
+
"tracking-[var(--button-letter-spacing,0)]",
|
|
221
|
+
"leading-[var(--button-line-height,1.25)]",
|
|
222
|
+
"[text-transform:var(--button-text-transform,none)]",
|
|
223
|
+
"text-sm",
|
|
224
|
+
// Border radius
|
|
225
|
+
"rounded-[var(--button-radius,var(--radius,0.375rem))]",
|
|
226
|
+
// Smooth transition - using [transition:...] to set full shorthand property (not just transition-property)
|
|
227
|
+
"[transition:var(--button-transition,all_250ms_cubic-bezier(0.4,0,0.2,1))]",
|
|
228
|
+
// Box shadow (master level) - using [box-shadow:...] for complex multi-value shadows
|
|
229
|
+
"[box-shadow:var(--button-shadow,none)]",
|
|
230
|
+
"hover:[box-shadow:var(--button-shadow-hover,var(--button-shadow,none))]",
|
|
231
|
+
// Disabled state
|
|
232
|
+
"disabled:pointer-events-none disabled:opacity-50",
|
|
233
|
+
// SVG handling
|
|
234
|
+
"[&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0",
|
|
235
|
+
// Focus styles
|
|
236
|
+
"outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
|
|
237
|
+
// Invalid state
|
|
238
|
+
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive"
|
|
239
|
+
].join(" ");
|
|
240
|
+
var buttonVariants = classVarianceAuthority.cva(baseStyles, {
|
|
241
|
+
variants: {
|
|
242
|
+
variant: {
|
|
243
|
+
// Default (Primary) variant - full customization
|
|
244
|
+
default: [
|
|
245
|
+
"bg-[var(--button-default-bg,hsl(var(--primary)))]",
|
|
246
|
+
"text-[var(--button-default-fg,hsl(var(--primary-foreground)))]",
|
|
247
|
+
"border-[length:var(--button-default-border-width,0px)]",
|
|
248
|
+
"border-[color:var(--button-default-border,transparent)]",
|
|
249
|
+
"[box-shadow:var(--button-default-shadow,var(--button-shadow,none))]",
|
|
250
|
+
"hover:bg-[var(--button-default-hover-bg,hsl(var(--primary)/0.9))]",
|
|
251
|
+
"hover:text-[var(--button-default-hover-fg,var(--button-default-fg,hsl(var(--primary-foreground))))]",
|
|
252
|
+
"hover:border-[color:var(--button-default-hover-border,var(--button-default-border,transparent))]",
|
|
253
|
+
"hover:[box-shadow:var(--button-default-shadow-hover,var(--button-shadow-hover,var(--button-default-shadow,var(--button-shadow,none))))]"
|
|
254
|
+
].join(" "),
|
|
255
|
+
// Destructive variant - full customization
|
|
256
|
+
destructive: [
|
|
257
|
+
"bg-[var(--button-destructive-bg,hsl(var(--destructive)))]",
|
|
258
|
+
"text-[var(--button-destructive-fg,white)]",
|
|
259
|
+
"border-[length:var(--button-destructive-border-width,0px)]",
|
|
260
|
+
"border-[color:var(--button-destructive-border,transparent)]",
|
|
261
|
+
"[box-shadow:var(--button-destructive-shadow,var(--button-shadow,none))]",
|
|
262
|
+
"hover:bg-[var(--button-destructive-hover-bg,hsl(var(--destructive)/0.9))]",
|
|
263
|
+
"hover:text-[var(--button-destructive-hover-fg,var(--button-destructive-fg,white))]",
|
|
264
|
+
"hover:border-[color:var(--button-destructive-hover-border,var(--button-destructive-border,transparent))]",
|
|
265
|
+
"hover:[box-shadow:var(--button-destructive-shadow-hover,var(--button-shadow-hover,var(--button-destructive-shadow,var(--button-shadow,none))))]",
|
|
266
|
+
"focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40",
|
|
267
|
+
"dark:bg-destructive/60"
|
|
268
|
+
].join(" "),
|
|
269
|
+
// Outline variant - full customization with proper border handling
|
|
270
|
+
outline: [
|
|
271
|
+
"bg-[var(--button-outline-bg,hsl(var(--background)))]",
|
|
272
|
+
"text-[var(--button-outline-fg,inherit)]",
|
|
273
|
+
"border-[length:var(--button-outline-border-width,1px)]",
|
|
274
|
+
"border-[color:var(--button-outline-border,hsl(var(--border)))]",
|
|
275
|
+
"[box-shadow:var(--button-outline-shadow,var(--button-shadow,0_1px_2px_0_rgb(0_0_0/0.05)))]",
|
|
276
|
+
"hover:bg-[var(--button-outline-hover-bg,hsl(var(--accent)))]",
|
|
277
|
+
"hover:text-[var(--button-outline-hover-fg,hsl(var(--accent-foreground)))]",
|
|
278
|
+
"hover:border-[color:var(--button-outline-hover-border,var(--button-outline-border,hsl(var(--border))))]",
|
|
279
|
+
"hover:[box-shadow:var(--button-outline-shadow-hover,var(--button-shadow-hover,var(--button-outline-shadow,var(--button-shadow,none))))]",
|
|
280
|
+
"dark:bg-input/30 dark:border-input dark:hover:bg-input/50"
|
|
281
|
+
].join(" "),
|
|
282
|
+
// Secondary variant - full customization
|
|
283
|
+
secondary: [
|
|
284
|
+
"bg-[var(--button-secondary-bg,hsl(var(--secondary)))]",
|
|
285
|
+
"text-[var(--button-secondary-fg,hsl(var(--secondary-foreground)))]",
|
|
286
|
+
"border-[length:var(--button-secondary-border-width,0px)]",
|
|
287
|
+
"border-[color:var(--button-secondary-border,transparent)]",
|
|
288
|
+
"[box-shadow:var(--button-secondary-shadow,var(--button-shadow,none))]",
|
|
289
|
+
"hover:bg-[var(--button-secondary-hover-bg,hsl(var(--secondary)/0.8))]",
|
|
290
|
+
"hover:text-[var(--button-secondary-hover-fg,var(--button-secondary-fg,hsl(var(--secondary-foreground))))]",
|
|
291
|
+
"hover:border-[color:var(--button-secondary-hover-border,var(--button-secondary-border,transparent))]",
|
|
292
|
+
"hover:[box-shadow:var(--button-secondary-shadow-hover,var(--button-shadow-hover,var(--button-secondary-shadow,var(--button-shadow,none))))]"
|
|
293
|
+
].join(" "),
|
|
294
|
+
// Ghost variant - full customization
|
|
295
|
+
ghost: [
|
|
296
|
+
"bg-[var(--button-ghost-bg,transparent)]",
|
|
297
|
+
"text-[var(--button-ghost-fg,inherit)]",
|
|
298
|
+
"border-[length:var(--button-ghost-border-width,0px)]",
|
|
299
|
+
"border-[color:var(--button-ghost-border,transparent)]",
|
|
300
|
+
"[box-shadow:var(--button-ghost-shadow,var(--button-shadow,none))]",
|
|
301
|
+
"hover:bg-[var(--button-ghost-hover-bg,hsl(var(--accent)))]",
|
|
302
|
+
"hover:text-[var(--button-ghost-hover-fg,hsl(var(--accent-foreground)))]",
|
|
303
|
+
"hover:border-[color:var(--button-ghost-hover-border,var(--button-ghost-border,transparent))]",
|
|
304
|
+
"hover:[box-shadow:var(--button-ghost-shadow-hover,var(--button-shadow-hover,var(--button-ghost-shadow,var(--button-shadow,none))))]",
|
|
305
|
+
"dark:hover:bg-accent/50"
|
|
306
|
+
].join(" "),
|
|
307
|
+
// Link variant - full customization
|
|
308
|
+
link: [
|
|
309
|
+
"bg-[var(--button-link-bg,transparent)]",
|
|
310
|
+
"text-[var(--button-link-fg,hsl(var(--primary)))]",
|
|
311
|
+
"border-[length:var(--button-link-border-width,0px)]",
|
|
312
|
+
"border-[color:var(--button-link-border,transparent)]",
|
|
313
|
+
"[box-shadow:var(--button-link-shadow,none)]",
|
|
314
|
+
"hover:bg-[var(--button-link-hover-bg,transparent)]",
|
|
315
|
+
"hover:text-[var(--button-link-hover-fg,var(--button-link-fg,hsl(var(--primary))))]",
|
|
316
|
+
"hover:[box-shadow:var(--button-link-shadow-hover,none)]",
|
|
317
|
+
"underline-offset-4 hover:underline"
|
|
318
|
+
].join(" ")
|
|
319
|
+
},
|
|
320
|
+
size: {
|
|
321
|
+
default: [
|
|
322
|
+
"h-[var(--button-height-md,2.25rem)]",
|
|
323
|
+
"px-[var(--button-padding-x-md,1rem)]",
|
|
324
|
+
"py-[var(--button-padding-y-md,0.5rem)]",
|
|
325
|
+
"has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]"
|
|
326
|
+
].join(" "),
|
|
327
|
+
sm: [
|
|
328
|
+
"h-[var(--button-height-sm,2rem)]",
|
|
329
|
+
"px-[var(--button-padding-x-sm,0.75rem)]",
|
|
330
|
+
"py-[var(--button-padding-y-sm,0.25rem)]",
|
|
331
|
+
"gap-1.5",
|
|
332
|
+
"has-[>svg]:px-[calc(var(--button-padding-x-sm,0.75rem)*0.83)]"
|
|
333
|
+
].join(" "),
|
|
334
|
+
md: [
|
|
335
|
+
"h-[var(--button-height-md,2.25rem)]",
|
|
336
|
+
"px-[var(--button-padding-x-md,1rem)]",
|
|
337
|
+
"py-[var(--button-padding-y-md,0.5rem)]",
|
|
338
|
+
"has-[>svg]:px-[calc(var(--button-padding-x-md,1rem)*0.75)]"
|
|
339
|
+
].join(" "),
|
|
340
|
+
lg: [
|
|
341
|
+
"h-[var(--button-height-lg,2.5rem)]",
|
|
342
|
+
"px-[var(--button-padding-x-lg,1.5rem)]",
|
|
343
|
+
"py-[var(--button-padding-y-lg,0.5rem)]",
|
|
344
|
+
"has-[>svg]:px-[calc(var(--button-padding-x-lg,1.5rem)*0.67)]"
|
|
345
|
+
].join(" "),
|
|
346
|
+
icon: "size-[var(--button-height-md,2.25rem)]",
|
|
347
|
+
"icon-sm": "size-[var(--button-height-sm,2rem)]",
|
|
348
|
+
"icon-lg": "size-[var(--button-height-lg,2.5rem)]"
|
|
349
|
+
}
|
|
350
|
+
},
|
|
351
|
+
defaultVariants: {
|
|
352
|
+
variant: "default",
|
|
353
|
+
size: "default"
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
var Pressable = React6__namespace.forwardRef(
|
|
357
|
+
({
|
|
358
|
+
children,
|
|
359
|
+
className,
|
|
360
|
+
href,
|
|
361
|
+
onClick,
|
|
362
|
+
variant,
|
|
363
|
+
size,
|
|
364
|
+
asButton = false,
|
|
365
|
+
fallbackComponentType = "span",
|
|
366
|
+
componentType,
|
|
367
|
+
"aria-label": ariaLabel,
|
|
368
|
+
"aria-describedby": ariaDescribedby,
|
|
369
|
+
id,
|
|
370
|
+
...props
|
|
371
|
+
}, ref) => {
|
|
372
|
+
const navigation = useNavigation({ href, onClick });
|
|
373
|
+
const {
|
|
374
|
+
normalizedHref,
|
|
375
|
+
target,
|
|
376
|
+
rel,
|
|
377
|
+
linkType,
|
|
378
|
+
isInternal,
|
|
379
|
+
handleClick
|
|
380
|
+
} = navigation;
|
|
381
|
+
const shouldRenderLink = normalizedHref && linkType !== "none";
|
|
382
|
+
const shouldRenderButton = !shouldRenderLink && onClick;
|
|
383
|
+
const effectiveComponentType = componentType || (shouldRenderLink ? "a" : shouldRenderButton ? "button" : fallbackComponentType);
|
|
384
|
+
const finalComponentType = isInternal && shouldRenderLink ? "a" : effectiveComponentType;
|
|
385
|
+
const shouldApplyButtonStyles = asButton || variant || size;
|
|
386
|
+
const combinedClassName = cn(
|
|
387
|
+
shouldApplyButtonStyles && buttonVariants({ variant, size }),
|
|
388
|
+
className
|
|
389
|
+
);
|
|
390
|
+
const dataProps = Object.fromEntries(
|
|
391
|
+
Object.entries(props).filter(([key]) => key.startsWith("data-"))
|
|
392
|
+
);
|
|
393
|
+
const buttonDataAttributes = shouldApplyButtonStyles ? {
|
|
394
|
+
"data-slot": "button",
|
|
395
|
+
"data-variant": variant ?? "default",
|
|
396
|
+
"data-size": size ?? "default"
|
|
397
|
+
} : {};
|
|
398
|
+
const commonProps = {
|
|
399
|
+
className: combinedClassName,
|
|
400
|
+
onClick: handleClick,
|
|
401
|
+
"aria-label": ariaLabel,
|
|
402
|
+
"aria-describedby": ariaDescribedby,
|
|
403
|
+
id,
|
|
404
|
+
...dataProps,
|
|
405
|
+
...buttonDataAttributes
|
|
406
|
+
};
|
|
407
|
+
if (finalComponentType === "a" && shouldRenderLink) {
|
|
408
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
409
|
+
"a",
|
|
410
|
+
{
|
|
411
|
+
ref,
|
|
412
|
+
href: normalizedHref,
|
|
413
|
+
target,
|
|
414
|
+
rel,
|
|
415
|
+
...commonProps,
|
|
416
|
+
...props,
|
|
417
|
+
children
|
|
418
|
+
}
|
|
419
|
+
);
|
|
420
|
+
}
|
|
421
|
+
if (finalComponentType === "button") {
|
|
422
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
423
|
+
"button",
|
|
424
|
+
{
|
|
425
|
+
ref,
|
|
426
|
+
type: props.type || "button",
|
|
427
|
+
...commonProps,
|
|
428
|
+
...props,
|
|
429
|
+
children
|
|
430
|
+
}
|
|
431
|
+
);
|
|
432
|
+
}
|
|
433
|
+
if (finalComponentType === "div") {
|
|
434
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
435
|
+
"div",
|
|
436
|
+
{
|
|
437
|
+
ref,
|
|
438
|
+
...commonProps,
|
|
439
|
+
children
|
|
440
|
+
}
|
|
441
|
+
);
|
|
442
|
+
}
|
|
443
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
444
|
+
"span",
|
|
445
|
+
{
|
|
446
|
+
ref,
|
|
447
|
+
...commonProps,
|
|
448
|
+
children
|
|
449
|
+
}
|
|
450
|
+
);
|
|
451
|
+
}
|
|
452
|
+
);
|
|
453
|
+
Pressable.displayName = "Pressable";
|
|
454
|
+
var svgCache = /* @__PURE__ */ new Map();
|
|
455
|
+
function DynamicIcon({
|
|
456
|
+
name,
|
|
457
|
+
size = 28,
|
|
458
|
+
color,
|
|
459
|
+
className,
|
|
460
|
+
alt
|
|
461
|
+
}) {
|
|
462
|
+
const [svgContent, setSvgContent] = React6__namespace.useState(null);
|
|
463
|
+
const [isLoading, setIsLoading] = React6__namespace.useState(true);
|
|
464
|
+
const [error, setError] = React6__namespace.useState(null);
|
|
465
|
+
const { url, iconName } = React6__namespace.useMemo(() => {
|
|
466
|
+
const separator = name.includes("/") ? "/" : ":";
|
|
467
|
+
const [prefix, iconName2] = name.split(separator);
|
|
468
|
+
const baseUrl = `https://icons.opensite.ai/api/icon/${prefix}/${iconName2}?format=svg&width=${size}&height=${size}`;
|
|
469
|
+
return {
|
|
470
|
+
url: baseUrl,
|
|
471
|
+
iconName: iconName2
|
|
472
|
+
};
|
|
473
|
+
}, [name, size]);
|
|
474
|
+
React6__namespace.useEffect(() => {
|
|
475
|
+
let isMounted = true;
|
|
476
|
+
const fetchSvg = async () => {
|
|
477
|
+
const cached = svgCache.get(url);
|
|
478
|
+
if (cached) {
|
|
479
|
+
if (isMounted) {
|
|
480
|
+
setSvgContent(cached);
|
|
481
|
+
setIsLoading(false);
|
|
482
|
+
}
|
|
483
|
+
return;
|
|
484
|
+
}
|
|
485
|
+
try {
|
|
486
|
+
setIsLoading(true);
|
|
487
|
+
setError(null);
|
|
488
|
+
const response = await fetch(url);
|
|
489
|
+
if (!response.ok) {
|
|
490
|
+
throw new Error(`Failed to fetch icon: ${response.status}`);
|
|
491
|
+
}
|
|
492
|
+
let svg = await response.text();
|
|
493
|
+
svg = processSvgForCurrentColor(svg);
|
|
494
|
+
svgCache.set(url, svg);
|
|
495
|
+
if (isMounted) {
|
|
496
|
+
setSvgContent(svg);
|
|
497
|
+
setIsLoading(false);
|
|
498
|
+
}
|
|
499
|
+
} catch (err) {
|
|
500
|
+
if (isMounted) {
|
|
501
|
+
setError(err instanceof Error ? err.message : "Failed to load icon");
|
|
502
|
+
setIsLoading(false);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
};
|
|
506
|
+
fetchSvg();
|
|
507
|
+
return () => {
|
|
508
|
+
isMounted = false;
|
|
509
|
+
};
|
|
510
|
+
}, [url]);
|
|
511
|
+
if (isLoading) {
|
|
512
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
513
|
+
"span",
|
|
514
|
+
{
|
|
515
|
+
className: cn("inline-block", className),
|
|
516
|
+
style: { width: size, height: size },
|
|
517
|
+
"aria-hidden": "true"
|
|
518
|
+
}
|
|
519
|
+
);
|
|
520
|
+
}
|
|
521
|
+
if (error || !svgContent) {
|
|
522
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
523
|
+
"span",
|
|
524
|
+
{
|
|
525
|
+
className: cn("inline-block", className),
|
|
526
|
+
style: { width: size, height: size },
|
|
527
|
+
role: "img",
|
|
528
|
+
"aria-label": alt || iconName
|
|
529
|
+
}
|
|
530
|
+
);
|
|
531
|
+
}
|
|
532
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
533
|
+
"span",
|
|
534
|
+
{
|
|
535
|
+
className: cn("inline-flex items-center justify-center", className),
|
|
536
|
+
style: {
|
|
537
|
+
width: size,
|
|
538
|
+
height: size,
|
|
539
|
+
color: color || "inherit"
|
|
540
|
+
},
|
|
541
|
+
role: "img",
|
|
542
|
+
"aria-label": alt || iconName,
|
|
543
|
+
dangerouslySetInnerHTML: { __html: svgContent }
|
|
544
|
+
}
|
|
545
|
+
);
|
|
546
|
+
}
|
|
547
|
+
function processSvgForCurrentColor(svg) {
|
|
548
|
+
let processed = svg;
|
|
549
|
+
processed = processed.replace(
|
|
550
|
+
/stroke=["'](#000000|#000|black)["']/gi,
|
|
551
|
+
'stroke="currentColor"'
|
|
552
|
+
);
|
|
553
|
+
processed = processed.replace(
|
|
554
|
+
/fill=["'](#000000|#000|black)["']/gi,
|
|
555
|
+
'fill="currentColor"'
|
|
556
|
+
);
|
|
557
|
+
return processed;
|
|
558
|
+
}
|
|
35
559
|
var maxWidthStyles = {
|
|
36
560
|
sm: "max-w-screen-sm",
|
|
37
561
|
md: "max-w-screen-md",
|
|
@@ -41,7 +565,7 @@ var maxWidthStyles = {
|
|
|
41
565
|
"4xl": "max-w-[1536px]",
|
|
42
566
|
full: "max-w-full"
|
|
43
567
|
};
|
|
44
|
-
var Container =
|
|
568
|
+
var Container = React6__namespace.default.forwardRef(
|
|
45
569
|
({ children, maxWidth = "xl", className, as = "div", ...props }, ref) => {
|
|
46
570
|
const Component = as;
|
|
47
571
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -346,7 +870,7 @@ var spacingStyles = {
|
|
|
346
870
|
};
|
|
347
871
|
var predefinedSpacings = ["none", "sm", "md", "lg", "xl"];
|
|
348
872
|
var isPredefinedSpacing = (spacing) => predefinedSpacings.includes(spacing);
|
|
349
|
-
var Section =
|
|
873
|
+
var Section = React6__namespace.default.forwardRef(
|
|
350
874
|
({
|
|
351
875
|
id,
|
|
352
876
|
title,
|
|
@@ -407,9 +931,9 @@ var Section = React3__namespace.default.forwardRef(
|
|
|
407
931
|
}
|
|
408
932
|
);
|
|
409
933
|
Section.displayName = "Section";
|
|
410
|
-
var ProgressSliderContext =
|
|
934
|
+
var ProgressSliderContext = React6__namespace.createContext(void 0);
|
|
411
935
|
function useProgressSliderContext() {
|
|
412
|
-
const context =
|
|
936
|
+
const context = React6__namespace.useContext(ProgressSliderContext);
|
|
413
937
|
if (!context) {
|
|
414
938
|
throw new Error(
|
|
415
939
|
"useProgressSliderContext must be used within a ProgressSlider"
|
|
@@ -438,13 +962,13 @@ function SliderBtn({
|
|
|
438
962
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
439
963
|
"div",
|
|
440
964
|
{
|
|
441
|
-
className: "absolute inset-0 -z-10 max-h-full max-w-full overflow-hidden",
|
|
965
|
+
className: "absolute inset-0 -z-10 max-h-full max-w-full overflow-hidden rounded-lg",
|
|
442
966
|
role: "progressbar",
|
|
443
967
|
"aria-valuenow": active === value ? progress : 0,
|
|
444
968
|
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
445
969
|
"span",
|
|
446
970
|
{
|
|
447
|
-
className: cn("absolute left-0", progressBarClass),
|
|
971
|
+
className: cn("absolute left-0 rounded-b-lg", progressBarClass),
|
|
448
972
|
style: {
|
|
449
973
|
[vertical ? "height" : "width"]: active === value ? `${progress}%` : "0%"
|
|
450
974
|
}
|
|
@@ -475,7 +999,7 @@ function CarouselProgressSlider({
|
|
|
475
999
|
subheading,
|
|
476
1000
|
slides,
|
|
477
1001
|
slidesSlot,
|
|
478
|
-
duration =
|
|
1002
|
+
duration = 8e3,
|
|
479
1003
|
fastDuration = 400,
|
|
480
1004
|
vertical = false,
|
|
481
1005
|
className,
|
|
@@ -491,25 +1015,38 @@ function CarouselProgressSlider({
|
|
|
491
1015
|
pattern,
|
|
492
1016
|
patternOpacity
|
|
493
1017
|
}) {
|
|
494
|
-
const [active, setActive] =
|
|
495
|
-
const [progress, setProgress] =
|
|
496
|
-
const [isFastForward, setIsFastForward] =
|
|
497
|
-
const
|
|
498
|
-
const
|
|
499
|
-
const
|
|
500
|
-
const
|
|
1018
|
+
const [active, setActive] = React6__namespace.useState(slides?.[0]?.id ?? "");
|
|
1019
|
+
const [progress, setProgress] = React6__namespace.useState(0);
|
|
1020
|
+
const [isFastForward, setIsFastForward] = React6__namespace.useState(false);
|
|
1021
|
+
const [isPaused, setIsPaused] = React6__namespace.useState(false);
|
|
1022
|
+
const frame = React6__namespace.useRef(0);
|
|
1023
|
+
const firstFrameTime = React6__namespace.useRef(performance.now());
|
|
1024
|
+
const targetValue = React6__namespace.useRef(null);
|
|
1025
|
+
const pausedProgress = React6__namespace.useRef(0);
|
|
1026
|
+
const sliderValues = React6__namespace.useMemo(
|
|
501
1027
|
() => slides?.map((slide) => slide.id),
|
|
502
1028
|
[slides]
|
|
503
1029
|
);
|
|
504
|
-
|
|
505
|
-
if ((sliderValues?.length ?? 0) > 0) {
|
|
1030
|
+
React6__namespace.useEffect(() => {
|
|
1031
|
+
if ((sliderValues?.length ?? 0) > 0 && !isPaused) {
|
|
506
1032
|
firstFrameTime.current = performance.now();
|
|
1033
|
+
if (pausedProgress.current > 0) {
|
|
1034
|
+
setProgress(pausedProgress.current);
|
|
1035
|
+
pausedProgress.current = 0;
|
|
1036
|
+
}
|
|
507
1037
|
frame.current = requestAnimationFrame(animate);
|
|
508
1038
|
}
|
|
509
1039
|
return () => {
|
|
510
1040
|
cancelAnimationFrame(frame.current);
|
|
511
1041
|
};
|
|
512
|
-
}, [sliderValues, active, isFastForward]);
|
|
1042
|
+
}, [sliderValues, active, isFastForward, isPaused]);
|
|
1043
|
+
const togglePause = () => {
|
|
1044
|
+
if (!isPaused) {
|
|
1045
|
+
pausedProgress.current = progress;
|
|
1046
|
+
cancelAnimationFrame(frame.current);
|
|
1047
|
+
}
|
|
1048
|
+
setIsPaused(!isPaused);
|
|
1049
|
+
};
|
|
513
1050
|
const animate = (now) => {
|
|
514
1051
|
const currentDuration = isFastForward ? fastDuration : duration;
|
|
515
1052
|
const elapsedTime = now - firstFrameTime.current;
|
|
@@ -561,26 +1098,40 @@ function CarouselProgressSlider({
|
|
|
561
1098
|
pattern,
|
|
562
1099
|
patternOpacity,
|
|
563
1100
|
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("relative", containerClassName), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("grid gap-8 lg:grid-cols-2", contentClassName), children: [
|
|
564
|
-
/* @__PURE__ */ jsxRuntime.
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
1101
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("relative", imageClassName), children: [
|
|
1102
|
+
slidesSlot ? slidesSlot : slides?.map((slide) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1103
|
+
SliderWrapper,
|
|
1104
|
+
{
|
|
1105
|
+
value: slide.id,
|
|
1106
|
+
className: cn("", slide.className),
|
|
1107
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "aspect-video overflow-hidden rounded-lg", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1108
|
+
img.Img,
|
|
1109
|
+
{
|
|
1110
|
+
src: slide.image,
|
|
1111
|
+
alt: typeof slide.title === "string" ? slide.title : `Slide ${slide.id}`,
|
|
1112
|
+
className: cn(
|
|
1113
|
+
"h-full w-full object-cover",
|
|
1114
|
+
slide.imageClassName
|
|
1115
|
+
),
|
|
1116
|
+
optixFlowConfig
|
|
1117
|
+
}
|
|
1118
|
+
) })
|
|
1119
|
+
},
|
|
1120
|
+
slide.id
|
|
1121
|
+
)),
|
|
1122
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 flex justify-center lg:justify-start", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1123
|
+
Pressable,
|
|
1124
|
+
{
|
|
1125
|
+
onClick: togglePause,
|
|
1126
|
+
asButton: true,
|
|
1127
|
+
variant: "outline",
|
|
1128
|
+
size: "icon",
|
|
1129
|
+
className: "flex h-10 w-10 items-center justify-center rounded-full",
|
|
1130
|
+
"aria-label": isPaused ? "Play" : "Pause",
|
|
1131
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(DynamicIcon, { name: isPaused ? "lucide/play" : "lucide/pause", size: 18 })
|
|
1132
|
+
}
|
|
1133
|
+
) })
|
|
1134
|
+
] }),
|
|
584
1135
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
585
1136
|
"div",
|
|
586
1137
|
{
|