Skip to content
This repository was archived by the owner on May 15, 2025. It is now read-only.

chore: copy and duration components #81

Merged
merged 6 commits into from
Mar 3, 2025
Merged
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
25 changes: 25 additions & 0 deletions src/components/primitives/Copy.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Icon, OverrideTheme, type Styled, Text, mergeClass } from "../..";
import useClipboard from "../../hooks/useClipboard";
import type { TextProps } from "./Text";

import type { textStyles } from "./Text";

export type CopyProps = Omit<TextProps, "children" | "value"> & {
value: string;
size?: Styled<typeof textStyles>["size"];
};

export default function Copy({ size, value, className, ...props }: CopyProps) {
const { copy: copyCall, isCopied } = useClipboard();
return (
<Text size={size} {...props} className={mergeClass("dim select-none inline-flex", className)}>
<OverrideTheme coloring={isCopied ? "good" : undefined}>
<Icon
className="text-main-11"
remix={isCopied ? "RiCheckboxCircleFill" : "RiFileCopyFill"}
onClick={() => copyCall(value)}
/>
</OverrideTheme>
</Text>
);
}
23 changes: 23 additions & 0 deletions src/components/primitives/Duration.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import moment from "moment";
import { useMemo } from "react";

export type DurationProps = {
timestamp: number | bigint;
relative?: "hours" | "day" | "auto";
};

export default function Duration({ timestamp }: DurationProps) {
const time = useMemo(() => {
const then = moment.duration(Number(timestamp)).humanize();

return then
.replace(/a\s/, "1 ")
.replace(/\bminute(s?)\b/g, "m")
.replace(/\bsecond(s?)\b/g, "s")
.replace(/\bhour(s?)\b/g, (_match, plural) => (plural ? "hours" : "hour"))
.replace(/\bday(s?)\b/g, (_match, plural) => (plural ? "days" : "day"))
.replace(/\bmonth(s?)\b/g, (_match, plural) => (plural ? "months" : "month"));
}, [timestamp]);

return time;
}
24 changes: 4 additions & 20 deletions src/components/primitives/Hash.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { useMemo } from "react";
import { Icon, OverrideTheme, type Styled, mergeClass } from "../..";
import useClipboard from "../../hooks/useClipboard";
import { type Styled, mergeClass } from "../..";
import Text, { type TextProps } from "./Text";

import Copy from "./Copy";
import type { textStyles } from "./Text";

export type HashProps = Omit<TextProps, "children" | "value"> & {
Expand All @@ -27,30 +27,14 @@ export default function Hash({ value, format, copy, size, children: hash, classN
}
}, [hash, format]);

const { copy: copyCall, isCopied } = useClipboard();
const copyButton = useMemo(
() =>
copy && (
<OverrideTheme coloring={isCopied ? "good" : undefined}>
<Icon className="text-main-11" remix={isCopied ? "RiCheckboxCircleFill" : "RiFileCopyFill"} />
</OverrideTheme>
),
[copy, isCopied],
);

if (value) return formatted;
return (
<Text
size={size}
onClick={() => copyCall(hash)}
{...props}
className={mergeClass(
"items-center gap-sm cursor-pointer font-text",
copy && "dim select-none inline-flex",
className,
)}>
className={mergeClass("items-center gap-sm font-text", copy && "select-none inline-flex", className)}>
{formatted}
{copyButton}
{copy && <Copy value={hash} />}
</Text>
);
}
4 changes: 4 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ export * from "./components/primitives/Bar";
export { default as Bar } from "./components/primitives/Bar";
export * from "./components/primitives/Time";
export { default as Time } from "./components/primitives/Time";
export * from "./components/primitives/Duration";
export { default as Duration } from "./components/primitives/Duration";
export * from "./components/primitives/Copy";
export { default as Copy } from "./components/primitives/Copy";
export * from "./components/primitives/List";
export { default as List } from "./components/primitives/List";
export * from "./components/primitives/Hash";
Expand Down