@airdraft/react-content 0.1.1 → 0.1.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.
- package/dist/fields/MediaField.d.ts +39 -0
- package/dist/fields/MediaField.d.ts.map +1 -0
- package/dist/fields/MediaField.js +51 -0
- package/dist/fields/MediaField.js.map +1 -0
- package/dist/fields/MediaListField.d.ts +33 -0
- package/dist/fields/MediaListField.d.ts.map +1 -0
- package/dist/fields/MediaListField.js +61 -0
- package/dist/fields/MediaListField.js.map +1 -0
- package/dist/fields/index.d.ts +4 -0
- package/dist/fields/index.d.ts.map +1 -1
- package/dist/fields/index.js +2 -0
- package/dist/fields/index.js.map +1 -1
- package/dist/next/AirdraftMedia.d.ts +35 -0
- package/dist/next/AirdraftMedia.d.ts.map +1 -0
- package/dist/next/AirdraftMedia.js +49 -0
- package/dist/next/AirdraftMedia.js.map +1 -0
- package/dist/next/index.d.ts +2 -0
- package/dist/next/index.d.ts.map +1 -1
- package/dist/next/index.js +1 -0
- package/dist/next/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import { resolveImageDimensions } from '@airdraft/content';
|
|
3
|
+
import type { Entry } from '@airdraft/core';
|
|
4
|
+
export interface MediaFieldProps {
|
|
5
|
+
/** The field name in the entry's data (e.g. 'cover', 'attachment'). */
|
|
6
|
+
field: string;
|
|
7
|
+
/** The entry whose data is searched for the media value. */
|
|
8
|
+
entry: Entry;
|
|
9
|
+
alt?: string;
|
|
10
|
+
className?: string;
|
|
11
|
+
/** Class applied to the rendered `<img>` when no children render prop is given. */
|
|
12
|
+
imgClassName?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Render prop — receives the resolved URL and MIME type hint (if known) and
|
|
15
|
+
* renders a custom element. Use this to plug in `next/image`, `<video>`, etc.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* <MediaField field="attachment" entry={entry}>
|
|
19
|
+
* {(url, mimeType) => <a href={url}>{mimeType ?? 'Download'}</a>}
|
|
20
|
+
* </MediaField>
|
|
21
|
+
*/
|
|
22
|
+
children?: (url: string, mimeType: string | undefined) => ReactNode;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Renders a media asset resolved from an Airdraft entry field.
|
|
26
|
+
*
|
|
27
|
+
* - Images: `<img>`
|
|
28
|
+
* - Videos: `<video>`
|
|
29
|
+
* - Audio: `<audio>`
|
|
30
|
+
* - Other: `<a>` link
|
|
31
|
+
*
|
|
32
|
+
* Resolution chain: `{field}_media.url` → `{field}_url` → `/{field}` key.
|
|
33
|
+
* Returns `null` when no URL can be resolved.
|
|
34
|
+
*
|
|
35
|
+
* RSC-compatible — no `"use client"`.
|
|
36
|
+
*/
|
|
37
|
+
export declare function MediaField({ field, entry, alt, className, imgClassName, children, }: MediaFieldProps): ReactNode;
|
|
38
|
+
export { resolveImageDimensions };
|
|
39
|
+
//# sourceMappingURL=MediaField.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MediaField.d.ts","sourceRoot":"","sources":["../../src/fields/MediaField.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,EAAmB,sBAAsB,EAAE,MAAM,mBAAmB,CAAA;AAC3E,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAE3C,MAAM,WAAW,eAAe;IAC9B,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAA;IACb,4DAA4D;IAC5D,KAAK,EAAE,KAAK,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,mFAAmF;IACnF,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,KAAK,SAAS,CAAA;CACpE;AAkCD;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,KAAK,EACL,GAAQ,EACR,SAAS,EACT,YAAY,EACZ,QAAQ,GACT,EAAE,eAAe,GAAG,SAAS,CAU7B;AAGD,OAAO,EAAE,sBAAsB,EAAE,CAAA"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { resolveMediaUrl, resolveImageDimensions } from '@airdraft/content';
|
|
3
|
+
function getMimeType(field, data) {
|
|
4
|
+
const mediaObj = data[`${field}_media`];
|
|
5
|
+
if (mediaObj && typeof mediaObj === 'object' && 'mimeType' in mediaObj) {
|
|
6
|
+
const m = mediaObj['mimeType'];
|
|
7
|
+
if (typeof m === 'string' && m)
|
|
8
|
+
return m;
|
|
9
|
+
}
|
|
10
|
+
return undefined;
|
|
11
|
+
}
|
|
12
|
+
function renderByMime(url, mimeType, alt, className) {
|
|
13
|
+
if (!mimeType || mimeType.startsWith('image/')) {
|
|
14
|
+
// eslint-disable-next-line @next/next/no-img-element
|
|
15
|
+
return _jsx("img", { src: url, alt: alt, className: className });
|
|
16
|
+
}
|
|
17
|
+
if (mimeType.startsWith('video/')) {
|
|
18
|
+
return (_jsx("video", { src: url, controls: true, className: className, children: _jsx("track", { kind: "captions" }) }));
|
|
19
|
+
}
|
|
20
|
+
if (mimeType.startsWith('audio/')) {
|
|
21
|
+
return _jsx("audio", { src: url, controls: true, className: className });
|
|
22
|
+
}
|
|
23
|
+
// Generic file — render a link
|
|
24
|
+
return (_jsx("a", { href: url, target: "_blank", rel: "noopener noreferrer", className: className, children: url.split('/').pop() ?? url }));
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Renders a media asset resolved from an Airdraft entry field.
|
|
28
|
+
*
|
|
29
|
+
* - Images: `<img>`
|
|
30
|
+
* - Videos: `<video>`
|
|
31
|
+
* - Audio: `<audio>`
|
|
32
|
+
* - Other: `<a>` link
|
|
33
|
+
*
|
|
34
|
+
* Resolution chain: `{field}_media.url` → `{field}_url` → `/{field}` key.
|
|
35
|
+
* Returns `null` when no URL can be resolved.
|
|
36
|
+
*
|
|
37
|
+
* RSC-compatible — no `"use client"`.
|
|
38
|
+
*/
|
|
39
|
+
export function MediaField({ field, entry, alt = '', className, imgClassName, children, }) {
|
|
40
|
+
const data = entry.data;
|
|
41
|
+
const url = resolveMediaUrl(field, data);
|
|
42
|
+
if (!url)
|
|
43
|
+
return null;
|
|
44
|
+
const mimeType = getMimeType(field, data);
|
|
45
|
+
if (children)
|
|
46
|
+
return children(url, mimeType);
|
|
47
|
+
return renderByMime(url, mimeType, alt, imgClassName ?? className);
|
|
48
|
+
}
|
|
49
|
+
// Re-export resolveImageDimensions for convenience when using MediaField with next/image
|
|
50
|
+
export { resolveImageDimensions };
|
|
51
|
+
//# sourceMappingURL=MediaField.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MediaField.js","sourceRoot":"","sources":["../../src/fields/MediaField.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAA;AAwB3E,SAAS,WAAW,CAAC,KAAa,EAAE,IAA6B;IAC/D,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAA;IACvC,IAAI,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,UAAU,IAAI,QAAQ,EAAE,CAAC;QACvE,MAAM,CAAC,GAAI,QAAoC,CAAC,UAAU,CAAC,CAAA;QAC3D,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC;YAAE,OAAO,CAAC,CAAA;IAC1C,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED,SAAS,YAAY,CAAC,GAAW,EAAE,QAA4B,EAAE,GAAW,EAAE,SAAkB;IAC9F,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC/C,qDAAqD;QACrD,OAAO,cAAK,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,SAAS,GAAI,CAAA;IAC1D,CAAC;IACD,IAAI,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAClC,OAAO,CACL,gBAAO,GAAG,EAAE,GAAG,EAAE,QAAQ,QAAC,SAAS,EAAE,SAAS,YAC5C,gBAAO,IAAI,EAAC,UAAU,GAAG,GACnB,CACT,CAAA;IACH,CAAC;IACD,IAAI,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAClC,OAAO,gBAAO,GAAG,EAAE,GAAG,EAAE,QAAQ,QAAC,SAAS,EAAE,SAAS,GAAI,CAAA;IAC3D,CAAC;IACD,+BAA+B;IAC/B,OAAO,CACL,YAAG,IAAI,EAAE,GAAG,EAAE,MAAM,EAAC,QAAQ,EAAC,GAAG,EAAC,qBAAqB,EAAC,SAAS,EAAE,SAAS,YACzE,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,GAAG,GAC1B,CACL,CAAA;AACH,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,UAAU,CAAC,EACzB,KAAK,EACL,KAAK,EACL,GAAG,GAAG,EAAE,EACR,SAAS,EACT,YAAY,EACZ,QAAQ,GACQ;IAChB,MAAM,IAAI,GAAG,KAAK,CAAC,IAA+B,CAAA;IAClD,MAAM,GAAG,GAAG,eAAe,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;IACxC,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAA;IAErB,MAAM,QAAQ,GAAG,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;IAEzC,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;IAE5C,OAAO,YAAY,CAAC,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,YAAY,IAAI,SAAS,CAAC,CAAA;AACpE,CAAC;AAED,yFAAyF;AACzF,OAAO,EAAE,sBAAsB,EAAE,CAAA"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import type { Entry } from '@airdraft/core';
|
|
3
|
+
export interface MediaListFieldProps {
|
|
4
|
+
/** The field name in the entry's data (e.g. 'gallery', 'attachments'). */
|
|
5
|
+
field: string;
|
|
6
|
+
/** The entry whose data is searched for the media array. */
|
|
7
|
+
entry: Entry;
|
|
8
|
+
className?: string;
|
|
9
|
+
/** Class applied to each rendered item's wrapper element. */
|
|
10
|
+
itemClassName?: string;
|
|
11
|
+
/**
|
|
12
|
+
* Render prop — receives the resolved URL, index, and MIME type hint for each item.
|
|
13
|
+
* Use this to render custom thumbnails, cards, links, etc.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* <MediaListField field="gallery" entry={entry}>
|
|
17
|
+
* {(url, i) => <img key={i} src={url} alt={`Gallery ${i + 1}`} />}
|
|
18
|
+
* </MediaListField>
|
|
19
|
+
*/
|
|
20
|
+
children?: (url: string, index: number, mimeType: string | undefined) => ReactNode;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Renders a list of media assets from a `media` field with `multiple: true`.
|
|
24
|
+
*
|
|
25
|
+
* Each item is rendered using the `children` render prop when provided,
|
|
26
|
+
* otherwise falls back to an `<img>` tag (for images) or an `<a>` link.
|
|
27
|
+
*
|
|
28
|
+
* Returns `null` when no URLs can be resolved.
|
|
29
|
+
*
|
|
30
|
+
* RSC-compatible — no `"use client"`.
|
|
31
|
+
*/
|
|
32
|
+
export declare function MediaListField({ field, entry, className, itemClassName, children, }: MediaListFieldProps): ReactNode;
|
|
33
|
+
//# sourceMappingURL=MediaListField.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MediaListField.d.ts","sourceRoot":"","sources":["../../src/fields/MediaListField.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAE3C,MAAM,WAAW,mBAAmB;IAClC,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAA;IACb,4DAA4D;IAC5D,KAAK,EAAE,KAAK,CAAA;IACZ,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,6DAA6D;IAC7D,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,KAAK,SAAS,CAAA;CACnF;AAmBD;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,KAAK,EACL,SAAS,EACT,aAAa,EACb,QAAQ,GACT,EAAE,mBAAmB,GAAG,SAAS,CA+CjC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { resolveMediaUrls } from '@airdraft/content';
|
|
3
|
+
function getMediaItems(field, data) {
|
|
4
|
+
const mediasRaw = data[`${field}_medias`];
|
|
5
|
+
if (Array.isArray(mediasRaw)) {
|
|
6
|
+
return mediasRaw.flatMap((item) => {
|
|
7
|
+
if (item && typeof item === 'object' && 'url' in item) {
|
|
8
|
+
const obj = item;
|
|
9
|
+
const url = typeof obj['url'] === 'string' ? obj['url'] : undefined;
|
|
10
|
+
if (!url)
|
|
11
|
+
return [];
|
|
12
|
+
const mimeType = typeof obj['mimeType'] === 'string' ? obj['mimeType'] : undefined;
|
|
13
|
+
return [{ url, mimeType }];
|
|
14
|
+
}
|
|
15
|
+
return [];
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
return [];
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Renders a list of media assets from a `media` field with `multiple: true`.
|
|
22
|
+
*
|
|
23
|
+
* Each item is rendered using the `children` render prop when provided,
|
|
24
|
+
* otherwise falls back to an `<img>` tag (for images) or an `<a>` link.
|
|
25
|
+
*
|
|
26
|
+
* Returns `null` when no URLs can be resolved.
|
|
27
|
+
*
|
|
28
|
+
* RSC-compatible — no `"use client"`.
|
|
29
|
+
*/
|
|
30
|
+
export function MediaListField({ field, entry, className, itemClassName, children, }) {
|
|
31
|
+
const data = entry.data;
|
|
32
|
+
const items = getMediaItems(field, data);
|
|
33
|
+
// Fall back to URL-only resolution when medias sidecar is absent
|
|
34
|
+
const urls = items.length > 0 ? null : resolveMediaUrls(field, data);
|
|
35
|
+
if (items.length === 0 && (!urls || urls.length === 0))
|
|
36
|
+
return null;
|
|
37
|
+
if (children) {
|
|
38
|
+
if (items.length > 0) {
|
|
39
|
+
return (_jsx(_Fragment, { children: items.map(({ url, mimeType }, i) => children(url, i, mimeType)) }));
|
|
40
|
+
}
|
|
41
|
+
return _jsx(_Fragment, { children: (urls ?? []).map((url, i) => children(url, i, undefined)) });
|
|
42
|
+
}
|
|
43
|
+
// Default render — img for each item inside a wrapper
|
|
44
|
+
const resolvedItems = items.length > 0
|
|
45
|
+
? items
|
|
46
|
+
: (urls ?? []).map((url) => ({ url, mimeType: undefined }));
|
|
47
|
+
return (_jsx("div", { className: className, children: resolvedItems.map(({ url, mimeType }, i) => {
|
|
48
|
+
if (!mimeType || mimeType.startsWith('image/')) {
|
|
49
|
+
// eslint-disable-next-line @next/next/no-img-element
|
|
50
|
+
return _jsx("img", { src: url, alt: `Item ${i + 1}`, className: itemClassName }, i);
|
|
51
|
+
}
|
|
52
|
+
if (mimeType.startsWith('video/')) {
|
|
53
|
+
return (_jsx("video", { src: url, controls: true, className: itemClassName, children: _jsx("track", { kind: "captions" }) }, i));
|
|
54
|
+
}
|
|
55
|
+
if (mimeType.startsWith('audio/')) {
|
|
56
|
+
return _jsx("audio", { src: url, controls: true, className: itemClassName }, i);
|
|
57
|
+
}
|
|
58
|
+
return (_jsx("a", { href: url, target: "_blank", rel: "noopener noreferrer", className: itemClassName, children: url.split('/').pop() ?? url }, i));
|
|
59
|
+
}) }));
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=MediaListField.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MediaListField.js","sourceRoot":"","sources":["../../src/fields/MediaListField.tsx"],"names":[],"mappings":"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"}
|
package/dist/fields/index.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
export { ImageField } from './ImageField.js';
|
|
2
2
|
export type { ImageFieldProps } from './ImageField.js';
|
|
3
|
+
export { MediaField } from './MediaField.js';
|
|
4
|
+
export type { MediaFieldProps } from './MediaField.js';
|
|
5
|
+
export { MediaListField } from './MediaListField.js';
|
|
6
|
+
export type { MediaListFieldProps } from './MediaListField.js';
|
|
3
7
|
export { BodyField } from './BodyField.js';
|
|
4
8
|
export type { BodyFieldProps } from './BodyField.js';
|
|
5
9
|
export { TagList } from './TagList.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/fields/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEtD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAEpD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAEhD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChD,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAE1E,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/fields/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEtD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAC5C,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEtD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,YAAY,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AAE9D,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAEpD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAEhD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChD,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAE1E,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA"}
|
package/dist/fields/index.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export { ImageField } from './ImageField.js';
|
|
2
|
+
export { MediaField } from './MediaField.js';
|
|
3
|
+
export { MediaListField } from './MediaListField.js';
|
|
2
4
|
export { BodyField } from './BodyField.js';
|
|
3
5
|
export { TagList } from './TagList.js';
|
|
4
6
|
export { AuthorByline } from './AuthorByline.js';
|
package/dist/fields/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/fields/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAG5C,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAG1C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAGtC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAGhD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/fields/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAG5C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAG5C,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AAGpD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAG1C,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAGtC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAGhD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
import type { Entry } from '@airdraft/core';
|
|
3
|
+
export interface AirdraftMediaProps {
|
|
4
|
+
/** The field name in the entry's data (e.g. 'cover', 'attachment'). */
|
|
5
|
+
field: string;
|
|
6
|
+
/** The entry whose data is searched for the media value. */
|
|
7
|
+
entry: Entry;
|
|
8
|
+
alt?: string;
|
|
9
|
+
className?: string;
|
|
10
|
+
/** Passed through to next/image when rendering images. */
|
|
11
|
+
priority?: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Render prop — receives the resolved URL and MIME type hint.
|
|
14
|
+
* Use this to plug in custom rendering for non-image types.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* <AirdraftMedia field="attachment" entry={entry}>
|
|
18
|
+
* {(url, mimeType) => <a href={url}>{mimeType ?? 'Download'}</a>}
|
|
19
|
+
* </AirdraftMedia>
|
|
20
|
+
*/
|
|
21
|
+
children?: (url: string, mimeType: string | undefined) => ReactNode;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Next.js-aware media component that handles all media types.
|
|
25
|
+
*
|
|
26
|
+
* - Images (image/* MIME or unknown type): uses `next/image` with dimensions when available
|
|
27
|
+
* - Videos: `<video controls>`
|
|
28
|
+
* - Audio: `<audio controls>`
|
|
29
|
+
* - Other: `<a>` download link
|
|
30
|
+
*
|
|
31
|
+
* Returns `null` when no URL can be resolved.
|
|
32
|
+
* RSC-compatible — no `"use client"`.
|
|
33
|
+
*/
|
|
34
|
+
export declare function AirdraftMedia({ field, entry, alt, className, priority, children, }: AirdraftMediaProps): ReactNode;
|
|
35
|
+
//# sourceMappingURL=AirdraftMedia.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AirdraftMedia.d.ts","sourceRoot":"","sources":["../../src/next/AirdraftMedia.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAA;AAG3C,MAAM,WAAW,kBAAkB;IACjC,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAA;IACb,4DAA4D;IAC5D,KAAK,EAAE,KAAK,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,KAAK,SAAS,CAAA;CACpE;AAWD;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,KAAK,EACL,GAAQ,EACR,SAAS,EACT,QAAQ,EACR,QAAQ,GACT,EAAE,kBAAkB,GAAG,SAAS,CAiDhC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import Image from 'next/image';
|
|
3
|
+
import { resolveMediaUrl, resolveImageDimensions } from '@airdraft/content';
|
|
4
|
+
function getMimeType(field, data) {
|
|
5
|
+
const mediaObj = data[`${field}_media`];
|
|
6
|
+
if (mediaObj && typeof mediaObj === 'object' && 'mimeType' in mediaObj) {
|
|
7
|
+
const m = mediaObj['mimeType'];
|
|
8
|
+
if (typeof m === 'string' && m)
|
|
9
|
+
return m;
|
|
10
|
+
}
|
|
11
|
+
return undefined;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Next.js-aware media component that handles all media types.
|
|
15
|
+
*
|
|
16
|
+
* - Images (image/* MIME or unknown type): uses `next/image` with dimensions when available
|
|
17
|
+
* - Videos: `<video controls>`
|
|
18
|
+
* - Audio: `<audio controls>`
|
|
19
|
+
* - Other: `<a>` download link
|
|
20
|
+
*
|
|
21
|
+
* Returns `null` when no URL can be resolved.
|
|
22
|
+
* RSC-compatible — no `"use client"`.
|
|
23
|
+
*/
|
|
24
|
+
export function AirdraftMedia({ field, entry, alt = '', className, priority, children, }) {
|
|
25
|
+
const data = entry.data;
|
|
26
|
+
const src = resolveMediaUrl(field, data);
|
|
27
|
+
if (!src)
|
|
28
|
+
return null;
|
|
29
|
+
const mimeType = getMimeType(field, data);
|
|
30
|
+
if (children)
|
|
31
|
+
return children(src, mimeType);
|
|
32
|
+
// Images (or unknown MIME) — use next/image
|
|
33
|
+
if (!mimeType || mimeType.startsWith('image/')) {
|
|
34
|
+
const dims = resolveImageDimensions(field, data);
|
|
35
|
+
if (dims) {
|
|
36
|
+
return (_jsx(Image, { src: src, alt: alt, width: dims.width, height: dims.height, className: className, priority: priority }));
|
|
37
|
+
}
|
|
38
|
+
return (_jsx("div", { className: className, style: { position: 'relative' }, children: _jsx(Image, { src: src, alt: alt, fill: true, priority: priority }) }));
|
|
39
|
+
}
|
|
40
|
+
if (mimeType.startsWith('video/')) {
|
|
41
|
+
return (_jsx("video", { src: src, controls: true, className: className, children: _jsx("track", { kind: "captions" }) }));
|
|
42
|
+
}
|
|
43
|
+
if (mimeType.startsWith('audio/')) {
|
|
44
|
+
return _jsx("audio", { src: src, controls: true, className: className });
|
|
45
|
+
}
|
|
46
|
+
// Generic file — render a link
|
|
47
|
+
return (_jsx("a", { href: src, target: "_blank", rel: "noopener noreferrer", className: className, children: src.split('/').pop() ?? src }));
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=AirdraftMedia.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AirdraftMedia.js","sourceRoot":"","sources":["../../src/next/AirdraftMedia.tsx"],"names":[],"mappings":";AACA,OAAO,KAAK,MAAM,YAAY,CAAA;AAE9B,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAA;AAuB3E,SAAS,WAAW,CAAC,KAAa,EAAE,IAA6B;IAC/D,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAA;IACvC,IAAI,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,UAAU,IAAI,QAAQ,EAAE,CAAC;QACvE,MAAM,CAAC,GAAI,QAAoC,CAAC,UAAU,CAAC,CAAA;QAC3D,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC;YAAE,OAAO,CAAC,CAAA;IAC1C,CAAC;IACD,OAAO,SAAS,CAAA;AAClB,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,aAAa,CAAC,EAC5B,KAAK,EACL,KAAK,EACL,GAAG,GAAG,EAAE,EACR,SAAS,EACT,QAAQ,EACR,QAAQ,GACW;IACnB,MAAM,IAAI,GAAG,KAAK,CAAC,IAA+B,CAAA;IAClD,MAAM,GAAG,GAAG,eAAe,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;IACxC,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAA;IAErB,MAAM,QAAQ,GAAG,WAAW,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;IAEzC,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAA;IAE5C,4CAA4C;IAC5C,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC/C,MAAM,IAAI,GAAG,sBAAsB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;QAChD,IAAI,IAAI,EAAE,CAAC;YACT,OAAO,CACL,KAAC,KAAK,IACJ,GAAG,EAAE,GAAG,EACR,GAAG,EAAE,GAAG,EACR,KAAK,EAAE,IAAI,CAAC,KAAK,EACjB,MAAM,EAAE,IAAI,CAAC,MAAM,EACnB,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,QAAQ,GAClB,CACH,CAAA;QACH,CAAC;QACD,OAAO,CACL,cAAK,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE,YACxD,KAAC,KAAK,IAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,QAAC,QAAQ,EAAE,QAAQ,GAAI,GAClD,CACP,CAAA;IACH,CAAC;IAED,IAAI,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAClC,OAAO,CACL,gBAAO,GAAG,EAAE,GAAG,EAAE,QAAQ,QAAC,SAAS,EAAE,SAAS,YAC5C,gBAAO,IAAI,EAAC,UAAU,GAAG,GACnB,CACT,CAAA;IACH,CAAC;IAED,IAAI,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAClC,OAAO,gBAAO,GAAG,EAAE,GAAG,EAAE,QAAQ,QAAC,SAAS,EAAE,SAAS,GAAI,CAAA;IAC3D,CAAC;IAED,+BAA+B;IAC/B,OAAO,CACL,YAAG,IAAI,EAAE,GAAG,EAAE,MAAM,EAAC,QAAQ,EAAC,GAAG,EAAC,qBAAqB,EAAC,SAAS,EAAE,SAAS,YACzE,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,GAAG,GAC1B,CACL,CAAA;AACH,CAAC"}
|
package/dist/next/index.d.ts
CHANGED
package/dist/next/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/next/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/next/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAE5D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,YAAY,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA"}
|
package/dist/next/index.js
CHANGED
package/dist/next/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/next/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/next/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAGlD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@airdraft/react-content",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Airdraft React components for rendering CMS content — field atoms, entry cards, and blog recipes",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@types/react": "^19.0.0",
|
|
49
|
-
"next": "^
|
|
49
|
+
"next": "^16.1.7",
|
|
50
50
|
"react": "^18.0.0",
|
|
51
51
|
"typescript": "^5.7.2"
|
|
52
52
|
},
|