@dcs-tech/ui 0.9.0 → 0.11.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 (235) hide show
  1. package/CHANGELOG.md +488 -0
  2. package/README.md +43 -7
  3. package/THIRD_PARTY_NOTICES.md +23 -0
  4. package/dist/ChartImageMenu-sB2QNQzd.js +9673 -0
  5. package/dist/ChartView-BstZkP1g.js +1942 -0
  6. package/dist/{SummaryChart-CxRjK_HU.js → SummaryChart-B5ibDNOZ.js} +11 -10
  7. package/dist/{SummaryImage-Crf1R-3a.js → SummaryImage-CRP7X2Nl.js} +2 -2
  8. package/dist/SummarySeeAll-CtYRGV4G.js +101 -0
  9. package/dist/assets/fileTask.worker-D97s2vRV.js +1 -0
  10. package/dist/columnValue-BOn9NC8X.js +644 -0
  11. package/dist/exportContext-CMzuzRjc.js +274 -0
  12. package/dist/{exportEngine-BFZD6djX.js → exportEngine-CYDN8Ty-.js} +167 -137
  13. package/dist/file-worker.js +1 -1
  14. package/dist/{fileActions-CFNO14Aj.js → fileActions-DkPEWE-t.js} +1 -1
  15. package/dist/{geometry-yZmKN662.js → geometry-CFS5If1N.js} +848 -439
  16. package/dist/index.js +24208 -12603
  17. package/dist/{labels-CnqqTrne.js → labels-mukFhYkc.js} +126 -1
  18. package/dist/{runFileTask-BIZTFnZP.js → runFileTask-DI_39TjR.js} +17 -0
  19. package/dist/scrollArea-B52kugL1.js +291 -0
  20. package/dist/style.css +1 -1
  21. package/dist/{summaryChartData-CARqGRUl.js → summaryChartData-D15kw64n.js} +10 -3
  22. package/dist/types/components/Alert/Alert.d.ts +16 -0
  23. package/dist/types/components/Alert/index.d.ts +2 -0
  24. package/dist/types/components/Card/Card.d.ts +4 -3
  25. package/dist/types/components/Card/index.d.ts +1 -1
  26. package/dist/types/components/Charts/BarList.d.ts +4 -3
  27. package/dist/types/components/Charts/CalendarHeatmap.d.ts +4 -2
  28. package/dist/types/components/Charts/Chart.d.ts +3 -2
  29. package/dist/types/components/Charts/ChartView.d.ts +3 -2
  30. package/dist/types/components/Charts/ColumnChart.d.ts +4 -3
  31. package/dist/types/components/Charts/Donut.d.ts +3 -2
  32. package/dist/types/components/Charts/Funnel.d.ts +4 -2
  33. package/dist/types/components/Charts/Gauge.d.ts +3 -2
  34. package/dist/types/components/Charts/LineChart.d.ts +4 -3
  35. package/dist/types/components/Charts/NumberTrend.d.ts +4 -3
  36. package/dist/types/components/Charts/Progress.d.ts +3 -2
  37. package/dist/types/components/Charts/StackedBar.d.ts +3 -2
  38. package/dist/types/components/Charts/Treemap.d.ts +3 -2
  39. package/dist/types/components/Charts/chartData.d.ts +6 -0
  40. package/dist/types/components/Charts/chartImage.d.ts +3 -0
  41. package/dist/types/components/Charts/geometry.d.ts +3 -0
  42. package/dist/types/components/Charts/index.d.ts +2 -0
  43. package/dist/types/components/Charts/palette.d.ts +1 -0
  44. package/dist/types/components/Charts/parts.d.ts +14 -0
  45. package/dist/types/components/Charts/useChartMotion.d.ts +8 -0
  46. package/dist/types/components/ChipInput/ChipTags.d.ts +3 -0
  47. package/dist/types/components/CommandPalette/CommandPaletteTrigger.d.ts +9 -0
  48. package/dist/types/components/CommandPalette/index.d.ts +2 -0
  49. package/dist/types/components/DataTable/DataTable.d.ts +3 -1
  50. package/dist/types/components/DataTable/DisplayPopover.d.ts +1 -0
  51. package/dist/types/components/DataTable/HeaderMenu.d.ts +1 -0
  52. package/dist/types/components/DataTable/TableColumnModal.d.ts +4 -1
  53. package/dist/types/components/DataTable/TablePagination.d.ts +1 -1
  54. package/dist/types/components/DataTable/TableToolbar.d.ts +21 -1
  55. package/dist/types/components/DataTable/TableView.d.ts +19 -2
  56. package/dist/types/components/DataTable/cards/CardView.d.ts +25 -5
  57. package/dist/types/components/DataTable/cards/cardFields.d.ts +1 -0
  58. package/dist/types/components/DataTable/cards/rowParts.d.ts +1 -0
  59. package/dist/types/components/DataTable/cellSelection/CellRangeBar.d.ts +16 -0
  60. package/dist/types/components/DataTable/cellSelection/cellRangeStore.d.ts +18 -0
  61. package/dist/types/components/DataTable/cellSelection/paintRanges.d.ts +2 -0
  62. package/dist/types/components/DataTable/cellSelection/useCellSelection.d.ts +63 -0
  63. package/dist/types/components/DataTable/data/listDelta.d.ts +27 -0
  64. package/dist/types/components/DataTable/data/rowLineage.d.ts +3 -0
  65. package/dist/types/components/DataTable/data/rowModels.d.ts +9 -0
  66. package/dist/types/components/DataTable/data/rowTransaction.d.ts +9 -0
  67. package/dist/types/components/DataTable/data/useServerData.d.ts +3 -1
  68. package/dist/types/components/DataTable/defaults.d.ts +4 -0
  69. package/dist/types/components/DataTable/export/exportCells.d.ts +5 -2
  70. package/dist/types/components/DataTable/export/exportEngine.d.ts +7 -2
  71. package/dist/types/components/DataTable/export/useTableExport.d.ts +17 -1
  72. package/dist/types/components/DataTable/filters/filterRowModel.d.ts +1 -0
  73. package/dist/types/components/DataTable/grouping/groupModel.d.ts +11 -0
  74. package/dist/types/components/DataTable/index.d.ts +1 -1
  75. package/dist/types/components/DataTable/keyboard/ShortcutsDialog.d.ts +4 -1
  76. package/dist/types/components/DataTable/keyboard/useGridKeyboard.d.ts +8 -0
  77. package/dist/types/components/DataTable/labels.d.ts +130 -0
  78. package/dist/types/components/DataTable/layout/LayoutSwitcher.d.ts +10 -2
  79. package/dist/types/components/DataTable/layout/useFitWidths.d.ts +7 -0
  80. package/dist/types/components/DataTable/menu/RowMenu.d.ts +1 -0
  81. package/dist/types/components/DataTable/menu/buildRowMenu.d.ts +6 -3
  82. package/dist/types/components/DataTable/motion/RowChangeNotice.d.ts +19 -0
  83. package/dist/types/components/DataTable/motion/rowChanges.d.ts +25 -0
  84. package/dist/types/components/DataTable/motion/useNoticeInsets.d.ts +2 -0
  85. package/dist/types/components/DataTable/motion/useRowChangeNotices.d.ts +35 -0
  86. package/dist/types/components/DataTable/motion/useRowMotion.d.ts +29 -3
  87. package/dist/types/components/DataTable/persistence/reconcile.d.ts +4 -0
  88. package/dist/types/components/DataTable/persistence/useColumnPersistence.d.ts +5 -1
  89. package/dist/types/components/DataTable/pivot/PivotPanel.d.ts +11 -0
  90. package/dist/types/components/DataTable/pivot/PivotView.d.ts +22 -0
  91. package/dist/types/components/DataTable/pivot/pivotModel.d.ts +54 -0
  92. package/dist/types/components/DataTable/pivot/usePivot.d.ts +44 -0
  93. package/dist/types/components/DataTable/rows/PressRow.d.ts +1 -0
  94. package/dist/types/components/DataTable/rows/RowLead.d.ts +23 -0
  95. package/dist/types/components/DataTable/rows/rowPress.d.ts +2 -0
  96. package/dist/types/components/DataTable/rows/usePinnedRows.d.ts +34 -0
  97. package/dist/types/components/DataTable/rows/useRowDrag.d.ts +44 -0
  98. package/dist/types/components/DataTable/split/SplitView.d.ts +4 -2
  99. package/dist/types/components/DataTable/summary/SummaryChart.d.ts +2 -1
  100. package/dist/types/components/DataTable/summary/TableSummary.d.ts +2 -1
  101. package/dist/types/components/DataTable/summary/summaryModel.d.ts +28 -6
  102. package/dist/types/components/DataTable/summary/useTableSummary.d.ts +3 -0
  103. package/dist/types/components/DataTable/toolbar/ToolbarMore.d.ts +14 -0
  104. package/dist/types/components/DataTable/toolbar/useToolbarFit.d.ts +10 -0
  105. package/dist/types/components/DataTable/tree/TreeChips.d.ts +5 -0
  106. package/dist/types/components/DataTable/tree/treeExport.d.ts +54 -0
  107. package/dist/types/components/DataTable/tree/treeMove.d.ts +1 -0
  108. package/dist/types/components/DataTable/tree/useTreeChildren.d.ts +15 -0
  109. package/dist/types/components/DataTable/tree/useTreeData.d.ts +60 -0
  110. package/dist/types/components/DataTable/types.d.ts +290 -6
  111. package/dist/types/components/DataTable/ui-local/TableReorderList.d.ts +13 -0
  112. package/dist/types/components/DataTable/ui.d.ts +2 -1
  113. package/dist/types/components/DataTable/useDataChangeTracker.d.ts +11 -4
  114. package/dist/types/components/DataTable/useTable.d.ts +14 -1
  115. package/dist/types/components/DataTable/virtual/useVirtualLines.d.ts +1 -0
  116. package/dist/types/components/DatePicker/PeriodGrid.d.ts +13 -0
  117. package/dist/types/components/DatePicker/PeriodPicker.d.ts +19 -0
  118. package/dist/types/components/DatePicker/index.d.ts +1 -1
  119. package/dist/types/components/Dialog/dialogSlots.d.ts +9 -0
  120. package/dist/types/components/DropdownMenu/DropdownMenu.d.ts +8 -0
  121. package/dist/types/components/EventCalendar/EventCalendar.d.ts +46 -0
  122. package/dist/types/components/EventCalendar/eventParts.d.ts +10 -0
  123. package/dist/types/components/EventCalendar/index.d.ts +3 -0
  124. package/dist/types/components/EventCalendar/useCalendarEdit.d.ts +40 -0
  125. package/dist/types/components/FieldWrapper/index.d.ts +1 -1
  126. package/dist/types/components/Fields/index.d.ts +1 -1
  127. package/dist/types/components/Icon/Icon.d.ts +36 -0
  128. package/dist/types/components/Icon/Icon.storyData.d.ts +6 -0
  129. package/dist/types/components/Icon/IconContext.d.ts +7 -0
  130. package/dist/types/components/Icon/icons.d.ts +223 -0
  131. package/dist/types/components/Icon/index.d.ts +7 -0
  132. package/dist/types/components/Icon/useIconDone.d.ts +5 -0
  133. package/dist/types/components/Image/ImageEditor.d.ts +21 -0
  134. package/dist/types/components/Image/ImagePicker.d.ts +10 -1
  135. package/dist/types/components/Image/imageRender.d.ts +33 -0
  136. package/dist/types/components/Image/index.d.ts +3 -1
  137. package/dist/types/components/Image/prepareImage.d.ts +4 -3
  138. package/dist/types/components/Link/Link.d.ts +22 -0
  139. package/dist/types/components/Link/index.d.ts +2 -0
  140. package/dist/types/components/NavList/NavList.d.ts +13 -0
  141. package/dist/types/components/NavList/index.d.ts +2 -0
  142. package/dist/types/components/PageProgress/PageProgress.d.ts +10 -0
  143. package/dist/types/components/PageProgress/index.d.ts +2 -0
  144. package/dist/types/components/Pagination/Pagination.d.ts +19 -0
  145. package/dist/types/components/Pagination/index.d.ts +2 -0
  146. package/dist/types/components/Popover/Popover.d.ts +2 -1
  147. package/dist/types/components/Popover/floatingPosition.d.ts +26 -2
  148. package/dist/types/components/ReorderList/ReorderGroup.d.ts +16 -0
  149. package/dist/types/components/ReorderList/ReorderList.d.ts +56 -0
  150. package/dist/types/components/ReorderList/crossListDrag.d.ts +61 -0
  151. package/dist/types/components/ReorderList/index.d.ts +5 -0
  152. package/dist/types/components/ReorderList/useReorderDrag.d.ts +28 -0
  153. package/dist/types/components/Scroll/ui.d.ts +1 -0
  154. package/dist/types/components/SlidingHighlight/index.d.ts +2 -0
  155. package/dist/types/components/SlidingHighlight/useSlidingHighlight.d.ts +20 -0
  156. package/dist/types/components/Suggest/SuggestionList.d.ts +1 -0
  157. package/dist/types/components/Tooltip/useTooltip.d.ts +4 -0
  158. package/dist/types/components/UIProvider/UILabelsContext.d.ts +120 -0
  159. package/dist/types/components/UIProvider/UIProvider.d.ts +2 -0
  160. package/dist/types/core/hooks/index.d.ts +2 -1
  161. package/dist/types/core/hooks/useMeasuredState.d.ts +1 -0
  162. package/dist/types/core/hooks/usePresence.d.ts +1 -0
  163. package/dist/types/core/icons/actions.icons.d.ts +37 -0
  164. package/dist/types/core/icons/commerce.icons.d.ts +16 -0
  165. package/dist/types/core/icons/communication.icons.d.ts +10 -0
  166. package/dist/types/core/icons/delivery.icons.d.ts +13 -0
  167. package/dist/types/core/icons/devices.icons.d.ts +16 -0
  168. package/dist/types/core/icons/files.icons.d.ts +13 -0
  169. package/dist/types/core/icons/general.icons.d.ts +24 -0
  170. package/dist/types/core/icons/index.d.ts +14 -0
  171. package/dist/types/core/icons/media.icons.d.ts +11 -0
  172. package/dist/types/core/icons/navigation.icons.d.ts +25 -0
  173. package/dist/types/core/icons/people.icons.d.ts +13 -0
  174. package/dist/types/core/icons/registry.d.ts +2 -0
  175. package/dist/types/core/icons/state.icons.d.ts +14 -0
  176. package/dist/types/core/icons/status.icons.d.ts +10 -0
  177. package/dist/types/core/icons/table.icons.d.ts +22 -0
  178. package/dist/types/core/icons/text.icons.d.ts +13 -0
  179. package/dist/types/core/logic/alert.logic.d.ts +3 -0
  180. package/dist/types/core/logic/cellRange.logic.d.ts +66 -0
  181. package/dist/types/core/logic/cellTouch.logic.d.ts +16 -0
  182. package/dist/types/core/logic/columnGroups.logic.d.ts +31 -0
  183. package/dist/types/core/logic/commandPalette.logic.d.ts +2 -0
  184. package/dist/types/core/logic/datePicker.logic.d.ts +12 -0
  185. package/dist/types/core/logic/dropdownSide.logic.d.ts +19 -0
  186. package/dist/types/core/logic/eventCalendar.logic.d.ts +225 -0
  187. package/dist/types/core/logic/fieldWrapper.logic.d.ts +6 -1
  188. package/dist/types/core/logic/fitColumns.logic.d.ts +7 -0
  189. package/dist/types/core/logic/icon.logic.d.ts +24 -0
  190. package/dist/types/core/logic/imageEditor.logic.d.ts +132 -0
  191. package/dist/types/core/logic/imageTransform.logic.d.ts +57 -0
  192. package/dist/types/core/logic/index.d.ts +25 -0
  193. package/dist/types/core/logic/inertProps.d.ts +3 -0
  194. package/dist/types/core/logic/pageProgress.logic.d.ts +3 -0
  195. package/dist/types/core/logic/pagination.logic.d.ts +7 -0
  196. package/dist/types/core/logic/periodPicker.logic.d.ts +86 -0
  197. package/dist/types/core/logic/pivot.logic.d.ts +100 -0
  198. package/dist/types/core/logic/reorder.logic.d.ts +49 -0
  199. package/dist/types/core/logic/rowActions.logic.d.ts +7 -0
  200. package/dist/types/core/logic/rowDrag.logic.d.ts +36 -0
  201. package/dist/types/core/logic/rowPinning.logic.d.ts +12 -0
  202. package/dist/types/core/logic/slidingHighlight.logic.d.ts +20 -0
  203. package/dist/types/core/logic/toolbarOverflow.logic.d.ts +21 -0
  204. package/dist/types/core/logic/treeData.logic.d.ts +44 -0
  205. package/dist/types/core/logic/treeDrag.logic.d.ts +63 -0
  206. package/dist/types/core/logic/tween.logic.d.ts +33 -0
  207. package/dist/types/core/logic/visualViewport.logic.d.ts +13 -0
  208. package/dist/types/core/types/chipinput.types.d.ts +3 -1
  209. package/dist/types/core/types/collapsible.types.d.ts +3 -0
  210. package/dist/types/core/types/datePicker.types.d.ts +7 -0
  211. package/dist/types/core/types/eventCalendar.types.d.ts +18 -0
  212. package/dist/types/core/types/field.types.d.ts +6 -3
  213. package/dist/types/core/types/fieldWrapper.types.d.ts +2 -0
  214. package/dist/types/core/types/fields.types.d.ts +6 -1
  215. package/dist/types/core/types/fileEngine.types.d.ts +6 -0
  216. package/dist/types/core/types/form.types.d.ts +1 -0
  217. package/dist/types/core/types/format.types.d.ts +2 -0
  218. package/dist/types/core/types/icon.types.d.ts +109 -0
  219. package/dist/types/core/types/index.d.ts +2 -0
  220. package/dist/types/core/types/input.types.d.ts +2 -0
  221. package/dist/types/core/types/navigation.types.d.ts +1 -0
  222. package/dist/types/core/types/select.types.d.ts +2 -6
  223. package/dist/types/core/types/suggest.types.d.ts +2 -0
  224. package/dist/types/index.d.ts +31 -6
  225. package/package.json +4 -4
  226. package/dist/ChartImageMenu-DDVNJNc6.js +0 -1499
  227. package/dist/ChartView-CW3m4Z_1.js +0 -1703
  228. package/dist/SummarySeeAll-BRHOMQRA.js +0 -101
  229. package/dist/assets/fileTask.worker--Q3rI3Bn.js +0 -1
  230. package/dist/columnValue-DwUqueZ6.js +0 -610
  231. package/dist/exportContext-BKFnNQ0q.js +0 -166
  232. package/dist/scrollArea-DbYFqbIH.js +0 -269
  233. package/dist/types/components/DataTable/ui-local/DragAndDropList/DragAndDropList.d.ts +0 -4
  234. package/dist/types/components/DataTable/ui-local/DragAndDropList/index.d.ts +0 -3
  235. package/dist/types/components/DataTable/ui-local/DragAndDropList/types.d.ts +0 -70
