# @cloud-ru/ds-drag-and-drop 中文文档

规范地址：https://npmcn.com/package/%40cloud-ru/ds-drag-and-drop/

版本：1\.1\.6
npm 元数据更新时间：2026-11-12T10:57:01.848Z
中文译文更新时间：2026-11-12T11:00:07.656Z
软件包许可：Apache-2\.0

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

原始 npm 页面：https://www.npmjs.com/package/%40cloud-ru/ds-drag-and-drop
原文对照：https://npmcn.com/package/%40cloud-ru/ds-drag-and-drop/?lang=original
项目主页：https://github.com/cloud-ru-tech/snack-v2/tree/master/packages/drag-and-drop
源码仓库：https://github.com/cloud-ru-tech/snack-v2

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

- 包体积（解压后）：306 kB，81 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- 运行依赖：3 个
- 首次发布：2026-08-18T14:59:32.486Z
- 最新版本发布：2026-11-12T10:57:01.438Z
- 近 30 天下载量：10171（2026-10-10 至 2026-11-08，npm 官方下载统计）
- 已发布版本数：20（近 12 个月 20 个）

## 中文简介

{\\fn黑体\\fs22\\bord1\\shad0\\3aHBE\\4aH00\\fscx67\\fscy66\\2cHFFFFFF\\3cH808080}你觉得呢.

## 安装

```sh
npm install @cloud-ru/ds-drag-and-drop
```

也可以使用：`pnpm add @cloud-ru/ds-drag-and-drop`、`yarn add @cloud-ru/ds-drag-and-drop`、`bun add @cloud-ru/ds-drag-and-drop`

## README

# 拖放( D)

`@cloud-ru/ds-drag-and-drop` {\\fn黑体\\fs20\\shad2\\2aH82\\3aH20\\4aH33\\fscx95\\3cH592001\\be1} - {\\fn黑体\\fs20\\shad2\\2aH82\\3aH20\\4aH33\\fscx95\\3cH592001\\be1} - {\\fn黑体\\fs20\\shad2\\2aH82\\3aH20\\4aH33\\fscx95\\3cH592001\\be1} - {\\fn黑体\\fs20\\shad2\\2aH82\\3aH20\\4aH33\\fscx95\\3cH592001\\be1}.

{\\fn黑体\\fs22\\bord1\\shad0\\3aHBE\\4aH00\\fscx67\\fscy66\\2cHFFFFFF\\3cH808080}你觉得呢? Логику (сенсоры,коллизии也 (单位:千美元)`@dnd-kit`, HTML5 DnD, собственные. Примитивы,как也 ? ? ? ? ? ? ? ? ? ? ? ? ? ? .

-   `DragGhost` {\\fn黑体\\fs22\\bord1\\shad0\\3ahbe\\4ah00\\fscx67\\fscy66\\2chffffff\\3ch808080}你觉得呢.
-   `DragPreview` - поверхность, которая, курсором.
-   `DropIndicator` - 。 。 。 。 .
-   `DropTarget` {\\fn黑体\\fs20\\shad2\\2ah82\\3ah20\\4ah33\\fscx95\\3ch592001\\be1} - ... {\\fn黑体\\fs20\\shad2\\2ah82\\3ah20\\4ah33\\fscx95\\3ch592001\\be1} - ... {\\fn黑体\\fs20\\shad2\\2ah82\\3ah20\\4ah33\\fscx95\\3ch592001\\be1} - ...

## Когда

-   {\\fn黑体\\fs20\\shad2\\2aH82\\3aH20\\4aH33\\fscx95\\3cH592001\\be1}########################### ##########################################################################################################################################################################################################.
-   {\\fn黑体\\fs22\\bord1\\shad0\\3aHBE\\4aH00\\fscx67\\fscy66\\2cHFFFFFF\\3cH808080}你觉得怎样`DropTarget`) (中文(简体) ).
-   Порядок:а也 `DropIndicator` 页:1 (原始内容存档于2017-10-29). qq (динамический).

Когда **не** нужен:

