You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
rappli/src/components/QrCode.tsx

71 lines
1.6 KiB
TypeScript

import {
Component,
createEffect,
createResource,
createSignal,
JSX,
Show,
splitProps,
} from "solid-js";
import qrcode from "qrcode";
import WarningIcon from "~icons/carbon/warning-alt-filled";
const QrCode: Component<
{
margin?: number;
value: string;
errorCorrectionLevel?: string;
} & JSX.HTMLAttributes<HTMLDivElement>
> = (p) => {
const [props, rest] = splitProps(p, [
"margin",
"value",
"errorCorrectionLevel",
]);
let ref: HTMLDivElement = undefined!;
const [qrError, setQrError] = createSignal<string | undefined>();
const [svg] = createResource(
() => props.value,
async (value) => {
let svg;
try {
svg = await qrcode.toString(value, {
type: "svg",
margin: props.margin,
errorCorrectionLevel: props.errorCorrectionLevel as any,
});
setQrError();
} catch (err) {
console.error(err);
setQrError((err as Error).message);
}
return svg;
}
);
createEffect(() => {
const html = svg() || "";
requestAnimationFrame(function () {
ref.innerHTML = html;
});
});
return (
<>
<Show when={qrError()}>
<div class="absolute h-full p-3 gap-2 rounded-sm flex items-start bg-error/80 backdrop-blur-sm ring-2 ring-error ring-offset-2 border border-error text-error-content overflow-y-auto">
<WarningIcon width="2em" height="2em" class="flex-shrink-0" /> Fehler:{" "}
{qrError()}
</div>
</Show>
<div ref={ref} {...rest}></div>
</>
);
};
export default QrCode;