asterui 0.12.66 → 0.12.67

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.
@@ -1,99 +1,114 @@
1
- import { jsxs as v, Fragment as H, jsx as a } from "react/jsx-runtime";
2
- import { forwardRef as T, useState as l, useEffect as W, useCallback as i } from "react";
3
- const R = "btn", V = "btn-circle", q = "btn-sm", A = T(
1
+ import { jsxs as x, Fragment as H, jsx as t } from "react/jsx-runtime";
2
+ import { forwardRef as T, useState as u, useRef as V, useEffect as B, useCallback as l } from "react";
3
+ const q = "btn", A = "btn-circle", G = "btn-sm", I = T(
4
4
  ({
5
- src: c,
6
- alt: s = "",
7
- fallback: g,
8
- placeholder: y,
9
- preview: n = !0,
10
- width: d,
11
- height: m,
12
- className: j = "",
13
- onLoad: k,
14
- onError: w,
5
+ src: m,
6
+ alt: c = "",
7
+ fallback: o,
8
+ placeholder: $,
9
+ preview: d = !0,
10
+ width: f,
11
+ height: h,
12
+ className: S = "",
13
+ onLoad: C,
14
+ onError: N,
15
15
  "data-testid": r = "image",
16
- ...L
17
- }, P) => {
18
- const [t, u] = l(!0), [o, f] = l(!1), [B, h] = l(!1), [S, x] = l(c), [$, C] = l(!1);
19
- W(() => {
20
- u(!0), f(!1), C(!1), x(c);
21
- }, [c]);
22
- const D = i(() => {
23
- u(!1), f(!1), k?.();
24
- }, [k]), E = i(() => {
25
- if (w?.(), g && !$) {
26
- C(!0), x(g), u(!0), f(!1);
16
+ ...D
17
+ }, g) => {
18
+ const [a, i] = u(!0), [s, n] = u(!1), [E, p] = u(!1), [j, b] = u(m), [v, w] = u(!1), L = V(null);
19
+ B(() => {
20
+ i(!0), n(!1), w(!1), b(m);
21
+ }, [m]), B(() => {
22
+ const e = L.current;
23
+ if (!(!e || !e.complete)) {
24
+ if (e.naturalWidth > 0) {
25
+ i(!1), n(!1);
26
+ return;
27
+ }
28
+ if (o && !v) {
29
+ w(!0), b(o), i(!0), n(!1);
30
+ return;
31
+ }
32
+ i(!1), n(!0);
33
+ }
34
+ }, [j, o, v]);
35
+ const F = l(() => {
36
+ i(!1), n(!1), C?.();
37
+ }, [C]), K = l(() => {
38
+ if (N?.(), o && !v) {
39
+ w(!0), b(o), i(!0), n(!1);
27
40
  return;
28
41
  }
29
- u(!1), f(!0);
30
- }, [g, $, w]), F = i(() => {
31
- n && !o && !t && h(!0);
32
- }, [n, o, t]), N = i(() => {
33
- h(!1);
34
- }, []), K = i(
42
+ i(!1), n(!0);
43
+ }, [o, v, N]), M = l(() => {
44
+ d && !s && !a && p(!0);
45
+ }, [d, s, a]), P = l(() => {
46
+ p(!1);
47
+ }, []), R = l(
35
48
  (e) => {
36
- n && !o && !t && (e.key === "Enter" || e.key === " ") && (e.preventDefault(), h(!0));
49
+ d && !s && !a && (e.key === "Enter" || e.key === " ") && (e.preventDefault(), p(!0));
37
50
  },
38
- [n, o, t]
39
- ), M = i((e) => {
40
- e.key === "Escape" && h(!1);
41
- }, []), p = () => {
51
+ [d, s, a]
52
+ ), W = l((e) => {
53
+ e.key === "Escape" && p(!1);
54
+ }, []), k = () => {
42
55
  const e = {};
43
- return d && (e.width = typeof d == "number" ? `${d}px` : d), m && (e.height = typeof m == "number" ? `${m}px` : m), e;
44
- }, b = n && !o && !t, z = [
45
- j,
46
- b ? "cursor-pointer hover:opacity-80 transition-opacity" : ""
56
+ return f && (e.width = typeof f == "number" ? `${f}px` : f), h && (e.height = typeof h == "number" ? `${h}px` : h), e;
57
+ }, y = d && !s && !a, z = [
58
+ S,
59
+ y ? "cursor-pointer hover:opacity-80 transition-opacity" : ""
47
60
  ].filter(Boolean).join(" ");
48
- return /* @__PURE__ */ v(H, { children: [
49
- /* @__PURE__ */ v(
61
+ return /* @__PURE__ */ x(H, { children: [
62
+ /* @__PURE__ */ x(
50
63
  "div",
51
64
  {
52
65
  className: "relative inline-block",
53
- style: p(),
66
+ style: k(),
54
67
  "data-testid": r,
55
- "data-state": t ? "loading" : o ? "error" : "loaded",
68
+ "data-state": a ? "loading" : s ? "error" : "loaded",
56
69
  children: [
57
- t && y && /* @__PURE__ */ a(
70
+ a && $ && /* @__PURE__ */ t(
58
71
  "div",
59
72
  {
60
73
  className: "absolute inset-0 flex items-center justify-center bg-base-200",
61
74
  "data-testid": `${r}-placeholder`,
62
- children: y
75
+ children: $
63
76
  }
64
77
  ),
65
- /* @__PURE__ */ a(
78
+ /* @__PURE__ */ t(
66
79
  "img",
67
80
  {
68
- ref: P,
69
- ...L,
70
- src: S,
71
- alt: s,
81
+ ref: (e) => {
82
+ L.current = e, typeof g == "function" ? g(e) : g && (g.current = e);
83
+ },
84
+ ...D,
85
+ src: j,
86
+ alt: c,
72
87
  className: z,
73
88
  style: {
74
- ...p(),
75
- opacity: t ? 0 : 1,
89
+ ...k(),
90
+ opacity: a ? 0 : 1,
76
91
  transition: "opacity 150ms ease"
77
92
  },
78
- onLoad: D,
79
- onError: E,
80
- onClick: F,
81
- onKeyDown: K,
82
- tabIndex: b ? 0 : void 0,
83
- role: b ? "button" : void 0,
84
- "aria-label": b ? `${s || "Image"} (click to preview)` : void 0,
93
+ onLoad: F,
94
+ onError: K,
95
+ onClick: M,
96
+ onKeyDown: R,
97
+ tabIndex: y ? 0 : void 0,
98
+ role: y ? "button" : void 0,
99
+ "aria-label": y ? `${c || "Image"} (click to preview)` : void 0,
85
100
  "data-testid": `${r}-img`
86
101
  }
87
102
  ),
88
- o && /* @__PURE__ */ a(
103
+ s && /* @__PURE__ */ t(
89
104
  "div",
90
105
  {
91
106
  className: "flex items-center justify-center bg-base-200 text-base-content/50",
92
- style: p(),
107
+ style: k(),
93
108
  "data-testid": `${r}-error`,
94
109
  role: "img",
95
- "aria-label": `Failed to load: ${s || "image"}`,
96
- children: /* @__PURE__ */ a(
110
+ "aria-label": `Failed to load: ${c || "image"}`,
111
+ children: /* @__PURE__ */ t(
97
112
  "svg",
98
113
  {
99
114
  className: "w-12 h-12",
@@ -101,7 +116,7 @@ const R = "btn", V = "btn-circle", q = "btn-sm", A = T(
101
116
  stroke: "currentColor",
102
117
  viewBox: "0 0 24 24",
103
118
  "aria-hidden": "true",
104
- children: /* @__PURE__ */ a(
119
+ children: /* @__PURE__ */ t(
105
120
  "path",
106
121
  {
107
122
  strokeLinecap: "round",
@@ -117,26 +132,26 @@ const R = "btn", V = "btn-circle", q = "btn-sm", A = T(
117
132
  ]
118
133
  }
119
134
  ),
120
- B && /* @__PURE__ */ a(
135
+ E && /* @__PURE__ */ t(
121
136
  "div",
122
137
  {
123
138
  className: "fixed inset-0 z-50 bg-black bg-opacity-80 flex items-center justify-center p-4",
124
- onClick: N,
125
- onKeyDown: M,
139
+ onClick: P,
140
+ onKeyDown: W,
126
141
  role: "dialog",
127
142
  "aria-modal": "true",
128
- "aria-label": `Preview: ${s || "Image"}`,
143
+ "aria-label": `Preview: ${c || "Image"}`,
129
144
  "data-testid": `${r}-preview`,
130
- children: /* @__PURE__ */ v("div", { className: "relative max-w-full max-h-full", children: [
131
- /* @__PURE__ */ a(
145
+ children: /* @__PURE__ */ x("div", { className: "relative max-w-full max-h-full", children: [
146
+ /* @__PURE__ */ t(
132
147
  "button",
133
148
  {
134
- className: `absolute top-4 right-4 ${R} ${V} ${q}`,
135
- onClick: N,
149
+ className: `absolute top-4 right-4 ${q} ${A} ${G}`,
150
+ onClick: P,
136
151
  "aria-label": "Close preview",
137
152
  autoFocus: !0,
138
153
  "data-testid": `${r}-preview-close`,
139
- children: /* @__PURE__ */ a(
154
+ children: /* @__PURE__ */ t(
140
155
  "svg",
141
156
  {
142
157
  className: "w-6 h-6",
@@ -144,7 +159,7 @@ const R = "btn", V = "btn-circle", q = "btn-sm", A = T(
144
159
  stroke: "currentColor",
145
160
  viewBox: "0 0 24 24",
146
161
  "aria-hidden": "true",
147
- children: /* @__PURE__ */ a(
162
+ children: /* @__PURE__ */ t(
148
163
  "path",
149
164
  {
150
165
  strokeLinecap: "round",
@@ -157,11 +172,11 @@ const R = "btn", V = "btn-circle", q = "btn-sm", A = T(
157
172
  )
158
173
  }
159
174
  ),
160
- /* @__PURE__ */ a(
175
+ /* @__PURE__ */ t(
161
176
  "img",
162
177
  {
163
- src: c,
164
- alt: s,
178
+ src: m,
179
+ alt: c,
165
180
  className: "max-w-full max-h-[90vh] object-contain",
166
181
  onClick: (e) => e.stopPropagation(),
167
182
  "data-testid": `${r}-preview-img`
@@ -173,8 +188,8 @@ const R = "btn", V = "btn-circle", q = "btn-sm", A = T(
173
188
  ] });
174
189
  }
175
190
  );
176
- A.displayName = "Image";
191
+ I.displayName = "Image";
177
192
  export {
178
- A as Image
193
+ I as Image
179
194
  };
180
195
  //# sourceMappingURL=Image.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Image.js","sources":["../../src/components/Image.tsx"],"sourcesContent":["import React, { useState, useEffect, forwardRef, useCallback } from 'react'\n\n// DaisyUI classes\nconst dBtn = 'btn'\nconst dBtnCircle = 'btn-circle'\nconst dBtnSm = 'btn-sm'\n\nexport interface ImageProps extends Omit<React.ImgHTMLAttributes<HTMLImageElement>, 'placeholder'> {\n /** Image source URL */\n src: string\n /** Alternative text for the image */\n alt?: string\n /** Fallback image URL when source fails to load */\n fallback?: string\n /** Placeholder content shown while loading */\n placeholder?: React.ReactNode\n /** Enable click to preview image in lightbox */\n preview?: boolean\n /** Image width */\n width?: string | number\n /** Image height */\n height?: string | number\n /** Additional CSS classes */\n className?: string\n /** Callback when image loads successfully */\n onLoad?: () => void\n /** Callback when image fails to load */\n onError?: () => void\n /** Test ID for the component */\n 'data-testid'?: string\n}\n\nexport const Image = forwardRef<HTMLImageElement, ImageProps>(\n (\n {\n src,\n alt = '',\n fallback,\n placeholder,\n preview = true,\n width,\n height,\n className = '',\n onLoad,\n onError,\n 'data-testid': testId = 'image',\n ...props\n },\n ref\n ) => {\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState(false)\n const [showPreview, setShowPreview] = useState(false)\n const [currentSrc, setCurrentSrc] = useState(src)\n const [hasTriedFallback, setHasTriedFallback] = useState(false)\n\n useEffect(() => {\n setLoading(true)\n setError(false)\n setHasTriedFallback(false)\n setCurrentSrc(src)\n }, [src])\n\n const handleLoad = useCallback(() => {\n setLoading(false)\n setError(false)\n onLoad?.()\n }, [onLoad])\n\n const handleError = useCallback(() => {\n onError?.()\n if (fallback && !hasTriedFallback) {\n setHasTriedFallback(true)\n setCurrentSrc(fallback)\n setLoading(true)\n setError(false)\n return\n }\n setLoading(false)\n setError(true)\n }, [fallback, hasTriedFallback, onError])\n\n const handleImageClick = useCallback(() => {\n if (preview && !error && !loading) {\n setShowPreview(true)\n }\n }, [preview, error, loading])\n\n const handleClosePreview = useCallback(() => {\n setShowPreview(false)\n }, [])\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (preview && !error && !loading && (e.key === 'Enter' || e.key === ' ')) {\n e.preventDefault()\n setShowPreview(true)\n }\n },\n [preview, error, loading]\n )\n\n const handlePreviewKeyDown = useCallback((e: React.KeyboardEvent) => {\n if (e.key === 'Escape') {\n setShowPreview(false)\n }\n }, [])\n\n const getStyle = (): React.CSSProperties => {\n const style: React.CSSProperties = {}\n if (width) {\n style.width = typeof width === 'number' ? `${width}px` : width\n }\n if (height) {\n style.height = typeof height === 'number' ? `${height}px` : height\n }\n return style\n }\n\n const isPreviewable = preview && !error && !loading\n const imageClasses = [\n className,\n isPreviewable ? 'cursor-pointer hover:opacity-80 transition-opacity' : '',\n ]\n .filter(Boolean)\n .join(' ')\n\n return (\n <>\n <div\n className=\"relative inline-block\"\n style={getStyle()}\n data-testid={testId}\n data-state={loading ? 'loading' : error ? 'error' : 'loaded'}\n >\n {loading && placeholder && (\n <div\n className=\"absolute inset-0 flex items-center justify-center bg-base-200\"\n data-testid={`${testId}-placeholder`}\n >\n {placeholder}\n </div>\n )}\n <img\n ref={ref}\n {...props}\n src={currentSrc}\n alt={alt}\n className={imageClasses}\n style={{\n ...getStyle(),\n opacity: loading ? 0 : 1,\n transition: 'opacity 150ms ease',\n }}\n onLoad={handleLoad}\n onError={handleError}\n onClick={handleImageClick}\n onKeyDown={handleKeyDown}\n tabIndex={isPreviewable ? 0 : undefined}\n role={isPreviewable ? 'button' : undefined}\n aria-label={isPreviewable ? `${alt || 'Image'} (click to preview)` : undefined}\n data-testid={`${testId}-img`}\n />\n {error && (\n <div\n className=\"flex items-center justify-center bg-base-200 text-base-content/50\"\n style={getStyle()}\n data-testid={`${testId}-error`}\n role=\"img\"\n aria-label={`Failed to load: ${alt || 'image'}`}\n >\n <svg\n className=\"w-12 h-12\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n aria-hidden=\"true\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z\"\n />\n </svg>\n </div>\n )}\n </div>\n\n {showPreview && (\n <div\n className=\"fixed inset-0 z-50 bg-black bg-opacity-80 flex items-center justify-center p-4\"\n onClick={handleClosePreview}\n onKeyDown={handlePreviewKeyDown}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={`Preview: ${alt || 'Image'}`}\n data-testid={`${testId}-preview`}\n >\n <div className=\"relative max-w-full max-h-full\">\n <button\n className={`absolute top-4 right-4 ${dBtn} ${dBtnCircle} ${dBtnSm}`}\n onClick={handleClosePreview}\n aria-label=\"Close preview\"\n autoFocus\n data-testid={`${testId}-preview-close`}\n >\n <svg\n className=\"w-6 h-6\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n aria-hidden=\"true\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </button>\n <img\n src={src}\n alt={alt}\n className=\"max-w-full max-h-[90vh] object-contain\"\n onClick={(e) => e.stopPropagation()}\n data-testid={`${testId}-preview-img`}\n />\n </div>\n </div>\n )}\n </>\n )\n }\n)\n\nImage.displayName = 'Image'\n"],"names":["dBtn","dBtnCircle","dBtnSm","Image","forwardRef","src","alt","fallback","placeholder","preview","width","height","className","onLoad","onError","testId","props","ref","loading","setLoading","useState","error","setError","showPreview","setShowPreview","currentSrc","setCurrentSrc","hasTriedFallback","setHasTriedFallback","useEffect","handleLoad","useCallback","handleError","handleImageClick","handleClosePreview","handleKeyDown","handlePreviewKeyDown","getStyle","style","isPreviewable","imageClasses","jsxs","Fragment","jsx"],"mappings":"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"}
1
+ {"version":3,"file":"Image.js","sources":["../../src/components/Image.tsx"],"sourcesContent":["import React, { useState, useEffect, forwardRef, useCallback, useRef } from 'react'\n\n// DaisyUI classes\nconst dBtn = 'btn'\nconst dBtnCircle = 'btn-circle'\nconst dBtnSm = 'btn-sm'\n\nexport interface ImageProps extends Omit<React.ImgHTMLAttributes<HTMLImageElement>, 'placeholder'> {\n /** Image source URL */\n src: string\n /** Alternative text for the image */\n alt?: string\n /** Fallback image URL when source fails to load */\n fallback?: string\n /** Placeholder content shown while loading */\n placeholder?: React.ReactNode\n /** Enable click to preview image in lightbox */\n preview?: boolean\n /** Image width */\n width?: string | number\n /** Image height */\n height?: string | number\n /** Additional CSS classes */\n className?: string\n /** Callback when image loads successfully */\n onLoad?: () => void\n /** Callback when image fails to load */\n onError?: () => void\n /** Test ID for the component */\n 'data-testid'?: string\n}\n\nexport const Image = forwardRef<HTMLImageElement, ImageProps>(\n (\n {\n src,\n alt = '',\n fallback,\n placeholder,\n preview = true,\n width,\n height,\n className = '',\n onLoad,\n onError,\n 'data-testid': testId = 'image',\n ...props\n },\n ref\n ) => {\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState(false)\n const [showPreview, setShowPreview] = useState(false)\n const [currentSrc, setCurrentSrc] = useState(src)\n const [hasTriedFallback, setHasTriedFallback] = useState(false)\n const imgRef = useRef<HTMLImageElement | null>(null)\n\n useEffect(() => {\n setLoading(true)\n setError(false)\n setHasTriedFallback(false)\n setCurrentSrc(src)\n }, [src])\n\n useEffect(() => {\n const img = imgRef.current\n if (!img || !img.complete) return\n\n if (img.naturalWidth > 0) {\n setLoading(false)\n setError(false)\n return\n }\n\n if (fallback && !hasTriedFallback) {\n setHasTriedFallback(true)\n setCurrentSrc(fallback)\n setLoading(true)\n setError(false)\n return\n }\n\n setLoading(false)\n setError(true)\n }, [currentSrc, fallback, hasTriedFallback])\n\n const handleLoad = useCallback(() => {\n setLoading(false)\n setError(false)\n onLoad?.()\n }, [onLoad])\n\n const handleError = useCallback(() => {\n onError?.()\n if (fallback && !hasTriedFallback) {\n setHasTriedFallback(true)\n setCurrentSrc(fallback)\n setLoading(true)\n setError(false)\n return\n }\n setLoading(false)\n setError(true)\n }, [fallback, hasTriedFallback, onError])\n\n const handleImageClick = useCallback(() => {\n if (preview && !error && !loading) {\n setShowPreview(true)\n }\n }, [preview, error, loading])\n\n const handleClosePreview = useCallback(() => {\n setShowPreview(false)\n }, [])\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (preview && !error && !loading && (e.key === 'Enter' || e.key === ' ')) {\n e.preventDefault()\n setShowPreview(true)\n }\n },\n [preview, error, loading]\n )\n\n const handlePreviewKeyDown = useCallback((e: React.KeyboardEvent) => {\n if (e.key === 'Escape') {\n setShowPreview(false)\n }\n }, [])\n\n const getStyle = (): React.CSSProperties => {\n const style: React.CSSProperties = {}\n if (width) {\n style.width = typeof width === 'number' ? `${width}px` : width\n }\n if (height) {\n style.height = typeof height === 'number' ? `${height}px` : height\n }\n return style\n }\n\n const isPreviewable = preview && !error && !loading\n const imageClasses = [\n className,\n isPreviewable ? 'cursor-pointer hover:opacity-80 transition-opacity' : '',\n ]\n .filter(Boolean)\n .join(' ')\n\n return (\n <>\n <div\n className=\"relative inline-block\"\n style={getStyle()}\n data-testid={testId}\n data-state={loading ? 'loading' : error ? 'error' : 'loaded'}\n >\n {loading && placeholder && (\n <div\n className=\"absolute inset-0 flex items-center justify-center bg-base-200\"\n data-testid={`${testId}-placeholder`}\n >\n {placeholder}\n </div>\n )}\n <img\n ref={(node) => {\n imgRef.current = node\n if (typeof ref === 'function') {\n ref(node)\n } else if (ref) {\n ref.current = node\n }\n }}\n {...props}\n src={currentSrc}\n alt={alt}\n className={imageClasses}\n style={{\n ...getStyle(),\n opacity: loading ? 0 : 1,\n transition: 'opacity 150ms ease',\n }}\n onLoad={handleLoad}\n onError={handleError}\n onClick={handleImageClick}\n onKeyDown={handleKeyDown}\n tabIndex={isPreviewable ? 0 : undefined}\n role={isPreviewable ? 'button' : undefined}\n aria-label={isPreviewable ? `${alt || 'Image'} (click to preview)` : undefined}\n data-testid={`${testId}-img`}\n />\n {error && (\n <div\n className=\"flex items-center justify-center bg-base-200 text-base-content/50\"\n style={getStyle()}\n data-testid={`${testId}-error`}\n role=\"img\"\n aria-label={`Failed to load: ${alt || 'image'}`}\n >\n <svg\n className=\"w-12 h-12\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n aria-hidden=\"true\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z\"\n />\n </svg>\n </div>\n )}\n </div>\n\n {showPreview && (\n <div\n className=\"fixed inset-0 z-50 bg-black bg-opacity-80 flex items-center justify-center p-4\"\n onClick={handleClosePreview}\n onKeyDown={handlePreviewKeyDown}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={`Preview: ${alt || 'Image'}`}\n data-testid={`${testId}-preview`}\n >\n <div className=\"relative max-w-full max-h-full\">\n <button\n className={`absolute top-4 right-4 ${dBtn} ${dBtnCircle} ${dBtnSm}`}\n onClick={handleClosePreview}\n aria-label=\"Close preview\"\n autoFocus\n data-testid={`${testId}-preview-close`}\n >\n <svg\n className=\"w-6 h-6\"\n fill=\"none\"\n stroke=\"currentColor\"\n viewBox=\"0 0 24 24\"\n aria-hidden=\"true\"\n >\n <path\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n d=\"M6 18L18 6M6 6l12 12\"\n />\n </svg>\n </button>\n <img\n src={src}\n alt={alt}\n className=\"max-w-full max-h-[90vh] object-contain\"\n onClick={(e) => e.stopPropagation()}\n data-testid={`${testId}-preview-img`}\n />\n </div>\n </div>\n )}\n </>\n )\n }\n)\n\nImage.displayName = 'Image'\n"],"names":["dBtn","dBtnCircle","dBtnSm","Image","forwardRef","src","alt","fallback","placeholder","preview","width","height","className","onLoad","onError","testId","props","ref","loading","setLoading","useState","error","setError","showPreview","setShowPreview","currentSrc","setCurrentSrc","hasTriedFallback","setHasTriedFallback","imgRef","useRef","useEffect","img","handleLoad","useCallback","handleError","handleImageClick","handleClosePreview","handleKeyDown","handlePreviewKeyDown","getStyle","style","isPreviewable","imageClasses","jsxs","Fragment","jsx","node"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "asterui",
3
- "version": "0.12.66",
3
+ "version": "0.12.67",
4
4
  "description": "React UI component library with DaisyUI",
5
5
  "homepage": "https://asterui.com",
6
6
  "repository": {