UNPKG

@helpwave/hightide

Version:

helpwave's component and theming library

361 lines (356 loc) 11.4 kB
// src/components/layout-and-navigation/FAQSection.tsx import clsx2 from "clsx"; // src/components/layout-and-navigation/Expandable.tsx import { forwardRef, useCallback, useEffect, useState } from "react"; import { ChevronDown } from "lucide-react"; import clsx from "clsx"; // src/util/noop.ts var noop = () => void 0; // src/components/layout-and-navigation/Expandable.tsx import { jsx, jsxs } from "react/jsx-runtime"; var ExpansionIcon = ({ isExpanded, className }) => { return /* @__PURE__ */ jsx( ChevronDown, { className: clsx( "min-w-6 w-6 min-h-6 h-6 transition-transform duration-200 ease-in-out", { "rotate-180": isExpanded }, className ) } ); }; var Expandable = forwardRef(function Expandable2({ children, label, icon, isExpanded = false, onChange = noop, clickOnlyOnHeader = true, disabled = false, className, headerClassName, contentClassName, contentExpandedClassName }, ref) { const defaultIcon = useCallback((expanded) => /* @__PURE__ */ jsx(ExpansionIcon, { isExpanded: expanded }), []); icon ??= defaultIcon; return /* @__PURE__ */ jsxs( "div", { ref, className: clsx("flex-col-0 bg-surface text-on-surface group rounded-lg shadow-sm", { "cursor-pointer": !clickOnlyOnHeader && !disabled }, className), onClick: () => !clickOnlyOnHeader && !disabled && onChange(!isExpanded), children: [ /* @__PURE__ */ jsxs( "div", { className: clsx( "flex-row-2 py-2 px-4 rounded-lg justify-between items-center bg-surface text-on-surface select-none", { "group-hover:brightness-97": !isExpanded, "hover:brightness-97": isExpanded && !disabled, "cursor-pointer": clickOnlyOnHeader && !disabled }, headerClassName ), onClick: () => clickOnlyOnHeader && !disabled && onChange(!isExpanded), children: [ label, icon(isExpanded) ] } ), /* @__PURE__ */ jsx( "div", { className: clsx( "flex-col-2 px-4 transition-all duration-300 ease-in-out", { [clsx("max-h-96 opacity-100 pb-2 overflow-y-auto", contentExpandedClassName)]: isExpanded, "max-h-0 opacity-0 overflow-hidden": !isExpanded }, contentClassName ), children } ) ] } ); }); var ExpandableUncontrolled = forwardRef(function ExpandableUncontrolled2({ isExpanded, onChange = noop, ...props }, ref) { const [usedIsExpanded, setUsedIsExpanded] = useState(isExpanded); useEffect(() => { setUsedIsExpanded(isExpanded); }, [isExpanded]); return /* @__PURE__ */ jsx( Expandable, { ...props, ref, isExpanded: usedIsExpanded, onChange: (value) => { onChange(value); setUsedIsExpanded(value); } } ); }); // src/components/layout-and-navigation/MarkdownInterpreter.tsx import { Fragment, jsx as jsx2 } from "react/jsx-runtime"; var astNodeInserterType = ["helpwave", "newline"]; var ASTNodeInterpreter = ({ node, isRoot = false, className = "" }) => { switch (node.type) { case "newline": return /* @__PURE__ */ jsx2("br", {}); case "text": return isRoot ? /* @__PURE__ */ jsx2("span", { className, children: node.text }) : node.text; case "helpwave": return /* @__PURE__ */ jsx2("span", { className: "font-bold font-space no-underline", children: "helpwave" }); case "none": return isRoot ? /* @__PURE__ */ jsx2("span", { className, children: node.children.map((value, index) => /* @__PURE__ */ jsx2( ASTNodeInterpreter, { node: value }, index )) }) : /* @__PURE__ */ jsx2(Fragment, { children: node.children.map((value, index) => /* @__PURE__ */ jsx2(ASTNodeInterpreter, { node: value }, index)) }); case "bold": return /* @__PURE__ */ jsx2("b", { children: node.children.map((value, index) => /* @__PURE__ */ jsx2(ASTNodeInterpreter, { node: value }, index)) }); case "italic": return /* @__PURE__ */ jsx2("i", { children: node.children.map((value, index) => /* @__PURE__ */ jsx2(ASTNodeInterpreter, { node: value }, index)) }); case "underline": return /* @__PURE__ */ jsx2("u", { children: node.children.map((value, index) => /* @__PURE__ */ jsx2(ASTNodeInterpreter, { node: value }, index)) }); case "font-space": return /* @__PURE__ */ jsx2("span", { className: "font-space", children: node.children.map((value, index) => /* @__PURE__ */ jsx2( ASTNodeInterpreter, { node: value }, index )) }); case "primary": return /* @__PURE__ */ jsx2("span", { className: "text-primary", children: node.children.map((value, index) => /* @__PURE__ */ jsx2( ASTNodeInterpreter, { node: value }, index )) }); case "secondary": return /* @__PURE__ */ jsx2("span", { className: "text-secondary", children: node.children.map((value, index) => /* @__PURE__ */ jsx2( ASTNodeInterpreter, { node: value }, index )) }); case "warn": return /* @__PURE__ */ jsx2("span", { className: "text-warning", children: node.children.map((value, index) => /* @__PURE__ */ jsx2( ASTNodeInterpreter, { node: value }, index )) }); case "positive": return /* @__PURE__ */ jsx2("span", { className: "text-positive", children: node.children.map((value, index) => /* @__PURE__ */ jsx2( ASTNodeInterpreter, { node: value }, index )) }); case "negative": return /* @__PURE__ */ jsx2("span", { className: "text-negative", children: node.children.map((value, index) => /* @__PURE__ */ jsx2( ASTNodeInterpreter, { node: value }, index )) }); default: return null; } }; var modifierIdentifierMapping = [ { id: "i", name: "italic" }, { id: "b", name: "bold" }, { id: "u", name: "underline" }, { id: "space", name: "font-space" }, { id: "primary", name: "primary" }, { id: "secondary", name: "secondary" }, { id: "warn", name: "warn" }, { id: "positive", name: "positive" }, { id: "negative", name: "negative" } ]; var inserterIdentifierMapping = [ { id: "helpwave", name: "helpwave" }, { id: "newline", name: "newline" } ]; var parseMarkdown = (text, commandStart = "\\", open = "{", close = "}") => { let start = text.indexOf(commandStart); const children = []; while (text !== "") { if (start === -1) { children.push({ type: "text", text }); break; } children.push(parseMarkdown(text.substring(0, start))); text = text.substring(start); if (text.length <= 1) { children.push({ type: "text", text }); text = ""; continue; } const simpleReplace = [commandStart, open, close]; if (simpleReplace.some((value) => text[1] === value)) { children.push({ type: "text", text: simpleReplace.find((value) => text[1] === value) }); text = text.substring(2); start = text.indexOf(commandStart); continue; } const inserter = inserterIdentifierMapping.find((value) => text.substring(1).startsWith(value.id)); if (inserter) { children.push({ type: inserter.name }); text = text.substring(inserter.id.length + 1); start = text.indexOf(commandStart); continue; } const modifier = modifierIdentifierMapping.find((value) => text.substring(1).startsWith(value.id)); if (modifier) { if (text[modifier.id.length + 1] !== open) { children.push({ type: "text", text: text.substring(0, modifier.id.length + 1) }); text = text.substring(modifier.id.length + 2); start = text.indexOf(commandStart); continue; } let closing = -1; let index = modifier.id.length + 2; let counter = 1; let escaping = false; while (index < text.length) { if (text[index] === open && !escaping) { counter++; } if (text[index] === close && !escaping) { counter--; if (counter === 0) { closing = index; break; } } escaping = text[index] === commandStart; index++; } if (closing !== -1) { children.push({ type: modifier.name, children: [parseMarkdown(text.substring(modifier.id.length + 2, closing))] }); text = text.substring(closing + 1); start = text.indexOf(commandStart); continue; } } children.push({ type: "text", text: text[0] }); text = text.substring(1); start = text.indexOf(commandStart); } return { type: "none", children }; }; var optimizeTree = (node) => { if (node.type === "text") { return !node.text ? void 0 : node; } if (astNodeInserterType.some((value) => value === node.type)) { return node; } const currentNode = node; if (currentNode.children.length === 0) { return void 0; } let children = []; for (let i = 0; i < currentNode.children.length; i++) { const child = optimizeTree(currentNode.children[i]); if (!child) { continue; } if (child.type === "none") { children.push(...child.children); } else { children.push(child); } } currentNode.children = children; children = []; for (let i = 0; i < currentNode.children.length; i++) { const child = currentNode.children[i]; if (child) { if (child.type === "text" && children[children.length - 1]?.type === "text") { children[children.length - 1].text += child.text; } else { children.push(child); } } } currentNode.children = children; return currentNode; }; var MarkdownInterpreter = ({ text, className }) => { const tree = parseMarkdown(text); const optimizedTree = optimizeTree(tree); return /* @__PURE__ */ jsx2(ASTNodeInterpreter, { node: optimizedTree, isRoot: true, className }); }; // src/components/layout-and-navigation/FAQSection.tsx import { jsx as jsx3 } from "react/jsx-runtime"; var FAQSection = ({ entries, expandableClassName }) => { return /* @__PURE__ */ jsx3("div", { className: "flex-col-4", children: entries.map(({ id, title, content, ...restProps }) => /* @__PURE__ */ jsx3( ExpandableUncontrolled, { ...restProps, label: /* @__PURE__ */ jsx3("h3", { id, className: "textstyle-title-md", children: title }), clickOnlyOnHeader: false, icon: (expanded) => /* @__PURE__ */ jsx3(ExpansionIcon, { isExpanded: expanded, className: "text-primary" }), className: clsx2("rounded-xl", expandableClassName), children: /* @__PURE__ */ jsx3("div", { className: "mt-2", children: content.type === "markdown" ? /* @__PURE__ */ jsx3(MarkdownInterpreter, { text: content.value }) : content.value }) }, id )) }); }; export { FAQSection }; //# sourceMappingURL=FAQSection.mjs.map