@lonik/oh-image 2.1.1 → 2.1.3

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,100 @@
1
+ import { t as loaderFactory } from "./loader-factory-CPgnRdhT.js";
2
+
3
+ //#region src/loaders/imgproxy/imgproxy-loader.tsx
4
+ const { useLoaderContext: useImgproxyContext, LoaderProvider: ImgproxyLoaderProvider, useLoader: useImgproxyLoader, usePlaceholder: useImgproxyPlaceholder } = loaderFactory({
5
+ transforms: { format: "webp" },
6
+ placeholderTransforms: {
7
+ quality: 10,
8
+ format: "webp"
9
+ }
10
+ }, {
11
+ optionSeparator: ":",
12
+ paramSeparator: "/",
13
+ orders: {
14
+ resize: [
15
+ "resizing_type",
16
+ "width",
17
+ "height",
18
+ "enlarge",
19
+ "extend"
20
+ ],
21
+ size: [
22
+ "width",
23
+ "height",
24
+ "enlarge",
25
+ "extend"
26
+ ],
27
+ extend: ["extend", "gravity"],
28
+ gravity: [
29
+ "type",
30
+ "x_offset",
31
+ "y_offset"
32
+ ],
33
+ crop: [
34
+ "width",
35
+ "height",
36
+ "gravity"
37
+ ],
38
+ trim: [
39
+ "threshold",
40
+ "color",
41
+ "equal_hor",
42
+ "equal_ver"
43
+ ],
44
+ padding: [
45
+ "top",
46
+ "right",
47
+ "bottom",
48
+ "left"
49
+ ],
50
+ background: [
51
+ "r",
52
+ "g",
53
+ "b"
54
+ ],
55
+ adjust: [
56
+ "brightness",
57
+ "contrast",
58
+ "saturation"
59
+ ],
60
+ blur_detections: ["sigma", "class_names"],
61
+ draw_detections: ["draw", "class_names"],
62
+ watermark: [
63
+ "opacity",
64
+ "position",
65
+ "x_offset",
66
+ "y_offset",
67
+ "scale"
68
+ ],
69
+ watermark_size: ["width", "height"],
70
+ unsharpening: [
71
+ "mode",
72
+ "weight",
73
+ "dividor"
74
+ ],
75
+ autoquality: [
76
+ "method",
77
+ "target",
78
+ "min_quality",
79
+ "max_quality",
80
+ "allowed_error"
81
+ ],
82
+ jpeg_options: [
83
+ "progressive",
84
+ "no_subsample",
85
+ "trellis_quant",
86
+ "overshoot_deringing",
87
+ "optimize_scans",
88
+ "quant_table"
89
+ ],
90
+ png_options: [
91
+ "interlaced",
92
+ "quantize",
93
+ "quantization_colors"
94
+ ],
95
+ zoom: ["x", "y"]
96
+ }
97
+ }, ({ path, params, imageOptions }) => `${path}/${params}/plain/${imageOptions.src}`);
98
+
99
+ //#endregion
100
+ export { ImgproxyLoaderProvider, useImgproxyContext, useImgproxyLoader, useImgproxyPlaceholder };
@@ -0,0 +1,79 @@
1
+ import { ImgHTMLAttributes } from "react";
2
+ import * as react_jsx_runtime3 from "react/jsx-runtime";
3
+
4
+ //#region src/react/types.d.ts
5
+ interface ImageLoaderOptions {
6
+ src: string;
7
+ width?: number | null | undefined;
8
+ height?: number | null | undefined;
9
+ }
10
+ type ImageLoader = (options: ImageLoaderOptions) => string | undefined;
11
+ type ImageSrcType = string | ImageSrc;
12
+ interface ImageProps extends Partial<Pick<ImgHTMLAttributes<HTMLImageElement>, "fetchPriority" | "decoding" | "loading" | "srcSet" | "className" | "sizes" | "style">> {
13
+ /** Alternative text for the image, required for accessibility. Use an empty string for decorative images. */
14
+ alt: string;
15
+ /** @deprecated Use `priority` instead. */
16
+ asap?: boolean;
17
+ /** Configures the Image component to load the image immediately. */
18
+ priority?: boolean;
19
+ /** */
20
+ src: ImageSrcType;
21
+ /** The URL of the placeholder image to display while loading. */
22
+ placeholder?: string | undefined | ImageLoader | null;
23
+ /**
24
+ * Sets the image to "fill mode", which eliminates the height/width requirement and adds
25
+ * styles such that the image fills its containing element.
26
+ */
27
+ fill?: boolean;
28
+ loader?: ImageLoader | null;
29
+ width?: number | undefined;
30
+ height?: number | undefined;
31
+ breakpoints?: number[];
32
+ }
33
+ //#endregion
34
+ //#region src/react/image.d.ts
35
+ declare function Image(props: ImageProps): react_jsx_runtime3.JSX.Element;
36
+ //#endregion
37
+ //#region src/react/use-img-loaded.d.ts
38
+ /**
39
+ * A hook that tracks whether an image element has finished loading.
40
+ *
41
+ * Handles all edge cases:
42
+ * - Image already cached/complete on mount
43
+ * - Normal load via event listener
44
+ * - Errors (resets to `false`)
45
+ * - `src` changes (resets to `false` until the new source loads)
46
+ * - Element unmount / ref set to `null`
47
+ *
48
+ * @returns `[ref, isLoaded]` — attach the ref callback to an `<img>` element.
49
+ *
50
+ * @example
51
+ * ```tsx
52
+ * function Avatar({ src }: { src: string }) {
53
+ * const [imgRef, isLoaded] = useImgLoaded(src);
54
+ * return (
55
+ * <img
56
+ * ref={imgRef}
57
+ * src={src}
58
+ * style={{ opacity: isLoaded ? 1 : 0 }}
59
+ * />
60
+ * );
61
+ * }
62
+ * ```
63
+ */
64
+ declare function useImgLoaded(src: string | undefined): [(img: HTMLImageElement | null) => void, boolean];
65
+ //#endregion
66
+ //#region src/react/image-context.d.ts
67
+ interface ImageContextValue extends Pick<ImageProps, "loading"> {
68
+ breakpoints: number[];
69
+ loader: ImageLoader | null;
70
+ }
71
+ declare function useImageContext(): ImageContextValue;
72
+ declare function ImageProvider({
73
+ children,
74
+ ...props
75
+ }: {
76
+ children: React.ReactNode;
77
+ } & Partial<ImageContextValue>): react_jsx_runtime3.JSX.Element;
78
+ //#endregion
79
+ export { ImageLoader as a, ImageSrcType as c, Image as i, useImageContext as n, ImageLoaderOptions as o, useImgLoaded as r, ImageProps as s, ImageProvider as t };
@@ -0,0 +1,94 @@
1
+ import { createContext, useContext } from "react";
2
+ import { jsx } from "react/jsx-runtime";
3
+
4
+ //#region src/loaders/transforms-resolver.ts
5
+ const stringifyOptions = (opCode, values, separator) => {
6
+ return [opCode, ...values.map((v) => v == null ? "" : encodeURIComponent(v))].join(separator);
7
+ };
8
+ const resolveObjectParam = (key, value, order, separator) => {
9
+ if (!order) return;
10
+ return stringifyOptions(key, order.map((k) => value[k]), separator);
11
+ };
12
+ function resolveTransform(transforms, config) {
13
+ if (!transforms) return [];
14
+ const params = [];
15
+ for (const key of Object.keys(transforms)) {
16
+ const value = transforms[key];
17
+ if (value === void 0) continue;
18
+ const type = typeof value;
19
+ if (config.customResolver) {
20
+ const resolverFn = config.customResolver[key];
21
+ if (resolverFn) {
22
+ const resolvedValue = resolverFn(key, value);
23
+ if (resolvedValue !== void 0) params.push(resolvedValue);
24
+ continue;
25
+ }
26
+ }
27
+ switch (type) {
28
+ case "boolean":
29
+ if (value === true) params.push(key);
30
+ break;
31
+ case "object": {
32
+ const objectParams = resolveObjectParam(key, value, config?.orders?.[key], config.optionSeparator);
33
+ if (objectParams) params.push(objectParams);
34
+ break;
35
+ }
36
+ default:
37
+ params.push(stringifyOptions(key, [value], config.optionSeparator));
38
+ break;
39
+ }
40
+ }
41
+ return params;
42
+ }
43
+
44
+ //#endregion
45
+ //#region src/loaders/loader-factory.tsx
46
+ function loaderFactory(defaults, config, urlResolver) {
47
+ const loaderContext = createContext(defaults);
48
+ function useLoaderContext() {
49
+ return useContext(loaderContext);
50
+ }
51
+ function LoaderProvider({ children, ...props }) {
52
+ const ctx = useLoaderContext();
53
+ return /* @__PURE__ */ jsx(loaderContext.Provider, {
54
+ value: {
55
+ ...ctx,
56
+ ...props
57
+ },
58
+ children
59
+ });
60
+ }
61
+ const loader = (isPlaceholder) => (options) => {
62
+ const context = useLoaderContext();
63
+ const path = options?.path || context.path;
64
+ const transforms = {
65
+ ...isPlaceholder ? context.placeholderTransforms : context.transforms,
66
+ ...options?.transforms
67
+ };
68
+ if (!path) {
69
+ console.warn("Path is not provided");
70
+ return () => void 0;
71
+ }
72
+ return (imageOptions) => {
73
+ const params = [];
74
+ if (imageOptions.width) params.push("width" + config.optionSeparator + imageOptions.width);
75
+ if (imageOptions.height) params.push("height" + config.optionSeparator + imageOptions.height);
76
+ const resolvedTransforms = resolveTransform(transforms, config);
77
+ return urlResolver({
78
+ imageOptions,
79
+ params: [...params, ...resolvedTransforms].join(config.paramSeparator),
80
+ path
81
+ });
82
+ };
83
+ };
84
+ return {
85
+ LoaderProvider,
86
+ loaderContext,
87
+ useLoaderContext,
88
+ useLoader: loader(false),
89
+ usePlaceholder: loader(true)
90
+ };
91
+ }
92
+
93
+ //#endregion
94
+ export { loaderFactory as t };
@@ -0,0 +1,40 @@
1
+ //#region src/react/prop-asserts.ts
2
+ function assertProps(prop) {
3
+ try {
4
+ if (prop.asap !== void 0) console.warn("The `asap` prop is deprecated and will be removed in a future version. Please use `priority` instead.");
5
+ assertLoadingProp(prop);
6
+ assertDecodingProp(prop);
7
+ assertFetchPriorityProp(prop);
8
+ assertBreakpointsProp(prop);
9
+ assertFillProp(prop);
10
+ assertDimensionsProp(prop);
11
+ } catch (err) {
12
+ const message = err instanceof Error ? err.message : err;
13
+ console.warn(message);
14
+ }
15
+ }
16
+ function assert(assertion, message) {
17
+ if (assertion()) throw new Error(message || void 0);
18
+ }
19
+ function assertLoadingProp(prop) {
20
+ assert(() => prop.loading && (prop.priority || prop.asap), `Do not use \`loading\` on a priority image — priority images are always eagerly loaded.`);
21
+ }
22
+ function assertDecodingProp(prop) {
23
+ assert(() => prop.decoding && (prop.priority || prop.asap), `Do not use \`decoding\` on a priority image — priority images always use async decoding.`);
24
+ }
25
+ function assertFetchPriorityProp(prop) {
26
+ assert(() => prop.fetchPriority && (prop.priority || prop.asap), `Do not use \`fetchPriority\` on a priority image — priority images always use high fetch priority.`);
27
+ }
28
+ function assertBreakpointsProp(prop) {
29
+ assert(() => prop.breakpoints && typeof prop.src === "object", `Do not use \`breakpoints\` when \`src\` is an imported image — the image's built-in srcSets are used instead.`);
30
+ assert(() => prop.breakpoints && typeof prop.src === "string" && !prop.loader, `Do not use \`breakpoints\` without a \`loader\` — breakpoints require a loader to generate srcSet entries.`);
31
+ }
32
+ function assertFillProp(prop) {
33
+ assert(() => prop.fill && (prop.width !== void 0 || prop.height !== void 0), `Do not use \`width\` or \`height\` with \`fill\` — fill mode makes the image fill its container.`);
34
+ }
35
+ function assertDimensionsProp(prop) {
36
+ assert(() => typeof prop.src === "string" && !prop.fill && prop.width === void 0 && prop.height === void 0, `Image is missing \`width\` and \`height\` props. Either provide dimensions, use \`fill\`, or use an imported image source.`);
37
+ }
38
+
39
+ //#endregion
40
+ export { assertProps as t };