-   {\\fn黑体\\fs20\\shad2\\2aH82\\3aH20\\4aH33\\fscx95\\3cH592001\\be1}你觉得怎么样
    -   у `@cloud-ru/ds-list` {\\fn黑体\\fs22\\bord1\\shad0\\3ahbe\\4ah00\\fscx67\\fscy66\\2chffffff\\3ch808080}你觉得呢 `onItemsReorder` - примитивы уже встроены встроены встроены.
-   {\\fn黑体\\fs20\\shad2\\2aH82\\3aH20\\4aH33\\fscx95\\3cH592001\\be1}你觉得怎样
    -   (原始内容存档于2019-10-21). DnD-библиотека, эти.

## Анатомия

### QQ (默认) `static`(中文(简体) )

Перенос. {\\fn黑体\\fs20\\shad2\\2aH82\\3aH20\\4aH33\\fscx95\\3cH592001\\be1}你觉得呢 на:смешивать也 интерфейсы.

-   `static` - соседи на месте месте исходная исходная приглушается (приглушается стоят месте месте месте месте месте месте месте месте приглушается приглушается приглушается (приглушается приглушается приглушается приглушается приглушается)`DragGhost` с `dragging`, (中文(简体) ), {\\fn黑体\\fs22\\bord1\\shad0\\3ahbe\\4ah00\\fscx67\\fscy66\\2chffffff\\3ch808080}你觉得呢`DropIndicator`) (中文(简体) ). {\\fn黑体\\fs20\\shad2\\2aH82\\3aH20\\4aH33\\fscx95\\3cH592001\\be1}你觉得呢 режим:длинные也.
-   `dynamic` - расступаются, на, попадания, остаётся (слот, слот, слот)`DragGhost` с `dragging` и `mode='dynamic'`) (中文(简体) ). Линию:точку也 пустота,а也.

Режим:копия也`DragPreview`{\\fn黑体\\fs22\\bord1\\shad0\\3ahbe\\4ah00\\fscx67\\fscy66\\2chffffff\\3ch808080}你觉得呢 (单位:千美元)`DropTarget`)"в""обоих".

### DragGhost (默认) `dragging: false`, (中文(简体) ), `mode: static`(中文(简体) )

{\\fn华文仿宋\\fs16\\1cHD1D1D1}好. `dragging` включает, `mode` 校对:soup `static` - приглушение на своём месте, `dynamic` - становится, сохраняя, своё {\\fn黑体\\fs22\\bord1\\shad0\\3ahbe\\4ah00\\fscx67\\fscy66\\2chffffff\\3ch808080}你觉得呢.

Заменяет:обёртку也 `innerRef`, (中文(简体) ), `className` {\\fn黑体\\fs22\\bord1\\shad0\\3ahbe\\4ah00\\fscx67\\fscy66\\2chffffff\\3ch808080}你觉得呢 `<div>`Создаёт,поэтому `DropIndicator` с `placement` {\\fn黑体\\fs22\\bord1\\shad0\\3ahbe\\4ah00\\fscx67\\fscy66\\2chffffff\\3ch808080}你觉得呢.

### 拖放预览

Обёртка:поверхность也 любым-相去相去相去相去相去相去相去相去相去相去.

{\\fn黑体\\fs22\\bord1\\shad0\\3aHBE\\4aH00\\fscx67\\fscy66\\2cHFFFFFF\\3cH808080}你觉得怎么样? {\\fn黑体\\fs20\\shad2\\2aH82\\3aH20\\4aH33\\fscx95\\3cH592001\\be1}你觉得呢, {\\fn黑体\\fs22\\bord1\\shad0\\3ahbe\\4ah00\\fscx67\\fscy66\\2chffffff\\3ch808080}你觉得呢.

### 投放指示器( 默认) `horizontal`(中文(简体) )

{\\fn黑体\\fs22\\bord1\\shad0\\3aHBE\\4aH00\\fscx67\\fscy66\\2cHFFFFFF\\3cH808080}你觉得怎样? {\\fn黑体\\fs22\\bord1\\shad0\\3aHBE\\4aH00\\fscx67\\fscy66\\2cHFFFFFF\\3cH808080}你还好吧 {\\fn黑体\\fs22\\bord1\\shad0\\3ahbe\\4ah00\\fscx67\\fscy66\\2chffffff\\3ch808080}你觉得呢.

