forty-cdk 0.2.0 → 0.3.0

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.
Files changed (220) hide show
  1. package/accordion/README.md +122 -0
  2. package/aspect-ratio/README.md +76 -0
  3. package/avatar/README.md +100 -0
  4. package/breadcrumbs/README.md +49 -0
  5. package/breakpoints/README.md +81 -0
  6. package/button/README.md +49 -0
  7. package/calendar/README.md +458 -0
  8. package/carousel/README.md +358 -0
  9. package/checkbox/README.md +146 -0
  10. package/combobox/README.md +535 -0
  11. package/context-menu/README.md +139 -0
  12. package/date-field/README.md +184 -0
  13. package/date-picker/README.md +338 -0
  14. package/dialog/README.md +388 -0
  15. package/disclosure/README.md +114 -0
  16. package/drag-drop/README.md +359 -0
  17. package/drawer/README.md +560 -0
  18. package/dropdown-menu/README.md +176 -0
  19. package/fesm2022/forty-cdk-accordion.mjs +348 -0
  20. package/fesm2022/forty-cdk-accordion.mjs.map +1 -0
  21. package/fesm2022/forty-cdk-aspect-ratio.mjs +74 -0
  22. package/fesm2022/forty-cdk-aspect-ratio.mjs.map +1 -0
  23. package/fesm2022/forty-cdk-avatar.mjs +308 -0
  24. package/fesm2022/forty-cdk-avatar.mjs.map +1 -0
  25. package/fesm2022/forty-cdk-breadcrumbs.mjs +125 -0
  26. package/fesm2022/forty-cdk-breadcrumbs.mjs.map +1 -0
  27. package/fesm2022/forty-cdk-breakpoints.mjs +117 -0
  28. package/fesm2022/forty-cdk-breakpoints.mjs.map +1 -0
  29. package/fesm2022/forty-cdk-button.mjs +134 -0
  30. package/fesm2022/forty-cdk-button.mjs.map +1 -0
  31. package/fesm2022/forty-cdk-calendar.mjs +2034 -0
  32. package/fesm2022/forty-cdk-calendar.mjs.map +1 -0
  33. package/fesm2022/forty-cdk-carousel.mjs +968 -0
  34. package/fesm2022/forty-cdk-carousel.mjs.map +1 -0
  35. package/fesm2022/forty-cdk-checkbox.mjs +226 -0
  36. package/fesm2022/forty-cdk-checkbox.mjs.map +1 -0
  37. package/fesm2022/forty-cdk-combobox.mjs +2596 -0
  38. package/fesm2022/forty-cdk-combobox.mjs.map +1 -0
  39. package/fesm2022/forty-cdk-context-menu.mjs +413 -0
  40. package/fesm2022/forty-cdk-context-menu.mjs.map +1 -0
  41. package/fesm2022/forty-cdk-core.mjs +9022 -0
  42. package/fesm2022/forty-cdk-core.mjs.map +1 -0
  43. package/fesm2022/forty-cdk-date-field.mjs +744 -0
  44. package/fesm2022/forty-cdk-date-field.mjs.map +1 -0
  45. package/fesm2022/forty-cdk-date-picker.mjs +1011 -0
  46. package/fesm2022/forty-cdk-date-picker.mjs.map +1 -0
  47. package/fesm2022/forty-cdk-dialog.mjs +707 -0
  48. package/fesm2022/forty-cdk-dialog.mjs.map +1 -0
  49. package/fesm2022/forty-cdk-disclosure.mjs +190 -0
  50. package/fesm2022/forty-cdk-disclosure.mjs.map +1 -0
  51. package/fesm2022/forty-cdk-drag-drop.mjs +1180 -0
  52. package/fesm2022/forty-cdk-drag-drop.mjs.map +1 -0
  53. package/fesm2022/forty-cdk-drawer.mjs +1641 -0
  54. package/fesm2022/forty-cdk-drawer.mjs.map +1 -0
  55. package/fesm2022/forty-cdk-dropdown-menu.mjs +350 -0
  56. package/fesm2022/forty-cdk-dropdown-menu.mjs.map +1 -0
  57. package/fesm2022/forty-cdk-field.mjs +425 -0
  58. package/fesm2022/forty-cdk-field.mjs.map +1 -0
  59. package/fesm2022/forty-cdk-fieldset.mjs +164 -0
  60. package/fesm2022/forty-cdk-fieldset.mjs.map +1 -0
  61. package/fesm2022/forty-cdk-file-upload.mjs +221 -0
  62. package/fesm2022/forty-cdk-file-upload.mjs.map +1 -0
  63. package/fesm2022/forty-cdk-hover-card.mjs +496 -0
  64. package/fesm2022/forty-cdk-hover-card.mjs.map +1 -0
  65. package/fesm2022/forty-cdk-input.mjs +274 -0
  66. package/fesm2022/forty-cdk-input.mjs.map +1 -0
  67. package/fesm2022/forty-cdk-internationalized-date.mjs +1 -1
  68. package/fesm2022/forty-cdk-internationalized-date.mjs.map +1 -1
  69. package/fesm2022/forty-cdk-listbox.mjs +1279 -0
  70. package/fesm2022/forty-cdk-listbox.mjs.map +1 -0
  71. package/fesm2022/forty-cdk-menu.mjs +1439 -0
  72. package/fesm2022/forty-cdk-menu.mjs.map +1 -0
  73. package/fesm2022/forty-cdk-menubar.mjs +787 -0
  74. package/fesm2022/forty-cdk-menubar.mjs.map +1 -0
  75. package/fesm2022/forty-cdk-meter.mjs +211 -0
  76. package/fesm2022/forty-cdk-meter.mjs.map +1 -0
  77. package/fesm2022/forty-cdk-navigation-menu.mjs +1145 -0
  78. package/fesm2022/forty-cdk-navigation-menu.mjs.map +1 -0
  79. package/fesm2022/forty-cdk-number-input.mjs +559 -0
  80. package/fesm2022/forty-cdk-number-input.mjs.map +1 -0
  81. package/fesm2022/forty-cdk-otp-input.mjs +527 -0
  82. package/fesm2022/forty-cdk-otp-input.mjs.map +1 -0
  83. package/fesm2022/forty-cdk-pagination.mjs +323 -0
  84. package/fesm2022/forty-cdk-pagination.mjs.map +1 -0
  85. package/fesm2022/forty-cdk-pane-resizer.mjs +297 -0
  86. package/fesm2022/forty-cdk-pane-resizer.mjs.map +1 -0
  87. package/fesm2022/forty-cdk-popover.mjs +698 -0
  88. package/fesm2022/forty-cdk-popover.mjs.map +1 -0
  89. package/fesm2022/forty-cdk-progress.mjs +226 -0
  90. package/fesm2022/forty-cdk-progress.mjs.map +1 -0
  91. package/fesm2022/forty-cdk-radio-group.mjs +378 -0
  92. package/fesm2022/forty-cdk-radio-group.mjs.map +1 -0
  93. package/fesm2022/forty-cdk-scroll-area.mjs +640 -0
  94. package/fesm2022/forty-cdk-scroll-area.mjs.map +1 -0
  95. package/fesm2022/forty-cdk-search.mjs +205 -0
  96. package/fesm2022/forty-cdk-search.mjs.map +1 -0
  97. package/fesm2022/forty-cdk-select.mjs +1661 -0
  98. package/fesm2022/forty-cdk-select.mjs.map +1 -0
  99. package/fesm2022/forty-cdk-separator.mjs +82 -0
  100. package/fesm2022/forty-cdk-separator.mjs.map +1 -0
  101. package/fesm2022/forty-cdk-signal-forms.mjs +97 -0
  102. package/fesm2022/forty-cdk-signal-forms.mjs.map +1 -0
  103. package/fesm2022/forty-cdk-slider.mjs +803 -0
  104. package/fesm2022/forty-cdk-slider.mjs.map +1 -0
  105. package/fesm2022/forty-cdk-stepper.mjs +886 -0
  106. package/fesm2022/forty-cdk-stepper.mjs.map +1 -0
  107. package/fesm2022/forty-cdk-switch.mjs +137 -0
  108. package/fesm2022/forty-cdk-switch.mjs.map +1 -0
  109. package/fesm2022/forty-cdk-table.mjs +1518 -0
  110. package/fesm2022/forty-cdk-table.mjs.map +1 -0
  111. package/fesm2022/forty-cdk-tabs.mjs +400 -0
  112. package/fesm2022/forty-cdk-tabs.mjs.map +1 -0
  113. package/fesm2022/forty-cdk-time-field.mjs +593 -0
  114. package/fesm2022/forty-cdk-time-field.mjs.map +1 -0
  115. package/fesm2022/forty-cdk-time-picker.mjs +1013 -0
  116. package/fesm2022/forty-cdk-time-picker.mjs.map +1 -0
  117. package/fesm2022/forty-cdk-toast.mjs +1153 -0
  118. package/fesm2022/forty-cdk-toast.mjs.map +1 -0
  119. package/fesm2022/forty-cdk-toggle.mjs +516 -0
  120. package/fesm2022/forty-cdk-toggle.mjs.map +1 -0
  121. package/fesm2022/forty-cdk-toolbar.mjs +374 -0
  122. package/fesm2022/forty-cdk-toolbar.mjs.map +1 -0
  123. package/fesm2022/forty-cdk-tooltip.mjs +672 -0
  124. package/fesm2022/forty-cdk-tooltip.mjs.map +1 -0
  125. package/fesm2022/forty-cdk-tree.mjs +2007 -0
  126. package/fesm2022/forty-cdk-tree.mjs.map +1 -0
  127. package/fesm2022/forty-cdk-virtualization.mjs +1 -1
  128. package/fesm2022/forty-cdk-virtualization.mjs.map +1 -1
  129. package/fesm2022/forty-cdk.mjs +0 -43310
  130. package/fesm2022/forty-cdk.mjs.map +1 -1
  131. package/field/README.md +97 -0
  132. package/fieldset/README.md +86 -0
  133. package/file-upload/README.md +73 -0
  134. package/hover-card/README.md +171 -0
  135. package/input/README.md +156 -0
  136. package/listbox/README.md +424 -0
  137. package/menu/README.md +181 -0
  138. package/menubar/README.md +140 -0
  139. package/meter/README.md +128 -0
  140. package/navigation-menu/README.md +253 -0
  141. package/number-input/README.md +171 -0
  142. package/otp-input/README.md +198 -0
  143. package/package.json +213 -1
  144. package/pagination/README.md +61 -0
  145. package/pane-resizer/README.md +136 -0
  146. package/popover/README.md +262 -0
  147. package/progress/README.md +115 -0
  148. package/radio-group/README.md +129 -0
  149. package/scroll-area/README.md +184 -0
  150. package/search/README.md +42 -0
  151. package/select/README.md +488 -0
  152. package/separator/README.md +84 -0
  153. package/signal-forms/README.md +72 -0
  154. package/slider/README.md +152 -0
  155. package/stepper/README.md +292 -0
  156. package/switch/README.md +116 -0
  157. package/table/README.md +769 -0
  158. package/tabs/README.md +130 -0
  159. package/time-field/README.md +157 -0
  160. package/time-picker/README.md +172 -0
  161. package/toast/README.md +398 -0
  162. package/toggle/README.md +224 -0
  163. package/toolbar/README.md +109 -0
  164. package/tooltip/README.md +274 -0
  165. package/tree/README.md +708 -0
  166. package/types/forty-cdk-accordion.d.ts +242 -0
  167. package/types/forty-cdk-aspect-ratio.d.ts +59 -0
  168. package/types/forty-cdk-avatar.d.ts +133 -0
  169. package/types/forty-cdk-breadcrumbs.d.ts +92 -0
  170. package/types/forty-cdk-breakpoints.d.ts +141 -0
  171. package/types/forty-cdk-button.d.ts +80 -0
  172. package/types/forty-cdk-calendar.d.ts +914 -0
  173. package/types/forty-cdk-carousel.d.ts +530 -0
  174. package/types/forty-cdk-checkbox.d.ts +141 -0
  175. package/types/forty-cdk-combobox.d.ts +1259 -0
  176. package/types/forty-cdk-context-menu.d.ts +313 -0
  177. package/types/forty-cdk-core.d.ts +5774 -0
  178. package/types/forty-cdk-date-field.d.ts +307 -0
  179. package/types/forty-cdk-date-picker.d.ts +622 -0
  180. package/types/forty-cdk-dialog.d.ts +546 -0
  181. package/types/forty-cdk-disclosure.d.ts +127 -0
  182. package/types/forty-cdk-drag-drop.d.ts +456 -0
  183. package/types/forty-cdk-drawer.d.ts +871 -0
  184. package/types/forty-cdk-dropdown-menu.d.ts +242 -0
  185. package/types/forty-cdk-field.d.ts +236 -0
  186. package/types/forty-cdk-fieldset.d.ts +119 -0
  187. package/types/forty-cdk-file-upload.d.ts +124 -0
  188. package/types/forty-cdk-hover-card.d.ts +320 -0
  189. package/types/forty-cdk-input.d.ts +169 -0
  190. package/types/forty-cdk-internationalized-date.d.ts +1 -1
  191. package/types/forty-cdk-listbox.d.ts +513 -0
  192. package/types/forty-cdk-menu.d.ts +629 -0
  193. package/types/forty-cdk-menubar.d.ts +451 -0
  194. package/types/forty-cdk-meter.d.ts +122 -0
  195. package/types/forty-cdk-navigation-menu.d.ts +514 -0
  196. package/types/forty-cdk-number-input.d.ts +319 -0
  197. package/types/forty-cdk-otp-input.d.ts +248 -0
  198. package/types/forty-cdk-pagination.d.ts +214 -0
  199. package/types/forty-cdk-pane-resizer.d.ts +145 -0
  200. package/types/forty-cdk-popover.d.ts +509 -0
  201. package/types/forty-cdk-progress.d.ts +143 -0
  202. package/types/forty-cdk-radio-group.d.ts +222 -0
  203. package/types/forty-cdk-scroll-area.d.ts +258 -0
  204. package/types/forty-cdk-search.d.ts +142 -0
  205. package/types/forty-cdk-select.d.ts +899 -0
  206. package/types/forty-cdk-separator.d.ts +59 -0
  207. package/types/forty-cdk-signal-forms.d.ts +58 -0
  208. package/types/forty-cdk-slider.d.ts +379 -0
  209. package/types/forty-cdk-stepper.d.ts +650 -0
  210. package/types/forty-cdk-switch.d.ts +87 -0
  211. package/types/forty-cdk-table.d.ts +723 -0
  212. package/types/forty-cdk-tabs.d.ts +235 -0
  213. package/types/forty-cdk-time-field.d.ts +307 -0
  214. package/types/forty-cdk-time-picker.d.ts +578 -0
  215. package/types/forty-cdk-toast.d.ts +598 -0
  216. package/types/forty-cdk-toggle.d.ts +310 -0
  217. package/types/forty-cdk-toolbar.d.ts +217 -0
  218. package/types/forty-cdk-tooltip.d.ts +436 -0
  219. package/types/forty-cdk-tree.d.ts +688 -0
  220. package/types/forty-cdk.d.ts +1 -19743
