fimo 0.12.0-staging.1 → 0.12.0-staging.2

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.
Files changed (66) hide show
  1. package/assets/skills/fimo-studio/SKILL.md +3 -1
  2. package/assets/skills/fimo-studio/references/ai-chat.md +1 -1
  3. package/assets/skills/fimo-studio/references/command-palette.md +31 -0
  4. package/dist/cli/bundle.json +1 -1
  5. package/dist/cli/index.js +4 -4
  6. package/dist/runtime/next/client.d.ts +8 -1
  7. package/dist/runtime/next/client.js +8 -1
  8. package/dist/runtime/next/{Text.d.ts → primitives/Text.d.ts} +1 -1
  9. package/dist/runtime/next/{Text.js → primitives/Text.js} +1 -1
  10. package/dist/runtime/next/primitives/server.d.ts +9 -0
  11. package/dist/runtime/next/primitives/server.js +46 -0
  12. package/dist/runtime/next/server.d.ts +3 -1
  13. package/dist/runtime/next/server.js +3 -1
  14. package/dist/runtime/primitives/index.d.ts +10 -10
  15. package/dist/runtime/primitives/index.js +10 -10
  16. package/dist/runtime/primitives/lib/image-optimization.d.ts +10 -1
  17. package/dist/runtime/primitives/lib/image-optimization.js +12 -12
  18. package/dist/runtime/primitives/lib/index.d.ts +0 -1
  19. package/dist/runtime/primitives/lib/index.js +0 -1
  20. package/dist/runtime/react/primitives/contracts.d.ts +56 -0
  21. package/dist/runtime/react/primitives/contracts.js +1 -0
  22. package/dist/runtime/react/primitives/editable/Boolean.d.ts +5 -0
  23. package/dist/runtime/react/primitives/editable/Boolean.js +11 -0
  24. package/dist/runtime/react/primitives/editable/Date.d.ts +4 -0
  25. package/dist/runtime/react/primitives/editable/Date.js +12 -0
  26. package/dist/runtime/react/primitives/editable/Image.d.ts +4 -0
  27. package/dist/runtime/react/primitives/editable/Image.js +10 -0
  28. package/dist/runtime/react/primitives/editable/Json.d.ts +5 -0
  29. package/dist/runtime/react/primitives/editable/Json.js +11 -0
  30. package/dist/runtime/react/primitives/editable/RichText.d.ts +4 -0
  31. package/dist/runtime/react/primitives/editable/RichText.js +11 -0
  32. package/dist/runtime/{primitives/components → react/primitives/editable}/Text.d.ts +3 -6
  33. package/dist/runtime/{primitives/components → react/primitives/editable}/Text.js +2 -1
  34. package/dist/runtime/react/primitives/editable/Video.d.ts +4 -0
  35. package/dist/runtime/react/primitives/editable/Video.js +10 -0
  36. package/dist/runtime/react/primitives/renderers/DateRenderer.d.ts +11 -0
  37. package/dist/runtime/react/primitives/renderers/DateRenderer.js +14 -0
  38. package/dist/runtime/react/primitives/renderers/ImageRenderer.d.ts +8 -0
  39. package/dist/runtime/react/primitives/renderers/ImageRenderer.js +50 -0
  40. package/dist/runtime/react/primitives/renderers/RichTextRenderer.d.ts +11 -0
  41. package/dist/runtime/{primitives/components/RichText.js → react/primitives/renderers/RichTextRenderer.js} +4 -6
  42. package/dist/runtime/{primitives/components → react/primitives/renderers}/StaticImage.d.ts +2 -11
  43. package/dist/runtime/{primitives/components → react/primitives/renderers}/StaticImage.js +5 -3
  44. package/dist/runtime/react/primitives/renderers/VideoRenderer.d.ts +8 -0
  45. package/dist/runtime/react/primitives/renderers/VideoRenderer.js +10 -0
  46. package/dist/runtime/{primitives/lib → react}/useFimoLiveValue.d.ts +3 -3
  47. package/dist/runtime/{primitives/lib → react}/useFimoLiveValue.js +3 -3
  48. package/dist/runtime/vite/primitives/Images.d.ts +4 -0
  49. package/dist/runtime/vite/primitives/Images.js +12 -0
  50. package/dist/runtime/{primitives → vite}/translations.d.ts +1 -1
  51. package/dist/runtime/{primitives → vite}/translations.js +1 -1
  52. package/package.json +1 -1
  53. package/templates/react-router/package.json +1 -1
  54. package/dist/runtime/primitives/components/Boolean.d.ts +0 -29
  55. package/dist/runtime/primitives/components/Boolean.js +0 -33
  56. package/dist/runtime/primitives/components/Date.d.ts +0 -30
  57. package/dist/runtime/primitives/components/Date.js +0 -43
  58. package/dist/runtime/primitives/components/Image.d.ts +0 -72
  59. package/dist/runtime/primitives/components/Image.js +0 -108
  60. package/dist/runtime/primitives/components/Json.d.ts +0 -25
  61. package/dist/runtime/primitives/components/Json.js +0 -29
  62. package/dist/runtime/primitives/components/RichText.d.ts +0 -9
  63. package/dist/runtime/primitives/components/Video.d.ts +0 -31
  64. package/dist/runtime/primitives/components/Video.js +0 -34
  65. package/dist/runtime/primitives/components/index.d.ts +0 -6
  66. package/dist/runtime/primitives/components/index.js +0 -5
