Skip to content

Commit 9014ade

Browse files
committed
feat: Add head component
1 parent a98f149 commit 9014ade

12 files changed

+1397
-1
lines changed

packages/sdk-components-react/src/__generated__/head-link.props.ts

+658
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

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

+562
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

+2
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,5 @@ export { XmlTime } from "./xml-time";
3838
export { Time } from "./time";
3939
export { Select } from "./select";
4040
export { Option } from "./option";
41+
export { Head } from "./head";
42+
export { HeadLink } from "./head-link";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { ReactSdkContext } from "@webstudio-is/react-sdk/runtime";
2+
import {
3+
forwardRef,
4+
type ElementRef,
5+
type ComponentProps,
6+
useContext,
7+
} from "react";
8+
import { XmlNode } from "./xml-node";
9+
10+
export const defaultTag = "link";
11+
12+
type LinkRel =
13+
| "alternate"
14+
| "author"
15+
| "canonical"
16+
| "dns-prefetch"
17+
| "help"
18+
| "icon"
19+
| "license"
20+
| "manifest"
21+
| "modulepreload"
22+
| "next"
23+
| "nofollow"
24+
| "noopener"
25+
| "noreferrer"
26+
| "opener"
27+
| "pingback"
28+
| "preconnect"
29+
| "prefetch"
30+
| "preload"
31+
| "prev"
32+
| "search"
33+
| "stylesheet"
34+
| "tag";
35+
36+
export const HeadLink = forwardRef<
37+
ElementRef<"div">,
38+
{ rel: LinkRel } & ComponentProps<typeof defaultTag>
39+
>(({ ...props }, ref) => {
40+
const { renderer } = useContext(ReactSdkContext);
41+
42+
if (renderer === undefined) {
43+
return <link {...props} />;
44+
}
45+
46+
return <XmlNode tag={defaultTag} {...props} ref={ref} />;
47+
});
48+
49+
HeadLink.displayName = "HeadLink";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { Link2Icon } from "@webstudio-is/icons/svg";
2+
import {
3+
type WsComponentMeta,
4+
type WsComponentPropsMeta,
5+
} from "@webstudio-is/sdk";
6+
7+
import { props } from "./__generated__/head-link.props";
8+
9+
export const meta: WsComponentMeta = {
10+
category: "hidden",
11+
icon: Link2Icon,
12+
type: "container",
13+
constraints: {
14+
relation: "parent",
15+
component: { $eq: "Head" },
16+
},
17+
};
18+
19+
export const propsMeta: WsComponentPropsMeta = {
20+
props,
21+
initialProps: ["rel", "href", "type", "hreflang"],
22+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { type TemplateMeta, $ } from "@webstudio-is/template";
2+
3+
export const meta: TemplateMeta = {
4+
category: "general",
5+
description: "Head",
6+
order: 4,
7+
template: (
8+
<$.Head>
9+
<$.HeadLink rel="help" href="/help"></$.HeadLink>
10+
</$.Head>
11+
),
12+
};
+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import {
2+
getClosestInstance,
3+
ReactSdkContext,
4+
type Hook,
5+
} from "@webstudio-is/react-sdk/runtime";
6+
import {
7+
forwardRef,
8+
type ElementRef,
9+
type ComponentProps,
10+
useContext,
11+
} from "react";
12+
import { XmlNode } from "./xml-node";
13+
14+
export const defaultTag = "head";
15+
16+
export const Head = forwardRef<
17+
ElementRef<"div">,
18+
{ "data-ws-expand": boolean } & ComponentProps<typeof defaultTag>
19+
>(({ ...props }, ref) => {
20+
const { renderer } = useContext(ReactSdkContext);
21+
22+
if (props["data-ws-expand"] !== true) {
23+
return null;
24+
}
25+
26+
if (renderer === undefined) {
27+
return props.children;
28+
}
29+
30+
return <XmlNode tag={defaultTag} {...props} ref={ref} />;
31+
});
32+
33+
Head.displayName = "Head";
34+
35+
export const hooksHead: Hook = {
36+
onNavigatorUnselect: (context, event) => {
37+
for (const instance of event.instancePath) {
38+
if (instance.component === `Head`) {
39+
const popover = getClosestInstance(
40+
event.instancePath,
41+
instance,
42+
`Head`
43+
);
44+
if (popover) {
45+
context.setMemoryProp(popover, "data-ws-expand", undefined);
46+
}
47+
}
48+
}
49+
},
50+
onNavigatorSelect: (context, event) => {
51+
for (const instance of event.instancePath) {
52+
if (instance.component === `Head`) {
53+
const popover = getClosestInstance(
54+
event.instancePath,
55+
instance,
56+
`Head`
57+
);
58+
if (popover) {
59+
context.setMemoryProp(popover, "data-ws-expand", true);
60+
}
61+
}
62+
}
63+
},
64+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { HeaderIcon } from "@webstudio-is/icons/svg";
2+
import {
3+
type WsComponentMeta,
4+
type WsComponentPropsMeta,
5+
} from "@webstudio-is/sdk";
6+
7+
import { props } from "./__generated__/head.props";
8+
9+
export const meta: WsComponentMeta = {
10+
icon: HeaderIcon,
11+
type: "container",
12+
constraints: {
13+
relation: "ancestor",
14+
component: { $nin: ["Head"] },
15+
},
16+
};
17+
18+
export const propsMeta: WsComponentPropsMeta = {
19+
props,
20+
initialProps: [],
21+
};
+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { Hook } from "@webstudio-is/react-sdk";
22
import { hooksSelect } from "./select";
3+
import { hooksHead } from "./head";
34

4-
export const hooks: Hook[] = [hooksSelect];
5+
export const hooks: Hook[] = [hooksSelect, hooksHead];

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

+2
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,5 @@ export { meta as XmlTime } from "./xml-time.ws";
3838
export { meta as Time } from "./time.ws";
3939
export { meta as Select } from "./select.ws";
4040
export { meta as Option } from "./option.ws";
41+
export { meta as Head } from "./head.ws";
42+
export { meta as HeadLink } from "./head-link.ws";

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

+2
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,5 @@ export { propsMeta as XmlTime } from "./xml-time.ws";
3838
export { propsMeta as Time } from "./time.ws";
3939
export { propsMeta as Select } from "./select.ws";
4040
export { propsMeta as Option } from "./option.ws";
41+
export { propsMeta as Head } from "./head.ws";
42+
export { propsMeta as HeadLink } from "./head-link.ws";

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

+1
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ export { meta as Checkbox } from "./checkbox.template";
1515
export { meta as Vimeo } from "./vimeo.template";
1616
export { meta as YouTube } from "./youtube.template";
1717
export { meta as Select } from "./select.template";
18+
export { meta as Head } from "./head.template";

0 commit comments

Comments
 (0)