@stackframe/dashboard-ui-components 2.8.83 → 2.8.85
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/components/analytics-chart/analytics-chart-pie.d.ts +67 -0
- package/dist/components/analytics-chart/analytics-chart-pie.d.ts.map +1 -0
- package/dist/components/analytics-chart/analytics-chart-pie.js +253 -0
- package/dist/components/analytics-chart/analytics-chart-pie.js.map +1 -0
- package/dist/components/analytics-chart/analytics-chart.d.ts +554 -0
- package/dist/components/analytics-chart/analytics-chart.d.ts.map +1 -0
- package/dist/components/analytics-chart/analytics-chart.js +1021 -0
- package/dist/components/analytics-chart/analytics-chart.js.map +1 -0
- package/dist/components/analytics-chart/default-analytics-chart-tooltip.d.ts +66 -0
- package/dist/components/analytics-chart/default-analytics-chart-tooltip.d.ts.map +1 -0
- package/dist/components/analytics-chart/default-analytics-chart-tooltip.js +179 -0
- package/dist/components/analytics-chart/default-analytics-chart-tooltip.js.map +1 -0
- package/dist/components/analytics-chart/format.d.ts +13 -0
- package/dist/components/analytics-chart/format.d.ts.map +1 -0
- package/dist/components/analytics-chart/format.js +138 -0
- package/dist/components/analytics-chart/format.js.map +1 -0
- package/dist/components/analytics-chart/index.d.ts +8 -0
- package/dist/components/analytics-chart/index.js +184 -0
- package/dist/components/analytics-chart/palette.d.ts +15 -0
- package/dist/components/analytics-chart/palette.d.ts.map +1 -0
- package/dist/components/analytics-chart/palette.js +60 -0
- package/dist/components/analytics-chart/palette.js.map +1 -0
- package/dist/components/analytics-chart/render-data-series.d.ts +28 -0
- package/dist/components/analytics-chart/render-data-series.d.ts.map +1 -0
- package/dist/components/analytics-chart/render-data-series.js +109 -0
- package/dist/components/analytics-chart/render-data-series.js.map +1 -0
- package/dist/components/analytics-chart/state.d.ts +54 -0
- package/dist/components/analytics-chart/state.d.ts.map +1 -0
- package/dist/components/analytics-chart/state.js +142 -0
- package/dist/components/analytics-chart/state.js.map +1 -0
- package/dist/components/analytics-chart/strings.d.ts +33 -0
- package/dist/components/analytics-chart/strings.d.ts.map +1 -0
- package/dist/components/analytics-chart/strings.js +37 -0
- package/dist/components/analytics-chart/strings.js.map +1 -0
- package/dist/components/analytics-chart/types.d.ts +157 -0
- package/dist/components/analytics-chart/types.d.ts.map +1 -0
- package/dist/components/analytics-chart/types.js +21 -0
- package/dist/components/analytics-chart/types.js.map +1 -0
- package/dist/components/badge.d.ts +16 -0
- package/dist/components/badge.d.ts.map +1 -1
- package/dist/components/badge.js +16 -0
- package/dist/components/badge.js.map +1 -1
- package/dist/components/button.d.ts +19 -5
- package/dist/components/button.d.ts.map +1 -1
- package/dist/components/button.js +14 -0
- package/dist/components/button.js.map +1 -1
- package/dist/components/card.d.ts +28 -0
- package/dist/components/card.d.ts.map +1 -1
- package/dist/components/card.js +28 -0
- package/dist/components/card.js.map +1 -1
- package/dist/components/chart-card.d.ts +29 -0
- package/dist/components/chart-card.d.ts.map +1 -1
- package/dist/components/chart-card.js +29 -0
- package/dist/components/chart-card.js.map +1 -1
- package/dist/components/chart-legend.d.ts +2 -3
- package/dist/components/chart-legend.d.ts.map +1 -1
- package/dist/components/chart-legend.js +0 -4
- package/dist/components/chart-legend.js.map +1 -1
- package/dist/components/data-grid/data-grid-sizing.d.ts +11 -0
- package/dist/components/data-grid/data-grid-sizing.d.ts.map +1 -0
- package/dist/components/data-grid/data-grid-sizing.js +34 -0
- package/dist/components/data-grid/data-grid-sizing.js.map +1 -0
- package/dist/components/data-grid/data-grid-toolbar.d.ts +31 -0
- package/dist/components/data-grid/data-grid-toolbar.d.ts.map +1 -0
- package/dist/components/data-grid/data-grid-toolbar.js +226 -0
- package/dist/components/data-grid/data-grid-toolbar.js.map +1 -0
- package/dist/components/data-grid/data-grid.d.ts +233 -0
- package/dist/components/data-grid/data-grid.d.ts.map +1 -0
- package/dist/components/data-grid/data-grid.js +871 -0
- package/dist/components/data-grid/data-grid.js.map +1 -0
- package/dist/components/data-grid/index.d.ts +7 -0
- package/dist/components/data-grid/index.js +176 -0
- package/dist/components/data-grid/state.d.ts +91 -0
- package/dist/components/data-grid/state.d.ts.map +1 -0
- package/dist/components/data-grid/state.js +329 -0
- package/dist/components/data-grid/state.js.map +1 -0
- package/dist/components/data-grid/strings.d.ts +8 -0
- package/dist/components/data-grid/strings.d.ts.map +1 -0
- package/dist/components/data-grid/strings.js +42 -0
- package/dist/components/data-grid/strings.js.map +1 -0
- package/dist/components/data-grid/types.d.ts +242 -0
- package/dist/components/data-grid/types.d.ts.map +1 -0
- package/dist/components/data-grid/types.js +0 -0
- package/dist/components/data-grid/use-data-source.d.ts +79 -0
- package/dist/components/data-grid/use-data-source.d.ts.map +1 -0
- package/dist/components/data-grid/use-data-source.js +236 -0
- package/dist/components/data-grid/use-data-source.js.map +1 -0
- package/dist/components/empty-state.d.ts +16 -0
- package/dist/components/empty-state.d.ts.map +1 -1
- package/dist/components/empty-state.js +16 -0
- package/dist/components/empty-state.js.map +1 -1
- package/dist/components/metric-card.d.ts +24 -0
- package/dist/components/metric-card.d.ts.map +1 -1
- package/dist/components/metric-card.js +24 -0
- package/dist/components/metric-card.js.map +1 -1
- package/dist/components/progress-bar.d.ts +10 -0
- package/dist/components/progress-bar.d.ts.map +1 -1
- package/dist/components/progress-bar.js +10 -0
- package/dist/components/progress-bar.js.map +1 -1
- package/dist/components/separator.d.ts +9 -0
- package/dist/components/separator.d.ts.map +1 -1
- package/dist/components/separator.js +9 -0
- package/dist/components/separator.js.map +1 -1
- package/dist/components/skeleton.d.ts +12 -0
- package/dist/components/skeleton.d.ts.map +1 -1
- package/dist/components/skeleton.js +12 -0
- package/dist/components/skeleton.js.map +1 -1
- package/dist/components/table.d.ts +25 -0
- package/dist/components/table.d.ts.map +1 -1
- package/dist/components/table.js +25 -0
- package/dist/components/table.js.map +1 -1
- package/dist/dashboard-ui-components.global.js +8607 -2902
- package/dist/dashboard-ui-components.global.js.map +4 -4
- package/dist/esm/components/analytics-chart/analytics-chart-pie.d.ts +67 -0
- package/dist/esm/components/analytics-chart/analytics-chart-pie.d.ts.map +1 -0
- package/dist/esm/components/analytics-chart/analytics-chart-pie.js +251 -0
- package/dist/esm/components/analytics-chart/analytics-chart-pie.js.map +1 -0
- package/dist/esm/components/analytics-chart/analytics-chart.d.ts +554 -0
- package/dist/esm/components/analytics-chart/analytics-chart.d.ts.map +1 -0
- package/dist/esm/components/analytics-chart/analytics-chart.js +1019 -0
- package/dist/esm/components/analytics-chart/analytics-chart.js.map +1 -0
- package/dist/esm/components/analytics-chart/default-analytics-chart-tooltip.d.ts +66 -0
- package/dist/esm/components/analytics-chart/default-analytics-chart-tooltip.d.ts.map +1 -0
- package/dist/esm/components/analytics-chart/default-analytics-chart-tooltip.js +176 -0
- package/dist/esm/components/analytics-chart/default-analytics-chart-tooltip.js.map +1 -0
- package/dist/esm/components/analytics-chart/format.d.ts +13 -0
- package/dist/esm/components/analytics-chart/format.d.ts.map +1 -0
- package/dist/esm/components/analytics-chart/format.js +133 -0
- package/dist/esm/components/analytics-chart/format.js.map +1 -0
- package/dist/esm/components/analytics-chart/index.d.ts +8 -0
- package/dist/esm/components/analytics-chart/index.js +9 -0
- package/dist/esm/components/analytics-chart/palette.d.ts +15 -0
- package/dist/esm/components/analytics-chart/palette.d.ts.map +1 -0
- package/dist/esm/components/analytics-chart/palette.js +55 -0
- package/dist/esm/components/analytics-chart/palette.js.map +1 -0
- package/dist/esm/components/analytics-chart/render-data-series.d.ts +28 -0
- package/dist/esm/components/analytics-chart/render-data-series.d.ts.map +1 -0
- package/dist/esm/components/analytics-chart/render-data-series.js +107 -0
- package/dist/esm/components/analytics-chart/render-data-series.js.map +1 -0
- package/dist/esm/components/analytics-chart/state.d.ts +54 -0
- package/dist/esm/components/analytics-chart/state.d.ts.map +1 -0
- package/dist/esm/components/analytics-chart/state.js +126 -0
- package/dist/esm/components/analytics-chart/state.js.map +1 -0
- package/dist/esm/components/analytics-chart/strings.d.ts +33 -0
- package/dist/esm/components/analytics-chart/strings.d.ts.map +1 -0
- package/dist/esm/components/analytics-chart/strings.js +34 -0
- package/dist/esm/components/analytics-chart/strings.js.map +1 -0
- package/dist/esm/components/analytics-chart/types.d.ts +157 -0
- package/dist/esm/components/analytics-chart/types.d.ts.map +1 -0
- package/dist/esm/components/analytics-chart/types.js +18 -0
- package/dist/esm/components/analytics-chart/types.js.map +1 -0
- package/dist/esm/components/badge.d.ts +16 -0
- package/dist/esm/components/badge.d.ts.map +1 -1
- package/dist/esm/components/badge.js +16 -0
- package/dist/esm/components/badge.js.map +1 -1
- package/dist/esm/components/button.d.ts +18 -4
- package/dist/esm/components/button.d.ts.map +1 -1
- package/dist/esm/components/button.js +14 -0
- package/dist/esm/components/button.js.map +1 -1
- package/dist/esm/components/card.d.ts +28 -0
- package/dist/esm/components/card.d.ts.map +1 -1
- package/dist/esm/components/card.js +28 -0
- package/dist/esm/components/card.js.map +1 -1
- package/dist/esm/components/chart-card.d.ts +29 -0
- package/dist/esm/components/chart-card.d.ts.map +1 -1
- package/dist/esm/components/chart-card.js +29 -0
- package/dist/esm/components/chart-card.js.map +1 -1
- package/dist/esm/components/chart-legend.d.ts +2 -3
- package/dist/esm/components/chart-legend.d.ts.map +1 -1
- package/dist/esm/components/chart-legend.js +1 -3
- package/dist/esm/components/chart-legend.js.map +1 -1
- package/dist/esm/components/data-grid/data-grid-sizing.d.ts +11 -0
- package/dist/esm/components/data-grid/data-grid-sizing.d.ts.map +1 -0
- package/dist/esm/components/data-grid/data-grid-sizing.js +29 -0
- package/dist/esm/components/data-grid/data-grid-sizing.js.map +1 -0
- package/dist/esm/components/data-grid/data-grid-toolbar.d.ts +31 -0
- package/dist/esm/components/data-grid/data-grid-toolbar.d.ts.map +1 -0
- package/dist/esm/components/data-grid/data-grid-toolbar.js +223 -0
- package/dist/esm/components/data-grid/data-grid-toolbar.js.map +1 -0
- package/dist/esm/components/data-grid/data-grid.d.ts +233 -0
- package/dist/esm/components/data-grid/data-grid.d.ts.map +1 -0
- package/dist/esm/components/data-grid/data-grid.js +868 -0
- package/dist/esm/components/data-grid/data-grid.js.map +1 -0
- package/dist/esm/components/data-grid/index.d.ts +7 -0
- package/dist/esm/components/data-grid/index.js +7 -0
- package/dist/esm/components/data-grid/state.d.ts +91 -0
- package/dist/esm/components/data-grid/state.d.ts.map +1 -0
- package/dist/esm/components/data-grid/state.js +305 -0
- package/dist/esm/components/data-grid/state.js.map +1 -0
- package/dist/esm/components/data-grid/strings.d.ts +8 -0
- package/dist/esm/components/data-grid/strings.d.ts.map +1 -0
- package/dist/esm/components/data-grid/strings.js +39 -0
- package/dist/esm/components/data-grid/strings.js.map +1 -0
- package/dist/esm/components/data-grid/types.d.ts +242 -0
- package/dist/esm/components/data-grid/types.d.ts.map +1 -0
- package/dist/esm/components/data-grid/types.js +1 -0
- package/dist/esm/components/data-grid/use-data-source.d.ts +79 -0
- package/dist/esm/components/data-grid/use-data-source.d.ts.map +1 -0
- package/dist/esm/components/data-grid/use-data-source.js +234 -0
- package/dist/esm/components/data-grid/use-data-source.js.map +1 -0
- package/dist/esm/components/empty-state.d.ts +16 -0
- package/dist/esm/components/empty-state.d.ts.map +1 -1
- package/dist/esm/components/empty-state.js +16 -0
- package/dist/esm/components/empty-state.js.map +1 -1
- package/dist/esm/components/metric-card.d.ts +24 -0
- package/dist/esm/components/metric-card.d.ts.map +1 -1
- package/dist/esm/components/metric-card.js +24 -0
- package/dist/esm/components/metric-card.js.map +1 -1
- package/dist/esm/components/progress-bar.d.ts +10 -0
- package/dist/esm/components/progress-bar.d.ts.map +1 -1
- package/dist/esm/components/progress-bar.js +10 -0
- package/dist/esm/components/progress-bar.js.map +1 -1
- package/dist/esm/components/separator.d.ts +9 -0
- package/dist/esm/components/separator.d.ts.map +1 -1
- package/dist/esm/components/separator.js +9 -0
- package/dist/esm/components/separator.js.map +1 -1
- package/dist/esm/components/skeleton.d.ts +12 -0
- package/dist/esm/components/skeleton.d.ts.map +1 -1
- package/dist/esm/components/skeleton.js +12 -0
- package/dist/esm/components/skeleton.js.map +1 -1
- package/dist/esm/components/table.d.ts +25 -0
- package/dist/esm/components/table.d.ts.map +1 -1
- package/dist/esm/components/table.js +25 -0
- package/dist/esm/components/table.js.map +1 -1
- package/dist/esm/index.d.ts +4 -2
- package/dist/esm/index.js +6 -2
- package/dist/index.d.ts +15 -2
- package/dist/index.js +16 -7
- package/package.json +4 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"card.js","names":["React","Card"],"sources":["../../src/components/card.tsx"],"sourcesContent":["\"use client\";\n\nimport { Card } from \"@stackframe/stack-ui\";\nimport { cn } from \"@stackframe/stack-ui\";\nimport React from \"react\";\n\n// ─── Card nesting context ────────────────────────────────────────────────────\n// Components with a `glassmorphic` prop use this to auto-detect whether they\n// sit inside a DesignCard. When they do, glassmorphic defaults to `true`;\n// when they don't, it defaults to `false`.\n\nconst DesignCardNestingContext = React.createContext(false);\n\n/**\n * Returns `true` when the calling component is rendered inside a DesignCard.\n * Useful for deriving a glassmorphic default.\n */\nexport function useInsideDesignCard(): boolean {\n return React.useContext(DesignCardNestingContext);\n}\n\n/**\n * Resolve the effective glassmorphic value.\n * - If the caller passed an explicit boolean → honour it.\n * - Otherwise → fall back to whether we're inside a DesignCard.\n */\nexport function useGlassmorphicDefault(explicit: boolean | undefined): boolean {\n const insideCard = useInsideDesignCard();\n return explicit ?? insideCard;\n}\n\ntype DesignCardGradient = \"blue\" | \"cyan\" | \"purple\" | \"green\" | \"orange\" | \"default\";\n\nconst hoverTintClasses = new Map<DesignCardGradient, string>([\n [\"blue\", \"group-hover:bg-blue-500/[0.03]\"],\n [\"purple\", \"group-hover:bg-purple-500/[0.03]\"],\n [\"green\", \"group-hover:bg-emerald-500/[0.03]\"],\n [\"orange\", \"group-hover:bg-orange-500/[0.03]\"],\n [\"default\", \"group-hover:bg-slate-500/[0.02]\"],\n [\"cyan\", \"group-hover:bg-cyan-500/[0.03]\"],\n]);\n\nconst demoTintClasses = new Map<DesignCardGradient, string>([\n [\"blue\", \"group-hover/tint:bg-blue-500/[0.02]\"],\n [\"purple\", \"group-hover/tint:bg-purple-500/[0.02]\"],\n [\"green\", \"group-hover/tint:bg-emerald-500/[0.02]\"],\n [\"orange\", \"group-hover/tint:bg-orange-500/[0.02]\"],\n [\"default\", \"group-hover/tint:bg-slate-500/[0.015]\"],\n [\"cyan\", \"group-hover/tint:bg-cyan-500/[0.02]\"],\n]);\n\nconst bodyPaddingClass = \"p-5\";\n\n// ─── Discriminated props ──────────────────────────────────────────────────\n// - If title is given, icon is required.\n// - The layout is derived automatically:\n// title + subtitle → \"header\" (full header block with subtitle)\n// title only → \"compact\" (slim bar with border-b)\n// no title → \"bodyOnly\" (just the body)\n\ntype DesignCardBaseProps = {\n glassmorphic?: boolean,\n gradient?: DesignCardGradient,\n contentClassName?: string,\n} & Omit<React.ComponentProps<typeof Card>, \"title\">;\n\ntype WithTitleProps = {\n title: React.ReactNode,\n subtitle?: React.ReactNode,\n icon: React.ElementType,\n actions?: React.ReactNode,\n};\n\ntype WithoutTitleProps = {\n title?: never,\n subtitle?: never,\n icon?: never,\n actions?: never,\n};\n\nexport type DesignCardProps = DesignCardBaseProps & (WithTitleProps | WithoutTitleProps);\n\nexport function DesignCard({\n title,\n subtitle,\n icon: Icon,\n actions,\n glassmorphic: glassmorphicProp,\n gradient = \"default\",\n children,\n className,\n contentClassName,\n ...props\n}: DesignCardProps) {\n const glassmorphic = glassmorphicProp ?? true;\n const hoverTintClass = hoverTintClasses.get(gradient) ?? \"group-hover:bg-slate-500/[0.02]\";\n const hasContent = React.Children.count(children) > 0;\n\n // Derive layout from which props were provided\n const variant = title != null\n ? (subtitle != null ? \"header\" : \"compact\")\n : \"bodyOnly\";\n\n return (\n <DesignCardNestingContext.Provider value={true}>\n <Card\n className={cn(\n \"group relative rounded-2xl overflow-hidden\",\n glassmorphic && [\n \"bg-white/90 dark:bg-background/60 dark:backdrop-blur-xl border-0 transition-all duration-150 hover:transition-none\",\n \"ring-1 ring-black/[0.06] hover:ring-black/[0.1] dark:ring-white/[0.06] dark:hover:ring-white/[0.1]\",\n \"shadow-none\",\n ],\n glassmorphic && variant === \"bodyOnly\" && \"dark:bg-transparent dark:ring-0 dark:shadow-none\",\n className\n )}\n {...props}\n >\n {glassmorphic && (\n <>\n <div className={cn(\n \"absolute inset-0 bg-gradient-to-br from-foreground/[0.04] dark:from-foreground/[0.02] to-transparent pointer-events-none rounded-2xl\",\n variant === \"bodyOnly\" && \"dark:hidden\"\n )} />\n {variant !== \"bodyOnly\" && (\n <div\n className={cn(\n \"absolute inset-0 transition-colors duration-150 group-hover:transition-none pointer-events-none rounded-2xl\",\n hoverTintClass\n )}\n />\n )}\n </>\n )}\n <div className=\"relative\">\n {variant === \"header\" && (\n <div className={bodyPaddingClass}>\n <div className=\"flex items-start justify-between gap-4\">\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n {Icon && (\n <div className=\"p-1.5 rounded-lg bg-foreground/[0.06] dark:bg-foreground/[0.04]\">\n <Icon className=\"h-3.5 w-3.5 text-foreground/70 dark:text-muted-foreground\" />\n </div>\n )}\n <span className=\"text-xs font-semibold text-foreground uppercase tracking-wider\">\n {title}\n </span>\n </div>\n {subtitle && (\n <p className=\"text-sm text-muted-foreground mt-1\">\n {subtitle}\n </p>\n )}\n </div>\n {actions && (\n <div className=\"flex-shrink-0\">\n {actions}\n </div>\n )}\n </div>\n </div>\n )}\n {variant === \"compact\" && (\n <div className=\"p-5 flex items-center justify-between gap-4 border-b border-black/[0.12] dark:border-white/[0.06]\">\n <div className=\"flex items-center gap-2 min-w-0\">\n {Icon && (\n <div className=\"p-1.5 rounded-lg bg-foreground/[0.04]\">\n <Icon className=\"h-3.5 w-3.5 text-muted-foreground\" />\n </div>\n )}\n <span className=\"text-xs font-semibold text-foreground uppercase tracking-wider\">\n {title}\n </span>\n </div>\n {actions && (\n <div className=\"flex-shrink-0\">\n {actions}\n </div>\n )}\n </div>\n )}\n {hasContent && (\n <div\n className={cn(\n variant === \"header\" ? \"border-t border-black/[0.12] dark:border-white/[0.06]\" : \"\",\n variant === \"compact\" ? \"px-5 py-4\" : \"\",\n variant === \"bodyOnly\" || variant === \"header\" ? bodyPaddingClass : \"\",\n contentClassName\n )}\n >\n {children}\n </div>\n )}\n </div>\n </Card>\n </DesignCardNestingContext.Provider>\n );\n}\n\nexport type DesignCardTintProps = {\n gradient: DesignCardGradient,\n} & React.ComponentProps<\"div\">\n\nexport function DesignCardTint({\n gradient,\n className,\n children,\n ...props\n}: DesignCardTintProps) {\n const tintClass = demoTintClasses.get(gradient) ?? \"group-hover/tint:bg-slate-500/[0.015]\";\n\n return (\n <div\n className={cn(\n \"group/tint relative rounded-2xl bg-white/90 dark:bg-background/60 dark:backdrop-blur-xl transition-all duration-150 hover:transition-none\",\n \"ring-1 ring-black/[0.06] hover:ring-black/[0.1] dark:ring-white/[0.06] dark:hover:ring-white/[0.1]\",\n \"shadow-none overflow-hidden\",\n className\n )}\n {...props}\n >\n <div className=\"absolute inset-0 bg-gradient-to-br from-foreground/[0.04] dark:from-foreground/[0.02] to-transparent pointer-events-none rounded-2xl\" />\n <div\n className={cn(\n \"absolute inset-0 transition-colors duration-150 group-hover/tint:transition-none pointer-events-none rounded-2xl\",\n tintClass\n )}\n />\n <div className=\"relative\">\n {children}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;AAWA,MAAM,2BAA2BA,cAAM,cAAc,MAAM;;;;;AAM3D,SAAgB,sBAA+B;AAC7C,QAAOA,cAAM,WAAW,yBAAyB;;;;;;;AAQnD,SAAgB,uBAAuB,UAAwC;CAC7E,MAAM,aAAa,qBAAqB;AACxC,QAAO,YAAY;;AAKrB,MAAM,mBAAmB,IAAI,IAAgC;CAC3D,CAAC,QAAQ,iCAAiC;CAC1C,CAAC,UAAU,mCAAmC;CAC9C,CAAC,SAAS,oCAAoC;CAC9C,CAAC,UAAU,mCAAmC;CAC9C,CAAC,WAAW,kCAAkC;CAC9C,CAAC,QAAQ,iCAAiC;CAC3C,CAAC;AAEF,MAAM,kBAAkB,IAAI,IAAgC;CAC1D,CAAC,QAAQ,sCAAsC;CAC/C,CAAC,UAAU,wCAAwC;CACnD,CAAC,SAAS,yCAAyC;CACnD,CAAC,UAAU,wCAAwC;CACnD,CAAC,WAAW,wCAAwC;CACpD,CAAC,QAAQ,sCAAsC;CAChD,CAAC;AAEF,MAAM,mBAAmB;AA+BzB,SAAgB,WAAW,EACzB,OACA,UACA,MAAM,MACN,SACA,cAAc,kBACd,WAAW,WACX,UACA,WACA,kBACA,GAAG,SACe;CAClB,MAAM,eAAe,oBAAoB;CACzC,MAAM,iBAAiB,iBAAiB,IAAI,SAAS,IAAI;CACzD,MAAM,aAAaA,cAAM,SAAS,MAAM,SAAS,GAAG;CAGpD,MAAM,UAAU,SAAS,OACpB,YAAY,OAAO,WAAW,YAC/B;AAEJ,QACE,2CAAC,yBAAyB;EAAS,OAAO;YACxC,4CAACC;GACC,wCACE,8CACA,gBAAgB;IACd;IACA;IACA;IACD,EACD,gBAAgB,YAAY,cAAc,oDAC1C,UACD;GACD,GAAI;cAEH,gBACC,qFACE,2CAAC,SAAI,wCACH,wIACA,YAAY,cAAc,cAC3B,GAAI,EACJ,YAAY,cACX,2CAAC,SACC,wCACE,+GACA,eACD,GACD,IAEH,EAEL,4CAAC;IAAI,WAAU;;KACZ,YAAY,YACX,2CAAC;MAAI,WAAW;gBACd,4CAAC;OAAI,WAAU;kBACb,4CAAC;QAAI,WAAU;mBACb,4CAAC;SAAI,WAAU;oBACZ,QACC,2CAAC;UAAI,WAAU;oBACb,2CAAC,QAAK,WAAU,8DAA8D;WAC1E,EAER,2CAAC;UAAK,WAAU;oBACb;WACI;UACH,EACL,YACC,2CAAC;SAAE,WAAU;mBACV;UACC;SAEF,EACL,WACC,2CAAC;QAAI,WAAU;kBACZ;SACG;QAEJ;OACF;KAEP,YAAY,aACX,4CAAC;MAAI,WAAU;iBACb,4CAAC;OAAI,WAAU;kBACZ,QACC,2CAAC;QAAI,WAAU;kBACb,2CAAC,QAAK,WAAU,sCAAsC;SAClD,EAER,2CAAC;QAAK,WAAU;kBACb;SACI;QACH,EACL,WACC,2CAAC;OAAI,WAAU;iBACZ;QACG;OAEJ;KAEP,cACC,2CAAC;MACC,wCACE,YAAY,WAAW,0DAA0D,IACjF,YAAY,YAAY,cAAc,IACtC,YAAY,cAAc,YAAY,WAAW,mBAAmB,IACpE,iBACD;MAEA;OACG;;KAEJ;IACD;GAC2B;;AAQxC,SAAgB,eAAe,EAC7B,UACA,WACA,UACA,GAAG,SACmB;CACtB,MAAM,YAAY,gBAAgB,IAAI,SAAS,IAAI;AAEnD,QACE,4CAAC;EACC,wCACE,6IACA,sGACA,+BACA,UACD;EACD,GAAI;;GAEJ,2CAAC,SAAI,WAAU,yIAAyI;GACxJ,2CAAC,SACC,wCACE,oHACA,UACD,GACD;GACF,2CAAC;IAAI,WAAU;IACZ;KACG;;GACF"}
|
|
1
|
+
{"version":3,"file":"card.js","names":["React","Card"],"sources":["../../src/components/card.tsx"],"sourcesContent":["\"use client\";\n\nimport { Card } from \"@stackframe/stack-ui\";\nimport { cn } from \"@stackframe/stack-ui\";\nimport React from \"react\";\n\n// ─── Card nesting context ────────────────────────────────────────────────────\n// Components with a `glassmorphic` prop use this to auto-detect whether they\n// sit inside a DesignCard. When they do, glassmorphic defaults to `true`;\n// when they don't, it defaults to `false`.\n\nconst DesignCardNestingContext = React.createContext(false);\n\n/**\n * Returns `true` when the calling component is rendered inside a DesignCard.\n * Useful for deriving a glassmorphic default.\n */\nexport function useInsideDesignCard(): boolean {\n return React.useContext(DesignCardNestingContext);\n}\n\n/**\n * Resolve the effective glassmorphic value.\n * - If the caller passed an explicit boolean → honour it.\n * - Otherwise → fall back to whether we're inside a DesignCard.\n */\nexport function useGlassmorphicDefault(explicit: boolean | undefined): boolean {\n const insideCard = useInsideDesignCard();\n return explicit ?? insideCard;\n}\n\ntype DesignCardGradient = \"blue\" | \"cyan\" | \"purple\" | \"green\" | \"orange\" | \"default\";\n\nconst hoverTintClasses = new Map<DesignCardGradient, string>([\n [\"blue\", \"group-hover:bg-blue-500/[0.03]\"],\n [\"purple\", \"group-hover:bg-purple-500/[0.03]\"],\n [\"green\", \"group-hover:bg-emerald-500/[0.03]\"],\n [\"orange\", \"group-hover:bg-orange-500/[0.03]\"],\n [\"default\", \"group-hover:bg-slate-500/[0.02]\"],\n [\"cyan\", \"group-hover:bg-cyan-500/[0.03]\"],\n]);\n\nconst demoTintClasses = new Map<DesignCardGradient, string>([\n [\"blue\", \"group-hover/tint:bg-blue-500/[0.02]\"],\n [\"purple\", \"group-hover/tint:bg-purple-500/[0.02]\"],\n [\"green\", \"group-hover/tint:bg-emerald-500/[0.02]\"],\n [\"orange\", \"group-hover/tint:bg-orange-500/[0.02]\"],\n [\"default\", \"group-hover/tint:bg-slate-500/[0.015]\"],\n [\"cyan\", \"group-hover/tint:bg-cyan-500/[0.02]\"],\n]);\n\nconst bodyPaddingClass = \"p-5\";\n\n// ─── Discriminated props ──────────────────────────────────────────────────\n// - If title is given, icon is required.\n// - The layout is derived automatically:\n// title + subtitle → \"header\" (full header block with subtitle)\n// title only → \"compact\" (slim bar with border-b)\n// no title → \"bodyOnly\" (just the body)\n\ntype DesignCardBaseProps = {\n glassmorphic?: boolean,\n gradient?: DesignCardGradient,\n contentClassName?: string,\n} & Omit<React.ComponentProps<typeof Card>, \"title\">;\n\ntype WithTitleProps = {\n title: React.ReactNode,\n subtitle?: React.ReactNode,\n icon: React.ElementType,\n actions?: React.ReactNode,\n};\n\ntype WithoutTitleProps = {\n title?: never,\n subtitle?: never,\n icon?: never,\n actions?: never,\n};\n\nexport type DesignCardProps = DesignCardBaseProps & (WithTitleProps | WithoutTitleProps);\n\n/**\n * General-purpose card for grouping related content: section headers,\n * description blocks, chart-less panels, etc. If the content is a\n * big-number metric, use `DesignMetricCard` instead. If it contains a\n * chart, wrap it in `DesignChartCard`.\n *\n * Two shapes, picked automatically by the props you pass:\n *\n * ```tsx\n * // With a header (title requires icon):\n * <DesignCard title=\"Recent activity\" icon={ActivityIcon}>\n * ...body...\n * </DesignCard>\n *\n * // Body-only (no header):\n * <DesignCard>\n * <h2 className=\"text-2xl font-semibold\">Dashboard</h2>\n * <p className=\"text-muted-foreground\">Overview of your user base</p>\n * </DesignCard>\n * ```\n *\n * Rules:\n * - DO NOT add padding classes (`p-6`, `p-5`, etc.) to `className` — the\n * component already has built-in padding and extra padding will look wrong.\n * - If you set `title`, you MUST also set `icon`. The TS types enforce this,\n * but writing `title` without `icon` will fail.\n * - Body-only cards (no `title`) automatically go transparent in dark mode.\n */\nexport function DesignCard({\n title,\n subtitle,\n icon: Icon,\n actions,\n glassmorphic: glassmorphicProp,\n gradient = \"default\",\n children,\n className,\n contentClassName,\n ...props\n}: DesignCardProps) {\n const glassmorphic = glassmorphicProp ?? true;\n const hoverTintClass = hoverTintClasses.get(gradient) ?? \"group-hover:bg-slate-500/[0.02]\";\n const hasContent = React.Children.count(children) > 0;\n\n // Derive layout from which props were provided\n const variant = title != null\n ? (subtitle != null ? \"header\" : \"compact\")\n : \"bodyOnly\";\n\n return (\n <DesignCardNestingContext.Provider value={true}>\n <Card\n className={cn(\n \"group relative rounded-2xl overflow-hidden\",\n glassmorphic && [\n \"bg-white/90 dark:bg-background/60 dark:backdrop-blur-xl border-0 transition-all duration-150 hover:transition-none\",\n \"ring-1 ring-black/[0.06] hover:ring-black/[0.1] dark:ring-white/[0.06] dark:hover:ring-white/[0.1]\",\n \"shadow-none\",\n ],\n glassmorphic && variant === \"bodyOnly\" && \"dark:bg-transparent dark:ring-0 dark:shadow-none\",\n className\n )}\n {...props}\n >\n {glassmorphic && (\n <>\n <div className={cn(\n \"absolute inset-0 bg-gradient-to-br from-foreground/[0.04] dark:from-foreground/[0.02] to-transparent pointer-events-none rounded-2xl\",\n variant === \"bodyOnly\" && \"dark:hidden\"\n )} />\n {variant !== \"bodyOnly\" && (\n <div\n className={cn(\n \"absolute inset-0 transition-colors duration-150 group-hover:transition-none pointer-events-none rounded-2xl\",\n hoverTintClass\n )}\n />\n )}\n </>\n )}\n <div className=\"relative\">\n {variant === \"header\" && (\n <div className={bodyPaddingClass}>\n <div className=\"flex items-start justify-between gap-4\">\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n {Icon && (\n <div className=\"p-1.5 rounded-lg bg-foreground/[0.06] dark:bg-foreground/[0.04]\">\n <Icon className=\"h-3.5 w-3.5 text-foreground/70 dark:text-muted-foreground\" />\n </div>\n )}\n <span className=\"text-xs font-semibold text-foreground uppercase tracking-wider\">\n {title}\n </span>\n </div>\n {subtitle && (\n <p className=\"text-sm text-muted-foreground mt-1\">\n {subtitle}\n </p>\n )}\n </div>\n {actions && (\n <div className=\"flex-shrink-0\">\n {actions}\n </div>\n )}\n </div>\n </div>\n )}\n {variant === \"compact\" && (\n <div className=\"p-5 flex items-center justify-between gap-4 border-b border-black/[0.12] dark:border-white/[0.06]\">\n <div className=\"flex items-center gap-2 min-w-0\">\n {Icon && (\n <div className=\"p-1.5 rounded-lg bg-foreground/[0.04]\">\n <Icon className=\"h-3.5 w-3.5 text-muted-foreground\" />\n </div>\n )}\n <span className=\"text-xs font-semibold text-foreground uppercase tracking-wider\">\n {title}\n </span>\n </div>\n {actions && (\n <div className=\"flex-shrink-0\">\n {actions}\n </div>\n )}\n </div>\n )}\n {hasContent && (\n <div\n className={cn(\n variant === \"header\" ? \"border-t border-black/[0.12] dark:border-white/[0.06]\" : \"\",\n variant === \"compact\" ? \"px-5 py-4\" : \"\",\n variant === \"bodyOnly\" || variant === \"header\" ? bodyPaddingClass : \"\",\n contentClassName\n )}\n >\n {children}\n </div>\n )}\n </div>\n </Card>\n </DesignCardNestingContext.Provider>\n );\n}\n\nexport type DesignCardTintProps = {\n gradient: DesignCardGradient,\n} & React.ComponentProps<\"div\">\n\nexport function DesignCardTint({\n gradient,\n className,\n children,\n ...props\n}: DesignCardTintProps) {\n const tintClass = demoTintClasses.get(gradient) ?? \"group-hover/tint:bg-slate-500/[0.015]\";\n\n return (\n <div\n className={cn(\n \"group/tint relative rounded-2xl bg-white/90 dark:bg-background/60 dark:backdrop-blur-xl transition-all duration-150 hover:transition-none\",\n \"ring-1 ring-black/[0.06] hover:ring-black/[0.1] dark:ring-white/[0.06] dark:hover:ring-white/[0.1]\",\n \"shadow-none overflow-hidden\",\n className\n )}\n {...props}\n >\n <div className=\"absolute inset-0 bg-gradient-to-br from-foreground/[0.04] dark:from-foreground/[0.02] to-transparent pointer-events-none rounded-2xl\" />\n <div\n className={cn(\n \"absolute inset-0 transition-colors duration-150 group-hover/tint:transition-none pointer-events-none rounded-2xl\",\n tintClass\n )}\n />\n <div className=\"relative\">\n {children}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;AAWA,MAAM,2BAA2BA,cAAM,cAAc,MAAM;;;;;AAM3D,SAAgB,sBAA+B;AAC7C,QAAOA,cAAM,WAAW,yBAAyB;;;;;;;AAQnD,SAAgB,uBAAuB,UAAwC;CAC7E,MAAM,aAAa,qBAAqB;AACxC,QAAO,YAAY;;AAKrB,MAAM,mBAAmB,IAAI,IAAgC;CAC3D,CAAC,QAAQ,iCAAiC;CAC1C,CAAC,UAAU,mCAAmC;CAC9C,CAAC,SAAS,oCAAoC;CAC9C,CAAC,UAAU,mCAAmC;CAC9C,CAAC,WAAW,kCAAkC;CAC9C,CAAC,QAAQ,iCAAiC;CAC3C,CAAC;AAEF,MAAM,kBAAkB,IAAI,IAAgC;CAC1D,CAAC,QAAQ,sCAAsC;CAC/C,CAAC,UAAU,wCAAwC;CACnD,CAAC,SAAS,yCAAyC;CACnD,CAAC,UAAU,wCAAwC;CACnD,CAAC,WAAW,wCAAwC;CACpD,CAAC,QAAQ,sCAAsC;CAChD,CAAC;AAEF,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2DzB,SAAgB,WAAW,EACzB,OACA,UACA,MAAM,MACN,SACA,cAAc,kBACd,WAAW,WACX,UACA,WACA,kBACA,GAAG,SACe;CAClB,MAAM,eAAe,oBAAoB;CACzC,MAAM,iBAAiB,iBAAiB,IAAI,SAAS,IAAI;CACzD,MAAM,aAAaA,cAAM,SAAS,MAAM,SAAS,GAAG;CAGpD,MAAM,UAAU,SAAS,OACpB,YAAY,OAAO,WAAW,YAC/B;AAEJ,QACE,2CAAC,yBAAyB;EAAS,OAAO;YACxC,4CAACC;GACC,wCACE,8CACA,gBAAgB;IACd;IACA;IACA;IACD,EACD,gBAAgB,YAAY,cAAc,oDAC1C,UACD;GACD,GAAI;cAEH,gBACC,qFACE,2CAAC,SAAI,wCACH,wIACA,YAAY,cAAc,cAC3B,GAAI,EACJ,YAAY,cACX,2CAAC,SACC,wCACE,+GACA,eACD,GACD,IAEH,EAEL,4CAAC;IAAI,WAAU;;KACZ,YAAY,YACX,2CAAC;MAAI,WAAW;gBACd,4CAAC;OAAI,WAAU;kBACb,4CAAC;QAAI,WAAU;mBACb,4CAAC;SAAI,WAAU;oBACZ,QACC,2CAAC;UAAI,WAAU;oBACb,2CAAC,QAAK,WAAU,8DAA8D;WAC1E,EAER,2CAAC;UAAK,WAAU;oBACb;WACI;UACH,EACL,YACC,2CAAC;SAAE,WAAU;mBACV;UACC;SAEF,EACL,WACC,2CAAC;QAAI,WAAU;kBACZ;SACG;QAEJ;OACF;KAEP,YAAY,aACX,4CAAC;MAAI,WAAU;iBACb,4CAAC;OAAI,WAAU;kBACZ,QACC,2CAAC;QAAI,WAAU;kBACb,2CAAC,QAAK,WAAU,sCAAsC;SAClD,EAER,2CAAC;QAAK,WAAU;kBACb;SACI;QACH,EACL,WACC,2CAAC;OAAI,WAAU;iBACZ;QACG;OAEJ;KAEP,cACC,2CAAC;MACC,wCACE,YAAY,WAAW,0DAA0D,IACjF,YAAY,YAAY,cAAc,IACtC,YAAY,cAAc,YAAY,WAAW,mBAAmB,IACpE,iBACD;MAEA;OACG;;KAEJ;IACD;GAC2B;;AAQxC,SAAgB,eAAe,EAC7B,UACA,WACA,UACA,GAAG,SACmB;CACtB,MAAM,YAAY,gBAAgB,IAAI,SAAS,IAAI;AAEnD,QACE,4CAAC;EACC,wCACE,6IACA,sGACA,+BACA,UACD;EACD,GAAI;;GAEJ,2CAAC,SAAI,WAAU,yIAAyI;GACxJ,2CAAC,SACC,wCACE,oHACA,UACD,GACD;GACF,2CAAC;IAAI,WAAU;IACZ;KACG;;GACF"}
|
|
@@ -8,6 +8,35 @@ type DesignChartCardProps = {
|
|
|
8
8
|
title?: React.ReactNode;
|
|
9
9
|
description?: React.ReactNode;
|
|
10
10
|
} & Omit<React.ComponentProps<"div">, "title">;
|
|
11
|
+
/**
|
|
12
|
+
* Card chrome (title + description + border) for a chart. Wrap every
|
|
13
|
+
* `AnalyticsChart` in this so the chart has context. Also used around raw
|
|
14
|
+
* Recharts components paired with `DesignChartContainer` for non-time-series
|
|
15
|
+
* fallbacks.
|
|
16
|
+
*
|
|
17
|
+
* ```tsx
|
|
18
|
+
* // Time-series chart (preferred):
|
|
19
|
+
* <DesignChartCard title="Signups" description="Last 30 days">
|
|
20
|
+
* <AnalyticsChart data={data} state={state} onChange={setState} />
|
|
21
|
+
* </DesignChartCard>
|
|
22
|
+
*
|
|
23
|
+
* // Non-time-series fallback (static ranking, distribution, etc.):
|
|
24
|
+
* <DesignChartCard title="Top referrers" description="This month">
|
|
25
|
+
* <DesignChartContainer config={chartConfig} maxHeight={300}>
|
|
26
|
+
* <Recharts.BarChart data={data}>
|
|
27
|
+
* <Recharts.CartesianGrid strokeDasharray="3 3" stroke="hsl(var(--border))" />
|
|
28
|
+
* <Recharts.XAxis dataKey="name" tick={{ fill: 'hsl(var(--muted-foreground))', fontSize: 12 }} />
|
|
29
|
+
* <Recharts.YAxis tick={{ fill: 'hsl(var(--muted-foreground))', fontSize: 12 }} />
|
|
30
|
+
* <Recharts.Tooltip content={<DesignChartTooltipContent />} />
|
|
31
|
+
* <Recharts.Bar dataKey="count" fill={getDesignChartColor(0)} radius={[4, 4, 0, 0]} />
|
|
32
|
+
* </Recharts.BarChart>
|
|
33
|
+
* </DesignChartContainer>
|
|
34
|
+
* </DesignChartCard>
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* `chartConfig` for `DesignChartContainer` maps each `dataKey` to its label and color:
|
|
38
|
+
* `{ count: { label: "Count", color: getDesignChartColor(0) } }`.
|
|
39
|
+
*/
|
|
11
40
|
declare function DesignChartCard({
|
|
12
41
|
gradient,
|
|
13
42
|
title,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart-card.d.ts","names":[],"sources":["../../src/components/chart-card.tsx"],"mappings":";;;;KAKK,uBAAA;AAAA,KAWO,oBAAA;EACV,QAAA,GAAW,uBAAA;EACX,KAAA,GAAQ,KAAA,CAAM,SAAA;EACd,WAAA,GAAc,KAAA,CAAM,SAAA;AAAA,IAClB,IAAA,CAAK,KAAA,CAAM,cAAA
|
|
1
|
+
{"version":3,"file":"chart-card.d.ts","names":[],"sources":["../../src/components/chart-card.tsx"],"mappings":";;;;KAKK,uBAAA;AAAA,KAWO,oBAAA;EACV,QAAA,GAAW,uBAAA;EACX,KAAA,GAAQ,KAAA,CAAM,SAAA;EACd,WAAA,GAAc,KAAA,CAAM,SAAA;AAAA,IAClB,IAAA,CAAK,KAAA,CAAM,cAAA;;;AAJf;;;;;;;;;;;;;;;;;;;;;;;AAmCA;;;;iBAAgB,eAAA,CAAA;EACd,QAAA;EACA,KAAA;EACA,WAAA;EACA,SAAA;EACA,QAAA;EAAA,GACG;AAAA,GACF,oBAAA,GAAoB,kBAAA,CAAA,GAAA,CAAA,OAAA"}
|
|
@@ -16,6 +16,35 @@ const hoverTintClasses = new Map([
|
|
|
16
16
|
["orange", "group-hover:bg-orange-500/[0.03]"],
|
|
17
17
|
["default", "group-hover:bg-slate-500/[0.02]"]
|
|
18
18
|
]);
|
|
19
|
+
/**
|
|
20
|
+
* Card chrome (title + description + border) for a chart. Wrap every
|
|
21
|
+
* `AnalyticsChart` in this so the chart has context. Also used around raw
|
|
22
|
+
* Recharts components paired with `DesignChartContainer` for non-time-series
|
|
23
|
+
* fallbacks.
|
|
24
|
+
*
|
|
25
|
+
* ```tsx
|
|
26
|
+
* // Time-series chart (preferred):
|
|
27
|
+
* <DesignChartCard title="Signups" description="Last 30 days">
|
|
28
|
+
* <AnalyticsChart data={data} state={state} onChange={setState} />
|
|
29
|
+
* </DesignChartCard>
|
|
30
|
+
*
|
|
31
|
+
* // Non-time-series fallback (static ranking, distribution, etc.):
|
|
32
|
+
* <DesignChartCard title="Top referrers" description="This month">
|
|
33
|
+
* <DesignChartContainer config={chartConfig} maxHeight={300}>
|
|
34
|
+
* <Recharts.BarChart data={data}>
|
|
35
|
+
* <Recharts.CartesianGrid strokeDasharray="3 3" stroke="hsl(var(--border))" />
|
|
36
|
+
* <Recharts.XAxis dataKey="name" tick={{ fill: 'hsl(var(--muted-foreground))', fontSize: 12 }} />
|
|
37
|
+
* <Recharts.YAxis tick={{ fill: 'hsl(var(--muted-foreground))', fontSize: 12 }} />
|
|
38
|
+
* <Recharts.Tooltip content={<DesignChartTooltipContent />} />
|
|
39
|
+
* <Recharts.Bar dataKey="count" fill={getDesignChartColor(0)} radius={[4, 4, 0, 0]} />
|
|
40
|
+
* </Recharts.BarChart>
|
|
41
|
+
* </DesignChartContainer>
|
|
42
|
+
* </DesignChartCard>
|
|
43
|
+
* ```
|
|
44
|
+
*
|
|
45
|
+
* `chartConfig` for `DesignChartContainer` maps each `dataKey` to its label and color:
|
|
46
|
+
* `{ count: { label: "Count", color: getDesignChartColor(0) } }`.
|
|
47
|
+
*/
|
|
19
48
|
function DesignChartCard({ gradient = "default", title, description, className, children, ...props }) {
|
|
20
49
|
const hoverTintClass = hoverTintClasses.get(gradient) ?? "group-hover:bg-slate-500/[0.02]";
|
|
21
50
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { dangerouslySetInnerHTML: { __html: `
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart-card.js","names":[],"sources":["../../src/components/chart-card.tsx"],"sourcesContent":["\"use client\";\n\nimport { cn } from \"@stackframe/stack-ui\";\nimport React from \"react\";\n\ntype DesignChartCardGradient = \"blue\" | \"cyan\" | \"purple\" | \"green\" | \"orange\" | \"default\";\n\nconst hoverTintClasses = new Map<DesignChartCardGradient, string>([\n [\"blue\", \"group-hover:bg-blue-500/[0.03]\"],\n [\"cyan\", \"group-hover:bg-cyan-500/[0.03]\"],\n [\"purple\", \"group-hover:bg-purple-500/[0.03]\"],\n [\"green\", \"group-hover:bg-emerald-500/[0.03]\"],\n [\"orange\", \"group-hover:bg-orange-500/[0.03]\"],\n [\"default\", \"group-hover:bg-slate-500/[0.02]\"],\n]);\n\nexport type DesignChartCardProps = {\n gradient?: DesignChartCardGradient,\n title?: React.ReactNode,\n description?: React.ReactNode,\n} & Omit<React.ComponentProps<\"div\">, \"title\">;\n\nexport function DesignChartCard({\n gradient = \"default\",\n title,\n description,\n className,\n children,\n ...props\n}: DesignChartCardProps) {\n const hoverTintClass = hoverTintClasses.get(gradient) ?? \"group-hover:bg-slate-500/[0.02]\";\n\n return (\n <>\n <style dangerouslySetInnerHTML={{ __html: `\n .design-chart-card-tooltip-escape .recharts-tooltip-wrapper {\n z-index: 9999 !important;\n overflow: visible !important;\n }\n .design-chart-card-tooltip-escape .recharts-tooltip-wrapper > * {\n overflow: visible !important;\n }\n ` }} />\n <div\n className={cn(\n \"group relative rounded-2xl bg-white/90 dark:bg-background/60 backdrop-blur-xl transition-all duration-150 hover:transition-none design-chart-card-tooltip-escape\",\n \"ring-1 ring-black/[0.06] hover:ring-black/[0.1] dark:ring-white/[0.06] dark:hover:ring-white/[0.1]\",\n \"shadow-sm hover:shadow-md hover:z-10\",\n className\n )}\n {...props}\n >\n <div className=\"absolute inset-0 bg-gradient-to-br from-foreground/[0.04] dark:from-foreground/[0.02] to-transparent pointer-events-none rounded-2xl overflow-hidden\" />\n <div\n className={cn(\n \"absolute inset-0 transition-colors duration-150 group-hover:transition-none pointer-events-none rounded-2xl overflow-hidden\",\n hoverTintClass\n )}\n />\n <div className=\"relative h-full flex flex-col p-4\">\n {(title || description) && (\n <div className=\"mb-3\">\n {title && <h3 className=\"text-sm font-semibold text-foreground\">{title}</h3>}\n {description && <p className=\"text-xs text-muted-foreground mt-0.5\">{description}</p>}\n </div>\n )}\n {children}\n </div>\n </div>\n </>\n );\n}\n"],"mappings":";;;;;;;;;;AAOA,MAAM,mBAAmB,IAAI,IAAqC;CAChE,CAAC,QAAQ,iCAAiC;CAC1C,CAAC,QAAQ,iCAAiC;CAC1C,CAAC,UAAU,mCAAmC;CAC9C,CAAC,SAAS,oCAAoC;CAC9C,CAAC,UAAU,mCAAmC;CAC9C,CAAC,WAAW,kCAAkC;CAC/C,CAAC
|
|
1
|
+
{"version":3,"file":"chart-card.js","names":[],"sources":["../../src/components/chart-card.tsx"],"sourcesContent":["\"use client\";\n\nimport { cn } from \"@stackframe/stack-ui\";\nimport React from \"react\";\n\ntype DesignChartCardGradient = \"blue\" | \"cyan\" | \"purple\" | \"green\" | \"orange\" | \"default\";\n\nconst hoverTintClasses = new Map<DesignChartCardGradient, string>([\n [\"blue\", \"group-hover:bg-blue-500/[0.03]\"],\n [\"cyan\", \"group-hover:bg-cyan-500/[0.03]\"],\n [\"purple\", \"group-hover:bg-purple-500/[0.03]\"],\n [\"green\", \"group-hover:bg-emerald-500/[0.03]\"],\n [\"orange\", \"group-hover:bg-orange-500/[0.03]\"],\n [\"default\", \"group-hover:bg-slate-500/[0.02]\"],\n]);\n\nexport type DesignChartCardProps = {\n gradient?: DesignChartCardGradient,\n title?: React.ReactNode,\n description?: React.ReactNode,\n} & Omit<React.ComponentProps<\"div\">, \"title\">;\n\n/**\n * Card chrome (title + description + border) for a chart. Wrap every\n * `AnalyticsChart` in this so the chart has context. Also used around raw\n * Recharts components paired with `DesignChartContainer` for non-time-series\n * fallbacks.\n *\n * ```tsx\n * // Time-series chart (preferred):\n * <DesignChartCard title=\"Signups\" description=\"Last 30 days\">\n * <AnalyticsChart data={data} state={state} onChange={setState} />\n * </DesignChartCard>\n *\n * // Non-time-series fallback (static ranking, distribution, etc.):\n * <DesignChartCard title=\"Top referrers\" description=\"This month\">\n * <DesignChartContainer config={chartConfig} maxHeight={300}>\n * <Recharts.BarChart data={data}>\n * <Recharts.CartesianGrid strokeDasharray=\"3 3\" stroke=\"hsl(var(--border))\" />\n * <Recharts.XAxis dataKey=\"name\" tick={{ fill: 'hsl(var(--muted-foreground))', fontSize: 12 }} />\n * <Recharts.YAxis tick={{ fill: 'hsl(var(--muted-foreground))', fontSize: 12 }} />\n * <Recharts.Tooltip content={<DesignChartTooltipContent />} />\n * <Recharts.Bar dataKey=\"count\" fill={getDesignChartColor(0)} radius={[4, 4, 0, 0]} />\n * </Recharts.BarChart>\n * </DesignChartContainer>\n * </DesignChartCard>\n * ```\n *\n * `chartConfig` for `DesignChartContainer` maps each `dataKey` to its label and color:\n * `{ count: { label: \"Count\", color: getDesignChartColor(0) } }`.\n */\nexport function DesignChartCard({\n gradient = \"default\",\n title,\n description,\n className,\n children,\n ...props\n}: DesignChartCardProps) {\n const hoverTintClass = hoverTintClasses.get(gradient) ?? \"group-hover:bg-slate-500/[0.02]\";\n\n return (\n <>\n <style dangerouslySetInnerHTML={{ __html: `\n .design-chart-card-tooltip-escape .recharts-tooltip-wrapper {\n z-index: 9999 !important;\n overflow: visible !important;\n }\n .design-chart-card-tooltip-escape .recharts-tooltip-wrapper > * {\n overflow: visible !important;\n }\n ` }} />\n <div\n className={cn(\n \"group relative rounded-2xl bg-white/90 dark:bg-background/60 backdrop-blur-xl transition-all duration-150 hover:transition-none design-chart-card-tooltip-escape\",\n \"ring-1 ring-black/[0.06] hover:ring-black/[0.1] dark:ring-white/[0.06] dark:hover:ring-white/[0.1]\",\n \"shadow-sm hover:shadow-md hover:z-10\",\n className\n )}\n {...props}\n >\n <div className=\"absolute inset-0 bg-gradient-to-br from-foreground/[0.04] dark:from-foreground/[0.02] to-transparent pointer-events-none rounded-2xl overflow-hidden\" />\n <div\n className={cn(\n \"absolute inset-0 transition-colors duration-150 group-hover:transition-none pointer-events-none rounded-2xl overflow-hidden\",\n hoverTintClass\n )}\n />\n <div className=\"relative h-full flex flex-col p-4\">\n {(title || description) && (\n <div className=\"mb-3\">\n {title && <h3 className=\"text-sm font-semibold text-foreground\">{title}</h3>}\n {description && <p className=\"text-xs text-muted-foreground mt-0.5\">{description}</p>}\n </div>\n )}\n {children}\n </div>\n </div>\n </>\n );\n}\n"],"mappings":";;;;;;;;;;AAOA,MAAM,mBAAmB,IAAI,IAAqC;CAChE,CAAC,QAAQ,iCAAiC;CAC1C,CAAC,QAAQ,iCAAiC;CAC1C,CAAC,UAAU,mCAAmC;CAC9C,CAAC,SAAS,oCAAoC;CAC9C,CAAC,UAAU,mCAAmC;CAC9C,CAAC,WAAW,kCAAkC;CAC/C,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCF,SAAgB,gBAAgB,EAC9B,WAAW,WACX,OACA,aACA,WACA,UACA,GAAG,SACoB;CACvB,MAAM,iBAAiB,iBAAiB,IAAI,SAAS,IAAI;AAEzD,QACE,qFACE,2CAAC,WAAM,yBAAyB,EAAE,QAAQ;;;;;;;;SAQvC,GAAI,EACP,4CAAC;EACC,wCACE,oKACA,sGACA,wCACA,UACD;EACD,GAAI;;GAEJ,2CAAC,SAAI,WAAU,yJAAyJ;GACxK,2CAAC,SACC,wCACE,+HACA,eACD,GACD;GACF,4CAAC;IAAI,WAAU;gBACX,SAAS,gBACT,4CAAC;KAAI,WAAU;gBACZ,SAAS,2CAAC;MAAG,WAAU;gBAAyC;OAAW,EAC3E,eAAe,2CAAC;MAAE,WAAU;gBAAwC;OAAgB;MACjF,EAEP;KACG;;GACF,IACL"}
|
|
@@ -2,11 +2,10 @@ import * as React$1 from "react";
|
|
|
2
2
|
import * as RechartsPrimitive from "recharts";
|
|
3
3
|
|
|
4
4
|
//#region src/components/chart-legend.d.ts
|
|
5
|
-
declare const
|
|
6
|
-
declare const DesignChartLegendContent: React$1.ForwardRefExoticComponent<Omit<React$1.ClassAttributes<HTMLDivElement> & React$1.HTMLAttributes<HTMLDivElement> & Pick<RechartsPrimitive.LegendProps, "payload" | "verticalAlign"> & {
|
|
5
|
+
declare const DesignChartLegendContent: React$1.ForwardRefExoticComponent<Omit<React$1.ClassAttributes<HTMLDivElement> & React$1.HTMLAttributes<HTMLDivElement> & Pick<RechartsPrimitive.LegendProps, "verticalAlign" | "payload"> & {
|
|
7
6
|
hideIcon?: boolean;
|
|
8
7
|
nameKey?: string;
|
|
9
8
|
}, "ref"> & React$1.RefAttributes<HTMLDivElement>>;
|
|
10
9
|
//#endregion
|
|
11
|
-
export {
|
|
10
|
+
export { DesignChartLegendContent };
|
|
12
11
|
//# sourceMappingURL=chart-legend.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart-legend.d.ts","names":[],"sources":["../../src/components/chart-legend.tsx"],"mappings":";;;;cAOa,
|
|
1
|
+
{"version":3,"file":"chart-legend.d.ts","names":[],"sources":["../../src/components/chart-legend.tsx"],"mappings":";;;;cAOa,wBAAA,EAAwB,OAAA,CAAA,yBAAA,CAAA,IAAA,CAAA,OAAA,CAAA,eAAA,CAAA,cAAA,IAAA,OAAA,CAAA,cAAA,CAAA,cAAA,IAAA,IAAA,CAAA,iBAAA,CAAA,WAAA"}
|
|
@@ -6,12 +6,9 @@ let _stackframe_stack_ui = require("@stackframe/stack-ui");
|
|
|
6
6
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
7
7
|
let react = require("react");
|
|
8
8
|
react = require_chunk.__toESM(react);
|
|
9
|
-
let recharts = require("recharts");
|
|
10
|
-
recharts = require_chunk.__toESM(recharts);
|
|
11
9
|
let __chart_container_js = require("./chart-container.js");
|
|
12
10
|
|
|
13
11
|
//#region src/components/chart-legend.tsx
|
|
14
|
-
const DesignChartLegend = recharts.Legend;
|
|
15
12
|
const DesignChartLegendContent = react.forwardRef(({ className, hideIcon = false, payload, verticalAlign = "bottom", nameKey }, ref) => {
|
|
16
13
|
const { config } = (0, __chart_container_js.useDesignChart)();
|
|
17
14
|
if (!payload?.length) return null;
|
|
@@ -36,6 +33,5 @@ const DesignChartLegendContent = react.forwardRef(({ className, hideIcon = false
|
|
|
36
33
|
DesignChartLegendContent.displayName = "DesignChartLegendContent";
|
|
37
34
|
|
|
38
35
|
//#endregion
|
|
39
|
-
exports.DesignChartLegend = DesignChartLegend;
|
|
40
36
|
exports.DesignChartLegendContent = DesignChartLegendContent;
|
|
41
37
|
//# sourceMappingURL=chart-legend.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chart-legend.js","names":["
|
|
1
|
+
{"version":3,"file":"chart-legend.js","names":["React"],"sources":["../../src/components/chart-legend.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport * as RechartsPrimitive from \"recharts\";\nimport { cn } from \"@stackframe/stack-ui\";\nimport { useDesignChart, getPayloadConfigFromPayload } from \"./chart-container\";\n\nexport const DesignChartLegendContent = React.forwardRef<\n HTMLDivElement,\n React.ComponentProps<\"div\"> &\n Pick<RechartsPrimitive.LegendProps, \"payload\" | \"verticalAlign\"> & {\n hideIcon?: boolean,\n nameKey?: string,\n }\n>(\n (\n { className, hideIcon = false, payload, verticalAlign = \"bottom\", nameKey },\n ref\n ) => {\n const { config } = useDesignChart();\n\n if (!payload?.length) {\n return null;\n }\n\n return (\n <div\n ref={ref}\n className={cn(\n \"flex flex-wrap items-center justify-center gap-2\",\n verticalAlign === \"top\" ? \"pb-3\" : \"pt-3\",\n className\n )}\n >\n {payload.map((item) => {\n const key = `${nameKey || item.dataKey || \"value\"}`;\n const itemConfig = getPayloadConfigFromPayload(config, item, key);\n\n return (\n <div\n key={item.value}\n className={cn(\n \"flex items-center gap-1.5 rounded-full bg-foreground/[0.03] ring-1 ring-foreground/[0.06] px-3 py-1.5 text-xs\",\n \"transition-colors duration-150 hover:transition-none hover:bg-foreground/[0.05]\"\n )}\n >\n {itemConfig?.icon && !hideIcon ? (\n <itemConfig.icon />\n ) : (\n <span\n className=\"h-2 w-2 shrink-0 rounded-full\"\n style={{ backgroundColor: item.color }}\n />\n )}\n <span className=\"font-medium text-foreground\">\n {itemConfig?.label || item.value}\n </span>\n </div>\n );\n })}\n </div>\n );\n }\n);\nDesignChartLegendContent.displayName = \"DesignChartLegendContent\";\n"],"mappings":";;;;;;;;;;;AAOA,MAAa,2BAA2BA,MAAM,YAS1C,EAAE,WAAW,WAAW,OAAO,SAAS,gBAAgB,UAAU,WAClE,QACG;CACH,MAAM,EAAE,qDAA2B;AAEnC,KAAI,CAAC,SAAS,OACZ,QAAO;AAGT,QACE,2CAAC;EACM;EACL,wCACE,oDACA,kBAAkB,QAAQ,SAAS,QACnC,UACD;YAEA,QAAQ,KAAK,SAAS;GAErB,MAAM,mEAAyC,QAAQ,MAD3C,GAAG,WAAW,KAAK,WAAW,UACuB;AAEjE,UACE,4CAAC;IAEC,wCACE,iHACA,kFACD;eAEA,YAAY,QAAQ,CAAC,WACpB,2CAAC,WAAW,SAAO,GAEnB,2CAAC;KACC,WAAU;KACV,OAAO,EAAE,iBAAiB,KAAK,OAAO;MACtC,EAEJ,2CAAC;KAAK,WAAU;eACb,YAAY,SAAS,KAAK;MACtB;MAhBF,KAAK,MAiBN;IAER;GACE;EAGX;AACD,yBAAyB,cAAc"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { DataGridColumnDef } from "./types.js";
|
|
2
|
+
import { CSSProperties } from "react";
|
|
3
|
+
|
|
4
|
+
//#region src/components/data-grid/data-grid-sizing.d.ts
|
|
5
|
+
declare function getColumnSizingStyle<TRow>(col: DataGridColumnDef<TRow>): CSSProperties;
|
|
6
|
+
declare function createGridSizingStyle(widths: ReadonlyMap<string, number>, totalWidth: number): Record<string, string>;
|
|
7
|
+
declare function applyDraggedColumnWidth(el: HTMLElement, columnId: string, width: number, totalWidth: number): void;
|
|
8
|
+
declare function clampColumnWidth<TRow>(col: DataGridColumnDef<TRow>, width: number): number;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { applyDraggedColumnWidth, clampColumnWidth, createGridSizingStyle, getColumnSizingStyle };
|
|
11
|
+
//# sourceMappingURL=data-grid-sizing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-grid-sizing.d.ts","names":[],"sources":["../../../src/components/data-grid/data-grid-sizing.ts"],"mappings":";;;;iBAWgB,oBAAA,MAAA,CAA2B,GAAA,EAAK,iBAAA,CAAkB,IAAA,IAAQ,aAAA;AAAA,iBAK1D,qBAAA,CACd,MAAA,EAAQ,WAAA,kBACR,UAAA,WACC,MAAA;AAAA,iBAQa,uBAAA,CACd,EAAA,EAAI,WAAA,EACJ,QAAA,UACA,KAAA,UACA,UAAA;AAAA,iBAMc,gBAAA,MAAA,CAAuB,GAAA,EAAK,iBAAA,CAAkB,IAAA,GAAO,KAAA"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
//#region src/components/data-grid/data-grid-sizing.ts
|
|
4
|
+
function colVar(id) {
|
|
5
|
+
return `--col-${id}`;
|
|
6
|
+
}
|
|
7
|
+
function getColumnSizingStyle(col) {
|
|
8
|
+
const w = `var(${colVar(col.id)})`;
|
|
9
|
+
return {
|
|
10
|
+
flex: `0 0 ${w}`,
|
|
11
|
+
width: w,
|
|
12
|
+
minWidth: col.minWidth ?? 50,
|
|
13
|
+
maxWidth: col.maxWidth ?? 800
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function createGridSizingStyle(widths, totalWidth) {
|
|
17
|
+
const style = { "--grid-total-w": `${totalWidth}px` };
|
|
18
|
+
for (const [id, w] of widths) style[colVar(id)] = `${w}px`;
|
|
19
|
+
return style;
|
|
20
|
+
}
|
|
21
|
+
function applyDraggedColumnWidth(el, columnId, width, totalWidth) {
|
|
22
|
+
el.style.setProperty(colVar(columnId), `${width}px`);
|
|
23
|
+
el.style.setProperty("--grid-total-w", `${totalWidth}px`);
|
|
24
|
+
}
|
|
25
|
+
function clampColumnWidth(col, width) {
|
|
26
|
+
return Math.max(col.minWidth ?? 50, Math.min(col.maxWidth ?? 800, width));
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
//#endregion
|
|
30
|
+
exports.applyDraggedColumnWidth = applyDraggedColumnWidth;
|
|
31
|
+
exports.clampColumnWidth = clampColumnWidth;
|
|
32
|
+
exports.createGridSizingStyle = createGridSizingStyle;
|
|
33
|
+
exports.getColumnSizingStyle = getColumnSizingStyle;
|
|
34
|
+
//# sourceMappingURL=data-grid-sizing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-grid-sizing.js","names":[],"sources":["../../../src/components/data-grid/data-grid-sizing.ts"],"sourcesContent":["import type { CSSProperties } from \"react\";\nimport type { DataGridColumnDef } from \"./types\";\n\n// CSS variable names for column widths set on the grid container.\n// Cells read these via var(...) so a single setProperty during drag\n// resizes every cell in a column with zero React re-renders.\n\nfunction colVar(id: string): `--col-${string}` {\n return `--col-${id}`;\n}\n\nexport function getColumnSizingStyle<TRow>(col: DataGridColumnDef<TRow>): CSSProperties {\n const w = `var(${colVar(col.id)})`;\n return { flex: `0 0 ${w}`, width: w, minWidth: col.minWidth ?? 50, maxWidth: col.maxWidth ?? 800 };\n}\n\nexport function createGridSizingStyle(\n widths: ReadonlyMap<string, number>,\n totalWidth: number,\n): Record<string, string> {\n const style: Record<string, string> = { \"--grid-total-w\": `${totalWidth}px` };\n for (const [id, w] of widths) {\n style[colVar(id)] = `${w}px`;\n }\n return style;\n}\n\nexport function applyDraggedColumnWidth(\n el: HTMLElement,\n columnId: string,\n width: number,\n totalWidth: number,\n) {\n el.style.setProperty(colVar(columnId), `${width}px`);\n el.style.setProperty(\"--grid-total-w\", `${totalWidth}px`);\n}\n\nexport function clampColumnWidth<TRow>(col: DataGridColumnDef<TRow>, width: number): number {\n return Math.max(col.minWidth ?? 50, Math.min(col.maxWidth ?? 800, width));\n}\n"],"mappings":";;;AAOA,SAAS,OAAO,IAA+B;AAC7C,QAAO,SAAS;;AAGlB,SAAgB,qBAA2B,KAA6C;CACtF,MAAM,IAAI,OAAO,OAAO,IAAI,GAAG,CAAC;AAChC,QAAO;EAAE,MAAM,OAAO;EAAK,OAAO;EAAG,UAAU,IAAI,YAAY;EAAI,UAAU,IAAI,YAAY;EAAK;;AAGpG,SAAgB,sBACd,QACA,YACwB;CACxB,MAAM,QAAgC,EAAE,kBAAkB,GAAG,WAAW,KAAK;AAC7E,MAAK,MAAM,CAAC,IAAI,MAAM,OACpB,OAAM,OAAO,GAAG,IAAI,GAAG,EAAE;AAE3B,QAAO;;AAGT,SAAgB,wBACd,IACA,UACA,OACA,YACA;AACA,IAAG,MAAM,YAAY,OAAO,SAAS,EAAE,GAAG,MAAM,IAAI;AACpD,IAAG,MAAM,YAAY,kBAAkB,GAAG,WAAW,IAAI;;AAG3D,SAAgB,iBAAuB,KAA8B,OAAuB;AAC1F,QAAO,KAAK,IAAI,IAAI,YAAY,IAAI,KAAK,IAAI,IAAI,YAAY,KAAK,MAAM,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { DataGridToolbarContext } from "./types.js";
|
|
2
|
+
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
3
|
+
import React from "react";
|
|
4
|
+
|
|
5
|
+
//#region src/components/data-grid/data-grid-toolbar.d.ts
|
|
6
|
+
declare function DataGridToolbar<TRow>({
|
|
7
|
+
ctx,
|
|
8
|
+
extra,
|
|
9
|
+
extraLeading,
|
|
10
|
+
hideQuickSearch
|
|
11
|
+
}: {
|
|
12
|
+
ctx: DataGridToolbarContext<TRow>;
|
|
13
|
+
/** Extra content rendered inside the toolbar row, to the left of the
|
|
14
|
+
* built-in columns / export actions. Use this to add table-specific
|
|
15
|
+
* affordances (refresh, custom toggles, row counts) without giving up
|
|
16
|
+
* the default actions. */
|
|
17
|
+
extra?: React.ReactNode;
|
|
18
|
+
/** Extra content rendered at the START of the toolbar row — occupies
|
|
19
|
+
* the same position as the built-in quick search (after it, if the
|
|
20
|
+
* quick search is visible). Use this together with `hideQuickSearch`
|
|
21
|
+
* to fully replace the quick search with a custom input, e.g. an
|
|
22
|
+
* AI-powered search bar. */
|
|
23
|
+
extraLeading?: React.ReactNode;
|
|
24
|
+
/** Whether to hide the built-in quick-search input. When `true`,
|
|
25
|
+
* callers are expected to provide their own search UI via
|
|
26
|
+
* `extraLeading`. */
|
|
27
|
+
hideQuickSearch?: boolean;
|
|
28
|
+
}): react_jsx_runtime0.JSX.Element;
|
|
29
|
+
//#endregion
|
|
30
|
+
export { DataGridToolbar };
|
|
31
|
+
//# sourceMappingURL=data-grid-toolbar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-grid-toolbar.d.ts","names":[],"sources":["../../../src/components/data-grid/data-grid-toolbar.tsx"],"mappings":";;;;;iBA6QgB,eAAA,MAAA,CAAA;EACd,GAAA;EACA,KAAA;EACA,YAAA;EACA;AAAA;EAEA,GAAA,EAAK,sBAAA,CAAuB,IAAA;;AAN9B;;;EAWE,KAAA,GAAQ,KAAA,CAAM,SAAA;EATd;;;;;EAeA,YAAA,GAAe,KAAA,CAAM,SAAA;EAAN;;;EAIf,eAAA;AAAA,IACD,kBAAA,CAAA,GAAA,CAAA,OAAA"}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
4
|
+
const require_chunk = require('../../chunk-BE-pF4vm.js');
|
|
5
|
+
let _phosphor_icons_react = require("@phosphor-icons/react");
|
|
6
|
+
let _stackframe_stack_ui = require("@stackframe/stack-ui");
|
|
7
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
8
|
+
let react = require("react");
|
|
9
|
+
react = require_chunk.__toESM(react);
|
|
10
|
+
|
|
11
|
+
//#region src/components/data-grid/data-grid-toolbar.tsx
|
|
12
|
+
function usePopover() {
|
|
13
|
+
const [open, setOpen] = (0, react.useState)(false);
|
|
14
|
+
const ref = (0, react.useRef)(null);
|
|
15
|
+
react.default.useEffect(() => {
|
|
16
|
+
if (!open) return;
|
|
17
|
+
const handler = (e) => {
|
|
18
|
+
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
19
|
+
};
|
|
20
|
+
document.addEventListener("mousedown", handler);
|
|
21
|
+
return () => document.removeEventListener("mousedown", handler);
|
|
22
|
+
}, [open]);
|
|
23
|
+
react.default.useEffect(() => {
|
|
24
|
+
if (!open) return;
|
|
25
|
+
const handler = (e) => {
|
|
26
|
+
if (e.key === "Escape") setOpen(false);
|
|
27
|
+
};
|
|
28
|
+
document.addEventListener("keydown", handler);
|
|
29
|
+
return () => document.removeEventListener("keydown", handler);
|
|
30
|
+
}, [open]);
|
|
31
|
+
return {
|
|
32
|
+
open,
|
|
33
|
+
setOpen,
|
|
34
|
+
ref
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function PopoverPanel({ children, className, popoverRef }) {
|
|
38
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
39
|
+
ref: popoverRef,
|
|
40
|
+
className: (0, _stackframe_stack_ui.cn)("absolute top-full left-0 mt-1 z-50", "bg-popover text-popover-foreground rounded-xl shadow-lg", "ring-1 ring-black/[0.08] dark:ring-white/[0.1]", "backdrop-blur-xl", className),
|
|
41
|
+
children
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function QuickSearch({ value, onChange, placeholder }) {
|
|
45
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
46
|
+
className: "relative flex min-w-0 flex-1 items-center sm:flex-initial",
|
|
47
|
+
children: [
|
|
48
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_phosphor_icons_react.MagnifyingGlass, { className: "absolute left-2.5 h-3.5 w-3.5 text-muted-foreground/50 pointer-events-none" }),
|
|
49
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
50
|
+
type: "text",
|
|
51
|
+
className: (0, _stackframe_stack_ui.cn)("h-8 w-full sm:w-52 pl-8 pr-7 rounded-xl text-xs", "bg-background", "border border-black/[0.08] dark:border-white/[0.08]", "placeholder:text-muted-foreground/40", "focus:outline-none focus:ring-1 focus:ring-foreground/[0.1]", "transition-all duration-150"),
|
|
52
|
+
placeholder,
|
|
53
|
+
value,
|
|
54
|
+
onChange: (e) => onChange(e.target.value)
|
|
55
|
+
}),
|
|
56
|
+
value && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
57
|
+
className: "absolute right-2 text-muted-foreground/40 hover:text-muted-foreground",
|
|
58
|
+
onClick: () => onChange(""),
|
|
59
|
+
"aria-label": "Clear search",
|
|
60
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_phosphor_icons_react.X, { className: "h-3 w-3" })
|
|
61
|
+
})
|
|
62
|
+
]
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
function ToolbarButton({ children, onClick, active, title, className: extraClassName }) {
|
|
66
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
67
|
+
className: (0, _stackframe_stack_ui.cn)("relative flex items-center justify-center rounded-lg text-xs font-medium", "h-7 w-7", "transition-colors duration-75", active ? "bg-foreground/[0.06] text-foreground" : "text-muted-foreground hover:text-foreground hover:bg-foreground/[0.04]", extraClassName),
|
|
68
|
+
onClick,
|
|
69
|
+
title,
|
|
70
|
+
children
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
function ColumnManager({ columns, visibility, onChange, strings, dateDisplay, onDateDisplayChange, hasDateColumns }) {
|
|
74
|
+
const hideableColumns = (0, react.useMemo)(() => columns.filter((c) => c.hideable !== false), [columns]);
|
|
75
|
+
const toggleColumn = (id) => {
|
|
76
|
+
const current = visibility[id] !== false;
|
|
77
|
+
onChange({
|
|
78
|
+
...visibility,
|
|
79
|
+
[id]: !current
|
|
80
|
+
});
|
|
81
|
+
};
|
|
82
|
+
const showAll = () => {
|
|
83
|
+
const next = { ...visibility };
|
|
84
|
+
for (const col of hideableColumns) next[col.id] = true;
|
|
85
|
+
onChange(next);
|
|
86
|
+
};
|
|
87
|
+
const hideAll = () => {
|
|
88
|
+
const next = { ...visibility };
|
|
89
|
+
for (const col of hideableColumns) next[col.id] = false;
|
|
90
|
+
onChange(next);
|
|
91
|
+
};
|
|
92
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
93
|
+
className: "p-2 min-w-[240px] max-w-[300px]",
|
|
94
|
+
children: [
|
|
95
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
96
|
+
className: "max-h-[280px] overflow-y-auto space-y-0.5",
|
|
97
|
+
children: hideableColumns.map((col) => {
|
|
98
|
+
const visible = visibility[col.id] !== false;
|
|
99
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
100
|
+
className: (0, _stackframe_stack_ui.cn)("flex items-center gap-2 w-full px-2.5 py-1.5 rounded-lg text-xs", "hover:bg-foreground/[0.06] transition-colors duration-75", visible ? "text-foreground" : "text-muted-foreground/50"),
|
|
101
|
+
onClick: () => toggleColumn(col.id),
|
|
102
|
+
children: [
|
|
103
|
+
visible ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_phosphor_icons_react.Eye, { className: "h-3.5 w-3.5 flex-shrink-0 text-blue-500" }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_phosphor_icons_react.EyeSlash, { className: "h-3.5 w-3.5 flex-shrink-0" }),
|
|
104
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
105
|
+
className: "truncate text-left",
|
|
106
|
+
children: typeof col.header === "string" ? col.header : col.id
|
|
107
|
+
}),
|
|
108
|
+
visible && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_phosphor_icons_react.Check, { className: "h-3 w-3 ml-auto flex-shrink-0 text-blue-500" })
|
|
109
|
+
]
|
|
110
|
+
}, col.id);
|
|
111
|
+
})
|
|
112
|
+
}),
|
|
113
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
114
|
+
className: "flex items-center gap-2 mt-2 pt-2 border-t border-foreground/[0.06]",
|
|
115
|
+
children: [
|
|
116
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
117
|
+
className: "text-[10px] text-muted-foreground hover:text-foreground font-medium uppercase tracking-wider transition-colors duration-75",
|
|
118
|
+
onClick: showAll,
|
|
119
|
+
children: strings.showAll
|
|
120
|
+
}),
|
|
121
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
122
|
+
className: "text-muted-foreground/20",
|
|
123
|
+
children: "|"
|
|
124
|
+
}),
|
|
125
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
126
|
+
className: "text-[10px] text-muted-foreground hover:text-foreground font-medium uppercase tracking-wider transition-colors duration-75",
|
|
127
|
+
onClick: hideAll,
|
|
128
|
+
children: strings.hideAll
|
|
129
|
+
})
|
|
130
|
+
]
|
|
131
|
+
}),
|
|
132
|
+
hasDateColumns && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
133
|
+
className: "mt-2 pt-2 border-t border-foreground/[0.06]",
|
|
134
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
135
|
+
className: "flex items-center justify-between gap-2 px-1",
|
|
136
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
137
|
+
className: "text-[10px] font-medium uppercase tracking-wider text-muted-foreground",
|
|
138
|
+
children: strings.dateFormat
|
|
139
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
140
|
+
className: "inline-flex items-center gap-0.5 rounded-lg bg-foreground/[0.04] p-0.5",
|
|
141
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
142
|
+
className: (0, _stackframe_stack_ui.cn)("px-2 py-0.5 rounded-md text-[11px] font-medium transition-colors duration-75", dateDisplay === "relative" ? "bg-background text-foreground shadow-sm ring-1 ring-foreground/[0.06]" : "text-muted-foreground hover:text-foreground"),
|
|
143
|
+
onClick: () => onDateDisplayChange("relative"),
|
|
144
|
+
children: strings.dateFormatRelative
|
|
145
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
146
|
+
className: (0, _stackframe_stack_ui.cn)("px-2 py-0.5 rounded-md text-[11px] font-medium transition-colors duration-75", dateDisplay === "absolute" ? "bg-background text-foreground shadow-sm ring-1 ring-foreground/[0.06]" : "text-muted-foreground hover:text-foreground"),
|
|
147
|
+
onClick: () => onDateDisplayChange("absolute"),
|
|
148
|
+
children: strings.dateFormatAbsolute
|
|
149
|
+
})]
|
|
150
|
+
})]
|
|
151
|
+
})
|
|
152
|
+
})
|
|
153
|
+
]
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
function DataGridToolbar({ ctx, extra, extraLeading, hideQuickSearch }) {
|
|
157
|
+
const { state, onChange, columns, strings, exportCsv } = ctx;
|
|
158
|
+
const columnPopover = usePopover();
|
|
159
|
+
const updateVisibility = (0, react.useCallback)((visibility) => {
|
|
160
|
+
onChange((s) => ({
|
|
161
|
+
...s,
|
|
162
|
+
columnVisibility: visibility
|
|
163
|
+
}));
|
|
164
|
+
}, [onChange]);
|
|
165
|
+
const updateDateDisplay = (0, react.useCallback)((mode) => {
|
|
166
|
+
onChange((s) => ({
|
|
167
|
+
...s,
|
|
168
|
+
dateDisplay: mode
|
|
169
|
+
}));
|
|
170
|
+
}, [onChange]);
|
|
171
|
+
const updateQuickSearch = (0, react.useCallback)((value) => {
|
|
172
|
+
onChange((s) => ({
|
|
173
|
+
...s,
|
|
174
|
+
quickSearch: value,
|
|
175
|
+
pagination: {
|
|
176
|
+
...s.pagination,
|
|
177
|
+
pageIndex: 0
|
|
178
|
+
}
|
|
179
|
+
}));
|
|
180
|
+
}, [onChange]);
|
|
181
|
+
const hasDateColumns = (0, react.useMemo)(() => columns.some((c) => c.type === "date" || c.type === "dateTime"), [columns]);
|
|
182
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
183
|
+
className: "flex items-center gap-2 px-2.5 py-2.5 border-b border-foreground/[0.06]",
|
|
184
|
+
children: [
|
|
185
|
+
!hideQuickSearch && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(QuickSearch, {
|
|
186
|
+
value: state.quickSearch,
|
|
187
|
+
onChange: updateQuickSearch,
|
|
188
|
+
placeholder: strings.searchPlaceholder
|
|
189
|
+
}),
|
|
190
|
+
extraLeading,
|
|
191
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "flex-1 min-w-0" }),
|
|
192
|
+
extra,
|
|
193
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
194
|
+
className: "relative shrink-0",
|
|
195
|
+
ref: columnPopover.ref,
|
|
196
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarButton, {
|
|
197
|
+
onClick: () => columnPopover.setOpen(!columnPopover.open),
|
|
198
|
+
active: columnPopover.open,
|
|
199
|
+
title: strings.columns,
|
|
200
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_phosphor_icons_react.Eye, { className: "h-3.5 w-3.5" })
|
|
201
|
+
}), columnPopover.open && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PopoverPanel, {
|
|
202
|
+
popoverRef: columnPopover.ref,
|
|
203
|
+
className: "right-0 left-auto",
|
|
204
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ColumnManager, {
|
|
205
|
+
columns,
|
|
206
|
+
visibility: state.columnVisibility,
|
|
207
|
+
onChange: updateVisibility,
|
|
208
|
+
strings,
|
|
209
|
+
dateDisplay: state.dateDisplay,
|
|
210
|
+
onDateDisplayChange: updateDateDisplay,
|
|
211
|
+
hasDateColumns
|
|
212
|
+
})
|
|
213
|
+
})]
|
|
214
|
+
}),
|
|
215
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarButton, {
|
|
216
|
+
onClick: exportCsv,
|
|
217
|
+
title: strings.export,
|
|
218
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_phosphor_icons_react.DownloadSimple, { className: "h-3.5 w-3.5" })
|
|
219
|
+
})
|
|
220
|
+
]
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
//#endregion
|
|
225
|
+
exports.DataGridToolbar = DataGridToolbar;
|
|
226
|
+
//# sourceMappingURL=data-grid-toolbar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-grid-toolbar.js","names":["MagnifyingGlass","X","Eye","EyeSlash","Check","DownloadSimple"],"sources":["../../../src/components/data-grid/data-grid-toolbar.tsx"],"sourcesContent":["\"use client\";\n\nimport { cn } from \"@stackframe/stack-ui\";\nimport {\n Check,\n DownloadSimple,\n Eye,\n EyeSlash,\n MagnifyingGlass,\n X,\n} from \"@phosphor-icons/react\";\nimport React, { useCallback, useMemo, useRef, useState } from \"react\";\nimport type {\n DataGridColumnDef,\n DataGridDateDisplay,\n DataGridStrings,\n DataGridToolbarContext,\n} from \"./types\";\n\n// ─── Popover primitive ───────────────────────────────────────────────\n\nfunction usePopover() {\n const [open, setOpen] = useState(false);\n const ref = useRef<HTMLDivElement>(null);\n\n React.useEffect(() => {\n if (!open) return;\n const handler = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) {\n setOpen(false);\n }\n };\n document.addEventListener(\"mousedown\", handler);\n return () => document.removeEventListener(\"mousedown\", handler);\n }, [open]);\n\n React.useEffect(() => {\n if (!open) return;\n const handler = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") setOpen(false);\n };\n document.addEventListener(\"keydown\", handler);\n return () => document.removeEventListener(\"keydown\", handler);\n }, [open]);\n\n return { open, setOpen, ref };\n}\n\nfunction PopoverPanel({\n children,\n className,\n popoverRef,\n}: {\n children: React.ReactNode;\n className?: string;\n popoverRef: React.Ref<HTMLDivElement>;\n}) {\n return (\n <div\n ref={popoverRef}\n className={cn(\n \"absolute top-full left-0 mt-1 z-50\",\n \"bg-popover text-popover-foreground rounded-xl shadow-lg\",\n \"ring-1 ring-black/[0.08] dark:ring-white/[0.1]\",\n \"backdrop-blur-xl\",\n className,\n )}\n >\n {children}\n </div>\n );\n}\n\n// ─── Quick search ────────────────────────────────────────────────────\n\nfunction QuickSearch({\n value,\n onChange,\n placeholder,\n}: {\n value: string;\n onChange: (value: string) => void;\n placeholder: string;\n}) {\n return (\n <div className=\"relative flex min-w-0 flex-1 items-center sm:flex-initial\">\n <MagnifyingGlass className=\"absolute left-2.5 h-3.5 w-3.5 text-muted-foreground/50 pointer-events-none\" />\n <input\n type=\"text\"\n className={cn(\n \"h-8 w-full sm:w-52 pl-8 pr-7 rounded-xl text-xs\",\n \"bg-background\",\n \"border border-black/[0.08] dark:border-white/[0.08]\",\n \"placeholder:text-muted-foreground/40\",\n \"focus:outline-none focus:ring-1 focus:ring-foreground/[0.1]\",\n \"transition-all duration-150\",\n )}\n placeholder={placeholder}\n value={value}\n onChange={(e) => onChange(e.target.value)}\n />\n {value && (\n <button\n className=\"absolute right-2 text-muted-foreground/40 hover:text-muted-foreground\"\n onClick={() => onChange(\"\")}\n aria-label=\"Clear search\"\n >\n <X className=\"h-3 w-3\" />\n </button>\n )}\n </div>\n );\n}\n\n// ─── Toolbar button ──────────────────────────────────────────────────\n\nfunction ToolbarButton({\n children,\n onClick,\n active,\n title,\n className: extraClassName,\n}: {\n children: React.ReactNode;\n onClick?: () => void;\n active?: boolean;\n title?: string;\n className?: string;\n}) {\n return (\n <button\n className={cn(\n \"relative flex items-center justify-center rounded-lg text-xs font-medium\",\n \"h-7 w-7\",\n \"transition-colors duration-75\",\n active\n ? \"bg-foreground/[0.06] text-foreground\"\n : \"text-muted-foreground hover:text-foreground hover:bg-foreground/[0.04]\",\n extraClassName,\n )}\n onClick={onClick}\n title={title}\n >\n {children}\n </button>\n );\n}\n\n// ─── Column manager ──────────────────────────────────────────────────\n\nfunction ColumnManager<TRow>({\n columns,\n visibility,\n onChange,\n strings,\n dateDisplay,\n onDateDisplayChange,\n hasDateColumns,\n}: {\n columns: readonly DataGridColumnDef<TRow>[];\n visibility: Record<string, boolean>;\n onChange: (visibility: Record<string, boolean>) => void;\n strings: DataGridStrings;\n dateDisplay: DataGridDateDisplay;\n onDateDisplayChange: (mode: DataGridDateDisplay) => void;\n hasDateColumns: boolean;\n}) {\n const hideableColumns = useMemo(\n () => columns.filter((c) => c.hideable !== false),\n [columns],\n );\n\n const toggleColumn = (id: string) => {\n const current = visibility[id] !== false;\n onChange({ ...visibility, [id]: !current });\n };\n\n const showAll = () => {\n const next = { ...visibility };\n for (const col of hideableColumns) next[col.id] = true;\n onChange(next);\n };\n\n const hideAll = () => {\n const next = { ...visibility };\n for (const col of hideableColumns) next[col.id] = false;\n onChange(next);\n };\n\n return (\n <div className=\"p-2 min-w-[240px] max-w-[300px]\">\n <div className=\"max-h-[280px] overflow-y-auto space-y-0.5\">\n {hideableColumns.map((col) => {\n const visible = visibility[col.id] !== false;\n return (\n <button\n key={col.id}\n className={cn(\n \"flex items-center gap-2 w-full px-2.5 py-1.5 rounded-lg text-xs\",\n \"hover:bg-foreground/[0.06] transition-colors duration-75\",\n visible ? \"text-foreground\" : \"text-muted-foreground/50\",\n )}\n onClick={() => toggleColumn(col.id)}\n >\n {visible ? (\n <Eye className=\"h-3.5 w-3.5 flex-shrink-0 text-blue-500\" />\n ) : (\n <EyeSlash className=\"h-3.5 w-3.5 flex-shrink-0\" />\n )}\n <span className=\"truncate text-left\">\n {typeof col.header === \"string\" ? col.header : col.id}\n </span>\n {visible && <Check className=\"h-3 w-3 ml-auto flex-shrink-0 text-blue-500\" />}\n </button>\n );\n })}\n </div>\n <div className=\"flex items-center gap-2 mt-2 pt-2 border-t border-foreground/[0.06]\">\n <button className=\"text-[10px] text-muted-foreground hover:text-foreground font-medium uppercase tracking-wider transition-colors duration-75\" onClick={showAll}>\n {strings.showAll}\n </button>\n <span className=\"text-muted-foreground/20\">|</span>\n <button className=\"text-[10px] text-muted-foreground hover:text-foreground font-medium uppercase tracking-wider transition-colors duration-75\" onClick={hideAll}>\n {strings.hideAll}\n </button>\n </div>\n\n {/* Date format toggle — only rendered when at least one column\n uses `type: \"date\"` or `\"dateTime\"`. Toggling writes to\n `state.dateDisplay` and the grid re-renders every date cell. */}\n {hasDateColumns && (\n <div className=\"mt-2 pt-2 border-t border-foreground/[0.06]\">\n <div className=\"flex items-center justify-between gap-2 px-1\">\n <span className=\"text-[10px] font-medium uppercase tracking-wider text-muted-foreground\">\n {strings.dateFormat}\n </span>\n <div className=\"inline-flex items-center gap-0.5 rounded-lg bg-foreground/[0.04] p-0.5\">\n <button\n className={cn(\n \"px-2 py-0.5 rounded-md text-[11px] font-medium transition-colors duration-75\",\n dateDisplay === \"relative\"\n ? \"bg-background text-foreground shadow-sm ring-1 ring-foreground/[0.06]\"\n : \"text-muted-foreground hover:text-foreground\",\n )}\n onClick={() => onDateDisplayChange(\"relative\")}\n >\n {strings.dateFormatRelative}\n </button>\n <button\n className={cn(\n \"px-2 py-0.5 rounded-md text-[11px] font-medium transition-colors duration-75\",\n dateDisplay === \"absolute\"\n ? \"bg-background text-foreground shadow-sm ring-1 ring-foreground/[0.06]\"\n : \"text-muted-foreground hover:text-foreground\",\n )}\n onClick={() => onDateDisplayChange(\"absolute\")}\n >\n {strings.dateFormatAbsolute}\n </button>\n </div>\n </div>\n </div>\n )}\n </div>\n );\n}\n\n// ─── Main toolbar ────────────────────────────────────────────────────\n\nexport function DataGridToolbar<TRow>({\n ctx,\n extra,\n extraLeading,\n hideQuickSearch,\n}: {\n ctx: DataGridToolbarContext<TRow>;\n /** Extra content rendered inside the toolbar row, to the left of the\n * built-in columns / export actions. Use this to add table-specific\n * affordances (refresh, custom toggles, row counts) without giving up\n * the default actions. */\n extra?: React.ReactNode;\n /** Extra content rendered at the START of the toolbar row — occupies\n * the same position as the built-in quick search (after it, if the\n * quick search is visible). Use this together with `hideQuickSearch`\n * to fully replace the quick search with a custom input, e.g. an\n * AI-powered search bar. */\n extraLeading?: React.ReactNode;\n /** Whether to hide the built-in quick-search input. When `true`,\n * callers are expected to provide their own search UI via\n * `extraLeading`. */\n hideQuickSearch?: boolean;\n}) {\n const { state, onChange, columns, strings, exportCsv } = ctx;\n\n const columnPopover = usePopover();\n\n const updateVisibility = useCallback(\n (visibility: Record<string, boolean>) => {\n onChange((s) => ({ ...s, columnVisibility: visibility }));\n },\n [onChange],\n );\n\n const updateDateDisplay = useCallback(\n (mode: DataGridDateDisplay) => {\n onChange((s) => ({ ...s, dateDisplay: mode }));\n },\n [onChange],\n );\n\n const updateQuickSearch = useCallback(\n (value: string) => {\n onChange((s) => ({\n ...s,\n quickSearch: value,\n // Reset to first page whenever the search text changes,\n // otherwise you can end up on a page index that no longer\n // exists in the filtered / refetched result set.\n pagination: { ...s.pagination, pageIndex: 0 },\n }));\n },\n [onChange],\n );\n\n const hasDateColumns = useMemo(\n () => columns.some((c) => c.type === \"date\" || c.type === \"dateTime\"),\n [columns],\n );\n\n return (\n <div className=\"flex items-center gap-2 px-2.5 py-2.5 border-b border-foreground/[0.06]\">\n {!hideQuickSearch && (\n <QuickSearch\n value={state.quickSearch}\n onChange={updateQuickSearch}\n placeholder={strings.searchPlaceholder}\n />\n )}\n {extraLeading}\n <div className=\"flex-1 min-w-0\" />\n\n {extra}\n\n <div className=\"relative shrink-0\" ref={columnPopover.ref}>\n <ToolbarButton\n onClick={() => columnPopover.setOpen(!columnPopover.open)}\n active={columnPopover.open}\n title={strings.columns}\n >\n <Eye className=\"h-3.5 w-3.5\" />\n </ToolbarButton>\n {columnPopover.open && (\n <PopoverPanel popoverRef={columnPopover.ref} className=\"right-0 left-auto\">\n <ColumnManager\n columns={columns}\n visibility={state.columnVisibility}\n onChange={updateVisibility}\n strings={strings}\n dateDisplay={state.dateDisplay}\n onDateDisplayChange={updateDateDisplay}\n hasDateColumns={hasDateColumns}\n />\n </PopoverPanel>\n )}\n </div>\n\n <ToolbarButton onClick={exportCsv} title={strings.export}>\n <DownloadSimple className=\"h-3.5 w-3.5\" />\n </ToolbarButton>\n </div>\n );\n}\n"],"mappings":"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"}
|