Improved Links

This commit is contained in:
aronmal 2023-10-20 15:17:02 +02:00
parent 7390bcbc01
commit 85f1ce262a
Signed by: aronmal
GPG key ID: 816B7707426FC612
14 changed files with 461 additions and 315 deletions

View file

@ -1,8 +1,9 @@
import { Show } from "solid-js";
import { A } from "solid-start";
function DeviceTile(props: { href?: string; name: string; src: string }) {
return (
<a href={props.href ?? "/soon"}>
<A href={props.href ?? "/soon"}>
<div class="raster">
<h3>{props.name}</h3>
<Show when={props.src.startsWith("/images")}>
@ -14,7 +15,7 @@ function DeviceTile(props: { href?: string; name: string; src: string }) {
</video>
</Show>
</div>
</a>
</A>
);
}

View file

@ -0,0 +1,113 @@
import { FaSymbol, FlipProp, IconDefinition, IconProp, PullProp, RotateProp, SizeProp, Transform } from "@fortawesome/fontawesome-svg-core";
import { Show, type JSX } from "solid-js";
export interface FontAwesomeIconProps extends Omit<JSX.SvgSVGAttributes<SVGSVGElement>, "children" | "mask" | "transform"> {
icon: IconDefinition;
mask?: IconProp;
maskId?: string;
color?: string;
spin?: boolean;
spinPulse?: boolean;
spinReverse?: boolean;
pulse?: boolean;
beat?: boolean;
fade?: boolean;
beatFade?: boolean;
bounce?: boolean;
shake?: boolean;
flash?: boolean;
border?: boolean;
fixedWidth?: boolean;
inverse?: boolean;
listItem?: boolean;
flip?: FlipProp;
size?: SizeProp;
pull?: PullProp;
rotation?: RotateProp;
transform?: string | Transform;
symbol?: FaSymbol;
style?: JSX.CSSProperties;
tabIndex?: number;
title?: string;
titleId?: string;
swapOpacity?: boolean;
}
const idPool = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
function nextUniqueId() {
let size = 12;
let id = "";
while (size-- > 0) {
id += idPool[(Math.random() * 62) | 0];
}
return id;
}
function Path(props: { d: string | string[] }) {
return (
<>
{typeof props.d === "string" ? (
<path fill="currentColor" d={props.d} />
) : (
<>
<path class="fa-secondary" fill="currentColor" d={props.d[0]} />
<path class="fa-primary" fill="currentColor" d={props.d[1]} />
</>
)}
</>
);
}
export function FontAwesomeIcon(props: FontAwesomeIconProps) {
const titleId = () => (props.title ? "svg-inline--fa-title-".concat(props.titleId || nextUniqueId()) : undefined);
// Get CSS class list from the props object
function attributes() {
const defaultClasses = {
"svg-inline--fa": true,
[`fa-${props.icon.iconName}`]: true,
[props.class ?? ""]: typeof props.class !== "undefined" && props.class !== null,
...props.classList,
};
// map of CSS class names to properties
const faClasses = {
"fa-beat": props.beat,
"fa-fade": props.fade,
"fa-beat-fade": props.beatFade,
"fa-bounce": props.bounce,
"fa-shake": props.shake,
"fa-flash": props.flash,
"fa-spin": props.spin,
"fa-spin-reverse": props.spinReverse,
"fa-spin-pulse": props.spinPulse,
"fa-pulse": props.pulse,
"fa-fw": props.fixedWidth,
"fa-inverse": props.inverse,
"fa-border": props.border,
"fa-li": props.listItem,
"fa-flip": typeof props.flip !== "undefined" && props.flip !== null,
"fa-flip-horizontal": props.flip === "horizontal" || props.flip === "both",
"fa-flip-vertical": props.flip === "vertical" || props.flip === "both",
[`fa-${props.size}`]: typeof props.size !== "undefined" && props.size !== null,
[`fa-rotate-${props.rotation}`]: typeof props.rotation !== "undefined" && props.size !== null,
[`fa-pull-${props.pull}`]: typeof props.pull !== "undefined" && props.pull !== null,
"fa-swap-opacity": props.swapOpacity,
};
const attributes = { focusable: !!props.title, "aria-hidden": !props.title, role: "img", xmlns: "http://www.w3.org/2000/svg", "aria-labelledby": titleId(), "data-prefix": props.icon.prefix, "data-icon": props.icon.iconName, "data-fa-transform": props.transform, "data-fa-mask": props.mask, "data-fa-mask-id": props.maskId, "data-fa-symbol": props.symbol, tabIndex: props.tabIndex, classList: { ...defaultClasses, ...faClasses }, color: props.color, style: props.style, viewBox: `0 0 ${props.icon.icon[0]} ${props.icon.icon[1]}` } as const;
// return the complete class list
return attributes;
}
return (
<svg {...attributes()}>
<Show when={props.title}>
<title id={titleId()}>{props.title}</title>
</Show>
<Path d={props.icon.icon[4]} />
</svg>
);
}

View file

@ -0,0 +1,42 @@
import { faArrowUpRightFromSquare, faBookOpen, faHashtag } from "@fortawesome/pro-regular-svg-icons";
import { JSXElement, Show, createMemo } from "solid-js";
import { A } from "solid-start";
import { FontAwesomeIcon } from "./FontAwesomeIcon";
const types = {
external: faArrowUpRightFromSquare,
page: faBookOpen,
id: faHashtag,
};
/**
* References to local and external resouces
*/
function R(props: { href: string; children: JSXElement; class?: string; id?: string }) {
const type = createMemo((): keyof typeof types => {
switch (true) {
case props.href.startsWith("http"):
return "external";
case props.href.startsWith("#"):
return "id";
case props.href.startsWith("/"):
return "page";
default:
console.warn("StartsWith is unknown:", props.href);
return "external";
}
});
return (
<A href={props.href} target={type() === "external" ? "_blank" : ""} rel={type() === "external" ? "noreferrer noopener" : ""} id={props.id} class={props.class}>
<Show when={type() === "id"}>
<FontAwesomeIcon class="left" icon={types["id"]} />
</Show>
{props.children}
<Show when={type() !== "id"}>
<FontAwesomeIcon class="right" icon={types[type()]} title={type()} />
</Show>
</A>
);
}
export default R;