package/CHANGELOG.md CHANGED
@@ -1,5 +1,493 @@
1
1
  # @dcs-tech/ui
2
2
 
3
+ ## 0.11.0
4
+
5
+ ### Upgrading from 0.10
6
+
7
+ Things that can change an existing screen or build. Each is described in full below.
8
+
9
+ - **`react-icons` is no longer a dependency.** The library draws its own icons. An app that imports `react-icons` itself must list it in its own `package.json`.
10
+ - **DataTable toolbar:**
11
+ - With two or more layouts, the Columns / Card fields / List fields button moves into the layout menu (as its last item).
12
+ - The layout button shows its name ("▦ Table ▾") when there is room.
13
+ - Buttons that do not fit move into a "⋯ More" menu instead of wrapping onto a second line. App toolbar actions take an optional `priority`.
14
+ - **DataTable cards** use the library Card's look: a border with no resting shadow, and a ring (not a tint) when selected.
15
+ - **DataTable split view:**
16
+ - ↑ / ↓ open the row they land on.
17
+ - The open row's mark slides between rows.
18
+ - **DataTable Fit width:** columns share the width by their sizes. When even their minimum widths do not fit (phones, many columns) the table scrolls instead of squeezing them.
19
+ - **DataTable export templates** now include column group rows and tree levels, like the quick export. Turn them off per template with `headerGroups: false` / `treeLevel: false`.
20
+ - **Select:**
21
+ - The search box sits outside the list, and the scrolling list is the `listbox`.
22
+ - Tests that looked for the search box inside `[role="listbox"]` need updating.
23
+ - **Suggest rows** are now the `option` elements themselves.
24
+ - **Popovers** give focus back to what had it when they close.
25
+ - **Charts:**
26
+ - Series colour 1 is slightly lighter.
27
+ - Change and delta figures use the status text colours.
28
+ - Labels on series colour 8 are white.
29
+ - **Icons in existing components:**
30
+ - The Link external mark is now a box and arrow.
31
+ - The DatePicker calendar icon is now an outline.
32
+ - **`IconCategory`** has new values. Code that switches over every category needs the new cases.
33
+
34
+ ### Minor Changes
35
+
36
+ - 601b85a: More chart motion. `Treemap`, `CalendarHeatmap` and `NumberTrend` now move to new data too, with the same `animate` / `animationDuration` props (`ChartMotionProps`) and the same rules: tiles move to their new layout, a new tile grows from its centre and a removed one shrinks into it; a day's shade blends to its new level; the sparkline's points glide. A change mid-move retargets from where things are, nothing animates on mount, and under `prefers-reduced-motion` the new values show at once.
37
+
38
+ A category added to or removed from a `ColumnChart`, `LineChart` or `BarList` now opens or closes its place: the others slide to their new places, a new column, point or row grows in at its slot and a removed one shrinks out where it was. When the scale changes, the y axis' ticks and grid lines glide to it, and a tick that comes or goes fades in or out.
39
+
40
+ New on a DataTable view's summary: `summary.animate` (default `true`). Set it to `false` and the summary cards' charts show every change at once.
41
+
42
+ The y axis numbers of `ColumnChart` and `LineChart` are now placed from the bottom of one grid cell instead of being spread with flex, and the column, x-label and BarList gaps are now margins. The look is the same.
43
+
44
+ - a9279b6: Charts move to new data, on by default: columns and bars grow or shrink from their old values, lines and areas move their points, donut and pie slices sweep to their new angles, stacked bar segments, funnel bars, Progress and Gauge glide to the new share, and a value that comes or goes grows from or shrinks to 0. A change while a move is running retargets it from where it is, so live data (a table summary updating several times a second) never piles moves up. The first drawing is not animated, and under `prefers-reduced-motion` the new values show at once.
45
+
46
+ New props on `ColumnChart`, `LineChart`, `BarList`, `StackedBar`, `Donut`, `Funnel`, `Gauge`, `Progress`, `ChartView` and `Chart` (type `ChartMotionProps`): `animate` (default `true`) and `animationDuration` in ms (default `CHART_ANIMATION_MS`, 300 — `--duration-long`; easing `--ease-standard`). Treemap, CalendarHeatmap and NumberTrend redraw without motion as before.
47
+
48
+ - 0a634e3: DataTable: users choose how many row actions show as buttons. Column Settings ▸ Actions has **Max visible buttons** (1–5) beside Display mode, and, when the view offers the cards layout, the card's display mode and count too (also under Display in the cards layout). New optional display prefs `maxVisibleActions` and `maxVisibleActionsCard` (`DataTableDisplayPrefs`), saved with the other display settings and checked on load (a value outside 1–5 is dropped; an older saved document without them is unchanged). Until the user picks, a table row shows the view's `inlineActions` (default 2) and a card its one primary action, as before. Primary actions come first, a dangerous one is a button only when primary, and ⋮ still lists every action. The Actions tab is shown only when the view has row actions (`actions`); without them the ⋮ column always shows. The Actions hint now reads "How the row's action buttons show; the rest are in the ⋮ menu." New labels: `maxVisibleActions`, `maxVisibleActionsCard`, `maxVisibleActionsHint`.
49
+
50
+ Alignment fixes. Right-aligned (number) column headers put their icons before the label, so the label ends where the figures below end. Filter row controls share one style (regular weight, same height, a drawn select arrow); in the Fit column width the two inputs of a number or date range stack when they do not fit side by side, a date column keeps the width of one date input, and no control runs past its column. The Sort dialog's label, column select, direction button and delete button sit on one line at one height. The Column Settings tabs use the library's Tabs: one active style, a focus ring on keyboard focus only. The Sort and Column Settings dialogs and the sort column selects have accessible names.
51
+
52
+ - 4058a21: DataTable: a toolbar that runs out of room no longer crams or cuts off its buttons. It measures its own width (a ResizeObserver, once a frame; new rows measure nothing): first the layout button drops its name (the icon alone, still "Layout: …" to a screen reader), then the buttons with the lowest priority move into a "⋯ More" menu, as labelled items with their icons. Picking one does what the button does (Group and Export open their own menus). A tool that is on (sorted, grouped, selecting) has a dot in the menu, and ⋯ has a dot while it holds one. Search, Filters and the layout button never move; at a width where everything fits the toolbar is unchanged.
53
+
54
+ Priority, the longest-staying first: Sort, the filter row, Columns / fields, expand / collapse cards, Group, Pivot, Select rows, Export, then the app's buttons. New: `DataTableToolbarAction.priority` (lower stays longer; default after Export).
55
+
56
+ The layout menu now ends with the current layout's fields window — "Columns…", "Card fields…" or "List fields…" — in place of the separate toolbar button. A view with one layout (no layout button) keeps its own Columns button.
57
+
58
+ New labels: `toolbarMore`, `toolbarMoreOn`, `layoutFieldsItem`.
59
+
60
+ Popover (and every floating surface on `useFloatingLayer`): closing it with focus still inside now gives focus back to what had it before. A surface that animates out stays in the page for a moment, inert, so the focus used to drop onto the page body (Escape on the table's Export panel, for one).
61
+
62
+ - a2eed71: EventCalendar: resize from the start, and a capped all-day row in the week and day views.
63
+
64
+ - **Resize from the start.** In the week and day views every event now has a handle at each end: drag a block's top edge (or an all-day bar's left end) to change when it starts, while its end stays where it is. It works like the end resize: pointer and touch (press and hold first), snapped to the slot, at least a slot long (a bar at least its last day), never past the end, across midnight into the day before, Escape cancels, `canChange` can refuse it, and `onEventChange` reports the new `start` (a timed event with no `end` is given the end it was drawn with). With the keyboard, Shift+R on a focused event starts it, then arrows, Enter or Escape; each step is read out. The month view is unchanged (end only).
65
+ - **All-day overflow.** New prop `maxAllDayRows` (default 3): the lines the week / day view's all-day row holds, its "+N more" line included. A day with more all-day or multi-day events than fit shows "+N more", which lists that day's all-day events in a popover, as a crowded month day does. A multi-day bar is drawn on the days it fits and counted on every day it is hidden. `Infinity` grows the row to fit everything, as before.
66
+ - New labels in `UILabels.eventCalendar`: `editHintWithStart` (the week / day views' edit hint), `resizeFromStart` (read out when a keyboard start resize begins) and `dayAllDayEvents` (the all-day popover's name).
67
+ - A short time block's resize handles are now thinner, so there is room left to press and move it.
68
+
69
+ - 452e4fd: `EventCalendar` gets week and day views and opt-in moving and resizing of events. The month view
70
+ is unchanged and stays the default.
71
+
72
+ - **Views:** `view` / `defaultView` / `onViewChange` (`'month' | 'week' | 'day'`), with a switcher in
73
+ the header (`views` picks the choices; one view hides it). `date` / `defaultDate` / `onDateChange`
74
+ set the day a view is built around; `month` / `onMonthChange` keep working. Previous / next and
75
+ Today move by the view's span, and the title fits the view.
76
+ - **Time grid** (week, day): an all-day row on top (all-day events and events a day long or more),
77
+ then timed events placed by start and end, overlapping events side by side (cluster and lane
78
+ packing, a short event stretching into free lanes), events over midnight cut per day, and a line
79
+ at the current time. `slotMinutes` (default 30), `dayStartHour` / `dayEndHour` (default 0 / 24),
80
+ `scrollToHour` (default: an hour before now when today is shown, else 8:00). `onSlotClick(dateTime)`
81
+ reports an empty slot as `yyyy-mm-ddThh:mm`. Keyboard: one tab stop; arrows by slot and day, Up from
82
+ the first slot into the all-day row, Home / End, Ctrl + Home / End, Page Up / Down by the span.
83
+ - **Phone width:** under 600px of its own width the week view shows its chosen day (and the switcher
84
+ offers Month and Day), as seven 50px columns cannot hold an event.
85
+ - **Moving and resizing:** `editable` (on by default when `onEventChange` is given). Drag an event to
86
+ another day (month) or time (week, day); drag a block's bottom edge or a bar's right end to change
87
+ its end; drops snap to the slot; a preview shows where it lands; Escape cancels; dropping in the
88
+ all-day row makes an event all day and the reverse gives it an hour. Touch: long-press to pick an
89
+ event up, so a swipe still scrolls. Keyboard: M on a focused event moves it, R moves its end;
90
+ arrows step by slot and day (by day and week on day cells), Enter drops, Escape cancels, and a
91
+ live region reads each step. `onEventChange({ event, start, end, allDay })` fires once per drop;
92
+ the calendar shows the change only when `events` changes. `canChange(event, start, end, allDay)`
93
+ refuses a drop, which snaps back.
94
+ - `renderEvent`'s `info.place` can now also be `'time'` (a block in the time grid).
95
+ - New words in `labels.eventCalendar`: `previousWeek`, `nextWeek`, `previousDay`, `nextDay`, `view`,
96
+ `monthView`, `weekView`, `dayView`, `slot`, `editHint`, `moveStart`, `resizeStart`, `movePreview`,
97
+ `moved`, `resized`, `changeRefused`, `changeCancelled`.
98
+ - New types: `CalendarViewType`, `CalendarEventChange`.
99
+
100
+ - de0c36c: New `EventCalendar`: a month calendar that shows events in its day cells. Events are
101
+ `{ id, title, start, end?, allDay?, color? }` with `Date` or ISO-string dates (an all-day `end` is
102
+ the last day it covers). Multi-day events are bars that span their days and wrap at the week end;
103
+ timed events show their time; a crowded day shows "+N more", which lists the day in a popover.
104
+ Previous / next / today navigation, controlled (`month` + `onMonthChange`) or uncontrolled
105
+ (`defaultMonth`); `onEventClick`, `onDayClick`, `renderEvent`; colours by semantic name
106
+ (`'success'`, …) or any CSS colour. The grid is one tab stop with roving focus (arrows, Home / End,
107
+ Page Up / Down, Shift + Page Up / Down). The first day of the week defaults to the locale's. Below
108
+ 600px of its own width it shows a dot per event and lists the chosen day's events under the grid.
109
+ Words come from the new `labels.eventCalendar` group. New types: `EventCalendarProps`,
110
+ `EventCalendarRenderInfo`, `CalendarEvent`, `CalendarEventColor`, `CalendarDateInput`.
111
+ - 43940e0: Icons can now animate in two ways. With `draw`, the lines draw themselves. With `move`, the icon moves on its own: an arrow nudges, a gear turns, and an icon with no movement of its own gives a small shake. Every icon has a default. A symbol draws, and in an icon made of several parts only the part that carries the meaning draws: the plus on filter-add, the tick on filter-only, the "!" on warning. An icon keeps moving only where the movement is the meaning: chevrons, arrows, download, export, reset, sort, expand-all and collapse-all, drag-handle, sliders, settings, auto-fit, the "more" dots and the spinner. For example, the plus no longer turns; its two lines draw at the same time.
112
+
113
+ - New prop `motion?: 'auto' | 'draw' | 'move'` on `Icon` and every `IconXxx`. `'auto'` (the default) uses the icon's own style. `UIProvider icons={{ motion }}` and `IconProvider motion` set it for a whole tree, and an icon's own prop still wins. `animate` still decides when the animation plays.
114
+ - Icon data: `IconDefinition.motion` (`'draw' | 'move'`, default `'move'`) is the icon's default style. `IconPart.draw` (`true`, or a number of steps to wait) marks the parts that draw; if no part is marked, the whole icon draws. New types `IconMotionStyle` and `IconMotionChoice`.
115
+ - A filled drawing always moves. Reduced motion and `animate="off"` still mean no animation in either style.
116
+ - Some path data is reversed so it draws in a natural direction: the bookmark, the right brace, the right code chevron, a share spoke, the click rays, the group-by stem and the plus on bookmark-add. They look the same as before. The search lens and the ring on filter-exclude are now paths that start at the top.
117
+ - `animate="always"` is meant for galleries and empty states, not for an icon in every row of a live table.
118
+
119
+ - f6cf04a: Icons: new `IconOpenDetail` / `openDetailIcon` — a row list with a details panel and an arrow into it. The DataTable row menu's "Open" uses it instead of the eye (the eye keeps meaning show / hide and preview).
120
+ - 6c2c8c1: The library has its own icon set: 76 outline icons on a 24-unit grid with an even rounded stroke, each with a small hover motion in CSS only. Use one component per icon (`IconFilter`, `IconExport`, `IconCopyRow`, …) or the generic `<Icon icon={filterIcon} />`; the drawings are also exported as data (`filterIcon`, …) for other renderers, and `createIcon(definition, name)` makes a component for your own drawing. Props: `size` (`'xs'`–`'xl'` from the `--icon-size-*` tokens, or pixels; default `1em`), `tone` (`primary | success | warning | danger | info | muted`), `filled` (pin, star, bookmark, checkbox, filter), `animate` (`'hover' | 'always' | 'off'`) and `label` (an accessible name; without it the icon is hidden from screen readers). The motion plays when the icon, or the button, link, menu item or tab it sits in, is hovered or keyboard-focused; reduced motion turns it off, except for `IconSpinner`. Set app-wide defaults with `<UIProvider icons={{ animate, size }}>` or `<IconProvider>`. Each icon is a separate export, so an app ships only the icons it imports. New token: `--ease-constant` (a spinner's even speed).
121
+
122
+ The DataTable now draws every icon from this set instead of `react-icons`: same sizes and places, with new drawings for Export (a table with an arrow leaving it), the toolbar Filters funnel, the filter row, pivot, copy row, and the row menu's "Show only this value", "Also show this value" and "Hide this value" (a funnel with a "no" sign, replacing the ≠ sign). Unpin now shows a crossed-out pin. Labels and tooltips are unchanged.
123
+
124
+ - 399d10b: Icons: state changes, "done" feedback, press feedback and badges.
125
+
126
+ - **State changes.** An icon animates when its drawing changes after it is on screen: `filled` on (the fill grows in with a small swell; the checkbox tick draws itself) or off (the outline settles back), and a different `icon`. Never on mount, so a remounted virtual row stays still. CSS only, no timers or effects. New `IconSwap` for a pair: `<IconSwap on={playing} icon={IconPlay} onIcon={IconPause} />` — the new drawing pops in, and a drawing with an accent (eye-off's slash) draws just the accent. `animateChanges={false}` turns it off.
127
+ - **Done feedback.** `done` on any icon shows a tick in its place (it draws itself). `useIconDone()` returns `[done, markDone]`: `markDone('Copied')` shows the tick for 1.4s with one timer, and says the message through a polite live region.
128
+ - **Press.** The icon squashes a little while its button / link / menu item is pressed, on the press engine's timing; reduced motion keeps it still. `press={false}` turns it off.
129
+ - **Badge.** `badge` (`true` a dot, a number a count capped at `badgeMax`, default 99: "99+"), `badgeTone`, `badgeLabel`. A ring is cut out of the drawing so it reads on any surface. A labelled icon says its count; a decorative one leaves it to its button's name.
130
+ - **Defaults.** `UIProvider icons={{ animateChanges, press, badgeTone, badgeMax, doneDuration }}` (and `IconProvider`).
131
+ - `createIcon` components now carry their drawing as `.icon` (`IconComponent` gains a read-only `icon`).
132
+ - DataTable: the toolbar's Filters button shows the number of active filters on its icon (was a dot), and the Export icon turns into a tick for a moment after a download finishes, saying the result.
133
+
134
+ - 3844545: Icons get line weights with optical sizing, a duotone style, and a draw-in on mount.
135
+
136
+ - New prop `weight?: 'light' | 'regular' | 'bold'` on `Icon` and every `IconXxx`: a stroke of 1.5, 2 (the default) or 2.5 on the 24 grid. Optical sizing, in CSS: the stroke is a little heavier at small sizes (×1.125 at 12px, ×1.083 at 16px) and lighter at large ones (×0.917 at 32px, ×0.85 from 38px), exact at 24px. It follows `size`, or the font size at the default `1em`; nothing is measured. Note that every icon's line now changes slightly with its size; at 24px it is unchanged.
137
+ - New prop `variant?: 'outline' | 'duotone'`. Duotone draws the outline over a soft fill of a second colour: the inside of a file, the body of a lock, the funnel. 59 of the 102 icons have a fill; lines, arrows and open shapes look the same as their outline. The fill is `--icon-duotone-color` (new token, default `currentColor`) at `--icon-duotone-opacity` (new token, 0.16 light / 0.22 dark); `duotoneTone` picks a palette colour. `filled` still wins.
138
+ - New prop `appear?: boolean`: the icon draws itself once as it mounts, for empty states and success screens. It plays on every mount, so do not use it in tables or virtual lists. Reduced motion shows the icon at once.
139
+ - `UIProvider icons={{ weight, variant, duotoneTone }}` and `IconProvider` set the defaults; an icon's own prop wins.
140
+ - Icon data: `IconShape.duo` (`true` tints a stroked shape's inside; `'only'` is a closed, tint-only shape drawn only in duotone). New types `IconWeight` and `IconVariant`.
141
+
142
+ - cbebca5: 120 new icons, so apps can move off `react-icons` and `lucide-react` (222 in all). Like the rest of the set, each icon draws or moves by default, has a duotone fill where it has an inside, and has the three weights with optical sizing. Each is a separate export (`IconMail` and `mailIcon`), so an app ships only the icons it imports.
143
+
144
+ - **Text and lists** (new category `text`): bold, italic, underline, strikethrough, font-size, text, eraser, hash, list-numbered, list-check, list-plus, list-minus.
145
+ - **People and account** (`people`): user-add, user-check, user-search, user-settings, user-shield, account-circle, id-card, logout, key, shield, shield-check, badge-check.
146
+ - **Communication** (`communication`): mail, phone, phone-call, message, comment, send, at-sign, bell, inbox.
147
+ - **Money and commerce** (`commerce`): cart, shopping-bag, wallet, coins, banknote, receipt, invoice, calculator, percent, tag, gift, point-of-sale, bank, rupee, dollar.
148
+ - **Delivery and places** (`delivery`): truck, package, boxes, archive, warehouse, building, location-pin, map, route, barcode, qr-code, scan.
149
+ - **Devices and system** (`devices`): monitor, smartphone, tablet, cloud, cloud-off, cloud-upload, cloud-download, wifi-off, power, moon, sun, palette, dashboard, layers, grid.
150
+ - **Added to existing categories**: arrow-right, arrow-up-right, panel-left, panel-right (navigation); undo, redo, repeat, link, unlink, scissors, minus, plus-circle, minus-circle, maximize, minimize, wrench (actions); heart (with a filled drawing), bookmark-check, circle (state); ban, cancel, check-double (status); image, crop (media); file-plus, file-check, file-upload, file-download (files); history, clock-plus, briefcase, book, clipboard, clipboard-list, clipboard-check, hierarchy, branch, shapes, scale, life-buoy, award, target, bar-chart, sparkles, handshake (general).
151
+
152
+ `IconCategory` has six new values: `text`, `people`, `communication`, `commerce`, `delivery`, `devices`. Code that switches over every category needs the new cases.
153
+
154
+ An icon mapping guide in the library's repository lists common `react-icons` / `lucide-react` names and the library icon to use instead. Brand marks and industry-specific objects stay with the app's own icon set.
155
+
156
+ - 2b5afc7: The whole library now draws its own icons, and `react-icons` is no longer a dependency of `@dcs-tech/ui`.
157
+
158
+ **Breaking for apps that used `react-icons` without installing it.** It used to be installed alongside `@dcs-tech/ui` as one of its dependencies. An app that imports `react-icons` itself but does not list it in its own `package.json` must now add it (`npm install react-icons`), or switch to the library icons below.
159
+
160
+ 26 new icons, each as a component (`IconHome`) and as data (`homeIcon`), with the same draw / move styles as the rest of the set:
161
+
162
+ - Navigation: `home`, `menu`, `swap-horizontal`
163
+ - Actions: `upload`, `refresh` (also "sync"), `align-left`, `align-center`, `align-right`
164
+ - State: `lock`, `unlock`
165
+ - Status: `info`, `help`
166
+ - Media (new category): `image-add`, `zoom-in`, `zoom-out`, `rotate-left`, `rotate-right`, `flip`, `ruler`, `hand`
167
+ - General (new category, people, time and places): `user`, `users`, `calendar`, `clock`, `store`, `card`
168
+
169
+ `IconCategory` gains `'media'` and `'general'`.
170
+
171
+ These components now show library icons in place of their `react-icons` or hand-drawn glyphs. Their labels, tooltips and sizes stay the same, and an icon you pass in yourself still wins:
172
+
173
+ - Pagination, ScrollStrip, ImageViewer and EventCalendar arrows
174
+ - the Input password toggle (eye / eye-off)
175
+ - the ReorderList and Select drag handles, and the Select lock and search
176
+ - ImagePicker and ImageEditor tools
177
+ - Alert and Toast tone icons and dismiss buttons
178
+ - the Dialog close button
179
+ - the Tooltip help icon
180
+ - the Sidebar, Breadcrumbs and Collapsible chevrons, and the Breadcrumbs home
181
+ - the Link external mark
182
+ - the DatePicker and PeriodPicker calendar and clock
183
+ - the CommandPalette search
184
+ - the EditableTable row actions
185
+ - the chart image menu
186
+
187
+ Each one now plays its icon's motion on hover. The drawings follow the set's 24-unit grid, so a few look slightly different:
188
+
189
+ - The Link external mark is now the box-and-arrow "open external" icon.
190
+ - The DatePicker calendar is now an outline instead of a filled shape.
191
+
192
+ - 0a97367: Value and ratio cards can take only the height their content needs: `height: 'content'`. Beside a taller card they stretch to its row's height, so a row stays aligned; drawn as a chart they keep the fixed height. The default stays `'fixed'`.
193
+ - 0a97367: Funnel steps can come and go: `showWhen` (the same context as a card's, decided before counting, so a hidden step is not asked of the data source) and `hideAtZero` (decided after counting, so that step is asked). The change between steps is computed from the steps shown.
194
+ - 0a97367: Breakdown and trend cards can add a figure up per bucket (`sum: { id, label, value?, format? }`) and take in only some rows (`where: { id, test?, condition? }`); counting every row stays the default. The data source's request carries `sum` and `where`, and its answer's `count` then holds the sum. Tooltips, totals, See all, the picture and the export use the sum's name and format; a chart draws a negative sum as nothing and leaves it out of the shares. With `where.condition`, a click on a value or period also filters the table by that condition, so the table shows the rows the card counted; without it the click filters by the value or period alone.
195
+ - 0a97367: Trend cards can show given dates: `range: { from, to }`, or a function of the same context as `showWhen`. Ending today stays the default. Both ends win over `count`; only `to` keeps `count` and the range menu; an invalid range counts as none; a range past the period's maximum keeps the latest periods. The data source's request carries `from` and `to`.
196
+ - 0a97367: A value card can list several labelled figures: `figures: [{ label, value: { id, compute }, text? }]`. They sit under the main `value`, which stays the card's headline, and over `sub`. Server mode asks for them in `request.values`; the export lists each as "Card · Label" and the card's picture lists them too.
197
+ - 13e92a6: DataTable cell flash: each flash now runs its own time, so a later change no longer cuts one short, and another change in the same cell restarts it. New props: `flash` and `flashDuration` on a view or column, `flashStyle` on a view, `flashDirection` on a column. Colours may be any CSS colour as well as the named ones, which are now tokens (`--flash-green` and the rest), so they follow the theme; other changes are yellow by default. A blank filled or emptied now counts as a change rather than a rise or fall.
198
+ - 9ff4d68: DataTable cell selection by touch (`view.cellSelection`), as spreadsheets on phones do it:
199
+ - **Start:** a long-press (500 ms) on a cell selects it; moving on without lifting drags out a range. A swipe scrolls the rows and the page as always: nothing is held until the long-press fires.
200
+ - **Resize:** a range made by touch shows a handle at its top-left and bottom-right corners (a small dot with a large touch target); dragging one moves that corner while the opposite one stays. Near an edge the rows (or the page) scroll, with pinned columns and virtual scrolling.
201
+ - **Tap:** while a touch range shows, a tap on a cell moves the range there (the row does not open); a tap outside the rows clears it.
202
+ - **Touch bar:** the range's size with Copy (the same tab-separated copy as Ctrl/Cmd+C), the row menu of the row the range ends on, and clear. The size is announced as for the mouse.
203
+ - **With the row menu:** with cell selection on, the long-press on a data cell starts a range, so the row menu opens from the touch bar instead (with `rowMenu.longPress: 'open'`, a tap opens the row as before once no touch range shows); a long-press elsewhere in the row (and every long-press with cell selection off) works as before. The row-drag handle keeps its own long-press. The pivot view gets the same touch gestures (Copy and clear).
204
+ - Mouse and keyboard ranges are unchanged; a mouse press or a key ends the touch handles and bar.
205
+ - Labels: `cellTouchBar`, `cellTouchSize`, `cellTouchCopy`, `cellTouchMenu`, `cellTouchClear`.
206
+ - cbaa859: DataTable cell selection (ranges of cells, as in a spreadsheet):
207
+ - **`cellSelection` on a view** (`true` or `DataTableCellSelectionConfig`; default off, table layout with `keyboard` on). A click selects a cell, a drag a rectangle (the rows area scrolls when the pointer nears an edge, virtual scrolling, pinned columns and header groups included); Shift+click and Shift+arrows extend it (Ctrl/Cmd+Shift+arrows to the last row / column, Shift+Home / End / PageUp / PageDown too), Ctrl/Cmd+click or drag adds another range (`multiRange: false` keeps one), Ctrl/Cmd+A selects every cell, Esc clears. A plain arrow takes the range to the cell it lands on.
208
+ - **Copy:** Ctrl/Cmd+C copies the ranges as tab-separated text, using each cell's text as the row menu copies it (`format` / `exportValue`); `copyHeaders: true` puts the column headers first. Several ranges copy as the rows and columns they touch, blank where no range is.
209
+ - **Paste:** with `onCellsPaste({ cells })`, Ctrl/Cmd+V hands the pasted text to the app cell by cell (`rowId`, `row`, `columnKey`, `value`): one value fills the range, a block goes from its top-left cell. The table changes no value itself.
210
+ - **The range bar** under the rows shows count, sum, average, min and max of the selected cells (numbers only for the last four), as AG Grid's status bar does; `statusBar` picks and orders them, `false` hides the bar.
211
+ - **API and callback:** `api.getCellRanges()`, `api.clearCellRanges()` and `onCellRangesChange(ranges)` (once per drag, when it ends). A range is kept by row id and column key: it stays on its rows while they update live, and a new sort, filter, search, page or view clears it. Pinned data rows can be in a range (in their order: top, rows, bottom); the app's own `pinnedRows` and group lines cannot.
212
+ - **Keys with row selection:** with cell selection on, Shift+arrows extend the cells instead of ticking rows; Shift+Space ticks the rows the ranges cover; Space, the checkboxes, row clicks (a Shift / Ctrl click only selects cells), the row menu, row pinning and the change flash work as before. The "?" list shows the cell keys.
213
+ - **Accessibility:** cells in a range carry `aria-selected`; the range's size is announced politely ("6 cells selected, 3 rows by 2 columns"). Labels: `kbCell*`, `cellRange*`, `cellsCopied`, `cellsPasted`.
214
+ - **Speed:** the ranges are painted on the cells on screen through data attributes, so a drag renders no row; with cell selection off nothing runs.
215
+ - 13e92a6: DataTable: `dataOnly` on a column makes it a field the table can sort and filter by without ever drawing it. It is a choice in the Sort and Filter windows and is left out of the Columns window, cards, row detail, files and search; a saved "show all" cannot bring it on screen.
216
+ - 1a78570: DataTable export templates now carry the view's look, as the quick export does. A template's file has the view's column group rows over its header (Excel and PDF, for the template's columns whose keys are in the view's `columnGroups`) and, with tree data, each row's level (a Level column, or the first column indented, per `treeData.exportLevel`) with totals of the rows without children (`treeData.totals: 'leaves'`). New template options switch each part: `headerGroups` (default `true`), `csvGroupRows` (default `false`), `treeLevel` (default `true`; only rows `transform` passes through unchanged get a level) and `pinnedRows` (default `false`: the table's own pinned rows, each side run through `transform`). Existing templates on views with column groups or tree data now get those group rows and levels. Before, their totals counted parent rows as well as their children, which was a bug. Set `headerGroups: false` / `treeLevel: false` to keep the old file.
217
+
218
+ Tree data in server mode: files now have every level. The export asks `dataSource.loadAllRows` for the whole tree in its one request (new `ctx.tree`, type `DataTableExportTreeRequest`: `withChildren`, `rowKey`, `shape` 'nested' | 'flat', `parentField`). The source answers with `tree: true` on the result (new field on `DataTableAllRowsResult`). The table then orders the rows under their parents and writes the levels. A source that ignores `ctx.tree` while child rows load through `dataSource.children` gets a file with the rows it sent plus the child rows already opened on screen, and the file's context line and the export's message say so. New metadata field `notes` on `DataTableExportMetadata` (written as "Note: …" in every format), and new labels `exportNoteLabel` and `exportTreePartial`.
219
+
220
+ In the quick export, an app pinned row in a tree view now has a blank Level instead of 1, because it is not a row of the tree.
221
+
222
+ - 5bcd004: DataTable column header groups and pinned rows:
223
+ - **`columnGroups` on a view:** headers over several columns ("Q1" over Jan / Feb / Mar), nested for more header rows. Groups name the view's column keys, so `columns` stay a flat list and saved order, visibility, widths and pins keep working. Groups work with pinned columns (a group splits at the pinned edge), horizontal and virtual scrolling (the header stays sticky), the filter row, the column menu, density and font size. A group whose columns are all hidden goes. When a reorder splits a group's columns, the group shows one header per run; `keepTogether: true` keeps them side by side instead. Dragging a group's edge resizes all its columns. The Columns window shows each column's groups. Excel and PDF files write the group rows above the column headers (merged / spanned); CSV writes them only with `export.quick.csvGroupRows`. Cards and the split list ignore groups.
224
+ - **`pinnedRows` on DataTable:** the app's own rows (a grand total, a target line) stay above / below the rows while they scroll. They are drawn by the view's columns but are not data rows: never searched, filtered, sorted, paged, selected, opened or counted in the totals row. Files carry them above / below the data (CSV, Excel, PDF, HTML; `export.quick.pinnedRows: false` leaves them out).
225
+ - **`rowPinning` on a view:** the row menu offers Pin to top / Pin to bottom / Unpin, and **`api.pinRow(id, 'top' | 'bottom' | null, row?)`** / **`api.getPinnedRows()`** pin from the app (needs `rowKey`). A pinned data row shows whatever the search, filter, sort or page, keeps updating live (transactions, flash), can be selected and opened, and is read in order by the keyboard and screen readers (top, rows, bottom). By default it leaves its place among the rows, as AG Grid does; `rowPinning: { keepInPlace: true }` shows it in both places. Pins are saved with the view's preferences (`pinnedRows`). Server mode keeps a pinned row's object, so it stays pinned on other pages. Table layout only.
226
+ - **File engine:** `XlsxSheetSpec.headerGroups` writes merged header rows over the header row.
227
+ - 92867f7: DataTable: pivot mode. Opt-in per view (`pivot: true` or a `DataTablePivotConfig`); a view without it is unchanged.
228
+
229
+ **The result** takes the place of the rows: a line per value of the row fields (pinned at the left), with a subtotal line after the lines of each value of an outer field; a column per value of the column fields, under header groups ("2026 › Q1" over "Sum of Amount"), keys in their options' order (else natural order), blanks last; total columns (each line's total, and each outer column value's); the grand-total line pinned at the bottom. Every total is worked out from the rows (an average is never an average of averages). The search and the filter choose the rows that are summed up; the summary strips stay the rows'. It sorts by any of its columns (header, Sort window, status row chips) — with subtotal lines, within each level, the subtotal staying after its lines; blanks last. Figures take the value column's number format (a count is a whole number, an average has decimals) and flash when they change. More result columns than `maxColumns` (default 200): the first are shown and a note says how many of how many. A keyboard grid; the view's cell selection works on it.
230
+
231
+ **Aggregations**: `sum`, `count`, `avg`, `min`, `max`, `first`, `last`, custom ones by name (`pivot.aggregations: { median: { label, fn } }`) or a function on a configured value. Columns say what they offer: `pivotable` (row / column field; client default: the groupable columns) and `aggregatable` (true, or a list of aggregations; client default: number columns). Server mode offers only the columns that say so.
232
+
233
+ **The Pivot window** (toolbar button): pivot mode on / off, Rows / Columns / Values / Fields — fields dragged between them (mouse, touch, or a grip with the keys), or put in with their buttons and taken out with ×; each value's aggregation; the totals; Reset, Cancel, Apply. Putting a field in turns pivot mode on. `pivot.panel: false` leaves it out.
234
+
235
+ **State**: the user's pivot is saved with the view's preferences (repaired against the config when read: fields and aggregations no longer offered are dropped). Or controlled: DataTable `pivot` + `onPivotChange(state, { viewId })`. `api.getPivot()` / `api.setPivot(state | null)`.
236
+
237
+ **Files**: the quick export in pivot mode is the result — Excel, PDF and CSV with the header groups over it (CSV too, unless `csvGroupRows: false`), each header saying where it sits ("2026 › Q1 › Sum of Amount"), the grand-total line under it. Templates stay the rows'.
238
+
239
+ **Live changes** (client mode): the pivot is worked out again at most every 250 ms while only the rows change; from 20,000 rows in parts between frames. 100,000 rows sum up in about 45 ms (two row fields × two column fields × three values); with ten updates a second a 100k-row table stays at about 60 frames a second, pivot on or off.
240
+
241
+ **Server mode**: `dataSource.pivot(query, { request, signal })` returns `{ cells }` — the row path's and column path's values (shorter = a total) with one figure per value (see `DataTablePivotRequest`, `DataTablePivotCell`). No page of rows is asked while pivot mode is on.
242
+
243
+ New types: `DataTablePivotConfig`, `DataTablePivotState`, `DataTablePivotValue`, `DataTablePivotTotals`, `DataTablePivotAggregate`, `DataTablePivotAggFn`, `DataTablePivotAggregation`, `DataTablePivotRequest`, `DataTablePivotResult`, `DataTablePivotCell`, `DataTablePivotKey`. New column props `pivotable`, `aggregatable`; new DataTable props `pivot`, `onPivotChange`; new `DataTableApi` methods `getPivot`, `setPivot`; new data-source method `pivot`; new labels `pivot*`.
244
+
245
+ - c5ded76: DataTable API around added and removed rows:
246
+ - **`applyTransaction` returns what it did:** `{ added, updated, removed }` by row key, or null when nothing changed or updates are paused. `applyTransactionAsync` takes the same options.
247
+ - **`keepPlace`:** the user's own change on a sorted table keeps its rows where they are, with an amber edge, until "Sort now" or any new sort. Use it as `applyTransaction(tx, { keepPlace: true })`. Changes from elsewhere still go to their sorted place.
248
+ - **`scrollToRow(id, { flash })`:** brings a row into view, going to its page in client mode, and pulses it.
249
+ - **`getRowPage(id)`:** says which page a row is on.
250
+ - **`flashRows(ids)`:** pulses rows that are on screen.
251
+ - **`pauseUpdates()` / `resumeUpdates()`:** pausing holds live changes and counts them; Resume applies them in order. While transactions keep coming, a Pause control shows at the bottom of the rows (`rowChanges.pauseControl`). Changes also wait while a row menu is open.
252
+ - 90cc8e9: DataTable: added and removed rows are easy to place.
253
+ - **Added row:** it fades in, with a tint and a bar at its edge that last 2s.
254
+ - **Removed row:** it turns red, then fades and closes up over 0.7s.
255
+ - **Where it works:** in every layout, with virtual scrolling and grouping too, which had no row motion before.
256
+ - **Out of sight:** rows added or removed above, below, or on another page show a notice ("3 new rows above"). Choosing it brings the row into view and pulses it.
257
+ - **Steady view:** under virtual scrolling, rows added above no longer push the rows in view.
258
+ - **Paging:** a row that only moved onto or off the page is not marked as added or removed.
259
+ - **Bulk changes:** more rows than the bulk limit at once are told, not marked one by one.
260
+ - **Screen readers:** they hear one line per burst ("3 rows added, 1 row removed").
261
+ - **Reduced motion:** the colour and bar stay; nothing moves.
262
+ - **Tuning:** set colours, timings, the bulk limit, the notice and the announcement with `view.rowChanges`.
263
+ - **Visual change:** the table's outer box clips with `overflow: clip` instead of `hidden`, so the notice can stick to the page while it scrolls.
264
+ - 0359e5d: DataTable: rows moved by hand on the cards, in the split list and within tree data. A view without `rowDrag` is unchanged.
265
+
266
+ **Cards and split** (`rowDrag` in the `cards` and `split` layouts). The handle sits at the start of a card's foot, or at the start of a split list item. Everything from the table works the same way: mouse drag, long-press on touch, the keys (Space / Enter on the handle, Alt+↑ / Alt+↓ on a card or item; on the cards ← / → also step), several selected rows moved together, auto-scroll near the edges and virtual scrolling, the same reasons the handles are off, and managed / unmanaged / server mode. On the cards a bar between two cards shows where the row will land.
267
+
268
+ **Tree data** (`rowDrag` with `treeData`, table layout; this used to be off). A row goes before or after another at the level the pointer picks: move it right to go one level in, left to go out. Dropped on the middle of a row, it goes into that row, which is highlighted, and lands last among its children. A closed row held over for a moment opens. A row never goes into its own rows, and a parent moves with the rows below it. The keys: while a row is held, ↑ / ↓ go between rows and ← / → change the level. Alt+→ / Alt+← on a row move it one level in (under the row above) or out (after its parent). Screen readers hear where the row went, for example "Task moved into Design, position 2 of 5". Managed client mode: flat rows (`parentField`) get the new parent key and their new place in the list. Nested rows (`getChildren`) keep the moved tree until the rows change. A new parent opens to show the moved row. Server mode only reports the move, and the app keeps it.
269
+
270
+ `DataTableRowOrderChange` gets only new optional fields, which are set for tree data: `parent`, `parentKey`, `index`, `previousParent`, `previousParentKey`, `previousIndex`. With tree data, `rows` holds every row in tree order. For flat rows this is the list in its new order with the new parent keys, so it can be given back as `data`. `before` is the next sibling under the new parent. In server mode, `index` counts only the child rows already loaded; `before: null` means last.
271
+
272
+ New labels: `rowDragTreeIn`, `rowDragTreeTop`, `rowDragTreeInto`, `rowDragTreeToTop`, `rowDragTreePicked`, `rowDragTreePickedMany`, `rowDragTreeDropped`, `rowDragTreeDroppedMany`, `rowDragTreeNoIndent`, `rowDragTreeNoOutdent`.
273
+
274
+ A held row's tint is now mixed into the row surface (opaque), so pinned cells no longer show the cells scrolling under them.
275
+
276
+ - f80276c: DataTable: rows put in order by hand, and tree data. Both are opt-in per view; a view without them is unchanged.
277
+
278
+ **`rowDrag`** (true or `DataTableRowDragConfig`; needs `rowKey`; table layout). A handle at the start of each row: drag it with the mouse, long-press it on a touch screen (a swipe over it still scrolls), or use the keys — Space / Enter on the handle, or Alt+↑ / Alt+↓ on a row, picks the row up, ↑ / ↓ / Home / End move it, Enter drops, Esc puts it back, each step told to screen readers. A line shows where the row will land and the rows area scrolls near its edges (virtual scrolling too). A selected row takes the other selected rows on the page along (`multiple: false` to stop that); `canDrag` leaves rows out; pinned rows stay put. While the rows are sorted, searched, filtered or grouped the handles are off and say why (tooltip and description). Live changes wait while a row is held. New prop `onRowOrderChange({ row, moved, from, to, rows, before, managed, viewId })`. Client mode is managed by default: the table keeps the new order, as it keeps a transaction, until a new `data` replaces the rows; `managed: false` only reports the move and the app gives `data` in the new order. Server mode only reports (indexes and `rows` are the page's).
279
+
280
+ **`treeData`** (`DataTableTreeDataConfig`; needs `rowKey`; table layout; grouping is off with it). Child rows from `getChildren` (nested) or `parentField` (flat, so transactions can add, move and remove any row). A chevron opens a row, → / ← on its first column open, close or go to the parent, Expand all / Collapse all in the status row, `defaultExpanded` (true, false or a number of levels); the rows area is a tree grid (`aria-level`, `aria-expanded`). The search and the filter keep the rows above a match, opened to show it, and a matching parent keeps its children (`filterMode: 'matches'` shows only the matching rows, flat). Sorting sorts each level on its own. The totals row adds up the rows without children (`totals: 'all'` for every row). Ticking a parent ticks the rows below it (`selectChildren: false` to stop that). Files have every row in tree order with a Level column first (`exportLevel: 'indent'` indents the first column instead), and their totals add up the rows without children. Server mode: `dataSource.children(parent, { query, signal })` loads a row's children when it is first opened (`treeData.hasChildren` says which rows have some).
281
+
282
+ New types: `DataTableRowDragConfig`, `DataTableRowOrderChange`, `DataTableTreeDataConfig`. New labels: `rowDrag*` and `tree*`.
283
+
284
+ - 13e92a6: DataTable: `api.applyTransaction({ add, update, remove })` changes single rows without a new `data` or a request, with their animations, in client and server mode; `api.applyTransactionAsync` collects a stream of updates into one render. In server mode it changes the page on screen and the total until the next fetch.
285
+
286
+ ### Patch Changes
287
+
288
+ - 8ed19cf: Accessibility fixes found by the axe gate. The markup is fixed; no rule is turned off.
289
+
290
+ - `DropdownMenu`: the `menu` element (the popover's surface, or the wrapper inside a sheet, which still carries your `className`) now holds focus and handles the keys. The focusable wrapper that sat between the menu and its items is gone. Keyboard behaviour is unchanged. While a pane shows, the popover is a named `dialog` (in a sheet, a `group`). `Popover` takes an optional `onKeyDown`.
291
+ - `DataTable` cards and split list: no `aria-selected` on a `listitem` while selecting. The row's checkbox carries the ticked state.
292
+ - `DataTable` toolbar and bulk buttons: the label uses the colour's `-text` role (`--accent-primary-text`, `--success-text` and the others), so a primary button's text passes 4.5:1 on its tint.
293
+ - `Sidebar` collapsed rail: the row label is visually hidden rather than removed, so every rail link keeps its name.
294
+ - `ChipInput` with `tags`: the chips and the input form one `group`, named as the field, with `aria-disabled` when the field is disabled.
295
+ - `Collapsible` with `color` primary or secondary: when expanded, the subtitle on the tinted header uses the secondary text colour, which passes 4.5:1.
296
+ - Charts: a read-only `Funnel` is built from `<div>`s, because an `<ol>` may not take `role="img"`. A funnel's change and a `NumberTrend` delta use the status `-text` colours. `inkOn` measures against the real inks. Light series 1 is `#2c7cdc`, so that every hand-picked colour carries its label at 4.5:1.
297
+
298
+ - 24bb113: DataTable cards now look and press like the library's clickable Card. Each card uses Card's own styles: the same surface, border, radius, hover shadow and lift, focus ring and selected ring. A press shows Card's wave from where the pointer went down, with no press-down. Split list items get the same wave and keep their own hover colour. Table rows are unchanged and keep the tint. A press on a control inside a card or item (its action buttons, ⋮, the expand chevron, the checkbox, the drag handle) still shows only that control's own press. It does not press, wave or open the card, and on a touch screen the card no longer tints while that control is held. Reduced motion: no lift, and the wave fades in place without growing. Card: its hover shadow and lift now apply only on devices that really hover, so a tap on a touch screen no longer leaves a card lifted. Roles and ARIA attributes are unchanged.
299
+ - f0dba21: DataTable cards and split layouts stay fast with many rows and live updates. A card's or list item's content (title, subtitle, badge, fields, avatar) is now built only for the cards drawn (the virtual window), and again only for a row that changed; before, every update rebuilt it for every row. After a transaction only the changed rows' cards are redrawn, the virtual window is not measured again, and the look-up of a row by its id is updated for the changed rows instead of rebuilt. With 100,000 rows, virtual scrolling and 10 updates a second, cards and split now run at 60 FPS, the same as the table (about 5 FPS before). Paged cards and split are unchanged or a little faster. Search, sort, filter, grouping, selection, the open row, row drag, keyboard navigation and card expand work as before.
300
+ - 5b02a0b: DataTable Fit width: a column's resize handle sits inside its header cell's edge, so the whole handle can be grabbed (half of it was clipped by the cell's own scroll). The `DataTableColumnWidth` docs now say what Fit does: a long value stays on one line and scrolls inside its cell.
301
+ - f2d925e: DataTable Fit column width: the columns now share the width by their sizes (a short status or number column is narrower than a long name), instead of all coming out the same width. Each column's width is worked out in px from the table's width and set on its `<col>`, and again when the table is resized (no re-render of the rows). A column's `minWidth` is kept (when the columns' least widths do not fit, the table scrolls); a column the user resized keeps its width and the others share the rest. While the filter row shows, a date column is at least wide enough for its date input (a least width now, no longer a fixed one). Pinned columns' offsets follow a resize in Fit.
302
+ - ddd2b72: DataTable: the layout button names the current layout — its icon, its name and a ▾ (for example "▦ Table ▾") — so it reads as a layout picker before it is pressed.
303
+ - 64025c4: DataTable live updates stay smooth on large client-mode tables. A transaction (`applyTransaction`, `applyTransactionAsync`) now finds its rows by key and records what it changed, and every step after it works on the changed rows only: the row models, the search and filters, the sort, the lines shown, the totals row, the cell flashes, the row marks and the notices of rows added elsewhere. With 100,000 rows, virtual scrolling and summary cards, ten updates a second now run at about 60 frames a second where they used to drop to about 20–28. On that many rows, the summary cards' recount during live updates runs card by card between frames, and all the figures then change at once. Rows, order, figures and every other result are the same as before.
304
+ - 131f7a6: DataTable windows (Columns, Sort, Filters, Export settings, Manage …) fit a phone screen: their desktop minimum width (400–560px) no longer pushes them past the screen's edge, where the Save button and the close × were cut off.
305
+ - a85b42b: DataTable display fixes. The row-change notices and the live-updates Pause control no longer cover rows pinned to the bottom (`pinnedRows` or `view.rowPinning`): they sit just above them, and the "new rows above" notice sits under rows pinned to the top, in paged, scrolling and virtual tables, with or without the totals row. With `view.columnGroups`, a wide group's name now stays in view while its columns scroll sideways, just clear of the columns pinned left or right, at every level of nested groups (CSS `position: sticky` only, nothing re-renders on scroll). Pivot headers use the same rule.
306
+ - addf28a: DataTable split list and cards: the row checkbox no longer takes the table's checkbox-column styles (a 44px cell with extra left padding, a sticky solid background), so it sits at the row's normal padding without a grey box on a selected row.
307
+ - 4bd333a: Select and Suggest lists: the side a list opens on is decided once, when it opens, and kept until it closes. A field near the bottom of the window with more of the page (or of its dialog body or scrolling panel) below now opens BELOW, and that container scrolls smoothly by just enough to show the list (instantly with reduced motion). Only a field at the very end, where nothing more can scroll into view, opens above. While open, scrolling and resizing only move the list with its field and cap its height; the list no longer jumps between below and above, and typing in its search box does not flip it. Scrolling inside a list stops at its end instead of scrolling the page or dialog under it (`overscroll-behavior: contain`). `position="top"` prefers above with the same rule mirrored; `position={{ flip: false }}` still never flips and never scrolls, it only caps the height.
308
+ - 65ac936: EventCalendar: what assistive technology reads now starts with the text on screen, so voice control users can say what they see (WCAG 2.5.3, label in name).
309
+ - **Events:** an event's name is its time and title as shown, then the rest of when it is ("9:30 Sync, until 10:00").
310
+ - **Day cells and time slots:** a cell says its date first ("Tuesday, 3 November 2026, 2 events"), then the events in it.
311
+ - **"+N more":** reads "+3 more, Wednesday, 4 November 2026".
312
+ - **Custom rendering:** with `renderEvent`, the app's own text comes first.
313
+ - 1778509: DataTable, Charts and ChipInput use the font size and icon size tokens everywhere instead of fixed sizes, so `--ui-scale` and theme changes reach every text and icon.
314
+ - **Default table text:** unchanged at 13px.
315
+ - **Slightly larger:** labels and badges that were 9–10px are now 11px (`--font-size-xxs`), and the phone search box is 16px (from 15px), which also stops iOS zooming in on it.
316
+ - **Fluid on phones:** the summary card value and the chart number follow the heading tokens. They're the same size as before on desktop and a little smaller on phones.
317
+ - b2db3e9: Icons: `layout-table` is drawn as a grid (header row, a row line and a column line), so the DataTable's Table layout reads as a table, not a list.
318
+ - 09142fd: Select and Suggest lists: an open list now stays above a phone's on-screen keyboard. The keyboard shrinks only the visual viewport (`window.visualViewport`), which the list did not listen to, so part of it could sit under the keyboard. While a list is open it now follows the visual viewport's resize and scroll too (once per frame) and caps its height to the room visible on its side; it never changes side. Browsers without `visualViewport` behave as before.
319
+
320
+ Their markup is now a valid ARIA listbox, so screen readers hear the options and an axe scan of an open list is clean:
321
+
322
+ - Select: the scrolling box is the `listbox` (it was the whole layer, search box included); every row is a `role="option"` with `aria-selected` (and `aria-disabled` when it cannot be picked), and multi-select lists say `aria-multiselectable`. The trigger, and the search box while it has focus, name the row under the keyboard cursor with `aria-activedescendant`. The checkbox drawn in a multi-select row is a picture of the state (inert), not a second control inside the option. The "no options" / "no results" message sits beside the listbox with `role="status"`. The search box has an accessible name.
323
+ - Suggest: each row's `<li>` is the `role="option"` (it was a `listitem` with an option inside), and the input names the active row with `aria-activedescendant`.
324
+ - ReorderList: new optional `announceTo` prop, a live region of your own for what screen readers hear (Select's reorderable list uses it to keep its announcements outside the listbox).
325
+
326
+ If your tests found Select's search box with `[role="listbox"] input`, it is no longer inside the listbox: use `[data-select-dropdown] input`.
327
+
328
+ - e4d6b42: Select and Suggest lists open and close smoothly. An outlined or filled list unrolls from its field and rolls back into it, where closing used to be a bare fade, and an underlined or standard list goes back the way it came. The field's corners animate and stay joined until the list has gone, instead of snapping as soon as it starts to close. The list's shadow no longer pops in when the animation ends.
329
+ - d0ee468: A Popover or DropdownMenu anchored to a point on screen now closes when anything outside it scrolls, instead of staying put while the page moves. This includes DataTable's row and column header menus. Those menus also clear their ⋮ button when they open upward, rather than covering it.
330
+ - ac52d2f: DataTable pivot: `api.getCellRanges()` and `api.clearCellRanges()` read and clear the ranges on the pivot's result while it is shown (they read the rows' ranges before, so they returned nothing in pivot mode).
331
+ - 9e44141: DataTable pivot mode:
332
+
333
+ - **Cell ranges reach the grand-total line.** With `view.cellSelection`, a drag, Shift+click, Shift+arrows and Ctrl/Cmd+A now take in the grand-total line pinned at the bottom (before, a range stopped at the last line above it). Ranges reported to `onCellRangesChange` name each line by its key, the grand total included.
334
+ - **Server mode follows transactions.** `applyTransaction` / `applyTransactionAsync` while a server pivot is on now ask `dataSource.pivot` again: at most every 250 ms, and the last change is always asked for. Changes that come in while a request is still running are asked for once it answers. A request made out of date by another pivot, search, filter or `refresh` is aborted through `signal`. The result stays on screen while the new one loads, and figures that change flash as they do in client mode. In this mode `applyTransaction` returns the keys the transaction names.
335
+
336
+ - 6a739e3: DataTable's row menu and column menu opened lower than their button by the page's scroll, and to its right by the sideways scroll. Popover and DropdownMenu now place a surface styled `position: fixed` in the window (or its transformed ancestor) rather than as if it were absolute, whichever way it gets that style. Absolute surfaces are placed as before.
337
+ - 4c01bb1: DataTable split list: the open row's highlight slides to a clicked row again. A real click's press effect (the row's press-down `scale`, its wave) was taken for rows moving, so the highlight held its old place until the next click. Only animations that move rows (on the rows or what holds them, `transform` / `translate` / layout) are followed now, and any leftover offset is cleared when following ends.
338
+ - b2e9d03: DataTable split view: ↑ / ↓, Home / End and PageUp / PageDown (within the page) open the row they land on, so the detail beside the list follows the keys, as in a mail reading pane. While ticking rows (selection on) the keys keep their selection behaviour. Other layouts are unchanged.
339
+ - 10f3d4c: DataTable split list: the open row's mark (its tint and accent bar) now glides from the old row to the new one, like the Tabs indicator, whether the row is opened by a click, Enter after ↑ / ↓, the detail's ‹ › or `api.openRow`. A long jump (more than 4 rows or 320px away, or from a row that is off screen) fades in at the new row instead of sweeping across the list. When rows are added or removed above the open one, the mark stays on it, following its glide. Reduced motion or `--motion-scale: 0` switches it instantly. `aria-current` and `aria-selected` are unchanged. Tabs now measures its indicator through the same internal helper; it looks and slides as before.
340
+ - 100b2cc: Suggest: an inline list near the screen's right edge moved left with a negative margin, which made its auto-width list wider instead of moving it, so every measure asked for more shift and the page crashed ("Maximum update depth exceeded"). It now moves with `translate`, read back from its own state.
341
+ - 760b8a9: DataTable column resizing follows the mouse in every width mode.
342
+ - **Compact mode (the default):** dragging a column's edge changed nothing on screen; a resized column now keeps its width while the others still fit their content.
343
+ - **Scroll mode:** a drag started from the stored size, not the width on screen, so when the table stretched its columns, nothing happened until the mouse passed the drawn edge. Drags now start from the width you see, and the other columns stay as they are instead of snapping back.
344
+ - **Single columns and column groups** use the same drag.
345
+ - edcb339: DataTable row changes, the remaining cases:
346
+ - **Server mode:** a row that only fell off the end of the page because a transaction added one is no longer marked as removed. Only what a transaction really added or removed is marked and told.
347
+ - **Apps that pass a new `data` array:**
348
+ - **Other pages:** rows that land on another page now show in the notice.
349
+ - **Pausing:** `pauseUpdates` and an open row menu now hold the new `data` too. The table keeps showing the rows as they were, the notice counts what is waiting, and Resume shows the latest rows and then applies any transactions that waited.
350
+ - **Screen readers:** in client mode the summary line counts from all the data, so rows on other pages and in closed groups are included.
351
+ - b64f800: DataTable search does less work per cell. A row's cells are looked up once for all its columns, a cell keeps only its lowercased text (no extra copy without dots, dashes and underscores), cells that don't match share one result instead of each making their own, and the plain-ASCII check runs only on likely misses. On 100,000 rows the first search after loading is quicker than it was before the live-update work, and later searches are 10–25% quicker.
352
+ - 1fe9792: DataTable is faster with many rows:
353
+ - Adding, removing or reordering rows without virtual scrolling no longer freezes the page. Row motion reads every row's place before it animates any, and rows out of sight don't glide.
354
+ - Text sorts use one shared collator.
355
+ - The totals row sums once per set of rows, not on every render.
356
+ - Work done for row motion while it is off (virtual scrolling, grouped) is skipped.
357
+ - `applyTransactionAsync` merges a burst of updates into one pass.
358
+ - A search that has no dots, dashes or underscores is ranked once, not twice.
359
+ - 0d3612d: DataTable is faster with many rows:
360
+ - **Summary cards during live updates:** when only the rows change (same cards, filter, search and ticked rows), the figures are counted at most every 250ms, and the last change is always counted. Changing a filter, the search or the ticked rows still counts at once.
361
+ - **Search, faster per row:** a row whose text can't match is turned away before the fuzzy ranking runs. For plain text the result is the same as before; accented text still goes through the full ranking.
362
+ - **Search, quicker typing:** in client mode the search box shows each key at once and the rows follow right after. `useTable` returns `searchApplied`, the search the rows are filtered by now.
363
+ - 8f2b14e: DataTable: after `applyTransaction` / `applyTransactionAsync`, the table redoes only the changed rows. Unchanged rows keep their row, sort key, search match and filter result, and changed rows are merged into the sorted order instead of sorting every row again. The order is the same as a full sort. A new `data` array from the app is still redone in full, so an app that changes row objects in place keeps working.
364
+
365
+ ## 0.10.0
366
+
367
+ ### Upgrading from 0.9
368
+
369
+ Most of this release adds to what is there. These can change an existing screen:
370
+
371
+ - **Bulk actions:** an `onRun` that returns nothing now shows no toast and keeps the rows selected. An action that does its work and returns nothing should return a result, or call `api.clearSelection()`. Rows turned down by `eligible` are then not summarised; the handler gets them as `ctx.skipped`.
372
+ - **Select and Suggest lists** fit their content by default, up to a limit. `listWidth="field"` gives the old width for one field.
373
+ - **Icons** in icon-only buttons and the Sidebar are larger (20px at `small`). The buttons stay the same size. An icon with its own `size` keeps it. Check dense toolbars.
374
+ - **DataTable page size:** `pagination: { pageSize: 10 }` with no `pageSizeOptions` shows 10 rows and offers 10. A `pageSize` outside the app's own options starts on the first option.
375
+ - **DataTable `emptyMessage`** now applies only with no search or filter active. Set `noResultsMessage` for the other case.
376
+ - **DatePicker:** the confirm button's default text is "Apply" (pass `applyLabel="Search"` to keep the old word). In a Form, Tab moves on instead of submitting. A press outside reports `onOpenChange(false, 'blur')`, not `'escape'`.
377
+ - **DropdownMenu:** a controlled menu takes focus when it opens, which can blur a field being edited. A `header` passed as an element no longer gets the forced text style.
378
+ - **Input `type="file"`** no longer takes `value`. Read `event.target.files`.
379
+ - **`reorder` on Select** now really drags, and `fixedItems` also locks those first places.
380
+ - **`fullWidth` on text fields** is deprecated: it warns once and does not change the width. Use `width`.
381
+
382
+ Removed with no deprecation period, for anyone using the `useSelect` hook directly: `handlers.handleDragStart`, `handleDragOver`, `handleDragEnd`, `handleDrop`, `state.draggedItem` and `draggedOver`. Use `handlers.handleReorder`. Also removed: the DataTable classes `.drag-and-drop-list`, `.drag-and-drop-item` and `.drag-and-drop-handle`; use `.dt-reorder-frame` and `.dt-reorder-item`.
383
+
384
+ ### Minor Changes
385
+
386
+ - aff428a: Breadcrumbs: new `iconOnly` on `NavItem` shows only a crumb's icon, on the home crumb, any crumb or the last one. The label stays the accessible name as visually hidden text, so a non-string label works, and an item with no icon still shows its label. Only Breadcrumbs reads it.
387
+ - f06bc9d: Card: `selected` shows a card as chosen (and sets `aria-pressed` on a clickable one); `aria-*`, `data-*`, drag events and other element attributes pass through to the root; the title is now a real heading, `h3` by default with `headingLevel` to choose (or `'none'` for a span). The title looks the same at every level. A clickable card is a button, so its title stays a span.
388
+ - b0fa6e8: ChipInput: `tags` and `onTagsChange` make it a field of free-text tags. Enter, a comma or leaving the field adds what is typed, a pasted list is split, duplicates are ignored, and Backspace in the empty input removes the last. `sources` is now optional. Without `tags` it is the format-string editor, unchanged. New label `chipInput.removeTag`.
389
+ - d1e907e: Collapsible: `keepMounted` (on the container or one item) renders closed panels' content too, so an FAQ is in the server-rendered HTML. Closed content stays hidden and out of the tab order. The default is unchanged: content mounts on first expand.
390
+ - 88aaeba: DataTable: a search or filter that leaves no rows now says so, separately from a view with no data. New `noResults` label and `noResultsMessage` view option. `emptyMessage` and the `empty` label keep their meaning but now apply only when no search or filter is active, so an app that set only `emptyMessage` shows the new default text for an empty search.
391
+ - a7d56b9: **DataTable: `toolbarActions`** (view option): an app's own buttons on the toolbar line, such as "Add", whatever is selected. Each has `label`, `icon`, `variant`, `display`, `tooltip`, `disabled`, `onClick`, and is left out by its own `authorize` or by `authorize('toolbarAction', action)` (a new gate). On a phone an action with an icon shows only the icon; when the line runs out of room the buttons move to a second line at the right.
392
+ - 6fefbd7: DatePicker: `picker="month"` and `picker="year"` pick a month or a year with no day. The value is `yyyy-mm` or `yyyy` (`{ from, to }` of the same with `range`) and the field reads by the locale ("Nov 2026"). The panel has a month grid with year navigation or a paged year grid, typing (`11/2026`, `nov`, `2026`), full keyboard navigation (arrows, Home/End, PageUp/PageDown, Enter, Escape, Tab) and `min`/`max` that also take `yyyy-mm` and `yyyy`. Fields and Form get `field: 'date'` (`DateFieldDefinition`), for days, months and years. New `labels.datePicker` words: `previousYear`, `nextYear`, `previousYears`, `nextYears`, `month`, `year`, `from`, `to`, `rangeTo`, `selected`, `chooseMonth`, `chooseYear`.
393
+ - 4f10dfb: DatePicker: the year list now reaches 100 years back and 10 ahead, long enough for a date of birth. New `yearRange` prop (`{ back, ahead }`) changes that; `min` and `max` always cut the list and set any end `yearRange` leaves out. New `autoComplete` prop for the typing boxes, default still `off`.
394
+ - 4e83751: DropdownMenu: rail icons get `selected` (shown and announced as `menuitemcheckbox`); `closeOnSelect` on one icon or row overrides the menu's; `className` and `style` on one icon or row; `onOpen`, for controlled and trigger menus. A `header` that is not plain text no longer gets the forced semibold, secondary colour, nowrap and ellipsis, so a name over an email shows as written; a text header looks the same.
395
+
396
+ Keyboard fixes: in a browser the first row never took focus when opened by key (the surface is hidden while measured), so the arrows did nothing. Fixed. A controlled menu now takes focus as it opens and gives it back on close, so its arrows work. Tab closes and carries on from the trigger, also when it was opened by pointer. The icon rail is reachable by arrow keys, and focus follows into and out of a pane.
397
+
398
+ - f5ef4ac: Add a `width` prop to the text fields (Input, Select, Suggest, DatePicker, ChipInput), to custom
399
+ widgets through `FieldWrapper`, and to `Fields` / `Form` definitions under `fprop`. Exported type:
400
+ `FieldWidth`.
401
+
402
+ - no `width`: today's field, the row up to `--field-control-max-width` (320px). No existing field
403
+ changes.
404
+ - `width="full"`: the row, with no limit.
405
+ - `width="auto"`: the content. Given less room it fits its parent and the text is cut.
406
+ - a number or a CSS length: exactly that, and never wider than its parent.
407
+
408
+ It works the same in `default`, `inline` and `horizontal` (where it sizes the control column; the
409
+ label keeps `--field-label-width`) and in every variant. In `cell` it is ignored: the column owns
410
+ the width. Checkbox, Radio and Switch do not take it.
411
+
412
+ **Deprecated:** `fullWidth` on these fields. It keeps working for one release and warns once,
413
+ naming `width`, when it is passed. It has never changed a field's width, and it still does not:
414
+ `fullWidth`, `fullWidth={true}` and `fullWidth={false}` all render as a field with no `width`. To
415
+ fit the content use `width="auto"`; to fill the row, `width="full"`. If both are passed, `width`
416
+ wins. `fullWidth` on Button, ButtonGroup, Tabs, Checkbox, Radio and Switch is unchanged.
417
+
418
+ - 6c06908: Form: `dialogSlots` puts the form's header and actions in the header and footer bands of the Dialog it is rendered in, so they stay in view while the fields scroll. Save is tied to the form by the `form` attribute, so submit, Enter and validation keep working. Outside a Dialog it does nothing, and the default is unchanged.
419
+ - 70a858b: `useFormat()`: `dateTime(value)` writes the day in the date format with the time as the locale writes it (`03-11-2026 2:30 pm`), and `shortDate(value)` writes the day with the month as a word (`3 Nov 2026`).
420
+ - 9f8ffb6: Summary funnel cards for figures that are not narrowing steps (an amount per payment method). `showChange: false` hides the change from the step before, on the rows, in the tooltip and the picture, and gives its column to the bars (`Funnel` takes the same prop). `chart: 'bars'` draws the card as bars, and users can pick it in Manage.
421
+ - 69971b5: New `ImageEditor`: crop (drag and resize box, ratios, free, circle mask), zoom, pan, quarter turns, straighten and flip, with mouse, touch and keyboard, in place or in a Dialog. A compact row of icon buttons under the image. A host allows or restricts each tool with `crop`, `zoom`, `pan`, `rotate`, `straighten`, `flip` and `reset`: a restricted tool has no button and no key, and cannot appear in the output, even through `initialTransform`. `crop.minWidth` and `crop.minHeight` refuse an output below them with a message, and nothing is ever enlarged. `output` sets the size limits, type and quality. EXIF orientation is honoured once. A remote image whose server does not allow CORS shows a clear message. `panel` adds the host's own content, such as a preview of the result.
422
+
423
+ ImagePicker: `editable` opens each chosen or replacing file in the editor first, so `onAdd` and `onReplace` get the edited file. `editor` passes the editor's options through. `onEdit` adds an Edit action to each tile, and with `editable` and `onReplace` it opens the editor on `item.editSrc` (or `item.src`). Existing callers are unchanged.
424
+
425
+ `prepareImage` takes a `transform`, the same one the editor gives, so crop, rotate and flip can run with no UI. `ImagePrepareError` has a `code`. New exports `resolveImageTransform` and `imageOutputSize`, and new labels under `imageEditor`.
426
+
427
+ - 8b1c25f: ImagePicker: `onReplace` swaps a single image at `max={1}` (click or drop on a Replace tile), `dropZone` draws the add tile as a wide drop zone, `max={Infinity}` means no limit and drops the "2 / 5" count, and `onRemove` is optional (no remove button without it). New labels `image.replace` and `image.drop`.
428
+ - dd19a67: Input: `type="file"` takes `accept` and `multiple`, has a styled choose-file button on the browser's own control, and is no longer controlled, so a re-render cannot clear the chosen file (read `event.target.files`). `type="color"` is a proper swatch with its value beside it. Read-only disables both, since neither has a read-only mode of its own.
429
+ - e699ab8: Select and Suggest lists fit their content. By default a list is as wide as its longest option: never narrower than its field, up to a limit (320px for Select, 480px for Suggest; `--popup-list-width-max` changes it), and always on screen. A row past the limit is cut off, with the full text on hover. The new `listWidth="field"` makes the list exactly the field's width, as does `position.matchWidth: true`. Fields are not changed. Select no longer passes `fullWidth` to the DOM.
430
+ - 16fd40f: New components. `Link`: a styled anchor; `as` takes a router's link. `Alert`: status tones (info, success, warning, danger), optional title, icon, action and dismiss, the right live-region role for each tone, and a page-wide `banner` form. `Pagination`: controlled page controls for anything paged that is not a DataTable, with a page list or a simple "Page 1 of 8", the row range and a size select. `CommandPaletteTrigger`: a ready button for `CommandPalette`, with text and keycap on wide screens and an icon button on small ones. `PageProgress`: a thin bar along the top while a route changes, driven by `active`, showing nothing for a quick navigation and standing still under reduced motion. `NavList`: a vertical list of links for inside a page, over `NavItem` and by the same link rule as `Sidebar`. Their words are in new `UIProvider labels` groups: `link`, `alert`, `pagination`, `pageProgress`, `navList`, and `commandPalette.trigger`.
431
+ - e8bd2f0: One reorder everywhere. `Select`'s `reorder` and the DataTable's Card fields / List fields editor now run on `ReorderList` instead of their own native drag and drop, so rows slide live, and both work on touch and with the keyboard.
432
+
433
+ `ReorderList` gains (all additive): `role` and `itemRole`; `axis="wrap"` for chips on several lines; `ReorderGroup` with `onMove`, for rows that travel between lists, with `listId`, `maxItems`, `whenFull` (`reject` or `replace`) and `sortable`, live sliding in the destination, keyboard steps through the lists in order and announcements (new `labels.reorder.movedToList` and `droppedInList`); `autoScroll` and `autoScrollSpeed`; `handleRef`, whose `move(key, step)` moves a row for an owner that keeps the focus elsewhere; and `data-reorder-grab` for a control inside a row that should drag on a press that travels and click otherwise.
434
+
435
+ `Select`: the selected options render as a `ReorderList` with the rest below them. A selected row drags from anywhere on it (on touch, its handle at once or the row after a long press). The focus stays on the search box or trigger: Alt+Up / Alt+Down moves the row under the keyboard cursor, and the plain arrows, Enter and Escape are unchanged. Escape during a drag cancels only the drag. Dragging is off while a search narrows the list. `reorder={true}` now drags too (it used to only put the selected options first). `fixedItems` also locks those first places by position. All of `ReorderConfig` is still accepted, and `dragHandleClassName` and `autoScrollSpeed`, which nothing read before, now work. In reorder mode the rows are `role="option"` and the selected ones are `<div>`s inside the ReorderList (new labels `select.selectedOptions` and `select.reorderInstructions`).
436
+
437
+ Card fields editor: fields can also be placed at a position within a part, the grip now shows on touch, and each field in the "not shown" pool has a grip for the keyboard. Enter on a pool field still adds it. New label `fieldsMove`. CSS: `.dt-cle-slot--drop` is gone, use `[data-reorder-over]`; `.dt-cle-chip-grip` is gone, the grip is `ReorderList`'s handle.
438
+
439
+ Breaking, for anyone using the `useSelect` hook directly: `handlers.handleDragStart`, `handleDragOver`, `handleDragEnd` and `handleDrop` and `state.draggedItem` and `draggedOver` are removed (use `handlers.handleReorder`). The `AutoScrollState` type is still exported, deprecated.
440
+
441
+ - 8873e83: New `ReorderList`: a drag-to-reorder list where the dragged row lifts with a shadow and follows the pointer while the other rows slide apart. One code path for mouse, touch and pen (a handle drags at once; `dragFrom="row"` asks for a long press on touch, so the page still scrolls). Vertical or horizontal, rows of any size, auto-scroll near the edges of scrolling containers, works inside a Dialog, honours reduced motion. Keyboard: Space or Enter on a focused handle picks up, arrows move, Space or Enter drops, Escape cancels, announced to screen readers through the new `labels.reorder` of `UIProvider`. Controlled, with `items`, `getKey`, `renderItem`, `onReorder`, plus `canDrag` and `isFixed`.
442
+
443
+ DataTable now uses it for the column chooser, the export columns, Manage's view tabs and templates, its summary cards and the "Grouped by" chips, so these all slide live and can be reordered with the keyboard and on touch. The private drag list and its classes (`.drag-and-drop-list`, `.drag-and-drop-item`, `.drag-and-drop-handle`) are gone; CSS that reached into them should target `.dt-reorder-frame` and `.dt-reorder-item`.
444
+
445
+ - 5eeae92: DataTable: `disableTextTransform` on a row action shows its button's label as written. Labels are uppercase otherwise, as on every Button.
446
+
447
+ ### Patch Changes
448
+
449
+ - aff428a: Breadcrumbs: the home crumb sizes only its icon, so a text label reads at the trail's size. A home crumb with a text label is also named by that label, not by a fixed "Home".
450
+ - a7d56b9: **DataTable: what a bulk action's `onRun` returns now decides the feedback** (behaviour change).
451
+
452
+ - **Returns nothing** (or a promise of nothing): the table says nothing and keeps the selection. It used to show "N done" and clear the selection straight away, even when the action had only opened a dialog that still needed the rows. An action that wants the old result returns one: `{}` gives the counted summary. An action that finishes later lets go of the rows with `api.clearSelection()`.
453
+ - **Returns a result**: reported exactly as before (`done`, `skipped`, `reason`, `message`, `status`, `undo`, `keepSelection`).
454
+ - **Throws or rejects**: the failure is always reported and the selection stays, as before.
455
+
456
+ Rows `eligible` turned down are no longer counted in a toast when `onRun` returns nothing: the action receives them as `skipped`. In server mode the table still fetches the rows again after an action that returned nothing.
457
+
458
+ - a7d56b9: **DataTable: an explicit `pageSize` wins when the app set no `pageSizeOptions`.** `pagination: { pageSize: 10 }` shows 10 rows (it showed 25), in client and server mode, and the selector offers 10 among the default sizes. The same goes for `initialState.pageSize`, and for a view's `pageSize` when switching to a view with no options of its own. The fallback to the first option now applies only to options the app set itself (on the view's `pagination` or on the `dataSource`).
459
+
460
+ The table's page size selector also keeps its sizes in order (10, 25, 50, 100, not 10, 100, 25, 50) and has no search box, like the standalone `Pagination`.
461
+
462
+ - 88aaeba: DataTable: a `pageSize` that is not in the app's own `pageSizeOptions` now starts on the first option, so the page-size selector no longer shows a placeholder. "All" is skipped when another option exists. This also applies when another view offers different options. With no `pageSizeOptions` from the app, the explicit `pageSize` wins (see below).
463
+ - 88aaeba: DataTable server mode: changing a view's `params` returns to page 1, with no request for the old page of the new params. Params are compared by value, so a new object with the same contents changes nothing, and a restored page index survives the mount.
464
+ - 4d09353: DatePicker: the confirm button's default text is now "Apply", not "Search". `applyLabel` still sets it per field (`''` hides it), and `labels.datePicker.apply` on `UIProvider` sets it for the app. A screen that relied on the default to read "Search" should pass `applyLabel="Search"`.
465
+ - b756194: DatePicker, days: the panel's date and time boxes no longer act on the grid or form around them (an arrow moved the table's cell, Tab moved it twice, Enter submitted the form). A failed Form submit now finds `field: 'date'` and focuses it (`data-name` on the trigger). A read-only or disabled field no longer opens by keyboard or by the `open` prop. Space opens the panel without replacing the box's text with a blank.
466
+ - b929252: DatePicker, days: closing the panel with Enter, Escape or the confirm button puts the focus back on the field, so Enter-to-next carries on in a Form or a table. A press outside now reports `onOpenChange(false, 'blur')` instead of `'escape'`, and leaves the focus where it landed. In a Form, Tab from the panel closes it and moves to the next field; it used to submit the form. Time boxes are still reached with Tab first.
467
+
468
+ Fields in a grid: Delete or Backspace no longer empties a read-only or disabled cell. This covers every field that clears through the grid, not only the DatePicker.
469
+
470
+ - 0665a92: Icons fill their space. An icon-only `Button`'s icon scaled with the button's text, about 13px in a 36px button; it now uses the new `--icon-size-xxs` … `--icon-size-xl` tokens (20px at `small`) and the button stays the same size. Sidebar icons use them too (20px, 16px on child rows), and the box and child indent now follow `--ui-scale`, so they zoom with the text. An icon given its own `size` keeps it.
471
+ - 656912e: Input: a `Button` in `icon.start` or `icon.end` no longer makes the field taller, at any pairing of button size and field size.
472
+ - f5ef4ac: Fix a Select's list running past the right edge of a phone screen when an option is long, and a
473
+ ChipInput tag longer than its field pushing out of the field. The tag's text is now cut instead.
474
+ - 14d7aba: The build's leak check now also scans `src/`, stories and tests included.
475
+ - a3d762c: Fix `Input type="password"` being taller than other fields at small sizes (32px against 28 at
476
+ `xxs`, up to 44 against 42 at `medium`). The show/hide button no longer sets the field's height.
477
+ - da337de: DatePicker `picker="month"` and `picker="year"`: one click or Enter chooses a single period and closes the panel, with the focus back on the field; clicking the period already chosen keeps it instead of clearing it. A single value has no confirm button, so the "Search" default no longer appears and `applyLabel=""` is no longer needed. A `range` closes once a click leaves two different ends, and shows a confirm button only when `applyLabel` is passed. `onApply` is called when a click or Enter chooses. Enter now also takes a cell reached with the panel's page buttons or year list, and the year list no longer jumps back to the value.
478
+ - 8324f7b: Fix opening a Select crashing with "Maximum update depth exceeded" on React 18. The list's
479
+ position is measured on every render, and React 18 kept replaying a waiting update against old
480
+ state, so the measurement never settled. Suggest's list had the same pattern and is fixed with it.
481
+ Also fix the `inert` attribute on React 18, where it was dropped with a warning, so leaving
482
+ surfaces and closed Collapsible content stayed reachable by keyboard.
483
+ - a5e99a5: DataTable: pressing a button, link or field inside a row no longer tints the whole row. The browser's `:active` also matches a parent of the pressed control, so a row looked clicked on every button press. Only a press on the row itself shows the tint and opens the row.
484
+ - 52af1d3: Sidebar: the expand chevrons and the collapse bar's chevron follow `--ui-scale`, so they zoom with the row's icon and text.
485
+ - 7a987e6: Sidebar: the collapsed rail's flyout keeps its title and rows while it animates out. It used to empty at once, so the exit played on a bare strip where the panel had been.
486
+ - 9f8ffb6: - ScrollStrip (Tabs, filter chips, view tabs): while the strip overflows, slim rectangular ‹ › boxes stand either side of it, always there, with the one that has nothing further that way disabled. They go when everything fits.
487
+ - DatePicker: the preset's name no longer stays after the app changes the value. It stays only if the new dates still match a preset; otherwise the dates show.
488
+ - Input: the password toggle is an icon, not an emoji.
489
+ - 0dc8be7: Tooltips and the collapsed Sidebar's flyouts no longer flicker. There is one tip at a time, and appearing from nothing or leaving to nothing are the only moves that animate: moving from one trigger to the next swaps in a single frame, with no delay and no fade, and never two tips on screen. In the collapsed Sidebar, flyouts and tips hand over the same way, and a flyout re-entered during its exit no longer restarts its entrance from invisible. A tip the pointer left during its delay was never seen, so it no longer shortens the next tip's wait. Rail tips anchor to their row, so they all line up.
490
+
3
491
  ## 0.9.0
4
492
 
5
493
  ### Minor Changes