Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update AirtableAsset, use Next 10 Image component #193

Draft
wants to merge 2 commits into
base: v2-mst-aptd-at-lcz-sty
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 17 additions & 9 deletions src/components/assets/AirtableAsset.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ type Props = {
asset: Asset;
id?: string;
transformationsOverride?: AssetTransformations;
defaults?: Asset;
override?: Asset;
defaults?: Asset; // TODO Should be renamed to "assetFallback"
override?: Asset; // TODO Should be renamed to "assetOverride"
className?: string;
style?: CSSStyles;
onClick?: () => void;
Expand All @@ -22,7 +22,7 @@ type Props = {
url?: string;
target?: string;
style?: CSSStyles;
classes?: string;
classes?: string; // TODO Should be renamed to "className"
};
}

Expand All @@ -44,14 +44,22 @@ const _defaultLink: Link = {
};

/**
* Displays an asset, based on the provided props
* Handles GraphCMS assets, including svg
* Should be used to display assets coming from GraphCMS (handles transformations)
* Displays an image with enriched capabilities, for a given "Asset".
*
* @param props
* @return {null|*}
* Extra capabilities:
* - Auto-generates an "id", based on the asset.id
* - Asset default properties
* - A default asset can be provided and its properties will be used as fallback properties, if they're undefined in the asset property
* - Asset override
* - An asset override can be provided and its properties will take priority, even if they're defined within the asset property
* - Link wrapper
* - The image will be wrapped with a link, if a valid link (contains a "url") is provided either through:
* - The asset itself (asset.linkUrl)
* - The linkOverride (linkOverride.url)
* - Link override
* - A link override can be provided and its properties will take priority, even if they're defined within the link property
*
* @see Transformations https://docs.graphcms.com/developers/assets/transformations/transforming-url-structure
* @param props
*/
const AirtableAsset = (props: Props): JSX.Element => {
const {
Expand Down
128 changes: 128 additions & 0 deletions src/components/assets/RichImage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import classnames from 'classnames';
import deepmerge from 'deepmerge';
import isEmpty from 'lodash.isempty';
import React from 'react';
import { CSSStyles } from '../../types/CSSStyles';
import { Asset } from '../../types/data/Asset';
import { Link } from '../../types/data/Link';
import { cssToReactStyle } from '../../utils/css';

type Props = {
asset: Asset;
id?: string;
defaults?: Asset; // XXX Should be renamed to "assetFallback"
override?: Asset; // XXX Should be renamed to "assetOverride"
className?: string;
style?: CSSStyles;
onClick?: () => void;
linkOverride?: {
id?: string;
url?: string;
target?: string;
style?: CSSStyles;
className?: string;
};
}

const _defaultAsset = {
id: null,
url: '', // TODO use link of default missing image
title: '',
alt: '',
style: null,
className: '',
};

const _defaultLink: Link = {
id: null,
url: null,
target: '_blank',
style: null,
className: '',
};

/**
* Displays an image with enriched capabilities, for a given "Asset".
*
* Extra capabilities:
* - Auto-generates an "id", based on the asset.id
* - Asset default properties
* - A default asset can be provided and its properties will be used as fallback properties, if they're undefined in the asset property
* - Asset override
* - An asset override can be provided and its properties will take priority, even if they're defined within the asset property
* - Link wrapper
* - The image will be wrapped with a link, if a valid link (contains a "url") is provided either through:
* - The asset itself (asset.linkUrl)
* - The linkOverride (linkOverride.url)
* - Link override
* - A link override can be provided and its properties will take priority, even if they're defined within the link property
*
* @param props
*/
const RichImage = (props: Props): JSX.Element => {
const {
asset,
id,
defaults = {},
override = {},
className = '',
style = null,
onClick = null,
linkOverride = {},
}: Props = props;
if (isEmpty(asset)) {
return null;
}
const identifier = id || `asset-${asset?.id}`;
const defaultClass = id ? `asset-${id}` : identifier;
const resolvedAssetProps: Asset = deepmerge.all([_defaultAsset, defaults, asset || {}, override]);
const resolvedLinkProps: Link = deepmerge.all([
_defaultLink,
{
url: asset.linkUrl || _defaultLink.url,
target: asset.linkTarget || _defaultLink.target,
},
linkOverride,
]);

// Convert "style" if it is a string, to a react style object (won't modify if already an object)
resolvedAssetProps.style = cssToReactStyle(resolvedAssetProps.style);
resolvedLinkProps.style = cssToReactStyle(resolvedLinkProps.style);

const Image = (): JSX.Element => {
return (
<img
key={identifier}
id={identifier}
src={resolvedAssetProps.url}
title={resolvedAssetProps.title || resolvedAssetProps.filename}
alt={resolvedAssetProps.title || resolvedAssetProps.filename || resolvedAssetProps.url}
className={classnames(defaultClass, className, resolvedAssetProps.classes)}
style={deepmerge(style || {}, resolvedAssetProps.style || {})}
/>
);
};

// Create a link wrapper only if a link url is provided
if (resolvedLinkProps.url) {
return (
<a
key={resolvedLinkProps.id}
id={resolvedLinkProps.id}
href={resolvedLinkProps.url}
target={resolvedLinkProps.target}
className={classnames(`asset-link-${id}`, resolvedLinkProps.classes, resolvedLinkProps.className)}
style={deepmerge(resolvedLinkProps.style || {}, resolvedLinkProps.style || {})}
onClick={onClick} // Support for usage within <Link> component (from Next.js)
>
<Image />
</a>
);
} else {
return (
<Image />
);
}
};

export default RichImage;