Skip to content

Commit da8a4be

Browse files
committed
feat: Create xml-time component to convert time to iso string in xml documents
1 parent c57d308 commit da8a4be

File tree

6 files changed

+104
-0
lines changed

6 files changed

+104
-0
lines changed

packages/sdk-components-react/src/__generated__/xml-time.props.ts

Lines changed: 17 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/sdk-components-react/src/components.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export { VimeoPreviewImage } from "./vimeo-preview-image";
3333
export { VimeoPlayButton } from "./vimeo-play-button";
3434
export { VimeoSpinner } from "./vimeo-spinner";
3535
export { XmlNode } from "./xml-node";
36+
export { XmlTime } from "./xml-time";
3637
export { Time } from "./time";
3738
export { Select } from "./select";
3839
export { Option } from "./option";

packages/sdk-components-react/src/metas.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export { meta as VimeoPreviewImage } from "./vimeo-preview-image.ws";
3434
export { meta as VimeoPlayButton } from "./vimeo-play-button.ws";
3535
export { meta as VimeoSpinner } from "./vimeo-spinner.ws";
3636
export { meta as XmlNode } from "./xml-node.ws";
37+
export { meta as XmlTime } from "./xml-time.ws";
3738
export { meta as Time } from "./time.ws";
3839
export { meta as Select } from "./select.ws";
3940
export { meta as Option } from "./option.ws";

packages/sdk-components-react/src/props.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export { propsMeta as VimeoPreviewImage } from "./vimeo-preview-image.ws";
3333
export { propsMeta as VimeoPlayButton } from "./vimeo-play-button.ws";
3434
export { propsMeta as VimeoSpinner } from "./vimeo-spinner.ws";
3535
export { propsMeta as XmlNode } from "./xml-node.ws";
36+
export { propsMeta as XmlTime } from "./xml-time.ws";
3637
export { propsMeta as Time } from "./time.ws";
3738
export { propsMeta as Select } from "./select.ws";
3839
export { propsMeta as Option } from "./option.ws";
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import { forwardRef, useContext, type ElementRef } from "react";
2+
import { ReactSdkContext } from "@webstudio-is/react-sdk/runtime";
3+
4+
const DEFAULT_DATE_STYLE = "short";
5+
const INITIAL_DATE_STRING = "dateTime attribute is not set";
6+
const INVALID_DATE_STRING = "";
7+
8+
type XmlTimeProps = {
9+
dateStyle: "long" | "short";
10+
datetime: string;
11+
};
12+
13+
const parseDate = (datetimeString: string) => {
14+
if (datetimeString === "") {
15+
return;
16+
}
17+
let date = new Date(datetimeString);
18+
19+
// Check if the date already in valid format, e.g. "2024"
20+
if (Number.isNaN(date.getTime()) === false) {
21+
return date;
22+
}
23+
24+
// If its a number, we assume it's a timestamp and we may need to normalize it
25+
if (/^\d+$/.test(datetimeString)) {
26+
let timestamp = Number(datetimeString);
27+
// Normalize a 10-digit timestamp to 13-digit
28+
if (datetimeString.length === 10) {
29+
timestamp *= 1000;
30+
}
31+
date = new Date(timestamp);
32+
}
33+
34+
if (Number.isNaN(date.getTime()) === false) {
35+
return date;
36+
}
37+
};
38+
39+
export const XmlTime = forwardRef<ElementRef<"time">, XmlTimeProps>(
40+
({ dateStyle = DEFAULT_DATE_STYLE, datetime = INITIAL_DATE_STRING }, ref) => {
41+
const { renderer } = useContext(ReactSdkContext);
42+
43+
const datetimeString =
44+
datetime === null ? INVALID_DATE_STRING : datetime.toString();
45+
46+
const date = parseDate(datetimeString);
47+
48+
let formattedDate = datetimeString;
49+
if (date) {
50+
formattedDate = date.toISOString();
51+
if (dateStyle === "short") {
52+
formattedDate = formattedDate.split("T")[0];
53+
}
54+
}
55+
56+
if (renderer === undefined) {
57+
return formattedDate;
58+
}
59+
60+
return <time ref={ref}>{formattedDate}</time>;
61+
}
62+
);
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { CalendarIcon } from "@webstudio-is/icons/svg";
2+
3+
import {
4+
type WsComponentMeta,
5+
type WsComponentPropsMeta,
6+
} from "@webstudio-is/react-sdk";
7+
8+
import { props } from "./__generated__/xml-time.props";
9+
10+
export const meta: WsComponentMeta = {
11+
category: "xml",
12+
type: "container",
13+
description: "Converts machine-readable date and time to ISO format.",
14+
icon: CalendarIcon,
15+
stylable: false,
16+
order: 7,
17+
};
18+
19+
export const propsMeta: WsComponentPropsMeta = {
20+
props,
21+
initialProps: ["datetime", "dateStyle"],
22+
};

0 commit comments

Comments
 (0)