@classytic/fluid 0.4.2 → 0.5.0
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/README.md +21 -1
- package/dist/client/calendar.d.mts +1 -2
- package/dist/client/calendar.mjs +4 -4
- package/dist/client/color-picker.d.mts +41 -25
- package/dist/client/color-picker.mjs +121 -73
- package/dist/client/core.d.mts +243 -557
- package/dist/client/core.mjs +351 -1462
- package/dist/client/error.d.mts +41 -41
- package/dist/client/error.mjs +35 -35
- package/dist/client/gallery.d.mts +33 -33
- package/dist/client/gallery.mjs +128 -127
- package/dist/client/hooks.d.mts +57 -39
- package/dist/client/hooks.mjs +29 -7
- package/dist/client/spreadsheet.d.mts +28 -28
- package/dist/client/spreadsheet.mjs +77 -77
- package/dist/client/table.d.mts +66 -33
- package/dist/client/table.mjs +87 -54
- package/dist/client/theme.mjs +1 -1
- package/dist/command.d.mts +6 -4
- package/dist/command.mjs +3 -3
- package/dist/compact.d.mts +97 -95
- package/dist/compact.mjs +336 -322
- package/dist/dashboard.d.mts +614 -422
- package/dist/dashboard.mjs +1051 -762
- package/dist/{dropdown-wrapper-B86u9Fri.mjs → dropdown-wrapper-B9nRDUlz.mjs} +25 -35
- package/dist/forms.d.mts +1037 -972
- package/dist/forms.mjs +2849 -2721
- package/dist/index.d.mts +218 -152
- package/dist/index.mjs +357 -264
- package/dist/layouts.d.mts +94 -94
- package/dist/layouts.mjs +115 -110
- package/dist/phone-input-B9_XPNvv.mjs +429 -0
- package/dist/phone-input-CLH_UjQZ.d.mts +31 -0
- package/dist/{search-context-DR7DBs7S.mjs → search-context-1g3ZmOvx.mjs} +1 -1
- package/dist/search.d.mts +168 -164
- package/dist/search.mjs +305 -301
- package/dist/{sheet-wrapper-C13Y-Q6w.mjs → sheet-wrapper-B2uxookb.mjs} +1 -1
- package/dist/timeline-Bgu1mIe9.d.mts +373 -0
- package/dist/timeline-HJtWf4Op.mjs +804 -0
- package/dist/{use-base-search-BGgWnWaF.d.mts → use-base-search-DFC4QKYU.d.mts} +1 -1
- package/dist/{use-media-query-BnVNIKT4.mjs → use-media-query-ChLfFChU.mjs} +6 -7
- package/package.json +2 -2
- /package/dist/{api-pagination-CJ0vR_w6.d.mts → api-pagination-C30ser2L.d.mts} +0 -0
- /package/dist/{filter-utils-DqMmy_v-.mjs → filter-utils-BGIvtq1R.mjs} +0 -0
- /package/dist/{filter-utils-IZ0GtuPo.d.mts → filter-utils-DOFTBWm1.d.mts} +0 -0
- /package/dist/{use-debounce-xmZucz5e.mjs → use-debounce-BNoNiEon.mjs} +0 -0
- /package/dist/{use-keyboard-shortcut-Bl6YM5Q7.mjs → use-keyboard-shortcut-C_Vk-36P.mjs} +0 -0
- /package/dist/{use-keyboard-shortcut-_mRCh3QO.d.mts → use-keyboard-shortcut-Q4CSPzSI.d.mts} +0 -0
- /package/dist/{use-mobile-BX3SQVo2.mjs → use-mobile-CnEmFiQx.mjs} +0 -0
- /package/dist/{use-scroll-detection-CsgsQYvy.mjs → use-scroll-detection-BKfqkmEC.mjs} +0 -0
- /package/dist/{utils-CDue7cEt.d.mts → utils-rqvYP1by.d.mts} +0 -0
package/dist/client/error.d.mts
CHANGED
|
@@ -1,7 +1,47 @@
|
|
|
1
|
-
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
2
1
|
import { ComponentType, ReactNode } from "react";
|
|
2
|
+
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
3
3
|
import { FallbackProps } from "react-error-boundary";
|
|
4
4
|
|
|
5
|
+
//#region src/components/async-boundary.d.ts
|
|
6
|
+
interface AsyncBoundaryProps {
|
|
7
|
+
/** Suspense fallback (shown while loading) */
|
|
8
|
+
fallback?: ReactNode;
|
|
9
|
+
/** Error fallback component (shown on error) */
|
|
10
|
+
errorFallback?: ComponentType<FallbackProps>;
|
|
11
|
+
/** Called when an error is caught */
|
|
12
|
+
onError?: (error: unknown, info: {
|
|
13
|
+
componentStack?: string | null;
|
|
14
|
+
}) => void;
|
|
15
|
+
/** Called when the error boundary resets */
|
|
16
|
+
onReset?: () => void;
|
|
17
|
+
children: ReactNode;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* AsyncBoundary — Suspense + ErrorBoundary combined.
|
|
21
|
+
*
|
|
22
|
+
* If `errorFallback` is provided, wraps in ErrorBoundary from react-error-boundary.
|
|
23
|
+
* Otherwise, renders Suspense only.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```tsx
|
|
27
|
+
* import { AsyncBoundary, InlineErrorFallback } from "@classytic/fluid/client";
|
|
28
|
+
*
|
|
29
|
+
* <AsyncBoundary
|
|
30
|
+
* fallback={<SkeletonTable rows={5} />}
|
|
31
|
+
* errorFallback={InlineErrorFallback}
|
|
32
|
+
* >
|
|
33
|
+
* <DataFetchingComponent />
|
|
34
|
+
* </AsyncBoundary>
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
declare function AsyncBoundary({
|
|
38
|
+
fallback,
|
|
39
|
+
errorFallback: ErrorFallback,
|
|
40
|
+
onError,
|
|
41
|
+
onReset,
|
|
42
|
+
children
|
|
43
|
+
}: AsyncBoundaryProps): react_jsx_runtime0.JSX.Element;
|
|
44
|
+
//#endregion
|
|
5
45
|
//#region src/components/error-boundary.d.ts
|
|
6
46
|
interface ErrorBoundaryFallbackProps extends FallbackProps {}
|
|
7
47
|
interface ErrorBoundaryProps {
|
|
@@ -82,44 +122,4 @@ declare function FeatureErrorBoundary({
|
|
|
82
122
|
className
|
|
83
123
|
}: FeatureErrorBoundaryProps): react_jsx_runtime0.JSX.Element;
|
|
84
124
|
//#endregion
|
|
85
|
-
//#region src/components/async-boundary.d.ts
|
|
86
|
-
interface AsyncBoundaryProps {
|
|
87
|
-
/** Suspense fallback (shown while loading) */
|
|
88
|
-
fallback?: ReactNode;
|
|
89
|
-
/** Error fallback component (shown on error) */
|
|
90
|
-
errorFallback?: ComponentType<FallbackProps>;
|
|
91
|
-
/** Called when an error is caught */
|
|
92
|
-
onError?: (error: unknown, info: {
|
|
93
|
-
componentStack?: string | null;
|
|
94
|
-
}) => void;
|
|
95
|
-
/** Called when the error boundary resets */
|
|
96
|
-
onReset?: () => void;
|
|
97
|
-
children: ReactNode;
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* AsyncBoundary — Suspense + ErrorBoundary combined.
|
|
101
|
-
*
|
|
102
|
-
* If `errorFallback` is provided, wraps in ErrorBoundary from react-error-boundary.
|
|
103
|
-
* Otherwise, renders Suspense only.
|
|
104
|
-
*
|
|
105
|
-
* @example
|
|
106
|
-
* ```tsx
|
|
107
|
-
* import { AsyncBoundary, InlineErrorFallback } from "@classytic/fluid/client";
|
|
108
|
-
*
|
|
109
|
-
* <AsyncBoundary
|
|
110
|
-
* fallback={<SkeletonTable rows={5} />}
|
|
111
|
-
* errorFallback={InlineErrorFallback}
|
|
112
|
-
* >
|
|
113
|
-
* <DataFetchingComponent />
|
|
114
|
-
* </AsyncBoundary>
|
|
115
|
-
* ```
|
|
116
|
-
*/
|
|
117
|
-
declare function AsyncBoundary({
|
|
118
|
-
fallback,
|
|
119
|
-
errorFallback: ErrorFallback,
|
|
120
|
-
onError,
|
|
121
|
-
onReset,
|
|
122
|
-
children
|
|
123
|
-
}: AsyncBoundaryProps): react_jsx_runtime0.JSX.Element;
|
|
124
|
-
//#endregion
|
|
125
125
|
export { AsyncBoundary, type AsyncBoundaryProps, ErrorBoundary, type ErrorBoundaryFallbackProps, type ErrorBoundaryProps, FeatureErrorBoundary, type FeatureErrorBoundaryProps, FullPageErrorFallback, InlineErrorFallback };
|
package/dist/client/error.mjs
CHANGED
|
@@ -1,12 +1,46 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { t as cn } from "../utils-DQ5SCVoW.mjs";
|
|
4
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
4
|
import { Suspense } from "react";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
import { AlertCircle, Home, RefreshCw } from "lucide-react";
|
|
7
7
|
import { Button } from "@/components/ui/button";
|
|
8
8
|
import { ErrorBoundary as ErrorBoundary$1 } from "react-error-boundary";
|
|
9
9
|
|
|
10
|
+
//#region src/components/async-boundary.tsx
|
|
11
|
+
/**
|
|
12
|
+
* AsyncBoundary — Suspense + ErrorBoundary combined.
|
|
13
|
+
*
|
|
14
|
+
* If `errorFallback` is provided, wraps in ErrorBoundary from react-error-boundary.
|
|
15
|
+
* Otherwise, renders Suspense only.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```tsx
|
|
19
|
+
* import { AsyncBoundary, InlineErrorFallback } from "@classytic/fluid/client";
|
|
20
|
+
*
|
|
21
|
+
* <AsyncBoundary
|
|
22
|
+
* fallback={<SkeletonTable rows={5} />}
|
|
23
|
+
* errorFallback={InlineErrorFallback}
|
|
24
|
+
* >
|
|
25
|
+
* <DataFetchingComponent />
|
|
26
|
+
* </AsyncBoundary>
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
function AsyncBoundary({ fallback, errorFallback: ErrorFallback, onError, onReset, children }) {
|
|
30
|
+
const suspenseWrapped = /* @__PURE__ */ jsx(Suspense, {
|
|
31
|
+
fallback: fallback ?? null,
|
|
32
|
+
children
|
|
33
|
+
});
|
|
34
|
+
if (!ErrorFallback) return suspenseWrapped;
|
|
35
|
+
return /* @__PURE__ */ jsx(ErrorBoundary$1, {
|
|
36
|
+
FallbackComponent: ErrorFallback,
|
|
37
|
+
onError,
|
|
38
|
+
onReset,
|
|
39
|
+
children: suspenseWrapped
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
//#endregion
|
|
10
44
|
//#region src/components/error-boundary.tsx
|
|
11
45
|
/**
|
|
12
46
|
* Full-page error fallback with retry and go-home buttons.
|
|
@@ -128,39 +162,5 @@ function FeatureErrorBoundary({ featureName = "Feature", onError, onReset, child
|
|
|
128
162
|
});
|
|
129
163
|
}
|
|
130
164
|
|
|
131
|
-
//#endregion
|
|
132
|
-
//#region src/components/async-boundary.tsx
|
|
133
|
-
/**
|
|
134
|
-
* AsyncBoundary — Suspense + ErrorBoundary combined.
|
|
135
|
-
*
|
|
136
|
-
* If `errorFallback` is provided, wraps in ErrorBoundary from react-error-boundary.
|
|
137
|
-
* Otherwise, renders Suspense only.
|
|
138
|
-
*
|
|
139
|
-
* @example
|
|
140
|
-
* ```tsx
|
|
141
|
-
* import { AsyncBoundary, InlineErrorFallback } from "@classytic/fluid/client";
|
|
142
|
-
*
|
|
143
|
-
* <AsyncBoundary
|
|
144
|
-
* fallback={<SkeletonTable rows={5} />}
|
|
145
|
-
* errorFallback={InlineErrorFallback}
|
|
146
|
-
* >
|
|
147
|
-
* <DataFetchingComponent />
|
|
148
|
-
* </AsyncBoundary>
|
|
149
|
-
* ```
|
|
150
|
-
*/
|
|
151
|
-
function AsyncBoundary({ fallback, errorFallback: ErrorFallback, onError, onReset, children }) {
|
|
152
|
-
const suspenseWrapped = /* @__PURE__ */ jsx(Suspense, {
|
|
153
|
-
fallback: fallback ?? null,
|
|
154
|
-
children
|
|
155
|
-
});
|
|
156
|
-
if (!ErrorFallback) return suspenseWrapped;
|
|
157
|
-
return /* @__PURE__ */ jsx(ErrorBoundary$1, {
|
|
158
|
-
FallbackComponent: ErrorFallback,
|
|
159
|
-
onError,
|
|
160
|
-
onReset,
|
|
161
|
-
children: suspenseWrapped
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
|
|
165
165
|
//#endregion
|
|
166
166
|
export { AsyncBoundary, ErrorBoundary, FeatureErrorBoundary, FullPageErrorFallback, InlineErrorFallback };
|
|
@@ -1,6 +1,25 @@
|
|
|
1
|
-
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
2
1
|
import { ReactNode } from "react";
|
|
2
|
+
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
3
3
|
|
|
4
|
+
//#region src/components/gallery/gallery-dots.d.ts
|
|
5
|
+
interface GalleryDotsProps {
|
|
6
|
+
/** Show on desktop (default: false — dots are usually mobile-only) */
|
|
7
|
+
showOnDesktop?: boolean;
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
declare function GalleryDots({
|
|
11
|
+
showOnDesktop,
|
|
12
|
+
className
|
|
13
|
+
}: GalleryDotsProps): react_jsx_runtime0.JSX.Element | null;
|
|
14
|
+
//#endregion
|
|
15
|
+
//#region src/components/gallery/gallery-lightbox.d.ts
|
|
16
|
+
interface GalleryLightboxProps {
|
|
17
|
+
className?: string;
|
|
18
|
+
}
|
|
19
|
+
declare function GalleryLightbox({
|
|
20
|
+
className
|
|
21
|
+
}: GalleryLightboxProps): react_jsx_runtime0.JSX.Element | null;
|
|
22
|
+
//#endregion
|
|
4
23
|
//#region src/components/gallery/types.d.ts
|
|
5
24
|
interface GalleryImage {
|
|
6
25
|
src: string;
|
|
@@ -60,6 +79,19 @@ declare function GalleryMain({
|
|
|
60
79
|
className
|
|
61
80
|
}: GalleryMainProps): react_jsx_runtime0.JSX.Element;
|
|
62
81
|
//#endregion
|
|
82
|
+
//#region src/components/gallery/gallery-nav.d.ts
|
|
83
|
+
interface GalleryNavProps {
|
|
84
|
+
/** Which direction this button navigates */
|
|
85
|
+
direction: "prev" | "next";
|
|
86
|
+
className?: string;
|
|
87
|
+
children?: React.ReactNode;
|
|
88
|
+
}
|
|
89
|
+
declare function GalleryNav({
|
|
90
|
+
direction,
|
|
91
|
+
className,
|
|
92
|
+
children
|
|
93
|
+
}: GalleryNavProps): react_jsx_runtime0.JSX.Element | null;
|
|
94
|
+
//#endregion
|
|
63
95
|
//#region src/components/gallery/gallery-thumbnails.d.ts
|
|
64
96
|
interface GalleryThumbnailsProps {
|
|
65
97
|
/** Show on mobile (default: true) */
|
|
@@ -77,38 +109,6 @@ declare function GalleryThumbnails({
|
|
|
77
109
|
className
|
|
78
110
|
}: GalleryThumbnailsProps): react_jsx_runtime0.JSX.Element | null;
|
|
79
111
|
//#endregion
|
|
80
|
-
//#region src/components/gallery/gallery-dots.d.ts
|
|
81
|
-
interface GalleryDotsProps {
|
|
82
|
-
/** Show on desktop (default: false — dots are usually mobile-only) */
|
|
83
|
-
showOnDesktop?: boolean;
|
|
84
|
-
className?: string;
|
|
85
|
-
}
|
|
86
|
-
declare function GalleryDots({
|
|
87
|
-
showOnDesktop,
|
|
88
|
-
className
|
|
89
|
-
}: GalleryDotsProps): react_jsx_runtime0.JSX.Element | null;
|
|
90
|
-
//#endregion
|
|
91
|
-
//#region src/components/gallery/gallery-lightbox.d.ts
|
|
92
|
-
interface GalleryLightboxProps {
|
|
93
|
-
className?: string;
|
|
94
|
-
}
|
|
95
|
-
declare function GalleryLightbox({
|
|
96
|
-
className
|
|
97
|
-
}: GalleryLightboxProps): react_jsx_runtime0.JSX.Element | null;
|
|
98
|
-
//#endregion
|
|
99
|
-
//#region src/components/gallery/gallery-nav.d.ts
|
|
100
|
-
interface GalleryNavProps {
|
|
101
|
-
/** Which direction this button navigates */
|
|
102
|
-
direction: "prev" | "next";
|
|
103
|
-
className?: string;
|
|
104
|
-
children?: React.ReactNode;
|
|
105
|
-
}
|
|
106
|
-
declare function GalleryNav({
|
|
107
|
-
direction,
|
|
108
|
-
className,
|
|
109
|
-
children
|
|
110
|
-
}: GalleryNavProps): react_jsx_runtime0.JSX.Element | null;
|
|
111
|
-
//#endregion
|
|
112
112
|
//#region src/components/gallery/index.d.ts
|
|
113
113
|
interface ImageGalleryRootProps {
|
|
114
114
|
children: ReactNode;
|
package/dist/client/gallery.mjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { t as cn } from "../utils-DQ5SCVoW.mjs";
|
|
4
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
5
4
|
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
|
|
5
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
import { ChevronLeft, ChevronRight, RotateCcw, X, ZoomIn, ZoomOut } from "lucide-react";
|
|
7
7
|
import Image from "next/image";
|
|
8
8
|
|
|
@@ -63,130 +63,6 @@ function GalleryProvider({ children, images, defaultIndex = 0, classNames, title
|
|
|
63
63
|
});
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
//#endregion
|
|
67
|
-
//#region src/components/gallery/gallery-main.tsx
|
|
68
|
-
function GalleryMain({ children, badges, showNav = true, aspectRatio = "aspect-[4/5]", className }) {
|
|
69
|
-
const { images, selectedIndex, setLightboxOpen, goToNext, goToPrevious, classNames, title } = useGallery();
|
|
70
|
-
const [imagesLoaded, setImagesLoaded] = useState(new Set([0]));
|
|
71
|
-
const [touchStart, setTouchStart] = useState(null);
|
|
72
|
-
const [touchEnd, setTouchEnd] = useState(null);
|
|
73
|
-
const sliderRef = useRef(null);
|
|
74
|
-
const minSwipeDistance = 50;
|
|
75
|
-
useEffect(() => {
|
|
76
|
-
images.forEach((img, index) => {
|
|
77
|
-
if (index === 0) return;
|
|
78
|
-
const preloadImg = new window.Image();
|
|
79
|
-
preloadImg.src = img.src;
|
|
80
|
-
preloadImg.onload = () => {
|
|
81
|
-
setImagesLoaded((prev) => new Set([...prev, index]));
|
|
82
|
-
};
|
|
83
|
-
});
|
|
84
|
-
}, [images]);
|
|
85
|
-
const onTouchStart = useCallback((e) => {
|
|
86
|
-
setTouchEnd(null);
|
|
87
|
-
setTouchStart(e.targetTouches[0].clientX);
|
|
88
|
-
}, []);
|
|
89
|
-
const onTouchMove = useCallback((e) => {
|
|
90
|
-
setTouchEnd(e.targetTouches[0].clientX);
|
|
91
|
-
}, []);
|
|
92
|
-
const onTouchEnd = useCallback(() => {
|
|
93
|
-
if (!touchStart || !touchEnd) return;
|
|
94
|
-
const distance = touchStart - touchEnd;
|
|
95
|
-
if (distance > minSwipeDistance) goToNext();
|
|
96
|
-
if (distance < -minSwipeDistance) goToPrevious();
|
|
97
|
-
}, [
|
|
98
|
-
touchStart,
|
|
99
|
-
touchEnd,
|
|
100
|
-
goToNext,
|
|
101
|
-
goToPrevious
|
|
102
|
-
]);
|
|
103
|
-
const handleImageLoad = useCallback((index) => {
|
|
104
|
-
setImagesLoaded((prev) => new Set([...prev, index]));
|
|
105
|
-
}, []);
|
|
106
|
-
return /* @__PURE__ */ jsx("div", {
|
|
107
|
-
className: cn("relative", className),
|
|
108
|
-
children: /* @__PURE__ */ jsxs("div", {
|
|
109
|
-
ref: sliderRef,
|
|
110
|
-
className: cn(aspectRatio, "bg-muted overflow-hidden relative rounded-lg", classNames?.main),
|
|
111
|
-
onTouchStart,
|
|
112
|
-
onTouchMove,
|
|
113
|
-
onTouchEnd,
|
|
114
|
-
children: [
|
|
115
|
-
/* @__PURE__ */ jsx("div", {
|
|
116
|
-
className: cn("absolute inset-0 flex transition-transform duration-300 ease-out", classNames?.slider),
|
|
117
|
-
style: { transform: `translateX(-${selectedIndex * 100}%)` },
|
|
118
|
-
children: images.map((img, index) => /* @__PURE__ */ jsxs("div", {
|
|
119
|
-
className: "w-full h-full shrink-0 relative cursor-zoom-in",
|
|
120
|
-
onClick: () => setLightboxOpen(true),
|
|
121
|
-
children: [/* @__PURE__ */ jsx(Image, {
|
|
122
|
-
src: img.src,
|
|
123
|
-
alt: img.alt || `${title || "Gallery"} - Image ${index + 1}`,
|
|
124
|
-
fill: true,
|
|
125
|
-
className: cn("object-cover transition-opacity duration-300", imagesLoaded.has(index) ? "opacity-100" : "opacity-0", classNames?.mainImage),
|
|
126
|
-
sizes: "(max-width: 768px) 100vw, 50vw",
|
|
127
|
-
priority: index === 0,
|
|
128
|
-
onLoad: () => handleImageLoad(index)
|
|
129
|
-
}), !imagesLoaded.has(index) && /* @__PURE__ */ jsx("div", {
|
|
130
|
-
className: "absolute inset-0 flex items-center justify-center bg-muted",
|
|
131
|
-
children: /* @__PURE__ */ jsx("div", { className: "w-8 h-8 border-2 border-muted-foreground/20 border-t-muted-foreground rounded-full animate-spin" })
|
|
132
|
-
})]
|
|
133
|
-
}, index))
|
|
134
|
-
}),
|
|
135
|
-
badges && badges.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
136
|
-
className: cn("absolute top-4 left-4 flex flex-col gap-2 z-10", classNames?.badges),
|
|
137
|
-
children: badges.map((badge, index) => /* @__PURE__ */ jsx("span", {
|
|
138
|
-
className: cn("px-3 py-1 text-xs font-medium uppercase tracking-wider", classNames?.badge, badge.className),
|
|
139
|
-
children: badge.label
|
|
140
|
-
}, index))
|
|
141
|
-
}),
|
|
142
|
-
showNav && images.length > 1 && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("button", {
|
|
143
|
-
type: "button",
|
|
144
|
-
onClick: (e) => {
|
|
145
|
-
e.stopPropagation();
|
|
146
|
-
goToPrevious();
|
|
147
|
-
},
|
|
148
|
-
className: cn("hidden sm:flex absolute left-3 top-1/2 -translate-y-1/2 z-10", "w-10 h-10 items-center justify-center rounded-full", "bg-background/80 backdrop-blur-sm shadow-md hover:bg-background transition-colors", classNames?.nav, classNames?.navPrev),
|
|
149
|
-
"aria-label": "Previous image",
|
|
150
|
-
children: /* @__PURE__ */ jsx(ChevronLeft, { className: "h-5 w-5" })
|
|
151
|
-
}), /* @__PURE__ */ jsx("button", {
|
|
152
|
-
type: "button",
|
|
153
|
-
onClick: (e) => {
|
|
154
|
-
e.stopPropagation();
|
|
155
|
-
goToNext();
|
|
156
|
-
},
|
|
157
|
-
className: cn("hidden sm:flex absolute right-3 top-1/2 -translate-y-1/2 z-10", "w-10 h-10 items-center justify-center rounded-full", "bg-background/80 backdrop-blur-sm shadow-md hover:bg-background transition-colors", classNames?.nav, classNames?.navNext),
|
|
158
|
-
"aria-label": "Next image",
|
|
159
|
-
children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-5 w-5" })
|
|
160
|
-
})] }),
|
|
161
|
-
children
|
|
162
|
-
]
|
|
163
|
-
})
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
//#endregion
|
|
168
|
-
//#region src/components/gallery/gallery-thumbnails.tsx
|
|
169
|
-
function GalleryThumbnails({ showOnMobile = true, orientation = "horizontal", sizeClassName = "w-16 h-20 sm:w-20 sm:h-24", className }) {
|
|
170
|
-
const { images, selectedIndex, setSelectedIndex, classNames, title } = useGallery();
|
|
171
|
-
if (images.length <= 1) return null;
|
|
172
|
-
return /* @__PURE__ */ jsx("div", {
|
|
173
|
-
className: cn("flex gap-2 sm:gap-3 scrollbar-hide", orientation === "vertical" ? "flex-col overflow-y-auto pr-2" : "overflow-x-auto pb-2", !showOnMobile && "hidden sm:flex", classNames?.thumbnails, className),
|
|
174
|
-
children: images.map((img, index) => /* @__PURE__ */ jsx("button", {
|
|
175
|
-
type: "button",
|
|
176
|
-
onClick: () => setSelectedIndex(index),
|
|
177
|
-
className: cn("bg-muted overflow-hidden border-2 transition-all duration-200 shrink-0 rounded-md relative", sizeClassName, selectedIndex === index ? cn("border-foreground", classNames?.thumbnailActive) : cn("border-transparent opacity-60 hover:opacity-100", classNames?.thumbnail)),
|
|
178
|
-
"aria-label": `View image ${index + 1}`,
|
|
179
|
-
children: /* @__PURE__ */ jsx(Image, {
|
|
180
|
-
src: img.thumbnail || img.src,
|
|
181
|
-
alt: img.alt || `${title || "Gallery"} thumbnail ${index + 1}`,
|
|
182
|
-
fill: true,
|
|
183
|
-
className: "object-cover",
|
|
184
|
-
sizes: "80px"
|
|
185
|
-
})
|
|
186
|
-
}, index))
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
|
|
190
66
|
//#endregion
|
|
191
67
|
//#region src/components/gallery/gallery-dots.tsx
|
|
192
68
|
function GalleryDots({ showOnDesktop = false, className }) {
|
|
@@ -198,7 +74,8 @@ function GalleryDots({ showOnDesktop = false, className }) {
|
|
|
198
74
|
type: "button",
|
|
199
75
|
onClick: () => setSelectedIndex(index),
|
|
200
76
|
className: cn("h-2 rounded-full transition-all duration-300", selectedIndex === index ? cn("bg-foreground w-6", classNames?.dotActive) : cn("bg-muted-foreground/30 hover:bg-muted-foreground/50 w-2", classNames?.dot)),
|
|
201
|
-
"aria-label": `Go to image ${index + 1}
|
|
77
|
+
"aria-label": `Go to image ${index + 1}`,
|
|
78
|
+
"aria-current": selectedIndex === index ? "true" : void 0
|
|
202
79
|
}, index))
|
|
203
80
|
});
|
|
204
81
|
}
|
|
@@ -436,7 +313,7 @@ function GalleryLightbox({ className }) {
|
|
|
436
313
|
})
|
|
437
314
|
})]
|
|
438
315
|
}),
|
|
439
|
-
images.length > 1 && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("button", {
|
|
316
|
+
images.length > 1 && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("button", {
|
|
440
317
|
type: "button",
|
|
441
318
|
onClick: goToPrevious,
|
|
442
319
|
className: "absolute left-4 top-1/2 -translate-y-1/2 z-50 p-3 rounded-full bg-white/10 hover:bg-white/20 transition-colors",
|
|
@@ -475,6 +352,107 @@ function GalleryLightbox({ className }) {
|
|
|
475
352
|
});
|
|
476
353
|
}
|
|
477
354
|
|
|
355
|
+
//#endregion
|
|
356
|
+
//#region src/components/gallery/gallery-main.tsx
|
|
357
|
+
function GalleryMain({ children, badges, showNav = true, aspectRatio = "aspect-[4/5]", className }) {
|
|
358
|
+
const { images, selectedIndex, setLightboxOpen, goToNext, goToPrevious, classNames, title } = useGallery();
|
|
359
|
+
const [imagesLoaded, setImagesLoaded] = useState(new Set([0]));
|
|
360
|
+
const [touchStart, setTouchStart] = useState(null);
|
|
361
|
+
const [touchEnd, setTouchEnd] = useState(null);
|
|
362
|
+
const sliderRef = useRef(null);
|
|
363
|
+
const minSwipeDistance = 50;
|
|
364
|
+
useEffect(() => {
|
|
365
|
+
images.forEach((img, index) => {
|
|
366
|
+
if (index === 0) return;
|
|
367
|
+
const preloadImg = new window.Image();
|
|
368
|
+
preloadImg.src = img.src;
|
|
369
|
+
preloadImg.onload = () => {
|
|
370
|
+
setImagesLoaded((prev) => new Set([...prev, index]));
|
|
371
|
+
};
|
|
372
|
+
});
|
|
373
|
+
}, [images]);
|
|
374
|
+
const onTouchStart = useCallback((e) => {
|
|
375
|
+
setTouchEnd(null);
|
|
376
|
+
setTouchStart(e.targetTouches[0].clientX);
|
|
377
|
+
}, []);
|
|
378
|
+
const onTouchMove = useCallback((e) => {
|
|
379
|
+
setTouchEnd(e.targetTouches[0].clientX);
|
|
380
|
+
}, []);
|
|
381
|
+
const onTouchEnd = useCallback(() => {
|
|
382
|
+
if (!touchStart || !touchEnd) return;
|
|
383
|
+
const distance = touchStart - touchEnd;
|
|
384
|
+
if (distance > minSwipeDistance) goToNext();
|
|
385
|
+
if (distance < -minSwipeDistance) goToPrevious();
|
|
386
|
+
}, [
|
|
387
|
+
touchStart,
|
|
388
|
+
touchEnd,
|
|
389
|
+
goToNext,
|
|
390
|
+
goToPrevious
|
|
391
|
+
]);
|
|
392
|
+
const handleImageLoad = useCallback((index) => {
|
|
393
|
+
setImagesLoaded((prev) => new Set([...prev, index]));
|
|
394
|
+
}, []);
|
|
395
|
+
return /* @__PURE__ */ jsx("div", {
|
|
396
|
+
className: cn("relative", className),
|
|
397
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
398
|
+
ref: sliderRef,
|
|
399
|
+
className: cn(aspectRatio, "bg-muted overflow-hidden relative rounded-lg", classNames?.main),
|
|
400
|
+
onTouchStart,
|
|
401
|
+
onTouchMove,
|
|
402
|
+
onTouchEnd,
|
|
403
|
+
children: [
|
|
404
|
+
/* @__PURE__ */ jsx("div", {
|
|
405
|
+
className: cn("absolute inset-0 flex transition-transform duration-300 ease-out", classNames?.slider),
|
|
406
|
+
style: { transform: `translateX(-${selectedIndex * 100}%)` },
|
|
407
|
+
children: images.map((img, index) => /* @__PURE__ */ jsxs("div", {
|
|
408
|
+
className: "w-full h-full shrink-0 relative cursor-zoom-in",
|
|
409
|
+
onClick: () => setLightboxOpen(true),
|
|
410
|
+
children: [/* @__PURE__ */ jsx(Image, {
|
|
411
|
+
src: img.src,
|
|
412
|
+
alt: img.alt || `${title || "Gallery"} - Image ${index + 1}`,
|
|
413
|
+
fill: true,
|
|
414
|
+
className: cn("object-cover transition-opacity duration-300", imagesLoaded.has(index) ? "opacity-100" : "opacity-0", classNames?.mainImage),
|
|
415
|
+
sizes: "(max-width: 768px) 100vw, 50vw",
|
|
416
|
+
priority: index === 0,
|
|
417
|
+
onLoad: () => handleImageLoad(index)
|
|
418
|
+
}), !imagesLoaded.has(index) && /* @__PURE__ */ jsx("div", {
|
|
419
|
+
className: "absolute inset-0 flex items-center justify-center bg-muted",
|
|
420
|
+
children: /* @__PURE__ */ jsx("div", { className: "w-8 h-8 border-2 border-muted-foreground/20 border-t-muted-foreground rounded-full animate-spin" })
|
|
421
|
+
})]
|
|
422
|
+
}, index))
|
|
423
|
+
}),
|
|
424
|
+
badges && badges.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
425
|
+
className: cn("absolute top-4 left-4 flex flex-col gap-2 z-10", classNames?.badges),
|
|
426
|
+
children: badges.map((badge, index) => /* @__PURE__ */ jsx("span", {
|
|
427
|
+
className: cn("px-3 py-1 text-xs font-medium uppercase tracking-wider", classNames?.badge, badge.className),
|
|
428
|
+
children: badge.label
|
|
429
|
+
}, index))
|
|
430
|
+
}),
|
|
431
|
+
showNav && images.length > 1 && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("button", {
|
|
432
|
+
type: "button",
|
|
433
|
+
onClick: (e) => {
|
|
434
|
+
e.stopPropagation();
|
|
435
|
+
goToPrevious();
|
|
436
|
+
},
|
|
437
|
+
className: cn("hidden sm:flex absolute left-3 top-1/2 -translate-y-1/2 z-10", "w-10 h-10 items-center justify-center rounded-full", "bg-background/80 backdrop-blur-sm shadow-md hover:bg-background transition-colors", classNames?.nav, classNames?.navPrev),
|
|
438
|
+
"aria-label": "Previous image",
|
|
439
|
+
children: /* @__PURE__ */ jsx(ChevronLeft, { className: "h-5 w-5" })
|
|
440
|
+
}), /* @__PURE__ */ jsx("button", {
|
|
441
|
+
type: "button",
|
|
442
|
+
onClick: (e) => {
|
|
443
|
+
e.stopPropagation();
|
|
444
|
+
goToNext();
|
|
445
|
+
},
|
|
446
|
+
className: cn("hidden sm:flex absolute right-3 top-1/2 -translate-y-1/2 z-10", "w-10 h-10 items-center justify-center rounded-full", "bg-background/80 backdrop-blur-sm shadow-md hover:bg-background transition-colors", classNames?.nav, classNames?.navNext),
|
|
447
|
+
"aria-label": "Next image",
|
|
448
|
+
children: /* @__PURE__ */ jsx(ChevronRight, { className: "h-5 w-5" })
|
|
449
|
+
})] }),
|
|
450
|
+
children
|
|
451
|
+
]
|
|
452
|
+
})
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
|
|
478
456
|
//#endregion
|
|
479
457
|
//#region src/components/gallery/gallery-nav.tsx
|
|
480
458
|
function GalleryNav({ direction, className, children }) {
|
|
@@ -490,6 +468,29 @@ function GalleryNav({ direction, className, children }) {
|
|
|
490
468
|
});
|
|
491
469
|
}
|
|
492
470
|
|
|
471
|
+
//#endregion
|
|
472
|
+
//#region src/components/gallery/gallery-thumbnails.tsx
|
|
473
|
+
function GalleryThumbnails({ showOnMobile = true, orientation = "horizontal", sizeClassName = "w-16 h-20 sm:w-20 sm:h-24", className }) {
|
|
474
|
+
const { images, selectedIndex, setSelectedIndex, classNames, title } = useGallery();
|
|
475
|
+
if (images.length <= 1) return null;
|
|
476
|
+
return /* @__PURE__ */ jsx("div", {
|
|
477
|
+
className: cn("flex gap-2 sm:gap-3 scrollbar-hide", orientation === "vertical" ? "flex-col overflow-y-auto pr-2" : "overflow-x-auto pb-2", !showOnMobile && "hidden sm:flex", classNames?.thumbnails, className),
|
|
478
|
+
children: images.map((img, index) => /* @__PURE__ */ jsx("button", {
|
|
479
|
+
type: "button",
|
|
480
|
+
onClick: () => setSelectedIndex(index),
|
|
481
|
+
className: cn("bg-muted overflow-hidden border-2 transition-all duration-200 shrink-0 rounded-md relative", sizeClassName, selectedIndex === index ? cn("border-foreground", classNames?.thumbnailActive) : cn("border-transparent opacity-60 hover:opacity-100", classNames?.thumbnail)),
|
|
482
|
+
"aria-label": `View image ${index + 1}`,
|
|
483
|
+
children: /* @__PURE__ */ jsx(Image, {
|
|
484
|
+
src: img.thumbnail || img.src,
|
|
485
|
+
alt: img.alt || `${title || "Gallery"} thumbnail ${index + 1}`,
|
|
486
|
+
fill: true,
|
|
487
|
+
className: "object-cover",
|
|
488
|
+
sizes: "80px"
|
|
489
|
+
})
|
|
490
|
+
}, index))
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
|
|
493
494
|
//#endregion
|
|
494
495
|
//#region src/components/gallery/index.tsx
|
|
495
496
|
function ImageGalleryRoot({ children, images, defaultIndex = 0, classNames, title, onIndexChange, className }) {
|
package/dist/client/hooks.d.mts
CHANGED
|
@@ -1,49 +1,24 @@
|
|
|
1
|
-
import { n as UseBaseSearchReturn, r as useBaseSearch, t as UseBaseSearchConfig } from "../use-base-search-
|
|
2
|
-
import { n as useKeyboardShortcut, t as UseKeyboardShortcutOptions } from "../use-keyboard-shortcut-
|
|
1
|
+
import { n as UseBaseSearchReturn, r as useBaseSearch, t as UseBaseSearchConfig } from "../use-base-search-DFC4QKYU.mjs";
|
|
2
|
+
import { n as useKeyboardShortcut, t as UseKeyboardShortcutOptions } from "../use-keyboard-shortcut-Q4CSPzSI.mjs";
|
|
3
3
|
import { RefObject } from "react";
|
|
4
4
|
|
|
5
|
-
//#region src/hooks/
|
|
6
|
-
|
|
7
|
-
//#endregion
|
|
8
|
-
//#region src/hooks/use-media-query.d.ts
|
|
9
|
-
declare function useMediaQuery(query: string, defaultValue?: boolean): boolean;
|
|
10
|
-
//#endregion
|
|
11
|
-
//#region src/hooks/use-scroll-detection.d.ts
|
|
12
|
-
declare const useScrollDetection: (ref: RefObject<HTMLDivElement | null>, delay?: number) => {
|
|
13
|
-
checkScroll: () => void;
|
|
14
|
-
canScrollLeft: boolean;
|
|
15
|
-
canScrollRight: boolean;
|
|
16
|
-
isScrollable: boolean;
|
|
17
|
-
};
|
|
18
|
-
//#endregion
|
|
19
|
-
//#region src/hooks/use-debounce.d.ts
|
|
20
|
-
/**
|
|
21
|
-
* useDebounce — Returns a debounced version of the input value.
|
|
22
|
-
*
|
|
23
|
-
* @example
|
|
24
|
-
* ```tsx
|
|
25
|
-
* const [search, setSearch] = useState("");
|
|
26
|
-
* const debouncedSearch = useDebounce(search, 300);
|
|
27
|
-
*
|
|
28
|
-
* useEffect(() => {
|
|
29
|
-
* fetchResults(debouncedSearch);
|
|
30
|
-
* }, [debouncedSearch]);
|
|
31
|
-
* ```
|
|
32
|
-
*/
|
|
33
|
-
declare function useDebounce<T>(value: T, delay?: number): T;
|
|
5
|
+
//#region src/hooks/create-search-hook.d.ts
|
|
6
|
+
interface CreateSearchHookConfig extends UseBaseSearchConfig {}
|
|
34
7
|
/**
|
|
35
|
-
*
|
|
8
|
+
* Factory that pre-configures useBaseSearch with typed defaults.
|
|
36
9
|
*
|
|
37
10
|
* @example
|
|
38
|
-
* ```
|
|
39
|
-
* const
|
|
40
|
-
*
|
|
41
|
-
* },
|
|
11
|
+
* ```ts
|
|
12
|
+
* const useOrderSearch = createSearchHook({
|
|
13
|
+
* basePath: "/dashboard/orders",
|
|
14
|
+
* searchFields: { name: "Name", sku: "SKU", barcode: "Barcode" },
|
|
15
|
+
* });
|
|
42
16
|
*
|
|
43
|
-
*
|
|
17
|
+
* // In component:
|
|
18
|
+
* const search = useOrderSearch();
|
|
44
19
|
* ```
|
|
45
20
|
*/
|
|
46
|
-
declare function
|
|
21
|
+
declare function createSearchHook(config: CreateSearchHookConfig): () => UseBaseSearchReturn;
|
|
47
22
|
//#endregion
|
|
48
23
|
//#region src/hooks/use-copy-to-clipboard.d.ts
|
|
49
24
|
interface UseCopyToClipboardReturn {
|
|
@@ -72,6 +47,35 @@ interface UseCopyToClipboardReturn {
|
|
|
72
47
|
*/
|
|
73
48
|
declare function useCopyToClipboard(resetDelay?: number): UseCopyToClipboardReturn;
|
|
74
49
|
//#endregion
|
|
50
|
+
//#region src/hooks/use-debounce.d.ts
|
|
51
|
+
/**
|
|
52
|
+
* useDebounce — Returns a debounced version of the input value.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```tsx
|
|
56
|
+
* const [search, setSearch] = useState("");
|
|
57
|
+
* const debouncedSearch = useDebounce(search, 300);
|
|
58
|
+
*
|
|
59
|
+
* useEffect(() => {
|
|
60
|
+
* fetchResults(debouncedSearch);
|
|
61
|
+
* }, [debouncedSearch]);
|
|
62
|
+
* ```
|
|
63
|
+
*/
|
|
64
|
+
declare function useDebounce<T>(value: T, delay?: number): T;
|
|
65
|
+
/**
|
|
66
|
+
* useDebouncedCallback — Returns a debounced version of a callback function.
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```tsx
|
|
70
|
+
* const debouncedSave = useDebouncedCallback((value: string) => {
|
|
71
|
+
* saveToApi(value);
|
|
72
|
+
* }, 500);
|
|
73
|
+
*
|
|
74
|
+
* <Input onChange={(e) => debouncedSave(e.target.value)} />
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
declare function useDebouncedCallback<T extends (...args: any[]) => any>(callback: T, delay?: number): (...args: Parameters<T>) => void;
|
|
78
|
+
//#endregion
|
|
75
79
|
//#region src/hooks/use-local-storage.d.ts
|
|
76
80
|
/**
|
|
77
81
|
* useLocalStorage — Persist state in localStorage with type safety and optional expiry.
|
|
@@ -92,6 +96,20 @@ declare function useCopyToClipboard(resetDelay?: number): UseCopyToClipboardRetu
|
|
|
92
96
|
*/
|
|
93
97
|
declare function useLocalStorage<T>(key: string, initialValue: T, ttl?: number): [T, (value: T | ((prev: T) => T)) => void, () => void];
|
|
94
98
|
//#endregion
|
|
99
|
+
//#region src/hooks/use-media-query.d.ts
|
|
100
|
+
declare function useMediaQuery(query: string, defaultValue?: boolean): boolean;
|
|
101
|
+
//#endregion
|
|
102
|
+
//#region src/hooks/use-mobile.d.ts
|
|
103
|
+
declare function useIsMobile(): boolean;
|
|
104
|
+
//#endregion
|
|
105
|
+
//#region src/hooks/use-scroll-detection.d.ts
|
|
106
|
+
declare const useScrollDetection: (ref: RefObject<HTMLDivElement | null>, delay?: number) => {
|
|
107
|
+
checkScroll: () => void;
|
|
108
|
+
canScrollLeft: boolean;
|
|
109
|
+
canScrollRight: boolean;
|
|
110
|
+
isScrollable: boolean;
|
|
111
|
+
};
|
|
112
|
+
//#endregion
|
|
95
113
|
//#region src/lib/storage.d.ts
|
|
96
114
|
/**
|
|
97
115
|
* A utility module for handling localStorage operations with error handling and SSR safety
|
|
@@ -163,4 +181,4 @@ declare const storage: {
|
|
|
163
181
|
};
|
|
164
182
|
};
|
|
165
183
|
//#endregion
|
|
166
|
-
export { TTL, type UseBaseSearchConfig, type UseBaseSearchReturn, type UseCopyToClipboardReturn, type UseKeyboardShortcutOptions, clearStorage, generateUUID, getStorageItem, isStorageEmpty, removeStorageItem, setStorageItem, storage, useBaseSearch, useCopyToClipboard, useDebounce, useDebouncedCallback, useIsMobile, useKeyboardShortcut, useLocalStorage, useMediaQuery, useScrollDetection };
|
|
184
|
+
export { type CreateSearchHookConfig, TTL, type UseBaseSearchConfig, type UseBaseSearchReturn, type UseCopyToClipboardReturn, type UseKeyboardShortcutOptions, clearStorage, createSearchHook, generateUUID, getStorageItem, isStorageEmpty, removeStorageItem, setStorageItem, storage, useBaseSearch, useCopyToClipboard, useDebounce, useDebouncedCallback, useIsMobile, useKeyboardShortcut, useLocalStorage, useMediaQuery, useScrollDetection };
|