Bin
2025-12-16 9e0b2ba2c317b1a86212f24cbae3195ad1f3dbfa
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import { inject, observer } from "mobx-react";
import { useEffect, useState } from "react";
// @ts-ignore - RadioGroup is a .jsx file without types
import { RadioGroup } from "../../Common/RadioGroup/RadioGroup";
import { IconRows3, IconRows4 } from "@humansignal/icons";
import { Tooltip } from "@humansignal/ui";
 
// Density constants - exported for use in other components
export const DENSITY_STORAGE_KEY = "dm:table:density";
export const DENSITY_COMFORTABLE = "comfortable" as const;
export const DENSITY_COMPACT = "compact" as const;
 
// Row height values for each density
export const ROW_HEIGHT_COMFORTABLE = 70;
export const ROW_HEIGHT_COMPACT = 50;
 
export type Density = typeof DENSITY_COMFORTABLE | typeof DENSITY_COMPACT;
 
interface DensityToggleProps {
  size?: "small" | "medium" | "large";
  onChange?: (density: Density) => void;
  storageKey?: string;
  view?: { type: string };
}
 
const densityInjector = inject(({ store }: any) => ({
  view: store.currentView,
}));
 
export const DensityToggle = densityInjector(
  observer(({ size, onChange, storageKey, view, ...rest }: DensityToggleProps) => {
    const key = storageKey ?? DENSITY_STORAGE_KEY;
    const [density, setDensity] = useState<Density>(() => {
      return (localStorage.getItem(key) as Density) ?? DENSITY_COMFORTABLE;
    });
 
    useEffect(() => {
      localStorage.setItem(key, density);
      onChange?.(density);
 
      // Notify other components about density change
      window.dispatchEvent(new CustomEvent("dm:density:changed", { detail: density }));
    }, [density, onChange, key]);
 
    // Hide density toggle when in grid view
    if (view?.type === "grid") {
      return null;
    }
 
    return (
      <RadioGroup
        size={size}
        value={density}
        onChange={(e: React.ChangeEvent<HTMLInputElement>) => setDensity(e.target.value as Density)}
        {...rest}
        style={{ "--button-padding": "0 var(--spacing-tighter)" } as React.CSSProperties}
        data-testid="density-toggle"
      >
        <Tooltip title="舒适密度">
          <div>
            <RadioGroup.Button
              value={DENSITY_COMFORTABLE}
              aria-label="Comfortable density"
              data-testid="density-comfortable"
            >
              <IconRows3 />
            </RadioGroup.Button>
          </div>
        </Tooltip>
        <Tooltip title="紧凑密度">
          <div>
            <RadioGroup.Button value={DENSITY_COMPACT} aria-label="Compact density" data-testid="density-compact">
              <IconRows4 />
            </RadioGroup.Button>
          </div>
        </Tooltip>
      </RadioGroup>
    );
  }),
);