gridsmith-ui 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/resizable.js CHANGED
@@ -1,89 +1,6 @@
1
- import { useBreakpoint } from './chunk-EKQHHP72.js';
2
- import { Icon } from './chunk-X4CNZFWC.js';
3
- import { cn } from './chunk-4KVFH5KC.js';
4
- import { Group, Panel, Separator } from 'react-resizable-panels';
5
- import { createContext, useContext } from 'react';
6
- import { jsx } from 'react/jsx-runtime';
7
-
8
- var DirectionCtx = createContext("horizontal");
9
- var MobileCtx = createContext(false);
10
- function ResizablePanelGroup({
11
- className,
12
- direction = "horizontal",
13
- stackOnMobile = true,
14
- ...props
15
- }) {
16
- const isMobile = useBreakpoint("sm");
17
- const shouldStack = stackOnMobile && isMobile && direction === "horizontal";
18
- const effectiveDirection = shouldStack ? "vertical" : direction;
19
- return /* @__PURE__ */ jsx(DirectionCtx.Provider, { value: effectiveDirection, children: /* @__PURE__ */ jsx(MobileCtx.Provider, { value: isMobile, children: /* @__PURE__ */ jsx(
20
- Group,
21
- {
22
- className: cn(
23
- "flex h-full w-full",
24
- effectiveDirection === "vertical" && "flex-col",
25
- className
26
- ),
27
- orientation: effectiveDirection,
28
- ...props
29
- }
30
- ) }) });
31
- }
32
- function ResizablePanel({ className, ...props }) {
33
- return /* @__PURE__ */ jsx(Panel, { className: cn("", className), ...props });
34
- }
35
- function ResizableHandle({
36
- withHandle,
37
- className,
38
- ...props
39
- }) {
40
- const direction = useContext(DirectionCtx);
41
- const isMobile = useContext(MobileCtx);
42
- const isVertical = direction === "vertical";
43
- return /* @__PURE__ */ jsx(
44
- Separator,
45
- {
46
- className: cn(
47
- "relative flex items-center justify-center bg-[var(--ds-border-default)]",
48
- isVertical ? cn(
49
- "h-[var(--ds-border-width)] w-full after:absolute after:left-0 after:right-0 after:content-['']",
50
- isMobile ? "after:-top-3 after:-bottom-3" : "after:-top-1 after:-bottom-1"
51
- ) : cn(
52
- "w-[var(--ds-border-width)] after:absolute after:inset-y-0 after:content-['']",
53
- isMobile ? "after:-left-3 after:-right-3" : "after:-left-1 after:-right-1"
54
- ),
55
- "focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]",
56
- "[&[data-resize-handle-state=drag]]:bg-[var(--ds-accent-primary)]",
57
- "[&[data-resize-handle-state=hover]]:bg-[var(--ds-accent-primary)]",
58
- className
59
- ),
60
- ...props,
61
- children: withHandle && /* @__PURE__ */ jsx(
62
- "div",
63
- {
64
- className: cn(
65
- "z-10 flex items-center justify-center rounded-[var(--ds-radius-sm)]",
66
- "border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
67
- "bg-[var(--ds-bg-surface)]",
68
- isVertical ? isMobile ? "h-4 w-8" : "h-3 w-4" : isMobile ? "h-8 w-4" : "h-4 w-3"
69
- ),
70
- children: /* @__PURE__ */ jsx(
71
- Icon,
72
- {
73
- name: "grip-vertical",
74
- size: isMobile ? 12 : 10,
75
- className: cn(
76
- "text-[var(--ds-text-muted)]",
77
- isVertical && "rotate-90"
78
- )
79
- }
80
- )
81
- }
82
- )
83
- }
84
- );
85
- }
86
-
87
- export { ResizableHandle, ResizablePanel, ResizablePanelGroup };
1
+ export { ResizableHandle, ResizablePanel, ResizablePanelGroup } from './chunk-5B2ZFL2H.js';
2
+ import './chunk-CRQ6KCRD.js';
3
+ import './chunk-X4CNZFWC.js';
4
+ import './chunk-4KVFH5KC.js';
88
5
  //# sourceMappingURL=resizable.js.map
