# @classic-homes/data-panel-core 中文文档

规范地址：https://npmcn.com/package/%40classic-homes/data-panel-core/

版本：0\.1\.3
npm 元数据更新时间：2026-10-16T14:35:14.786Z
中文译文更新时间：2026-11-09T23:53:09.678Z
软件包许可：未声明

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40classic-homes/data-panel-core
原文对照：https://npmcn.com/package/%40classic-homes/data-panel-core/?lang=original

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：87.1 kB，10 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- 运行依赖：0 个
- 首次发布：2026-02-03T21:39:35.855Z
- 最新版本发布：2026-10-16T14:35:14.609Z
- 近 30 天下载量：1765（2026-10-10 至 2026-11-08，npm 官方下载统计）
- 已发布版本数：10（近 12 个月 10 个）

## 中文简介

数据小组组成部分的核心公用事业和类型

## 安装

```sh
npm install @classic-homes/data-panel-core
```

也可以使用：`pnpm add @classic-homes/data-panel-core`、`yarn add @classic-homes/data-panel-core`、`bun add @classic-homes/data-panel-core`

## README

# @classic-homes/data-panel-core (英语)

数据小组组件的核心公用事业和类型。 这个软件包为跨越React和Svelte执行的构建灵活,可拖放,可重排的面板提供了共享功能.

## 安装

```bash
npm install @classic-homes/data-panel-core
```

## 快速启动

```typescript
import {
  // Types
  type PanelMode,
  type PanelEdge,
  type DataPanelState,

  // Default values
  DEFAULT_PANEL_STATE,
  DEFAULT_CONSTRAINTS,

  // Utilities
  constrainSize,
  constrainPosition,
  loadPanelState,
  savePanelState,
} from '@classic-homes/data-panel-core';

// Load persisted state
const persisted = loadPanelState('my-panel');
const state = mergeWithDefaults(persisted);

// Constrain panel size
const size = constrainSize({ width: 500, height: 600 }, { minWidth: 300, maxWidth: 800 });
```

## API 参考

### 类型

#### 面板配置类型

```typescript
type PanelMode = 'pinned' | 'detached';
type PanelEdge = 'left' | 'right' | 'top' | 'bottom';
type PanelVariant = 'full' | 'card';
type ResizeHandle =
  | 'top'
  | 'right'
  | 'bottom'
  | 'left'
  | 'top-left'
  | 'top-right'
  | 'bottom-left'
  | 'bottom-right';
```

#### 状态类型

```typescript
interface Position {
  x: number;
  y: number;
}

interface Size {
  width: number;
  height: number;
}

interface PanelConstraints {
  minWidth?: number;
  maxWidth?: number;
  minHeight?: number;
  maxHeight?: number;
}

interface DataPanelState {
  mode: PanelMode;
  variant: PanelVariant;
  edge: PanelEdge;
  isExpanded: boolean;
  detachedPosition: Position;
  detachedSize: Size;
  pinnedSize: number;
  cardSnapIndex: number;
}
```

#### 交互状态类型

```typescript
interface DragState {
  isDragging: boolean;
  startPosition: Position;
  startPanelPosition: Position;
  currentPosition: Position;
}

interface ResizeState {
  isResizing: boolean;
  handle: ResizeHandle | null;
  startPosition: Position;
  startSize: Size;
  startPanelPosition: Position;
}

interface PinnedDragState {
  isDragging: boolean;
  hasDetached: boolean;
  startPosition: Position;
  currentPosition: Position;
  edge: PanelEdge;
  pinnedSize: number;
}
```

### 常数

#### 默认值

```typescript
import {
  DEFAULT_PANEL_STATE, // Default DataPanelState
  DEFAULT_CONSTRAINTS, // Default PanelConstraints
  DEFAULT_CARD_CONFIG, // Default CardConfig
  DEFAULT_SNAP_POINTS, // Default snap points { peek: 0.25, half: 0.5, full: 1.0 }
} from '@classic-homes/data-panel-core';
```

#### 卡片模式常数

```typescript
import {
  CARD_HEADER_HEIGHT, // 72 - Height of collapsed card header
  CARD_EXPANDED_RATIO, // 0.85 - Max height as ratio of viewport
  CARD_MIN_WIDTH, // 280 - Minimum card width
} from '@classic-homes/data-panel-core';
```

### 拖动公用事业

#### 国家初始化

```typescript
// Create initial drag state
const dragState = createDragState();

// Create initial resize state
const resizeState = createResizeState();

// Create pinned drag-to-detach state
const pinnedDragState = createPinnedDragState();
```

#### 指针处理

```typescript
// Get position from any pointer event type
const position = getPointerPosition(event); // MouseEvent | PointerEvent | TouchEvent

// Calculate new panel position during drag
const newPosition = calculateDragPosition(dragState, currentPointer);

// Calculate new size and position during resize
const { position, size } = calculateResize(resizeState, currentPointer);
```

#### 调整处理大小

```typescript
// Get cursor style for a resize handle
const cursor = getResizeCursor('top-left'); // 'nwse-resize'

// Get the resize handle for a pinned panel edge
const handle = getPinnedResizeHandle('right'); // 'left'

// Get all handles for detached mode
const handles = getDetachedResizeHandles(); // ['top', 'right', 'bottom', 'left', ...]

// Check if pointer is near a resize handle
const nearHandle = isNearResizeHandle(mousePos, panelRect, threshold);
```

#### 被绑住的拖放