Ориентация:

-   `horizontal` {\\fn黑体\\fs22\\bord1\\shad0\\3ahbe\\4ah00\\fscx67\\fscy66\\2chffffff\\3ch808080}你觉得呢.
-   `vertical` {\\fn黑体\\fs22\\bord1\\shad0\\3ahbe\\4ah00\\fscx67\\fscy66\\2chffffff\\3ch808080}你觉得呢.

{\\fn黑体\\fs20\\shad2\\2aH82\\3aH20\\4aH33\\fscx95\\3cH592001\\be1}你觉得怎样.

`placement` {\\fn黑体\\fs22\\bord1\\shad0\\3ahbe\\4ah00\\fscx67\\fscy66\\2chffffff\\3ch808080}你觉得呢 `before` - перед,ним, `after` - 额... {\\fn黑体\\fs22\\bord1\\shad0\\3aHBE\\4aH00\\fscx67\\fscy66\\2cHFFFFFF\\3cH808080}你觉得呢 с. Без `placement` {\\fn黑体\\fs22\\bord1\\shad0\\3ahbe\\4ah00\\fscx67\\fscy66\\2chffffff\\3ch808080}你觉得呢.

`atEdge` нужен:у也 {\\fn黑体\\fs20\\shad2\\2ah82\\3ah20\\4ah33\\fscx95\\3ch592001\\be1}你觉得怎么样.

### 投放目标( 默认) `active: false`(中文(简体) )

Область,принимающая也. `active` {\\fn黑体\\fs22\\bord1\\shad0\\3ahbe\\4ah00\\fscx67\\fscy66\\2chffffff\\3ch808080}你觉得呢.

Рамка-признак **{\\fn黑体\\fs22\\bord1\\shad0\\3ahbe\\4ah00\\fscx67\\fscy66\\2chffffff\\3ch808080}你觉得呢**{\\fn黑体\\fs22\\bord1\\shad0\\3ahbe\\4ah00\\fscx67\\fscy66\\2chffffff\\3ch808080}你觉得呢, а:отпускают也. {\\fn黑体\\fs22\\bord1\\shad0\\3aHBE\\4aH00\\fscx67\\fscy66\\2cHFFFFFF\\3cH808080}你觉得呢 зоны:там也, {\\fn黑体\\fs22\\bord1\\shad0\\3ahbe\\4ah00\\fscx67\\fscy66\\2chffffff\\3ch808080}你觉得呢.

Обводка **внутри** {\\fn黑体\\fs20\\shad2\\2ah82\\3ah20\\4ah33\\fscx95\\3ch592001\\be1}你觉得怎样.

## Установка

```bash
pnpm add @cloud-ru/ds-drag-and-drop
```

```ts
import {
  DRAG_MODE,
  DragGhost,
  DragPreview,
  DropIndicator,
  DropTarget,
  ORIENTATION,
  PLACEMENT,
} from '@cloud-ru/ds-drag-and-drop'
```

## Примеры

### Поверхность

DragPreview # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # ## # # # # # # # # # # # #####################################################################################################################################

```tsx
import { DragPreview } from '@cloud-ru/ds-drag-and-drop';

import styles from './demo.module.scss';

export function PreviewSurface() {
  return (
    <DragPreview className={styles.entity}>
      <div className={styles.row}>ListItem 2</div>
    </DragPreview>
  );
}
```

{\\fn黑体\\fs22\\bord1\\shad0\\3aHBE\\4aH00\\fscx67\\fscy66\\2cHFFFFFF\\3cH808080}你觉得呢 `@dnd-kit` . . . . . С N библиотекой `isDragging` 编号 : `over`{\\fn黑体\\fs22\\bord1\\shad0\\3ahbe\\4ah00\\fscx67\\fscy66\\2chffffff\\3ch808080}你觉得呢.

### Статический

Потяните:соседи也