89
6
  //# sourceMappingURL=resizable.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../showcase/src/components/ResizablePanels.tsx"],"names":["PanelGroup","PanelResizeHandle"],"mappings":";;;;;;;AAaA,IAAM,YAAA,GAAe,cAAyB,YAAY,CAAA;AAC1D,IAAM,SAAA,GAAY,cAAc,KAAK,CAAA;AAa9B,SAAS,mBAAA,CAAoB;AAAA,EAClC,SAAA;AAAA,EACA,SAAA,GAAY,YAAA;AAAA,EACZ,aAAA,GAAgB,IAAA;AAAA,EAChB,GAAG;AACL,CAAA,EAA6B;AAC3B,EAAA,MAAM,QAAA,GAAW,cAAc,IAAI,CAAA;AACnC,EAAA,MAAM,WAAA,GAAc,aAAA,IAAiB,QAAA,IAAY,SAAA,KAAc,YAAA;AAC/D,EAAA,MAAM,kBAAA,GAAqB,cAAc,UAAA,GAAa,SAAA;AAEtD,EAAA,uBACE,GAAA,CAAC,YAAA,CAAa,QAAA,EAAb,EAAsB,KAAA,EAAO,kBAAA,EAC5B,QAAA,kBAAA,GAAA,CAAC,SAAA,CAAU,QAAA,EAAV,EAAmB,KAAA,EAAO,QAAA,EACzB,QAAA,kBAAA,GAAA;AAAA,IAACA,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,EAAA;AAAA,QACT,oBAAA;AAAA,QACA,uBAAuB,UAAA,IAAc,UAAA;AAAA,QACrC;AAAA,OACF;AAAA,MACA,WAAA,EAAa,kBAAA;AAAA,MACZ,GAAG;AAAA;AAAA,KAER,CAAA,EACF,CAAA;AAEJ;AAcO,SAAS,cAAA,CAAe,EAAE,SAAA,EAAW,GAAG,OAAM,EAAwB;AAC3E,EAAA,uBAAO,GAAA,CAAC,SAAM,SAAA,EAAW,EAAA,CAAG,IAAI,SAAS,CAAA,EAAI,GAAG,KAAA,EAAO,CAAA;AACzD;AAUO,SAAS,eAAA,CAAgB;AAAA,EAC9B,UAAA;AAAA,EACA,SAAA;AAAA,EACA,GAAG;AACL,CAAA,EAAyB;AACvB,EAAA,MAAM,SAAA,GAAY,WAAW,YAAY,CAAA;AACzC,EAAA,MAAM,QAAA,GAAW,WAAW,SAAS,CAAA;AACrC,EAAA,MAAM,aAAa,SAAA,KAAc,UAAA;AAEjC,EAAA,uBACE,GAAA;AAAA,IAACC,SAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,EAAA;AAAA,QACT,yEAAA;AAAA,QACA,UAAA,GACI,EAAA;AAAA,UACE,gGAAA;AAAA,UACA,WAAW,8BAAA,GAAiC;AAAA,SAC9C,GACA,EAAA;AAAA,UACE,8EAAA;AAAA,UACA,WAAW,8BAAA,GAAiC;AAAA,SAC9C;AAAA,QACJ,0EAAA;AAAA,QACA,kEAAA;AAAA,QACA,mEAAA;AAAA,QACA;AAAA,OACF;AAAA,MACC,GAAG,KAAA;AAAA,MAEH,QAAA,EAAA,UAAA,oBACC,GAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UACC,SAAA,EAAW,EAAA;AAAA,YACT,qEAAA;AAAA,YACA,0EAAA;AAAA,YACA,2BAAA;AAAA,YACA,UAAA,GACK,QAAA,GAAW,SAAA,GAAY,SAAA,GACvB,WAAW,SAAA,GAAY;AAAA,WAC9B;AAAA,UAEA,QAAA,kBAAA,GAAA;AAAA,YAAC,IAAA;AAAA,YAAA;AAAA,cACC,IAAA,EAAK,eAAA;AAAA,cACL,IAAA,EAAM,WAAW,EAAA,GAAK,EAAA;AAAA,cACtB,SAAA,EAAW,EAAA;AAAA,gBACT,6BAAA;AAAA,gBACA,UAAA,IAAc;AAAA;AAChB;AAAA;AACF;AAAA;AACF;AAAA,GAEJ;AAEJ","file":"resizable.js","sourcesContent":["import {\n Panel,\n Group as PanelGroup,\n Separator as PanelResizeHandle,\n} from \"react-resizable-panels\";\nimport { createContext, useContext, type ComponentProps } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { useBreakpoint } from \"../lib/use-breakpoint\";\nimport { Icon } from \"../lib/icons\";\n\ntype PanelGroupProps = ComponentProps<typeof PanelGroup>;\n\ntype Direction = \"horizontal\" | \"vertical\";\nconst DirectionCtx = createContext<Direction>(\"horizontal\");\nconst MobileCtx = createContext(false);\n\nexport interface ResizablePanelGroupProps\n extends Omit<PanelGroupProps, \"className\" | \"orientation\"> {\n direction?: Direction;\n stackOnMobile?: boolean;\n className?: string;\n /** Map of panel id → percentage (0–100). Must be an object, never an array. Panels need matching id props. */\n defaultLayout?: { [panelId: string]: number };\n /** Called after resize ends. Receives { [panelId]: number }, not number[]. */\n onLayoutChanged?: (layout: { [panelId: string]: number }) => void;\n}\n\nexport function ResizablePanelGroup({\n className,\n direction = \"horizontal\",\n stackOnMobile = true,\n ...props\n}: ResizablePanelGroupProps) {\n const isMobile = useBreakpoint(\"sm\");\n const shouldStack = stackOnMobile && isMobile && direction === \"horizontal\";\n const effectiveDirection = shouldStack ? \"vertical\" : direction;\n\n return (\n <DirectionCtx.Provider value={effectiveDirection}>\n <MobileCtx.Provider value={isMobile}>\n <PanelGroup\n className={cn(\n \"flex h-full w-full\",\n effectiveDirection === \"vertical\" && \"flex-col\",\n className,\n )}\n orientation={effectiveDirection}\n {...props}\n />\n </MobileCtx.Provider>\n </DirectionCtx.Provider>\n );\n}\n\ntype PanelProps = ComponentProps<typeof Panel>;\n\nexport interface ResizablePanelProps extends Omit<PanelProps, \"className\"> {\n className?: string;\n id?: string;\n /** number = px. \"30%\" or \"30\" = percent. \"28rem\" / \"400px\" also valid. */\n defaultSize?: number | string;\n minSize?: number | string;\n maxSize?: number | string;\n collapsible?: boolean;\n}\n\nexport function ResizablePanel({ className, ...props }: ResizablePanelProps) {\n return <Panel className={cn(\"\", className)} {...props} />;\n}\n\ntype PanelResizeHandleProps = ComponentProps<typeof PanelResizeHandle>;\n\nexport interface ResizableHandleProps\n extends Omit<PanelResizeHandleProps, \"className\"> {\n withHandle?: boolean;\n className?: string;\n}\n\nexport function ResizableHandle({\n withHandle,\n className,\n ...props\n}: ResizableHandleProps) {\n const direction = useContext(DirectionCtx);\n const isMobile = useContext(MobileCtx);\n const isVertical = direction === \"vertical\";\n\n return (\n <PanelResizeHandle\n className={cn(\n \"relative flex items-center justify-center bg-[var(--ds-border-default)]\",\n isVertical\n ? cn(\n \"h-[var(--ds-border-width)] w-full after:absolute after:left-0 after:right-0 after:content-['']\",\n isMobile ? \"after:-top-3 after:-bottom-3\" : \"after:-top-1 after:-bottom-1\"\n )\n : cn(\n \"w-[var(--ds-border-width)] after:absolute after:inset-y-0 after:content-['']\",\n isMobile ? \"after:-left-3 after:-right-3\" : \"after:-left-1 after:-right-1\"\n ),\n \"focus-visible:outline-none focus-visible:shadow-[var(--ds-shadow-focus)]\",\n \"[&[data-resize-handle-state=drag]]:bg-[var(--ds-accent-primary)]\",\n \"[&[data-resize-handle-state=hover]]:bg-[var(--ds-accent-primary)]\",\n className,\n )}\n {...props}\n >\n {withHandle && (\n <div\n className={cn(\n \"z-10 flex items-center justify-center rounded-[var(--ds-radius-sm)]\",\n \"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]\",\n \"bg-[var(--ds-bg-surface)]\",\n isVertical\n ? (isMobile ? \"h-4 w-8\" : \"h-3 w-4\")\n : (isMobile ? \"h-8 w-4\" : \"h-4 w-3\"),\n )}\n >\n <Icon\n name=\"grip-vertical\"\n size={isMobile ? 12 : 10}\n className={cn(\n \"text-[var(--ds-text-muted)]\",\n isVertical && \"rotate-90\",\n )}\n />\n </div>\n )}\n </PanelResizeHandle>\n );\n}\n"]}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"resizable.js"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gridsmith-ui",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Gridsmith component library — 98 React components with design tokens and a CSS custom property theming engine",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../showcase/src/lib/use-breakpoint.ts"],"names":[],"mappings":";;;AAEA,IAAM,mBAAA,GAAsB,EAAE,EAAA,EAAI,GAAA,EAAK,IAAI,GAAA,EAAK,EAAA,EAAI,IAAA,EAAM,EAAA,EAAI,IAAA,EAAK;AAInE,IAAM,kBAAA,GAAqB,cAA6B,IAAI,CAAA;AAOrD,SAAS,uBAAA,CAAwB,EAAE,KAAA,EAAO,QAAA,EAAS,EAAkD;AAC1G,EAAA,OAAO,cAAc,kBAAA,EAAoB,EAAE,KAAA,EAAO,KAAA,IAAS,QAAQ,CAAA;AACrE;AAEA,SAAS,cAAc,GAAA,EAA4B;AACjD,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,EAAa,OAAO,oBAAoB,GAAG,CAAA;AACjE,EAAA,MAAM,GAAA,GAAM,gBAAA,CAAiB,QAAA,CAAS,eAAe,CAAA,CAClD,iBAAiB,CAAA,QAAA,EAAW,GAAG,CAAA,CAAE,CAAA,CACjC,IAAA,EAAK;AACR,EAAA,MAAM,EAAA,GAAK,QAAA,CAAS,GAAA,EAAK,EAAE,CAAA;AAC3B,EAAA,OAAO,KAAA,CAAM,EAAE,CAAA,GAAI,mBAAA,CAAoB,GAAG,CAAA,GAAI,EAAA;AAChD;AAEA,IAAM,aAAA,GAAgB,MAAM,MAAM;AAAC,CAAA;AACnC,IAAM,iBAAiB,MAAM,KAAA;AAatB,SAAS,cAAc,GAAA,EAA6B;AACzD,EAAA,MAAM,aAAA,GAAgB,WAAW,kBAAkB,CAAA;AACnD,EAAA,MAAM,EAAA,GAAK,QAAQ,MAAM,aAAA,CAAc,GAAG,CAAA,EAAG,CAAC,GAAG,CAAC,CAAA;AAClD,EAAA,MAAM,UAAA,GAAa,eAAe,EAAE,CAAA,GAAA,CAAA;AAEpC,EAAA,MAAM,SAAA,GAAY,WAAA,CAAY,CAAC,QAAA,KAAyB;AACtD,IAAA,IAAI,kBAAkB,IAAA,IAAQ,OAAO,MAAA,KAAW,WAAA,SAAoB,aAAA,EAAc;AAClF,IAAA,MAAM,GAAA,GAAM,MAAA,CAAO,UAAA,CAAW,UAAU,CAAA;AACxC,IAAA,GAAA,CAAI,gBAAA,CAAiB,UAAU,QAAQ,CAAA;AACvC,IAAA,OAAO,MAAM,GAAA,CAAI,mBAAA,CAAoB,QAAA,EAAU,QAAQ,CAAA;AAAA,EACzD,CAAA,EAAG,CAAC,UAAA,EAAY,aAAa,CAAC,CAAA;AAE9B,EAAA,MAAM,OAAA,GAAU,oBAAA;AAAA,IACd,SAAA;AAAA,IACA,MAAO,OAAO,MAAA,KAAW,WAAA,GAAc,OAAO,UAAA,CAAW,UAAU,EAAE,OAAA,GAAU,KAAA;AAAA,IAC/E;AAAA,GACF;AAEA,EAAA,IAAI,aAAA,KAAkB,IAAA,EAAM,OAAO,aAAA,IAAiB,EAAA;AACpD,EAAA,OAAO,OAAA;AACT","file":"chunk-EKQHHP72.js","sourcesContent":["import { useCallback, useMemo, useSyncExternalStore, createContext, useContext, createElement, type ReactNode } from \"react\";\n\nconst DEFAULT_BREAKPOINTS = { sm: 640, md: 768, lg: 1024, xl: 1280 } as const;\n\nexport type BreakpointKey = keyof typeof DEFAULT_BREAKPOINTS;\n\nconst BreakpointWidthCtx = createContext<number | null>(null);\n\n/**\n * Provides an override container width for all `useBreakpoint` calls within\n * this subtree. Used by the builder's viewport preview to make components\n * respond to the constrained canvas width instead of the browser viewport.\n */\nexport function BreakpointWidthProvider({ width, children }: { width: number | null; children: ReactNode }) {\n return createElement(BreakpointWidthCtx, { value: width }, children);\n}\n\nfunction readBpFromCSS(key: BreakpointKey): number {\n if (typeof window === \"undefined\") return DEFAULT_BREAKPOINTS[key];\n const raw = getComputedStyle(document.documentElement)\n .getPropertyValue(`--ds-bp-${key}`)\n .trim();\n const px = parseInt(raw, 10);\n return isNaN(px) ? DEFAULT_BREAKPOINTS[key] : px;\n}\n\nconst noopSubscribe = () => () => {};\nconst serverSnapshot = () => false;\n\n/**\n * Reactive breakpoint check that reads `--ds-bp-*` CSS variables.\n * Returns true when the viewport (or override container) is at or below the\n * named breakpoint.\n *\n * Implemented with useSyncExternalStore so the first render already reflects\n * the media query and a change between render and subscribe cannot be missed.\n *\n * @example\n * const isMobile = useBreakpoint(\"md\"); // true when ≤768px\n */\nexport function useBreakpoint(key: BreakpointKey): boolean {\n const overrideWidth = useContext(BreakpointWidthCtx);\n const px = useMemo(() => readBpFromCSS(key), [key]);\n const mediaQuery = `(max-width: ${px}px)`;\n\n const subscribe = useCallback((onChange: () => void) => {\n if (overrideWidth !== null || typeof window === \"undefined\") return noopSubscribe();\n const mql = window.matchMedia(mediaQuery);\n mql.addEventListener(\"change\", onChange);\n return () => mql.removeEventListener(\"change\", onChange);\n }, [mediaQuery, overrideWidth]);\n\n const matches = useSyncExternalStore(\n subscribe,\n () => (typeof window !== \"undefined\" ? window.matchMedia(mediaQuery).matches : false),\n serverSnapshot,\n );\n\n if (overrideWidth !== null) return overrideWidth <= px;\n return matches;\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../../showcase/src/components/CodeBlock.tsx","../../../showcase/src/components/Link.tsx","../../../showcase/src/components/Divider.tsx"],"names":["Link","jsxs","jsx"],"mappings":"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","file":"chunk-G6KC5YNY.js","sourcesContent":["import { useState, useCallback } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { Icon } from \"../lib/icons\";\nimport { Badge } from \"./Badge\";\n\ninterface CodeBlockProps {\n code: string;\n language?: string;\n showLineNumbers?: boolean;\n className?: string;\n}\n\nexport function CodeBlock({\n code,\n language,\n showLineNumbers = false,\n className,\n}: CodeBlockProps) {\n const [copied, setCopied] = useState(false);\n\n const handleCopy = useCallback(async () => {\n try {\n await navigator.clipboard.writeText(code);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n } catch {\n /* clipboard not available */\n }\n }, [code]);\n\n const lines = code.split(\"\\n\");\n const gutterWidth = showLineNumbers ? `${String(lines.length).length + 1}ch` : undefined;\n\n return (\n <div\n className={cn(\n \"relative group\",\n \"bg-[var(--ds-bg-surface)] text-[var(--ds-text-primary)]\",\n \"border-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)]\",\n \"rounded-[var(--ds-radius-md)]\",\n \"shadow-[var(--ds-shadow-sm)]\",\n \"overflow-hidden\",\n className,\n )}\n >\n <div className=\"flex items-center justify-between px-ds-4 py-ds-2 border-b-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)] bg-[var(--ds-bg-muted)]\">\n <div className=\"flex items-center gap-ds-2\">\n {language && <Badge variant=\"outline\" size=\"sm\">{language}</Badge>}\n </div>\n <button\n type=\"button\"\n onClick={handleCopy}\n className={cn(\n \"inline-flex items-center gap-ds-1.5 px-ds-2 py-ds-1 text-xs font-medium cursor-pointer\",\n \"text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)]\",\n \"rounded-[var(--ds-radius-sm)]\",\n \"hover:bg-[var(--ds-bg-surface)]\",\n \"transition-colors\",\n \"focus-visible:shadow-[var(--ds-shadow-focus)] outline-none\",\n )}\n aria-label={copied ? \"Copied\" : \"Copy code\"}\n >\n <Icon name={copied ? \"check\" : \"folder\"} size={14} />\n {copied ? \"Copied\" : \"Copy\"}\n </button>\n </div>\n\n <div className=\"overflow-x-auto\">\n <pre className=\"p-ds-4 text-sm leading-relaxed font-[family-name:var(--ds-font-mono)]\">\n <code>\n {lines.map((line, i) => (\n <span key={i} className=\"block\">\n {showLineNumbers && (\n <span\n className=\"inline-block text-right text-[var(--ds-text-muted)] select-none mr-ds-4 opacity-50\"\n style={{ width: gutterWidth }}\n >\n {i + 1}\n </span>\n )}\n {line || \" \"}\n </span>\n ))}\n </code>\n </pre>\n </div>\n </div>\n );\n}\n","import { forwardRef, type AnchorHTMLAttributes, type ComponentType, type ReactNode } from \"react\";\nimport { cn } from \"../lib/utils\";\n\ntype LinkUnderline = \"hover\" | \"always\" | \"none\";\ntype LinkTone = \"accent\" | \"muted\" | \"inherit\";\n\nexport interface LinkProps extends AnchorHTMLAttributes<HTMLAnchorElement> {\n href: string;\n children: ReactNode;\n /** When to show the underline. Default \"hover\". */\n underline?: LinkUnderline;\n /** Colour: accent (default), muted for secondary links, inherit to match surrounding text. */\n tone?: LinkTone;\n /** Opens in a new tab with rel=\"noopener noreferrer\". Default false. */\n external?: boolean;\n /**\n * Render through a router link component instead of a plain anchor\n * (e.g. `component={RouterLink}` from react-router or next/link). The\n * component receives the same props; `href` is also passed as `to` for\n * react-router compatibility.\n */\n component?: ComponentType<Record<string, unknown>>;\n iconLeft?: ReactNode;\n iconRight?: ReactNode;\n}\n\nconst toneStyles: Record<LinkTone, string> = {\n accent: \"text-[var(--ds-accent-primary)] hover:text-[var(--ds-accent-primary-hover)] active:text-[var(--ds-accent-primary-active)]\",\n muted: \"text-[var(--ds-text-secondary)] hover:text-[var(--ds-text-primary)]\",\n inherit: \"text-inherit hover:text-[var(--ds-accent-primary)]\",\n};\n\nconst underlineStyles: Record<LinkUnderline, string> = {\n hover: \"no-underline hover:underline\",\n always: \"underline underline-offset-2\",\n none: \"no-underline\",\n};\n\n/**\n * Navigation link. Renders a real <a> (or a router link via `component`) so\n * middle-click, open-in-new-tab, right-click \"copy link\" and screen readers\n * all behave correctly. Visually identical to Button variant=\"link\".\n *\n * Use Link for NAVIGATION (to a page or URL). Use Button variant=\"link\" for an\n * ACTION that should look like a link (show more, resend code). Never use a\n * ghost Button for inline text — its padding breaks the line.\n */\nexport const Link = forwardRef<HTMLAnchorElement, LinkProps>(function Link(\n { href, children, underline = \"hover\", tone = \"accent\", external = false, component: Component, iconLeft, iconRight, className, target, rel, ...props },\n ref,\n) {\n const classes = cn(\n \"inline-flex items-center gap-ds-1 font-medium cursor-pointer\",\n \"transition-colors duration-[var(--ds-transition-speed)]\",\n \"focus-visible:outline-2 focus-visible:outline-[var(--ds-accent-primary)] focus-visible:outline-offset-2 rounded-[var(--ds-radius-sm)]\",\n toneStyles[tone],\n underlineStyles[underline],\n className,\n );\n const resolvedTarget = external ? \"_blank\" : target;\n const resolvedRel = external ? cn(\"noopener noreferrer\", rel) : rel;\n const content = (\n <>\n {iconLeft}\n {children}\n {iconRight}\n </>\n );\n\n if (Component) {\n return (\n <Component ref={ref} href={href} to={href} className={classes} target={resolvedTarget} rel={resolvedRel} {...props}>\n {content}\n </Component>\n );\n }\n\n return (\n <a ref={ref} href={href} className={classes} target={resolvedTarget} rel={resolvedRel} {...props}>\n {content}\n </a>\n );\n});\n","import { cn } from \"../lib/utils\";\nimport type { ReactNode } from \"react\";\n\ntype Orientation = \"horizontal\" | \"vertical\";\n\ninterface DividerProps {\n orientation?: Orientation;\n label?: ReactNode;\n className?: string;\n}\n\nexport function Divider({\n orientation = \"horizontal\",\n label,\n className,\n}: DividerProps) {\n if (orientation === \"vertical\") {\n return (\n <div\n role=\"separator\"\n aria-orientation=\"vertical\"\n className={cn(\n \"inline-block self-stretch min-h-[1em]\",\n \"w-[var(--ds-divider-width)]\",\n \"bg-[var(--ds-border-default)]\",\n className,\n )}\n />\n );\n }\n\n if (label) {\n return (\n <div\n role=\"separator\"\n className={cn(\"flex items-center gap-ds-3\", className)}\n >\n <span className=\"flex-1 h-[var(--ds-divider-width)] bg-[var(--ds-border-default)]\" />\n <span className=\"text-xs font-medium text-[var(--ds-text-muted)] shrink-0\">\n {label}\n </span>\n <span className=\"flex-1 h-[var(--ds-divider-width)] bg-[var(--ds-border-default)]\" />\n </div>\n );\n }\n\n return (\n <hr\n role=\"separator\"\n className={cn(\n \"border-none w-full\",\n \"h-[var(--ds-divider-width)]\",\n \"bg-[var(--ds-border-default)]\",\n className,\n )}\n />\n );\n}\n"]}