@01.software/sdk 0.5.4 → 0.5.5
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/auth.cjs +22 -46
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.js +22 -47
- package/dist/auth.js.map +1 -1
- package/dist/index.cjs +922 -1069
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +922 -1072
- package/dist/index.js.map +1 -1
- package/dist/realtime.cjs +75 -101
- package/dist/realtime.cjs.map +1 -1
- package/dist/realtime.js +75 -102
- package/dist/realtime.js.map +1 -1
- package/dist/ui/code-block.cjs +13 -35
- package/dist/ui/code-block.cjs.map +1 -1
- package/dist/ui/code-block.js +13 -35
- package/dist/ui/code-block.js.map +1 -1
- package/dist/ui/flow/server.cjs +26 -68
- package/dist/ui/flow/server.cjs.map +1 -1
- package/dist/ui/flow/server.js +26 -71
- package/dist/ui/flow/server.js.map +1 -1
- package/dist/ui/flow.cjs +176 -232
- package/dist/ui/flow.cjs.map +1 -1
- package/dist/ui/flow.js +176 -234
- package/dist/ui/flow.js.map +1 -1
- package/dist/ui/form.cjs +40 -84
- package/dist/ui/form.cjs.map +1 -1
- package/dist/ui/form.js +40 -86
- package/dist/ui/form.js.map +1 -1
- package/dist/ui/image.cjs +27 -40
- package/dist/ui/image.cjs.map +1 -1
- package/dist/ui/image.js +27 -42
- package/dist/ui/image.js.map +1 -1
- package/dist/ui/rich-text.cjs +33 -67
- package/dist/ui/rich-text.cjs.map +1 -1
- package/dist/ui/rich-text.js +33 -69
- package/dist/ui/rich-text.js.map +1 -1
- package/dist/ui/video.cjs +32 -50
- package/dist/ui/video.cjs.map +1 -1
- package/dist/ui/video.js +32 -52
- package/dist/ui/video.js.map +1 -1
- package/dist/webhook.cjs +48 -73
- package/dist/webhook.cjs.map +1 -1
- package/dist/webhook.js +48 -74
- package/dist/webhook.js.map +1 -1
- package/package.json +3 -3
package/dist/ui/image.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/ui/Image/index.tsx","../../src/utils/image.ts"],"sourcesContent":["'use client'\n\nimport React, { useCallback, useRef, useState } from 'react'\nimport type { CSSProperties } from 'react'\nimport type { ImageData } from '../../utils/image'\nimport { getImageSrcSet, getImagePlaceholderStyle } from '../../utils/image'\n\nexport interface ImageProps {\n /** Payload image document */\n image: ImageData\n /** Display width in CSS pixels (for selecting optimal srcset size) */\n width?: number\n /** Device pixel ratio (default: 1) */\n dpr?: number\n /** Placeholder strategy (default: 'blur'; defaults to 'none' when imageRendering is 'pixelated' or 'crisp-edges') */\n placeholder?: 'blur' | 'color' | 'none'\n /** Container className */\n className?: string\n /** Container style */\n style?: CSSProperties\n /** Inner `<img>` className */\n imgClassName?: string\n /** Inner `<img>` style */\n imgStyle?: CSSProperties\n /** HTML sizes attribute */\n sizes?: string\n /** Loading strategy (default: 'lazy'; automatically 'eager' when priority is true) */\n loading?: 'lazy' | 'eager'\n /** Callback when image finishes loading */\n onLoad?: () => void\n /** Object-fit for the image (default: 'cover') */\n objectFit?: 'cover' | 'contain' | 'fill' | 'none' | 'scale-down'\n /** When true, loads eagerly with high fetch priority (for LCP images) */\n priority?: boolean\n /** When true, fills parent container (width/height: 100%, no aspect ratio) */\n fill?: boolean\n /** CSS image-rendering mode (e.g. 'pixelated' for pixel art) */\n imageRendering?: 'auto' | 'pixelated' | 'crisp-edges'\n}\n\n/**\n * Image component with blur-up / color placeholder support.\n *\n * Uses LQIP (Low Quality Image Placeholder) for a smooth blur-up effect,\n * falling back to palette color or no placeholder.\n */\nexport function Image({\n image,\n width,\n dpr = 1,\n placeholder: placeholderProp,\n className,\n style,\n imgClassName,\n imgStyle,\n sizes,\n loading: loadingProp,\n onLoad,\n objectFit = 'cover',\n priority = false,\n fill = false,\n imageRendering,\n}: ImageProps) {\n const [loaded, setLoaded] = useState(false)\n const firedRef = useRef(false)\n\n // Resolve defaults based on other props\n const isPixelRendering =\n imageRendering === 'pixelated' || imageRendering === 'crisp-edges'\n const placeholder = placeholderProp ?? (isPixelRendering ? 'none' : 'blur')\n const loading = priority ? 'eager' : (loadingProp ?? 'lazy')\n\n const aspectRatio =\n !fill && image.width && image.height\n ? `${image.width} / ${image.height}`\n : undefined\n\n const srcSet = getImageSrcSet(image)\n const src = image.url ?? undefined\n\n // Placeholder: LQIP overlay or color overlay (mutually exclusive)\n const hasLqip = placeholder === 'blur' && !!image.lqip\n const placeholderStyle = getImagePlaceholderStyle(image, {\n type: placeholder,\n })\n const placeholderColor =\n !hasLqip && 'backgroundColor' in placeholderStyle\n ? placeholderStyle.backgroundColor\n : undefined\n\n const fireLoad = useCallback(() => {\n if (firedRef.current) return\n firedRef.current = true\n setLoaded(true)\n onLoad?.()\n }, [onLoad])\n\n // Callback ref: detect SSR-cached images that are already loaded\n const imgRef = useCallback(\n (node: HTMLImageElement | null) => {\n if (node && node.complete && node.naturalWidth > 0) {\n fireLoad()\n }\n },\n [fireLoad],\n )\n\n // Container styles\n const containerStyle: CSSProperties = {\n position: 'relative',\n overflow: 'hidden',\n ...(fill ? { width: '100%', height: '100%' } : {}),\n ...(aspectRatio ? { aspectRatio } : {}),\n ...style,\n }\n\n // Shared overlay styles (LQIP and color)\n const overlayBase: CSSProperties = {\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n height: '100%',\n opacity: loaded ? 0 : 1,\n transition: 'opacity 0.3s ease',\n pointerEvents: 'none',\n }\n\n // Main image styles\n const mainImgStyle: CSSProperties = {\n display: 'block',\n width: '100%',\n height: '100%',\n objectFit,\n ...(imageRendering ? { imageRendering } : {}),\n opacity: loaded ? 1 : 0,\n transition: 'opacity 0.3s ease',\n ...imgStyle,\n }\n\n return (\n <div className={className} style={containerStyle}>\n {hasLqip && (\n <img\n aria-hidden\n alt=\"\"\n src={image.lqip!}\n style={{\n ...overlayBase,\n display: 'block',\n objectFit,\n filter: 'blur(20px)',\n transform: 'scale(1.1)',\n }}\n />\n )}\n {placeholderColor && (\n <div\n aria-hidden\n style={{\n ...overlayBase,\n backgroundColor: placeholderColor,\n }}\n />\n )}\n <img\n ref={imgRef}\n alt={image.alt ?? ''}\n src={src}\n srcSet={srcSet || undefined}\n sizes={sizes}\n width={width ? width * dpr : undefined}\n loading={loading}\n decoding=\"async\"\n fetchPriority={priority ? 'high' : undefined}\n onLoad={fireLoad}\n className={imgClassName}\n style={mainImgStyle}\n />\n </div>\n )\n}\n","/** Palette colors extracted from an image */\nexport interface ImagePalette {\n vibrant?: string | null\n muted?: string | null\n darkVibrant?: string | null\n darkMuted?: string | null\n lightVibrant?: string | null\n lightMuted?: string | null\n}\n\n/** Common image data shape from Payload CMS upload collections */\nexport interface ImageData {\n url?: string | null\n width?: number | null\n height?: number | null\n alt?: string | null\n lqip?: string | null\n palette?: ImagePalette | null\n sizes?: Record<\n string,\n | {\n url?: string | null\n width?: number | null\n height?: number | null\n }\n | undefined\n >\n}\n\n/** Pre-generated image size breakpoints (px) */\nexport const IMAGE_SIZES = [384, 768, 1536] as const\n\n/**\n * Returns the optimal image URL for a given display width.\n *\n * Picks the smallest pre-generated size whose width >= displayWidth × dpr.\n * Falls back to the original URL when no matching size exists.\n *\n * @param image - Payload image document\n * @param displayWidth - CSS pixel width the image will be displayed at\n * @param dpr - Device pixel ratio (default: 1)\n * @returns URL string, or empty string if no URL is available\n */\nexport function getImageUrl(\n image: ImageData,\n displayWidth: number,\n dpr: number = 1,\n): string {\n const target = displayWidth * dpr\n const sizes = image.sizes\n\n if (sizes) {\n for (const size of IMAGE_SIZES) {\n if (size >= target) {\n const entry = sizes[String(size)]\n if (entry?.url) return entry.url\n }\n }\n }\n\n return image.url ?? ''\n}\n\n/**\n * Generates an HTML `srcset` attribute string from pre-generated sizes.\n *\n * Includes all available sizes plus the original image.\n * Example output: `\"url-384 384w, url-768 768w, url-1536 1536w, url-original 2000w\"`\n *\n * @param image - Payload image document\n * @returns srcset string, or empty string if no URLs are available\n */\nexport function getImageSrcSet(image: ImageData): string {\n const parts: string[] = []\n const sizes = image.sizes\n\n if (sizes) {\n for (const size of IMAGE_SIZES) {\n const entry = sizes[String(size)]\n if (entry?.url && entry.width) {\n parts.push(`${entry.url} ${entry.width}w`)\n }\n }\n }\n\n if (image.url && image.width) {\n parts.push(`${image.url} ${image.width}w`)\n }\n\n return parts.join(', ')\n}\n\n/**\n * Returns the LQIP (Low Quality Image Placeholder) data URL for an image.\n *\n * @param image - Payload image document\n * @returns LQIP data URL string, or undefined if not available\n */\nexport function getImageLqip(image: ImageData): string | undefined {\n return image.lqip ?? undefined\n}\n\n/**\n * Returns the extracted color palette for an image.\n *\n * @param image - Payload image document\n * @returns ImagePalette object, or undefined if not available\n */\nexport function getImagePalette(image: ImageData): ImagePalette | undefined {\n return image.palette ?? undefined\n}\n\n/** Options for `getImagePlaceholderStyle` */\nexport interface ImagePlaceholderOptions {\n /** Placeholder strategy (default: 'blur') */\n type?: 'blur' | 'color' | 'none'\n /** Which palette color to use for 'color' strategy (default: 'muted') */\n paletteColor?: keyof ImagePalette\n}\n\n/**\n * Returns inline CSS styles for an image placeholder.\n *\n * - `blur`: uses LQIP as background, falls back to palette color, then empty\n * - `color`: uses palette color as background, falls back to empty\n * - `none`: always returns empty\n *\n * @param image - Payload image document\n * @param options - Placeholder options\n * @returns CSS style object compatible with React CSSProperties\n */\nexport function getImagePlaceholderStyle(\n image: ImageData,\n options?: ImagePlaceholderOptions,\n): Record<string, string> {\n const type = options?.type ?? 'blur'\n const paletteColor = options?.paletteColor ?? 'muted'\n\n if (type === 'none') return {}\n\n const color = image.palette?.[paletteColor]\n\n if (type === 'blur') {\n const lqip = image.lqip\n if (lqip) {\n return {\n backgroundImage: `url(${lqip})`,\n backgroundSize: 'cover',\n backgroundPosition: 'center',\n }\n }\n // Cascade: fall back to color\n if (color) {\n return { backgroundColor: color }\n }\n return {}\n }\n\n // type === 'color'\n if (color) {\n return { backgroundColor: color }\n }\n return {}\n}\n"],"mappings":"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","names":["React"]}
|
|
1
|
+
{"version":3,"sources":["../../src/ui/Image/index.tsx","../../src/utils/image.ts"],"sourcesContent":["'use client'\n\nimport React, { useCallback, useRef, useState } from 'react'\nimport type { CSSProperties } from 'react'\nimport type { ImageData } from '../../utils/image'\nimport { getImageSrcSet, getImagePlaceholderStyle } from '../../utils/image'\n\nexport interface ImageProps {\n /** Payload image document */\n image: ImageData\n /** Display width in CSS pixels (for selecting optimal srcset size) */\n width?: number\n /** Device pixel ratio (default: 1) */\n dpr?: number\n /** Placeholder strategy (default: 'blur'; defaults to 'none' when imageRendering is 'pixelated' or 'crisp-edges') */\n placeholder?: 'blur' | 'color' | 'none'\n /** Container className */\n className?: string\n /** Container style */\n style?: CSSProperties\n /** Inner `<img>` className */\n imgClassName?: string\n /** Inner `<img>` style */\n imgStyle?: CSSProperties\n /** HTML sizes attribute */\n sizes?: string\n /** Loading strategy (default: 'lazy'; automatically 'eager' when priority is true) */\n loading?: 'lazy' | 'eager'\n /** Callback when image finishes loading */\n onLoad?: () => void\n /** Object-fit for the image (default: 'cover') */\n objectFit?: 'cover' | 'contain' | 'fill' | 'none' | 'scale-down'\n /** When true, loads eagerly with high fetch priority (for LCP images) */\n priority?: boolean\n /** When true, fills parent container (width/height: 100%, no aspect ratio) */\n fill?: boolean\n /** CSS image-rendering mode (e.g. 'pixelated' for pixel art) */\n imageRendering?: 'auto' | 'pixelated' | 'crisp-edges'\n}\n\n/**\n * Image component with blur-up / color placeholder support.\n *\n * Uses LQIP (Low Quality Image Placeholder) for a smooth blur-up effect,\n * falling back to palette color or no placeholder.\n */\nexport function Image({\n image,\n width,\n dpr = 1,\n placeholder: placeholderProp,\n className,\n style,\n imgClassName,\n imgStyle,\n sizes,\n loading: loadingProp,\n onLoad,\n objectFit = 'cover',\n priority = false,\n fill = false,\n imageRendering,\n}: ImageProps) {\n const [loaded, setLoaded] = useState(false)\n const firedRef = useRef(false)\n\n // Resolve defaults based on other props\n const isPixelRendering =\n imageRendering === 'pixelated' || imageRendering === 'crisp-edges'\n const placeholder = placeholderProp ?? (isPixelRendering ? 'none' : 'blur')\n const loading = priority ? 'eager' : (loadingProp ?? 'lazy')\n\n const aspectRatio =\n !fill && image.width && image.height\n ? `${image.width} / ${image.height}`\n : undefined\n\n const srcSet = getImageSrcSet(image)\n const src = image.url ?? undefined\n\n // Placeholder: LQIP overlay or color overlay (mutually exclusive)\n const hasLqip = placeholder === 'blur' && !!image.lqip\n const placeholderStyle = getImagePlaceholderStyle(image, {\n type: placeholder,\n })\n const placeholderColor =\n !hasLqip && 'backgroundColor' in placeholderStyle\n ? placeholderStyle.backgroundColor\n : undefined\n\n const fireLoad = useCallback(() => {\n if (firedRef.current) return\n firedRef.current = true\n setLoaded(true)\n onLoad?.()\n }, [onLoad])\n\n // Callback ref: detect SSR-cached images that are already loaded\n const imgRef = useCallback(\n (node: HTMLImageElement | null) => {\n if (node && node.complete && node.naturalWidth > 0) {\n fireLoad()\n }\n },\n [fireLoad],\n )\n\n // Container styles\n const containerStyle: CSSProperties = {\n position: 'relative',\n overflow: 'hidden',\n ...(fill ? { width: '100%', height: '100%' } : {}),\n ...(aspectRatio ? { aspectRatio } : {}),\n ...style,\n }\n\n // Shared overlay styles (LQIP and color)\n const overlayBase: CSSProperties = {\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n height: '100%',\n opacity: loaded ? 0 : 1,\n transition: 'opacity 0.3s ease',\n pointerEvents: 'none',\n }\n\n // Main image styles\n const mainImgStyle: CSSProperties = {\n display: 'block',\n width: '100%',\n height: '100%',\n objectFit,\n ...(imageRendering ? { imageRendering } : {}),\n opacity: loaded ? 1 : 0,\n transition: 'opacity 0.3s ease',\n ...imgStyle,\n }\n\n return (\n <div className={className} style={containerStyle}>\n {hasLqip && (\n <img\n aria-hidden\n alt=\"\"\n src={image.lqip!}\n style={{\n ...overlayBase,\n display: 'block',\n objectFit,\n filter: 'blur(20px)',\n transform: 'scale(1.1)',\n }}\n />\n )}\n {placeholderColor && (\n <div\n aria-hidden\n style={{\n ...overlayBase,\n backgroundColor: placeholderColor,\n }}\n />\n )}\n <img\n ref={imgRef}\n alt={image.alt ?? ''}\n src={src}\n srcSet={srcSet || undefined}\n sizes={sizes}\n width={width ? width * dpr : undefined}\n loading={loading}\n decoding=\"async\"\n fetchPriority={priority ? 'high' : undefined}\n onLoad={fireLoad}\n className={imgClassName}\n style={mainImgStyle}\n />\n </div>\n )\n}\n","/** Palette colors extracted from an image */\nexport interface ImagePalette {\n vibrant?: string | null\n muted?: string | null\n darkVibrant?: string | null\n darkMuted?: string | null\n lightVibrant?: string | null\n lightMuted?: string | null\n}\n\n/** Common image data shape from Payload CMS upload collections */\nexport interface ImageData {\n url?: string | null\n width?: number | null\n height?: number | null\n alt?: string | null\n lqip?: string | null\n palette?: ImagePalette | null\n sizes?: Record<\n string,\n | {\n url?: string | null\n width?: number | null\n height?: number | null\n }\n | undefined\n >\n}\n\n/** Pre-generated image size breakpoints (px) */\nexport const IMAGE_SIZES = [384, 768, 1536] as const\n\n/**\n * Returns the optimal image URL for a given display width.\n *\n * Picks the smallest pre-generated size whose width >= displayWidth × dpr.\n * Falls back to the original URL when no matching size exists.\n *\n * @param image - Payload image document\n * @param displayWidth - CSS pixel width the image will be displayed at\n * @param dpr - Device pixel ratio (default: 1)\n * @returns URL string, or empty string if no URL is available\n */\nexport function getImageUrl(\n image: ImageData,\n displayWidth: number,\n dpr: number = 1,\n): string {\n const target = displayWidth * dpr\n const sizes = image.sizes\n\n if (sizes) {\n for (const size of IMAGE_SIZES) {\n if (size >= target) {\n const entry = sizes[String(size)]\n if (entry?.url) return entry.url\n }\n }\n }\n\n return image.url ?? ''\n}\n\n/**\n * Generates an HTML `srcset` attribute string from pre-generated sizes.\n *\n * Includes all available sizes plus the original image.\n * Example output: `\"url-384 384w, url-768 768w, url-1536 1536w, url-original 2000w\"`\n *\n * @param image - Payload image document\n * @returns srcset string, or empty string if no URLs are available\n */\nexport function getImageSrcSet(image: ImageData): string {\n const parts: string[] = []\n const sizes = image.sizes\n\n if (sizes) {\n for (const size of IMAGE_SIZES) {\n const entry = sizes[String(size)]\n if (entry?.url && entry.width) {\n parts.push(`${entry.url} ${entry.width}w`)\n }\n }\n }\n\n if (image.url && image.width) {\n parts.push(`${image.url} ${image.width}w`)\n }\n\n return parts.join(', ')\n}\n\n/**\n * Returns the LQIP (Low Quality Image Placeholder) data URL for an image.\n *\n * @param image - Payload image document\n * @returns LQIP data URL string, or undefined if not available\n */\nexport function getImageLqip(image: ImageData): string | undefined {\n return image.lqip ?? undefined\n}\n\n/**\n * Returns the extracted color palette for an image.\n *\n * @param image - Payload image document\n * @returns ImagePalette object, or undefined if not available\n */\nexport function getImagePalette(image: ImageData): ImagePalette | undefined {\n return image.palette ?? undefined\n}\n\n/** Options for `getImagePlaceholderStyle` */\nexport interface ImagePlaceholderOptions {\n /** Placeholder strategy (default: 'blur') */\n type?: 'blur' | 'color' | 'none'\n /** Which palette color to use for 'color' strategy (default: 'muted') */\n paletteColor?: keyof ImagePalette\n}\n\n/**\n * Returns inline CSS styles for an image placeholder.\n *\n * - `blur`: uses LQIP as background, falls back to palette color, then empty\n * - `color`: uses palette color as background, falls back to empty\n * - `none`: always returns empty\n *\n * @param image - Payload image document\n * @param options - Placeholder options\n * @returns CSS style object compatible with React CSSProperties\n */\nexport function getImagePlaceholderStyle(\n image: ImageData,\n options?: ImagePlaceholderOptions,\n): Record<string, string> {\n const type = options?.type ?? 'blur'\n const paletteColor = options?.paletteColor ?? 'muted'\n\n if (type === 'none') return {}\n\n const color = image.palette?.[paletteColor]\n\n if (type === 'blur') {\n const lqip = image.lqip\n if (lqip) {\n return {\n backgroundImage: `url(${lqip})`,\n backgroundSize: 'cover',\n backgroundPosition: 'center',\n }\n }\n // Cascade: fall back to color\n if (color) {\n return { backgroundColor: color }\n }\n return {}\n }\n\n // type === 'color'\n if (color) {\n return { backgroundColor: color }\n }\n return {}\n}\n"],"mappings":"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","names":["React"]}
|
package/dist/ui/image.js
CHANGED
|
@@ -1,23 +1,4 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __defProps = Object.defineProperties;
|
|
4
|
-
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
5
|
-
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
6
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
-
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
8
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
9
|
-
var __spreadValues = (a, b) => {
|
|
10
|
-
for (var prop in b || (b = {}))
|
|
11
|
-
if (__hasOwnProp.call(b, prop))
|
|
12
|
-
__defNormalProp(a, prop, b[prop]);
|
|
13
|
-
if (__getOwnPropSymbols)
|
|
14
|
-
for (var prop of __getOwnPropSymbols(b)) {
|
|
15
|
-
if (__propIsEnum.call(b, prop))
|
|
16
|
-
__defNormalProp(a, prop, b[prop]);
|
|
17
|
-
}
|
|
18
|
-
return a;
|
|
19
|
-
};
|
|
20
|
-
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
21
2
|
|
|
22
3
|
// src/ui/Image/index.tsx
|
|
23
4
|
import React, { useCallback, useRef, useState } from "react";
|
|
@@ -30,7 +11,7 @@ function getImageSrcSet(image) {
|
|
|
30
11
|
if (sizes) {
|
|
31
12
|
for (const size of IMAGE_SIZES) {
|
|
32
13
|
const entry = sizes[String(size)];
|
|
33
|
-
if (
|
|
14
|
+
if (entry?.url && entry.width) {
|
|
34
15
|
parts.push(`${entry.url} ${entry.width}w`);
|
|
35
16
|
}
|
|
36
17
|
}
|
|
@@ -41,11 +22,10 @@ function getImageSrcSet(image) {
|
|
|
41
22
|
return parts.join(", ");
|
|
42
23
|
}
|
|
43
24
|
function getImagePlaceholderStyle(image, options) {
|
|
44
|
-
|
|
45
|
-
const
|
|
46
|
-
const paletteColor = (_b = options == null ? void 0 : options.paletteColor) != null ? _b : "muted";
|
|
25
|
+
const type = options?.type ?? "blur";
|
|
26
|
+
const paletteColor = options?.paletteColor ?? "muted";
|
|
47
27
|
if (type === "none") return {};
|
|
48
|
-
const color =
|
|
28
|
+
const color = image.palette?.[paletteColor];
|
|
49
29
|
if (type === "blur") {
|
|
50
30
|
const lqip = image.lqip;
|
|
51
31
|
if (lqip) {
|
|
@@ -84,15 +64,14 @@ function Image({
|
|
|
84
64
|
fill = false,
|
|
85
65
|
imageRendering
|
|
86
66
|
}) {
|
|
87
|
-
var _a, _b;
|
|
88
67
|
const [loaded, setLoaded] = useState(false);
|
|
89
68
|
const firedRef = useRef(false);
|
|
90
69
|
const isPixelRendering = imageRendering === "pixelated" || imageRendering === "crisp-edges";
|
|
91
|
-
const placeholder = placeholderProp
|
|
92
|
-
const loading = priority ? "eager" : loadingProp
|
|
70
|
+
const placeholder = placeholderProp ?? (isPixelRendering ? "none" : "blur");
|
|
71
|
+
const loading = priority ? "eager" : loadingProp ?? "lazy";
|
|
93
72
|
const aspectRatio = !fill && image.width && image.height ? `${image.width} / ${image.height}` : void 0;
|
|
94
73
|
const srcSet = getImageSrcSet(image);
|
|
95
|
-
const src =
|
|
74
|
+
const src = image.url ?? void 0;
|
|
96
75
|
const hasLqip = placeholder === "blur" && !!image.lqip;
|
|
97
76
|
const placeholderStyle = getImagePlaceholderStyle(image, {
|
|
98
77
|
type: placeholder
|
|
@@ -102,7 +81,7 @@ function Image({
|
|
|
102
81
|
if (firedRef.current) return;
|
|
103
82
|
firedRef.current = true;
|
|
104
83
|
setLoaded(true);
|
|
105
|
-
onLoad
|
|
84
|
+
onLoad?.();
|
|
106
85
|
}, [onLoad]);
|
|
107
86
|
const imgRef = useCallback(
|
|
108
87
|
(node) => {
|
|
@@ -112,10 +91,13 @@ function Image({
|
|
|
112
91
|
},
|
|
113
92
|
[fireLoad]
|
|
114
93
|
);
|
|
115
|
-
const containerStyle =
|
|
94
|
+
const containerStyle = {
|
|
116
95
|
position: "relative",
|
|
117
|
-
overflow: "hidden"
|
|
118
|
-
|
|
96
|
+
overflow: "hidden",
|
|
97
|
+
...fill ? { width: "100%", height: "100%" } : {},
|
|
98
|
+
...aspectRatio ? { aspectRatio } : {},
|
|
99
|
+
...style
|
|
100
|
+
};
|
|
119
101
|
const overlayBase = {
|
|
120
102
|
position: "absolute",
|
|
121
103
|
top: 0,
|
|
@@ -126,41 +108,44 @@ function Image({
|
|
|
126
108
|
transition: "opacity 0.3s ease",
|
|
127
109
|
pointerEvents: "none"
|
|
128
110
|
};
|
|
129
|
-
const mainImgStyle =
|
|
111
|
+
const mainImgStyle = {
|
|
130
112
|
display: "block",
|
|
131
113
|
width: "100%",
|
|
132
114
|
height: "100%",
|
|
133
|
-
objectFit
|
|
134
|
-
|
|
115
|
+
objectFit,
|
|
116
|
+
...imageRendering ? { imageRendering } : {},
|
|
135
117
|
opacity: loaded ? 1 : 0,
|
|
136
|
-
transition: "opacity 0.3s ease"
|
|
137
|
-
|
|
118
|
+
transition: "opacity 0.3s ease",
|
|
119
|
+
...imgStyle
|
|
120
|
+
};
|
|
138
121
|
return /* @__PURE__ */ React.createElement("div", { className, style: containerStyle }, hasLqip && /* @__PURE__ */ React.createElement(
|
|
139
122
|
"img",
|
|
140
123
|
{
|
|
141
124
|
"aria-hidden": true,
|
|
142
125
|
alt: "",
|
|
143
126
|
src: image.lqip,
|
|
144
|
-
style:
|
|
127
|
+
style: {
|
|
128
|
+
...overlayBase,
|
|
145
129
|
display: "block",
|
|
146
130
|
objectFit,
|
|
147
131
|
filter: "blur(20px)",
|
|
148
132
|
transform: "scale(1.1)"
|
|
149
|
-
}
|
|
133
|
+
}
|
|
150
134
|
}
|
|
151
135
|
), placeholderColor && /* @__PURE__ */ React.createElement(
|
|
152
136
|
"div",
|
|
153
137
|
{
|
|
154
138
|
"aria-hidden": true,
|
|
155
|
-
style:
|
|
139
|
+
style: {
|
|
140
|
+
...overlayBase,
|
|
156
141
|
backgroundColor: placeholderColor
|
|
157
|
-
}
|
|
142
|
+
}
|
|
158
143
|
}
|
|
159
144
|
), /* @__PURE__ */ React.createElement(
|
|
160
145
|
"img",
|
|
161
146
|
{
|
|
162
147
|
ref: imgRef,
|
|
163
|
-
alt:
|
|
148
|
+
alt: image.alt ?? "",
|
|
164
149
|
src,
|
|
165
150
|
srcSet: srcSet || void 0,
|
|
166
151
|
sizes,
|
package/dist/ui/image.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/ui/Image/index.tsx","../../src/utils/image.ts"],"sourcesContent":["'use client'\n\nimport React, { useCallback, useRef, useState } from 'react'\nimport type { CSSProperties } from 'react'\nimport type { ImageData } from '../../utils/image'\nimport { getImageSrcSet, getImagePlaceholderStyle } from '../../utils/image'\n\nexport interface ImageProps {\n /** Payload image document */\n image: ImageData\n /** Display width in CSS pixels (for selecting optimal srcset size) */\n width?: number\n /** Device pixel ratio (default: 1) */\n dpr?: number\n /** Placeholder strategy (default: 'blur'; defaults to 'none' when imageRendering is 'pixelated' or 'crisp-edges') */\n placeholder?: 'blur' | 'color' | 'none'\n /** Container className */\n className?: string\n /** Container style */\n style?: CSSProperties\n /** Inner `<img>` className */\n imgClassName?: string\n /** Inner `<img>` style */\n imgStyle?: CSSProperties\n /** HTML sizes attribute */\n sizes?: string\n /** Loading strategy (default: 'lazy'; automatically 'eager' when priority is true) */\n loading?: 'lazy' | 'eager'\n /** Callback when image finishes loading */\n onLoad?: () => void\n /** Object-fit for the image (default: 'cover') */\n objectFit?: 'cover' | 'contain' | 'fill' | 'none' | 'scale-down'\n /** When true, loads eagerly with high fetch priority (for LCP images) */\n priority?: boolean\n /** When true, fills parent container (width/height: 100%, no aspect ratio) */\n fill?: boolean\n /** CSS image-rendering mode (e.g. 'pixelated' for pixel art) */\n imageRendering?: 'auto' | 'pixelated' | 'crisp-edges'\n}\n\n/**\n * Image component with blur-up / color placeholder support.\n *\n * Uses LQIP (Low Quality Image Placeholder) for a smooth blur-up effect,\n * falling back to palette color or no placeholder.\n */\nexport function Image({\n image,\n width,\n dpr = 1,\n placeholder: placeholderProp,\n className,\n style,\n imgClassName,\n imgStyle,\n sizes,\n loading: loadingProp,\n onLoad,\n objectFit = 'cover',\n priority = false,\n fill = false,\n imageRendering,\n}: ImageProps) {\n const [loaded, setLoaded] = useState(false)\n const firedRef = useRef(false)\n\n // Resolve defaults based on other props\n const isPixelRendering =\n imageRendering === 'pixelated' || imageRendering === 'crisp-edges'\n const placeholder = placeholderProp ?? (isPixelRendering ? 'none' : 'blur')\n const loading = priority ? 'eager' : (loadingProp ?? 'lazy')\n\n const aspectRatio =\n !fill && image.width && image.height\n ? `${image.width} / ${image.height}`\n : undefined\n\n const srcSet = getImageSrcSet(image)\n const src = image.url ?? undefined\n\n // Placeholder: LQIP overlay or color overlay (mutually exclusive)\n const hasLqip = placeholder === 'blur' && !!image.lqip\n const placeholderStyle = getImagePlaceholderStyle(image, {\n type: placeholder,\n })\n const placeholderColor =\n !hasLqip && 'backgroundColor' in placeholderStyle\n ? placeholderStyle.backgroundColor\n : undefined\n\n const fireLoad = useCallback(() => {\n if (firedRef.current) return\n firedRef.current = true\n setLoaded(true)\n onLoad?.()\n }, [onLoad])\n\n // Callback ref: detect SSR-cached images that are already loaded\n const imgRef = useCallback(\n (node: HTMLImageElement | null) => {\n if (node && node.complete && node.naturalWidth > 0) {\n fireLoad()\n }\n },\n [fireLoad],\n )\n\n // Container styles\n const containerStyle: CSSProperties = {\n position: 'relative',\n overflow: 'hidden',\n ...(fill ? { width: '100%', height: '100%' } : {}),\n ...(aspectRatio ? { aspectRatio } : {}),\n ...style,\n }\n\n // Shared overlay styles (LQIP and color)\n const overlayBase: CSSProperties = {\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n height: '100%',\n opacity: loaded ? 0 : 1,\n transition: 'opacity 0.3s ease',\n pointerEvents: 'none',\n }\n\n // Main image styles\n const mainImgStyle: CSSProperties = {\n display: 'block',\n width: '100%',\n height: '100%',\n objectFit,\n ...(imageRendering ? { imageRendering } : {}),\n opacity: loaded ? 1 : 0,\n transition: 'opacity 0.3s ease',\n ...imgStyle,\n }\n\n return (\n <div className={className} style={containerStyle}>\n {hasLqip && (\n <img\n aria-hidden\n alt=\"\"\n src={image.lqip!}\n style={{\n ...overlayBase,\n display: 'block',\n objectFit,\n filter: 'blur(20px)',\n transform: 'scale(1.1)',\n }}\n />\n )}\n {placeholderColor && (\n <div\n aria-hidden\n style={{\n ...overlayBase,\n backgroundColor: placeholderColor,\n }}\n />\n )}\n <img\n ref={imgRef}\n alt={image.alt ?? ''}\n src={src}\n srcSet={srcSet || undefined}\n sizes={sizes}\n width={width ? width * dpr : undefined}\n loading={loading}\n decoding=\"async\"\n fetchPriority={priority ? 'high' : undefined}\n onLoad={fireLoad}\n className={imgClassName}\n style={mainImgStyle}\n />\n </div>\n )\n}\n","/** Palette colors extracted from an image */\nexport interface ImagePalette {\n vibrant?: string | null\n muted?: string | null\n darkVibrant?: string | null\n darkMuted?: string | null\n lightVibrant?: string | null\n lightMuted?: string | null\n}\n\n/** Common image data shape from Payload CMS upload collections */\nexport interface ImageData {\n url?: string | null\n width?: number | null\n height?: number | null\n alt?: string | null\n lqip?: string | null\n palette?: ImagePalette | null\n sizes?: Record<\n string,\n | {\n url?: string | null\n width?: number | null\n height?: number | null\n }\n | undefined\n >\n}\n\n/** Pre-generated image size breakpoints (px) */\nexport const IMAGE_SIZES = [384, 768, 1536] as const\n\n/**\n * Returns the optimal image URL for a given display width.\n *\n * Picks the smallest pre-generated size whose width >= displayWidth × dpr.\n * Falls back to the original URL when no matching size exists.\n *\n * @param image - Payload image document\n * @param displayWidth - CSS pixel width the image will be displayed at\n * @param dpr - Device pixel ratio (default: 1)\n * @returns URL string, or empty string if no URL is available\n */\nexport function getImageUrl(\n image: ImageData,\n displayWidth: number,\n dpr: number = 1,\n): string {\n const target = displayWidth * dpr\n const sizes = image.sizes\n\n if (sizes) {\n for (const size of IMAGE_SIZES) {\n if (size >= target) {\n const entry = sizes[String(size)]\n if (entry?.url) return entry.url\n }\n }\n }\n\n return image.url ?? ''\n}\n\n/**\n * Generates an HTML `srcset` attribute string from pre-generated sizes.\n *\n * Includes all available sizes plus the original image.\n * Example output: `\"url-384 384w, url-768 768w, url-1536 1536w, url-original 2000w\"`\n *\n * @param image - Payload image document\n * @returns srcset string, or empty string if no URLs are available\n */\nexport function getImageSrcSet(image: ImageData): string {\n const parts: string[] = []\n const sizes = image.sizes\n\n if (sizes) {\n for (const size of IMAGE_SIZES) {\n const entry = sizes[String(size)]\n if (entry?.url && entry.width) {\n parts.push(`${entry.url} ${entry.width}w`)\n }\n }\n }\n\n if (image.url && image.width) {\n parts.push(`${image.url} ${image.width}w`)\n }\n\n return parts.join(', ')\n}\n\n/**\n * Returns the LQIP (Low Quality Image Placeholder) data URL for an image.\n *\n * @param image - Payload image document\n * @returns LQIP data URL string, or undefined if not available\n */\nexport function getImageLqip(image: ImageData): string | undefined {\n return image.lqip ?? undefined\n}\n\n/**\n * Returns the extracted color palette for an image.\n *\n * @param image - Payload image document\n * @returns ImagePalette object, or undefined if not available\n */\nexport function getImagePalette(image: ImageData): ImagePalette | undefined {\n return image.palette ?? undefined\n}\n\n/** Options for `getImagePlaceholderStyle` */\nexport interface ImagePlaceholderOptions {\n /** Placeholder strategy (default: 'blur') */\n type?: 'blur' | 'color' | 'none'\n /** Which palette color to use for 'color' strategy (default: 'muted') */\n paletteColor?: keyof ImagePalette\n}\n\n/**\n * Returns inline CSS styles for an image placeholder.\n *\n * - `blur`: uses LQIP as background, falls back to palette color, then empty\n * - `color`: uses palette color as background, falls back to empty\n * - `none`: always returns empty\n *\n * @param image - Payload image document\n * @param options - Placeholder options\n * @returns CSS style object compatible with React CSSProperties\n */\nexport function getImagePlaceholderStyle(\n image: ImageData,\n options?: ImagePlaceholderOptions,\n): Record<string, string> {\n const type = options?.type ?? 'blur'\n const paletteColor = options?.paletteColor ?? 'muted'\n\n if (type === 'none') return {}\n\n const color = image.palette?.[paletteColor]\n\n if (type === 'blur') {\n const lqip = image.lqip\n if (lqip) {\n return {\n backgroundImage: `url(${lqip})`,\n backgroundSize: 'cover',\n backgroundPosition: 'center',\n }\n }\n // Cascade: fall back to color\n if (color) {\n return { backgroundColor: color }\n }\n return {}\n }\n\n // type === 'color'\n if (color) {\n return { backgroundColor: color }\n }\n return {}\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/ui/Image/index.tsx","../../src/utils/image.ts"],"sourcesContent":["'use client'\n\nimport React, { useCallback, useRef, useState } from 'react'\nimport type { CSSProperties } from 'react'\nimport type { ImageData } from '../../utils/image'\nimport { getImageSrcSet, getImagePlaceholderStyle } from '../../utils/image'\n\nexport interface ImageProps {\n /** Payload image document */\n image: ImageData\n /** Display width in CSS pixels (for selecting optimal srcset size) */\n width?: number\n /** Device pixel ratio (default: 1) */\n dpr?: number\n /** Placeholder strategy (default: 'blur'; defaults to 'none' when imageRendering is 'pixelated' or 'crisp-edges') */\n placeholder?: 'blur' | 'color' | 'none'\n /** Container className */\n className?: string\n /** Container style */\n style?: CSSProperties\n /** Inner `<img>` className */\n imgClassName?: string\n /** Inner `<img>` style */\n imgStyle?: CSSProperties\n /** HTML sizes attribute */\n sizes?: string\n /** Loading strategy (default: 'lazy'; automatically 'eager' when priority is true) */\n loading?: 'lazy' | 'eager'\n /** Callback when image finishes loading */\n onLoad?: () => void\n /** Object-fit for the image (default: 'cover') */\n objectFit?: 'cover' | 'contain' | 'fill' | 'none' | 'scale-down'\n /** When true, loads eagerly with high fetch priority (for LCP images) */\n priority?: boolean\n /** When true, fills parent container (width/height: 100%, no aspect ratio) */\n fill?: boolean\n /** CSS image-rendering mode (e.g. 'pixelated' for pixel art) */\n imageRendering?: 'auto' | 'pixelated' | 'crisp-edges'\n}\n\n/**\n * Image component with blur-up / color placeholder support.\n *\n * Uses LQIP (Low Quality Image Placeholder) for a smooth blur-up effect,\n * falling back to palette color or no placeholder.\n */\nexport function Image({\n image,\n width,\n dpr = 1,\n placeholder: placeholderProp,\n className,\n style,\n imgClassName,\n imgStyle,\n sizes,\n loading: loadingProp,\n onLoad,\n objectFit = 'cover',\n priority = false,\n fill = false,\n imageRendering,\n}: ImageProps) {\n const [loaded, setLoaded] = useState(false)\n const firedRef = useRef(false)\n\n // Resolve defaults based on other props\n const isPixelRendering =\n imageRendering === 'pixelated' || imageRendering === 'crisp-edges'\n const placeholder = placeholderProp ?? (isPixelRendering ? 'none' : 'blur')\n const loading = priority ? 'eager' : (loadingProp ?? 'lazy')\n\n const aspectRatio =\n !fill && image.width && image.height\n ? `${image.width} / ${image.height}`\n : undefined\n\n const srcSet = getImageSrcSet(image)\n const src = image.url ?? undefined\n\n // Placeholder: LQIP overlay or color overlay (mutually exclusive)\n const hasLqip = placeholder === 'blur' && !!image.lqip\n const placeholderStyle = getImagePlaceholderStyle(image, {\n type: placeholder,\n })\n const placeholderColor =\n !hasLqip && 'backgroundColor' in placeholderStyle\n ? placeholderStyle.backgroundColor\n : undefined\n\n const fireLoad = useCallback(() => {\n if (firedRef.current) return\n firedRef.current = true\n setLoaded(true)\n onLoad?.()\n }, [onLoad])\n\n // Callback ref: detect SSR-cached images that are already loaded\n const imgRef = useCallback(\n (node: HTMLImageElement | null) => {\n if (node && node.complete && node.naturalWidth > 0) {\n fireLoad()\n }\n },\n [fireLoad],\n )\n\n // Container styles\n const containerStyle: CSSProperties = {\n position: 'relative',\n overflow: 'hidden',\n ...(fill ? { width: '100%', height: '100%' } : {}),\n ...(aspectRatio ? { aspectRatio } : {}),\n ...style,\n }\n\n // Shared overlay styles (LQIP and color)\n const overlayBase: CSSProperties = {\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n height: '100%',\n opacity: loaded ? 0 : 1,\n transition: 'opacity 0.3s ease',\n pointerEvents: 'none',\n }\n\n // Main image styles\n const mainImgStyle: CSSProperties = {\n display: 'block',\n width: '100%',\n height: '100%',\n objectFit,\n ...(imageRendering ? { imageRendering } : {}),\n opacity: loaded ? 1 : 0,\n transition: 'opacity 0.3s ease',\n ...imgStyle,\n }\n\n return (\n <div className={className} style={containerStyle}>\n {hasLqip && (\n <img\n aria-hidden\n alt=\"\"\n src={image.lqip!}\n style={{\n ...overlayBase,\n display: 'block',\n objectFit,\n filter: 'blur(20px)',\n transform: 'scale(1.1)',\n }}\n />\n )}\n {placeholderColor && (\n <div\n aria-hidden\n style={{\n ...overlayBase,\n backgroundColor: placeholderColor,\n }}\n />\n )}\n <img\n ref={imgRef}\n alt={image.alt ?? ''}\n src={src}\n srcSet={srcSet || undefined}\n sizes={sizes}\n width={width ? width * dpr : undefined}\n loading={loading}\n decoding=\"async\"\n fetchPriority={priority ? 'high' : undefined}\n onLoad={fireLoad}\n className={imgClassName}\n style={mainImgStyle}\n />\n </div>\n )\n}\n","/** Palette colors extracted from an image */\nexport interface ImagePalette {\n vibrant?: string | null\n muted?: string | null\n darkVibrant?: string | null\n darkMuted?: string | null\n lightVibrant?: string | null\n lightMuted?: string | null\n}\n\n/** Common image data shape from Payload CMS upload collections */\nexport interface ImageData {\n url?: string | null\n width?: number | null\n height?: number | null\n alt?: string | null\n lqip?: string | null\n palette?: ImagePalette | null\n sizes?: Record<\n string,\n | {\n url?: string | null\n width?: number | null\n height?: number | null\n }\n | undefined\n >\n}\n\n/** Pre-generated image size breakpoints (px) */\nexport const IMAGE_SIZES = [384, 768, 1536] as const\n\n/**\n * Returns the optimal image URL for a given display width.\n *\n * Picks the smallest pre-generated size whose width >= displayWidth × dpr.\n * Falls back to the original URL when no matching size exists.\n *\n * @param image - Payload image document\n * @param displayWidth - CSS pixel width the image will be displayed at\n * @param dpr - Device pixel ratio (default: 1)\n * @returns URL string, or empty string if no URL is available\n */\nexport function getImageUrl(\n image: ImageData,\n displayWidth: number,\n dpr: number = 1,\n): string {\n const target = displayWidth * dpr\n const sizes = image.sizes\n\n if (sizes) {\n for (const size of IMAGE_SIZES) {\n if (size >= target) {\n const entry = sizes[String(size)]\n if (entry?.url) return entry.url\n }\n }\n }\n\n return image.url ?? ''\n}\n\n/**\n * Generates an HTML `srcset` attribute string from pre-generated sizes.\n *\n * Includes all available sizes plus the original image.\n * Example output: `\"url-384 384w, url-768 768w, url-1536 1536w, url-original 2000w\"`\n *\n * @param image - Payload image document\n * @returns srcset string, or empty string if no URLs are available\n */\nexport function getImageSrcSet(image: ImageData): string {\n const parts: string[] = []\n const sizes = image.sizes\n\n if (sizes) {\n for (const size of IMAGE_SIZES) {\n const entry = sizes[String(size)]\n if (entry?.url && entry.width) {\n parts.push(`${entry.url} ${entry.width}w`)\n }\n }\n }\n\n if (image.url && image.width) {\n parts.push(`${image.url} ${image.width}w`)\n }\n\n return parts.join(', ')\n}\n\n/**\n * Returns the LQIP (Low Quality Image Placeholder) data URL for an image.\n *\n * @param image - Payload image document\n * @returns LQIP data URL string, or undefined if not available\n */\nexport function getImageLqip(image: ImageData): string | undefined {\n return image.lqip ?? undefined\n}\n\n/**\n * Returns the extracted color palette for an image.\n *\n * @param image - Payload image document\n * @returns ImagePalette object, or undefined if not available\n */\nexport function getImagePalette(image: ImageData): ImagePalette | undefined {\n return image.palette ?? undefined\n}\n\n/** Options for `getImagePlaceholderStyle` */\nexport interface ImagePlaceholderOptions {\n /** Placeholder strategy (default: 'blur') */\n type?: 'blur' | 'color' | 'none'\n /** Which palette color to use for 'color' strategy (default: 'muted') */\n paletteColor?: keyof ImagePalette\n}\n\n/**\n * Returns inline CSS styles for an image placeholder.\n *\n * - `blur`: uses LQIP as background, falls back to palette color, then empty\n * - `color`: uses palette color as background, falls back to empty\n * - `none`: always returns empty\n *\n * @param image - Payload image document\n * @param options - Placeholder options\n * @returns CSS style object compatible with React CSSProperties\n */\nexport function getImagePlaceholderStyle(\n image: ImageData,\n options?: ImagePlaceholderOptions,\n): Record<string, string> {\n const type = options?.type ?? 'blur'\n const paletteColor = options?.paletteColor ?? 'muted'\n\n if (type === 'none') return {}\n\n const color = image.palette?.[paletteColor]\n\n if (type === 'blur') {\n const lqip = image.lqip\n if (lqip) {\n return {\n backgroundImage: `url(${lqip})`,\n backgroundSize: 'cover',\n backgroundPosition: 'center',\n }\n }\n // Cascade: fall back to color\n if (color) {\n return { backgroundColor: color }\n }\n return {}\n }\n\n // type === 'color'\n if (color) {\n return { backgroundColor: color }\n }\n return {}\n}\n"],"mappings":"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","names":[]}
|
package/dist/ui/rich-text.cjs
CHANGED
|
@@ -2,39 +2,10 @@
|
|
|
2
2
|
"use client";
|
|
3
3
|
var __create = Object.create;
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
5
|
-
var __defProps = Object.defineProperties;
|
|
6
5
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
7
|
-
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
8
6
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
9
|
-
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
10
7
|
var __getProtoOf = Object.getPrototypeOf;
|
|
11
8
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
12
|
-
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
13
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
14
|
-
var __spreadValues = (a, b) => {
|
|
15
|
-
for (var prop in b || (b = {}))
|
|
16
|
-
if (__hasOwnProp.call(b, prop))
|
|
17
|
-
__defNormalProp(a, prop, b[prop]);
|
|
18
|
-
if (__getOwnPropSymbols)
|
|
19
|
-
for (var prop of __getOwnPropSymbols(b)) {
|
|
20
|
-
if (__propIsEnum.call(b, prop))
|
|
21
|
-
__defNormalProp(a, prop, b[prop]);
|
|
22
|
-
}
|
|
23
|
-
return a;
|
|
24
|
-
};
|
|
25
|
-
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
26
|
-
var __objRest = (source, exclude) => {
|
|
27
|
-
var target = {};
|
|
28
|
-
for (var prop in source)
|
|
29
|
-
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
30
|
-
target[prop] = source[prop];
|
|
31
|
-
if (source != null && __getOwnPropSymbols)
|
|
32
|
-
for (var prop of __getOwnPropSymbols(source)) {
|
|
33
|
-
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
34
|
-
target[prop] = source[prop];
|
|
35
|
-
}
|
|
36
|
-
return target;
|
|
37
|
-
};
|
|
38
9
|
var __export = (target, all) => {
|
|
39
10
|
for (var name in all)
|
|
40
11
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -79,7 +50,7 @@ function createComponentConverters(components, internalDocToHref) {
|
|
|
79
50
|
const Paragraph = components.Paragraph;
|
|
80
51
|
converters.paragraph = ({ node, nodesToJSX }) => {
|
|
81
52
|
const children = nodesToJSX({ nodes: node.children });
|
|
82
|
-
return /* @__PURE__ */ import_react.default.createElement(Paragraph, { isEmpty: !
|
|
53
|
+
return /* @__PURE__ */ import_react.default.createElement(Paragraph, { isEmpty: !children?.length, node }, children?.length ? children : /* @__PURE__ */ import_react.default.createElement("br", null));
|
|
83
54
|
};
|
|
84
55
|
}
|
|
85
56
|
if (components.Blockquote) {
|
|
@@ -111,11 +82,10 @@ function createComponentConverters(components, internalDocToHref) {
|
|
|
111
82
|
if (components.Link) {
|
|
112
83
|
const Link = components.Link;
|
|
113
84
|
const resolveHref = (node) => {
|
|
114
|
-
var _a;
|
|
115
85
|
if (node.fields.linkType === "internal") {
|
|
116
86
|
return internalDocToHref ? internalDocToHref({ linkNode: node }) : "#";
|
|
117
87
|
}
|
|
118
|
-
return
|
|
88
|
+
return node.fields.url ?? "";
|
|
119
89
|
};
|
|
120
90
|
converters.link = ({ node, nodesToJSX }) => /* @__PURE__ */ import_react.default.createElement(
|
|
121
91
|
Link,
|
|
@@ -127,19 +97,16 @@ function createComponentConverters(components, internalDocToHref) {
|
|
|
127
97
|
},
|
|
128
98
|
nodesToJSX({ nodes: node.children })
|
|
129
99
|
);
|
|
130
|
-
converters.autolink = ({ node, nodesToJSX }) =>
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
nodesToJSX({ nodes: node.children })
|
|
141
|
-
);
|
|
142
|
-
};
|
|
100
|
+
converters.autolink = ({ node, nodesToJSX }) => /* @__PURE__ */ import_react.default.createElement(
|
|
101
|
+
Link,
|
|
102
|
+
{
|
|
103
|
+
href: node.fields.url ?? "",
|
|
104
|
+
rel: node.fields.newTab ? "noopener noreferrer" : void 0,
|
|
105
|
+
target: node.fields.newTab ? "_blank" : void 0,
|
|
106
|
+
node
|
|
107
|
+
},
|
|
108
|
+
nodesToJSX({ nodes: node.children })
|
|
109
|
+
);
|
|
143
110
|
}
|
|
144
111
|
if (components.HorizontalRule) {
|
|
145
112
|
const HorizontalRule = components.HorizontalRule;
|
|
@@ -148,7 +115,6 @@ function createComponentConverters(components, internalDocToHref) {
|
|
|
148
115
|
if (components.Upload) {
|
|
149
116
|
const Upload = components.Upload;
|
|
150
117
|
converters.upload = ({ node }) => {
|
|
151
|
-
var _a;
|
|
152
118
|
const uploadNode = node;
|
|
153
119
|
if (typeof uploadNode.value !== "object") return null;
|
|
154
120
|
const doc = uploadNode.value;
|
|
@@ -156,7 +122,7 @@ function createComponentConverters(components, internalDocToHref) {
|
|
|
156
122
|
Upload,
|
|
157
123
|
{
|
|
158
124
|
src: doc.url,
|
|
159
|
-
alt:
|
|
125
|
+
alt: uploadNode.fields?.alt || doc?.alt || "",
|
|
160
126
|
width: doc.width,
|
|
161
127
|
height: doc.height,
|
|
162
128
|
mimeType: doc.mimeType,
|
|
@@ -191,27 +157,23 @@ function createComponentConverters(components, internalDocToHref) {
|
|
|
191
157
|
}
|
|
192
158
|
return converters;
|
|
193
159
|
}
|
|
194
|
-
function StyledRichTextContent(
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
"components",
|
|
202
|
-
"internalDocToHref",
|
|
203
|
-
"blocks",
|
|
204
|
-
"textState"
|
|
205
|
-
]);
|
|
160
|
+
function StyledRichTextContent({
|
|
161
|
+
components = {},
|
|
162
|
+
internalDocToHref,
|
|
163
|
+
blocks,
|
|
164
|
+
textState,
|
|
165
|
+
...props
|
|
166
|
+
}) {
|
|
206
167
|
const converters = createComponentConverters(components, internalDocToHref);
|
|
207
168
|
return /* @__PURE__ */ import_react.default.createElement(
|
|
208
169
|
RichTextContent,
|
|
209
|
-
|
|
170
|
+
{
|
|
171
|
+
...props,
|
|
210
172
|
internalDocToHref,
|
|
211
173
|
converters,
|
|
212
174
|
blocks,
|
|
213
175
|
textState
|
|
214
|
-
}
|
|
176
|
+
}
|
|
215
177
|
);
|
|
216
178
|
}
|
|
217
179
|
|
|
@@ -221,17 +183,15 @@ function hyphenToCamel(str) {
|
|
|
221
183
|
}
|
|
222
184
|
function createTextStateConverter(state) {
|
|
223
185
|
const defaultTextConverter = import_react3.TextJSXConverter.text;
|
|
224
|
-
return (
|
|
225
|
-
|
|
226
|
-
var _a2, _b2;
|
|
227
|
-
const base = defaultTextConverter(__spreadValues({ node }, rest));
|
|
186
|
+
return ({ node, ...rest }) => {
|
|
187
|
+
const base = defaultTextConverter({ node, ...rest });
|
|
228
188
|
const nodeState = node.$;
|
|
229
189
|
if (!nodeState || typeof nodeState !== "object") return base;
|
|
230
190
|
const style = {};
|
|
231
191
|
for (const stateKey in nodeState) {
|
|
232
192
|
const stateValue = nodeState[stateKey];
|
|
233
193
|
if (!stateValue) continue;
|
|
234
|
-
const css =
|
|
194
|
+
const css = state[stateKey]?.[stateValue]?.css;
|
|
235
195
|
if (css) {
|
|
236
196
|
for (const prop in css) {
|
|
237
197
|
const val = css[prop];
|
|
@@ -252,7 +212,13 @@ function RichTextContent({
|
|
|
252
212
|
disableDefaultConverters,
|
|
253
213
|
textState
|
|
254
214
|
}) {
|
|
255
|
-
const baseConverters =
|
|
215
|
+
const baseConverters = {
|
|
216
|
+
...disableDefaultConverters ? {} : import_react3.defaultJSXConverters,
|
|
217
|
+
...(0, import_react3.LinkJSXConverter)({ internalDocToHref }),
|
|
218
|
+
...textState ? { text: createTextStateConverter(textState) } : {},
|
|
219
|
+
...converters,
|
|
220
|
+
...blocks ? { blocks } : {}
|
|
221
|
+
};
|
|
256
222
|
return /* @__PURE__ */ import_react2.default.createElement(
|
|
257
223
|
import_react3.RichText,
|
|
258
224
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/ui/RichText/index.tsx","../../src/ui/RichText/styled.tsx"],"sourcesContent":["'use client'\n\nimport React from 'react'\nimport {\n SerializedBlockNode,\n SerializedLinkNode,\n} from '@payloadcms/richtext-lexical'\nimport {\n SerializedEditorState,\n SerializedLexicalNode,\n} from '@payloadcms/richtext-lexical/lexical'\nimport {\n defaultJSXConverters,\n JSXConverter,\n JSXConverters,\n LinkJSXConverter,\n RichText,\n TextJSXConverter,\n} from '@payloadcms/richtext-lexical/react'\n\n/**\n * Accepts both Lexical's strict `SerializedEditorState` and Payload's generated\n * richText type (which includes index signatures like `[k: string]: unknown`).\n */\nexport type RichTextData = SerializedEditorState<SerializedLexicalNode> | {\n root: {\n type: string\n children: { type: string; version: number; [k: string]: unknown }[]\n direction: string | null\n format: string\n indent: number\n version: number\n [k: string]: unknown\n }\n [k: string]: unknown\n}\n\nexport type TextStateConfig = {\n [stateKey: string]: {\n [stateValue: string]: {\n css: Record<string, string>\n label: string\n }\n }\n}\n\nexport interface RichTextContentProps {\n data: RichTextData\n className?: string\n internalDocToHref?: (args: { linkNode: SerializedLinkNode }) => string\n converters?: Partial<JSXConverters>\n blocks?: Record<string, JSXConverter<SerializedBlockNode>>\n disableDefaultConverters?: boolean\n textState?: TextStateConfig\n}\n\nexport { StyledRichTextContent } from './styled'\nexport type {\n RichTextComponents,\n StyledRichTextContentProps,\n HeadingSlotProps,\n ParagraphSlotProps,\n BlockquoteSlotProps,\n ListSlotProps,\n ListItemSlotProps,\n LinkSlotProps,\n HorizontalRuleSlotProps,\n UploadSlotProps,\n TableSlotProps,\n TableRowSlotProps,\n TableCellSlotProps,\n} from './styled'\n\nfunction hyphenToCamel(str: string): string {\n return str.replace(/-([a-z])/g, (_, c) => c.toUpperCase())\n}\n\nfunction createTextStateConverter(\n state: TextStateConfig,\n): JSXConverters['text'] {\n const defaultTextConverter = TextJSXConverter.text\n // eslint-disable-next-line react/display-name\n return ({ node, ...rest }) => {\n const base = (\n defaultTextConverter as (...args: unknown[]) => React.ReactNode\n )({ node, ...rest })\n const nodeState = (node as Record<string, unknown>).$ as\n | Record<string, string>\n | undefined\n if (!nodeState || typeof nodeState !== 'object') return base\n\n const style: Record<string, string> = {}\n for (const stateKey in nodeState) {\n const stateValue = nodeState[stateKey]\n if (!stateValue) continue\n const css = state[stateKey]?.[stateValue]?.css\n if (css) {\n for (const prop in css) {\n const val = css[prop]\n if (val) style[hyphenToCamel(prop)] = val\n }\n }\n }\n\n if (Object.keys(style).length === 0) return base\n return <span style={style}>{base}</span>\n }\n}\n\nexport function RichTextContent({\n data,\n className,\n internalDocToHref,\n converters,\n blocks,\n disableDefaultConverters,\n textState,\n}: RichTextContentProps) {\n const baseConverters: JSXConverters = {\n ...(disableDefaultConverters ? {} : defaultJSXConverters),\n ...LinkJSXConverter({ internalDocToHref }),\n ...(textState ? { text: createTextStateConverter(textState) } : {}),\n ...converters,\n ...(blocks ? { blocks } : {}),\n }\n\n return (\n <RichText\n data={data as SerializedEditorState<SerializedLexicalNode>}\n className={className}\n converters={baseConverters}\n />\n )\n}\n","'use client'\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport React from 'react'\nimport { SerializedLinkNode } from '@payloadcms/richtext-lexical'\nimport { JSXConverters } from '@payloadcms/richtext-lexical/react'\nimport { RichTextContent, RichTextContentProps } from './index'\n\n// --- Slot prop types (each slot gets structured data + raw node) ---\n\nexport interface HeadingSlotProps {\n tag: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'\n children: React.ReactNode\n node: any\n}\n\nexport interface ParagraphSlotProps {\n children: React.ReactNode\n isEmpty: boolean\n node: any\n}\n\nexport interface BlockquoteSlotProps {\n children: React.ReactNode\n node: any\n}\n\nexport interface ListSlotProps {\n tag: 'ul' | 'ol'\n listType: string\n children: React.ReactNode\n node: any\n}\n\nexport interface ListItemSlotProps {\n children: React.ReactNode\n hasSubLists: boolean\n checked?: boolean\n value?: number\n node: any\n}\n\nexport interface LinkSlotProps {\n href: string\n target?: string\n rel?: string\n children: React.ReactNode\n node: any\n}\n\nexport interface HorizontalRuleSlotProps {\n node?: any\n}\n\nexport interface UploadSlotProps {\n src: string\n alt: string\n width?: number\n height?: number\n mimeType: string\n filename: string\n sizes?: Record<string, any>\n node: any\n}\n\nexport interface TableSlotProps {\n children: React.ReactNode\n node: any\n}\n\nexport interface TableRowSlotProps {\n children: React.ReactNode\n node: any\n}\n\nexport interface TableCellSlotProps {\n tag: 'th' | 'td'\n children: React.ReactNode\n colSpan?: number\n rowSpan?: number\n backgroundColor?: string\n node: any\n}\n\n// --- Components map ---\n\nexport interface RichTextComponents {\n Heading?: React.ComponentType<HeadingSlotProps>\n Paragraph?: React.ComponentType<ParagraphSlotProps>\n Blockquote?: React.ComponentType<BlockquoteSlotProps>\n List?: React.ComponentType<ListSlotProps>\n ListItem?: React.ComponentType<ListItemSlotProps>\n Link?: React.ComponentType<LinkSlotProps>\n HorizontalRule?: React.ComponentType<HorizontalRuleSlotProps>\n Upload?: React.ComponentType<UploadSlotProps>\n Table?: React.ComponentType<TableSlotProps>\n TableRow?: React.ComponentType<TableRowSlotProps>\n TableCell?: React.ComponentType<TableCellSlotProps>\n}\n\nexport interface StyledRichTextContentProps extends Omit<\n RichTextContentProps,\n 'converters' | 'disableDefaultConverters'\n> {\n components?: RichTextComponents\n}\n\nfunction createComponentConverters(\n components: RichTextComponents,\n internalDocToHref?: (args: { linkNode: SerializedLinkNode }) => string,\n): Partial<JSXConverters> {\n const converters: Partial<JSXConverters> = {}\n\n if (components.Heading) {\n const Heading = components.Heading\n converters.heading = ({ node, nodesToJSX }) => (\n <Heading tag={node.tag} node={node}>\n {nodesToJSX({ nodes: node.children })}\n </Heading>\n )\n }\n\n if (components.Paragraph) {\n const Paragraph = components.Paragraph\n converters.paragraph = ({ node, nodesToJSX }) => {\n const children = nodesToJSX({ nodes: node.children })\n return (\n <Paragraph isEmpty={!children?.length} node={node}>\n {children?.length ? children : <br />}\n </Paragraph>\n )\n }\n }\n\n if (components.Blockquote) {\n const Blockquote = components.Blockquote\n converters.quote = ({ node, nodesToJSX }) => (\n <Blockquote node={node}>\n {nodesToJSX({ nodes: node.children })}\n </Blockquote>\n )\n }\n\n if (components.List) {\n const List = components.List\n converters.list = ({ node, nodesToJSX }) => (\n <List tag={node.tag} listType={node.listType} node={node}>\n {nodesToJSX({ nodes: node.children })}\n </List>\n )\n }\n\n if (components.ListItem) {\n const ListItem = components.ListItem\n converters.listitem = ({ node, nodesToJSX }) => {\n const hasSubLists = node.children.some(\n (child: { type: string }) => child.type === 'list',\n )\n return (\n <ListItem\n hasSubLists={hasSubLists}\n checked={node.checked}\n value={node.value}\n node={node}\n >\n {nodesToJSX({ nodes: node.children })}\n </ListItem>\n )\n }\n }\n\n if (components.Link) {\n const Link = components.Link\n\n const resolveHref = (node: any): string => {\n if (node.fields.linkType === 'internal') {\n return internalDocToHref ? internalDocToHref({ linkNode: node }) : '#'\n }\n return node.fields.url ?? ''\n }\n\n converters.link = ({ node, nodesToJSX }) => (\n <Link\n href={resolveHref(node)}\n rel={node.fields.newTab ? 'noopener noreferrer' : undefined}\n target={node.fields.newTab ? '_blank' : undefined}\n node={node}\n >\n {nodesToJSX({ nodes: node.children })}\n </Link>\n )\n\n converters.autolink = ({ node, nodesToJSX }) => (\n <Link\n href={node.fields.url ?? ''}\n rel={node.fields.newTab ? 'noopener noreferrer' : undefined}\n target={node.fields.newTab ? '_blank' : undefined}\n node={node}\n >\n {nodesToJSX({ nodes: node.children })}\n </Link>\n )\n }\n\n if (components.HorizontalRule) {\n const HorizontalRule = components.HorizontalRule\n converters.horizontalrule = <HorizontalRule />\n }\n\n if (components.Upload) {\n const Upload = components.Upload\n converters.upload = ({ node }) => {\n const uploadNode = node as any\n if (typeof uploadNode.value !== 'object') return null\n const doc = uploadNode.value\n return (\n <Upload\n src={doc.url}\n alt={uploadNode.fields?.alt || doc?.alt || ''}\n width={doc.width}\n height={doc.height}\n mimeType={doc.mimeType}\n filename={doc.filename}\n sizes={doc.sizes}\n node={node}\n />\n )\n }\n }\n\n if (components.Table) {\n const Table = components.Table\n converters.table = ({ node, nodesToJSX }) => (\n <Table node={node}>{nodesToJSX({ nodes: node.children })}</Table>\n )\n }\n\n if (components.TableRow) {\n const TableRow = components.TableRow\n converters.tablerow = ({ node, nodesToJSX }) => (\n <TableRow node={node}>{nodesToJSX({ nodes: node.children })}</TableRow>\n )\n }\n\n if (components.TableCell) {\n const TableCell = components.TableCell\n converters.tablecell = ({ node, nodesToJSX }) => (\n <TableCell\n tag={node.headerState > 0 ? 'th' : 'td'}\n colSpan={node.colSpan > 1 ? node.colSpan : undefined}\n rowSpan={node.rowSpan > 1 ? node.rowSpan : undefined}\n backgroundColor={node.backgroundColor || undefined}\n node={node}\n >\n {nodesToJSX({ nodes: node.children })}\n </TableCell>\n )\n }\n\n return converters\n}\n\nexport function StyledRichTextContent({\n components = {},\n internalDocToHref,\n blocks,\n textState,\n ...props\n}: StyledRichTextContentProps) {\n const converters = createComponentConverters(components, internalDocToHref)\n\n return (\n <RichTextContent\n {...props}\n internalDocToHref={internalDocToHref}\n converters={converters}\n blocks={blocks}\n textState={textState}\n />\n )\n}\n"],"mappings":"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","names":["import_react","React","_a","_b","React"]}
|
|
1
|
+
{"version":3,"sources":["../../src/ui/RichText/index.tsx","../../src/ui/RichText/styled.tsx"],"sourcesContent":["'use client'\n\nimport React from 'react'\nimport {\n SerializedBlockNode,\n SerializedLinkNode,\n} from '@payloadcms/richtext-lexical'\nimport {\n SerializedEditorState,\n SerializedLexicalNode,\n} from '@payloadcms/richtext-lexical/lexical'\nimport {\n defaultJSXConverters,\n JSXConverter,\n JSXConverters,\n LinkJSXConverter,\n RichText,\n TextJSXConverter,\n} from '@payloadcms/richtext-lexical/react'\n\n/**\n * Accepts both Lexical's strict `SerializedEditorState` and Payload's generated\n * richText type (which includes index signatures like `[k: string]: unknown`).\n */\nexport type RichTextData = SerializedEditorState<SerializedLexicalNode> | {\n root: {\n type: string\n children: { type: string; version: number; [k: string]: unknown }[]\n direction: string | null\n format: string\n indent: number\n version: number\n [k: string]: unknown\n }\n [k: string]: unknown\n}\n\nexport type TextStateConfig = {\n [stateKey: string]: {\n [stateValue: string]: {\n css: Record<string, string>\n label: string\n }\n }\n}\n\nexport interface RichTextContentProps {\n data: RichTextData\n className?: string\n internalDocToHref?: (args: { linkNode: SerializedLinkNode }) => string\n converters?: Partial<JSXConverters>\n blocks?: Record<string, JSXConverter<SerializedBlockNode>>\n disableDefaultConverters?: boolean\n textState?: TextStateConfig\n}\n\nexport { StyledRichTextContent } from './styled'\nexport type {\n RichTextComponents,\n StyledRichTextContentProps,\n HeadingSlotProps,\n ParagraphSlotProps,\n BlockquoteSlotProps,\n ListSlotProps,\n ListItemSlotProps,\n LinkSlotProps,\n HorizontalRuleSlotProps,\n UploadSlotProps,\n TableSlotProps,\n TableRowSlotProps,\n TableCellSlotProps,\n} from './styled'\n\nfunction hyphenToCamel(str: string): string {\n return str.replace(/-([a-z])/g, (_, c) => c.toUpperCase())\n}\n\nfunction createTextStateConverter(\n state: TextStateConfig,\n): JSXConverters['text'] {\n const defaultTextConverter = TextJSXConverter.text\n // eslint-disable-next-line react/display-name\n return ({ node, ...rest }) => {\n const base = (\n defaultTextConverter as (...args: unknown[]) => React.ReactNode\n )({ node, ...rest })\n const nodeState = (node as Record<string, unknown>).$ as\n | Record<string, string>\n | undefined\n if (!nodeState || typeof nodeState !== 'object') return base\n\n const style: Record<string, string> = {}\n for (const stateKey in nodeState) {\n const stateValue = nodeState[stateKey]\n if (!stateValue) continue\n const css = state[stateKey]?.[stateValue]?.css\n if (css) {\n for (const prop in css) {\n const val = css[prop]\n if (val) style[hyphenToCamel(prop)] = val\n }\n }\n }\n\n if (Object.keys(style).length === 0) return base\n return <span style={style}>{base}</span>\n }\n}\n\nexport function RichTextContent({\n data,\n className,\n internalDocToHref,\n converters,\n blocks,\n disableDefaultConverters,\n textState,\n}: RichTextContentProps) {\n const baseConverters: JSXConverters = {\n ...(disableDefaultConverters ? {} : defaultJSXConverters),\n ...LinkJSXConverter({ internalDocToHref }),\n ...(textState ? { text: createTextStateConverter(textState) } : {}),\n ...converters,\n ...(blocks ? { blocks } : {}),\n }\n\n return (\n <RichText\n data={data as SerializedEditorState<SerializedLexicalNode>}\n className={className}\n converters={baseConverters}\n />\n )\n}\n","'use client'\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\nimport React from 'react'\nimport { SerializedLinkNode } from '@payloadcms/richtext-lexical'\nimport { JSXConverters } from '@payloadcms/richtext-lexical/react'\nimport { RichTextContent, RichTextContentProps } from './index'\n\n// --- Slot prop types (each slot gets structured data + raw node) ---\n\nexport interface HeadingSlotProps {\n tag: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'\n children: React.ReactNode\n node: any\n}\n\nexport interface ParagraphSlotProps {\n children: React.ReactNode\n isEmpty: boolean\n node: any\n}\n\nexport interface BlockquoteSlotProps {\n children: React.ReactNode\n node: any\n}\n\nexport interface ListSlotProps {\n tag: 'ul' | 'ol'\n listType: string\n children: React.ReactNode\n node: any\n}\n\nexport interface ListItemSlotProps {\n children: React.ReactNode\n hasSubLists: boolean\n checked?: boolean\n value?: number\n node: any\n}\n\nexport interface LinkSlotProps {\n href: string\n target?: string\n rel?: string\n children: React.ReactNode\n node: any\n}\n\nexport interface HorizontalRuleSlotProps {\n node?: any\n}\n\nexport interface UploadSlotProps {\n src: string\n alt: string\n width?: number\n height?: number\n mimeType: string\n filename: string\n sizes?: Record<string, any>\n node: any\n}\n\nexport interface TableSlotProps {\n children: React.ReactNode\n node: any\n}\n\nexport interface TableRowSlotProps {\n children: React.ReactNode\n node: any\n}\n\nexport interface TableCellSlotProps {\n tag: 'th' | 'td'\n children: React.ReactNode\n colSpan?: number\n rowSpan?: number\n backgroundColor?: string\n node: any\n}\n\n// --- Components map ---\n\nexport interface RichTextComponents {\n Heading?: React.ComponentType<HeadingSlotProps>\n Paragraph?: React.ComponentType<ParagraphSlotProps>\n Blockquote?: React.ComponentType<BlockquoteSlotProps>\n List?: React.ComponentType<ListSlotProps>\n ListItem?: React.ComponentType<ListItemSlotProps>\n Link?: React.ComponentType<LinkSlotProps>\n HorizontalRule?: React.ComponentType<HorizontalRuleSlotProps>\n Upload?: React.ComponentType<UploadSlotProps>\n Table?: React.ComponentType<TableSlotProps>\n TableRow?: React.ComponentType<TableRowSlotProps>\n TableCell?: React.ComponentType<TableCellSlotProps>\n}\n\nexport interface StyledRichTextContentProps extends Omit<\n RichTextContentProps,\n 'converters' | 'disableDefaultConverters'\n> {\n components?: RichTextComponents\n}\n\nfunction createComponentConverters(\n components: RichTextComponents,\n internalDocToHref?: (args: { linkNode: SerializedLinkNode }) => string,\n): Partial<JSXConverters> {\n const converters: Partial<JSXConverters> = {}\n\n if (components.Heading) {\n const Heading = components.Heading\n converters.heading = ({ node, nodesToJSX }) => (\n <Heading tag={node.tag} node={node}>\n {nodesToJSX({ nodes: node.children })}\n </Heading>\n )\n }\n\n if (components.Paragraph) {\n const Paragraph = components.Paragraph\n converters.paragraph = ({ node, nodesToJSX }) => {\n const children = nodesToJSX({ nodes: node.children })\n return (\n <Paragraph isEmpty={!children?.length} node={node}>\n {children?.length ? children : <br />}\n </Paragraph>\n )\n }\n }\n\n if (components.Blockquote) {\n const Blockquote = components.Blockquote\n converters.quote = ({ node, nodesToJSX }) => (\n <Blockquote node={node}>\n {nodesToJSX({ nodes: node.children })}\n </Blockquote>\n )\n }\n\n if (components.List) {\n const List = components.List\n converters.list = ({ node, nodesToJSX }) => (\n <List tag={node.tag} listType={node.listType} node={node}>\n {nodesToJSX({ nodes: node.children })}\n </List>\n )\n }\n\n if (components.ListItem) {\n const ListItem = components.ListItem\n converters.listitem = ({ node, nodesToJSX }) => {\n const hasSubLists = node.children.some(\n (child: { type: string }) => child.type === 'list',\n )\n return (\n <ListItem\n hasSubLists={hasSubLists}\n checked={node.checked}\n value={node.value}\n node={node}\n >\n {nodesToJSX({ nodes: node.children })}\n </ListItem>\n )\n }\n }\n\n if (components.Link) {\n const Link = components.Link\n\n const resolveHref = (node: any): string => {\n if (node.fields.linkType === 'internal') {\n return internalDocToHref ? internalDocToHref({ linkNode: node }) : '#'\n }\n return node.fields.url ?? ''\n }\n\n converters.link = ({ node, nodesToJSX }) => (\n <Link\n href={resolveHref(node)}\n rel={node.fields.newTab ? 'noopener noreferrer' : undefined}\n target={node.fields.newTab ? '_blank' : undefined}\n node={node}\n >\n {nodesToJSX({ nodes: node.children })}\n </Link>\n )\n\n converters.autolink = ({ node, nodesToJSX }) => (\n <Link\n href={node.fields.url ?? ''}\n rel={node.fields.newTab ? 'noopener noreferrer' : undefined}\n target={node.fields.newTab ? '_blank' : undefined}\n node={node}\n >\n {nodesToJSX({ nodes: node.children })}\n </Link>\n )\n }\n\n if (components.HorizontalRule) {\n const HorizontalRule = components.HorizontalRule\n converters.horizontalrule = <HorizontalRule />\n }\n\n if (components.Upload) {\n const Upload = components.Upload\n converters.upload = ({ node }) => {\n const uploadNode = node as any\n if (typeof uploadNode.value !== 'object') return null\n const doc = uploadNode.value\n return (\n <Upload\n src={doc.url}\n alt={uploadNode.fields?.alt || doc?.alt || ''}\n width={doc.width}\n height={doc.height}\n mimeType={doc.mimeType}\n filename={doc.filename}\n sizes={doc.sizes}\n node={node}\n />\n )\n }\n }\n\n if (components.Table) {\n const Table = components.Table\n converters.table = ({ node, nodesToJSX }) => (\n <Table node={node}>{nodesToJSX({ nodes: node.children })}</Table>\n )\n }\n\n if (components.TableRow) {\n const TableRow = components.TableRow\n converters.tablerow = ({ node, nodesToJSX }) => (\n <TableRow node={node}>{nodesToJSX({ nodes: node.children })}</TableRow>\n )\n }\n\n if (components.TableCell) {\n const TableCell = components.TableCell\n converters.tablecell = ({ node, nodesToJSX }) => (\n <TableCell\n tag={node.headerState > 0 ? 'th' : 'td'}\n colSpan={node.colSpan > 1 ? node.colSpan : undefined}\n rowSpan={node.rowSpan > 1 ? node.rowSpan : undefined}\n backgroundColor={node.backgroundColor || undefined}\n node={node}\n >\n {nodesToJSX({ nodes: node.children })}\n </TableCell>\n )\n }\n\n return converters\n}\n\nexport function StyledRichTextContent({\n components = {},\n internalDocToHref,\n blocks,\n textState,\n ...props\n}: StyledRichTextContentProps) {\n const converters = createComponentConverters(components, internalDocToHref)\n\n return (\n <RichTextContent\n {...props}\n internalDocToHref={internalDocToHref}\n converters={converters}\n blocks={blocks}\n textState={textState}\n />\n )\n}\n"],"mappings":"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","names":["import_react","React","React"]}
|