@colineapp/ui 0.3.1 → 0.4.1

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/index.js CHANGED
@@ -8,6 +8,7 @@ function cn(...inputs) {
8
8
  }
9
9
 
10
10
  // src/provider.tsx
11
+ import { MotionConfig } from "framer-motion";
11
12
  import * as React from "react";
12
13
  import {
13
14
  connectGuestBridge
@@ -24,18 +25,22 @@ function applyTheme(theme, colorScheme) {
24
25
  root.classList.toggle("dark", colorScheme === "dark");
25
26
  }
26
27
  function ColineAppProvider({ children }) {
28
+ const [connectionError, setConnectionError] = React.useState(null);
27
29
  const [runtime, setRuntime] = React.useState(null);
28
30
  React.useEffect(() => {
29
31
  let disposed = false;
32
+ let activeBridge = null;
30
33
  let removeThemeListener = null;
31
34
  void connectGuestBridge().then((bridge) => {
32
- if (disposed) return;
35
+ if (disposed) {
36
+ bridge.dispose();
37
+ return;
38
+ }
39
+ activeBridge = bridge;
33
40
  applyTheme(bridge.theme, bridge.colorScheme);
34
41
  removeThemeListener = bridge.onThemeChange((theme, colorScheme) => {
35
42
  applyTheme(theme, colorScheme);
36
- setRuntime(
37
- (current) => current ? { ...current, colorScheme } : current
38
- );
43
+ setRuntime((current) => current ? { ...current, colorScheme } : current);
39
44
  });
40
45
  setRuntime({
41
46
  bridge,
@@ -43,9 +48,12 @@ function ColineAppProvider({ children }) {
43
48
  context: bridge.context,
44
49
  colorScheme: bridge.colorScheme
45
50
  });
51
+ }).catch((error) => {
52
+ if (!disposed) setConnectionError(error instanceof Error ? error.message : String(error));
46
53
  });
47
54
  return () => {
48
55
  disposed = true;
56
+ activeBridge?.dispose();
49
57
  removeThemeListener?.();
50
58
  };
51
59
  }, []);
@@ -58,9 +66,9 @@ function ColineAppProvider({ children }) {
58
66
  return () => observer.disconnect();
59
67
  }, [runtime]);
60
68
  if (!runtime) {
61
- return null;
69
+ return /* @__PURE__ */ jsx("p", { role: connectionError ? "alert" : "status", children: connectionError ?? "Connecting to Coline\u2026" });
62
70
  }
63
- return /* @__PURE__ */ jsx(ColineRuntimeContext.Provider, { value: runtime, children });
71
+ return /* @__PURE__ */ jsx(ColineRuntimeContext.Provider, { value: runtime, children: /* @__PURE__ */ jsx(MotionConfig, { reducedMotion: "user", children }) });
64
72
  }
65
73
  function useColine() {
66
74
  const runtime = React.useContext(ColineRuntimeContext);
@@ -158,7 +166,7 @@ import { cva as cva2 } from "class-variance-authority";
158
166
  import { Slot as Slot2 } from "radix-ui";
159
167
  import { jsx as jsx3 } from "react/jsx-runtime";
160
168
  var buttonVariants = cva2(
161
- "group/button inline-flex shrink-0 items-center justify-center rounded-4xl border border-white/20 text-sm font-medium whitespace-nowrap transition-[color,background-color,border-color] duration-200 ease-out outline-none select-none focus-visible:border-ring disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-[3px] aria-invalid:ring-destructive/20 dark:border-white/[0.06] dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
169
+ "coline-button group/button inline-flex shrink-0 items-center justify-center rounded-4xl border border-white/20 text-sm font-medium whitespace-nowrap transition-[color,background-color,border-color,transform,box-shadow] duration-150 ease-[cubic-bezier(0.23,1,0.32,1)] outline-none select-none focus-visible:border-ring disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-[3px] aria-invalid:ring-destructive/20 dark:border-white/[0.06] dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
162
170
  {
163
171
  variants: {
164
172
  variant: {
@@ -191,6 +199,7 @@ var Button = React3.forwardRef(function Button2({
191
199
  variant = "default",
192
200
  size = "default",
193
201
  asChild = false,
202
+ type,
194
203
  ...props
195
204
  }, ref) {
196
205
  const Comp = asChild ? Slot2.Root : "button";
@@ -198,6 +207,7 @@ var Button = React3.forwardRef(function Button2({
198
207
  Comp,
199
208
  {
200
209
  ref,
210
+ ...!asChild ? { type: type ?? "button" } : type ? { type } : {},
201
211
  "data-slot": "button",
202
212
  "data-variant": variant,
203
213
  "data-size": size,
@@ -332,6 +342,11 @@ function Checkbox({
332
342
  import "react";
333
343
  import { Dialog as DialogPrimitive } from "radix-ui";
334
344
  import { IconX } from "@tabler/icons-react";
345
+
346
+ // src/components/liquid-menu-surface.ts
347
+ var liquidMenuSurfaceClasses = "rounded-2xl bg-popover/75 dark:bg-zinc-900/75 backdrop-blur-[3px] border border-black/[0.08] text-popover-foreground shadow-[0_4px_16px_-4px_rgba(0,0,0,0.08),0_16px_48px_-12px_rgba(0,0,0,0.28)] dark:border-white/[0.09] dark:bg-[#141417] dark:shadow-[0_4px_16px_-4px_rgba(0,0,0,0.4),0_16px_48px_-12px_rgba(0,0,0,0.7)]";
348
+
349
+ // src/components/dialog.tsx
335
350
  import { jsx as jsx6, jsxs } from "react/jsx-runtime";
336
351
  function Dialog({
337
352
  ...props
@@ -362,7 +377,7 @@ function DialogOverlay({
362
377
  {
363
378
  "data-slot": "dialog-overlay",
364
379
  className: cn(
365
- "fixed inset-0 isolate z-50 bg-black/30 supports-backdrop-filter:backdrop-blur-sm",
380
+ "coline-dialog-overlay fixed inset-0 isolate z-50 bg-black/30 supports-backdrop-filter:backdrop-blur-sm",
366
381
  className
367
382
  ),
368
383
  ...props
@@ -383,15 +398,16 @@ function DialogContent({
383
398
  "data-slot": "dialog-content",
384
399
  className: cn(
385
400
  // Mobile: bottom-sheet style, pinned to bottom with slide-up
386
- "fixed z-50 grid w-full gap-4 bg-background/75 dark:bg-zinc-900/75 backdrop-blur-sm p-4 text-sm shadow-xl shadow-black/10 dark:shadow-black/30 ring-1 ring-white/15 dark:ring-white/10 inset-ring inset-ring-white/10 dark:inset-ring-white/5 outline-none",
387
- "inset-x-0 bottom-0 max-h-[85dvh] overflow-y-auto rounded-t-3xl pb-[max(1rem,env(safe-area-inset-bottom))]",
401
+ "coline-dialog-content fixed z-50 grid w-full gap-4 p-4 text-sm outline-none",
402
+ liquidMenuSurfaceClasses,
403
+ "inset-x-0 bottom-0 max-h-[85dvh] overflow-y-auto rounded-b-none pb-[max(1rem,env(safe-area-inset-bottom))]",
388
404
  // Desktop: centered modal
389
- "sm:inset-x-auto sm:bottom-auto sm:top-1/2 sm:left-1/2 sm:max-w-md sm:max-h-[calc(100dvh-4rem)] sm:-translate-x-1/2 sm:-translate-y-1/2 sm:rounded-4xl sm:p-6 sm:gap-6 sm:pb-6",
405
+ "sm:inset-x-auto sm:bottom-auto sm:top-1/2 sm:left-1/2 sm:max-w-md sm:max-h-[calc(100dvh-4rem)] sm:-translate-x-1/2 sm:-translate-y-1/2 sm:rounded-2xl sm:p-6 sm:gap-6 sm:pb-6",
390
406
  className
391
407
  ),
392
408
  ...props,
393
409
  children: [
394
- /* @__PURE__ */ jsx6("div", { className: "mx-auto h-1 w-10 shrink-0 rounded-full bg-muted-foreground/30 sm:hidden" }),
410
+ /* @__PURE__ */ jsx6("div", { className: "mx-auto h-1 w-10 shrink-0 rounded-full bg-muted-foreground/30 sm:hidden", "aria-hidden": "true" }),
395
411
  children,
396
412
  showCloseButton && /* @__PURE__ */ jsx6(DialogPrimitive.Close, { "data-slot": "dialog-close", asChild: true, children: /* @__PURE__ */ jsxs(
397
413
  Button,
@@ -415,7 +431,7 @@ function DialogHeader({ className, ...props }) {
415
431
  "div",
416
432
  {
417
433
  "data-slot": "dialog-header",
418
- className: cn("flex flex-col gap-2", className),
434
+ className: cn("flex flex-col gap-2 pr-8", className),
419
435
  ...props
420
436
  }
421
437
  );
@@ -477,9 +493,6 @@ import * as React8 from "react";
477
493
  import { DropdownMenu as DropdownMenuPrimitive } from "radix-ui";
478
494
  import { IconCheck as IconCheck2, IconChevronRight } from "@tabler/icons-react";
479
495
 
480
- // src/components/liquid-menu-surface.ts
481
- var liquidMenuSurfaceClasses = "rounded-2xl bg-popover/75 dark:bg-zinc-900/75 backdrop-blur-[3px] border border-black/[0.08] text-popover-foreground shadow-[0_4px_16px_-4px_rgba(0,0,0,0.08),0_16px_48px_-12px_rgba(0,0,0,0.28)] dark:border-white/[0.09] dark:bg-[#141417] dark:shadow-[0_4px_16px_-4px_rgba(0,0,0,0.4),0_16px_48px_-12px_rgba(0,0,0,0.7)]";
482
-
483
496
  // src/components/menu-highlight.tsx
484
497
  import * as React7 from "react";
485
498
  import { motion } from "framer-motion";
@@ -1639,115 +1652,73 @@ function TableCaption({
1639
1652
  }
1640
1653
 
1641
1654
  // src/components/tabs.tsx
1642
- import "react";
1655
+ import * as React18 from "react";
1643
1656
  import { cva as cva4 } from "class-variance-authority";
1644
1657
  import { Tabs as TabsPrimitive } from "radix-ui";
1645
- import { motion as motion2 } from "framer-motion";
1646
- import { jsx as jsx20 } from "react/jsx-runtime";
1647
- var TABS_LAYOUT_SPRING = {
1648
- type: "spring",
1649
- stiffness: 720,
1650
- damping: 46,
1651
- mass: 0.48
1652
- };
1653
- function Tabs({
1654
- className,
1655
- orientation = "horizontal",
1656
- ...props
1657
- }) {
1658
- return /* @__PURE__ */ jsx20(
1658
+ import { motion as motion2, useReducedMotion } from "framer-motion";
1659
+ import { Fragment, jsx as jsx20, jsxs as jsxs6 } from "react/jsx-runtime";
1660
+ var TABS_LAYOUT_SPRING = { type: "spring", stiffness: 300, damping: 26, mass: 1 };
1661
+ var TabsContext = React18.createContext(null);
1662
+ var ListVariantContext = React18.createContext("default");
1663
+ function Tabs({ className, orientation = "horizontal", value, defaultValue, onValueChange, ...props }) {
1664
+ const [localValue, setLocalValue] = React18.useState(defaultValue);
1665
+ const id = React18.useId();
1666
+ const activeValue = value ?? localValue;
1667
+ const context = React18.useMemo(() => ({ value: activeValue, id }), [activeValue, id]);
1668
+ return /* @__PURE__ */ jsx20(TabsContext.Provider, { value: context, children: /* @__PURE__ */ jsx20(
1659
1669
  TabsPrimitive.Root,
1660
1670
  {
1671
+ ...props,
1672
+ ...activeValue === void 0 ? {} : { value: activeValue },
1673
+ orientation,
1674
+ onValueChange: (next) => {
1675
+ if (value === void 0) setLocalValue(next);
1676
+ onValueChange?.(next);
1677
+ },
1661
1678
  "data-slot": "tabs",
1662
- "data-orientation": orientation,
1663
- className: cn(
1664
- "group/tabs flex gap-2 data-horizontal:flex-col",
1665
- className
1666
- ),
1667
- ...props
1668
- }
1669
- );
1670
- }
1671
- var tabsListVariants = cva4(
1672
- "group/tabs-list relative inline-flex w-fit items-center justify-center rounded-4xl p-[3px] text-muted-foreground group-data-horizontal/tabs:h-9 group-data-vertical/tabs:h-fit group-data-vertical/tabs:flex-col group-data-vertical/tabs:rounded-2xl data-[variant=line]:rounded-none",
1673
- {
1674
- variants: {
1675
- variant: {
1676
- default: "bg-muted/70 border border-black/4 shadow-[inset_0_1px_2px_rgba(0,0,0,0.06)] dark:bg-white/4 dark:border-white/4 dark:shadow-[inset_0_1px_3px_rgba(0,0,0,0.3)]",
1677
- line: "gap-1 bg-transparent"
1678
- }
1679
- },
1680
- defaultVariants: {
1681
- variant: "default"
1679
+ className: cn("coline-tabs", className)
1682
1680
  }
1683
- }
1684
- );
1685
- function TabsList({
1686
- className,
1687
- variant = "default",
1688
- ...props
1689
- }) {
1690
- return /* @__PURE__ */ jsx20(
1691
- TabsPrimitive.List,
1692
- {
1693
- "data-slot": "tabs-list",
1694
- "data-variant": variant,
1695
- className: cn(tabsListVariants({ variant }), className),
1696
- ...props
1697
- }
1698
- );
1681
+ ) });
1699
1682
  }
1700
- function TabsTrigger({
1701
- className,
1702
- ...props
1703
- }) {
1704
- return /* @__PURE__ */ jsx20(
1705
- TabsPrimitive.Trigger,
1706
- {
1707
- "data-slot": "tabs-trigger",
1708
- className: cn(
1709
- "relative z-1 inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-xl border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap text-foreground/50 transition-[color,background-color,border-color] duration-150 ease-[cubic-bezier(0.23,1,0.32,1)] group-data-vertical/tabs:w-full group-data-vertical/tabs:justify-start group-data-vertical/tabs:px-2.5 group-data-vertical/tabs:py-1.5 hover:text-foreground/80 focus-visible:border-ring disabled:pointer-events-none disabled:opacity-50 dark:text-muted-foreground/70 dark:hover:text-muted-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
1710
- "group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-active:bg-transparent group-data-[variant=line]/tabs-list:data-active:shadow-none dark:group-data-[variant=line]/tabs-list:data-active:border-transparent dark:group-data-[variant=line]/tabs-list:data-active:bg-transparent",
1711
- "data-active:text-foreground data-active:hover:text-foreground dark:data-active:text-foreground dark:data-active:hover:text-foreground",
1712
- "after:absolute after:bg-foreground after:opacity-0 after:transition-opacity group-data-horizontal/tabs:after:inset-x-0 group-data-horizontal/tabs:after:-bottom-1.25 group-data-horizontal/tabs:after:h-0.5 group-data-vertical/tabs:after:inset-y-0 group-data-vertical/tabs:after:-right-1 group-data-vertical/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-active:after:opacity-100",
1713
- className
1714
- ),
1715
- ...props
1716
- }
1717
- );
1683
+ var tabsListVariants = cva4("coline-tabs-list", {
1684
+ variants: { variant: { default: "coline-tabs-raised", line: "coline-tabs-line" } },
1685
+ defaultVariants: { variant: "default" }
1686
+ });
1687
+ function TabsList({ className, variant = "default", ...props }) {
1688
+ return /* @__PURE__ */ jsx20(ListVariantContext.Provider, { value: variant ?? "default", children: /* @__PURE__ */ jsx20(TabsPrimitive.List, { ...props, "data-slot": "tabs-list", "data-variant": variant, className: cn(tabsListVariants({ variant }), className) }) });
1689
+ }
1690
+ function hasIndicator(children) {
1691
+ return React18.Children.toArray(children).some((child) => React18.isValidElement(child) && (child.type === TabsIndicator || hasIndicator(child.props.children)));
1692
+ }
1693
+ function TabsTrigger({ className, children, value, asChild = false, ...props }) {
1694
+ const tabs = React18.useContext(TabsContext);
1695
+ const variant = React18.useContext(ListVariantContext);
1696
+ const indicator = tabs?.value === value && variant === "default" && !hasIndicator(children) ? /* @__PURE__ */ jsx20(TabsIndicator, {}) : null;
1697
+ const content = asChild && React18.isValidElement(children) ? React18.cloneElement(children, void 0, indicator, children.props.children) : /* @__PURE__ */ jsxs6(Fragment, { children: [
1698
+ indicator,
1699
+ children
1700
+ ] });
1701
+ return /* @__PURE__ */ jsx20(TabsPrimitive.Trigger, { ...props, value, asChild, "data-slot": "tabs-trigger", className: cn("coline-tabs-trigger", className), children: content });
1718
1702
  }
1719
- function TabsIndicator({
1720
- className,
1721
- layoutId = "tabs-indicator"
1722
- }) {
1703
+ function TabsIndicator({ className, layoutId = "selection" }) {
1704
+ const tabs = React18.useContext(TabsContext);
1705
+ const fallbackId = React18.useId();
1706
+ const reducedMotion = useReducedMotion();
1723
1707
  return /* @__PURE__ */ jsx20(
1724
1708
  motion2.div,
1725
1709
  {
1726
- layout: "position",
1727
- layoutId,
1728
- className: cn(
1729
- "absolute inset-0 z-[-1] rounded-xl bg-background border border-black/6 shadow-[0_1px_3px_0_rgba(0,0,0,0.08)] dark:bg-white/7 dark:border-white/6 dark:shadow-[0_1px_3px_0_rgba(0,0,0,0.3),inset_0_1px_0_0_rgba(255,255,255,0.04)]",
1730
- className
1731
- ),
1732
- transition: TABS_LAYOUT_SPRING
1710
+ "aria-hidden": "true",
1711
+ "data-slot": "tabs-indicator",
1712
+ layout: true,
1713
+ layoutId: `${tabs?.id ?? fallbackId}-${layoutId}`,
1714
+ initial: false,
1715
+ className: cn("coline-tabs-indicator", className),
1716
+ transition: reducedMotion ? { duration: 0 } : TABS_LAYOUT_SPRING
1733
1717
  }
1734
1718
  );
1735
1719
  }
1736
- function TabsContent({
1737
- className,
1738
- ...props
1739
- }) {
1740
- return /* @__PURE__ */ jsx20(
1741
- TabsPrimitive.Content,
1742
- {
1743
- "data-slot": "tabs-content",
1744
- className: cn(
1745
- "flex-1 text-sm outline-none animate-in fade-in-0 slide-in-from-bottom-0.5 duration-100 ease-out",
1746
- className
1747
- ),
1748
- ...props
1749
- }
1750
- );
1720
+ function TabsContent({ className, ...props }) {
1721
+ return /* @__PURE__ */ jsx20(TabsPrimitive.Content, { ...props, "data-slot": "tabs-content", className: cn("coline-tabs-content", className) });
1751
1722
  }
1752
1723
 
1753
1724
  // src/components/textarea.tsx
@@ -1857,8 +1828,247 @@ function TooltipContent({
1857
1828
  }
1858
1829
  ) });
1859
1830
  }
1831
+
1832
+ // src/live-collection.ts
1833
+ import * as React22 from "react";
1834
+ import {
1835
+ createLiveCollection
1836
+ } from "@colineapp/sdk/v2";
1837
+ function useLiveCollection(name, query, options) {
1838
+ const coline = useColine();
1839
+ const context = useColineContext();
1840
+ const key = JSON.stringify({
1841
+ query,
1842
+ options: { actorUserId: context.actor?.userId, installId: context.app.installId, ...options }
1843
+ });
1844
+ const live = React22.useMemo(() => {
1845
+ const input = JSON.parse(key);
1846
+ return createLiveCollection(coline, name, input.query, input.options);
1847
+ }, [coline, name, key]);
1848
+ React22.useEffect(() => {
1849
+ void live.start();
1850
+ return () => live.stop();
1851
+ }, [live]);
1852
+ const snapshot = React22.useSyncExternalStore(live.subscribe, live.getSnapshot, live.getSnapshot);
1853
+ return {
1854
+ ...snapshot,
1855
+ insert: live.insert,
1856
+ update: live.update,
1857
+ delete: live.delete,
1858
+ setAccess: live.setAccess,
1859
+ refresh: live.refresh
1860
+ };
1861
+ }
1862
+
1863
+ // src/patterns/workspace.tsx
1864
+ import * as React23 from "react";
1865
+ import { Fragment as Fragment2, jsx as jsx24, jsxs as jsxs7 } from "react/jsx-runtime";
1866
+ function AppPage({
1867
+ title,
1868
+ description,
1869
+ eyebrow,
1870
+ actions,
1871
+ children,
1872
+ width = "wide",
1873
+ className
1874
+ }) {
1875
+ return /* @__PURE__ */ jsxs7("main", { className: cn("coline-page", className), "data-width": width, children: [
1876
+ /* @__PURE__ */ jsxs7("header", { className: "coline-page-header", children: [
1877
+ /* @__PURE__ */ jsxs7("div", { className: "coline-page-heading", children: [
1878
+ eyebrow && /* @__PURE__ */ jsx24("div", { className: "coline-eyebrow", children: eyebrow }),
1879
+ /* @__PURE__ */ jsx24("h1", { children: title }),
1880
+ description && /* @__PURE__ */ jsx24("p", { className: "coline-page-description", children: description })
1881
+ ] }),
1882
+ actions && /* @__PURE__ */ jsx24("div", { className: "coline-page-actions", children: actions })
1883
+ ] }),
1884
+ children
1885
+ ] });
1886
+ }
1887
+ function PageToolbar({
1888
+ children,
1889
+ label = "View controls",
1890
+ className
1891
+ }) {
1892
+ return /* @__PURE__ */ jsx24("div", { className: cn("coline-toolbar", className), role: "group", "aria-label": label, children });
1893
+ }
1894
+ function EmptyState({
1895
+ title,
1896
+ description,
1897
+ action,
1898
+ icon
1899
+ }) {
1900
+ return /* @__PURE__ */ jsxs7("section", { className: "coline-empty", children: [
1901
+ icon && /* @__PURE__ */ jsx24("div", { className: "coline-empty-icon", "aria-hidden": "true", children: icon }),
1902
+ /* @__PURE__ */ jsx24("h2", { children: title }),
1903
+ description && /* @__PURE__ */ jsx24("p", { children: description }),
1904
+ action && /* @__PURE__ */ jsx24("div", { children: action })
1905
+ ] });
1906
+ }
1907
+ function AppErrorState({ message, onRetry }) {
1908
+ return /* @__PURE__ */ jsxs7("section", { className: "coline-error", role: "alert", children: [
1909
+ /* @__PURE__ */ jsxs7("div", { children: [
1910
+ /* @__PURE__ */ jsx24("h2", { children: "Something went wrong" }),
1911
+ /* @__PURE__ */ jsx24("p", { children: message })
1912
+ ] }),
1913
+ onRetry && /* @__PURE__ */ jsx24(Button, { variant: "outline", onClick: onRetry, children: "Try again" })
1914
+ ] });
1915
+ }
1916
+ function AppLoadingState({
1917
+ label = "Loading",
1918
+ rows = 5
1919
+ }) {
1920
+ return /* @__PURE__ */ jsxs7("div", { className: "coline-loading", role: "status", "aria-label": label, children: [
1921
+ Array.from({ length: Math.max(1, Math.min(rows, 12)) }, (_, i) => /* @__PURE__ */ jsx24("div", { style: { width: `${92 - i % 3 * 14}%` } }, i)),
1922
+ /* @__PURE__ */ jsx24("span", { className: "coline-sr-only", children: label })
1923
+ ] });
1924
+ }
1925
+ function StatusBadge({
1926
+ children,
1927
+ tone = "neutral"
1928
+ }) {
1929
+ return /* @__PURE__ */ jsxs7("span", { className: "coline-status", "data-tone": tone, children: [
1930
+ /* @__PURE__ */ jsx24("span", { "aria-hidden": "true" }),
1931
+ children
1932
+ ] });
1933
+ }
1934
+ function SplitView({
1935
+ list,
1936
+ detail,
1937
+ label = "Details"
1938
+ }) {
1939
+ return /* @__PURE__ */ jsxs7("div", { className: "coline-split", "data-open": Boolean(detail), children: [
1940
+ /* @__PURE__ */ jsx24("section", { className: "coline-split-list", children: list }),
1941
+ detail && /* @__PURE__ */ jsx24("aside", { className: "coline-split-detail", "aria-label": label, children: detail })
1942
+ ] });
1943
+ }
1944
+ function DetailPanel({
1945
+ title,
1946
+ subtitle,
1947
+ onClose,
1948
+ children,
1949
+ actions
1950
+ }) {
1951
+ return /* @__PURE__ */ jsxs7("section", { className: "coline-detail", children: [
1952
+ /* @__PURE__ */ jsxs7("header", { children: [
1953
+ /* @__PURE__ */ jsxs7("div", { children: [
1954
+ subtitle && /* @__PURE__ */ jsx24("div", { className: "coline-eyebrow", children: subtitle }),
1955
+ /* @__PURE__ */ jsx24("h2", { children: title })
1956
+ ] }),
1957
+ onClose && /* @__PURE__ */ jsx24(Button, { variant: "ghost", size: "sm", onClick: onClose, "aria-label": "Close details", children: "Close" })
1958
+ ] }),
1959
+ /* @__PURE__ */ jsx24("div", { className: "coline-detail-body", children }),
1960
+ actions && /* @__PURE__ */ jsx24("footer", { children: actions })
1961
+ ] });
1962
+ }
1963
+ function RecordTable({
1964
+ records,
1965
+ columns,
1966
+ rowKey,
1967
+ onOpen,
1968
+ label = "Records",
1969
+ empty
1970
+ }) {
1971
+ if (!records.length)
1972
+ return /* @__PURE__ */ jsx24(Fragment2, { children: empty ?? /* @__PURE__ */ jsx24(EmptyState, { title: "No results", description: "Try changing your filters." }) });
1973
+ return /* @__PURE__ */ jsx24("div", { className: "coline-table-scroll", children: /* @__PURE__ */ jsxs7("table", { className: "coline-record-table", "aria-label": label, children: [
1974
+ /* @__PURE__ */ jsx24("thead", { children: /* @__PURE__ */ jsx24("tr", { children: columns.map((column) => /* @__PURE__ */ jsx24(
1975
+ "th",
1976
+ {
1977
+ scope: "col",
1978
+ "data-secondary": column.secondary || void 0,
1979
+ "data-align": column.align,
1980
+ children: column.label
1981
+ },
1982
+ column.key
1983
+ )) }) }),
1984
+ /* @__PURE__ */ jsx24("tbody", { children: records.map((record) => /* @__PURE__ */ jsx24("tr", { children: columns.map((column, i) => /* @__PURE__ */ jsx24(
1985
+ "td",
1986
+ {
1987
+ "data-secondary": column.secondary || void 0,
1988
+ "data-align": column.align,
1989
+ children: i === 0 && onOpen ? /* @__PURE__ */ jsx24(
1990
+ "button",
1991
+ {
1992
+ type: "button",
1993
+ className: "coline-row-open",
1994
+ onClick: () => onOpen(record),
1995
+ children: column.render(record)
1996
+ }
1997
+ ) : column.render(record)
1998
+ },
1999
+ column.key
2000
+ )) }, rowKey(record))) })
2001
+ ] }) });
2002
+ }
2003
+ function Board({
2004
+ children,
2005
+ label = "Board"
2006
+ }) {
2007
+ return /* @__PURE__ */ jsx24("div", { className: "coline-board", role: "region", "aria-label": label, tabIndex: 0, children });
2008
+ }
2009
+ function BoardColumn({
2010
+ title,
2011
+ count,
2012
+ children,
2013
+ action
2014
+ }) {
2015
+ return /* @__PURE__ */ jsxs7("section", { className: "coline-board-column", children: [
2016
+ /* @__PURE__ */ jsxs7("header", { children: [
2017
+ /* @__PURE__ */ jsx24("h2", { children: title }),
2018
+ count !== void 0 && /* @__PURE__ */ jsx24("span", { className: "coline-count", children: count }),
2019
+ action
2020
+ ] }),
2021
+ /* @__PURE__ */ jsx24("div", { className: "coline-board-items", children })
2022
+ ] });
2023
+ }
2024
+ function BoardCard({
2025
+ title,
2026
+ children,
2027
+ footer,
2028
+ onOpen
2029
+ }) {
2030
+ return /* @__PURE__ */ jsxs7("article", { className: "coline-board-card", children: [
2031
+ /* @__PURE__ */ jsx24("h3", { children: onOpen ? /* @__PURE__ */ jsx24("button", { type: "button", className: "coline-row-open", onClick: onOpen, children: title }) : title }),
2032
+ children && /* @__PURE__ */ jsx24("div", { className: "coline-board-card-body", children }),
2033
+ footer && /* @__PURE__ */ jsx24("footer", { children: footer })
2034
+ ] });
2035
+ }
2036
+ function SettingsSection({
2037
+ title,
2038
+ description,
2039
+ children
2040
+ }) {
2041
+ const id = React23.useId();
2042
+ return /* @__PURE__ */ jsxs7("section", { className: "coline-settings-section", "aria-labelledby": id, children: [
2043
+ /* @__PURE__ */ jsxs7("div", { children: [
2044
+ /* @__PURE__ */ jsx24("h2", { id, children: title }),
2045
+ description && /* @__PURE__ */ jsx24("p", { children: description })
2046
+ ] }),
2047
+ /* @__PURE__ */ jsx24("div", { className: "coline-settings-fields", children })
2048
+ ] });
2049
+ }
2050
+
2051
+ // src/patterns/filter-menu.tsx
2052
+ import * as React24 from "react";
2053
+ import { IconChevronDown as IconChevronDown2 } from "@tabler/icons-react";
2054
+ import { jsx as jsx25, jsxs as jsxs8 } from "react/jsx-runtime";
2055
+ var FilterMenu = React24.forwardRef(function FilterMenu2({ value, options, onValueChange, className, disabled, "aria-label": label }, ref) {
2056
+ return /* @__PURE__ */ jsxs8(DropdownMenu, { children: [
2057
+ /* @__PURE__ */ jsx25(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs8(Button, { ref, variant: "outline", disabled, "aria-label": label, className: cn("coline-filter-menu", className), children: [
2058
+ /* @__PURE__ */ jsx25("span", { children: options.find((option) => option.value === value)?.label ?? label }),
2059
+ /* @__PURE__ */ jsx25(IconChevronDown2, { "aria-hidden": "true" })
2060
+ ] }) }),
2061
+ /* @__PURE__ */ jsx25(DropdownMenuContent, { children: /* @__PURE__ */ jsx25(DropdownMenuRadioGroup, { "aria-label": label, value, onValueChange, children: options.map((option) => /* @__PURE__ */ jsx25(DropdownMenuRadioItem, { value: option.value, disabled: option.disabled ?? false, children: option.label }, option.value)) }) })
2062
+ ] });
2063
+ });
1860
2064
  export {
2065
+ AppErrorState,
2066
+ AppLoadingState,
2067
+ AppPage,
1861
2068
  Badge,
2069
+ Board,
2070
+ BoardCard,
2071
+ BoardColumn,
1862
2072
  Button,
1863
2073
  Card,
1864
2074
  CardAction,
@@ -1869,6 +2079,7 @@ export {
1869
2079
  CardTitle,
1870
2080
  Checkbox,
1871
2081
  ColineAppProvider,
2082
+ DetailPanel,
1872
2083
  Dialog,
1873
2084
  DialogClose,
1874
2085
  DialogContent,
@@ -1894,6 +2105,7 @@ export {
1894
2105
  DropdownMenuSubContent,
1895
2106
  DropdownMenuSubTrigger,
1896
2107
  DropdownMenuTrigger,
2108
+ EmptyState,
1897
2109
  Field,
1898
2110
  FieldContent,
1899
2111
  FieldDescription,
@@ -1904,8 +2116,10 @@ export {
1904
2116
  FieldSeparator,
1905
2117
  FieldSet,
1906
2118
  FieldTitle,
2119
+ FilterMenu,
1907
2120
  Input,
1908
2121
  Label,
2122
+ PageToolbar,
1909
2123
  Popover,
1910
2124
  PopoverAnchor,
1911
2125
  PopoverContent,
@@ -1914,6 +2128,7 @@ export {
1914
2128
  PopoverTitle,
1915
2129
  PopoverTrigger,
1916
2130
  Progress,
2131
+ RecordTable,
1917
2132
  Select,
1918
2133
  SelectContent,
1919
2134
  SelectGroup,
@@ -1925,8 +2140,11 @@ export {
1925
2140
  SelectTrigger,
1926
2141
  SelectValue,
1927
2142
  Separator,
2143
+ SettingsSection,
1928
2144
  Skeleton,
1929
2145
  Slider,
2146
+ SplitView,
2147
+ StatusBadge,
1930
2148
  Switch,
1931
2149
  TABS_LAYOUT_SPRING,
1932
2150
  Table,
@@ -1956,6 +2174,7 @@ export {
1956
2174
  useColine,
1957
2175
  useColineContext,
1958
2176
  useColineQuery,
1959
- useColorScheme
2177
+ useColorScheme,
2178
+ useLiveCollection
1960
2179
  };
1961
2180
  //# sourceMappingURL=index.js.map