UNPKG

@flanksource/clicky-ui

Version:

Flanksource Clicky UI — React component library built on shadcn/ui with light/dark and density theming.

127 lines (126 loc) 4.55 kB
import { jsxs, jsx, Fragment } from "react/jsx-runtime"; import { useRef, useState, useEffect } from "react"; import { Button } from "../components/button.js"; import { Icon } from "../data/Icon.js"; import { cn } from "../lib/utils.js"; const ACCEPT_OPTIONS = [ { value: "application/json", label: "JSON" }, { value: "application/clicky+json", label: "Clicky" }, { value: "text/markdown", label: "Markdown" }, { value: "text/html", label: "HTML" }, { value: "application/x-yaml", label: "YAML" }, { value: "text/csv", label: "CSV" }, { value: "application/pdf", label: "PDF" }, { value: "text/plain", label: "Pretty" } ]; const VIEW_OPTIONS = [ { value: "application/json", label: "JSON" }, { value: "application/clicky+json", label: "Clicky" }, { value: "application/pdf", label: "PDF" } ]; const PREVIEW_OPTIONS = [ { value: "curl", label: "Show cURL preview" }, { value: "cli", label: "Show CLI preview" }, { value: "hidden", label: "Hide preview" } ]; function AcceptPicker({ value, onChange, size = "md", options = ACCEPT_OPTIONS, previewMode = "hidden", onPreviewModeChange, className }) { const rootRef = useRef(null); const [open, setOpen] = useState(false); const pad = size === "sm" ? "px-2 py-0.5" : "px-2.5 py-1"; useEffect(() => { if (!open) return; const onPointerDown = (event) => { var _a; if (!((_a = rootRef.current) == null ? void 0 : _a.contains(event.target))) { setOpen(false); } }; const onKeyDown = (event) => { if (event.key === "Escape") setOpen(false); }; document.addEventListener("pointerdown", onPointerDown); document.addEventListener("keydown", onKeyDown); return () => { document.removeEventListener("pointerdown", onPointerDown); document.removeEventListener("keydown", onKeyDown); }; }, [open]); return /* @__PURE__ */ jsxs("div", { ref: rootRef, className: cn("relative flex flex-wrap gap-1", className), children: [ options.map((opt) => /* @__PURE__ */ jsx( "button", { type: "button", onClick: () => onChange(opt.value), className: cn( "rounded-md border text-xs transition-colors", pad, value === opt.value ? "border-emerald-500 bg-emerald-50 font-medium text-emerald-700 dark:border-emerald-600 dark:bg-emerald-950/30 dark:text-emerald-400" : "text-muted-foreground hover:border-foreground/20 hover:text-foreground" ), children: opt.label }, opt.value )), onPreviewModeChange && /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx( Button, { type: "button", variant: "outline", size: "sm", "aria-label": "Open preview menu", "aria-haspopup": "menu", "aria-expanded": open, className: cn("h-auto", pad), onClick: () => setOpen((current) => !current), children: /* @__PURE__ */ jsx(Icon, { name: "codicon:ellipsis" }) } ), open && /* @__PURE__ */ jsx( "div", { role: "menu", "aria-label": "Preview options", className: "absolute right-0 top-[calc(100%+0.375rem)] z-50 min-w-[12rem] rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-lg shadow-black/5", children: PREVIEW_OPTIONS.map((option) => { const active = option.value === previewMode; return /* @__PURE__ */ jsxs( "button", { type: "button", role: "menuitemradio", "aria-checked": active, className: cn( "flex w-full items-center gap-2 rounded-sm px-2 py-1.5 text-left text-sm transition-colors", "hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none" ), onClick: () => { onPreviewModeChange(option.value); setOpen(false); }, children: [ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1", children: option.label }), active ? /* @__PURE__ */ jsx(Icon, { name: "ph:check", className: "shrink-0" }) : null ] }, option.value ); }) } ) ] }) ] }); } export { ACCEPT_OPTIONS, AcceptPicker, VIEW_OPTIONS }; //# sourceMappingURL=AcceptPicker.js.map