@almadar/ui 4.50.17 → 4.50.19

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.
@@ -24913,6 +24913,7 @@ function useDataDnd(args) {
24913
24913
  sortable: sortable$1,
24914
24914
  dropEvent,
24915
24915
  reorderEvent,
24916
+ positionEvent,
24916
24917
  dndItemIdField = "id",
24917
24918
  dndRoot,
24918
24919
  items,
@@ -24980,8 +24981,8 @@ function useDataDnd(args) {
24980
24981
  const [activeDrag, setActiveDrag] = React93__namespace.default.useState(null);
24981
24982
  const [overZoneGroup, setOverZoneGroup] = React93__namespace.default.useState(null);
24982
24983
  const meta = React93__namespace.default.useMemo(
24983
- () => ({ group: ownGroup, dropEvent, reorderEvent, itemIds, rawItems: items, idField: dndItemIdField }),
24984
- [ownGroup, dropEvent, reorderEvent, itemIds, items, dndItemIdField]
24984
+ () => ({ group: ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, rawItems: items, idField: dndItemIdField }),
24985
+ [ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, items, dndItemIdField]
24985
24986
  );
24986
24987
  React93__namespace.default.useEffect(() => {
24987
24988
  const target = isRoot ? null : parentRoot;
@@ -25067,6 +25068,20 @@ function useDataDnd(args) {
25067
25068
  dndLog.warn("dragEnd:abort:no-zone-resolved", { activeId: active.id, hasSource: !!sourceMeta, hasTarget: !!targetMeta });
25068
25069
  return;
25069
25070
  }
25071
+ const emitPositions = (zoneMeta) => {
25072
+ if (!zoneMeta.positionEvent) {
25073
+ dndLog.debug("dragEnd:positions:no-event", { group: zoneMeta.group });
25074
+ return;
25075
+ }
25076
+ const evt = `UI:${zoneMeta.positionEvent}`;
25077
+ const order = optimisticOrdersRef.current.get(zoneMeta.group) ?? zoneMeta.rawItems;
25078
+ order.forEach((it, idx) => {
25079
+ const id = String(it[zoneMeta.idField]);
25080
+ const position = idx * 1e3;
25081
+ eventBus.emit(evt, { id, position });
25082
+ });
25083
+ dndLog.info("dragEnd:positions:emitted", { event: evt, group: zoneMeta.group, count: order.length });
25084
+ };
25070
25085
  if (sourceMeta.group !== targetMeta.group) {
25071
25086
  if (targetMeta.dropEvent) {
25072
25087
  const evt = `UI:${targetMeta.dropEvent}`;
@@ -25086,6 +25101,8 @@ function useDataDnd(args) {
25086
25101
  } else {
25087
25102
  dndLog.warn("dragEnd:cross-container:no-dropEvent-on-target", { targetGroup: targetMeta.group });
25088
25103
  }
25104
+ emitPositions(sourceMeta);
25105
+ emitPositions(targetMeta);
25089
25106
  return;
25090
25107
  }
25091
25108
  if (oldIndex === newIndex) {
@@ -25108,6 +25125,7 @@ function useDataDnd(args) {
25108
25125
  } else {
25109
25126
  dndLog.debug("dragEnd:reorder:no-reorderEvent", { sourceGroup: sourceMeta.group });
25110
25127
  }
25128
+ emitPositions(sourceMeta);
25111
25129
  },
25112
25130
  [eventBus]
25113
25131
  );
@@ -25412,6 +25430,7 @@ function DataGrid({
25412
25430
  sortable,
25413
25431
  dropEvent,
25414
25432
  reorderEvent,
25433
+ positionEvent,
25415
25434
  dndItemIdField,
25416
25435
  dndRoot
25417
25436
  }) {
@@ -25429,6 +25448,7 @@ function DataGrid({
25429
25448
  sortable,
25430
25449
  dropEvent,
25431
25450
  reorderEvent,
25451
+ positionEvent,
25432
25452
  dndItemIdField,
25433
25453
  dndRoot
25434
25454
  });
@@ -25821,6 +25841,7 @@ function DataList({
25821
25841
  sortable: sortableProp,
25822
25842
  dropEvent,
25823
25843
  reorderEvent: dndReorderEvent,
25844
+ positionEvent,
25824
25845
  dndItemIdField,
25825
25846
  dndRoot
25826
25847
  }) {
@@ -25837,6 +25858,7 @@ function DataList({
25837
25858
  sortable: sortableProp,
25838
25859
  dropEvent,
25839
25860
  reorderEvent: dndReorderEvent,
25861
+ positionEvent,
25840
25862
  dndItemIdField,
25841
25863
  dndRoot
25842
25864
  });
package/dist/avl/index.js CHANGED
@@ -24867,6 +24867,7 @@ function useDataDnd(args) {
24867
24867
  sortable,
24868
24868
  dropEvent,
24869
24869
  reorderEvent,
24870
+ positionEvent,
24870
24871
  dndItemIdField = "id",
24871
24872
  dndRoot,
24872
24873
  items,
@@ -24934,8 +24935,8 @@ function useDataDnd(args) {
24934
24935
  const [activeDrag, setActiveDrag] = React93__default.useState(null);
24935
24936
  const [overZoneGroup, setOverZoneGroup] = React93__default.useState(null);
24936
24937
  const meta = React93__default.useMemo(
24937
- () => ({ group: ownGroup, dropEvent, reorderEvent, itemIds, rawItems: items, idField: dndItemIdField }),
24938
- [ownGroup, dropEvent, reorderEvent, itemIds, items, dndItemIdField]
24938
+ () => ({ group: ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, rawItems: items, idField: dndItemIdField }),
24939
+ [ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, items, dndItemIdField]
24939
24940
  );
24940
24941
  React93__default.useEffect(() => {
24941
24942
  const target = isRoot ? null : parentRoot;
@@ -25021,6 +25022,20 @@ function useDataDnd(args) {
25021
25022
  dndLog.warn("dragEnd:abort:no-zone-resolved", { activeId: active.id, hasSource: !!sourceMeta, hasTarget: !!targetMeta });
25022
25023
  return;
25023
25024
  }
25025
+ const emitPositions = (zoneMeta) => {
25026
+ if (!zoneMeta.positionEvent) {
25027
+ dndLog.debug("dragEnd:positions:no-event", { group: zoneMeta.group });
25028
+ return;
25029
+ }
25030
+ const evt = `UI:${zoneMeta.positionEvent}`;
25031
+ const order = optimisticOrdersRef.current.get(zoneMeta.group) ?? zoneMeta.rawItems;
25032
+ order.forEach((it, idx) => {
25033
+ const id = String(it[zoneMeta.idField]);
25034
+ const position = idx * 1e3;
25035
+ eventBus.emit(evt, { id, position });
25036
+ });
25037
+ dndLog.info("dragEnd:positions:emitted", { event: evt, group: zoneMeta.group, count: order.length });
25038
+ };
25024
25039
  if (sourceMeta.group !== targetMeta.group) {
25025
25040
  if (targetMeta.dropEvent) {
25026
25041
  const evt = `UI:${targetMeta.dropEvent}`;
@@ -25040,6 +25055,8 @@ function useDataDnd(args) {
25040
25055
  } else {
25041
25056
  dndLog.warn("dragEnd:cross-container:no-dropEvent-on-target", { targetGroup: targetMeta.group });
25042
25057
  }
25058
+ emitPositions(sourceMeta);
25059
+ emitPositions(targetMeta);
25043
25060
  return;
25044
25061
  }
25045
25062
  if (oldIndex === newIndex) {
@@ -25062,6 +25079,7 @@ function useDataDnd(args) {
25062
25079
  } else {
25063
25080
  dndLog.debug("dragEnd:reorder:no-reorderEvent", { sourceGroup: sourceMeta.group });
25064
25081
  }
25082
+ emitPositions(sourceMeta);
25065
25083
  },
25066
25084
  [eventBus]
25067
25085
  );
@@ -25366,6 +25384,7 @@ function DataGrid({
25366
25384
  sortable,
25367
25385
  dropEvent,
25368
25386
  reorderEvent,
25387
+ positionEvent,
25369
25388
  dndItemIdField,
25370
25389
  dndRoot
25371
25390
  }) {
@@ -25383,6 +25402,7 @@ function DataGrid({
25383
25402
  sortable,
25384
25403
  dropEvent,
25385
25404
  reorderEvent,
25405
+ positionEvent,
25386
25406
  dndItemIdField,
25387
25407
  dndRoot
25388
25408
  });
@@ -25775,6 +25795,7 @@ function DataList({
25775
25795
  sortable: sortableProp,
25776
25796
  dropEvent,
25777
25797
  reorderEvent: dndReorderEvent,
25798
+ positionEvent,
25778
25799
  dndItemIdField,
25779
25800
  dndRoot
25780
25801
  }) {
@@ -25791,6 +25812,7 @@ function DataList({
25791
25812
  sortable: sortableProp,
25792
25813
  dropEvent,
25793
25814
  reorderEvent: dndReorderEvent,
25815
+ positionEvent,
25794
25816
  dndItemIdField,
25795
25817
  dndRoot
25796
25818
  });
@@ -20080,6 +20080,7 @@ function useDataDnd(args) {
20080
20080
  sortable: sortable$1,
20081
20081
  dropEvent,
20082
20082
  reorderEvent,
20083
+ positionEvent,
20083
20084
  dndItemIdField = "id",
20084
20085
  dndRoot,
20085
20086
  items,
@@ -20147,8 +20148,8 @@ function useDataDnd(args) {
20147
20148
  const [activeDrag, setActiveDrag] = React75__namespace.default.useState(null);
20148
20149
  const [overZoneGroup, setOverZoneGroup] = React75__namespace.default.useState(null);
20149
20150
  const meta = React75__namespace.default.useMemo(
20150
- () => ({ group: ownGroup, dropEvent, reorderEvent, itemIds, rawItems: items, idField: dndItemIdField }),
20151
- [ownGroup, dropEvent, reorderEvent, itemIds, items, dndItemIdField]
20151
+ () => ({ group: ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, rawItems: items, idField: dndItemIdField }),
20152
+ [ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, items, dndItemIdField]
20152
20153
  );
20153
20154
  React75__namespace.default.useEffect(() => {
20154
20155
  const target = isRoot ? null : parentRoot;
@@ -20234,6 +20235,20 @@ function useDataDnd(args) {
20234
20235
  dndLog.warn("dragEnd:abort:no-zone-resolved", { activeId: active.id, hasSource: !!sourceMeta, hasTarget: !!targetMeta });
20235
20236
  return;
20236
20237
  }
20238
+ const emitPositions = (zoneMeta) => {
20239
+ if (!zoneMeta.positionEvent) {
20240
+ dndLog.debug("dragEnd:positions:no-event", { group: zoneMeta.group });
20241
+ return;
20242
+ }
20243
+ const evt = `UI:${zoneMeta.positionEvent}`;
20244
+ const order = optimisticOrdersRef.current.get(zoneMeta.group) ?? zoneMeta.rawItems;
20245
+ order.forEach((it, idx) => {
20246
+ const id = String(it[zoneMeta.idField]);
20247
+ const position = idx * 1e3;
20248
+ eventBus.emit(evt, { id, position });
20249
+ });
20250
+ dndLog.info("dragEnd:positions:emitted", { event: evt, group: zoneMeta.group, count: order.length });
20251
+ };
20237
20252
  if (sourceMeta.group !== targetMeta.group) {
20238
20253
  if (targetMeta.dropEvent) {
20239
20254
  const evt = `UI:${targetMeta.dropEvent}`;
@@ -20253,6 +20268,8 @@ function useDataDnd(args) {
20253
20268
  } else {
20254
20269
  dndLog.warn("dragEnd:cross-container:no-dropEvent-on-target", { targetGroup: targetMeta.group });
20255
20270
  }
20271
+ emitPositions(sourceMeta);
20272
+ emitPositions(targetMeta);
20256
20273
  return;
20257
20274
  }
20258
20275
  if (oldIndex === newIndex) {
@@ -20275,6 +20292,7 @@ function useDataDnd(args) {
20275
20292
  } else {
20276
20293
  dndLog.debug("dragEnd:reorder:no-reorderEvent", { sourceGroup: sourceMeta.group });
20277
20294
  }
20295
+ emitPositions(sourceMeta);
20278
20296
  },
20279
20297
  [eventBus]
20280
20298
  );
@@ -20579,6 +20597,7 @@ function DataGrid({
20579
20597
  sortable,
20580
20598
  dropEvent,
20581
20599
  reorderEvent,
20600
+ positionEvent,
20582
20601
  dndItemIdField,
20583
20602
  dndRoot
20584
20603
  }) {
@@ -20596,6 +20615,7 @@ function DataGrid({
20596
20615
  sortable,
20597
20616
  dropEvent,
20598
20617
  reorderEvent,
20618
+ positionEvent,
20599
20619
  dndItemIdField,
20600
20620
  dndRoot
20601
20621
  });
@@ -20988,6 +21008,7 @@ function DataList({
20988
21008
  sortable: sortableProp,
20989
21009
  dropEvent,
20990
21010
  reorderEvent: dndReorderEvent,
21011
+ positionEvent,
20991
21012
  dndItemIdField,
20992
21013
  dndRoot
20993
21014
  }) {
@@ -21004,6 +21025,7 @@ function DataList({
21004
21025
  sortable: sortableProp,
21005
21026
  dropEvent,
21006
21027
  reorderEvent: dndReorderEvent,
21028
+ positionEvent,
21007
21029
  dndItemIdField,
21008
21030
  dndRoot
21009
21031
  });
@@ -20034,6 +20034,7 @@ function useDataDnd(args) {
20034
20034
  sortable,
20035
20035
  dropEvent,
20036
20036
  reorderEvent,
20037
+ positionEvent,
20037
20038
  dndItemIdField = "id",
20038
20039
  dndRoot,
20039
20040
  items,
@@ -20101,8 +20102,8 @@ function useDataDnd(args) {
20101
20102
  const [activeDrag, setActiveDrag] = React75__default.useState(null);
20102
20103
  const [overZoneGroup, setOverZoneGroup] = React75__default.useState(null);
20103
20104
  const meta = React75__default.useMemo(
20104
- () => ({ group: ownGroup, dropEvent, reorderEvent, itemIds, rawItems: items, idField: dndItemIdField }),
20105
- [ownGroup, dropEvent, reorderEvent, itemIds, items, dndItemIdField]
20105
+ () => ({ group: ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, rawItems: items, idField: dndItemIdField }),
20106
+ [ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, items, dndItemIdField]
20106
20107
  );
20107
20108
  React75__default.useEffect(() => {
20108
20109
  const target = isRoot ? null : parentRoot;
@@ -20188,6 +20189,20 @@ function useDataDnd(args) {
20188
20189
  dndLog.warn("dragEnd:abort:no-zone-resolved", { activeId: active.id, hasSource: !!sourceMeta, hasTarget: !!targetMeta });
20189
20190
  return;
20190
20191
  }
20192
+ const emitPositions = (zoneMeta) => {
20193
+ if (!zoneMeta.positionEvent) {
20194
+ dndLog.debug("dragEnd:positions:no-event", { group: zoneMeta.group });
20195
+ return;
20196
+ }
20197
+ const evt = `UI:${zoneMeta.positionEvent}`;
20198
+ const order = optimisticOrdersRef.current.get(zoneMeta.group) ?? zoneMeta.rawItems;
20199
+ order.forEach((it, idx) => {
20200
+ const id = String(it[zoneMeta.idField]);
20201
+ const position = idx * 1e3;
20202
+ eventBus.emit(evt, { id, position });
20203
+ });
20204
+ dndLog.info("dragEnd:positions:emitted", { event: evt, group: zoneMeta.group, count: order.length });
20205
+ };
20191
20206
  if (sourceMeta.group !== targetMeta.group) {
20192
20207
  if (targetMeta.dropEvent) {
20193
20208
  const evt = `UI:${targetMeta.dropEvent}`;
@@ -20207,6 +20222,8 @@ function useDataDnd(args) {
20207
20222
  } else {
20208
20223
  dndLog.warn("dragEnd:cross-container:no-dropEvent-on-target", { targetGroup: targetMeta.group });
20209
20224
  }
20225
+ emitPositions(sourceMeta);
20226
+ emitPositions(targetMeta);
20210
20227
  return;
20211
20228
  }
20212
20229
  if (oldIndex === newIndex) {
@@ -20229,6 +20246,7 @@ function useDataDnd(args) {
20229
20246
  } else {
20230
20247
  dndLog.debug("dragEnd:reorder:no-reorderEvent", { sourceGroup: sourceMeta.group });
20231
20248
  }
20249
+ emitPositions(sourceMeta);
20232
20250
  },
20233
20251
  [eventBus]
20234
20252
  );
@@ -20533,6 +20551,7 @@ function DataGrid({
20533
20551
  sortable,
20534
20552
  dropEvent,
20535
20553
  reorderEvent,
20554
+ positionEvent,
20536
20555
  dndItemIdField,
20537
20556
  dndRoot
20538
20557
  }) {
@@ -20550,6 +20569,7 @@ function DataGrid({
20550
20569
  sortable,
20551
20570
  dropEvent,
20552
20571
  reorderEvent,
20572
+ positionEvent,
20553
20573
  dndItemIdField,
20554
20574
  dndRoot
20555
20575
  });
@@ -20942,6 +20962,7 @@ function DataList({
20942
20962
  sortable: sortableProp,
20943
20963
  dropEvent,
20944
20964
  reorderEvent: dndReorderEvent,
20965
+ positionEvent,
20945
20966
  dndItemIdField,
20946
20967
  dndRoot
20947
20968
  }) {
@@ -20958,6 +20979,7 @@ function DataList({
20958
20979
  sortable: sortableProp,
20959
20980
  dropEvent,
20960
20981
  reorderEvent: dndReorderEvent,
20982
+ positionEvent,
20961
20983
  dndItemIdField,
20962
20984
  dndRoot
20963
20985
  });
@@ -103,7 +103,7 @@ export interface DataGridProps<T extends EntityRow = EntityRow> extends DataDndP
103
103
  /** Max items to show before "Show More" button. Defaults to 0 (disabled). */
104
104
  pageSize?: number;
105
105
  }
106
- export declare function DataGrid<T extends EntityRow = EntityRow>({ entity, fields, columns, itemActions, cols, gap, minCardWidth, className, isLoading, error, imageField, selectable, selectionEvent, infiniteScroll, loadMoreEvent, hasMore, children, pageSize, renderItem: schemaRenderItem, dragGroup, accepts, sortable, dropEvent, reorderEvent, dndItemIdField, dndRoot, }: DataGridProps<T>): string | number | bigint | boolean | import("react/jsx-runtime").JSX.Element | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined> | null | undefined;
106
+ export declare function DataGrid<T extends EntityRow = EntityRow>({ entity, fields, columns, itemActions, cols, gap, minCardWidth, className, isLoading, error, imageField, selectable, selectionEvent, infiniteScroll, loadMoreEvent, hasMore, children, pageSize, renderItem: schemaRenderItem, dragGroup, accepts, sortable, dropEvent, reorderEvent, positionEvent, dndItemIdField, dndRoot, }: DataGridProps<T>): string | number | bigint | boolean | import("react/jsx-runtime").JSX.Element | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined> | null | undefined;
107
107
  export declare namespace DataGrid {
108
108
  var displayName: string;
109
109
  }
@@ -117,7 +117,7 @@ export interface DataListProps<T extends EntityRow = EntityRow> extends DataDndP
117
117
  /** Max items to show before "Show More" button. Defaults to 5. Set to 0 to disable. */
118
118
  pageSize?: number;
119
119
  }
120
- export declare function DataList<T extends EntityRow = EntityRow>({ entity, fields, columns, itemActions, gap, variant, groupBy, senderField, currentUser, className, isLoading, error, reorderable: _reorderable, reorderEvent: _reorderEvent, swipeLeftEvent: _swipeLeftEvent, swipeLeftActions: _swipeLeftActions, swipeRightEvent: _swipeRightEvent, swipeRightActions: _swipeRightActions, longPressEvent: _longPressEvent, infiniteScroll, loadMoreEvent, hasMore, children, pageSize, renderItem: schemaRenderItem, dragGroup, accepts, sortable: sortableProp, dropEvent, reorderEvent: dndReorderEvent, dndItemIdField, dndRoot, }: DataListProps<T>): string | number | bigint | boolean | import("react/jsx-runtime").JSX.Element | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined> | null | undefined;
120
+ export declare function DataList<T extends EntityRow = EntityRow>({ entity, fields, columns, itemActions, gap, variant, groupBy, senderField, currentUser, className, isLoading, error, reorderable: _reorderable, reorderEvent: _reorderEvent, swipeLeftEvent: _swipeLeftEvent, swipeLeftActions: _swipeLeftActions, swipeRightEvent: _swipeRightEvent, swipeRightActions: _swipeRightActions, longPressEvent: _longPressEvent, infiniteScroll, loadMoreEvent, hasMore, children, pageSize, renderItem: schemaRenderItem, dragGroup, accepts, sortable: sortableProp, dropEvent, reorderEvent: dndReorderEvent, positionEvent, dndItemIdField, dndRoot, }: DataListProps<T>): string | number | bigint | boolean | import("react/jsx-runtime").JSX.Element | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined> | null | undefined;
121
121
  export declare namespace DataList {
122
122
  var displayName: string;
123
123
  }
@@ -20,6 +20,14 @@ import React from 'react';
20
20
  import { type UniqueIdentifier } from '@dnd-kit/core';
21
21
  import type { EntityRow, EventKey } from '@almadar/core';
22
22
  export interface DataDndProps {
23
+ /**
24
+ * Event emitted N times per drop (one per item in each affected zone) so
25
+ * the trait can persist new positions for every item — not just the moved
26
+ * one. Required for stable sort-by-position because setting only the
27
+ * dragged item's position creates collisions with the (unchanged) others.
28
+ * Payload: { id : string, position : number }.
29
+ */
30
+ positionEvent?: EventKey;
23
31
  dragGroup?: string;
24
32
  accepts?: string;
25
33
  sortable?: boolean;
@@ -21325,6 +21325,7 @@ function useDataDnd(args) {
21325
21325
  sortable: sortable$1,
21326
21326
  dropEvent,
21327
21327
  reorderEvent,
21328
+ positionEvent,
21328
21329
  dndItemIdField = "id",
21329
21330
  dndRoot,
21330
21331
  items,
@@ -21392,8 +21393,8 @@ function useDataDnd(args) {
21392
21393
  const [activeDrag, setActiveDrag] = React81__namespace.default.useState(null);
21393
21394
  const [overZoneGroup, setOverZoneGroup] = React81__namespace.default.useState(null);
21394
21395
  const meta = React81__namespace.default.useMemo(
21395
- () => ({ group: ownGroup, dropEvent, reorderEvent, itemIds, rawItems: items, idField: dndItemIdField }),
21396
- [ownGroup, dropEvent, reorderEvent, itemIds, items, dndItemIdField]
21396
+ () => ({ group: ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, rawItems: items, idField: dndItemIdField }),
21397
+ [ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, items, dndItemIdField]
21397
21398
  );
21398
21399
  React81__namespace.default.useEffect(() => {
21399
21400
  const target = isRoot ? null : parentRoot;
@@ -21479,6 +21480,20 @@ function useDataDnd(args) {
21479
21480
  dndLog.warn("dragEnd:abort:no-zone-resolved", { activeId: active.id, hasSource: !!sourceMeta, hasTarget: !!targetMeta });
21480
21481
  return;
21481
21482
  }
21483
+ const emitPositions = (zoneMeta) => {
21484
+ if (!zoneMeta.positionEvent) {
21485
+ dndLog.debug("dragEnd:positions:no-event", { group: zoneMeta.group });
21486
+ return;
21487
+ }
21488
+ const evt = `UI:${zoneMeta.positionEvent}`;
21489
+ const order = optimisticOrdersRef.current.get(zoneMeta.group) ?? zoneMeta.rawItems;
21490
+ order.forEach((it, idx) => {
21491
+ const id = String(it[zoneMeta.idField]);
21492
+ const position = idx * 1e3;
21493
+ eventBus.emit(evt, { id, position });
21494
+ });
21495
+ dndLog.info("dragEnd:positions:emitted", { event: evt, group: zoneMeta.group, count: order.length });
21496
+ };
21482
21497
  if (sourceMeta.group !== targetMeta.group) {
21483
21498
  if (targetMeta.dropEvent) {
21484
21499
  const evt = `UI:${targetMeta.dropEvent}`;
@@ -21498,6 +21513,8 @@ function useDataDnd(args) {
21498
21513
  } else {
21499
21514
  dndLog.warn("dragEnd:cross-container:no-dropEvent-on-target", { targetGroup: targetMeta.group });
21500
21515
  }
21516
+ emitPositions(sourceMeta);
21517
+ emitPositions(targetMeta);
21501
21518
  return;
21502
21519
  }
21503
21520
  if (oldIndex === newIndex) {
@@ -21520,6 +21537,7 @@ function useDataDnd(args) {
21520
21537
  } else {
21521
21538
  dndLog.debug("dragEnd:reorder:no-reorderEvent", { sourceGroup: sourceMeta.group });
21522
21539
  }
21540
+ emitPositions(sourceMeta);
21523
21541
  },
21524
21542
  [eventBus]
21525
21543
  );
@@ -21824,6 +21842,7 @@ function DataGrid({
21824
21842
  sortable,
21825
21843
  dropEvent,
21826
21844
  reorderEvent,
21845
+ positionEvent,
21827
21846
  dndItemIdField,
21828
21847
  dndRoot
21829
21848
  }) {
@@ -21841,6 +21860,7 @@ function DataGrid({
21841
21860
  sortable,
21842
21861
  dropEvent,
21843
21862
  reorderEvent,
21863
+ positionEvent,
21844
21864
  dndItemIdField,
21845
21865
  dndRoot
21846
21866
  });
@@ -22233,6 +22253,7 @@ function DataList({
22233
22253
  sortable: sortableProp,
22234
22254
  dropEvent,
22235
22255
  reorderEvent: dndReorderEvent,
22256
+ positionEvent,
22236
22257
  dndItemIdField,
22237
22258
  dndRoot
22238
22259
  }) {
@@ -22249,6 +22270,7 @@ function DataList({
22249
22270
  sortable: sortableProp,
22250
22271
  dropEvent,
22251
22272
  reorderEvent: dndReorderEvent,
22273
+ positionEvent,
22252
22274
  dndItemIdField,
22253
22275
  dndRoot
22254
22276
  });
@@ -21279,6 +21279,7 @@ function useDataDnd(args) {
21279
21279
  sortable,
21280
21280
  dropEvent,
21281
21281
  reorderEvent,
21282
+ positionEvent,
21282
21283
  dndItemIdField = "id",
21283
21284
  dndRoot,
21284
21285
  items,
@@ -21346,8 +21347,8 @@ function useDataDnd(args) {
21346
21347
  const [activeDrag, setActiveDrag] = React81__default.useState(null);
21347
21348
  const [overZoneGroup, setOverZoneGroup] = React81__default.useState(null);
21348
21349
  const meta = React81__default.useMemo(
21349
- () => ({ group: ownGroup, dropEvent, reorderEvent, itemIds, rawItems: items, idField: dndItemIdField }),
21350
- [ownGroup, dropEvent, reorderEvent, itemIds, items, dndItemIdField]
21350
+ () => ({ group: ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, rawItems: items, idField: dndItemIdField }),
21351
+ [ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, items, dndItemIdField]
21351
21352
  );
21352
21353
  React81__default.useEffect(() => {
21353
21354
  const target = isRoot ? null : parentRoot;
@@ -21433,6 +21434,20 @@ function useDataDnd(args) {
21433
21434
  dndLog.warn("dragEnd:abort:no-zone-resolved", { activeId: active.id, hasSource: !!sourceMeta, hasTarget: !!targetMeta });
21434
21435
  return;
21435
21436
  }
21437
+ const emitPositions = (zoneMeta) => {
21438
+ if (!zoneMeta.positionEvent) {
21439
+ dndLog.debug("dragEnd:positions:no-event", { group: zoneMeta.group });
21440
+ return;
21441
+ }
21442
+ const evt = `UI:${zoneMeta.positionEvent}`;
21443
+ const order = optimisticOrdersRef.current.get(zoneMeta.group) ?? zoneMeta.rawItems;
21444
+ order.forEach((it, idx) => {
21445
+ const id = String(it[zoneMeta.idField]);
21446
+ const position = idx * 1e3;
21447
+ eventBus.emit(evt, { id, position });
21448
+ });
21449
+ dndLog.info("dragEnd:positions:emitted", { event: evt, group: zoneMeta.group, count: order.length });
21450
+ };
21436
21451
  if (sourceMeta.group !== targetMeta.group) {
21437
21452
  if (targetMeta.dropEvent) {
21438
21453
  const evt = `UI:${targetMeta.dropEvent}`;
@@ -21452,6 +21467,8 @@ function useDataDnd(args) {
21452
21467
  } else {
21453
21468
  dndLog.warn("dragEnd:cross-container:no-dropEvent-on-target", { targetGroup: targetMeta.group });
21454
21469
  }
21470
+ emitPositions(sourceMeta);
21471
+ emitPositions(targetMeta);
21455
21472
  return;
21456
21473
  }
21457
21474
  if (oldIndex === newIndex) {
@@ -21474,6 +21491,7 @@ function useDataDnd(args) {
21474
21491
  } else {
21475
21492
  dndLog.debug("dragEnd:reorder:no-reorderEvent", { sourceGroup: sourceMeta.group });
21476
21493
  }
21494
+ emitPositions(sourceMeta);
21477
21495
  },
21478
21496
  [eventBus]
21479
21497
  );
@@ -21778,6 +21796,7 @@ function DataGrid({
21778
21796
  sortable,
21779
21797
  dropEvent,
21780
21798
  reorderEvent,
21799
+ positionEvent,
21781
21800
  dndItemIdField,
21782
21801
  dndRoot
21783
21802
  }) {
@@ -21795,6 +21814,7 @@ function DataGrid({
21795
21814
  sortable,
21796
21815
  dropEvent,
21797
21816
  reorderEvent,
21817
+ positionEvent,
21798
21818
  dndItemIdField,
21799
21819
  dndRoot
21800
21820
  });
@@ -22187,6 +22207,7 @@ function DataList({
22187
22207
  sortable: sortableProp,
22188
22208
  dropEvent,
22189
22209
  reorderEvent: dndReorderEvent,
22210
+ positionEvent,
22190
22211
  dndItemIdField,
22191
22212
  dndRoot
22192
22213
  }) {
@@ -22203,6 +22224,7 @@ function DataList({
22203
22224
  sortable: sortableProp,
22204
22225
  dropEvent,
22205
22226
  reorderEvent: dndReorderEvent,
22227
+ positionEvent,
22206
22228
  dndItemIdField,
22207
22229
  dndRoot
22208
22230
  });
@@ -21094,6 +21094,7 @@ function useDataDnd(args) {
21094
21094
  sortable: sortable$1,
21095
21095
  dropEvent,
21096
21096
  reorderEvent,
21097
+ positionEvent,
21097
21098
  dndItemIdField = "id",
21098
21099
  dndRoot,
21099
21100
  items,
@@ -21161,8 +21162,8 @@ function useDataDnd(args) {
21161
21162
  const [activeDrag, setActiveDrag] = React80__namespace.default.useState(null);
21162
21163
  const [overZoneGroup, setOverZoneGroup] = React80__namespace.default.useState(null);
21163
21164
  const meta = React80__namespace.default.useMemo(
21164
- () => ({ group: ownGroup, dropEvent, reorderEvent, itemIds, rawItems: items, idField: dndItemIdField }),
21165
- [ownGroup, dropEvent, reorderEvent, itemIds, items, dndItemIdField]
21165
+ () => ({ group: ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, rawItems: items, idField: dndItemIdField }),
21166
+ [ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, items, dndItemIdField]
21166
21167
  );
21167
21168
  React80__namespace.default.useEffect(() => {
21168
21169
  const target = isRoot ? null : parentRoot;
@@ -21248,6 +21249,20 @@ function useDataDnd(args) {
21248
21249
  dndLog.warn("dragEnd:abort:no-zone-resolved", { activeId: active.id, hasSource: !!sourceMeta, hasTarget: !!targetMeta });
21249
21250
  return;
21250
21251
  }
21252
+ const emitPositions = (zoneMeta) => {
21253
+ if (!zoneMeta.positionEvent) {
21254
+ dndLog.debug("dragEnd:positions:no-event", { group: zoneMeta.group });
21255
+ return;
21256
+ }
21257
+ const evt = `UI:${zoneMeta.positionEvent}`;
21258
+ const order = optimisticOrdersRef.current.get(zoneMeta.group) ?? zoneMeta.rawItems;
21259
+ order.forEach((it, idx) => {
21260
+ const id = String(it[zoneMeta.idField]);
21261
+ const position = idx * 1e3;
21262
+ eventBus.emit(evt, { id, position });
21263
+ });
21264
+ dndLog.info("dragEnd:positions:emitted", { event: evt, group: zoneMeta.group, count: order.length });
21265
+ };
21251
21266
  if (sourceMeta.group !== targetMeta.group) {
21252
21267
  if (targetMeta.dropEvent) {
21253
21268
  const evt = `UI:${targetMeta.dropEvent}`;
@@ -21267,6 +21282,8 @@ function useDataDnd(args) {
21267
21282
  } else {
21268
21283
  dndLog.warn("dragEnd:cross-container:no-dropEvent-on-target", { targetGroup: targetMeta.group });
21269
21284
  }
21285
+ emitPositions(sourceMeta);
21286
+ emitPositions(targetMeta);
21270
21287
  return;
21271
21288
  }
21272
21289
  if (oldIndex === newIndex) {
@@ -21289,6 +21306,7 @@ function useDataDnd(args) {
21289
21306
  } else {
21290
21307
  dndLog.debug("dragEnd:reorder:no-reorderEvent", { sourceGroup: sourceMeta.group });
21291
21308
  }
21309
+ emitPositions(sourceMeta);
21292
21310
  },
21293
21311
  [eventBus]
21294
21312
  );
@@ -21593,6 +21611,7 @@ function DataGrid({
21593
21611
  sortable,
21594
21612
  dropEvent,
21595
21613
  reorderEvent,
21614
+ positionEvent,
21596
21615
  dndItemIdField,
21597
21616
  dndRoot
21598
21617
  }) {
@@ -21610,6 +21629,7 @@ function DataGrid({
21610
21629
  sortable,
21611
21630
  dropEvent,
21612
21631
  reorderEvent,
21632
+ positionEvent,
21613
21633
  dndItemIdField,
21614
21634
  dndRoot
21615
21635
  });
@@ -22002,6 +22022,7 @@ function DataList({
22002
22022
  sortable: sortableProp,
22003
22023
  dropEvent,
22004
22024
  reorderEvent: dndReorderEvent,
22025
+ positionEvent,
22005
22026
  dndItemIdField,
22006
22027
  dndRoot
22007
22028
  }) {
@@ -22018,6 +22039,7 @@ function DataList({
22018
22039
  sortable: sortableProp,
22019
22040
  dropEvent,
22020
22041
  reorderEvent: dndReorderEvent,
22042
+ positionEvent,
22021
22043
  dndItemIdField,
22022
22044
  dndRoot
22023
22045
  });
@@ -21048,6 +21048,7 @@ function useDataDnd(args) {
21048
21048
  sortable,
21049
21049
  dropEvent,
21050
21050
  reorderEvent,
21051
+ positionEvent,
21051
21052
  dndItemIdField = "id",
21052
21053
  dndRoot,
21053
21054
  items,
@@ -21115,8 +21116,8 @@ function useDataDnd(args) {
21115
21116
  const [activeDrag, setActiveDrag] = React80__default.useState(null);
21116
21117
  const [overZoneGroup, setOverZoneGroup] = React80__default.useState(null);
21117
21118
  const meta = React80__default.useMemo(
21118
- () => ({ group: ownGroup, dropEvent, reorderEvent, itemIds, rawItems: items, idField: dndItemIdField }),
21119
- [ownGroup, dropEvent, reorderEvent, itemIds, items, dndItemIdField]
21119
+ () => ({ group: ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, rawItems: items, idField: dndItemIdField }),
21120
+ [ownGroup, dropEvent, reorderEvent, positionEvent, itemIds, items, dndItemIdField]
21120
21121
  );
21121
21122
  React80__default.useEffect(() => {
21122
21123
  const target = isRoot ? null : parentRoot;
@@ -21202,6 +21203,20 @@ function useDataDnd(args) {
21202
21203
  dndLog.warn("dragEnd:abort:no-zone-resolved", { activeId: active.id, hasSource: !!sourceMeta, hasTarget: !!targetMeta });
21203
21204
  return;
21204
21205
  }
21206
+ const emitPositions = (zoneMeta) => {
21207
+ if (!zoneMeta.positionEvent) {
21208
+ dndLog.debug("dragEnd:positions:no-event", { group: zoneMeta.group });
21209
+ return;
21210
+ }
21211
+ const evt = `UI:${zoneMeta.positionEvent}`;
21212
+ const order = optimisticOrdersRef.current.get(zoneMeta.group) ?? zoneMeta.rawItems;
21213
+ order.forEach((it, idx) => {
21214
+ const id = String(it[zoneMeta.idField]);
21215
+ const position = idx * 1e3;
21216
+ eventBus.emit(evt, { id, position });
21217
+ });
21218
+ dndLog.info("dragEnd:positions:emitted", { event: evt, group: zoneMeta.group, count: order.length });
21219
+ };
21205
21220
  if (sourceMeta.group !== targetMeta.group) {
21206
21221
  if (targetMeta.dropEvent) {
21207
21222
  const evt = `UI:${targetMeta.dropEvent}`;
@@ -21221,6 +21236,8 @@ function useDataDnd(args) {
21221
21236
  } else {
21222
21237
  dndLog.warn("dragEnd:cross-container:no-dropEvent-on-target", { targetGroup: targetMeta.group });
21223
21238
  }
21239
+ emitPositions(sourceMeta);
21240
+ emitPositions(targetMeta);
21224
21241
  return;
21225
21242
  }
21226
21243
  if (oldIndex === newIndex) {
@@ -21243,6 +21260,7 @@ function useDataDnd(args) {
21243
21260
  } else {
21244
21261
  dndLog.debug("dragEnd:reorder:no-reorderEvent", { sourceGroup: sourceMeta.group });
21245
21262
  }
21263
+ emitPositions(sourceMeta);
21246
21264
  },
21247
21265
  [eventBus]
21248
21266
  );
@@ -21547,6 +21565,7 @@ function DataGrid({
21547
21565
  sortable,
21548
21566
  dropEvent,
21549
21567
  reorderEvent,
21568
+ positionEvent,
21550
21569
  dndItemIdField,
21551
21570
  dndRoot
21552
21571
  }) {
@@ -21564,6 +21583,7 @@ function DataGrid({
21564
21583
  sortable,
21565
21584
  dropEvent,
21566
21585
  reorderEvent,
21586
+ positionEvent,
21567
21587
  dndItemIdField,
21568
21588
  dndRoot
21569
21589
  });
@@ -21956,6 +21976,7 @@ function DataList({
21956
21976
  sortable: sortableProp,
21957
21977
  dropEvent,
21958
21978
  reorderEvent: dndReorderEvent,
21979
+ positionEvent,
21959
21980
  dndItemIdField,
21960
21981
  dndRoot
21961
21982
  }) {
@@ -21972,6 +21993,7 @@ function DataList({
21972
21993
  sortable: sortableProp,
21973
21994
  dropEvent,
21974
21995
  reorderEvent: dndReorderEvent,
21996
+ positionEvent,
21975
21997
  dndItemIdField,
21976
21998
  dndRoot
21977
21999
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almadar/ui",
3
- "version": "4.50.17",
3
+ "version": "4.50.19",
4
4
  "description": "React UI components, hooks, and providers for Almadar",
5
5
  "type": "module",
6
6
  "sideEffects": [