feat(widget-image): enable images ordering (#4857)

This commit is contained in:
Francois-Stevenart 2021-01-29 16:26:56 +01:00 committed by GitHub
parent 27aec85550
commit 30c11954d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 54 additions and 12 deletions

View File

@ -23,7 +23,9 @@
"build:esm": "cross-env NODE_ENV=esm babel src --out-dir dist/esm --ignore \"**/__tests__\" --root-mode upward"
},
"dependencies": {
"common-tags": "^1.8.0"
"common-tags": "^1.8.0",
"react-sortable-hoc": "^1.0.0",
"array-move": "3.0.1"
},
"peerDependencies": {
"@emotion/core": "^10.0.35",

View File

@ -2,12 +2,15 @@ import React from 'react';
import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
import styled from '@emotion/styled';
import { css } from '@emotion/core';
import { Map, List } from 'immutable';
import { once } from 'lodash';
import uuid from 'uuid/v4';
import { oneLine } from 'common-tags';
import { lengths, components, buttons, borders, effects, shadows } from 'netlify-cms-ui-default';
import { basename } from 'netlify-cms-lib-util';
import { SortableContainer, SortableElement } from 'react-sortable-hoc';
import arrayMove from 'array-move';
const MAX_DISPLAY_LENGTH = 50;
@ -22,6 +25,7 @@ const ImageWrapper = styled.div`
overflow: hidden;
${effects.checkerboard};
${shadows.inset};
cursor: ${props => (props.sortable ? 'pointer' : 'auto')};
`;
const StyledImage = styled.img`
@ -32,10 +36,34 @@ const StyledImage = styled.img`
const Image = props => <StyledImage role="presentation" {...props} />;
const MultiImageWrapper = styled.div`
display: flex;
flex-wrap: wrap;
`;
const SortableImage = SortableElement(({ itemValue, getAsset, field }) => {
return (
<ImageWrapper sortable>
<Image src={getAsset(itemValue, field) || ''} />
</ImageWrapper>
);
});
const SortableMultiImageWrapper = SortableContainer(({ items, getAsset, field }) => {
return (
<div
css={css`
display: flex;
flex-wrap: wrap;
`}
>
{items.map((itemValue, index) => (
<SortableImage
key={`item-${itemValue}`}
index={index}
itemValue={itemValue}
getAsset={getAsset}
field={field}
/>
))}
</div>
);
});
const FileLink = styled.a`
margin-bottom: 20px;
@ -188,6 +216,12 @@ export default function withFileControl({ forImage } = {}) {
return this.props.onChange('');
};
onSortEnd = ({ oldIndex, newIndex }) => {
const { value } = this.props;
const newValue = arrayMove(value, oldIndex, newIndex);
return this.props.onChange(newValue);
};
getValidateValue = () => {
const { value } = this.props;
if (value) {
@ -235,13 +269,14 @@ export default function withFileControl({ forImage } = {}) {
if (isMultiple(value)) {
return (
<MultiImageWrapper>
{value.map(val => (
<ImageWrapper key={val}>
<Image src={getAsset(val, field) || ''} />
</ImageWrapper>
))}
</MultiImageWrapper>
<SortableMultiImageWrapper
items={value}
onSortEnd={this.onSortEnd}
getAsset={getAsset}
field={field}
axis="xy"
lockToContainerEdges={true}
></SortableMultiImageWrapper>
);
}

View File

@ -4323,6 +4323,11 @@ array-includes@^3.0.3, array-includes@^3.1.1, array-includes@^3.1.2:
get-intrinsic "^1.0.1"
is-string "^1.0.5"
array-move@3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/array-move/-/array-move-3.0.1.tgz#179645cc0987b65953a4fc06b6df9045e4ba9618"
integrity sha512-H3Of6NIn2nNU1gsVDqDnYKY/LCdWvCMMOWifNGhKcVQgiZ6nOek39aESOvro6zmueP07exSl93YLvkN4fZOkSg==
array-union@^1.0.1, array-union@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39"