Merge branch 'master' into storeForward

This commit is contained in:
rcarteraz 2024-02-24 08:46:57 -07:00 committed by GitHub
commit f4faa95a14
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 73 additions and 73 deletions

View file

@ -190,38 +190,38 @@ If you use your ham radio license with Meshtastic, consider both the privileges
## Overview ## Overview
<FaqAccordion rows={Faq.general} slug="general" /> <FaqAccordion rows={Faq.general} />
## Android Client ## Android Client
<FaqAccordion rows={Faq.android} slug="android" /> <FaqAccordion rows={Faq.android} />
## Apple Clients ## Apple Clients
<FaqAccordion rows={Faq.apple} slug="apple" /> <FaqAccordion rows={Faq.apple} />
## Channels ## Channels
<FaqAccordion rows={Faq.channels} slug="channels" /> <FaqAccordion rows={Faq.channels} />
## Python CLI ## Python CLI
<FaqAccordion rows={Faq.python} slug="python" /> <FaqAccordion rows={Faq.python} />
## Devices ## Devices
<FaqAccordion rows={Faq.devices} slug="devices" /> <FaqAccordion rows={Faq.devices} />
## Amateur Radio (ham) ## Amateur Radio (ham)
Meshtastic can be used by both unlicensed people and licensed HAM operators. Meshtastic can be used by both unlicensed people and licensed HAM operators.
<FaqAccordion rows={Faq.ham} slug="ham" /> <FaqAccordion rows={Faq.ham} />
## Mesh ## Mesh
<FaqAccordion rows={Faq.mesh} slug="mesh" /> <FaqAccordion rows={Faq.mesh} />
## Modules ## Modules
<FaqAccordion rows={Faq.modules} slug="modules" /> <FaqAccordion rows={Faq.modules} />

View file

@ -1,4 +1,3 @@
import BrowserOnly from "@docusaurus/BrowserOnly";
import { import {
Accordion, Accordion,
AccordionItem, AccordionItem,
@ -16,83 +15,84 @@ export interface Faq {
} }
/** /**
* Gets the query parameter `openFaqItems` which is an array of * Finds the nearest heading to an element
* faq items that should be pre-opened * @param {Element} null The element to find the nearest heading to
* @type {Function} * @return {Element|null} The heading or null
*/ */
const getOpenFaqItemsFromUrl = (slug: string): string[] => { const findNearestHeading = (element: Element): Element | null => {
if (typeof window !== "undefined") { const isHeading = (element: Element): boolean =>
// Use URLSearchParams to parse the query parameters from the current URL /^H[1-6]$/.test(element.tagName);
const searchParams = new URLSearchParams(window.location.search); let currentElement: Element | null = element;
// Get the 'openFaqItems' parameter as a comma-separated string while (currentElement !== null) {
const openFaqItemsString = searchParams.get(`openFaqItems-${slug}`); // Check previous siblings
let prevSibling: Element | null = currentElement.previousElementSibling;
while (prevSibling) {
if (isHeading(prevSibling)) {
return prevSibling;
}
prevSibling = prevSibling.previousElementSibling;
}
// If the parameter exists, split it by commas into an array; otherwise, return an empty array // If no heading is found among siblings, move to the parent node
return openFaqItemsString ? openFaqItemsString.split(",") : []; currentElement = currentElement.parentElement;
} }
return null;
}; };
/** /**
* Updates query parameters in the url when items are opened * Takes in uuids from react-accessible-accordion onchange event
* so that a link can be shared with the faq item already opened * and updates the browser url with the nearest heading's id
* @param {[type]} void [description]
* @return {[type]} [description]
*/ */
const handleChange = ( const updateUrlWithNearestHeadingId = (targetElementUuid: string): void => {
openFaqItems: (string | number)[], const targetElement: HTMLElement | null = document.getElementById(
slug: string, `accordion__heading-${targetElementUuid[0]}`,
): void => { );
const searchParams = new URLSearchParams(window.location.search);
if (openFaqItems.length > 0) { const nearestHeading: Element | null = targetElement
// Create comma-separated string and update/add the parameter ? findNearestHeading(targetElement)
searchParams.set( : null;
`openFaqItems-${slug}`,
openFaqItems.map(String).join(","), // Add the hash without scrolling the page
); if (nearestHeading?.id) {
} else { window.history.pushState({}, "", `#${nearestHeading.id}`);
// If openFaqItems is empty, remove the parameter from the URL
searchParams.delete(`openFaqItems-${slug}`);
} }
// Construct the new URL, preserve existing parameters // If they're all collapsed, remove the hash
const newUrl = `${window.location.protocol}//${window.location.host}${ if (!targetElement) {
window.location.pathname history.pushState(
}?${searchParams.toString()}`; null,
null,
// Change the URL without reloading the page window.location.origin +
window.history.pushState({ path: newUrl }, "", newUrl); window.location.pathname +
window.location.search,
);
}
}; };
export const FaqAccordion = ({ export const FaqAccordion = ({ rows }: { rows: Faq[] }): JSX.Element => {
rows,
slug,
}: { rows: Faq[]; slug: string }): JSX.Element => {
return ( return (
<BrowserOnly fallback={<div>Loading FAQ's...</div>}> <Accordion
{() => { allowMultipleExpanded={true}
return ( allowZeroExpanded={true}
<Accordion onChange={(itemUuids) => {
allowMultipleExpanded={true} updateUrlWithNearestHeadingId(itemUuids);
allowZeroExpanded={true}
onChange={(itemUuids) => {
handleChange(itemUuids, slug);
}}
preExpanded={getOpenFaqItemsFromUrl(slug)}
>
{rows.map((row, index) => (
// biome-ignore lint/suspicious/noArrayIndexKey: React complains if there is no key
<AccordionItem key={index}>
<AccordionItemHeading aria-level="3">
<AccordionItemButton>{row.title}</AccordionItemButton>
</AccordionItemHeading>
<AccordionItemPanel>
<ReactMarkdown>{row.content}</ReactMarkdown>
</AccordionItemPanel>
</AccordionItem>
))}
</Accordion>
);
}} }}
</BrowserOnly> >
{rows.map((row, index) => (
// biome-ignore lint/suspicious/noArrayIndexKey: React complains if there is no key
<AccordionItem key={index}>
<AccordionItemHeading aria-level="3">
<AccordionItemButton>{row.title}</AccordionItemButton>
</AccordionItemHeading>
<AccordionItemPanel>
<ReactMarkdown>{row.content}</ReactMarkdown>
</AccordionItemPanel>
</AccordionItem>
))}
</Accordion>
); );
}; };