Skip to content

Commit

Permalink
refactor: replace date-fns with use-relative-time
Browse files Browse the repository at this point in the history
See https://github.com/nkzw-tech/use-relative-time

We use only single function from date-fns while the package is like 22MB.
Here's small alternative for react based on intl.

Added jsx support to ours toasts inside of builder and RelativeTime
component to use it inside of callbacks.
  • Loading branch information
TrySound committed Jan 10, 2025
1 parent 4b1c143 commit 12ce22e
Show file tree
Hide file tree
Showing 8 changed files with 61 additions and 43 deletions.
24 changes: 9 additions & 15 deletions apps/builder/app/builder/features/ai/ai-command-bar.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { formatDistance } from "date-fns/formatDistance";
import {
AutogrowTextArea,
Box,
Expand Down Expand Up @@ -41,6 +40,7 @@ import { AiApiException, RateLimitException } from "./api-exceptions";
import { getSetting, setSetting } from "~/builder/shared/client-settings";
import { flushSync } from "react-dom";
import { $selectedPage } from "~/shared/awareness";
import { RelativeTime } from "~/builder/shared/relative-time";

type PartialButtonProps<T = ComponentPropsWithoutRef<typeof Button>> = {
[key in keyof T]?: T[key];
Expand Down Expand Up @@ -117,13 +117,10 @@ export const AiCommandBar = () => {
} catch (error) {
if (error instanceof RateLimitException) {
toast.info(
`Temporary AI rate limit reached. Please wait ${formatDistance(
Date.now(),
new Date(error.meta.reset),
{
includeSeconds: true,
}
)} and try again.`
<>
Temporary AI rate limit reached. Please wait{" "}
<RelativeTime time={new Date(error.meta.reset)} /> and try again.
</>
);
return;
}
Expand Down Expand Up @@ -219,13 +216,10 @@ export const AiCommandBar = () => {

if (error instanceof RateLimitException) {
toast.info(
`Temporary AI rate limit reached. Please wait ${formatDistance(
Date.now(),
new Date(error.meta.reset),
{
includeSeconds: true,
}
)} and try again.`
<>
Temporary AI rate limit reached. Please wait{" "}
<RelativeTime time={new Date(error.meta.reset)} /> and try again.
</>
);
return;
}
Expand Down
18 changes: 9 additions & 9 deletions apps/builder/app/builder/features/topbar/domains.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ import {
useOptimistic,
useRef,
useState,
type ReactNode,
} from "react";
import { formatDistance } from "date-fns/formatDistance";
import { Entri } from "./entri";
import { nativeClient } from "~/shared/trpc/trpc-client";
import { useStore } from "@nanostores/react";
Expand All @@ -36,6 +36,7 @@ import { extractCname } from "./cname";
import { useEffectEvent } from "~/shared/hook-utils/effect-event";
import DomainCheckbox from "./domain-checkbox";
import { CopyToClipboard } from "~/builder/shared/copy-to-clipboard";
import { RelativeTime } from "~/builder/shared/relative-time";

export type Domain = Project["domainsVirtual"][number];
type DomainStatus = Project["domainsVirtual"][number]["status"];
Expand Down Expand Up @@ -77,13 +78,12 @@ export const getPublishStatusAndText = ({
? "Publish failed"
: "Publishing started";

const statusText = `${textStart} ${formatDistance(
new Date(createdAt),
new Date(),
{
addSuffix: true,
}
)}`;
const statusText = (
<>
{textStart}
<RelativeTime time={new Date(createdAt)} />
</>
);

return { statusText, status };
};
Expand All @@ -95,7 +95,7 @@ const getStatusText = (props: {
const status = getStatus(props.projectDomain);

let isVerifiedActive = false;
let text = "Something went wrong";
let text: ReactNode = "Something went wrong";

switch (status) {
case "UNVERIFIED":
Expand Down
18 changes: 9 additions & 9 deletions apps/builder/app/builder/features/topbar/publish.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ import { humanizeString } from "~/shared/string-utils";
import { trpcClient, nativeClient } from "~/shared/trpc/trpc-client";
import { isFeatureEnabled } from "@webstudio-is/feature-flags";
import type { Templates } from "@webstudio-is/sdk";
import { formatDistance } from "date-fns/formatDistance";
import DomainCheckbox, { domainToPublishName } from "./domain-checkbox";
import { CopyToClipboard } from "~/builder/shared/copy-to-clipboard";
import { $openProjectSettings } from "~/shared/nano-states/project-settings";
import { RelativeTime } from "~/builder/shared/relative-time";

type ChangeProjectDomainProps = {
project: Project;
Expand Down Expand Up @@ -206,7 +206,9 @@ const Publish = ({

refresh: () => Promise<void>;
}) => {
const [publishError, setPublishError] = useState<undefined | string>();
const [publishError, setPublishError] = useState<
undefined | JSX.Element | string
>();
const [isPublishing, setIsPublishing] = useOptimistic(false);
const buttonRef = useRef<HTMLButtonElement>(null);
const [hasSelectedDomains, setHasSelectedDomains] = useState(false);
Expand Down Expand Up @@ -391,13 +393,11 @@ const getStaticPublishStatusAndText = ({
? "Download failed"
: "Download started";

const statusText = `${textStart} ${formatDistance(
new Date(updatedAt),
new Date(),
{
addSuffix: true,
}
)}`;
const statusText = (
<>
{textStart} <RelativeTime time={new Date(updatedAt)} />
</>
);

return { statusText, status };
};
Expand Down
5 changes: 5 additions & 0 deletions apps/builder/app/builder/shared/relative-time.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import useRelativeTime from "@nkzw/use-relative-time";

export const RelativeTime = ({ time }: { time: Date }) => {
return useRelativeTime(time.getTime());
};
9 changes: 8 additions & 1 deletion apps/builder/app/shared/builder-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,16 @@ import { uploadAssets } from "~/builder/shared/assets/use-assets";

const apiWindowNamespace = "__webstudio__$__builderApi";

type ToastHandler = (message: string) => void;

const _builderApi = {
isInitialized: () => true,
toast,
toast: {
info: toast.info as ToastHandler,
warn: toast.warn as ToastHandler,
error: toast.error as ToastHandler,
success: toast.success as ToastHandler,
},
uploadImages: async (srcs: string[]) => {
const urlToIds = await uploadAssets(
"image",
Expand Down
2 changes: 1 addition & 1 deletion apps/builder/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"@lezer/css": "^1.1.9",
"@lezer/highlight": "^1.2.1",
"@nanostores/react": "^0.8.0",
"@nkzw/use-relative-time": "^1.1.0",
"@radix-ui/react-select": "^2.1.4",
"@radix-ui/react-tooltip": "^1.1.6",
"@react-aria/interactions": "^3.22.5",
Expand Down Expand Up @@ -81,7 +82,6 @@
"colord": "^2.9.3",
"cookie": "^1.0.1",
"css-tree": "^2.3.1",
"date-fns": "^3.6.0",
"debug": "^4.3.7",
"downshift": "^6.1.7",
"fast-deep-equal": "^3.1.3",
Expand Down
13 changes: 8 additions & 5 deletions packages/design-system/src/components/toast.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { JSX } from "react";
import * as ToastPrimitive from "@radix-ui/react-toast";
import hotToast, {
resolveValue,
Expand All @@ -9,7 +10,6 @@ import { keyframes, rawTheme, styled, type CSS } from "../stitches.config";
import { Box } from "./box";
import { theme } from "../stitches.config";
import { Grid } from "./grid";

import { Text } from "./text";
import { Flex } from "./flex";
import { Tooltip } from "./tooltip";
Expand Down Expand Up @@ -383,9 +383,12 @@ export const Toaster = () => {
type Options = Pick<ToastOptions, "duration" | "id" | "icon">;

export const toast = {
info: (value: string, options?: Options) => hotToast(value, options),
error: (value: string, options?: Options) => hotToast.error(value, options),
warn: (value: string, options?: Options) => hotToast.custom(value, options),
success: (value: string, options?: Options) =>
info: (value: JSX.Element | string, options?: Options) =>
hotToast(value, options),
error: (value: JSX.Element | string, options?: Options) =>
hotToast.error(value, options),
warn: (value: JSX.Element | string, options?: Options) =>
hotToast.custom(value, options),
success: (value: JSX.Element | string, options?: Options) =>
hotToast.success(value, options),
};
15 changes: 12 additions & 3 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 12ce22e

Please sign in to comment.