| 1 |
import React from "react"; |
| 2 |
import PropTypes from "prop-types"; |
| 3 |
import { |
| 4 |
SortableContainer, |
| 5 |
SortableElement, |
| 6 |
SortableHandle, |
| 7 |
} from "react-sortable-hoc"; |
| 8 |
import ColorControl from "../color-control"; |
| 9 |
|
| 10 |
const { __ } = wp.i18n; |
| 11 |
const DEFAULT_PROFILE_COLOR = "#9f9f9f"; |
| 12 |
|
| 13 |
const TrashIcon = ({ position, onDeleteProfile }) => ( |
| 14 |
<span |
| 15 |
className="eb-social-delete-icon" |
| 16 |
style={trashStyle} |
| 17 |
onClick={() => onDeleteProfile(position)} |
| 18 |
> |
| 19 |
<svg |
| 20 |
xmlns="http://www.w3.org/2000/svg" |
| 21 |
x="0" |
| 22 |
y="0" |
| 23 |
enableBackground="new 0 0 512 512" |
| 24 |
version="1.1" |
| 25 |
viewBox="0 0 512 512" |
| 26 |
xmlSpace="preserve" |
| 27 |
style={{ width: 14 }} |
| 28 |
> |
| 29 |
<path |
| 30 |
d="M423.3 86.6H89c-16.8.1-32.2 9.3-40.1 24.1-7.9 14.8-7.1 32.7 2.2 46.8l37.2 55.6V456c0 30.9 25.1 56 56 56h223.9c30.9 0 56-25.1 56-56V213.1l37.2-56c9.1-14 9.8-31.8 1.9-46.5-8.1-14.7-23.4-23.9-40-24zm-198 347c0 13.9-11.3 25.2-25.2 25.2-13.9 0-25.2-11.3-25.2-25.2V220.9c0-13.9 11.3-25.2 25.2-25.2 13.9 0 25.2 11.3 25.2 25.2v212.7zm112 0c0 13.9-11.3 25.2-25.2 25.2-13.9 0-25.2-11.3-25.2-25.2V220.9c0-13.9 11.3-25.2 25.2-25.2 13.9 0 25.2 11.3 25.2 25.2v212.7zM325.8 19.4C309.9 7.1 290.2 0 269.3 0h-26.4c-20.9 0-40.6 7.1-56.5 19.4-11.2 8.7-20.5 20.1-26.9 33.4h193.1c-6.3-13.3-15.6-24.7-26.8-33.4z" |
| 31 |
style={{ fill: "#FF6464" }} |
| 32 |
></path> |
| 33 |
</svg> |
| 34 |
</span> |
| 35 |
); |
| 36 |
|
| 37 |
const DragHandle = SortableHandle(() => ( |
| 38 |
<span className="drag-handle"> |
| 39 |
<svg |
| 40 |
xmlns="http://www.w3.org/2000/svg" |
| 41 |
x="0" |
| 42 |
y="0" |
| 43 |
enableBackground="new 0 0 512 512" |
| 44 |
version="1.1" |
| 45 |
viewBox="0 0 512 512" |
| 46 |
xmlSpace="preserve" |
| 47 |
style={{ height: 14 }} |
| 48 |
> |
| 49 |
<path |
| 50 |
d="M512 256L402.6 146.6 402.6 210.3 301 210.3 301 109.4 365.4 109.4 256 0 146.6 109.4 211 109.4 211 210.3 109.4 210.3 109.4 146.6 0 256 109.4 365.4 109.4 300.3 211 300.3 211 402.6 146.6 402.6 256 512 365.4 402.6 301 402.6 301 300.3 402.6 300.3 402.6 365.4z" |
| 51 |
style={{ fill: "#a9a9a9" }} |
| 52 |
></path> |
| 53 |
</svg> |
| 54 |
</span> |
| 55 |
)); |
| 56 |
|
| 57 |
const SortableItem = SortableElement( |
| 58 |
({ |
| 59 |
position, |
| 60 |
profile, |
| 61 |
onProfileClick, |
| 62 |
onDeleteProfile, |
| 63 |
onColorChange, |
| 64 |
selectedIcon, |
| 65 |
url, |
| 66 |
onUrlChange, |
| 67 |
onSubmit, |
| 68 |
}) => ( |
| 69 |
<li className="drag-helper"> |
| 70 |
<span className="profile-wrapper"> |
| 71 |
<span |
| 72 |
className="profile-icon-container" |
| 73 |
onClick={() => onProfileClick(profile.icon)} |
| 74 |
> |
| 75 |
<span className={`fab fa-${profile.icon}`} /> |
| 76 |
<span className="selected-profile-icon">{profile.icon}</span> |
| 77 |
</span> |
| 78 |
<DragHandle /> |
| 79 |
<TrashIcon position={position} onDeleteProfile={onDeleteProfile} /> |
| 80 |
</span> |
| 81 |
|
| 82 |
{selectedIcon === profile.icon && profile.isExpanded && ( |
| 83 |
<div className="link-form-wrapper"> |
| 84 |
<ColorControl |
| 85 |
label={__("Icon Color", "betterdocs")} |
| 86 |
color={profile.color || DEFAULT_PROFILE_COLOR} |
| 87 |
onChange={(color) => onColorChange(color, position)} |
| 88 |
/> |
| 89 |
<input |
| 90 |
type="text" |
| 91 |
className="social-link-input" |
| 92 |
placeholder={`Enter ${profile.icon} link`} |
| 93 |
value={url} |
| 94 |
onChange={(event) => onUrlChange(event, profile.icon)} |
| 95 |
/> |
| 96 |
<button |
| 97 |
className="save-button" |
| 98 |
onClick={() => onSubmit(profile.icon)} |
| 99 |
> |
| 100 |
Save |
| 101 |
</button> |
| 102 |
</div> |
| 103 |
)} |
| 104 |
</li> |
| 105 |
) |
| 106 |
); |
| 107 |
|
| 108 |
const SortableList = SortableContainer((props) => { |
| 109 |
const { profiles, ...rest } = props; |
| 110 |
|
| 111 |
return ( |
| 112 |
<ul> |
| 113 |
{profiles.map((profile, index) => ( |
| 114 |
<SortableItem |
| 115 |
profile={profile} |
| 116 |
key={index} |
| 117 |
{...rest} |
| 118 |
position={index} |
| 119 |
index={index} |
| 120 |
/> |
| 121 |
))} |
| 122 |
</ul> |
| 123 |
); |
| 124 |
}); |
| 125 |
|
| 126 |
const SortableComponent = ({ profiles, onSortEnd, ...rest }) => { |
| 127 |
if (profiles.length === 0) return <ul />; |
| 128 |
|
| 129 |
return ( |
| 130 |
<SortableList |
| 131 |
profiles={profiles} |
| 132 |
useDragHandle={true} |
| 133 |
onSortEnd={onSortEnd} |
| 134 |
{...rest} |
| 135 |
/> |
| 136 |
); |
| 137 |
}; |
| 138 |
|
| 139 |
// Style objects |
| 140 |
const trashStyle = { |
| 141 |
fontSize: 14, |
| 142 |
borderLeft: "1px solid #b4b4cb", |
| 143 |
lineHeight: "2.5em", |
| 144 |
flex: 2, |
| 145 |
textAlign: "center", |
| 146 |
display: "flex", |
| 147 |
justifyContent: "center", |
| 148 |
}; |
| 149 |
|
| 150 |
SortableComponent.propTypes = { |
| 151 |
profiles: PropTypes.shape({ |
| 152 |
icon: PropTypes.string.isRequired, |
| 153 |
link: PropTypes.string, |
| 154 |
isExpanded: PropTypes.bool.isRequired, |
| 155 |
}), |
| 156 |
onProfileClick: PropTypes.func.isRequired, |
| 157 |
onDeleteProfile: PropTypes.func.isRequired, |
| 158 |
selectedIcon: PropTypes.string.isRequired, |
| 159 |
url: PropTypes.string.isRequired, |
| 160 |
onUrlChange: PropTypes.func.isRequired, |
| 161 |
onSubmit: PropTypes.func.isRequired, |
| 162 |
onProfileAdd: PropTypes.func.isRequired, |
| 163 |
onSortEnd: PropTypes.func.isRequired, |
| 164 |
onColorChange: PropTypes.func.isRequired, |
| 165 |
}; |
| 166 |
|
| 167 |
export default SortableComponent; |
| 168 |
|