Skip to content
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
15 changes: 13 additions & 2 deletions apps/builder/app/canvas/interceptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,21 @@ const switchPageAndUpdateSystem = (href: string, formData?: FormData) => {
return;
}
// preserve pathname when not specified in href/action
if (href === "" || href.startsWith("?") || href.startsWith("#")) {
if (href === "" || href.startsWith("?")) {
const pathname = getSelectedPagePathname();
if (pathname) {
href = pathname + href;
href = `${pathname}${href}`;
}
}
// preserve also search params when navigate with hash
if (href.startsWith("#")) {
const pathname = getSelectedPagePathname();
if (pathname) {
const system = $currentSystem.get();
const searchParams = new URLSearchParams(
system.search as Record<string, string>
);
href = `${pathname}?${searchParams}${href}`;
}
}
const pageHref = new URL(href, "https://any-valid.url");
Expand Down
42 changes: 40 additions & 2 deletions packages/sdk-components-react-remix/src/link.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,42 @@
import { forwardRef, type ComponentPropsWithoutRef, useContext } from "react";
import { NavLink as RemixLink } from "@remix-run/react";
import { ReactSdkContext } from "@webstudio-is/react-sdk/runtime";
import { Link as BaseLink } from "@webstudio-is/sdk-components-react";
import { wrapLinkComponent } from "./shared/remix-link";

export const Link = wrapLinkComponent(BaseLink);
type Props = Omit<ComponentPropsWithoutRef<typeof BaseLink>, "target"> & {
// override (string & {}) in target to generate keywords
target?: "_self" | "_blank" | "_parent" | "_top";

// useful remix props
prefetch?: "none" | "intent" | "render" | "viewport";
reloadDocument?: boolean;
replace?: boolean;
preventScrollReset?: boolean;
};

export const Link = forwardRef<HTMLAnchorElement, Props>((props, ref) => {
const { assetBaseUrl } = useContext(ReactSdkContext);
// cast to string when invalid value type is provided with binding
const href = String(props.href ?? "");

// use remix link for self reference and all relative urls
// ignore asset paths which can be relative too
// urls starting with # should be handled natively to not override search params
if (
// remix appends ?index in runtime but not in ssr
href === "" ||
href.startsWith("?") ||
(href.startsWith("/") && href.startsWith(assetBaseUrl) === false)
) {
// In the future, we will switch to the :local-link pseudo-class (https://developer.mozilla.org/en-US/docs/Web/CSS/:local-link). (aria-current="page" is used now)
// Therefore, we decided to use end={true} (exact route matching) for all links to facilitate easier migration.
return <RemixLink {...props} to={href} ref={ref} end />;
}

const { prefetch, reloadDocument, replace, preventScrollReset, ...rest } =
props;

return <BaseLink {...rest} ref={ref} />;
});

Link.displayName = BaseLink.displayName;
5 changes: 1 addition & 4 deletions packages/sdk-components-react-remix/src/rich-text-link.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
import { RichTextLink as BaseLink } from "@webstudio-is/sdk-components-react";
import { wrapLinkComponent } from "./shared/remix-link";

export const RichTextLink = wrapLinkComponent(BaseLink);
export { Link as RichTextLink } from "./link";
46 changes: 0 additions & 46 deletions packages/sdk-components-react-remix/src/shared/remix-link.tsx

This file was deleted.

42 changes: 40 additions & 2 deletions packages/sdk-components-react-router/src/link.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,42 @@
import { type ComponentPropsWithoutRef, forwardRef, useContext } from "react";
import { NavLink as RemixLink } from "react-router";
import { ReactSdkContext } from "@webstudio-is/react-sdk/runtime";
import { Link as BaseLink } from "@webstudio-is/sdk-components-react";
import { wrapLinkComponent } from "./shared/remix-link";

export const Link = wrapLinkComponent(BaseLink);
type Props = Omit<ComponentPropsWithoutRef<typeof BaseLink>, "target"> & {
// override (string & {}) in target to generate keywords
target?: "_self" | "_blank" | "_parent" | "_top";

// useful remix props
prefetch?: "none" | "intent" | "render" | "viewport";
reloadDocument?: boolean;
replace?: boolean;
preventScrollReset?: boolean;
};

export const Link = forwardRef<HTMLAnchorElement, Props>((props, ref) => {
const { assetBaseUrl } = useContext(ReactSdkContext);
// cast to string when invalid value type is provided with binding
const href = String(props.href ?? "");

// use remix link for self reference and all relative urls
// ignore asset paths which can be relative too
// urls starting with # should be handled natively to not override search params
if (
// remix appends ?index in runtime but not in ssr
href === "" ||
href.startsWith("?") ||
(href.startsWith("/") && href.startsWith(assetBaseUrl) === false)
) {
// In the future, we will switch to the :local-link pseudo-class (https://developer.mozilla.org/en-US/docs/Web/CSS/:local-link). (aria-current="page" is used now)
// Therefore, we decided to use end={true} (exact route matching) for all links to facilitate easier migration.
return <RemixLink {...props} to={href} ref={ref} end />;
}

const { prefetch, reloadDocument, replace, preventScrollReset, ...rest } =
props;

return <BaseLink {...rest} ref={ref} />;
});

Link.displayName = BaseLink.displayName;
5 changes: 1 addition & 4 deletions packages/sdk-components-react-router/src/rich-text-link.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
import { RichTextLink as BaseLink } from "@webstudio-is/sdk-components-react";
import { wrapLinkComponent } from "./shared/remix-link";

export const RichTextLink = wrapLinkComponent(BaseLink);
export { Link as RichTextLink } from "./link";
46 changes: 0 additions & 46 deletions packages/sdk-components-react-router/src/shared/remix-link.tsx

This file was deleted.