```tsx
import { closestCenter, DndContext, DragOverlay, PointerSensor, useSensor, useSensors } from '@dnd-kit/core';
import { arrayMove, SortableContext, useSortable, verticalListSortingStrategy } from '@dnd-kit/sortable';
import { DRAG_MODE, DragGhost, DragPreview, DropIndicator, PLACEMENT } from '@cloud-ru/ds-drag-and-drop';
import { useState } from 'react';

import styles from './demo.module.scss';

const INITIAL_ROWS = [
  { id: 'row-1', label: 'ListItem 1' },
  { id: 'row-2', label: 'ListItem 2' },
  { id: 'row-3', label: 'ListItem 3' },
  { id: 'row-4', label: 'ListItem 4' },
];

function Row({ id, label, lastIndex }: { id: string; label: string; lastIndex: number }) {
  const { activeIndex, attributes, index, isDragging, listeners, overIndex, setNodeRef } = useSortable({ id });

  // Статический перенос: соседи стоят на месте, поэтому трансляцию от `@dnd-kit` строке
  // не применяем. Точку вставки отмечает линия на строке-цели, сторона — по тому, откуда
  // пришла перетаскиваемая строка.
  const showIndicator = activeIndex !== -1 && index === overIndex && index !== activeIndex;
  const placement = overIndex > activeIndex ? PLACEMENT.After : PLACEMENT.Before;

  return (
    <DragGhost
      innerRef={setNodeRef}
      dragging={isDragging}
      mode={DRAG_MODE.Static}
      className={styles.grabbable}
      {...attributes}
      {...listeners}
    >
      <div className={styles.row}>{label}</div>
      {showIndicator && (
        <DropIndicator
          placement={placement}
          atEdge={
            (index === 0 && placement === PLACEMENT.Before) || (index === lastIndex && placement === PLACEMENT.After)
          }
        />
      )}
    </DragGhost>
  );
}

export function InsertionLine() {
  const [rows, setRows] = useState(INITIAL_ROWS);
  const [activeId, setActiveId] = useState<string>();
  // Порог в 4px: без него клик по строке уже считался бы началом переноса.
  const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 4 } }));

  const activeRow = rows.find(row => row.id === activeId);

  return (
    <DndContext
      // Фиксированный id: без него `@dnd-kit` нумерует свои aria-узлы счётчиком, и на
      // SSR-странице разметка расходится с клиентской.
      id='insertion-line'
      sensors={sensors}
      collisionDetection={closestCenter}
      onDragStart={({ active }) => setActiveId(String(active.id))}
      onDragCancel={() => setActiveId(undefined)}
      onDragEnd={({ active, over }) => {
        setActiveId(undefined);

        if (!over || active.id === over.id) {
          return;
        }

        setRows(rows =>
          arrayMove(
            rows,
            rows.findIndex(row => row.id === active.id),
            rows.findIndex(row => row.id === over.id),
          ),
        );
      }}
    >
      <SortableContext items={rows.map(row => row.id)} strategy={verticalListSortingStrategy}>
        <div className={styles.list}>
          {rows.map(row => (
            <Row key={row.id} id={row.id} label={row.label} lastIndex={rows.length - 1} />
          ))}
        </div>
      </SortableContext>
      {/* Копия за курсором: позиционирует её `DragOverlay`, поверхность даёт `DragPreview`. */}
      <DragOverlay dropAnimation={null}>
        {activeRow && (
          <DragPreview className={styles.entity}>
            <div className={styles.row}>{activeRow.label}</div>
          </DragPreview>
        )}
      </DragOverlay>
    </DndContext>
  );
}
```

### Динамический

Потяните:соседи也

