diff options
Diffstat (limited to 'docs/src/components/codes')
-rw-r--r-- | docs/src/components/codes/Context.jsx | 17 | ||||
-rw-r--r-- | docs/src/components/codes/Description.jsx | 51 | ||||
-rw-r--r-- | docs/src/components/codes/Footnote.jsx | 23 | ||||
-rw-r--r-- | docs/src/components/codes/FootnoteRef.jsx | 22 | ||||
-rw-r--r-- | docs/src/components/codes/FootnoteRefs.jsx | 43 | ||||
-rw-r--r-- | docs/src/components/codes/Footnotes.jsx | 30 | ||||
-rw-r--r-- | docs/src/components/codes/LinkIcon.jsx | 14 | ||||
-rw-r--r-- | docs/src/components/codes/Name.jsx | 25 | ||||
-rw-r--r-- | docs/src/components/codes/OsLegend.jsx | 23 | ||||
-rw-r--r-- | docs/src/components/codes/OsSupport.jsx | 26 | ||||
-rw-r--r-- | docs/src/components/codes/OsSupportIcon.jsx | 51 | ||||
-rw-r--r-- | docs/src/components/codes/Table.jsx | 80 | ||||
-rw-r--r-- | docs/src/components/codes/TableRow.jsx | 70 | ||||
-rw-r--r-- | docs/src/components/codes/ToastyContainer.jsx | 22 | ||||
-rw-r--r-- | docs/src/components/codes/ToastyCopyToClipboard.jsx | 30 |
15 files changed, 527 insertions, 0 deletions
diff --git a/docs/src/components/codes/Context.jsx b/docs/src/components/codes/Context.jsx new file mode 100644 index 0000000..4fdcbfc --- /dev/null +++ b/docs/src/components/codes/Context.jsx @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: CC-BY-NC-SA-4.0 + */ + +import React from "react"; +import PropTypes from "prop-types"; + +export default function Context({ children }) { + return <p className="context">{children}</p>; +} + +Context.propTypes = { + children: PropTypes.oneOfType([PropTypes.element, PropTypes.string]) + .isRequired, +}; diff --git a/docs/src/components/codes/Description.jsx b/docs/src/components/codes/Description.jsx new file mode 100644 index 0000000..6d8c5f6 --- /dev/null +++ b/docs/src/components/codes/Description.jsx @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: CC-BY-NC-SA-4.0 + */ + +import React from "react"; +import PropTypes from "prop-types"; + +const specialCharactersRegex = /(?:^|\s)((?:&(?:(?:\w+)|(?:#\d+));)|[_]|[^\w\s])(?:\s*\[([^[\]]+?)\])/g; + +function renderSpecialCharacters(description) { + const matches = Array.from(description.matchAll(specialCharactersRegex)); + if (matches.length == 0) return description; + let lastIndex = 0; + const parts = matches.reduce((acc, match, i) => { + const { index } = match; + const str = match[0]; + const chars = match[1]; + const meaning = match[2]; + if (index != lastIndex) { + acc.push(description.substring(lastIndex, index)); + } + const pos = str.indexOf(chars); + if (pos > 0) { + acc.push(description.substr(index, pos)); + } + acc.push( + <span key={i} className="symbol" title={meaning ?? ""}> + <code>{description.substr(index + pos, chars.length)}</code> + {meaning ? <span className="meaning">{meaning}</span> : undefined} + </span> + ); + lastIndex = index + str.length; + return acc; + }, []); + if (lastIndex < description.length) { + parts.push(description.substr(lastIndex)); + } + return parts; +} + +export default function Description({ description = "" }) { + return ( + <span className="description">{renderSpecialCharacters(description)}</span> + ); +} + +Description.propTypes = { + description: PropTypes.string.isRequired, +}; diff --git a/docs/src/components/codes/Footnote.jsx b/docs/src/components/codes/Footnote.jsx new file mode 100644 index 0000000..c9396a3 --- /dev/null +++ b/docs/src/components/codes/Footnote.jsx @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: CC-BY-NC-SA-4.0 + */ + +import React from "react"; +import PropTypes from "prop-types"; + +export default function Footnote({ children, symbol, id }) { + return ( + <div className="footnote" id={id}> + <div className="symbol">{symbol}</div> + <div className="content">{children}</div> + </div> + ); +} + +Footnote.propTypes = { + children: PropTypes.element.isRequired, + symbol: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, + id: PropTypes.string.isRequired, +}; diff --git a/docs/src/components/codes/FootnoteRef.jsx b/docs/src/components/codes/FootnoteRef.jsx new file mode 100644 index 0000000..c7b11a7 --- /dev/null +++ b/docs/src/components/codes/FootnoteRef.jsx @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: CC-BY-NC-SA-4.0 + */ + +import React from "react"; +import PropTypes from "prop-types"; + +export default function FootnoteRef({ children, anchor }) { + return ( + <a href={"#" + anchor} className="footnoteRef"> + {children} + </a> + ); +} + +FootnoteRef.propTypes = { + children: PropTypes.oneOfType([PropTypes.string, PropTypes.number]) + .isRequired, + anchor: PropTypes.string.isRequired, +}; diff --git a/docs/src/components/codes/FootnoteRefs.jsx b/docs/src/components/codes/FootnoteRefs.jsx new file mode 100644 index 0000000..3782c13 --- /dev/null +++ b/docs/src/components/codes/FootnoteRefs.jsx @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: CC-BY-NC-SA-4.0 + */ + +import React from "react"; +import PropTypes from "prop-types"; +import FootnoteRef from "./FootnoteRef"; + +function joinReactElements(arr, delimiter) { + return arr.reduce((acc, fragment) => { + if (acc === null) { + return fragment; + } + return ( + <> + {acc} + {delimiter} + {fragment} + </> + ); + }, null); +} + +export default function FootnoteRefs({ footnotes }) { + return ( + <span className="footnoteRefs"> + {joinReactElements( + footnotes.map((footnote) => ( + <FootnoteRef key={footnote.reference} {...footnote}> + {footnote.symbol} + </FootnoteRef> + )), + ", " + )} + </span> + ); +} + +FootnoteRefs.propTypes = { + footnotes: PropTypes.array.isRequired, +}; diff --git a/docs/src/components/codes/Footnotes.jsx b/docs/src/components/codes/Footnotes.jsx new file mode 100644 index 0000000..b382141 --- /dev/null +++ b/docs/src/components/codes/Footnotes.jsx @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: CC-BY-NC-SA-4.0 + */ + +import React from "react"; +import PropTypes from "prop-types"; +import Footnote from "./Footnote"; + +export default function Footnotes({ footnotes = [], id }) { + return ( + <div className="footnotes"> + <a id={id} className="anchor" /> + <div className="label">Notes</div> + <div className="notes"> + {footnotes.map((footnote) => ( + <Footnote key={footnote.id} {...footnote}> + {footnote.value} + </Footnote> + ))} + </div> + </div> + ); +} + +Footnotes.propTypes = { + footnotes: PropTypes.array.isRequired, + id: PropTypes.string.isRequired, +}; diff --git a/docs/src/components/codes/LinkIcon.jsx b/docs/src/components/codes/LinkIcon.jsx new file mode 100644 index 0000000..5bfeebd --- /dev/null +++ b/docs/src/components/codes/LinkIcon.jsx @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: CC-BY-NC-SA-4.0 + */ + +import React from "react"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faExternalLinkAlt } from "@fortawesome/free-solid-svg-icons"; +export default function LinkIcon() { + return <FontAwesomeIcon className="icon" icon={faExternalLinkAlt} />; +} + +LinkIcon.propTypes = {}; diff --git a/docs/src/components/codes/Name.jsx b/docs/src/components/codes/Name.jsx new file mode 100644 index 0000000..52dc734 --- /dev/null +++ b/docs/src/components/codes/Name.jsx @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: CC-BY-NC-SA-4.0 + */ + +import React from "react"; +import PropTypes from "prop-types"; +import ToastyCopyToClipboard from "./ToastyCopyToClipboard"; + +export default function Name({ children, name }) { + return ( + <ToastyCopyToClipboard text={name}> + <code className="name" title="Copy 📋"> + {children} + </code> + </ToastyCopyToClipboard> + ); +} + +Name.propTypes = { + children: PropTypes.oneOfType([PropTypes.element, PropTypes.string]) + .isRequired, + name: PropTypes.string.isRequired, +}; diff --git a/docs/src/components/codes/OsLegend.jsx b/docs/src/components/codes/OsLegend.jsx new file mode 100644 index 0000000..c53907f --- /dev/null +++ b/docs/src/components/codes/OsLegend.jsx @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: CC-BY-NC-SA-4.0 + */ + +import React from "react"; +import operatingSystems from "@site/src/data/operating-systems"; + +export default function OsLegend() { + return ( + <div className="codes os legend"> + {operatingSystems.map(({ key, className, heading, title }) => ( + <div key={key} className={"os " + className}> + <span className="heading">{heading}</span> + <span className="title">{title}</span> + </div> + ))} + </div> + ); +} + +OsLegend.propTypes = {}; diff --git a/docs/src/components/codes/OsSupport.jsx b/docs/src/components/codes/OsSupport.jsx new file mode 100644 index 0000000..2cb60c9 --- /dev/null +++ b/docs/src/components/codes/OsSupport.jsx @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: CC-BY-NC-SA-4.0 + */ + +import React from "react"; +import PropTypes from "prop-types"; +import OsSupportIcon from "./OsSupportIcon"; +import FootnoteRefs from "./FootnoteRefs"; + +export default function OsSupport({ value, footnotes = [] }) { + return ( + <> + <OsSupportIcon value={value} /> + {footnotes.length > 0 ? ( + <FootnoteRefs footnotes={footnotes} /> + ) : undefined} + </> + ); +} + +OsSupport.propTypes = { + value: PropTypes.oneOf([true, false, null]), + footnotes: PropTypes.array.isRequired, +}; diff --git a/docs/src/components/codes/OsSupportIcon.jsx b/docs/src/components/codes/OsSupportIcon.jsx new file mode 100644 index 0000000..a518d62 --- /dev/null +++ b/docs/src/components/codes/OsSupportIcon.jsx @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: CC-BY-NC-SA-4.0 + */ + +import React from "react"; +import PropTypes from "prop-types"; + +const Icon = ({ children, className, title }) => ( + <span className={className} title={title}> + {children} + </span> +); + +Icon.propTypes = { + children: PropTypes.oneOfType([PropTypes.element, PropTypes.string]) + .isRequired, + className: PropTypes.string.isRequired, + title: PropTypes.string.isRequired, +}; + +export const Supported = () => ( + <Icon className="supported" title="Supported 😄"> + ⭐ + </Icon> +); +export const NotSupported = () => ( + <Icon className="not-supported" title="Not Supported 😢"> + ❌ + </Icon> +); +export const NotTested = () => ( + <Icon className="not-tested" title="Not Tested Yet - PR's welcomed! 🧐"> + ❔ + </Icon> +); + +export default function OsSupportIcon({ value }) { + if (value === true) { + return <Supported />; + } + if (value === false) { + return <NotSupported />; + } + return <NotTested />; +} + +OsSupportIcon.propTypes = { + value: PropTypes.oneOf([true, false, null]), +}; diff --git a/docs/src/components/codes/Table.jsx b/docs/src/components/codes/Table.jsx new file mode 100644 index 0000000..c7dd20c --- /dev/null +++ b/docs/src/components/codes/Table.jsx @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: CC-BY-NC-SA-4.0 + */ + +import React from "react"; +import PropTypes from "prop-types"; +import TableRow from "./TableRow"; +import Footnotes from "./Footnotes"; +import LinkIcon from "./LinkIcon"; +import operatingSystems from "@site/src/data/operating-systems"; +import { getCodes } from "@site/src/hid"; +import { getGroup } from "@site/src/groups"; +import { getFootnote } from "@site/src/footnotes"; + +function extractFootnoteIds(codes) { + return Array.from( + new Set( + codes + .flatMap(({ footnotes }) => Object.values(footnotes)) + .map((refs) => (Array.isArray(refs) ? refs.flat() : refs)) + ) + ); +} + +export default function Table({ group }) { + const codes = getCodes(getGroup(group)); + + const footnotesAnchor = group + "-" + "footnotes"; + + const tableFootnotes = extractFootnoteIds(codes).map((id, i) => { + const Component = getFootnote(id); + return { + id, + anchor: footnotesAnchor, + symbol: i + 1, + value: Component ? <Component /> : undefined, + }; + }); + + return ( + <div className="codes"> + <table> + <thead> + <tr> + <th className="names">Names</th> + <th className="description">Description</th> + <th className="documentation" title="Documentation"> + <LinkIcon /> + </th> + {operatingSystems.map(({ key, className, heading, title }) => ( + <th key={key} className={`os ${className}`} title={title}> + {heading} + </th> + ))} + </tr> + </thead> + <tbody> + {Array.isArray(codes) + ? codes.map((code) => ( + <TableRow + key={code.names[0]} + {...code} + tableFootnotes={tableFootnotes} + /> + )) + : undefined} + </tbody> + </table> + {tableFootnotes.length > 0 ? ( + <Footnotes id={footnotesAnchor} footnotes={tableFootnotes} /> + ) : undefined} + </div> + ); +} + +Table.propTypes = { + group: PropTypes.string.isRequired, +}; diff --git a/docs/src/components/codes/TableRow.jsx b/docs/src/components/codes/TableRow.jsx new file mode 100644 index 0000000..a560911 --- /dev/null +++ b/docs/src/components/codes/TableRow.jsx @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: CC-BY-NC-SA-4.0 + */ + +import React from "react"; +import PropTypes from "prop-types"; +import Name from "./Name"; +import Description from "./Description"; +import Context from "./Context"; +import LinkIcon from "./LinkIcon"; +import OsSupport from "./OsSupport"; +import operatingSystems from "@site/src/data/operating-systems"; + +export default function TableRow({ + names, + description, + context = "", + clarify = false, + documentation, + os, + footnotes, + tableFootnotes, +}) { + return ( + <tr> + <td className="names"> + {names.map((name) => ( + <Name key={name} name={name}> + {name} + </Name> + ))} + </td> + <td className="description"> + <Description description={description} /> + {clarify && context ? <Context>{context}</Context> : undefined} + </td> + <td className="documentation" title="Documentation"> + <a href={documentation} target="_blank" rel="noreferrer"> + <LinkIcon /> + </a> + </td> + {operatingSystems.map(({ key, className, title }) => ( + <td key={key} className={`os ${className}`} title={title}> + <OsSupport + value={os[key]} + footnotes={tableFootnotes.filter( + ({ id }) => + (Array.isArray(footnotes[key]) && + footnotes[key].includes(id)) || + footnotes[key] == id + )} + /> + </td> + ))} + </tr> + ); +} + +TableRow.propTypes = { + names: PropTypes.array.isRequired, + description: PropTypes.string.isRequired, + context: PropTypes.string.isRequired, + clarify: PropTypes.bool, + documentation: PropTypes.string.isRequired, + os: PropTypes.object.isRequired, + footnotes: PropTypes.object.isRequired, + tableFootnotes: PropTypes.array.isRequired, +}; diff --git a/docs/src/components/codes/ToastyContainer.jsx b/docs/src/components/codes/ToastyContainer.jsx new file mode 100644 index 0000000..ee4e3bc --- /dev/null +++ b/docs/src/components/codes/ToastyContainer.jsx @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: CC-BY-NC-SA-4.0 + */ + +import React from "react"; +import { ToastContainer } from "react-toastify"; +import "react-toastify/dist/ReactToastify.css"; + +export default function ToastyContainer() { + return ( + <ToastContainer + position="bottom-right" + autoClose={2000} + hideProgressBar={true} + newestOnTop={true} + /> + ); +} + +ToastyContainer.propTypes = {}; diff --git a/docs/src/components/codes/ToastyCopyToClipboard.jsx b/docs/src/components/codes/ToastyCopyToClipboard.jsx new file mode 100644 index 0000000..b0e9809 --- /dev/null +++ b/docs/src/components/codes/ToastyCopyToClipboard.jsx @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020 The ZMK Contributors + * + * SPDX-License-Identifier: CC-BY-NC-SA-4.0 + */ + +import React from "react"; +import PropTypes from "prop-types"; +import { toast } from "react-toastify"; +import { CopyToClipboard } from "react-copy-to-clipboard"; + +export default function ToastyCopyToClipboard({ children, text }) { + const notify = () => + toast( + <span> + 📋 Copied <code>{text}</code> + </span> + ); + return ( + <div onClick={notify}> + <CopyToClipboard text={text}>{children}</CopyToClipboard> + </div> + ); +} + +ToastyCopyToClipboard.propTypes = { + children: PropTypes.oneOfType([PropTypes.element, PropTypes.string]) + .isRequired, + text: PropTypes.string.isRequired, +}; |