```typescript
// Calculate distance dragged away from edge
const distance = calculateDetachDistance(startPos, currentPos, 'right');

// Calculate rubber-band pull offset
const offset = calculatePullOffset(distance, threshold, maxPull);

// Get new position when detaching
const newPos = calculateDetachedPositionFromPinned(
  pointerPos,
  pinnedSize,
  detachedSize,
  edge,
  viewportWidth,
  viewportHeight
);

// Get CSS transform for pull effect
const transform = getPinnedPullTransform(pullOffset, 'right'); // 'translateX(-10px)'
```

### 约束性公用事业

#### 点燃值

```typescript
// Clamp a value between min and max
const clamped = clamp(value, min, max);

// Constrain size to min/max bounds
const size = constrainSize({ width: 1000, height: 1000 }, constraints);

// Constrain position within viewport
const pos = constrainPosition(position, size, viewportWidth, viewportHeight, padding);

// Combined size and position constraint during resize.
// Pass the active handle so left/top edges keep the opposite edge anchored
// when the size is clamped (omit it to leave position unadjusted).
const { position, size } = constrainResize(newPos, newSize, constraints, vw, vh, handle);
```

#### 固定小组的限制

```typescript
// Constrain width for horizontal edges (left/right)
const width = constrainPinnedWidth(width, constraints, viewportWidth, maxRatio);

// Constrain height for vertical edges (top/bottom)
const height = constrainPinnedHeight(height, constraints, viewportHeight, maxRatio);
```

#### 边缘检测

```typescript
// Check if position should snap to an edge
const { shouldSnap, edge, distance } = detectEdgeSnap(
  position,
  size,
  viewportWidth,
  viewportHeight,
  threshold
);

// Edge type helpers
const isHoriz = isHorizontalEdge('left'); // true
const isVert = isVerticalEdge('top'); // true
```

#### 位置样式

```typescript
// Get CSS styles for pinned panel
const styles = getPinnedPositionStyles('right', 400);
// { top: '0', right: '0', bottom: '0', width: '400px', height: '100%' }

// Get CSS styles for detached panel
const styles = getDetachedPositionStyles({ x: 100, y: 200 }, { width: 400, height: 500 });
// { top: '200px', left: '100px', width: '400px', height: '500px' }

// Get centered initial position
const pos = getInitialDetachedPosition(size, viewportWidth, viewportHeight);
```

#### 卡片模式公用事业

```typescript
// Calculate snap point height in pixels
const height = getSnapPointHeight(0.5, viewportHeight, headerHeight);

// Get CSS styles for card mode
const styles = getCardPositionStyles(0.5, viewportWidth, viewportHeight, cardConfig);

// Find nearest snap point to current height
const index = findNearestSnapIndex(currentHeight, viewportHeight, snapPoints);

// Determine snap based on swipe velocity
const index = getSnapIndexFromVelocity(currentIndex, velocity, snapPoints, threshold);

// Calculate drag velocity
const velocity = calculateDragVelocity(startY, endY, startTime, endTime);

// Check if card should be dismissed
const dismiss = shouldDismissCard(currentHeight, viewportHeight, threshold);

// Get labels for snap points
const labels = getSnapPointLabels([0.25, 0.5, 1.0]); // ['Peek', 'Half', 'Full']
```

### 持久性公用事业

```typescript
// Load state from localStorage
const state = loadPanelState('my-panel-key');

// Save state to localStorage
savePanelState('my-panel-key', panelState);

// Clear persisted state
clearPanelState('my-panel-key');

// Merge persisted state with defaults
const fullState = mergeWithDefaults(persisted, customDefaults);

// Create debounced save function
const debouncedSave = createDebouncedSave('my-panel-key', 300);
debouncedSave(state); // Saves after 300ms of inactivity
```

## 使用反相/ Svelte

这个软件包是框架不可知的,为DataPanel组件提供了核心逻辑. 使用方式:

-   `@classic-homes/react` - 反应数据小组组件
-   `@classic-homes/svelte` - 斯维尔特数据小组组件

两种执行都使用这个软件包在内部进行一致的行为.

## 许可证

麻省理工学院

## 常见问题

### @classic-homes/data-panel-core 是什么？

数据小组组成部分的核心公用事业和类型

### 如何安装 @classic-homes/data-panel-core？

在项目目录运行 npm install @classic-homes/data-panel-core，或使用 pnpm add / yarn add / bun add。

### @classic-homes/data-panel-core 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @classic-homes/data-panel-core 支持 ESM 还是 CommonJS？

同时提供 ES Module 与 CommonJS 入口，import 和 require\(\) 都可以使用，打包工具会自动选择合适的版本。

### @classic-homes/data-panel-core 可以商用吗？

@classic-homes/data-panel-core 使用 未声明 许可。package\.json 没有声明许可证。没有许可证的代码默认保留全部权利，商用前请联系作者或查看仓库中的 LICENSE 文件。以上为概括，不构成法律意见，请以许可原文为准。

### @classic-homes/data-panel-core 的下载量有多少？

根据 npm 官方下载统计，@classic-homes/data-panel-core 在 2026/10/10 – 2026/11/08 这 30 天内被下载 1,765 次，日均约 59 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @classic-homes/data-panel-core 还在维护吗？

最新版本 0\.1\.3 发布于 2026/10/16（24 天前）；至今共发布 10 个版本，其中过去 12 个月发布了 10 个；首次发布于 2026/02/04。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