```tsx
import { closestCenter, DndContext, DragOverlay, PointerSensor, useSensor, useSensors } from '@dnd-kit/core';
import { arrayMove, SortableContext, useSortable, verticalListSortingStrategy } from '@dnd-kit/sortable';
import { CSS } from '@dnd-kit/utilities';
import { DRAG_MODE, DragGhost, DragPreview } from '@cloud-ru/ds-drag-and-drop';
import { useState } from 'react';

import styles from './demo.module.scss';

const INITIAL_ROWS = [
  { id: 'row-1', label: 'ListItem 1' },
  { id: 'row-2', label: 'ListItem 2' },
  { id: 'row-3', label: 'ListItem 3' },
  { id: 'row-4', label: 'ListItem 4' },
];

function Row({ id, label }: { id: string; label: string }) {
  const { attributes, isDragging, listeners, setNodeRef, transform, transition } = useSortable({ id });

  return (
    <DragGhost
      innerRef={setNodeRef}
      dragging={isDragging}
      mode={DRAG_MODE.Dynamic}
      className={styles.grabbable}
      // Динамический перенос: соседи расступаются трансляцией от `@dnd-kit`, а слот
      // перетаскиваемой строки пустеет и сам показывает точку вставки — линия не нужна.
      style={{ transform: CSS.Translate.toString(transform), transition }}
      {...attributes}
      {...listeners}
    >
      <div className={styles.row}>{label}</div>
    </DragGhost>
  );
}

export function DynamicGap() {
  const [rows, setRows] = useState(INITIAL_ROWS);
  const [activeId, setActiveId] = useState<string>();
  // Порог в 4px: без него клик по строке уже считался бы началом переноса.
  const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 4 } }));

  const activeRow = rows.find(row => row.id === activeId);

  return (
    <DndContext
      // Фиксированный id: без него `@dnd-kit` нумерует свои aria-узлы счётчиком, и на
      // SSR-странице разметка расходится с клиентской.
      id='dynamic-gap'
      sensors={sensors}
      collisionDetection={closestCenter}
      onDragStart={({ active }) => setActiveId(String(active.id))}
      onDragCancel={() => setActiveId(undefined)}
      onDragEnd={({ active, over }) => {
        setActiveId(undefined);

        if (!over || active.id === over.id) {
          return;
        }

        setRows(rows =>
          arrayMove(
            rows,
            rows.findIndex(row => row.id === active.id),
            rows.findIndex(row => row.id === over.id),
          ),
        );
      }}
    >
      <SortableContext items={rows.map(row => row.id)} strategy={verticalListSortingStrategy}>
        <div className={styles.list}>
          {rows.map(row => (
            <Row key={row.id} id={row.id} label={row.label} />
          ))}
        </div>
      </SortableContext>
      <DragOverlay dropAnimation={null}>
        {activeRow && (
          <DragPreview className={styles.entity}>
            <div className={styles.row}>{activeRow.label}</div>
          </DragPreview>
        )}
      </DragOverlay>
    </DndContext>
  );
}
```

### {\\fn黑体\\fs22\\bord1\\shad0\\3aHBE\\4aH00\\fscx67\\fscy66\\2cHFFFFFF\\3cH808080}你觉得呢

Перетащите:рамку也

