UNPKG

@spark-ui/components

Version:

Spark (Leboncoin design system) components.

391 lines (376 loc) 11.5 kB
import { Button } from "../chunk-USSL4UZ5.mjs"; import "../chunk-MUNDKRAE.mjs"; import { Icon } from "../chunk-AESXFMCC.mjs"; import "../chunk-NBZKMCHF.mjs"; import "../chunk-4F5DOL57.mjs"; // src/tabs/Tabs.tsx import { Tabs as RadixTabs } from "radix-ui"; // src/tabs/TabsContext.tsx import { createContext, useContext } from "react"; var TabsContext = createContext({}); var useTabsContext = () => { const context = useContext(TabsContext); if (!context) { throw Error("useTabsContext must be used within a TabsContext Provider"); } return context; }; // src/tabs/TabsRoot.styles.ts import { cva } from "class-variance-authority"; var rootStyles = cva([ "flex", "data-[orientation=horizontal]:flex-col", "data-[orientation=vertical]:flex-row", "max-w-full" ]); // src/tabs/Tabs.tsx import { jsx } from "react/jsx-runtime"; var Tabs = ({ intent = "basic", size = "md", /** * Default Radix Primitive values * see https://www.radix-ui.com/docs/primitives/components/tabs#root */ asChild = false, forceMount = false, orientation = "horizontal", children, className, ref, ...rest }) => { return /* @__PURE__ */ jsx( TabsContext.Provider, { value: { intent, size, orientation, forceMount }, children: /* @__PURE__ */ jsx( RadixTabs.Root, { ref, asChild, orientation, className: rootStyles({ className }), "data-spark-component": "tabs", activationMode: "automatic", ...rest, children } ) } ); }; Tabs.displayName = "Tabs"; // src/tabs/TabsContent.tsx import { Tabs as RadixTabs2 } from "radix-ui"; // src/tabs/TabsContent.styles.ts import { cva as cva2 } from "class-variance-authority"; var contentStyles = cva2(["w-full p-lg", "focus-visible:u-outline-inset"], { variants: { forceMount: { true: "data-[state=inactive]:hidden", false: "" } } }); // src/tabs/TabsContent.tsx import { jsx as jsx2 } from "react/jsx-runtime"; var TabsContent = ({ /** * Default Radix Primitive values * see https://www.radix-ui.com/docs/primitives/components/tabs#content */ children, asChild = false, className, ref, ...rest }) => { const { forceMount } = useTabsContext(); return /* @__PURE__ */ jsx2( RadixTabs2.Content, { ref, forceMount: forceMount || rest.forceMount, className: contentStyles({ className, forceMount }), asChild, ...rest, children } ); }; TabsContent.displayName = "Tabs.Content"; // src/tabs/TabsList.tsx import { ArrowVerticalLeft } from "@spark-ui/icons/ArrowVerticalLeft"; import { ArrowVerticalRight } from "@spark-ui/icons/ArrowVerticalRight"; import { Tabs as RadixTabs3 } from "radix-ui"; import { useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react"; // src/tabs/TabsList.styles.ts import { cva as cva3 } from "class-variance-authority"; var wrapperStyles = cva3(["relative flex"]); var listStyles = cva3([ "flex w-full", "data-[orientation=horizontal]:flex-row", "data-[orientation=vertical]:flex-col", "overflow-y-hidden u-no-scrollbar data-[orientation=vertical]:overflow-x-hidden", "after:flex after:shrink after:grow after:border-outline", "data-[orientation=horizontal]:after:border-b-sm", "data-[orientation=vertical]:after:border-r-sm" ]); var navigationArrowStyles = cva3([ "h-auto! flex-none", "border-b-sm border-outline", "outline-hidden", "focus-visible:border-none focus-visible:bg-surface-hovered focus-visible:u-outline-inset!" ]); // src/tabs/useResizeObserver.ts import { useEffect, useRef, useState } from "react"; var useResizeObserver = (target, onResize) => { const [size, setSize] = useState({ width: void 0, height: void 0 }); const resizeObserverRef = useRef(null); const resizeCallbackRef = useRef(onResize); useEffect(() => { resizeCallbackRef.current = onResize; }, [onResize]); useEffect(() => { const targetElm = target && "current" in target ? target.current : target; if (!targetElm || resizeObserverRef.current) { return; } resizeObserverRef.current = new ResizeObserver(([entry]) => { const { inlineSize: width, blockSize: height } = entry?.borderBoxSize?.[0] ?? {}; resizeCallbackRef.current?.(entry); setSize({ width, height }); }); resizeObserverRef.current.observe(targetElm); return () => { resizeObserverRef.current && resizeObserverRef.current.unobserve(targetElm); }; }, [target, resizeObserverRef, resizeCallbackRef]); return size; }; // src/tabs/TabsList.tsx import { jsx as jsx3, jsxs } from "react/jsx-runtime"; var TabsList = ({ /** * Default Radix Primitive values * see https://www.radix-ui.com/docs/primitives/components/tabs#list */ asChild = false, loop = false, children, className, ref, ...rest }) => { const wrapperRef = useRef2(null); const innerRef = useRef2(null); const listRef = ref || innerRef; const { orientation } = useTabsContext(); const { width } = useResizeObserver(wrapperRef); const [arrows, setArrows] = useState2({ prev: "hidden", next: "hidden" }); useEffect2(() => { if (typeof listRef === "function" || !listRef.current) { return; } if (orientation !== "horizontal") { setArrows({ prev: "hidden", next: "hidden" }); } else { setArrows({ prev: listRef.current.scrollWidth > listRef.current.clientWidth ? "visible" : "hidden", next: listRef.current.scrollWidth > listRef.current.clientWidth ? "visible" : "hidden" }); } }, [orientation, listRef, width]); useEffect2(() => { if (typeof listRef === "function" || !listRef.current || arrows.prev === "hidden" || loop) { return; } const toggleArrowsVisibility = (target) => { setArrows({ prev: target.scrollLeft > 0 ? "visible" : "disabled", next: target.scrollLeft + target.clientWidth < target.scrollWidth ? "visible" : "disabled" }); }; const currentList = listRef.current; toggleArrowsVisibility(currentList); currentList.addEventListener( "scroll", ({ target }) => toggleArrowsVisibility(target) ); return () => currentList.removeEventListener( "scroll", ({ target }) => toggleArrowsVisibility(target) ); }, [listRef, arrows.prev, loop]); const handlePrevClick = () => { if (typeof listRef === "function" || !listRef.current) { return; } const shouldLoopForward = loop && listRef.current.scrollLeft <= 0; listRef.current.scrollTo({ left: shouldLoopForward ? listRef.current.scrollLeft + listRef.current.scrollWidth - listRef.current.clientWidth : listRef.current.scrollLeft - listRef.current.clientWidth, behavior: "smooth" }); }; const handleNextClick = () => { if (typeof listRef === "function" || !listRef.current) { return; } const shouldLoopBackward = loop && listRef.current.scrollLeft + listRef.current.clientWidth >= listRef.current.scrollWidth; listRef.current.scrollTo({ left: shouldLoopBackward ? 0 : listRef.current.scrollLeft + listRef.current.clientWidth, behavior: "smooth" }); }; return /* @__PURE__ */ jsxs("div", { className: wrapperStyles({ className }), ref: wrapperRef, children: [ arrows.prev !== "hidden" && /* @__PURE__ */ jsx3( Button, { shape: "square", intent: "surface", size: "sm", className: navigationArrowStyles(), onClick: handlePrevClick, disabled: arrows.prev === "disabled", "aria-label": "Scroll left", children: /* @__PURE__ */ jsx3(Icon, { children: /* @__PURE__ */ jsx3(ArrowVerticalLeft, {}) }) } ), /* @__PURE__ */ jsx3( RadixTabs3.List, { ref: listRef, className: listStyles(), asChild, loop, ...rest, children } ), arrows.next !== "hidden" && /* @__PURE__ */ jsx3( Button, { shape: "square", intent: "surface", size: "sm", className: navigationArrowStyles(), onClick: handleNextClick, disabled: arrows.next === "disabled", "aria-label": "Scroll right", children: /* @__PURE__ */ jsx3(Icon, { children: /* @__PURE__ */ jsx3(ArrowVerticalRight, {}) }) } ) ] }); }; TabsList.displayName = "Tabs.List"; // src/tabs/TabsTrigger.tsx import { Tabs as RadixTabs4 } from "radix-ui"; // src/tabs/TabsTrigger.styles.ts import { makeVariants } from "@spark-ui/internal-utils"; import { cva as cva4 } from "class-variance-authority"; var triggerVariants = cva4( [ "px-md", "relative flex flex-none items-center", "border-outline", "outline-hidden", "hover:bg-surface-hovered", "after:absolute", "data-[orientation=horizontal]:border-b-sm data-[orientation=horizontal]:after:inset-x-0 data-[orientation=horizontal]:after:bottom-[-1px] data-[orientation=horizontal]:after:h-sz-2", "data-[orientation=vertical]:border-r-sm data-[orientation=vertical]:after:inset-y-0 data-[orientation=vertical]:after:right-[-1px] data-[orientation=vertical]:after:w-sz-2", "focus-visible:border-none focus-visible:bg-surface-hovered focus-visible:u-outline-inset", "disabled:cursor-not-allowed disabled:opacity-dim-3", "duration-300 ease-linear", "gap-md [&>*:first-child]:ml-md [&>*:last-child]:mr-md", "[&>svg:last-child:first-child]:mx-auto" ], { variants: { /** * Change the color scheme of the tabs * @default basic */ intent: makeVariants({ main: ["data-[state=active]:text-main data-[state=active]:after:bg-main"], support: ["data-[state=active]:text-support data-[state=active]:after:bg-support"], basic: ["data-[state=active]:text-basic data-[state=active]:after:bg-basic"] }), /** * Change the size of the tabs * @default md */ size: { xs: ["h-sz-32 min-w-sz-32 text-caption"], sm: ["h-sz-36 min-w-sz-36 text-body-2"], md: ["h-sz-40 min-w-sz-40 text-body-1"] } }, defaultVariants: { intent: "basic", size: "md" } } ); // src/tabs/TabsTrigger.tsx import { jsx as jsx4 } from "react/jsx-runtime"; var TabsTrigger = ({ /** * Default Radix Primitive values * see https://www.radix-ui.com/docs/primitives/components/tabs#trigger */ asChild = false, value, disabled = false, children, className, ref, ...rest }) => { const { intent, size } = useTabsContext(); const scrollToFocusedElement = ({ target }) => target.scrollIntoView({ behavior: "smooth", block: "nearest", inline: "nearest" }); return /* @__PURE__ */ jsx4( RadixTabs4.Trigger, { ref, className: triggerVariants({ intent, size, className }), asChild, disabled, value, onFocus: scrollToFocusedElement, ...rest, children } ); }; TabsTrigger.displayName = "Tabs.Trigger"; // src/tabs/index.ts var Tabs2 = Object.assign(Tabs, { List: TabsList, Trigger: TabsTrigger, Content: TabsContent }); Tabs2.displayName = "Tabs"; TabsList.displayName = "Tabs.List"; TabsTrigger.displayName = "Tabs.Trigger"; TabsContent.displayName = "Tabs.Content"; export { Tabs2 as Tabs }; //# sourceMappingURL=index.mjs.map