summaryrefslogtreecommitdiff
path: root/legacy/components/properties/section.tsx
diff options
context:
space:
mode:
authorMaze Winther <mazewinther@gmail.com>2026-04-18 15:35:04 +0200
committerMaze Winther <mazewinther@gmail.com>2026-04-18 15:35:04 +0200
commit0387bd4c80f699cf0272fa0165d3c86dceaf39dc (patch)
tree7c72abb6dde074b16ebf84b1d2c72a3bd58b3fff /legacy/components/properties/section.tsx
parentb1d0b103549b7b707c8b90e8a5cb98235dc385c9 (diff)
downloadopencut-0387bd4c80f699cf0272fa0165d3c86dceaf39dc.tar.gz
delete legacy folder
Diffstat (limited to 'legacy/components/properties/section.tsx')
-rw-r--r--legacy/components/properties/section.tsx262
1 files changed, 0 insertions, 262 deletions
diff --git a/legacy/components/properties/section.tsx b/legacy/components/properties/section.tsx
deleted file mode 100644
index 07d1c0ca..00000000
--- a/legacy/components/properties/section.tsx
+++ /dev/null
@@ -1,262 +0,0 @@
-import { createContext, useContext, useEffect, useState } from "react";
-import { cn } from "@/utils/ui";
-import { HugeiconsIcon } from "@hugeicons/react";
-import { ArrowDownIcon } from "@hugeicons/core-free-icons";
-import { Label } from "@/components/ui/label";
-import { Button } from "@/components/ui/button";
-
-const sectionExpandedCache = new Map<string, boolean>();
-const mountedSectionKeys = new Set<string>();
-
-interface SectionContext {
- isOpen: boolean;
- toggle: () => void;
- collapsible: boolean;
-}
-
-const SectionCtx = createContext<SectionContext | null>(null);
-
-function useSectionContext() {
- return useContext(SectionCtx);
-}
-
-interface SectionProps {
- children: React.ReactNode;
- collapsible?: boolean;
- defaultOpen?: boolean;
- sectionKey?: string;
- className?: string;
- showTopBorder?: boolean;
- showBottomBorder?: boolean;
-}
-
-export function Section({
- children,
- collapsible = false,
- defaultOpen = true,
- sectionKey,
- className,
- showTopBorder = true,
- showBottomBorder = true,
-}: SectionProps) {
- const cached = sectionKey ? sectionExpandedCache.get(sectionKey) : undefined;
- const [isOpen, setIsOpen] = useState(cached ?? defaultOpen);
-
- useEffect(() => {
- if (!sectionKey) return;
- if (process.env.NODE_ENV !== "production" && mountedSectionKeys.has(sectionKey)) {
- console.error(`[Section] duplicate sectionKey mounted simultaneously: "${sectionKey}"`);
- }
- mountedSectionKeys.add(sectionKey);
- return () => { mountedSectionKeys.delete(sectionKey); };
- }, [sectionKey]);
-
- const toggle = () => {
- const next = !isOpen;
- setIsOpen(next);
- if (sectionKey) sectionExpandedCache.set(sectionKey, next);
- };
-
- return (
- <SectionCtx.Provider value={{ isOpen, toggle, collapsible }}>
- <div
- className={cn(
- "flex flex-col",
- showTopBorder && "border-t",
- showBottomBorder && "last:border-b",
- className,
- )}
- >
- {children}
- </div>
- </SectionCtx.Provider>
- );
-}
-
-interface SectionHeaderProps {
- children?: React.ReactNode;
- trailing?: React.ReactNode;
- leading?: React.ReactNode;
- actions?: React.ReactNode;
- onClick?: () => void;
- className?: string;
-}
-
-export function SectionHeader({
- children,
- trailing,
- leading,
- actions,
- onClick,
- className,
-}: SectionHeaderProps) {
- const ctx = useSectionContext();
- const isCollapsible = ctx?.collapsible ?? false;
- const isOpen = ctx?.isOpen ?? true;
- const isInteractive = isCollapsible || !!onClick;
- const handleClick = isCollapsible ? ctx?.toggle : onClick;
-
- const chevronIcon = isCollapsible ? (
- <HugeiconsIcon
- icon={ArrowDownIcon}
- className={cn(
- "size-4 shrink-0 transition-transform duration-200 ease-out",
- isOpen ? "rotate-0 text-foreground" : "-rotate-90 text-muted-foreground",
- )}
- />
- ) : null;
-
- const headerContent = (
- <>
- {leading}
- <div className="min-w-0 flex-1">{children}</div>
- {(trailing || chevronIcon) && (
- <div className="flex items-center">
- {trailing}
- {chevronIcon && (
- <Button
- variant="ghost"
- size="icon"
- aria-label={isOpen ? "Collapse section" : "Expand section"}
- onClick={(event) => {
- event.stopPropagation();
- handleClick?.();
- }}
- >
- {chevronIcon}
- </Button>
- )}
- </div>
- )}
- {actions}
- </>
- );
-
- if (!isInteractive) {
- return (
- <div className={cn("flex h-11 w-full items-center gap-2 px-3.5", className)}>
- {headerContent}
- </div>
- );
- }
-
- return (
- // biome-ignore lint/a11y/useSemanticElements: outer div intentionally wraps a nested <Button> (chevron), making <button> invalid HTML here
- <div
- role="button"
- tabIndex={0}
- className={cn(
- "flex h-11 w-full cursor-pointer items-center gap-2 px-3.5",
- className,
- )}
- onClick={handleClick}
- onKeyDown={(event) => { if (event.key === "Enter" || event.key === " ") handleClick?.(); }}
- >
- {headerContent}
- </div>
- );
-}
-
-export function SectionTitle({
- children,
- className,
- onClick,
-}: {
- children: React.ReactNode;
- className?: string;
- onClick?: () => void;
-}) {
- const ctx = useSectionContext();
- const isOpen = ctx?.isOpen ?? true;
-
- if (onClick) {
- return (
- <button
- type="button"
- className={cn(
- "cursor-pointer text-sm font-medium",
- isOpen ? "text-foreground" : "text-muted-foreground",
- className,
- )}
- onClick={onClick}
- >
- {children}
- </button>
- );
- }
-
- return (
- <span
- className={cn(
- "text-sm font-medium",
- isOpen ? "text-foreground" : "text-muted-foreground",
- className,
- )}
- >
- {children}
- </span>
- );
-}
-
-export function SectionFields({
- children,
- className,
-}: {
- children: React.ReactNode;
- className?: string;
-}) {
- return (
- <div className={cn("flex flex-col gap-3.5", className)}>{children}</div>
- );
-}
-
-export function SectionField({
- label,
- beforeLabel,
- children,
- className,
-}: {
- label: string;
- beforeLabel?: React.ReactNode;
- children: React.ReactNode;
- className?: string;
-}) {
- return (
- <div className={cn("flex flex-col gap-2", className)}>
- <div className="flex h-4 items-center gap-1.5">
- {beforeLabel}
- <Label>{label}</Label>
- </div>
- {children}
- </div>
- );
-}
-
-export function SectionContent({
- children,
- className,
-}: {
- children: React.ReactNode;
- className?: string;
-}) {
- const ctx = useSectionContext();
- const isCollapsible = ctx?.collapsible ?? false;
- const isOpen = ctx?.isOpen ?? true;
-
- if (isCollapsible) {
- return (
- <div
- className={cn(
- "grid transition-[grid-template-rows] duration-100 ease-out",
- isOpen ? "grid-rows-[1fr]" : "grid-rows-[0fr]",
- )}
- >
- <div className="overflow-hidden">
- <div className={cn("p-4 pt-0", className)}>{children}</div>
- </div>
- </div>
- );
- }
-
- return <div className={cn("p-4 pt-0", className)}>{children}</div>;
-}