```tsx
import {
  DndContext,
  DragOverlay,
  PointerSensor,
  useDraggable,
  useDroppable,
  useSensor,
  useSensors,
} from '@dnd-kit/core';
import { DragGhost, DragPreview, DropTarget } from '@cloud-ru/ds-drag-and-drop';
import { useState } from 'react';

import styles from './demo.module.scss';

const ZONES = [
  { id: 'zone-1', label: 'Зона 1' },
  { id: 'zone-2', label: 'Зона 2' },
];

const INITIAL_ITEMS = [
  { id: 'item-1', label: 'ListItem 1', zoneId: 'zone-1' },
  { id: 'item-2', label: 'ListItem 2', zoneId: 'zone-1' },
  { id: 'item-3', label: 'ListItem 3', zoneId: 'zone-2' },
];

type Item = (typeof INITIAL_ITEMS)[number];

function Row({ id, label }: Pick<Item, 'id' | 'label'>) {
  const { attributes, isDragging, listeners, setNodeRef } = useDraggable({ id });

  return (
    <DragGhost innerRef={setNodeRef} dragging={isDragging} className={styles.grabbable} {...attributes} {...listeners}>
      <div className={styles.row}>{label}</div>
    </DragGhost>
  );
}

function Zone({ id, label, items, sourceZoneId }: { id: string; label: string; items: Item[]; sourceZoneId?: string }) {
  const { isOver, setNodeRef } = useDroppable({ id });

  // Рамка — признак переноса между зонами: своя зона её не получает.
  const active = isOver && sourceZoneId !== undefined && sourceZoneId !== id;

  return (
    <DropTarget innerRef={setNodeRef} active={active} className={styles.zone}>
      <div className={styles.zoneLabel}>{label}</div>
      {items.map(item => (
        <Row key={item.id} id={item.id} label={item.label} />
      ))}
    </DropTarget>
  );
}

export function ActiveZone() {
  const [items, setItems] = useState(INITIAL_ITEMS);
  const [activeId, setActiveId] = useState<string>();
  // Порог в 4px: без него клик по строке уже считался бы началом переноса.
  const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 4 } }));

  const activeItem = items.find(item => item.id === activeId);

  return (
    <DndContext
      // Фиксированный id: без него `@dnd-kit` нумерует свои aria-узлы счётчиком, и на
      // SSR-странице разметка расходится с клиентской.
      id='active-zone'
      sensors={sensors}
      onDragStart={({ active }) => setActiveId(String(active.id))}
      onDragCancel={() => setActiveId(undefined)}
      onDragEnd={({ active, over }) => {
        setActiveId(undefined);

        if (!over) {
          return;
        }

        setItems(items => items.map(item => (item.id === active.id ? { ...item, zoneId: String(over.id) } : item)));
      }}
    >
      <div className={styles.zones}>
        {ZONES.map(zone => (
          <Zone
            key={zone.id}
            id={zone.id}
            label={zone.label}
            items={items.filter(item => item.zoneId === zone.id)}
            sourceZoneId={activeItem?.zoneId}
          />
        ))}
      </div>
      <DragOverlay dropAnimation={null}>
        {activeItem && (
          <DragPreview className={styles.entity}>
            <div className={styles.row}>{activeItem.label}</div>
          </DragPreview>
        )}
      </DragOverlay>
    </DndContext>
  );
}
```

## 道具

### 拖曳幽灵

**拖曳Ghost 选项**

| Prop | 类型 | 默认 | 说明 |
| --- | --- | --- | --- |
| `children` | `ReactNode` | —— 说 | Сущность,остающаяся也. |
| `className` | `string` | —— 说 | 支助科 |
| `data-test-id` | `string` | —— 说 |  |
| `dragging` | `boolean` | `false` | {\\fn黑体\\fs22\\bord1\\shad0\\3aHBE\\4aH00\\fscx67\\fscy66\\2cHFFFFFF\\3cH808080}你觉得呢? По:假 |
| `innerRef` | `Ref<HTMLDivElement>` | —— 说 | 校对:Soup. |
| `mode` | `"dynamic"` | `"static"` | `static` | 校对:Soup `static` - соседи на месте приглушается приглушается  
показывает `DropIndicator`· ; `dynamic` - расступаются сразу сразу слот  
{\\fn黑体\\fs20\\shad2\\2aH82\\3aH20\\4aH33\\fscx95\\3cH592001\\be1}你觉得呢? :静态 |

#### 相关类型

-   `DragMode` =: `"dynamic"` | `"static"`

### 拖放预览

**拖放预览程序**

| Prop | 类型 | 默认 | 说明 |
| --- | --- | --- | --- |
| `children` | `ReactNode` | —— 说 | Перетаскиваемая:строка也. |
| `className` | `string` | —— 说 | 支助科 |
| `data-test-id` | `string` | —— 说 |  |
| `innerRef` | `Ref<HTMLDivElement>` | —— 说 | 参考文献: |

### 投递指示器

**投放指标**