@@ -0,0 +1,359 @@
1
+ # Drag & Drop
2
+
3
+ Headless accessible drag-and-drop for sortable lists and cross-list item
4
+ transfers. Supports both keyboard and pointer (mouse / touch / pen) dragging.
5
+
6
+ For repositioning an arbitrary element (no list, no reorder) — e.g. dragging a
7
+ whole dialog around by its header — see [`[forFreeDrag]`](#free-drag-forfreedrag).
8
+
9
+ ## Keyboard model
10
+
11
+ | State | Key | Action |
12
+ | ------ | ----------- | ------------------------------------------ |
13
+ | Idle | Arrow keys | Move roving focus between items |
14
+ | Idle | Home / End | Jump to first / last item |
15
+ | Idle | Space/Enter | **Lift** the focused item |
16
+ | Lifted | Arrow keys | Step the logical drop position |
17
+ | Lifted | Space/Enter | **Drop** (commits and emits `(dragDrop)`) |
18
+ | Lifted | Escape | **Cancel** (no event, focus stays on item) |
19
+
20
+ Arrow direction follows the list's `orientation` and respects RTL via `dir`. In
21
+ `orientation="mixed"` every arrow key steps the lifted item linearly in DOM order.
22
+
23
+ ## Pointer dragging
24
+
25
+ When a pointer drag starts, the dragged item stays in place and reflects
26
+ `data-dragging` (style it as a dimmed gap). A fixed-position clone of the item
27
+ follows the pointer as the default preview. The clone carries
28
+ `data-for-drag-preview` and `aria-hidden="true"`.
29
+
30
+ ### Auto-scroll
31
+
32
+ While a pointer drag is in flight, `[forDropList]` automatically scrolls the
33
+ nearest scrollable container (the list itself, a scrollable ancestor, or the
34
+ viewport) toward whichever edge the pointer approaches. Speed scales with
35
+ proximity — the closer the pointer is to the edge, the faster the scroll.
36
+
37
+ The feature is **on by default**. Opt out with `[autoScroll]="false"`:
38
+
39
+ ```html
40
+ <ul forDropList [autoScroll]="false" (dragDrop)="onDrop($event)">
41
+ …
42
+ </ul>
43
+ ```
44
+
45
+ Configure the edge zone and max speed via `provideForDragDropDefaults`:
46
+
47
+ ```ts
48
+ providers: [
49
+ provideForDragDropDefaults({
50
+ autoScrollEdgeSize: 80,
51
+ autoScrollMaxSpeed: 24,
52
+ }),
53
+ ];
54
+ ```
55
+
56
+ Keyboard dragging is unaffected. SSR-safe — no-op when there is no browser window.
57
+
58
+ ### Optional drag handle
59
+
60
+ Apply `[forDragHandle]` on a child element of `[forDraggable]` to restrict
61
+ where a pointer gesture may start. Once any handle is present on an item,
62
+ pointer drags may only begin from within that handle — keyboard dragging is
63
+ unaffected.
64
+
65
+ ```html
66
+ <li forDraggable [dragData]="item">
67
+ <span forDragHandle aria-hidden="true">::</span>
68
+ {{ item.label }}
69
+ </li>
70
+ ```
71
+
72
+ ### Custom preview & placeholder
73
+
74
+ Place `<ng-template forDragPreview>` and/or `<ng-template forDragPlaceholder>` as direct
75
+ children of `[forDraggable]` to override the default drag visuals during a pointer drag.
76
+
77
+ ```html
78
+ <li forDraggable [dragData]="item">
79
+ {{ item.label }}
80
+ <ng-template forDragPreview>
81
+ <div class="my-preview">{{ item.label }}</div>
82
+ </ng-template>
83
+ <ng-template forDragPlaceholder>
84
+ <div class="my-placeholder"></div>
85
+ </ng-template>
86
+ </li>
87
+ ```
88
+
89
+ - **`[forDragPreview]`** replaces the default cloned floating element that follows the pointer
90
+ during a pointer drag. Applies to pointer drags only; keyboard dragging is unaffected.
91
+ - **`[forDragPlaceholder]`** renders in the dragged item's slot while a pointer drag is in flight.
92
+ The dragged item's host is hidden (`display: none`) and the placeholder template occupies its
93
+ space, preserving the gap. When the drag ends (drop or cancel) the placeholder is removed and
94
+ the item is revealed again. Keyboard dragging keeps the default behaviour — the lifted item
95
+ stays in place reflecting `data-dragging`, and no placeholder is rendered.
96
+
97
+ ### Live-sort placeholder
98
+
99
+ Add `[liveSort]="true"` to `[forDropList]` to make the `[forDragPlaceholder]` follow the live
100
+ resolved drop index during a pointer drag — within the list and across connected lists — so
101
+ siblings part to reveal where the item will land. When `false` (the default), the placeholder
102
+ stays in the dragged item's source slot.
103
+
104
+ ```html
105
+ <ul forDropList [liveSort]="true" (dragDrop)="onDrop($event)">
106
+ @for (item of items(); track item.id) {
107
+ <li forDraggable [dragData]="item">
108
+ {{ item.label }}
109
+ <ng-template forDragPlaceholder>
110
+ <div class="my-placeholder"></div>
111
+ </ng-template>
112
+ </li>
113
+ }
114
+ </ul>
115
+ ```
116
+
117
+ `[liveSort]` has no visible effect without a `[forDragPlaceholder]` template, and has no effect
118
+ on keyboard dragging.
119
+
120
+ ### Boundary & axis lock
121
+
122
+ `[forDropList]` supports two opt-in visual constraints on the pointer-drag preview. Both are
123
+ `null` by default and have **no effect on keyboard dragging** (which has no floating preview).
124
+ Neither changes the resolved drop index — they constrain the visual preview only.
125
+
126
+ **`[boundary]`** — confine the preview within a boundary element. Accepts an `HTMLElement` or
127
+ a CSS selector string resolved via `closest()` from the list host. The preview box is clamped so
128
+ it stays fully inside the boundary. When the boundary is smaller than the preview on an axis,
129
+ the preview is pinned to the boundary's start edge on that axis.
130
+
131
+ **`[lockAxis]`** — constrain movement to one axis. `'x'` keeps the preview at its lift-time `y`
132
+ (horizontal-only movement); `'y'` keeps it at its lift-time `x` (vertical-only movement).
133
+
134
+ Both inputs may be combined:
135
+
136
+ ```html
137
+ <div class="container" #container>
138
+ <ul forDropList [boundary]="container" lockAxis="x" (dragDrop)="onDrop($event)">
139
+ @for (item of items(); track item.id) {
140
+ <li forDraggable [dragData]="item">{{ item.label }}</li>
141
+ }
142
+ </ul>
143
+ </div>
144
+ ```
145
+
146
+ String selector form (resolved via `closest()` on the list host):
147
+
148
+ ```html
149
+ <ul forDropList [boundary]="'.my-scroller'" (dragDrop)="onDrop($event)">
150
+ …
151
+ </ul>
152
+ ```
153
+
154
+ ### Reorder & settle animations
155
+
156
+ Add `[animateReorder]="true"` to `[forDropList]` to animate committed drops. When enabled:
157
+
158
+ - **FLIP reorder** — displaced sibling items transition smoothly from their old positions to their
159
+ new ones instead of snapping.
160
+ - **Drop-settle** — on a pointer drag, the floating preview transitions from its release position
161
+ into the final item slot before it is removed.
162
+
163
+ Both are opt-in and fully skipped under `prefers-reduced-motion: reduce`. They work for both
164
+ keyboard and pointer drags. The library publishes the styling hooks below — duration / easing are
165
+ always provided by the consumer via CSS; the library imposes none.
166
+
167
+ ```html
168
+ <ul forDropList [animateReorder]="true" (dragDrop)="onDrop($event)">
169
+ …
170
+ </ul>
171
+ ```
172
+
173
+ ```css
174
+ [forDraggable][data-drag-animating] {
175
+ transition: transform 200ms ease;
176
+ }
177
+ [data-for-drag-preview][data-settling] {
178
+ transition: transform 200ms ease;
179
+ }
180
+ ```
181
+
182
+ With no such CSS, `animateReorder` is a graceful no-op — transforms clear instantly and the
183
+ preview is destroyed promptly.
184
+
185
+ ## Orientation
186
+
187
+ `[forDropList]` resolves the live drop index along its `orientation`:
188
+
189
+ - **`"vertical"`** (default) — a stacked column; the index is resolved by the pointer's `y`.
190
+ - **`"horizontal"`** — a single row; the index is resolved by the pointer's `x` (RTL-aware).
191
+ - **`"mixed"`** — a wrapping grid (`flex-wrap` / CSS grid) of **uniformly-sized** items. The index
192
+ is resolved in 2D, so an item dragged across a wrapped row lands in the slot under the pointer's
193
+ row **and** column instead of mis-resolving to the nearest single-axis slot. A `"mixed"` list that
194
+ happens to render as a single row or single column resolves identically to `"horizontal"` /
195
+ `"vertical"`.
196
+
197
+ ```html
198
+ <ul class="grid" forDropList orientation="mixed" (dragDrop)="onDrop($event)">
199
+ @for (item of items(); track item.id) {
200
+ <li forDraggable [dragData]="item">{{ item.label }}</li>
201
+ }
202
+ </ul>
203
+ ```
204
+
205
+ ```css
206
+ .grid {
207
+ display: flex;
208
+ flex-wrap: wrap;
209
+ gap: 8px;
210
+ }
211
+ ```
212
+
213
+ A wrapper can default the orientation for every `[forDropList]` in its scope via the
214
+ `FOR_DROP_LIST_DEFAULT_ORIENTATION` token (the same mechanism `ForTableColumnReorder` uses for
215
+ `"horizontal"`):
216
+
217
+ ```ts
218
+ providers: [{ provide: FOR_DROP_LIST_DEFAULT_ORIENTATION, useValue: 'mixed' }];
219
+ ```
220
+
221
+ `"mixed"` targets regular grids of uniformly-sized items; variable-size / masonry layouts are out of
222
+ scope. `[animateReorder]` (FLIP) reflows by DOM order and needs no change in mixed mode.
223
+
224
+ ## Free drag (`[forFreeDrag]`)
225
+
226
+ `[forFreeDrag]` repositions its host element (or a resolved `rootElement`) by pointer drag, with
227
+ **no `[forDropList]` required** — it never commits a reorder, it just moves the element around via a
228
+ CSS `transform: translate(...)`. It is the standalone counterpart to a sortable list item: a
229
+ pointer-driven way to move an element freely, with optional root-element retargeting, a confinement
230
+ boundary, axis locking, and a controllable position (see the inputs below).
231
+
232
+ ```html
233
+ <!-- move the whole dialog by its header -->
234
+ <div class="dialog">
235
+ <header forFreeDrag rootElement=".dialog" boundary=".viewport">Drag me</header>
236
+ …
237
+ </div>
238
+
239
+ <!-- or with an explicit handle and a controllable position -->
240
+ <div forFreeDrag [(position)]="pos" boundary=".viewport">
241
+ <span forDragHandle aria-hidden="true">⠿</span>
242
+ …
243
+ </div>
244
+ ```
245
+
246
+ | Input | Type | Default | Meaning |
247
+ | ------------- | ------------------------------- | ------------- | -------------------------------------------------------------------------------------------------- |
248
+ | `disabled` | `boolean` | `false` | When true, the element can't be dragged (it stays focusable; the transform doesn't change). |
249
+ | `rootElement` | `HTMLElement \| string \| null` | `null` | The element actually moved. A `closest()` selector resolves an ancestor. `null` moves the host. |
250
+ | `boundary` | `HTMLElement \| string \| null` | `null` | Confine the moved element fully inside this element (or `closest()` selector). `null` = unbounded. |
251
+ | `lockAxis` | `'x' \| 'y' \| null` | `null` | Constrain movement to one axis. `'x'` pins lift-time `y`, `'y'` pins lift-time `x`. |
252
+ | `position` | `model<{ x; y }>` | `{ x:0,y:0 }` | Two-way translate offset (px) from the element's natural position. Controllable / restorable. |
253
+
254
+ | Output | Payload | Fires |
255
+ | ----------- | ---------- | ---------------------------------------------------------------------------------------------- |
256
+ | `dragStart` | `{ x; y }` | When a pointer drag starts (the lift-time position). |
257
+ | `dragMove` | `{ x; y }` | On every armed move, with the live position. |
258
+ | `dragEnd` | `{ x; y }` | When the drag ends (commit keeps the position; cancel/Escape restores the lift-time snapshot). |
259
+
260
+ `[forDragHandle]` works inside `[forFreeDrag]` exactly as it does inside `[forDraggable]`: once any
261
+ handle is present, a pointer drag may only start from within a handle.
262
+
263
+ **Accessibility.** Free-drag is **pointer-only** — there is no WAI-ARIA pattern for "reposition an
264
+ element", so it owns no role or ARIA state. The consumer is responsible
265
+ for keeping the moved element fully usable at its default position (e.g. a repositionable dialog must
266
+ still be operable by keyboard); dragging is a pointer convenience, not the only way to use it.
267
+
268
+ ## Data attributes
269
+
270
+ | Attribute | Element | Meaning |
271
+ | ----------------------- | ----------------- | ------------------------------------------------------------------------------------ |
272
+ | `data-orientation` | `[forDropList]` | `"vertical"`, `"horizontal"`, or `"mixed"` |
273
+ | `data-disabled` | both | Present when the item or list is disabled |
274
+ | `data-disabled` | `[forFreeDrag]` | Present when the free-drag element is disabled |
275
+ | `data-dragging` | `[forDropList]` | Present while a drag originates here |
276
+ | `data-dragging` | `[forDraggable]` | Present while this item is lifted |
277
+ | `data-dragging` | `[forFreeDrag]` | Present while a free-drag pointer gesture is armed |
278
+ | `data-drag-over` | `[forDropList]` | Present while this list is the drop target |
279
+ | `data-drag-handle` | `[forDragHandle]` | Present on every registered drag handle |
280
+ | `data-for-drag-preview` | preview element | Present on the default clone preview **or** the `[forDragPreview]` template wrapper |
281
+ | `data-drag-animating` | `[forDraggable]` | Present while the item's FLIP reorder transition plays (requires `[animateReorder]`) |
282
+ | `data-settling` | preview element | Present while the drop-settle transition plays (requires `[animateReorder]`) |
283
+
284
+ ## Sortable list
285
+
286
+ ```html
287
+ <ul forDropList (dragDrop)="onDrop($event)">
288
+ @for (item of items(); track item.id) {
289
+ <li forDraggable [dragData]="item">{{ item.label }}</li>
290
+ }
291
+ </ul>
292
+ ```
293
+
294
+ ```ts
295
+ onDrop(event: ForDragDropEvent<MyItem>): void {
296
+ this.items.set(
297
+ moveItemInArray(this.items(), event.previousIndex, event.currentIndex),
298
+ );
299
+ }
300
+ ```
301
+
302
+ ## Two-list transfer with `forDropListGroup`
303
+
304
+ ```html
305
+ <div forDropListGroup>
306
+ <ul forDropList (dragDrop)="onDrop($event)">
307
+ @for (item of active(); track item.id) {
308
+ <li forDraggable [dragData]="item">{{ item.label }}</li>
309
+ }
310
+ </ul>
311
+ <ul forDropList (dragDrop)="onDrop($event)">
312
+ @for (item of archived(); track item.id) {
313
+ <li forDraggable [dragData]="item">{{ item.label }}</li>
314
+ }
315
+ </ul>
316
+ </div>
317
+ ```
318
+
319
+ ```ts
320
+ onDrop(event: ForDragDropEvent<MyItem>): void {
321
+ if (event.previousContainer === event.container) {
322
+ this.updateList(event.container, (arr) =>
323
+ moveItemInArray(arr, event.previousIndex, event.currentIndex),
324
+ );
325
+ } else {
326
+ const result = transferArrayItem(
327
+ event.previousContainer === this.activeCtx ? this.active() : this.archived(),
328
+ event.container === this.activeCtx ? this.active() : this.archived(),
329
+ event.previousIndex,
330
+ event.currentIndex,
331
+ );
332
+ this.active.set(result.from);
333
+ this.archived.set(result.to);
334
+ }
335
+ }
336
+ ```
337
+
338
+ ## Two-list transfer with explicit `[connectedTo]`
339
+
340
+ ```html
341
+ <ul forDropList #listA="forDropList" [connectedTo]="[listB]" (dragDrop)="onDrop($event)">
342
+ ...
343
+ </ul>
344
+ <ul forDropList #listB="forDropList" [connectedTo]="[listA]" (dragDrop)="onDrop($event)">
345
+ ...
346
+ </ul>
347
+ ```
348
+
349
+ ## Announcement customisation
350
+
351
+ Override the default ARIA live-region messages at any injector scope:
352
+
353
+ ```ts
354
+ providers: [
355
+ provideForDragDropDefaults({
356
+ announceLift: (label, index, total) => `Grabbed ${label}, position ${index} of ${total}.`,
357
+ }),
358
+ ];
359
+ ```