Remove design-system dependency

This commit is contained in:
Lachlan Kermode
2022-03-03 20:24:38 -05:00
parent 20025dac57
commit 723c4b7007
14 changed files with 609 additions and 43 deletions

View File

@@ -0,0 +1,86 @@
import React from "react";
import PropTypes from "prop-types";
/**
* Primary UI component for user interaction
*/
export const Button = ({
primary,
backgroundColor,
borderRadius,
size,
label,
normalCursor,
...props
}) => {
const mode = primary ? "button--primary" : "button--secondary";
return (
<button
type="button"
className={[
"button",
`button--${size}`,
mode,
normalCursor ? "no-hover" : "",
].join(" ")}
style={{ backgroundColor: backgroundColor, borderRadius: borderRadius }}
{...props}
>
{label}
</button>
);
};
Button.propTypes = {
/**
* Is this the principal call to action on the page?
*/
primary: PropTypes.bool,
/**
* What background color to use
*/
backgroundColor: PropTypes.string,
/**
* How much rounded are they?
*/
borderRadius: PropTypes.string,
/**
* How large should the button be?
*/
size: PropTypes.oneOf(["small", "medium", "large"]),
/**
* Button contents
*/
label: PropTypes.string.isRequired,
/**
* Optional click handler
*/
onClick: PropTypes.func,
};
Button.defaultProps = {
backgroundColor: "red",
borderRadius: "0%",
primary: false,
size: "medium",
onClick: undefined,
};
const CardButton = ({
text,
color = "#000",
onClick = () => {},
normalCursor,
}) => (
<Button
size={"small"}
backgroundColor={color}
borderRadius={"12px"}
primary={false}
label={text}
onClick={onClick}
normalCursor={normalCursor}
/>
);
export default CardButton;

View File

@@ -0,0 +1,15 @@
import React from "react";
const CardCaret = ({ isOpen, toggle }) => {
let classes = isOpen ? "arrow-down" : "arrow-down folded";
return (
<div className="card-toggle" onClick={toggle}>
<p>
<i className={classes} />
</p>
</div>
);
};
export default CardCaret;

View File

@@ -0,0 +1,12 @@
import React from "react";
import marked from "marked";
// TODO could this be a security vulnerability?
const CardCustomField = ({ title, value }) => (
<div className="card-cell">
{title ? <h4>{title}</h4> : null}
<div dangerouslySetInnerHTML={{ __html: marked(`${value}`) }} />
</div>
);
export default CardCustomField;

View File

@@ -0,0 +1,61 @@
import React, { useRef } from "react";
import { useCallback } from "react";
import { typeForPath } from "../../../common/utilities";
const TITLE_LENGTH = 50;
// TODO should videos
// - play inline
// - appear zoomed out/in
// - only show cover image and then lightbox when clicked
// - show video control plane?
// TODO landscape image doesn't fit in box properly
const Media = ({ src, title }) => {
const videoRef = useRef();
const onVideoStart = useCallback(() => {
return videoRef.current?.play();
}, []);
const onVideoStop = useCallback(() => {
return videoRef.current?.pause();
}, []);
const type = typeForPath(src);
const formattedTitle =
title && title.length > TITLE_LENGTH
? `${title.slice(0, TITLE_LENGTH + 1)}...`
: title;
switch (type) {
case "Video":
return (
<div className="card-cell media">
{title && <h4 title={title}>{formattedTitle}</h4>}
<video
onMouseEnter={onVideoStart}
onMouseLeave={onVideoStop}
ref={videoRef}
// controls
// controlsList="nodownload noremoteplayback"
disablePictureInPicture
>
<source src={src} />
</video>
</div>
);
case "Image":
return (
<div className="card-cell media">
{title && <h4 title={title}>{formattedTitle}</h4>}
<div className="img-wrapper">
<img
src={src}
alt="an inline photograph for the event card component"
/>
</div>
</div>
);
default:
return null;
}
};
export default Media;

View File

@@ -0,0 +1,46 @@
import React, { useState } from "react";
const CardText = ({ title, value, hoverValue = null }) => {
const [showHover, setShowHover] = useState(false);
return (
<div className="card-cell">
{title ? <h4>{title}</h4> : null}
<div
style={{
width: `fit-content`,
}}
>
<div
onMouseOver={() => hoverValue && setShowHover(true)}
onMouseOut={() => hoverValue && setShowHover(false)}
>
{showHover ? (
<span
style={{
pointerEvents: `none`,
opacity: 0.8,
}}
>
<em>{hoverValue}</em>
</span>
) : (
<div
style={{
pointerEvents: `none`,
display: `inline-block`,
height: `1.1rem`,
borderBottom: hoverValue && `1px rgb(235, 68, 62) dashed`,
}}
>
{value}
</div>
)}
</div>
{/* {!showHover && value} */}
</div>
</div>
);
};
export default CardText;

View File

@@ -0,0 +1,29 @@
import React from "react";
import copy from "../../../common/data/copy.json";
import { isNotNullNorUndefined } from "../../../common/utilities";
const CardTime = ({ title = "Timestamp", timelabel, language, precision }) => {
const unknownLang = copy[language].cardstack.unknown_time;
if (isNotNullNorUndefined(timelabel)) {
return (
<div className="card-cell">
{/* <i className="material-icons left">today</i> */}
<h4>{title}</h4>
{timelabel}
{precision && precision !== "" ? ` - ${precision}` : null}
</div>
);
} else {
return (
<div className="card-cell">
{/* <i className="material-icons left">today</i> */}
<h4>{title}</h4>
{unknownLang}
</div>
);
}
};
export default CardTime;