| Prop | 类型 | 默认 | 说明 |
| --- | --- | --- | --- |
| `atEdge` | `boolean` | `false` | {\\fn黑体\\fs22\\bord1\\shad0\\3aHBE\\4aH00\\fscx67\\fscy66\\2cHFFFFFF\\3cH808080}你觉得呢? {\\fn黑体\\fs22\\bord1\\shad0\\3aHBE\\4aH00\\fscx67\\fscy66\\2cHFFFFFF\\3cH808080}你觉得呢  
{\\fn黑体\\fs22\\bord1\\shad0\\3aHBE\\4aH00\\fscx67\\fscy66\\2cHFFFFFF\\3cH808080}你觉得呢? Работает вместе `placement`。 。 。 .  
По:假 |
| `className` | `string` | —— 说 | 支助科 |
| `data-test-id` | `string` | —— 说 |  |
| `innerRef` | `Ref<HTMLDivElement>` | —— 说 | 参考文献: |
| `orientation` | `"horizontal"` | `"vertical"` | `horizontal` | Ориентация:水平-между,垂直-между. QQ: 横向 |
| `placement` | `"after"` | `"before"` | —— 说 | {\\fn黑体\\fs22\\bord1\\shad0\\3aHBE\\4aH00\\fscx67\\fscy66\\2cHFFFFFF\\3cH808080}你觉得呢? {\\fn黑体\\fs22\\bord1\\shad0\\3aHBE\\4aH00\\fscx67\\fscy66\\2cHFFFFFF\\3cH808080}你觉得呢  
\# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #  
потребитель. Требует `position` {\\fn黑体\\fs22\\bord1\\shad0\\3ahbe\\4ah00\\fscx67\\fscy66\\2chffffff\\3ch808080}你觉得呢. |

#### 相关类型

-   `Orientation` =: `"horizontal"` | `"vertical"`
    
-   `Placement` =: `"after"` | `"before"`
    

### 投放目标

**投放目标**

| Prop | 类型 | 默认 | 说明 |
| --- | --- | --- | --- |
| `active` | `boolean` | `false` | {\\fn黑体\\fs22\\bord1\\shad0\\3aHBE\\4aH00\\fscx67\\fscy66\\2cHFFFFFF\\3cH808080}你觉得怎么样? По:假 |
| `children` | `ReactNode` | —— 说 | Содержимое |
| `className` | `string` | —— 说 | 支助科 |
| `data-test-id` | `string` | —— 说 |  |
| `innerRef` | `Ref<HTMLDivElement>` | —— 说 | D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. . D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. D. . D. D. D. . . D. D. D. . D. . . D. D. . D. D. . D. D. . . D. D. . D. D. . . D. . . . . D. . |

{\\fn黑体\\fs22\\bord1\\shad0\\3aHBE\\4aH00\\fscx67\\fscy66\\2cHFFFFFF\\3cH808080}你觉得呢 `<div>`, (中文(简体) ), `data-test-id` 阿丽亚.. и `innerRef` (原始内容存档于2019-10-21) (英语). DnD.

## Смотри

-   **列表** {\\fn黑体\\fs20\\shad2\\2ah82\\3ah20\\4ah33\\fscx95\\3ch592001\\be1}你觉得呢.

## 常见问题

### @cloud-ru/ds-drag-and-drop 是什么？

\{\\fn黑体\\fs22\\bord1\\shad0\\3aHBE\\4aH00\\fscx67\\fscy66\\2cHFFFFFF\\3cH808080\}你觉得呢\.

### 如何安装 @cloud-ru/ds-drag-and-drop？

在项目目录运行 npm install @cloud-ru/ds-drag-and-drop，或使用 pnpm add / yarn add / bun add。

### @cloud-ru/ds-drag-and-drop 支持 TypeScript 吗？

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

### @cloud-ru/ds-drag-and-drop 支持 ESM 还是 CommonJS？

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

### @cloud-ru/ds-drag-and-drop 可以商用吗？

@cloud-ru/ds-drag-and-drop 使用 Apache-2\.0 许可。宽松许可：允许商业使用、修改和再分发，并附带明确的专利授权；分发时需保留许可与 NOTICE 文件，修改过的文件要注明改动。以上为概括，不构成法律意见，请以许可原文为准。

### @cloud-ru/ds-drag-and-drop 的下载量有多少？

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

### @cloud-ru/ds-drag-and-drop 还在维护吗？

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