@@ -1,6 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Fragment } from 'react';
3
- import { FIMO_SOURCE, useFimoLiveValue, } from '../lib/index.js';
4
3
  function DefaultParagraph({ children }) {
5
4
  return _jsx("p", { children: children });
6
5
  }
@@ -118,7 +117,7 @@ function renderNode(node, components, key) {
118
117
  }
119
118
  return _jsx(Fragment, { children: result }, key);
120
119
  }
121
- const children = node.content?.map((child, i) => renderNode(child, components, i)) ?? null;
120
+ const children = node.content?.map((child, index) => renderNode(child, components, index)) ?? null;
122
121
  if (node.type === 'doc') {
123
122
  return _jsx(Fragment, { children: children }, key);
124
123
  }
@@ -128,10 +127,9 @@ function renderNode(node, components, key) {
128
127
  }
129
128
  return _jsx(Fragment, { children: children }, key);
130
129
  }
131
- export function RichText({ value, components, ...props }) {
132
- const { value: liveContent, ref } = useFimoLiveValue(value?.content ?? null);
133
- if (!value || !liveContent) {
130
+ export function RichTextRenderer({ document, source, components, elementRef, ...props }) {
131
+ if (!document) {
134
132
  return null;
135
133
  }
136
- return (_jsx("div", { ref: ref, ...props, "data-fimo-source": value[FIMO_SOURCE], "data-fimo-richtext": "", children: renderNode(liveContent, components, 0) }));
134
+ return (_jsx("div", { ref: elementRef, ...props, "data-fimo-source": source, "data-fimo-richtext": "", children: renderNode(document, components, 0) }));
137
135
  }
@@ -1,13 +1,5 @@
1
- import type { ComponentPropsWithoutRef } from 'react';
2
- import { type ImageFit } from '../lib/image-optimization.js';
3
- type StaticImageProps = Omit<ComponentPropsWithoutRef<'img'>, 'children'> & {
4
- /** Image quality (1-100). Defaults to 85. */
5
- quality?: number;
6
- /** Resize fit mode. Also maps to CSS object-fit. Defaults to 'scale-down'. */
7
- fit?: ImageFit;
8
- /** Skip optimization and use original URL. */
9
- unoptimized?: boolean;
10
- };
1
+ import type { StaticImageProps } from '../contracts.js';
2
+ export type { StaticImageProps } from '../contracts.js';
11
3
  /**
12
4
  * Optimized image component for non-schema images.
13
5
  *
@@ -40,5 +32,4 @@ type StaticImageProps = Omit<ComponentPropsWithoutRef<'img'>, 'children'> & {
40
32
  * <StaticImage src="/images/logo.svg" alt="Logo" unoptimized />
41
33
  */
42
34
  export declare function StaticImage(props: StaticImageProps): import("react/jsx-runtime").JSX.Element | null;
43
- export {};
44
35
  //# sourceMappingURL=StaticImage.d.ts.map
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { clampQuality, resolveFit, toObjectFit, toPositiveInt, isOptimizableFimoUrl, buildOptimizedUrl, computeImageOptimizationConfig, } from '../lib/image-optimization.js';
2
+ import { clampQuality, resolveFit, toObjectFit, toPositiveInt, isOptimizableFimoUrl, buildOptimizedUrl, computeImageOptimizationConfig, } from '../../../primitives/lib/image-optimization.js';
3
3
  /**
4
4
  * Optimized image component for non-schema images.
5
5
  *
@@ -32,7 +32,7 @@ import { clampQuality, resolveFit, toObjectFit, toPositiveInt, isOptimizableFimo
32
32
  * <StaticImage src="/images/logo.svg" alt="Logo" unoptimized />
33
33
  */
34
34
  export function StaticImage(props) {
35
- const { src, alt, quality, unoptimized = false, fit, width, height, srcSet: srcSetOverride, sizes, style, ...imgProps } = props;
35
+ const { src, alt, quality, unoptimized = false, fit, width, height, srcSet: srcSetOverride, sizes, style, hostSuffixes, ...imgProps } = props;
36
36
  if (!src) {
37
37
  return null;
38
38
  }
@@ -42,7 +42,7 @@ export function StaticImage(props) {
42
42
  const requestedHeight = toPositiveInt(height);
43
43
  const hasSizesAttr = typeof sizes === 'string' && sizes.trim().length > 0;
44
44
  const hasSizingHint = hasSizesAttr || requestedWidth !== undefined || requestedHeight !== undefined;
45
- const canOptimizeSource = !unoptimized && isOptimizableFimoUrl(src);
45
+ const canOptimizeSource = !unoptimized && isOptimizableFimoUrl(src, hostSuffixes);
46
46
  const shouldOptimize = canOptimizeSource && hasSizingHint;
47
47
  const { generatedSrcSet, transformWidth, transformDpr } = computeImageOptimizationConfig({
48
48
  shouldOptimize,
@@ -53,6 +53,7 @@ export function StaticImage(props) {
53
53
  renderWidth: requestedWidth,
54
54
  quality: normalizedQuality,
55
55
  fit: normalizedFit,
56
+ hostSuffixes,
56
57
  });
57
58
  const finalSrcSet = srcSetOverride ?? generatedSrcSet;
58
59
  const optimizedSrc = shouldOptimize
@@ -61,6 +62,7 @@ export function StaticImage(props) {
61
62
  quality: normalizedQuality,
62
63
  fit: normalizedFit,
63
64
  dpr: transformDpr,
65
+ hostSuffixes,
64
66
  })
65
67
  : src;
66
68
  const finalStyle = style?.objectFit
@@ -0,0 +1,8 @@
1
+ import { type RefObject } from 'react';
2
+ import type { VideoProps } from '../contracts.js';
3
+ interface VideoRendererProps extends VideoProps {
4
+ elementRef?: RefObject<HTMLElement | null>;
5
+ }
6
+ export declare function VideoRenderer({ value: media, children, overrideSrc, autoPlay, loop, muted, playsInline, style, elementRef, ...videoProps }: VideoRendererProps): import("react/jsx-runtime").JSX.Element;
7
+ export {};
8
+ //# sourceMappingURL=VideoRenderer.d.ts.map
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { FIMO_SOURCE } from '../../../primitives/lib/primitives.js';
3
+ export function VideoRenderer({ value: media, children, overrideSrc, autoPlay = true, loop = true, muted = true, playsInline = true, style, elementRef, ...videoProps }) {
4
+ const mediaSource = media[FIMO_SOURCE];
5
+ if (children) {
6
+ return (_jsx("span", { ref: elementRef, "data-fimo-source": mediaSource, children: children(media) }));
7
+ }
8
+ const finalSrc = overrideSrc ?? media.url;
9
+ return (_jsx("video", { ref: elementRef, src: finalSrc, width: media.width, height: media.height, autoPlay: autoPlay, loop: loop, muted: muted, playsInline: playsInline, style: style, ...videoProps, "data-fimo-source": mediaSource }));
10
+ }
@@ -9,9 +9,9 @@ import { type RefObject } from 'react';
9
9
  * preview knows to dispatch events instead of falling back to raw DOM writes,
10
10
  * and updates internal state when a mutation arrives.
11
11
  *
12
- * The subscription is framework-neutral: Vite and Next.js render the same
13
- * primitives, and environments that never dispatch `fimo:live-edit` simply
14
- * keep mirroring the external value.
12
+ * The hook is framework-adapter-neutral: Vite and Next.js clients render the
13
+ * same React primitives, and environments that never dispatch
14
+ * `fimo:live-edit` simply keep mirroring the external value.
15
15
  */
16
16
  export declare function useFimoLiveValue<T, E extends HTMLElement = HTMLElement>(external: T): {
17
17
  value: T;
@@ -9,9 +9,9 @@ import { useEffect, useRef, useState } from 'react';
9
9
  * preview knows to dispatch events instead of falling back to raw DOM writes,
10
10
  * and updates internal state when a mutation arrives.
11
11
  *
12
- * The subscription is framework-neutral: Vite and Next.js render the same
13
- * primitives, and environments that never dispatch `fimo:live-edit` simply
14
- * keep mirroring the external value.
12
+ * The hook is framework-adapter-neutral: Vite and Next.js clients render the
13
+ * same React primitives, and environments that never dispatch
14
+ * `fimo:live-edit` simply keep mirroring the external value.
15
15
  */
16
16
  export function useFimoLiveValue(external) {
17
17
  const ref = useRef(null);
@@ -0,0 +1,4 @@
1
+ import type { ImageProps, StaticImageProps } from '../../react/primitives/contracts.js';
2
+ export declare function Image(props: ImageProps): import("react/jsx-runtime").JSX.Element;
3
+ export declare function StaticImage(props: StaticImageProps): import("react/jsx-runtime").JSX.Element;
4
+ //# sourceMappingURL=Images.d.ts.map
@@ -0,0 +1,12 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { parseImageHostSuffixes } from '../../primitives/lib/image-optimization.js';
3
+ import { Image as BaseImage } from '../../react/primitives/editable/Image.js';
4
+ import { StaticImage as BaseStaticImage } from '../../react/primitives/renderers/StaticImage.js';
5
+ const viteEnvironment = import.meta.env;
6
+ const IMAGE_HOST_SUFFIXES = parseImageHostSuffixes(viteEnvironment?.VITE_FIMO_IMAGE_HOSTS);
7
+ export function Image(props) {
8
+ return _jsx(BaseImage, { ...props, hostSuffixes: IMAGE_HOST_SUFFIXES });
9
+ }
10
+ export function StaticImage(props) {
11
+ return _jsx(BaseStaticImage, { ...props, hostSuffixes: IMAGE_HOST_SUFFIXES });
12
+ }
@@ -1,4 +1,4 @@
1
- import { FimoString } from './lib/index.js';
1
+ import { FimoString } from '../primitives/lib/index.js';
2
2
  /**
3
3
  * Hook to provide a label function (`t`).
4
4
  *
@@ -1,7 +1,7 @@
1
1
  import { useSyncExternalStore } from 'react';
2
2
  import { defaultLocale as bundledDefaultLocale, dictionaries as bundledDictionaries, signature as translationSignature, updatedAt as bundledUpdatedAt, } from 'virtual:translations';
3
3
  import { useLocale } from '../i18n/FimoLocaleContext.js';
4
- import { FimoString } from './lib/index.js';
4
+ import { FimoString } from '../primitives/lib/index.js';
5
5
  const labelListeners = new Set();
6
6
  let labelState = {
7
7
  dictionaries: bundledDictionaries ?? {},
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fimo",
3
- "version": "0.12.0-staging.1",
3
+ "version": "0.12.0-staging.2",
4
4
  "description": "Fimo CLI - create, deploy, and manage Fimo projects",
5
5
  "bin": {
6
6
  "fimo": "dist/cli/index.js"
@@ -21,7 +21,7 @@
21
21
  "cmdk": "^1.1.1",
22
22
  "date-fns": "^4.1.0",
23
23
  "embla-carousel-react": "^8.6.0",
24
- "fimo": "0.12.0-staging.1",
24
+ "fimo": "0.12.0-staging.2",
25
25
  "input-otp": "^1.4.2",
26
26
  "isbot": "^5",
27
27
  "lucide-react": "^0.577.0",
@@ -1,29 +0,0 @@
1
- import { type ComponentPropsWithoutRef, type ElementType, type ReactNode } from 'react';
2
- import { type FimoBoolean } from '../lib/index.js';
3
- type BooleanProps<T extends ElementType = 'span'> = {
4
- value: FimoBoolean;
5
- as?: T;
6
- children?: (value: boolean) => ReactNode;
7
- } & Omit<ComponentPropsWithoutRef<T>, 'value' | 'as' | 'children'>;
8
- /**
9
- * Boolean component for rendering boolean values with source tracking
10
- *
11
- * Use children render function to customize how the boolean is displayed.
12
- *
13
- * @example
14
- * // Default (renders "true" or "false")
15
- * <Boolean value={product.inStock} />
16
- *
17
- * // With render function for custom display
18
- * <Boolean value={product.inStock}>
19
- * {(val) => val ? '✓ In Stock' : '✗ Out of Stock'}
20
- * </Boolean>
21
- *
22
- * // Conditional styling
23
- * <Boolean value={product.featured}>
24
- * {(val) => val && <span className="badge">Featured</span>}
25
- * </Boolean>
26
- */
27
- export declare function Boolean<T extends ElementType = 'span'>({ value, as, children, ...props }: BooleanProps<T>): import("react/jsx-runtime").JSX.Element | null;
28
- export {};
29
- //# sourceMappingURL=Boolean.d.ts.map
@@ -1,33 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { FIMO_SOURCE, useFimoLiveValue } from '../lib/index.js';
3
- /**
4
- * Boolean component for rendering boolean values with source tracking
5
- *
6
- * Use children render function to customize how the boolean is displayed.
7
- *
8
- * @example
9
- * // Default (renders "true" or "false")
10
- * <Boolean value={product.inStock} />
11
- *
12
- * // With render function for custom display
13
- * <Boolean value={product.inStock}>
14
- * {(val) => val ? '✓ In Stock' : '✗ Out of Stock'}
15
- * </Boolean>
16
- *
17
- * // Conditional styling
18
- * <Boolean value={product.featured}>
19
- * {(val) => val && <span className="badge">Featured</span>}
20
- * </Boolean>
21
- */
22
- export function Boolean({ value, as, children, ...props }) {
23
- const Component = as || 'span';
24
- const { value: liveBool, ref } = useFimoLiveValue(value ? value.valueOf() : false);
25
- // Defensive: return null if no value
26
- if (!value) {
27
- return null;
28
- }
29
- const source = value[FIMO_SOURCE];
30
- // Use render function if provided, otherwise display raw boolean
31
- const content = children ? children(liveBool) : String(liveBool);
32
- return (_jsx(Component, { ref: ref, ...props, "data-fimo-source": source, children: content }));
33
- }
@@ -1,30 +0,0 @@
1
- import { type ReactNode } from 'react';
2
- import { type FimoDate, type FimoString } from '../lib/index.js';
3
- type DateProps = {
4
- value: FimoDate | FimoString | Date | string;
5
- children?: (date: Date) => ReactNode;
6
- className?: string;
7
- };
8
- /**
9
- * Date component for rendering dates with source tracking
10
- *
11
- * Default format uses browser's locale (e.g., "28 ene 2026" in Spain, "Jan 28, 2026" in US)
12
- * Use children render function for custom formatting.
13
- *
14
- * @example
15
- * // Default format (locale-aware)
16
- * <Date value={post.publishedAt} />
17
- *
18
- * // Custom format with render function
19
- * <Date value={post.publishedAt}>
20
- * {(date) => format(date, 'EEEE, MMMM do yyyy')}
21
- * </Date>
22
- *
23
- * // Relative time
24
- * <Date value={post.publishedAt}>
25
- * {(date) => formatDistanceToNow(date, { addSuffix: true })}
26
- * </Date>
27
- */
28
- export declare function Date({ value, children, className }: DateProps): import("react/jsx-runtime").JSX.Element | null;
29
- export {};
30
- //# sourceMappingURL=Date.d.ts.map
@@ -1,43 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { FIMO_SOURCE, useFimoLiveValue } from '../lib/index.js';
3
- /**
4
- * Date component for rendering dates with source tracking
5
- *
6
- * Default format uses browser's locale (e.g., "28 ene 2026" in Spain, "Jan 28, 2026" in US)
7
- * Use children render function for custom formatting.
8
- *
9
- * @example
10
- * // Default format (locale-aware)
11
- * <Date value={post.publishedAt} />
12
- *
13
- * // Custom format with render function
14
- * <Date value={post.publishedAt}>
15
- * {(date) => format(date, 'EEEE, MMMM do yyyy')}
16
- * </Date>
17
- *
18
- * // Relative time
19
- * <Date value={post.publishedAt}>
20
- * {(date) => formatDistanceToNow(date, { addSuffix: true })}
21
- * </Date>
22
- */
23
- export function Date({ value, children, className }) {
24
- const { value: liveValue, ref } = useFimoLiveValue(value ?? null);
25
- // Defensive: return null if no value
26
- if (!liveValue) {
27
- return null;
28
- }
29
- const source = typeof value === 'object' && FIMO_SOURCE in value ? value[FIMO_SOURCE] : undefined;
30
- const rawValue = liveValue instanceof String ? liveValue.toString() : liveValue;
31
- const dateValue = new globalThis.Date(rawValue);
32
- // Format for datetime attribute (ISO format)
33
- const isoDate = dateValue.toISOString().split('T')[0];
34
- // Render content - use children if provided, otherwise locale-aware default
35
- const content = children
36
- ? children(dateValue)
37
- : dateValue.toLocaleDateString(undefined, {
38
- year: 'numeric',
39
- month: 'short',
40
- day: 'numeric',
41
- });
42
- return (_jsx("time", { ref: ref, dateTime: isoDate, className: className, "data-fimo-source": source, children: content }));
43
- }
@@ -1,72 +0,0 @@
1
- import { type ComponentPropsWithoutRef, type ReactNode } from 'react';
2
- import { type ImageFit } from '../lib/image-optimization.js';
3
- import { type FimoMedia } from '../lib/index.js';
4
- /** Base props for Image, extending native img props with optimization options. */
5
- type BaseImageProps = Omit<ComponentPropsWithoutRef<'img'>, 'src' | 'alt' | 'children'> & {
6
- /** Image quality (1-100). Defaults to 85. */
7
- quality?: number;
8
- /** Resize fit mode. Also maps to CSS object-fit. Defaults to 'scale-down'. */
9
- fit?: ImageFit;
10
- /** Skip optimization and use original URL. */
11
- unoptimized?: boolean;
12
- overrideSrc?: string;
13
- };
14
- type ImageProps = BaseImageProps & {
15
- /** The FimoMedia object from schema data. */
16
- value: FimoMedia;
17
- /** Override the alt text from FimoMedia. */
18
- alt?: string;
19
- /** Render function for custom markup (bypasses default img rendering). */
20
- children?: (media: FimoMedia) => ReactNode;
21
- };
22
- /**
23
- * Image component for rendering schema media with optional optimization.
24
- *
25
- * Optimization:
26
- * - Applies only to http(s) URLs on *.fimo.team, *.fimo.ai, and *.fimo.site.
27
- * - Generates optimized `src` automatically only when at least one sizing hint
28
- * is provided (`width`, `height`, or `sizes`).
29
- * - Uses default quality 85 and internal format=auto.
30
- * - Maps `fit` to CSS object-fit by default.
31
- *
32
- * Escape hatch:
33
- * - Pass `unoptimized` to bypass all URL rewriting.
34
- *
35
- * Use children render function for custom rendering (e.g., picture element).
36
- *
37
- * @example
38
- * <Image value={post.coverImage} />
39
- * <Image value={post.coverImage} className="rounded-lg" loading="lazy" />
40
- *
41
- * // With render function for custom markup
42
- * <Image value={post.cover}>
43
- * {(media) => (
44
- * <img src={media.url} alt={media.alt} />
45
- * )}
46
- * </Image>
47
- *
48
- * // Fixed-size mode (no `sizes`): uses DPR candidates
49
- * <Image value={post.coverImage} width={320} />
50
- * // srcSet:
51
- * // ...?w=320&q=85&fit=scale-down&f=auto&dpr=1 1x,
52
- * // ...?w=320&q=85&fit=scale-down&f=auto&dpr=2 2x
53
- * // src:
54
- * // ...?w=320&q=85&fit=scale-down&f=auto&dpr=2
55
- *
56
- * // Responsive mode (`sizes`): uses width candidates
57
- * <Image
58
- * value={post.coverImage}
59
- * sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
60
- * />
61
- * // srcSet (example):
62
- * // ...?w=640&q=85&fit=scale-down&f=auto 640w,
63
- * // ...?w=750&q=85&fit=scale-down&f=auto 750w,
64
- * // ...?w=828&q=85&fit=scale-down&f=auto 828w
65
- *
66
- * // No `width`/`height`/`sizes`: keep source URL unchanged
67
- * <Image value={post.coverImage} />
68
- * // src: original media URL
69
- */
70
- export declare function Image(props: ImageProps): import("react/jsx-runtime").JSX.Element | null;
71
- export {};
72
- //# sourceMappingURL=Image.d.ts.map
@@ -1,108 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { clampQuality, resolveFit, toObjectFit, toPositiveInt, isOptimizableFimoUrl, buildOptimizedUrl, computeImageOptimizationConfig, } from '../lib/image-optimization.js';
3
- import { FIMO_SOURCE, useFimoLiveValue } from '../lib/index.js';
4
- /**
5
- * Image component for rendering schema media with optional optimization.
6
- *
7
- * Optimization:
8
- * - Applies only to http(s) URLs on *.fimo.team, *.fimo.ai, and *.fimo.site.
9
- * - Generates optimized `src` automatically only when at least one sizing hint
10
- * is provided (`width`, `height`, or `sizes`).
11
- * - Uses default quality 85 and internal format=auto.
12
- * - Maps `fit` to CSS object-fit by default.
13
- *
14
- * Escape hatch:
15
- * - Pass `unoptimized` to bypass all URL rewriting.
16
- *
17
- * Use children render function for custom rendering (e.g., picture element).
18
- *
19
- * @example
20
- * <Image value={post.coverImage} />
21
- * <Image value={post.coverImage} className="rounded-lg" loading="lazy" />
22
- *
23
- * // With render function for custom markup
24
- * <Image value={post.cover}>
25
- * {(media) => (
26
- * <img src={media.url} alt={media.alt} />
27
- * )}
28
- * </Image>
29
- *
30
- * // Fixed-size mode (no `sizes`): uses DPR candidates
31
- * <Image value={post.coverImage} width={320} />
32
- * // srcSet:
33
- * // ...?w=320&q=85&fit=scale-down&f=auto&dpr=1 1x,
34
- * // ...?w=320&q=85&fit=scale-down&f=auto&dpr=2 2x
35
- * // src:
36
- * // ...?w=320&q=85&fit=scale-down&f=auto&dpr=2
37
- *
38
- * // Responsive mode (`sizes`): uses width candidates
39
- * <Image
40
- * value={post.coverImage}
41
- * sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
42
- * />
43
- * // srcSet (example):
44
- * // ...?w=640&q=85&fit=scale-down&f=auto 640w,
45
- * // ...?w=750&q=85&fit=scale-down&f=auto 750w,
46
- * // ...?w=828&q=85&fit=scale-down&f=auto 828w
47
- *
48
- * // No `width`/`height`/`sizes`: keep source URL unchanged
49
- * <Image value={post.coverImage} />
50
- * // src: original media URL
51
- */
52
- export function Image(props) {
53
- const { value: media, children, quality, unoptimized = false, fit, width, height, alt: altOverride, overrideSrc, srcSet: srcSetOverride, sizes, style, ...imgProps } = props;
54
- const { value: liveMedia, ref } = useFimoLiveValue(media ?? null);
55
- // Defensive: return null if no media
56
- if (!liveMedia) {
57
- return null;
58
- }
59
- const mediaSource = liveMedia[FIMO_SOURCE];
60
- if (children) {
61
- return (_jsx("span", { ref: ref, "data-fimo-source": mediaSource, children: children(liveMedia) }));
62
- }
63
- const normalizedQuality = clampQuality(quality);
64
- const normalizedFit = resolveFit(fit);
65
- const requestedWidth = toPositiveInt(width);
66
- const requestedHeight = toPositiveInt(height);
67
- const displayWidth = requestedWidth ?? liveMedia.width;
68
- const displayHeight = requestedHeight ?? liveMedia.height;
69
- const originalSrc = liveMedia.url;
70
- const resolvedAlt = altOverride ?? liveMedia.alt;
71
- // User-defined sizes attribute
72
- const hasSizesAttr = typeof sizes === 'string' && sizes.trim().length > 0;
73
- const hasSizingHint = hasSizesAttr || requestedWidth !== undefined || requestedHeight !== undefined;
74
- const canOptimizeSource = !unoptimized && isOptimizableFimoUrl(originalSrc);
75
- const shouldOptimize = canOptimizeSource && hasSizingHint;
76
- const { generatedSrcSet, transformWidth, transformDpr } = computeImageOptimizationConfig({
77
- shouldOptimize,
78
- hasSizesAttr,
79
- srcSetOverride,
80
- originalSrc,
81
- mediaWidth: media.width,
82
- renderWidth: displayWidth,
83
- quality: normalizedQuality,
84
- fit: normalizedFit,
85
- });
86
- const finalSrcSet = srcSetOverride ?? generatedSrcSet;
87
- const optimizedSrc = shouldOptimize
88
- ? buildOptimizedUrl(originalSrc, {
89
- width: transformWidth,
90
- quality: normalizedQuality,
91
- fit: normalizedFit,
92
- dpr: transformDpr,
93
- })
94
- : originalSrc;
95
- const finalSrc = overrideSrc ?? optimizedSrc;
96
- /**
97
- * Apply browser-side object fitting so the rendered image also respects
98
- * the container box. Cloudflare `fit` controls transformed pixels, while
99
- * `object-fit` controls layout behavior at render time.
100
- */
101
- const finalStyle = style?.objectFit
102
- ? style
103
- : {
104
- ...style,
105
- objectFit: toObjectFit(normalizedFit),
106
- };
107
- return (_jsx("img", { ref: ref, src: finalSrc, alt: resolvedAlt, width: displayWidth, height: displayHeight, style: finalStyle, sizes: sizes, srcSet: finalSrcSet, ...imgProps, "data-fimo-source": mediaSource }));
108
- }
@@ -1,25 +0,0 @@
1
- import { type ComponentPropsWithoutRef, type ElementType, type ReactNode } from 'react';
2
- type JsonProps<T extends ElementType = 'span'> = {
3
- value: unknown;
4
- as?: T;
5
- children?: (value: unknown) => ReactNode;
6
- } & Omit<ComponentPropsWithoutRef<T>, 'value' | 'as' | 'children'>;
7
- /**
8
- * Json component for rendering JSON field values with source tracking.
9
- *
10
- * Use children render function to customize how the value is displayed.
11
- * Pass `as="pre"` (with a `white-space: pre-wrap` class) for formatted output.
12
- *
13
- * @example
14
- * // Default (single-line JSON text)
15
- * <Json value={product.metadata} />
16
- *
17
- * // Pretty-printed
18
- * <Json value={product.metadata} as="pre" className="whitespace-pre-wrap" />
19
- *
20
- * // With render function for custom display
21
- * <Json value={product.metadata}>{(val) => val.tags?.join(', ')}</Json>
22
- */
23
- export declare function Json<T extends ElementType = 'span'>({ value, as, children, ...props }: JsonProps<T>): import("react/jsx-runtime").JSX.Element | null;
24
- export {};
25
- //# sourceMappingURL=Json.d.ts.map
@@ -1,29 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { getFimoSource, useFimoLiveValue } from '../lib/index.js';
3
- /**
4
- * Json component for rendering JSON field values with source tracking.
5
- *
6
- * Use children render function to customize how the value is displayed.
7
- * Pass `as="pre"` (with a `white-space: pre-wrap` class) for formatted output.
8
- *
9
- * @example
10
- * // Default (single-line JSON text)
11
- * <Json value={product.metadata} />
12
- *
13
- * // Pretty-printed
14
- * <Json value={product.metadata} as="pre" className="whitespace-pre-wrap" />
15
- *
16
- * // With render function for custom display
17
- * <Json value={product.metadata}>{(val) => val.tags?.join(', ')}</Json>
18
- */
19
- export function Json({ value, as, children, ...props }) {
20
- const Component = as || 'span';
21
- const { value: liveValue, ref } = useFimoLiveValue(value);
22
- // Defensive: return null if no value
23
- if (value === null || value === undefined) {
24
- return null;
25
- }
26
- const source = getFimoSource(value);
27
- const content = children ? children(liveValue) : JSON.stringify(liveValue);
28
- return (_jsx(Component, { ref: ref, ...props, "data-fimo-source": source, children: content }));
29
- }
@@ -1,9 +0,0 @@
1
- import { type ComponentPropsWithoutRef } from 'react';
2
- import { type FimoRichText, type FimoRichTextComponents } from '../lib/index.js';
3
- type RichTextProps = {
4
- value: FimoRichText | null | undefined;
5
- components?: FimoRichTextComponents;
6
- } & Omit<ComponentPropsWithoutRef<'div'>, 'children'>;
7
- export declare function RichText({ value, components, ...props }: RichTextProps): import("react/jsx-runtime").JSX.Element | null;
8
- export {};
9
- //# sourceMappingURL=RichText.d.ts.map
@@ -1,31 +0,0 @@
1
- import { type ComponentPropsWithoutRef, type ReactNode } from 'react';
2
- import { type FimoMedia } from '../lib/index.js';
3
- type BaseVideoProps = Omit<ComponentPropsWithoutRef<'video'>, 'src' | 'children'> & {
4
- overrideSrc?: string;
5
- };
6
- type VideoProps = BaseVideoProps & {
7
- value: FimoMedia;
8
- children?: (media: FimoMedia) => ReactNode;
9
- };
10
- /**
11
- * Video component for rendering schema media with source tracking.
12
- *
13
- * Renders a native `<video>` element with `data-fimo-source` for edit tracking.
14
- * Defaults to `autoPlay`, `loop`, `muted`, and `playsInline` for hero/background use.
15
- * All defaults can be overridden via props.
16
- *
17
- * @example
18
- * <Video value={post.heroVideo} />
19
- * <Video value={post.heroVideo} autoPlay={false} controls />
20
- * <Video value={post.bgVideo} className="absolute inset-0 object-cover" />
21
- *
22
- * // With render function for custom markup
23
- * <Video value={post.video}>
24
- * {(media) => (
25
- * <video src={media.url} controls />
26
- * )}
27
- * </Video>
28
- */
29
- export declare function Video(props: VideoProps): import("react/jsx-runtime").JSX.Element | null;
30
- export {};
31
- //# sourceMappingURL=Video.d.ts.map
@@ -1,34 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { FIMO_SOURCE, useFimoLiveValue } from '../lib/index.js';
3
- /**
4
- * Video component for rendering schema media with source tracking.
5
- *
6
- * Renders a native `<video>` element with `data-fimo-source` for edit tracking.
7
- * Defaults to `autoPlay`, `loop`, `muted`, and `playsInline` for hero/background use.
8
- * All defaults can be overridden via props.
9
- *
10
- * @example
11
- * <Video value={post.heroVideo} />
12
- * <Video value={post.heroVideo} autoPlay={false} controls />
13
- * <Video value={post.bgVideo} className="absolute inset-0 object-cover" />
14
- *
15
- * // With render function for custom markup
16
- * <Video value={post.video}>
17
- * {(media) => (
18
- * <video src={media.url} controls />
19
- * )}
20
- * </Video>
21
- */
22
- export function Video(props) {
23
- const { value: media, children, overrideSrc, autoPlay = true, loop = true, muted = true, playsInline = true, style, ...videoProps } = props;
24
- const { value: liveMedia, ref } = useFimoLiveValue(media ?? null);
25
- if (!liveMedia) {
26
- return null;
27
- }
28
- const mediaSource = liveMedia[FIMO_SOURCE];
29
- if (children) {
30
- return (_jsx("span", { ref: ref, "data-fimo-source": mediaSource, children: children(liveMedia) }));
31
- }
32
- const finalSrc = overrideSrc ?? liveMedia.url;
33
- return (_jsx("video", { ref: ref, src: finalSrc, width: liveMedia.width, height: liveMedia.height, autoPlay: autoPlay, loop: loop, muted: muted, playsInline: playsInline, style: style, ...videoProps, "data-fimo-source": mediaSource }));
34
- }