@datum-cloud/activity-ui 0.1.2 → 0.3.0-dev.eaadbbb

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.esm.js CHANGED
@@ -7597,13 +7597,32 @@ const createLucideIcon = (iconName, iconNode) => {
7597
7597
  */
7598
7598
 
7599
7599
 
7600
- const __iconNode$m = [
7600
+ const __iconNode$o = [
7601
+ [
7602
+ "path",
7603
+ {
7604
+ d: "M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2",
7605
+ key: "169zse"
7606
+ }
7607
+ ]
7608
+ ];
7609
+ const Activity = createLucideIcon("activity", __iconNode$o);
7610
+
7611
+ /**
7612
+ * @license lucide-react v0.563.0 - ISC
7613
+ *
7614
+ * This source code is licensed under the ISC license.
7615
+ * See the LICENSE file in the root directory of this source tree.
7616
+ */
7617
+
7618
+
7619
+ const __iconNode$n = [
7601
7620
  ["path", { d: "M8 2v4", key: "1cmpym" }],
7602
7621
  ["path", { d: "M16 2v4", key: "4m81vk" }],
7603
7622
  ["rect", { width: "18", height: "18", x: "3", y: "4", rx: "2", key: "1hopcy" }],
7604
7623
  ["path", { d: "M3 10h18", key: "8toen8" }]
7605
7624
  ];
7606
- const Calendar = createLucideIcon("calendar", __iconNode$m);
7625
+ const Calendar = createLucideIcon("calendar", __iconNode$n);
7607
7626
 
7608
7627
  /**
7609
7628
  * @license lucide-react v0.563.0 - ISC
@@ -7613,8 +7632,8 @@ const Calendar = createLucideIcon("calendar", __iconNode$m);
7613
7632
  */
7614
7633
 
7615
7634
 
7616
- const __iconNode$l = [["path", { d: "M20 6 9 17l-5-5", key: "1gmf2c" }]];
7617
- const Check = createLucideIcon("check", __iconNode$l);
7635
+ const __iconNode$m = [["path", { d: "M20 6 9 17l-5-5", key: "1gmf2c" }]];
7636
+ const Check = createLucideIcon("check", __iconNode$m);
7618
7637
 
7619
7638
  /**
7620
7639
  * @license lucide-react v0.563.0 - ISC
@@ -7624,8 +7643,8 @@ const Check = createLucideIcon("check", __iconNode$l);
7624
7643
  */
7625
7644
 
7626
7645
 
7627
- const __iconNode$k = [["path", { d: "m6 9 6 6 6-6", key: "qrunsl" }]];
7628
- const ChevronDown = createLucideIcon("chevron-down", __iconNode$k);
7646
+ const __iconNode$l = [["path", { d: "m6 9 6 6 6-6", key: "qrunsl" }]];
7647
+ const ChevronDown = createLucideIcon("chevron-down", __iconNode$l);
7629
7648
 
7630
7649
  /**
7631
7650
  * @license lucide-react v0.563.0 - ISC
@@ -7635,8 +7654,8 @@ const ChevronDown = createLucideIcon("chevron-down", __iconNode$k);
7635
7654
  */
7636
7655
 
7637
7656
 
7638
- const __iconNode$j = [["path", { d: "m9 18 6-6-6-6", key: "mthhwq" }]];
7639
- const ChevronRight = createLucideIcon("chevron-right", __iconNode$j);
7657
+ const __iconNode$k = [["path", { d: "m9 18 6-6-6-6", key: "mthhwq" }]];
7658
+ const ChevronRight = createLucideIcon("chevron-right", __iconNode$k);
7640
7659
 
7641
7660
  /**
7642
7661
  * @license lucide-react v0.563.0 - ISC
@@ -7646,8 +7665,8 @@ const ChevronRight = createLucideIcon("chevron-right", __iconNode$j);
7646
7665
  */
7647
7666
 
7648
7667
 
7649
- const __iconNode$i = [["path", { d: "m18 15-6-6-6 6", key: "153udz" }]];
7650
- const ChevronUp = createLucideIcon("chevron-up", __iconNode$i);
7668
+ const __iconNode$j = [["path", { d: "m18 15-6-6-6 6", key: "153udz" }]];
7669
+ const ChevronUp = createLucideIcon("chevron-up", __iconNode$j);
7651
7670
 
7652
7671
  /**
7653
7672
  * @license lucide-react v0.563.0 - ISC
@@ -7657,11 +7676,11 @@ const ChevronUp = createLucideIcon("chevron-up", __iconNode$i);
7657
7676
  */
7658
7677
 
7659
7678
 
7660
- const __iconNode$h = [
7679
+ const __iconNode$i = [
7661
7680
  ["path", { d: "m7 15 5 5 5-5", key: "1hf1tw" }],
7662
7681
  ["path", { d: "m7 9 5-5 5 5", key: "sgt6xg" }]
7663
7682
  ];
7664
- const ChevronsUpDown = createLucideIcon("chevrons-up-down", __iconNode$h);
7683
+ const ChevronsUpDown = createLucideIcon("chevrons-up-down", __iconNode$i);
7665
7684
 
7666
7685
  /**
7667
7686
  * @license lucide-react v0.563.0 - ISC
@@ -7671,12 +7690,12 @@ const ChevronsUpDown = createLucideIcon("chevrons-up-down", __iconNode$h);
7671
7690
  */
7672
7691
 
7673
7692
 
7674
- const __iconNode$g = [
7693
+ const __iconNode$h = [
7675
7694
  ["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
7676
7695
  ["line", { x1: "12", x2: "12", y1: "8", y2: "12", key: "1pkeuh" }],
7677
7696
  ["line", { x1: "12", x2: "12.01", y1: "16", y2: "16", key: "4dfq90" }]
7678
7697
  ];
7679
- const CircleAlert = createLucideIcon("circle-alert", __iconNode$g);
7698
+ const CircleAlert = createLucideIcon("circle-alert", __iconNode$h);
7680
7699
 
7681
7700
  /**
7682
7701
  * @license lucide-react v0.563.0 - ISC
@@ -7686,11 +7705,11 @@ const CircleAlert = createLucideIcon("circle-alert", __iconNode$g);
7686
7705
  */
7687
7706
 
7688
7707
 
7689
- const __iconNode$f = [
7708
+ const __iconNode$g = [
7690
7709
  ["path", { d: "M21.801 10A10 10 0 1 1 17 3.335", key: "yps3ct" }],
7691
7710
  ["path", { d: "m9 11 3 3L22 4", key: "1pflzl" }]
7692
7711
  ];
7693
- const CircleCheckBig = createLucideIcon("circle-check-big", __iconNode$f);
7712
+ const CircleCheckBig = createLucideIcon("circle-check-big", __iconNode$g);
7694
7713
 
7695
7714
  /**
7696
7715
  * @license lucide-react v0.563.0 - ISC
@@ -7700,11 +7719,11 @@ const CircleCheckBig = createLucideIcon("circle-check-big", __iconNode$f);
7700
7719
  */
7701
7720
 
7702
7721
 
7703
- const __iconNode$e = [
7722
+ const __iconNode$f = [
7704
7723
  ["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
7705
7724
  ["path", { d: "m9 12 2 2 4-4", key: "dzmm74" }]
7706
7725
  ];
7707
- const CircleCheck = createLucideIcon("circle-check", __iconNode$e);
7726
+ const CircleCheck = createLucideIcon("circle-check", __iconNode$f);
7708
7727
 
7709
7728
  /**
7710
7729
  * @license lucide-react v0.563.0 - ISC
@@ -7714,12 +7733,12 @@ const CircleCheck = createLucideIcon("circle-check", __iconNode$e);
7714
7733
  */
7715
7734
 
7716
7735
 
7717
- const __iconNode$d = [
7736
+ const __iconNode$e = [
7718
7737
  ["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
7719
7738
  ["path", { d: "m15 9-6 6", key: "1uzhvr" }],
7720
7739
  ["path", { d: "m9 9 6 6", key: "z0biqf" }]
7721
7740
  ];
7722
- const CircleX = createLucideIcon("circle-x", __iconNode$d);
7741
+ const CircleX = createLucideIcon("circle-x", __iconNode$e);
7723
7742
 
7724
7743
  /**
7725
7744
  * @license lucide-react v0.563.0 - ISC
@@ -7729,11 +7748,11 @@ const CircleX = createLucideIcon("circle-x", __iconNode$d);
7729
7748
  */
7730
7749
 
7731
7750
 
7732
- const __iconNode$c = [
7751
+ const __iconNode$d = [
7733
7752
  ["path", { d: "M12 6v6l4 2", key: "mmk7yg" }],
7734
7753
  ["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }]
7735
7754
  ];
7736
- const Clock = createLucideIcon("clock", __iconNode$c);
7755
+ const Clock = createLucideIcon("clock", __iconNode$d);
7737
7756
 
7738
7757
  /**
7739
7758
  * @license lucide-react v0.563.0 - ISC
@@ -7743,11 +7762,11 @@ const Clock = createLucideIcon("clock", __iconNode$c);
7743
7762
  */
7744
7763
 
7745
7764
 
7746
- const __iconNode$b = [
7765
+ const __iconNode$c = [
7747
7766
  ["rect", { width: "14", height: "14", x: "8", y: "8", rx: "2", ry: "2", key: "17jyea" }],
7748
7767
  ["path", { d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2", key: "zix9uf" }]
7749
7768
  ];
7750
- const Copy = createLucideIcon("copy", __iconNode$b);
7769
+ const Copy = createLucideIcon("copy", __iconNode$c);
7751
7770
 
7752
7771
  /**
7753
7772
  * @license lucide-react v0.563.0 - ISC
@@ -7757,7 +7776,7 @@ const Copy = createLucideIcon("copy", __iconNode$b);
7757
7776
  */
7758
7777
 
7759
7778
 
7760
- const __iconNode$a = [
7779
+ const __iconNode$b = [
7761
7780
  [
7762
7781
  "path",
7763
7782
  {
@@ -7767,7 +7786,18 @@ const __iconNode$a = [
7767
7786
  ],
7768
7787
  ["circle", { cx: "12", cy: "12", r: "3", key: "1v7zrd" }]
7769
7788
  ];
7770
- const Eye = createLucideIcon("eye", __iconNode$a);
7789
+ const Eye = createLucideIcon("eye", __iconNode$b);
7790
+
7791
+ /**
7792
+ * @license lucide-react v0.563.0 - ISC
7793
+ *
7794
+ * This source code is licensed under the ISC license.
7795
+ * See the LICENSE file in the root directory of this source tree.
7796
+ */
7797
+
7798
+
7799
+ const __iconNode$a = [["path", { d: "M21 12a9 9 0 1 1-6.219-8.56", key: "13zald" }]];
7800
+ const LoaderCircle = createLucideIcon("loader-circle", __iconNode$a);
7771
7801
 
7772
7802
  /**
7773
7803
  * @license lucide-react v0.563.0 - ISC
@@ -7777,8 +7807,17 @@ const Eye = createLucideIcon("eye", __iconNode$a);
7777
7807
  */
7778
7808
 
7779
7809
 
7780
- const __iconNode$9 = [["path", { d: "M21 12a9 9 0 1 1-6.219-8.56", key: "13zald" }]];
7781
- const LoaderCircle = createLucideIcon("loader-circle", __iconNode$9);
7810
+ const __iconNode$9 = [
7811
+ [
7812
+ "path",
7813
+ {
7814
+ d: "M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z",
7815
+ key: "1a8usu"
7816
+ }
7817
+ ],
7818
+ ["path", { d: "m15 5 4 4", key: "1mk7zo" }]
7819
+ ];
7820
+ const Pencil = createLucideIcon("pencil", __iconNode$9);
7782
7821
 
7783
7822
  /**
7784
7823
  * @license lucide-react v0.563.0 - ISC
@@ -8517,7 +8556,7 @@ function FilterChip({ label, values, options = [], onValuesChange, onClear, inpu
8517
8556
  }, [options]);
8518
8557
  // Find selected options for chips display
8519
8558
  const selectedOptions = options.filter((opt) => values.includes(opt.value));
8520
- return (jsxs("div", { className: cn('inline-flex items-center', className), children: [jsxs(Popover.Root, { open: open, onOpenChange: handleOpenChange, children: [jsx(Popover.Trigger, { asChild: true, children: jsxs("button", { type: "button", disabled: disabled, className: cn('flex h-7 items-center gap-2 rounded-l-md border border-r-0 border-border bg-secondary px-2 text-xs', 'hover:bg-secondary/80 transition-colors', 'focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2', 'disabled:cursor-not-allowed disabled:opacity-50'), children: [jsxs("span", { className: "font-medium text-foreground", children: [label, ":"] }), jsx("span", { className: "text-foreground truncate max-w-[120px]", children: displayValue }), jsx(ChevronDown, { className: "h-3 w-3 text-muted-foreground ml-1" })] }) }), jsx(Popover.Portal, { children: jsx(Popover.Content, { className: cn('z-50 min-w-[var(--radix-popover-trigger-width)] max-w-[320px] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md', 'data-[state=open]:animate-in data-[state=closed]:animate-out', 'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0', 'data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95', 'data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2'), sideOffset: 4, align: "start", children: inputMode === 'typeahead' ? (jsxs(Command, { filter: filterOptions, className: "w-full", children: [jsx("div", { className: "flex items-center border-b px-3", children: jsx(CommandInput, { placeholder: searchPlaceholder, value: search, onValueChange: setSearch, className: "flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50" }) }), values.length > 0 && (jsx("div", { className: "flex flex-wrap gap-1 p-2 border-b", children: selectedOptions.map((option) => (jsxs("span", { className: "inline-flex items-center gap-1 px-2 py-0.5 rounded-md bg-accent text-accent-foreground text-xs", children: [option.label, jsx("button", { type: "button", onClick: (e) => handleRemoveValue(e, option.value), className: "rounded-sm hover:bg-accent-foreground/20", children: jsx(X, { className: "h-3 w-3" }) })] }, option.value))) })), jsxs(CommandList, { className: "max-h-[300px] overflow-y-auto p-1", children: [jsx(CommandEmpty, { className: "py-6 text-center text-sm text-muted-foreground", children: "No results found." }), jsx(CommandGroup, { children: options.map((option) => (jsxs(CommandItem, { value: option.value, onSelect: () => handleSelect(option.value), className: cn('relative flex cursor-pointer select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none', 'data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground', 'hover:bg-accent hover:text-accent-foreground'), children: [jsx("input", { type: "checkbox", checked: values.includes(option.value), onChange: () => { }, className: "mr-2 h-4 w-4" }), jsx("span", { className: "flex-1 truncate", children: option.label }), option.count !== undefined && (jsxs("span", { className: "ml-2 text-xs text-muted-foreground", children: ["(", option.count, ")"] }))] }, option.value))) })] })] })) : (jsx("div", { className: "p-3", children: jsx(Input, { type: "text", value: textValue, onChange: handleTextChange, placeholder: placeholder, className: "w-full", autoFocus: true }) })) }) })] }), jsx("button", { type: "button", onClick: handleClearAll, disabled: disabled, className: cn('flex h-7 items-center rounded-r-md border border-border bg-secondary px-2', 'hover:bg-secondary/80 transition-colors', 'focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2', 'disabled:cursor-not-allowed disabled:opacity-50'), "aria-label": `Clear ${label} filter`, children: jsx(X, { className: "h-3 w-3 text-muted-foreground" }) })] }));
8559
+ return (jsxs("div", { className: cn('inline-flex items-center', className), children: [jsxs(Popover.Root, { open: open, onOpenChange: handleOpenChange, children: [jsx(Popover.Trigger, { asChild: true, children: jsxs("button", { type: "button", disabled: disabled, className: cn('flex h-7 items-center gap-2 rounded-l-md border border-r-0 border-border bg-card px-2 text-xs outline-none', 'hover:bg-accent/40 data-[state=open]:bg-accent/40 transition-colors', 'disabled:cursor-not-allowed disabled:opacity-50'), children: [jsxs("span", { className: "font-medium text-foreground", children: [label, ":"] }), jsx("span", { className: "text-foreground truncate max-w-[120px]", children: displayValue }), jsx(ChevronDown, { className: "h-3 w-3 text-muted-foreground ml-1" })] }) }), jsx(Popover.Portal, { children: jsx(Popover.Content, { className: cn('z-50 min-w-[var(--radix-popover-trigger-width)] max-w-[320px] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md', 'data-[state=open]:animate-in data-[state=closed]:animate-out', 'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0', 'data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95', 'data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2'), sideOffset: 4, align: "start", children: inputMode === 'typeahead' ? (jsxs(Command, { filter: filterOptions, className: "w-full", children: [jsx("div", { className: "flex items-center border-b px-3", children: jsx(CommandInput, { placeholder: searchPlaceholder, value: search, onValueChange: setSearch, className: "flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50" }) }), values.length > 0 && (jsx("div", { className: "flex flex-wrap gap-1 p-2 border-b", children: selectedOptions.map((option) => (jsxs("span", { className: "inline-flex items-center gap-1 px-2 py-0.5 rounded-md bg-accent text-accent-foreground text-xs", children: [option.label, jsx("button", { type: "button", onClick: (e) => handleRemoveValue(e, option.value), className: "rounded-sm hover:bg-accent-foreground/20", children: jsx(X, { className: "h-3 w-3" }) })] }, option.value))) })), jsxs(CommandList, { className: "max-h-[300px] overflow-y-auto p-1", children: [jsx(CommandEmpty, { className: "py-6 text-center text-sm text-muted-foreground", children: "No results found." }), jsx(CommandGroup, { children: options.map((option) => (jsxs(CommandItem, { value: option.value, onSelect: () => handleSelect(option.value), className: cn('relative flex cursor-pointer select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none', 'data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground', 'hover:bg-accent hover:text-accent-foreground'), children: [jsx("div", { className: cn('mr-2 h-4 w-4 shrink-0 rounded-sm border border-border', values.includes(option.value) && 'bg-primary border-primary'), children: values.includes(option.value) && (jsx("svg", { viewBox: "0 0 12 12", fill: "none", className: "h-full w-full p-0.5 text-primary-foreground", children: jsx("path", { d: "M2 6l3 3 5-5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })) }), jsx("span", { className: "flex-1 truncate", children: option.label }), option.count !== undefined && (jsxs("span", { className: "ml-2 text-xs text-muted-foreground", children: ["(", option.count, ")"] }))] }, option.value))) })] })] })) : (jsx("div", { className: "p-3", children: jsx(Input, { type: "text", value: textValue, onChange: handleTextChange, placeholder: placeholder, className: "w-full", autoFocus: true }) })) }) })] }), jsx("button", { type: "button", onClick: handleClearAll, disabled: disabled, className: cn('flex h-7 items-center rounded-r-md border border-border bg-card px-2 outline-none', 'hover:bg-accent/40 transition-colors', 'disabled:cursor-not-allowed disabled:opacity-50'), "aria-label": `Clear ${label} filter`, children: jsx(X, { className: "h-3 w-3 text-muted-foreground" }) })] }));
8521
8560
  }
8522
8561
 
8523
8562
  /**
@@ -10209,13 +10248,14 @@ const TooltipContent = React.forwardRef(({ className, sideOffset = 4, ...props }
10209
10248
  TooltipContent.displayName = TooltipPrimitive.Content.displayName;
10210
10249
 
10211
10250
  /**
10212
- * Format timestamp for display (with timezone)
10251
+ * Format timestamp for display (in UTC)
10213
10252
  */
10214
10253
  function formatTimestampFull$3(timestamp) {
10215
10254
  if (!timestamp)
10216
10255
  return 'Unknown time';
10217
10256
  try {
10218
- return format(new Date(timestamp), 'yyyy-MM-dd HH:mm:ss \'UTC\'');
10257
+ const date = new Date(timestamp);
10258
+ return `${date.getUTCFullYear()}-${String(date.getUTCMonth() + 1).padStart(2, '0')}-${String(date.getUTCDate()).padStart(2, '0')} ${String(date.getUTCHours()).padStart(2, '0')}:${String(date.getUTCMinutes()).padStart(2, '0')}:${String(date.getUTCSeconds()).padStart(2, '0')} UTC`;
10219
10259
  }
10220
10260
  catch {
10221
10261
  return timestamp;
@@ -10251,11 +10291,11 @@ function CopyButton({ value, label }) {
10251
10291
  * 5. Resource - what resource was affected
10252
10292
  * 6. Origin - correlation to audit logs
10253
10293
  */
10254
- function ActivityExpandedDetails({ activity, tenantLinkResolver }) {
10294
+ function ActivityExpandedDetails({ activity, tenantLinkResolver, compact = false }) {
10255
10295
  const { spec, metadata } = activity;
10256
10296
  const { actor, resource, origin, changes, tenant } = spec;
10257
10297
  const timestamp = metadata?.creationTimestamp;
10258
- return (jsx(TooltipProvider, { children: jsxs("div", { className: "mt-4 pt-4 border-t border-border", children: [changes && changes.length > 0 && (jsxs("div", { className: "mb-3", children: [jsx("h4", { className: "m-0 mb-2 text-xs font-semibold text-muted-foreground uppercase tracking-wide", children: "Changes" }), jsx("div", { className: "flex flex-col gap-2", children: changes.map((change, index) => (jsxs("div", { className: "p-2 bg-muted rounded text-sm", children: [jsx("span", { className: "block font-semibold text-foreground mb-1 font-mono text-xs", children: change.field }), change.old && (jsxs("span", { className: "block ml-2 text-red-600 dark:text-red-400 text-xs", children: [jsx("span", { className: "font-medium mr-1", children: "\u2212" }), jsx("span", { className: "line-through", children: change.old })] })), change.new && (jsxs("span", { className: "block ml-2 text-green-600 dark:text-green-400 text-xs", children: [jsx("span", { className: "font-medium mr-1", children: "+" }), change.new] }))] }, index))) })] })), jsxs("dl", { className: "grid grid-cols-[repeat(auto-fit,minmax(250px,1fr))] gap-x-6 gap-y-2 m-0 text-xs", children: [jsxs("div", { className: "flex gap-1 items-baseline", children: [jsx("dt", { className: "text-muted-foreground shrink-0", children: "Timestamp:" }), jsxs("dd", { className: "m-0 text-foreground flex items-center min-w-0", children: [jsx("span", { className: "truncate", children: formatTimestampFull$3(timestamp) }), jsx(CopyButton, { value: formatTimestampFull$3(timestamp), label: "timestamp" })] })] }), jsxs("div", { className: "flex gap-1 items-baseline", children: [jsx("dt", { className: "text-muted-foreground shrink-0", children: "Actor Type:" }), jsxs("dd", { className: "m-0 text-foreground flex items-center min-w-0", children: [jsx("span", { className: "truncate", children: actor.type }), jsx(CopyButton, { value: actor.type, label: "actor type" })] })] }), jsxs("div", { className: "flex gap-1 items-baseline", children: [jsx("dt", { className: "text-muted-foreground shrink-0", children: "Actor:" }), jsxs("dd", { className: "m-0 text-foreground flex items-center min-w-0", children: [jsx("span", { className: "truncate", children: actor.name }), jsx(CopyButton, { value: actor.name, label: "actor name" })] })] }), resource.apiGroup && (jsxs("div", { className: "flex gap-1 items-baseline", children: [jsx("dt", { className: "text-muted-foreground shrink-0", children: "API Group:" }), jsxs("dd", { className: "m-0 text-foreground flex items-center min-w-0", children: [jsx("span", { className: "truncate", children: resource.apiGroup }), jsx(CopyButton, { value: resource.apiGroup, label: "API group" })] })] })), jsxs("div", { className: "flex gap-1 items-baseline", children: [jsx("dt", { className: "text-muted-foreground shrink-0", children: "Resource:" }), jsxs("dd", { className: "m-0 text-foreground flex items-center min-w-0", children: [jsx("span", { className: "truncate", children: resource.kind }), jsx(CopyButton, { value: resource.kind, label: "resource kind" })] })] }), jsxs("div", { className: "flex gap-1 items-baseline", children: [jsx("dt", { className: "text-muted-foreground shrink-0", children: "Resource Name:" }), jsxs("dd", { className: "m-0 text-foreground flex items-center min-w-0", children: [jsx("span", { className: "truncate", children: resource.name }), jsx(CopyButton, { value: resource.name, label: "resource name" })] })] }), resource.namespace && (jsxs("div", { className: "flex gap-1 items-baseline", children: [jsx("dt", { className: "text-muted-foreground shrink-0", children: "Namespace:" }), jsxs("dd", { className: "m-0 text-foreground flex items-center min-w-0", children: [jsx("span", { className: "truncate", children: resource.namespace }), jsx(CopyButton, { value: resource.namespace, label: "namespace" })] })] })), resource.uid && (jsxs("div", { className: "flex gap-1 items-baseline", children: [jsx("dt", { className: "text-muted-foreground shrink-0", children: "Resource UID:" }), jsxs("dd", { className: "m-0 font-mono text-muted-foreground flex items-center min-w-0", children: [jsx("span", { className: "truncate", children: resource.uid }), jsx(CopyButton, { value: resource.uid, label: "resource UID" })] })] })), jsxs("div", { className: "flex gap-1 items-baseline", children: [jsx("dt", { className: "text-muted-foreground shrink-0", children: "Origin:" }), jsxs("dd", { className: "m-0 text-foreground flex items-center min-w-0", children: [jsx("span", { className: "truncate", children: origin.type }), jsx(CopyButton, { value: origin.type, label: "origin type" })] })] }), jsxs("div", { className: "flex gap-1 items-baseline", children: [jsx("dt", { className: "text-muted-foreground shrink-0", children: "Origin ID:" }), jsxs("dd", { className: "m-0 font-mono text-muted-foreground flex items-center min-w-0", children: [jsx("span", { className: "truncate", children: origin.id }), jsx(CopyButton, { value: origin.id, label: "origin ID" })] })] })] })] }) }));
10298
+ return (jsx(TooltipProvider, { children: jsxs("div", { className: compact ? 'p-4 bg-muted/30' : 'mt-4 pt-4 border-t border-border', children: [changes && changes.length > 0 && (jsxs("div", { className: "mb-3", children: [jsx("h4", { className: "m-0 mb-2 text-xs font-semibold text-muted-foreground uppercase tracking-wide", children: "Changes" }), jsx("div", { className: "flex flex-col gap-2", children: changes.map((change, index) => (jsxs("div", { className: "p-2 bg-muted rounded text-sm", children: [jsx("span", { className: "block font-semibold text-foreground mb-1 font-mono text-xs", children: change.field }), change.old && (jsxs("span", { className: "block ml-2 text-red-600 dark:text-red-400 text-xs", children: [jsx("span", { className: "font-medium mr-1", children: "\u2212" }), jsx("span", { className: "line-through", children: change.old })] })), change.new && (jsxs("span", { className: "block ml-2 text-green-600 dark:text-green-400 text-xs", children: [jsx("span", { className: "font-medium mr-1", children: "+" }), change.new] }))] }, index))) })] })), jsxs("dl", { className: "grid grid-cols-[repeat(auto-fit,minmax(250px,1fr))] gap-x-6 gap-y-2 m-0 text-xs", children: [jsxs("div", { className: "flex gap-1 items-baseline", children: [jsx("dt", { className: "text-muted-foreground shrink-0", children: "Timestamp:" }), jsxs("dd", { className: "m-0 text-foreground flex items-center min-w-0", children: [jsx("span", { className: "truncate", children: formatTimestampFull$3(timestamp) }), jsx(CopyButton, { value: formatTimestampFull$3(timestamp), label: "timestamp" })] })] }), jsxs("div", { className: "flex gap-1 items-baseline", children: [jsx("dt", { className: "text-muted-foreground shrink-0", children: "Actor Type:" }), jsxs("dd", { className: "m-0 text-foreground flex items-center min-w-0", children: [jsx("span", { className: "truncate", children: actor.type }), jsx(CopyButton, { value: actor.type, label: "actor type" })] })] }), jsxs("div", { className: "flex gap-1 items-baseline", children: [jsx("dt", { className: "text-muted-foreground shrink-0", children: "Actor:" }), jsxs("dd", { className: "m-0 text-foreground flex items-center min-w-0", children: [jsx("span", { className: "truncate", children: actor.name }), jsx(CopyButton, { value: actor.name, label: "actor name" })] })] }), resource.apiGroup && (jsxs("div", { className: "flex gap-1 items-baseline", children: [jsx("dt", { className: "text-muted-foreground shrink-0", children: "API Group:" }), jsxs("dd", { className: "m-0 text-foreground flex items-center min-w-0", children: [jsx("span", { className: "truncate", children: resource.apiGroup }), jsx(CopyButton, { value: resource.apiGroup, label: "API group" })] })] })), jsxs("div", { className: "flex gap-1 items-baseline", children: [jsx("dt", { className: "text-muted-foreground shrink-0", children: "Resource:" }), jsxs("dd", { className: "m-0 text-foreground flex items-center min-w-0", children: [jsx("span", { className: "truncate", children: resource.kind }), jsx(CopyButton, { value: resource.kind, label: "resource kind" })] })] }), jsxs("div", { className: "flex gap-1 items-baseline", children: [jsx("dt", { className: "text-muted-foreground shrink-0", children: "Resource Name:" }), jsxs("dd", { className: "m-0 text-foreground flex items-center min-w-0", children: [jsx("span", { className: "truncate", children: resource.name }), jsx(CopyButton, { value: resource.name, label: "resource name" })] })] }), resource.namespace && (jsxs("div", { className: "flex gap-1 items-baseline", children: [jsx("dt", { className: "text-muted-foreground shrink-0", children: "Namespace:" }), jsxs("dd", { className: "m-0 text-foreground flex items-center min-w-0", children: [jsx("span", { className: "truncate", children: resource.namespace }), jsx(CopyButton, { value: resource.namespace, label: "namespace" })] })] })), resource.uid && (jsxs("div", { className: "flex gap-1 items-baseline", children: [jsx("dt", { className: "text-muted-foreground shrink-0", children: "Resource UID:" }), jsxs("dd", { className: "m-0 font-mono text-muted-foreground flex items-center min-w-0", children: [jsx("span", { className: "truncate", children: resource.uid }), jsx(CopyButton, { value: resource.uid, label: "resource UID" })] })] })), jsxs("div", { className: "flex gap-1 items-baseline", children: [jsx("dt", { className: "text-muted-foreground shrink-0", children: "Origin:" }), jsxs("dd", { className: "m-0 text-foreground flex items-center min-w-0", children: [jsx("span", { className: "truncate", children: origin.type }), jsx(CopyButton, { value: origin.type, label: "origin type" })] })] }), jsxs("div", { className: "flex gap-1 items-baseline", children: [jsx("dt", { className: "text-muted-foreground shrink-0", children: "Origin ID:" }), jsxs("dd", { className: "m-0 font-mono text-muted-foreground flex items-center min-w-0", children: [jsx("span", { className: "truncate", children: origin.id }), jsx(CopyButton, { value: origin.id, label: "origin ID" })] })] })] })] }) }));
10259
10299
  }
10260
10300
 
10261
10301
  /**
@@ -10273,13 +10313,14 @@ function formatTimestamp$1(timestamp) {
10273
10313
  }
10274
10314
  }
10275
10315
  /**
10276
- * Format timestamp for tooltip (with timezone)
10316
+ * Format timestamp for tooltip (in UTC)
10277
10317
  */
10278
10318
  function formatTimestampFull$2(timestamp) {
10279
10319
  if (!timestamp)
10280
10320
  return 'Unknown time';
10281
10321
  try {
10282
- return format(new Date(timestamp), 'yyyy-MM-dd HH:mm:ss \'UTC\'');
10322
+ const date = new Date(timestamp);
10323
+ return `${date.getUTCFullYear()}-${String(date.getUTCMonth() + 1).padStart(2, '0')}-${String(date.getUTCDate()).padStart(2, '0')} ${String(date.getUTCHours()).padStart(2, '0')}:${String(date.getUTCMinutes()).padStart(2, '0')}:${String(date.getUTCSeconds()).padStart(2, '0')} UTC`;
10283
10324
  }
10284
10325
  catch {
10285
10326
  return timestamp;
@@ -10336,25 +10377,41 @@ function normalizeVerb(verb) {
10336
10377
  return 'other';
10337
10378
  }
10338
10379
  /**
10339
- * Get timeline node classes based on verb
10380
+ * Get icon container + icon color classes based on verb
10340
10381
  */
10341
- function getTimelineNodeClasses(verb) {
10382
+ function getActionIconClasses(verb) {
10342
10383
  const normalizedVerb = normalizeVerb(verb);
10343
10384
  switch (normalizedVerb) {
10344
10385
  case 'create':
10345
- return 'bg-green-500';
10386
+ return { container: 'bg-blue-50 dark:bg-blue-950', icon: 'text-blue-500 dark:text-blue-400' };
10346
10387
  case 'update':
10347
- return 'bg-amber-500';
10388
+ return { container: 'bg-green-50 dark:bg-green-950', icon: 'text-green-600 dark:text-green-400' };
10348
10389
  case 'delete':
10349
- return 'bg-red-500';
10390
+ return { container: 'bg-red-50 dark:bg-red-950', icon: 'text-red-500 dark:text-red-400' };
10350
10391
  default:
10351
- return 'bg-muted-foreground';
10392
+ return { container: 'bg-slate-100 dark:bg-slate-800', icon: 'text-slate-500 dark:text-slate-400' };
10393
+ }
10394
+ }
10395
+ /**
10396
+ * Get the Lucide icon component for the timeline node based on verb
10397
+ */
10398
+ function getTimelineIcon(verb) {
10399
+ const normalizedVerb = normalizeVerb(verb);
10400
+ switch (normalizedVerb) {
10401
+ case 'create':
10402
+ return Plus;
10403
+ case 'update':
10404
+ return Pencil;
10405
+ case 'delete':
10406
+ return Trash2;
10407
+ default:
10408
+ return Activity;
10352
10409
  }
10353
10410
  }
10354
10411
  /**
10355
10412
  * ActivityFeedItem renders a single activity in the feed or timeline
10356
10413
  */
10357
- function ActivityFeedItem({ activity, onResourceClick, resourceLinkResolver, tenantLinkResolver, tenantRenderer, onActorClick, onActivityClick, isSelected = false, className = '', compact = false, isNew = false, variant = 'feed', isFirst = false, isLast = false, defaultExpanded = false, }) {
10414
+ function ActivityFeedItem({ activity, onResourceClick, resourceLinkResolver, tenantLinkResolver, tenantRenderer, onActorClick, onActivityClick, isSelected = false, className = '', compact = false, isNew = false, variant = 'feed', isLast = false, defaultExpanded = false, }) {
10358
10415
  const [isExpanded, setIsExpanded] = useState(defaultExpanded);
10359
10416
  const { spec, metadata } = activity;
10360
10417
  const { actor, summary, links, tenant } = spec;
@@ -10374,9 +10431,11 @@ function ActivityFeedItem({ activity, onResourceClick, resourceLinkResolver, ten
10374
10431
  const timestamp = metadata?.creationTimestamp;
10375
10432
  const verb = extractVerb(summary);
10376
10433
  const isTimeline = variant === 'timeline';
10377
- // Timeline variant wrapper
10434
+ // Timeline variant — flat list row with bottom border
10378
10435
  if (isTimeline) {
10379
- return (jsxs("div", { className: cn('relative cursor-pointer group flex', compact ? 'pl-7' : 'pl-9', className), onClick: handleClick, children: [jsxs("div", { className: cn('absolute left-0 top-0 bottom-0 flex flex-col items-center', compact ? 'w-7' : 'w-9'), children: [jsx("div", { className: cn('w-0.5 flex-1', isFirst ? 'bg-transparent' : 'bg-border'), style: { minHeight: compact ? 12 : 16 } }), jsx("div", { className: cn('rounded-full shrink-0 z-10', compact ? 'w-2.5 h-2.5' : 'w-3 h-3', getTimelineNodeClasses(verb)) }), jsx("div", { className: cn('w-0.5 flex-1', isLast ? 'bg-transparent' : 'bg-border') })] }), jsxs("div", { className: cn('flex-1 border border-border rounded-lg transition-all duration-200 bg-card', 'shadow-sm hover:shadow-md hover:-translate-y-0.5', 'hover:border-primary/30 dark:hover:border-primary/40', compact ? 'p-2 mb-2' : 'p-2.5 mb-2', isSelected && 'border-primary bg-primary/5 ring-1 ring-primary/20 dark:bg-primary/10'), children: [jsxs("div", { className: "flex items-center gap-2", children: [jsx("div", { className: "flex-1 min-w-0 text-xs leading-snug", children: jsx(ActivityFeedSummary, { summary: summary, links: links, onResourceClick: onResourceClick, resourceLinkResolver: resourceLinkResolver, resourceLinkContext: { tenant } }) }), tenant && (jsx("div", { className: "shrink-0", children: tenantRenderer ? tenantRenderer(tenant) : jsx(TenantBadge, { tenant: tenant, tenantLinkResolver: tenantLinkResolver, size: "compact" }) })), jsx("span", { className: "text-xs text-muted-foreground whitespace-nowrap shrink-0", title: formatTimestampFull$2(timestamp), children: formatTimestamp$1(timestamp) }), jsx(Button, { variant: "ghost", size: "sm", className: "h-5 py-0 px-1 text-base text-muted-foreground hover:text-foreground shrink-0", onClick: toggleExpand, "aria-expanded": isExpanded, children: isExpanded ? '−' : '+' })] }), isExpanded && jsx(ActivityExpandedDetails, { activity: activity, tenantLinkResolver: tenantLinkResolver })] })] }));
10436
+ const { container: iconBg, icon: iconColor } = getActionIconClasses(verb);
10437
+ const Icon = getTimelineIcon(verb);
10438
+ return (jsxs("div", { className: cn(!isLast && !isExpanded && 'border-b border-border', className), children: [jsxs("div", { className: cn('flex items-center gap-3 py-3 pl-4 cursor-pointer group', isSelected && 'bg-muted/40'), onClick: toggleExpand, children: [jsx("div", { className: cn('w-8 h-8 rounded-md shrink-0 flex items-center justify-center', iconBg, iconColor), children: jsx(Icon, { size: 16, strokeWidth: 2 }) }), jsx("div", { className: "flex-1 min-w-0 text-sm text-foreground leading-snug", children: jsx(ActivityFeedSummary, { summary: summary, links: links, onResourceClick: onResourceClick, resourceLinkResolver: resourceLinkResolver, resourceLinkContext: { tenant } }) }), tenant && (jsx("div", { className: "shrink-0", children: tenantRenderer ? tenantRenderer(tenant) : jsx(TenantBadge, { tenant: tenant, tenantLinkResolver: tenantLinkResolver, size: "compact" }) })), jsx("span", { className: "text-xs text-muted-foreground whitespace-nowrap shrink-0", title: formatTimestampFull$2(timestamp), children: formatTimestamp$1(timestamp) }), jsx(Button, { variant: "ghost", size: "sm", className: "h-5 py-0 px-1 text-base text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity shrink-0", onClick: toggleExpand, "aria-expanded": isExpanded, children: isExpanded ? '−' : '+' })] }), isExpanded && (jsx(ActivityExpandedDetails, { activity: activity, tenantLinkResolver: tenantLinkResolver, compact: true }))] }));
10380
10439
  }
10381
10440
  // Feed variant (single-row layout)
10382
10441
  return (jsxs(Card, { className: cn('cursor-pointer transition-all duration-200', 'shadow-sm hover:shadow-md hover:-translate-y-0.5', 'hover:border-primary/30 dark:hover:border-primary/40', compact ? 'p-1.5 mb-1' : 'p-4 mb-3', isSelected && 'border-primary bg-primary/5 shadow-md ring-1 ring-primary/20 dark:bg-primary/10', isNew && 'border-l-4 border-l-green-500 bg-green-50/50 dark:border-l-green-400 dark:bg-green-950/30', className), onClick: handleClick, children: [jsxs("div", { className: "flex items-center gap-2", children: [jsx("div", { className: cn(getActorAvatarClasses(actor.type, compact), onActorClick && 'cursor-pointer hover:opacity-80 transition-opacity'), title: actor.name, onClick: onActorClick ? handleActorClick : undefined, children: actor.type === 'controller' ? (jsx("span", { className: "text-xs", children: "\u2699" })) : actor.type === 'machine account' ? (jsx("span", { className: "text-xs", children: "\uD83E\uDD16" })) : (jsx("span", { className: "uppercase", children: getActorInitials(actor.name) })) }), jsx("div", { className: "flex-1 min-w-0 text-xs leading-snug", children: jsx(ActivityFeedSummary, { summary: summary, links: links, onResourceClick: onResourceClick, resourceLinkResolver: resourceLinkResolver, resourceLinkContext: { tenant } }) }), tenant && (jsx("div", { className: "shrink-0", children: tenantRenderer ? tenantRenderer(tenant) : jsx(TenantBadge, { tenant: tenant, tenantLinkResolver: tenantLinkResolver, size: "compact" }) })), jsx("span", { className: "text-xs text-muted-foreground whitespace-nowrap shrink-0", title: formatTimestampFull$2(timestamp), children: formatTimestamp$1(timestamp) }), jsx(Button, { variant: "ghost", size: "sm", className: "h-5 py-0 px-1 text-base text-muted-foreground hover:text-foreground shrink-0", onClick: toggleExpand, "aria-expanded": isExpanded, children: isExpanded ? '−' : '+' })] }), isExpanded && jsx(ActivityExpandedDetails, { activity: activity, tenantLinkResolver: tenantLinkResolver })] }));
@@ -10696,19 +10755,22 @@ function ActivityFeedFilters({ client, filters, timeRange, onFiltersChange, onTi
10696
10755
  return 'Select time range';
10697
10756
  };
10698
10757
  // Determine which filters are currently active (have values) and not hidden
10699
- const filtersWithValues = [];
10700
- if (filters.resourceKinds && filters.resourceKinds.length > 0 && !hiddenFilters.includes('resourceKinds'))
10701
- filtersWithValues.push('resourceKinds');
10702
- if (filters.actorNames && filters.actorNames.length > 0 && !hiddenFilters.includes('actorNames'))
10703
- filtersWithValues.push('actorNames');
10704
- if (filters.apiGroups && filters.apiGroups.length > 0 && !hiddenFilters.includes('apiGroups'))
10705
- filtersWithValues.push('apiGroups');
10706
- if (filters.resourceNamespaces && filters.resourceNamespaces.length > 0 && !hiddenFilters.includes('resourceNamespaces'))
10707
- filtersWithValues.push('resourceNamespaces');
10708
- if (filters.resourceName && !hiddenFilters.includes('resourceName'))
10709
- filtersWithValues.push('resourceName');
10710
- if (filters.actions && filters.actions.length > 0)
10711
- filtersWithValues.push('actions');
10758
+ const filtersWithValues = useMemo(() => {
10759
+ const result = [];
10760
+ if (filters.resourceKinds && filters.resourceKinds.length > 0 && !hiddenFilters.includes('resourceKinds'))
10761
+ result.push('resourceKinds');
10762
+ if (filters.actorNames && filters.actorNames.length > 0 && !hiddenFilters.includes('actorNames'))
10763
+ result.push('actorNames');
10764
+ if (filters.apiGroups && filters.apiGroups.length > 0 && !hiddenFilters.includes('apiGroups'))
10765
+ result.push('apiGroups');
10766
+ if (filters.resourceNamespaces && filters.resourceNamespaces.length > 0 && !hiddenFilters.includes('resourceNamespaces'))
10767
+ result.push('resourceNamespaces');
10768
+ if (filters.resourceName && !hiddenFilters.includes('resourceName'))
10769
+ result.push('resourceName');
10770
+ if (filters.actions && filters.actions.length > 0)
10771
+ result.push('actions');
10772
+ return result;
10773
+ }, [filters, hiddenFilters]);
10712
10774
  // Include pendingFilter (newly added filter awaiting value selection) in the displayed filters
10713
10775
  const activeFilterIds = pendingFilter && !filtersWithValues.includes(pendingFilter)
10714
10776
  ? [...filtersWithValues, pendingFilter]
@@ -10727,7 +10789,7 @@ function ActivityFeedFilters({ client, filters, timeRange, onFiltersChange, onTi
10727
10789
  { id: 'apiGroups', label: 'API Group' },
10728
10790
  { id: 'resourceNamespaces', label: 'Namespace' },
10729
10791
  { id: 'resourceName', label: 'Resource Name' },
10730
- { id: 'actions', label: 'Action' },
10792
+ // 'actions' hidden until backend facet support is available
10731
10793
  ].filter((filter) => !hiddenFilters.includes(filter.id));
10732
10794
  // Handle adding a filter
10733
10795
  const handleAddFilter = useCallback((filterId) => {
@@ -10814,15 +10876,37 @@ function ActivityFeedFilters({ client, filters, timeRange, onFiltersChange, onTi
10814
10876
  }
10815
10877
  return value || [];
10816
10878
  };
10817
- // Handle search input change with debouncing
10879
+ // Local search value for debouncing — keeps input responsive while query runs
10880
+ const [searchInputValue, setSearchInputValue] = useState(filters.search || '');
10881
+ const searchDebounceRef = useRef(null);
10882
+ // Use refs so the debounced callback never closes over stale values
10883
+ const filtersRef = useRef(filters);
10884
+ filtersRef.current = filters;
10885
+ const onFiltersChangeRef = useRef(onFiltersChange);
10886
+ onFiltersChangeRef.current = onFiltersChange;
10887
+ // Cancel any pending debounce on unmount
10888
+ useEffect(() => {
10889
+ return () => {
10890
+ if (searchDebounceRef.current)
10891
+ clearTimeout(searchDebounceRef.current);
10892
+ };
10893
+ }, []);
10818
10894
  const handleSearchChange = useCallback((event) => {
10819
10895
  const value = event.target.value;
10820
- onFiltersChange({
10821
- ...filters,
10822
- search: value || undefined,
10823
- });
10824
- }, [filters, onFiltersChange]);
10825
- return (jsx("div", { className: `mb-3 pb-3 border-b border-border pr-2 ${className}`, children: jsxs("div", { className: "flex flex-wrap gap-2 items-center", children: [!hiddenFilters.includes('changeSource') && (jsx(ChangeSourceToggle, { value: filters.changeSource || 'all', onChange: handleChangeSourceChange, disabled: disabled })), jsxs("div", { className: "relative min-w-[200px] flex-1 max-w-xs", children: [jsx(Search, { className: "absolute left-2 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" }), jsx(Input, { type: "text", placeholder: "Search activities...", value: filters.search || '', onChange: handleSearchChange, disabled: disabled, className: "pl-8 h-7 text-xs" })] }), activeFilterIds.map((filterId) => {
10896
+ setSearchInputValue(value);
10897
+ if (searchDebounceRef.current)
10898
+ clearTimeout(searchDebounceRef.current);
10899
+ searchDebounceRef.current = setTimeout(() => {
10900
+ onFiltersChangeRef.current({ ...filtersRef.current, search: value || undefined });
10901
+ }, 400);
10902
+ }, []);
10903
+ const handleSearchClear = useCallback(() => {
10904
+ setSearchInputValue('');
10905
+ if (searchDebounceRef.current)
10906
+ clearTimeout(searchDebounceRef.current);
10907
+ onFiltersChangeRef.current({ ...filtersRef.current, search: undefined });
10908
+ }, []);
10909
+ return (jsx("div", { className: `mb-3 pb-3 border-b border-border p-4 ${className}`, children: jsxs("div", { className: "flex flex-wrap gap-2 items-center", children: [!hiddenFilters.includes('changeSource') && (jsx(ChangeSourceToggle, { value: filters.changeSource || 'all', onChange: handleChangeSourceChange, disabled: disabled })), jsxs("div", { className: "relative min-w-[200px] flex-1 max-w-xs", children: [jsx(Search, { className: "absolute left-2 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground" }), jsx(Input, { type: "text", placeholder: "Search activities...", value: searchInputValue, onChange: handleSearchChange, className: "pl-8 h-7 text-xs pr-6" }), searchInputValue && (jsx("button", { onClick: handleSearchClear, className: "absolute right-1.5 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground transition-colors", "aria-label": "Clear search", children: jsx(X, { className: "h-3.5 w-3.5" }) }))] }), activeFilterIds.map((filterId) => {
10826
10910
  const config = FILTER_CONFIGS$1[filterId];
10827
10911
  return (jsx(FilterChip, { label: config.label, values: getFilterValues(filterId), options: config.inputMode === 'typeahead' ? getFilterOptions(filterId) : undefined, onValuesChange: (values) => handleFilterChange(filterId, values), onClear: () => handleFilterClear(filterId), onPopoverClose: () => handlePopoverClose(filterId), inputMode: config.inputMode, placeholder: config.placeholder, searchPlaceholder: config.searchPlaceholder, autoOpen: pendingFilter === filterId, disabled: disabled }, filterId));
10828
10912
  }), jsx(AddFilterDropdown, { availableFilters: availableFilters, activeFilterIds: activeFilterIds, onAddFilter: handleAddFilter, hasActiveFilters: activeFilterIds.length > 0, disabled: disabled }), jsx("div", { className: "flex-1 min-w-[20px]" }), jsx(TimeRangeDropdown, { presets: TIME_PRESETS$1, selectedPreset: selectedPreset, onPresetSelect: handleTimePresetSelect, onCustomRangeApply: handleCustomRangeApply, customStart: customStart, customEnd: customEnd, disabled: disabled, displayLabel: getTimeRangeLabel() })] }) }));
@@ -10832,7 +10916,7 @@ function ActivityFeedFilters({ client, filters, timeRange, onFiltersChange, onTi
10832
10916
  * ActivityFeed displays a chronological list of activities with filtering and pagination.
10833
10917
  * Supports optional real-time streaming of new activities.
10834
10918
  */
10835
- function ActivityFeed({ client, initialFilters = { changeSource: 'human' }, initialTimeRange = { start: 'now-7d' }, pageSize = 30, onResourceClick, resourceLinkResolver, tenantLinkResolver, tenantRenderer, onActivityClick, compact = false, resourceUid, showFilters = true, hiddenFilters = [], className = '', infiniteScroll = true, loadMoreThreshold = 200, onCreatePolicy, enableStreaming = false, onEffectiveTimeRangeChange, errorFormatter, maxHeight, onFiltersChange: onFiltersChangeProp, }) {
10919
+ function ActivityFeed({ client, initialFilters = { changeSource: 'human' }, initialTimeRange = { start: 'now-7d' }, pageSize = 30, onResourceClick, resourceLinkResolver, tenantLinkResolver, tenantRenderer, onActivityClick, compact = false, variant = 'feed', resourceUid, showFilters = true, hiddenFilters = [], className = '', infiniteScroll = true, loadMoreThreshold = 200, onCreatePolicy, enableStreaming = false, onEffectiveTimeRangeChange, errorFormatter, maxHeight, onFiltersChange: onFiltersChangeProp, }) {
10836
10920
  // Merge resourceUid into initial filters if provided
10837
10921
  const mergedInitialFilters = {
10838
10922
  ...initialFilters,
@@ -10932,13 +11016,13 @@ function ActivityFeed({ client, initialFilters = { changeSource: 'human' }, init
10932
11016
  // Build container classes - use flex layout to properly fill available space
10933
11017
  // flex-1 min-h-0 allows the Card to fill parent flex container and enable child scrolling
10934
11018
  const containerClasses = compact
10935
- ? `flex-1 min-h-0 flex flex-col p-1 shadow-none border-border ${className}`
11019
+ ? `flex-1 min-h-0 flex flex-col p-0 shadow-none border-none ${className}`
10936
11020
  : `flex-1 min-h-0 flex flex-col p-3 ${className}`;
10937
11021
  // Build list classes - use flex-1 min-h-0 for flex-based scrolling
10938
11022
  // Parent containers must have proper height constraints (h-screen/h-full + overflow-hidden)
10939
11023
  const effectiveMaxHeight = maxHeight === 'none' ? undefined : maxHeight;
10940
- const listClasses = 'flex-1 min-h-0 overflow-y-auto pr-2 flex flex-col';
10941
- return (jsxs(Card, { className: containerClasses, children: [enableStreaming && (jsxs("div", { className: "flex items-center justify-between mb-1 pb-0.5 border-b border-border", children: [jsxs("div", { className: "flex items-center gap-2", children: [isStreaming && !watchError && (jsx(TooltipProvider, { delayDuration: 300, children: jsxs(Tooltip, { children: [jsx(TooltipTrigger, { asChild: true, children: jsxs("div", { className: "flex items-center gap-2", children: [jsxs("span", { className: "relative flex h-2 w-2", children: [jsx("span", { className: "animate-ping absolute inline-flex h-full w-full rounded-full bg-green-400 dark:bg-green-500 opacity-75" }), jsx("span", { className: "relative inline-flex rounded-full h-2 w-2 bg-green-500 dark:bg-green-400" })] }), jsx("span", { className: "text-xs text-muted-foreground", children: "Streaming activity..." })] }) }), jsx(TooltipContent, { className: "text-xs", children: jsx("p", { children: "New activities will appear automatically" }) })] }) })), watchError && (jsx(TooltipProvider, { delayDuration: 300, children: jsxs(Tooltip, { children: [jsx(TooltipTrigger, { asChild: true, children: jsxs("div", { className: "flex items-center gap-2", children: [jsx("span", { className: "relative flex h-2 w-2", children: jsx("span", { className: "relative inline-flex rounded-full h-2 w-2 bg-red-500 dark:bg-red-400" }) }), jsx("span", { className: "text-xs text-destructive", children: "Connection error" })] }) }), jsx(TooltipContent, { className: "text-xs", children: jsx("p", { children: "Stream connection lost" }) })] }) })), newActivitiesCount > 0 && !watchError && (jsxs(Badge, { variant: "secondary", className: "text-xs", children: ["+", newActivitiesCount, " new"] }))] }), jsx(Button, { variant: "ghost", size: "sm", onClick: handleStreamingToggle, className: "text-xs", children: watchError ? (jsxs(Fragment, { children: [jsxs("svg", { className: "w-4 h-4 mr-1.5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", strokeWidth: "2", children: [jsx("path", { d: "M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4" }), jsx("circle", { cx: "12", cy: "12", r: "3" })] }), "Retry"] })) : isStreaming ? (jsxs(Fragment, { children: [jsxs("svg", { className: "w-4 h-4 mr-1.5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: [jsx("rect", { x: "6", y: "4", width: "4", height: "16" }), jsx("rect", { x: "14", y: "4", width: "4", height: "16" })] }), "Pause"] })) : (jsxs(Fragment, { children: [jsx("svg", { className: "w-4 h-4 mr-1.5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: jsx("polygon", { points: "5,3 19,12 5,21", fill: "currentColor" }) }), "Resume"] })) })] })), showFilters && (jsx(ActivityFeedFilters, { client: client, filters: filters, timeRange: timeRange, onFiltersChange: handleFiltersChange, onTimeRangeChange: handleTimeRangeChange, disabled: isLoading, hiddenFilters: hiddenFilters })), jsx(ApiErrorAlert, { error: error, onRetry: refresh, className: "mb-4", errorFormatter: errorFormatter }), jsx(ApiErrorAlert, { error: watchError, onRetry: startStreaming, className: "mb-4", errorFormatter: errorFormatter }), !policiesLoading && hasPolicies === false && (jsxs("div", { className: "flex flex-col items-center py-12 px-8 text-center bg-muted border border-dashed border-border rounded-xl mb-4", children: [jsx("div", { className: "flex justify-center mb-4 text-muted-foreground", children: jsxs("svg", { width: "56", height: "56", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [jsx("path", { d: "M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2" }), jsx("rect", { x: "9", y: "3", width: "6", height: "4", rx: "1" }), jsx("path", { d: "M9 12h6" }), jsx("path", { d: "M9 16h6" })] }) }), jsx("h3", { className: "m-0 mb-2 text-lg font-semibold text-foreground leading-snug", children: "Get started with activity logging" }), jsx("p", { className: "m-0 mb-6 text-sm leading-relaxed text-muted-foreground max-w-[400px]", children: "Activity policies define which resources to track and how to summarize changes. Create your first policy to start seeing activity logs here." }), onCreatePolicy && (jsx(Button, { onClick: onCreatePolicy, children: "Create Policy" }))] })), jsxs("div", { className: listClasses, ref: scrollContainerRef, style: { gap: compact ? '0.25rem' : '0.5rem', ...(effectiveMaxHeight ? { maxHeight: effectiveMaxHeight } : {}) }, children: [isLoading && activities.length === 0 && (jsx(Fragment, { children: Array.from({ length: 8 }).map((_, index) => (jsx(ActivityFeedItemSkeleton, { compact: compact }, index))) })), !isLoading && activities.length === 0 && hasPolicies !== false && (jsxs("div", { className: "py-12 text-center text-muted-foreground", children: [jsx("p", { className: "m-0", children: "No activities found" }), jsx("p", { className: "text-sm text-muted-foreground mt-2 m-0", children: "Try adjusting your filters or time range" })] })), activities.map((activity, index) => (jsx(ActivityFeedItem, { activity: activity, onResourceClick: onResourceClick, resourceLinkResolver: resourceLinkResolver, tenantLinkResolver: tenantLinkResolver, tenantRenderer: tenantRenderer, onActorClick: handleActorClick, onActivityClick: onActivityClick, compact: compact, isNew: enableStreaming && index < newActivitiesCount }, activity.metadata?.uid || activity.metadata?.name))), infiniteScroll && hasMore && (jsx("div", { ref: loadMoreTriggerRef, className: "h-px mt-4" })), !infiniteScroll && hasMore && !isLoading && (jsx("div", { className: "flex justify-center p-4 mt-4", children: jsx(Button, { onClick: handleLoadMoreClick, children: "Load more" }) })), !hasMore && activities.length > 0 && !isLoading && (jsx("div", { className: "text-center py-6 text-muted-foreground text-sm border-t border-border mt-4", children: "No more activities to load" }))] })] }));
11024
+ const listClasses = 'flex-1 min-h-0 overflow-y-auto flex flex-col';
11025
+ return (jsxs(Card, { className: containerClasses, children: [enableStreaming && (jsxs("div", { className: "flex items-center justify-between mb-1 pb-0.5 border-b border-border", children: [jsxs("div", { className: "flex items-center gap-2", children: [isStreaming && !watchError && (jsx(TooltipProvider, { delayDuration: 300, children: jsxs(Tooltip, { children: [jsx(TooltipTrigger, { asChild: true, children: jsxs("div", { className: "flex items-center gap-2", children: [jsxs("span", { className: "relative flex h-2 w-2", children: [jsx("span", { className: "animate-ping absolute inline-flex h-full w-full rounded-full bg-green-400 dark:bg-green-500 opacity-75" }), jsx("span", { className: "relative inline-flex rounded-full h-2 w-2 bg-green-500 dark:bg-green-400" })] }), jsx("span", { className: "text-xs text-muted-foreground", children: "Streaming activity..." })] }) }), jsx(TooltipContent, { className: "text-xs", children: jsx("p", { children: "New activities will appear automatically" }) })] }) })), watchError && (jsx(TooltipProvider, { delayDuration: 300, children: jsxs(Tooltip, { children: [jsx(TooltipTrigger, { asChild: true, children: jsxs("div", { className: "flex items-center gap-2", children: [jsx("span", { className: "relative flex h-2 w-2", children: jsx("span", { className: "relative inline-flex rounded-full h-2 w-2 bg-red-500 dark:bg-red-400" }) }), jsx("span", { className: "text-xs text-destructive", children: "Connection error" })] }) }), jsx(TooltipContent, { className: "text-xs", children: jsx("p", { children: "Stream connection lost" }) })] }) })), newActivitiesCount > 0 && !watchError && (jsxs(Badge, { variant: "secondary", className: "text-xs", children: ["+", newActivitiesCount, " new"] }))] }), jsx(Button, { variant: "ghost", size: "sm", onClick: handleStreamingToggle, className: "text-xs", children: watchError ? (jsxs(Fragment, { children: [jsxs("svg", { className: "w-4 h-4 mr-1.5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", strokeWidth: "2", children: [jsx("path", { d: "M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4" }), jsx("circle", { cx: "12", cy: "12", r: "3" })] }), "Retry"] })) : isStreaming ? (jsxs(Fragment, { children: [jsxs("svg", { className: "w-4 h-4 mr-1.5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: [jsx("rect", { x: "6", y: "4", width: "4", height: "16" }), jsx("rect", { x: "14", y: "4", width: "4", height: "16" })] }), "Pause"] })) : (jsxs(Fragment, { children: [jsx("svg", { className: "w-4 h-4 mr-1.5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: jsx("polygon", { points: "5,3 19,12 5,21", fill: "currentColor" }) }), "Resume"] })) })] })), showFilters && (jsx(ActivityFeedFilters, { client: client, filters: filters, timeRange: timeRange, onFiltersChange: handleFiltersChange, onTimeRangeChange: handleTimeRangeChange, disabled: isLoading, hiddenFilters: hiddenFilters })), jsx(ApiErrorAlert, { error: error, onRetry: refresh, className: "mb-4", errorFormatter: errorFormatter }), jsx(ApiErrorAlert, { error: watchError, onRetry: startStreaming, className: "mb-4", errorFormatter: errorFormatter }), !policiesLoading && hasPolicies === false && (jsxs("div", { className: "flex flex-col items-center py-12 px-8 text-center bg-muted border border-dashed border-border rounded-xl mb-4", children: [jsx("div", { className: "flex justify-center mb-4 text-muted-foreground", children: jsxs("svg", { width: "56", height: "56", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: [jsx("path", { d: "M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2" }), jsx("rect", { x: "9", y: "3", width: "6", height: "4", rx: "1" }), jsx("path", { d: "M9 12h6" }), jsx("path", { d: "M9 16h6" })] }) }), jsx("h3", { className: "m-0 mb-2 text-lg font-semibold text-foreground leading-snug", children: "Get started with activity logging" }), jsx("p", { className: "m-0 mb-6 text-sm leading-relaxed text-muted-foreground max-w-[400px]", children: "Activity policies define which resources to track and how to summarize changes. Create your first policy to start seeing activity logs here." }), onCreatePolicy && (jsx(Button, { onClick: onCreatePolicy, children: "Create Policy" }))] })), jsxs("div", { className: listClasses, ref: scrollContainerRef, style: { gap: compact ? '0.25rem' : '0.5rem', ...(effectiveMaxHeight ? { maxHeight: effectiveMaxHeight } : {}) }, children: [isLoading && activities.length === 0 && (jsx(Fragment, { children: Array.from({ length: 8 }).map((_, index) => (jsx(ActivityFeedItemSkeleton, { compact: compact }, index))) })), !isLoading && activities.length === 0 && hasPolicies !== false && (jsxs("div", { className: "py-12 text-center text-muted-foreground", children: [jsx("p", { className: "m-0", children: "No activities found" }), jsx("p", { className: "text-sm text-muted-foreground mt-2 m-0", children: "Try adjusting your filters or time range" })] })), activities.map((activity, index) => (jsx(ActivityFeedItem, { activity: activity, onResourceClick: onResourceClick, resourceLinkResolver: resourceLinkResolver, tenantLinkResolver: tenantLinkResolver, tenantRenderer: tenantRenderer, onActorClick: handleActorClick, onActivityClick: onActivityClick, compact: compact, isNew: enableStreaming && index < newActivitiesCount, variant: variant, isLast: index === activities.length - 1 }, activity.metadata?.uid || activity.metadata?.name))), infiniteScroll && hasMore && (jsx("div", { ref: loadMoreTriggerRef, className: "h-px mt-4" })), !infiniteScroll && hasMore && !isLoading && (jsx("div", { className: "flex justify-center p-4 mt-4", children: jsx(Button, { onClick: handleLoadMoreClick, children: "Load more" }) })), !hasMore && activities.length > 0 && !isLoading && (jsx("div", { className: "text-center py-6 text-muted-foreground text-sm border-t border-border mt-4", children: "No more activities to load" }))] })] }));
10942
11026
  }
10943
11027
 
10944
11028
  /**
@@ -11025,7 +11109,7 @@ function ResourceHistoryView({ client, resourceFilter, startTime = 'now-30d', li
11025
11109
  resourceFilter.name;
11026
11110
  return (jsxs(Card, { className: cn(compact ? 'p-0 shadow-none border-0' : '', className), children: [showHeader && (jsx(CardHeader, { className: cn(compact ? 'px-0 pt-0 pb-3' : 'pb-4'), children: jsxs(CardTitle, { className: "text-base font-semibold text-foreground flex items-center gap-2", children: [jsx("svg", { className: "w-4 h-4 text-muted-foreground", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" }) }), headerTitle] }) })), jsxs(CardContent, { className: cn(compact ? 'p-0' : ''), children: [!hasValidFilter && (jsxs("div", { className: "py-12 text-center text-muted-foreground", children: [jsx("svg", { className: "w-12 h-12 mx-auto mb-3 text-muted-foreground/50", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }), jsx("p", { className: "m-0 text-sm", children: "No resource filter specified" }), jsx("p", { className: "text-xs text-muted-foreground mt-1 m-0", children: "Provide at least one filter criterion to view resource history" })] })), hasValidFilter && jsx(ApiErrorAlert, { error: error, onRetry: refresh, className: "mb-4", errorFormatter: errorFormatter }), hasValidFilter && isLoading && activities.length === 0 && (jsxs("div", { className: "flex items-center justify-center gap-3 py-12 text-muted-foreground text-sm", children: [jsx("div", { className: "w-5 h-5 border-[3px] border-muted border-t-primary rounded-full animate-spin" }), jsx("span", { children: "Loading history..." })] })), hasValidFilter && !isLoading && activities.length === 0 && !error && (jsxs("div", { className: "py-12 text-center text-muted-foreground", children: [jsx("svg", { className: "w-12 h-12 mx-auto mb-3 text-muted-foreground/50", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2" }) }), jsx("p", { className: "m-0 text-sm", children: "No history found for this resource" }), jsx("p", { className: "text-xs text-muted-foreground mt-1 m-0", children: "Changes will appear here once activity policies are configured" })] })), hasValidFilter && activities.length > 0 && (jsxs("div", { className: "relative", children: [activities.map((activity, index) => {
11027
11111
  const activityId = activity.metadata?.uid || activity.metadata?.name || String(index);
11028
- return (jsx(ActivityFeedItem, { activity: activity, variant: "timeline", compact: compact, isFirst: index === 0, isLast: index === activities.length - 1 && !hasMore, onActivityClick: onActivityClick, onResourceClick: onResourceClick, resourceLinkResolver: resourceLinkResolver, onActorClick: onActorClick }, activityId));
11112
+ return (jsx(ActivityFeedItem, { activity: activity, variant: "timeline", compact: compact, isLast: index === activities.length - 1 && !hasMore, onActivityClick: onActivityClick, onResourceClick: onResourceClick, resourceLinkResolver: resourceLinkResolver, onActorClick: onActorClick }, activityId));
11029
11113
  }), isLoading && activities.length > 0 && (jsx("div", { className: cn('relative', compact ? 'pl-8' : 'pl-10'), children: jsxs("div", { className: "flex items-center gap-3 py-4 text-muted-foreground text-sm", children: [jsx("div", { className: "w-4 h-4 border-2 border-muted border-t-primary rounded-full animate-spin" }), jsx("span", { children: "Loading more..." })] }) })), hasMore && !isLoading && (jsxs("div", { className: cn('relative', compact ? 'pl-8' : 'pl-10'), children: [jsx("div", { className: cn('absolute w-0.5 bg-border', compact ? 'left-[11px] top-0 h-4' : 'left-[15px] top-0 h-5') }), jsx(Button, { variant: "ghost", size: "sm", onClick: handleLoadMore, className: "text-muted-foreground hover:text-foreground mt-2", children: "Load more history" })] }))] })), hasValidFilter && activities.length > 0 && (jsxs("div", { className: cn('text-xs text-muted-foreground mt-4 pt-3 border-t border-border', compact ? '' : ''), children: ["Showing ", activities.length, " event", activities.length !== 1 ? 's' : '', hasMore && ' (more available)'] }))] })] }));
11030
11114
  }
11031
11115