@seed-design/react-image 0.1.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.
@@ -0,0 +1,151 @@
1
+ 'use client';
2
+ import { jsx } from 'react/jsx-runtime';
3
+ import { composeRefs } from '@radix-ui/react-compose-refs';
4
+ import { useLayoutEffect } from '@radix-ui/react-use-layout-effect';
5
+ import { elementProps, imgProps, dataAttr, mergeProps } from '@seed-design/dom-utils';
6
+ import { Primitive } from '@seed-design/react-primitive';
7
+ import { useState, useRef, useMemo, useCallback, createContext, useContext, forwardRef } from 'react';
8
+ import { useCallbackRef } from '@radix-ui/react-use-callback-ref';
9
+
10
+ function useImage(props) {
11
+ const onLoadingStatusChange = useCallbackRef(props.onLoadingStatusChange);
12
+ const [loadingStatus, setLoadingStatus] = useState("loading");
13
+ const imageRef = useRef(null);
14
+ useLayoutEffect(()=>{
15
+ if (imageRef.current) {
16
+ if (imageRef.current.complete) {
17
+ if (imageRef.current.naturalWidth === 0 || imageRef.current.naturalHeight === 0) {
18
+ setLoadingStatus("error");
19
+ onLoadingStatusChange?.("error");
20
+ } else {
21
+ setLoadingStatus("loaded");
22
+ onLoadingStatusChange?.("loaded");
23
+ }
24
+ }
25
+ }
26
+ }, [
27
+ onLoadingStatusChange
28
+ ]);
29
+ const isLoaded = loadingStatus === "loaded";
30
+ const stateProps = useMemo(()=>elementProps({
31
+ "data-loading-state": loadingStatus
32
+ }), [
33
+ loadingStatus
34
+ ]);
35
+ const setSrc = useCallback((src)=>{
36
+ if (src === undefined || src === null) {
37
+ setLoadingStatus("error");
38
+ onLoadingStatusChange?.("error");
39
+ } else {
40
+ setLoadingStatus("loading");
41
+ onLoadingStatusChange?.("loading");
42
+ }
43
+ }, [
44
+ onLoadingStatusChange
45
+ ]);
46
+ const getContentProps = useCallback(({ src })=>{
47
+ return imgProps({
48
+ hidden: !isLoaded,
49
+ "data-visible": dataAttr(isLoaded),
50
+ src,
51
+ ...stateProps
52
+ });
53
+ }, [
54
+ isLoaded,
55
+ stateProps
56
+ ]);
57
+ const handleLoad = useCallback(()=>{
58
+ setLoadingStatus("loaded");
59
+ onLoadingStatusChange?.("loaded");
60
+ }, [
61
+ onLoadingStatusChange
62
+ ]);
63
+ const handleError = useCallback(()=>{
64
+ setLoadingStatus("error");
65
+ onLoadingStatusChange?.("error");
66
+ }, [
67
+ onLoadingStatusChange
68
+ ]);
69
+ const fallbackProps = useMemo(()=>elementProps({
70
+ hidden: isLoaded,
71
+ "data-visible": dataAttr(!isLoaded),
72
+ ...stateProps
73
+ }), [
74
+ isLoaded,
75
+ stateProps
76
+ ]);
77
+ return {
78
+ refs: {
79
+ image: imageRef
80
+ },
81
+ loadingStatus,
82
+ stateProps,
83
+ rootProps: stateProps,
84
+ setSrc,
85
+ getContentProps,
86
+ handleLoad,
87
+ handleError,
88
+ fallbackProps
89
+ };
90
+ }
91
+
92
+ const ImageContext = /*#__PURE__*/ createContext(null);
93
+ const ImageProvider = ImageContext.Provider;
94
+ function useImageContext({ strict = true } = {}) {
95
+ const context = useContext(ImageContext);
96
+ if (!context && strict) {
97
+ throw new Error("useImageContext must be used within an Image");
98
+ }
99
+ return context;
100
+ }
101
+
102
+ const ImageRoot = /*#__PURE__*/ forwardRef((props, ref)=>{
103
+ const { onLoadingStatusChange, ...otherProps } = props;
104
+ const api = useImage({
105
+ onLoadingStatusChange
106
+ });
107
+ return /*#__PURE__*/ jsx(ImageProvider, {
108
+ value: api,
109
+ children: /*#__PURE__*/ jsx(Primitive.div, {
110
+ ref: ref,
111
+ ...mergeProps(api.rootProps, otherProps)
112
+ })
113
+ });
114
+ });
115
+ ImageRoot.displayName = "ImageRoot";
116
+ const ImageContent = /*#__PURE__*/ forwardRef((props, ref)=>{
117
+ const { src, onLoad, onError, ...otherProps } = props;
118
+ const { refs, setSrc, getContentProps, handleLoad, handleError } = useImageContext();
119
+ useLayoutEffect(()=>{
120
+ setSrc(src);
121
+ }, [
122
+ src,
123
+ setSrc
124
+ ]);
125
+ const contentProps = getContentProps({
126
+ src
127
+ });
128
+ return /*#__PURE__*/ jsx(Primitive.img, {
129
+ ref: composeRefs(refs.image, ref),
130
+ ...mergeProps(contentProps, otherProps),
131
+ onLoad: (e)=>{
132
+ handleLoad();
133
+ onLoad?.(e);
134
+ },
135
+ onError: (e)=>{
136
+ handleError();
137
+ onError?.(e);
138
+ }
139
+ });
140
+ });
141
+ ImageContent.displayName = "ImageContent";
142
+ const ImageFallback = /*#__PURE__*/ forwardRef((props, ref)=>{
143
+ const { fallbackProps } = useImageContext();
144
+ return /*#__PURE__*/ jsx(Primitive.div, {
145
+ ref: ref,
146
+ ...mergeProps(fallbackProps, props)
147
+ });
148
+ });
149
+ ImageFallback.displayName = "ImageFallback";
150
+
151
+ export { ImageContent as I, ImageFallback as a, ImageRoot as b, useImage as c, useImageContext as u };
@@ -0,0 +1,155 @@
1
+ 'use client';
2
+ var jsxRuntime = require('react/jsx-runtime');
3
+ var reactComposeRefs = require('@radix-ui/react-compose-refs');
4
+ var reactUseLayoutEffect = require('@radix-ui/react-use-layout-effect');
5
+ var domUtils = require('@seed-design/dom-utils');
6
+ var reactPrimitive = require('@seed-design/react-primitive');
7
+ var react = require('react');
8
+ var reactUseCallbackRef = require('@radix-ui/react-use-callback-ref');
9
+
10
+ function useImage(props) {
11
+ const onLoadingStatusChange = reactUseCallbackRef.useCallbackRef(props.onLoadingStatusChange);
12
+ const [loadingStatus, setLoadingStatus] = react.useState("loading");
13
+ const imageRef = react.useRef(null);
14
+ reactUseLayoutEffect.useLayoutEffect(()=>{
15
+ if (imageRef.current) {
16
+ if (imageRef.current.complete) {
17
+ if (imageRef.current.naturalWidth === 0 || imageRef.current.naturalHeight === 0) {
18
+ setLoadingStatus("error");
19
+ onLoadingStatusChange?.("error");
20
+ } else {
21
+ setLoadingStatus("loaded");
22
+ onLoadingStatusChange?.("loaded");
23
+ }
24
+ }
25
+ }
26
+ }, [
27
+ onLoadingStatusChange
28
+ ]);
29
+ const isLoaded = loadingStatus === "loaded";
30
+ const stateProps = react.useMemo(()=>domUtils.elementProps({
31
+ "data-loading-state": loadingStatus
32
+ }), [
33
+ loadingStatus
34
+ ]);
35
+ const setSrc = react.useCallback((src)=>{
36
+ if (src === undefined || src === null) {
37
+ setLoadingStatus("error");
38
+ onLoadingStatusChange?.("error");
39
+ } else {
40
+ setLoadingStatus("loading");
41
+ onLoadingStatusChange?.("loading");
42
+ }
43
+ }, [
44
+ onLoadingStatusChange
45
+ ]);
46
+ const getContentProps = react.useCallback(({ src })=>{
47
+ return domUtils.imgProps({
48
+ hidden: !isLoaded,
49
+ "data-visible": domUtils.dataAttr(isLoaded),
50
+ src,
51
+ ...stateProps
52
+ });
53
+ }, [
54
+ isLoaded,
55
+ stateProps
56
+ ]);
57
+ const handleLoad = react.useCallback(()=>{
58
+ setLoadingStatus("loaded");
59
+ onLoadingStatusChange?.("loaded");
60
+ }, [
61
+ onLoadingStatusChange
62
+ ]);
63
+ const handleError = react.useCallback(()=>{
64
+ setLoadingStatus("error");
65
+ onLoadingStatusChange?.("error");
66
+ }, [
67
+ onLoadingStatusChange
68
+ ]);
69
+ const fallbackProps = react.useMemo(()=>domUtils.elementProps({
70
+ hidden: isLoaded,
71
+ "data-visible": domUtils.dataAttr(!isLoaded),
72
+ ...stateProps
73
+ }), [
74
+ isLoaded,
75
+ stateProps
76
+ ]);
77
+ return {
78
+ refs: {
79
+ image: imageRef
80
+ },
81
+ loadingStatus,
82
+ stateProps,
83
+ rootProps: stateProps,
84
+ setSrc,
85
+ getContentProps,
86
+ handleLoad,
87
+ handleError,
88
+ fallbackProps
89
+ };
90
+ }
91
+
92
+ const ImageContext = /*#__PURE__*/ react.createContext(null);
93
+ const ImageProvider = ImageContext.Provider;
94
+ function useImageContext({ strict = true } = {}) {
95
+ const context = react.useContext(ImageContext);
96
+ if (!context && strict) {
97
+ throw new Error("useImageContext must be used within an Image");
98
+ }
99
+ return context;
100
+ }
101
+
102
+ const ImageRoot = /*#__PURE__*/ react.forwardRef((props, ref)=>{
103
+ const { onLoadingStatusChange, ...otherProps } = props;
104
+ const api = useImage({
105
+ onLoadingStatusChange
106
+ });
107
+ return /*#__PURE__*/ jsxRuntime.jsx(ImageProvider, {
108
+ value: api,
109
+ children: /*#__PURE__*/ jsxRuntime.jsx(reactPrimitive.Primitive.div, {
110
+ ref: ref,
111
+ ...domUtils.mergeProps(api.rootProps, otherProps)
112
+ })
113
+ });
114
+ });
115
+ ImageRoot.displayName = "ImageRoot";
116
+ const ImageContent = /*#__PURE__*/ react.forwardRef((props, ref)=>{
117
+ const { src, onLoad, onError, ...otherProps } = props;
118
+ const { refs, setSrc, getContentProps, handleLoad, handleError } = useImageContext();
119
+ reactUseLayoutEffect.useLayoutEffect(()=>{
120
+ setSrc(src);
121
+ }, [
122
+ src,
123
+ setSrc
124
+ ]);
125
+ const contentProps = getContentProps({
126
+ src
127
+ });
128
+ return /*#__PURE__*/ jsxRuntime.jsx(reactPrimitive.Primitive.img, {
129
+ ref: reactComposeRefs.composeRefs(refs.image, ref),
130
+ ...domUtils.mergeProps(contentProps, otherProps),
131
+ onLoad: (e)=>{
132
+ handleLoad();
133
+ onLoad?.(e);
134
+ },
135
+ onError: (e)=>{
136
+ handleError();
137
+ onError?.(e);
138
+ }
139
+ });
140
+ });
141
+ ImageContent.displayName = "ImageContent";
142
+ const ImageFallback = /*#__PURE__*/ react.forwardRef((props, ref)=>{
143
+ const { fallbackProps } = useImageContext();
144
+ return /*#__PURE__*/ jsxRuntime.jsx(reactPrimitive.Primitive.div, {
145
+ ref: ref,
146
+ ...domUtils.mergeProps(fallbackProps, props)
147
+ });
148
+ });
149
+ ImageFallback.displayName = "ImageFallback";
150
+
151
+ exports.ImageContent = ImageContent;
152
+ exports.ImageFallback = ImageFallback;
153
+ exports.ImageRoot = ImageRoot;
154
+ exports.useImage = useImage;
155
+ exports.useImageContext = useImageContext;
package/lib/index.cjs ADDED
@@ -0,0 +1,15 @@
1
+ var Image12s = require('./Image-12s-LZ-Fna1t.cjs');
2
+
3
+ var Image_namespace = {
4
+ __proto__: null,
5
+ Content: Image12s.ImageContent,
6
+ Fallback: Image12s.ImageFallback,
7
+ Root: Image12s.ImageRoot
8
+ };
9
+
10
+ exports.ImageContent = Image12s.ImageContent;
11
+ exports.ImageFallback = Image12s.ImageFallback;
12
+ exports.ImageRoot = Image12s.ImageRoot;
13
+ exports.useImage = Image12s.useImage;
14
+ exports.useImageContext = Image12s.useImageContext;
15
+ exports.Image = Image_namespace;