"use client"; import { Button, Checkbox, TextField, TextFieldProps, Typography, } from "@mui/material"; import { usePathname, useRouter, useSearchParams } from "next/navigation"; import { ReactElement, ReactNode, useCallback, useEffect, useMemo, useRef, } from "react"; import { Prism as SyntaxHighlighter } from "react-syntax-highlighter"; import useAttrFromUrlParams from "../hooks/useAttrFromUrlParams"; import usePublicKey from "../hooks/usePublicKey"; export interface AttrConfig { defaultValue?: string; description: ReactNode; props?: TextFieldProps; type?: "boolean"; } function WebComponentDoc({ attrsConfig, Comp, compProps, events, isFullScreen, tagName, }: { attrsConfig: Record; Comp: (props: Record) => ReactElement; compProps: Record; events?: string[]; isFullScreen?: boolean; tagName: string; }) { const wcAttributes = Object.keys(attrsConfig); const ref = useRef(null); const router = useRouter(); const pathname = usePathname(); const apiKey = usePublicKey(); const attributes = useAttrFromUrlParams(wcAttributes); const searchParams = useSearchParams(); // Get a new searchParams string by merging the current // searchParams with a provided key/value pair const createQueryString = useCallback( (name: string, value?: string) => { const params = new URLSearchParams(searchParams.toString()); if (value === undefined || value === "") { params.delete(name); } else { params.set(name, value); } return params.toString(); }, [searchParams], ); const code = useMemo(() => { let str = ` <${tagName}`; str = Object.keys({ apikey: "", ...attributes }).reduce((acc, key) => { if (key === "apikey" && !attributes[key]) { return `${acc}\n\tapikey="YOUR_GEOPS_API_KEY"`; } return `${acc}\n\t${key}="${attributes[key]}"`; }, str); str += `>\n`; return str; }, [attributes, tagName]); const onChange = useCallback( (key: string, value: string) => { const val = value === attrsConfig[key]?.defaultValue ? undefined : value; router.replace(pathname + "?" + createQueryString(key, val), { scroll: false, }); }, [attrsConfig, createQueryString, pathname, router], ); useEffect(() => { const cb = (event: CustomEvent<{ data: object; type: string }>) => { const eventLog = document.getElementById("textarea"); // @ts-expect-error - strange error const data = event.data; if (!eventLog) { return; } if (!data) { eventLog.innerText = ""; } else { eventLog.innerText = "Event " + event.type + " received :\n " + JSON.stringify(data, undefined, " "); // window.top.postMessage(data, "*"); } }; if (ref.current) { // Listen to element event events?.forEach((event) => { // @ts-expect-error - strange error ref.current?.addEventListener(event, cb); }); } return () => { events?.forEach((event) => { // @ts-expect-error - strange error ref.current?.removeEventListener(event, cb); }); }; }, [events]); const webComponent = useMemo(() => { return ( { ref.current = node; }} {...compProps} /> ); }, [Comp, apiKey, attributes, compProps]); if (isFullScreen) { return webComponent; } return (
{`<${tagName} />`}
This is a demo of the <{tagName} /> Web Component.
{webComponent}
{events?.length && ( <> Event received

          
)} HTML code
{code}
Attributes
{wcAttributes .sort((a, b) => { return a < b ? -1 : 1; }) .filter((key) => { return attrsConfig[key]?.description; }) .map((key) => { const { defaultValue, description, props = {}, type, } = attrsConfig[key] || {}; return ( ); })}
Name Description
{key}
{!type && (
)} {type === "boolean" && ( { onChange( key, evt.target.checked ? "true" : "false", ); }} /> )}
{typeof description !== "string" ? ( description ) : ( )}{" "} {defaultValue && ( <> Default to "{defaultValue}" )}
); } export default WebComponentDoc;