@vendure/dashboard 3.5.2-master-202512170238 → 3.5.2-master-202512190240
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.
- package/dist/plugin/constants.js +21 -2
- package/dist/plugin/dashboard.plugin.js +1 -1
- package/package.json +3 -3
- package/src/app/routeTree.gen.ts +1135 -1072
- package/src/app/routes/_authenticated/_collections/collections.graphql.ts +1 -0
- package/src/app/routes/_authenticated/_collections/collections.tsx +249 -167
- package/src/app/routes/_authenticated/_collections/components/collection-bulk-actions.tsx +8 -0
- package/src/app/routes/_authenticated/_collections/components/move-collections-dialog.tsx +4 -0
- package/src/app/routes/_authenticated/_facets/components/facet-values-sheet.tsx +4 -1
- package/src/app/routes/_authenticated/_facets/components/facet-values-table.tsx +1 -1
- package/src/app/routes/_authenticated/_facets/facets.tsx +22 -38
- package/src/app/routes/_authenticated/_orders/components/order-table-totals.tsx +16 -1
- package/src/app/routes/_authenticated/_product-variants/product-variants.graphql.ts +0 -1
- package/src/app/routes/_authenticated/_product-variants/product-variants_.$id.tsx +2 -2
- package/src/app/routes/_authenticated/_products/products.graphql.ts +5 -0
- package/src/app/routes/_authenticated/_products/products_.$id.tsx +24 -1
- package/src/app/routes/_authenticated/_system/components/payload-dialog.tsx +9 -2
- package/src/app/routes/_authenticated/_system/job-queue.tsx +11 -2
- package/src/app/routes/_authenticated/_tax-rates/tax-rates_.$id.tsx +2 -9
- package/src/app/routes/_authenticated/_zones/zones.tsx +1 -0
- package/src/i18n/locales/ar.po +177 -141
- package/src/i18n/locales/cs.po +177 -141
- package/src/i18n/locales/de.po +177 -141
- package/src/i18n/locales/en.po +177 -141
- package/src/i18n/locales/es.po +177 -141
- package/src/i18n/locales/fa.po +177 -141
- package/src/i18n/locales/fr.po +177 -141
- package/src/i18n/locales/he.po +177 -141
- package/src/i18n/locales/hr.po +177 -141
- package/src/i18n/locales/it.po +177 -141
- package/src/i18n/locales/ja.po +177 -141
- package/src/i18n/locales/nb.po +177 -141
- package/src/i18n/locales/ne.po +177 -141
- package/src/i18n/locales/pl.po +177 -141
- package/src/i18n/locales/pt_BR.po +177 -141
- package/src/i18n/locales/pt_PT.po +177 -141
- package/src/i18n/locales/ru.po +177 -141
- package/src/i18n/locales/sv.po +177 -141
- package/src/i18n/locales/tr.po +177 -141
- package/src/i18n/locales/uk.po +177 -141
- package/src/i18n/locales/zh_Hans.po +177 -141
- package/src/i18n/locales/zh_Hant.po +177 -141
- package/src/lib/components/data-input/number-input.tsx +24 -5
- package/src/lib/components/data-table/data-table-context.tsx +18 -3
- package/src/lib/components/data-table/data-table-utils.ts +241 -1
- package/src/lib/components/data-table/data-table.tsx +189 -60
- package/src/lib/components/data-table/global-views-bar.tsx +1 -1
- package/src/lib/components/data-table/save-view-dialog.tsx +21 -0
- package/src/lib/components/data-table/use-generated-columns.tsx +56 -24
- package/src/lib/components/data-table/views-sheet.tsx +1 -1
- package/src/lib/components/layout/channel-switcher.tsx +7 -5
- package/src/lib/components/layout/nav-main.tsx +2 -2
- package/src/lib/components/shared/alerts.tsx +3 -1
- package/src/lib/components/shared/assign-to-channel-bulk-action.tsx +10 -10
- package/src/lib/components/shared/assign-to-channel-dialog.tsx +1 -1
- package/src/lib/components/shared/assigned-channels.tsx +108 -0
- package/src/lib/components/shared/assigned-facet-values.tsx +5 -7
- package/src/lib/components/shared/channel-chip.tsx +43 -0
- package/src/lib/components/shared/paginated-list-data-table.tsx +19 -0
- package/src/lib/components/ui/alert.tsx +1 -1
- package/src/lib/components/ui/dropdown-menu.tsx +4 -1
- package/src/lib/components/ui/sidebar.tsx +2 -1
- package/src/lib/framework/page/list-page.tsx +62 -38
- package/src/lib/hooks/use-drag-and-drop.ts +86 -0
- package/src/lib/hooks/use-saved-views.ts +1 -0
- package/src/lib/providers/channel-provider.tsx +7 -1
- package/src/lib/types/saved-views.ts +3 -0
|
@@ -3,11 +3,14 @@ import { Input } from '@/vdb/components/ui/input.js';
|
|
|
3
3
|
|
|
4
4
|
import { DashboardFormComponentProps } from '@/vdb/framework/form-engine/form-engine-types.js';
|
|
5
5
|
import { isReadonlyField } from '@/vdb/framework/form-engine/utils.js';
|
|
6
|
+
import { ReactNode } from 'react';
|
|
6
7
|
|
|
7
8
|
export type NumberInputProps = DashboardFormComponentProps & {
|
|
8
9
|
min?: number;
|
|
9
10
|
max?: number;
|
|
10
11
|
step?: number;
|
|
12
|
+
prefix?: ReactNode;
|
|
13
|
+
suffix?: ReactNode;
|
|
11
14
|
};
|
|
12
15
|
|
|
13
16
|
/**
|
|
@@ -17,28 +20,43 @@ export type NumberInputProps = DashboardFormComponentProps & {
|
|
|
17
20
|
* @docsCategory form-components
|
|
18
21
|
* @docsPage NumberInput
|
|
19
22
|
*/
|
|
20
|
-
export function NumberInput({
|
|
23
|
+
export function NumberInput({
|
|
24
|
+
fieldDef,
|
|
25
|
+
onChange,
|
|
26
|
+
prefix: overridePrefix,
|
|
27
|
+
suffix: overrideSuffix,
|
|
28
|
+
...fieldProps
|
|
29
|
+
}: Readonly<NumberInputProps>) {
|
|
21
30
|
const readOnly = fieldProps.disabled || isReadonlyField(fieldDef);
|
|
22
31
|
const isFloat = fieldDef ? fieldDef.type === 'float' : false;
|
|
23
32
|
const min = fieldProps.min ?? fieldDef?.ui?.min;
|
|
24
33
|
const max = fieldProps.max ?? fieldDef?.ui?.max;
|
|
25
34
|
const step = fieldProps.step ?? (fieldDef?.ui?.step || (isFloat ? 0.01 : 1));
|
|
26
|
-
const prefix = fieldDef?.ui?.prefix;
|
|
27
|
-
const suffix = fieldDef?.ui?.suffix;
|
|
35
|
+
const prefix = overridePrefix ?? fieldDef?.ui?.prefix;
|
|
36
|
+
const suffix = overrideSuffix ?? fieldDef?.ui?.suffix;
|
|
28
37
|
const shouldUseAffixedInput = prefix || suffix;
|
|
38
|
+
const value = fieldProps.value ?? '';
|
|
29
39
|
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
30
40
|
if (readOnly) return;
|
|
31
|
-
|
|
41
|
+
|
|
42
|
+
let numValue = e.target.valueAsNumber;
|
|
43
|
+
|
|
44
|
+
if (Number.isNaN(numValue) && e.target.value) {
|
|
45
|
+
const normalized = e.target.value.replace(',', '.');
|
|
46
|
+
numValue = Number(normalized);
|
|
47
|
+
}
|
|
48
|
+
|
|
32
49
|
if (Number.isNaN(numValue)) {
|
|
33
50
|
onChange(null);
|
|
34
51
|
} else {
|
|
35
|
-
onChange(
|
|
52
|
+
onChange(numValue);
|
|
36
53
|
}
|
|
37
54
|
};
|
|
38
55
|
if (shouldUseAffixedInput) {
|
|
39
56
|
return (
|
|
40
57
|
<AffixedInput
|
|
41
58
|
{...fieldProps}
|
|
59
|
+
value={value}
|
|
42
60
|
type="number"
|
|
43
61
|
onChange={handleChange}
|
|
44
62
|
min={min}
|
|
@@ -57,6 +75,7 @@ export function NumberInput({ fieldDef, onChange, ...fieldProps }: Readonly<Numb
|
|
|
57
75
|
type="number"
|
|
58
76
|
onChange={handleChange}
|
|
59
77
|
{...fieldProps}
|
|
78
|
+
value={value}
|
|
60
79
|
min={min}
|
|
61
80
|
max={max}
|
|
62
81
|
step={step}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
|
|
2
|
+
import { useUserSettings } from '@/vdb/hooks/use-user-settings.js';
|
|
3
3
|
import { ColumnFiltersState, SortingState, Table } from '@tanstack/react-table';
|
|
4
4
|
import React, { createContext, ReactNode, useContext } from 'react';
|
|
5
5
|
|
|
6
|
+
export type ColumnConfig = { columnOrder: string[]; columnVisibility: Record<string, boolean> };
|
|
7
|
+
|
|
6
8
|
interface DataTableContextValue {
|
|
7
9
|
columnFilters: ColumnFiltersState;
|
|
8
10
|
setColumnFilters: React.Dispatch<React.SetStateAction<ColumnFiltersState>>;
|
|
@@ -16,7 +18,7 @@ interface DataTableContextValue {
|
|
|
16
18
|
onRefresh?: () => void;
|
|
17
19
|
isLoading?: boolean;
|
|
18
20
|
table?: Table<any>;
|
|
19
|
-
handleApplyView: (filters: ColumnFiltersState, searchTerm?: string) => void;
|
|
21
|
+
handleApplyView: (filters: ColumnFiltersState, columnConfig: ColumnConfig, searchTerm?: string) => void;
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
const DataTableContext = createContext<DataTableContextValue | undefined>(undefined);
|
|
@@ -52,7 +54,13 @@ export function DataTableProvider({
|
|
|
52
54
|
isLoading,
|
|
53
55
|
table,
|
|
54
56
|
}: DataTableProviderProps) {
|
|
55
|
-
const
|
|
57
|
+
const { setTableSettings } = useUserSettings();
|
|
58
|
+
|
|
59
|
+
const handleApplyView = (
|
|
60
|
+
filters: ColumnFiltersState,
|
|
61
|
+
columnConfig: ColumnConfig,
|
|
62
|
+
viewSearchTerm?: string,
|
|
63
|
+
) => {
|
|
56
64
|
setColumnFilters(filters);
|
|
57
65
|
if (viewSearchTerm !== undefined && onSearchTermChange) {
|
|
58
66
|
setSearchTerm(viewSearchTerm);
|
|
@@ -61,6 +69,13 @@ export function DataTableProvider({
|
|
|
61
69
|
if (onFilterChange && table) {
|
|
62
70
|
onFilterChange(table, filters);
|
|
63
71
|
}
|
|
72
|
+
|
|
73
|
+
if (pageId && columnConfig.columnOrder) {
|
|
74
|
+
setTableSettings(pageId, 'columnOrder', columnConfig.columnOrder);
|
|
75
|
+
}
|
|
76
|
+
if (pageId && columnConfig.columnVisibility) {
|
|
77
|
+
setTableSettings(pageId, 'columnVisibility', columnConfig.columnVisibility);
|
|
78
|
+
}
|
|
64
79
|
};
|
|
65
80
|
|
|
66
81
|
const value: DataTableContextValue = {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AccessorFnColumnDef } from '@tanstack/react-table';
|
|
1
|
+
import { AccessorFnColumnDef, ExpandedState } from '@tanstack/react-table';
|
|
2
2
|
import { AccessorKeyColumnDef } from '@tanstack/table-core';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -49,3 +49,243 @@ export function getStandardizedDefaultColumnOrder<T extends string | number | sy
|
|
|
49
49
|
const rest = defaultColumnOrder.filter(c => !standardFirstColumns.has(c as string));
|
|
50
50
|
return [...standardFirstColumns, ...rest] as T[];
|
|
51
51
|
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Hierarchical item type with parent-child relationships
|
|
55
|
+
*/
|
|
56
|
+
export interface HierarchicalItem {
|
|
57
|
+
id: string;
|
|
58
|
+
parentId?: string | null;
|
|
59
|
+
breadcrumbs?: Array<{ id: string }>;
|
|
60
|
+
children?: Array<{ id: string }> | null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Gets the parent ID of a hierarchical item
|
|
65
|
+
*/
|
|
66
|
+
export function getItemParentId<T extends HierarchicalItem>(
|
|
67
|
+
item: T | null | undefined,
|
|
68
|
+
): string | null | undefined {
|
|
69
|
+
return item?.parentId || item?.breadcrumbs?.[0]?.id;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Gets all siblings (items with the same parent) for a given parent ID
|
|
74
|
+
*/
|
|
75
|
+
export function getItemSiblings<T extends HierarchicalItem>(
|
|
76
|
+
items: T[],
|
|
77
|
+
parentId: string | null | undefined,
|
|
78
|
+
): T[] {
|
|
79
|
+
return items.filter(item => getItemParentId(item) === parentId);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Checks if moving an item to a new parent would create a circular reference
|
|
84
|
+
*/
|
|
85
|
+
export function isCircularReference<T extends HierarchicalItem>(
|
|
86
|
+
item: T,
|
|
87
|
+
targetParentId: string,
|
|
88
|
+
items: T[],
|
|
89
|
+
): boolean {
|
|
90
|
+
const targetParentItem = items.find(i => i.id === targetParentId);
|
|
91
|
+
return (
|
|
92
|
+
item.children?.some(child => {
|
|
93
|
+
if (child.id === targetParentId) return true;
|
|
94
|
+
const targetBreadcrumbIds = targetParentItem?.breadcrumbs?.map(b => b.id) || [];
|
|
95
|
+
return targetBreadcrumbIds.includes(item.id);
|
|
96
|
+
}) ?? false
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Result of calculating the target position for a drag and drop operation
|
|
102
|
+
*/
|
|
103
|
+
export interface TargetPosition {
|
|
104
|
+
targetParentId: string;
|
|
105
|
+
adjustedIndex: number;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Context for drag and drop position calculation
|
|
110
|
+
*/
|
|
111
|
+
interface DragContext<T extends HierarchicalItem> {
|
|
112
|
+
item: T;
|
|
113
|
+
targetItem: T | undefined;
|
|
114
|
+
previousItem: T | null;
|
|
115
|
+
isDraggingDown: boolean;
|
|
116
|
+
isTargetExpanded: boolean;
|
|
117
|
+
isPreviousExpanded: boolean;
|
|
118
|
+
sourceParentId: string;
|
|
119
|
+
items: T[];
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Checks if dragging down directly onto an expanded item
|
|
124
|
+
*/
|
|
125
|
+
function isDroppingIntoExpandedTarget<T extends HierarchicalItem>(context: DragContext<T>): boolean {
|
|
126
|
+
const { isDraggingDown, targetItem, item, isTargetExpanded } = context;
|
|
127
|
+
return isDraggingDown && targetItem?.id !== item.id && isTargetExpanded;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Checks if dragging down into an expanded item's children area
|
|
132
|
+
*/
|
|
133
|
+
function isDroppingIntoExpandedPreviousChildren<T extends HierarchicalItem>(
|
|
134
|
+
context: DragContext<T>,
|
|
135
|
+
): boolean {
|
|
136
|
+
const { isDraggingDown, targetItem, previousItem, item, isPreviousExpanded } = context;
|
|
137
|
+
return (
|
|
138
|
+
isDraggingDown &&
|
|
139
|
+
previousItem !== null &&
|
|
140
|
+
targetItem?.id !== item.id &&
|
|
141
|
+
isPreviousExpanded &&
|
|
142
|
+
targetItem?.parentId === previousItem.id
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Checks if dragging up into an expanded item's children area
|
|
148
|
+
*/
|
|
149
|
+
function isDroppingIntoExpandedPreviousWhenDraggingUp<T extends HierarchicalItem>(
|
|
150
|
+
context: DragContext<T>,
|
|
151
|
+
): boolean {
|
|
152
|
+
const { isDraggingDown, previousItem, isPreviousExpanded } = context;
|
|
153
|
+
return !isDraggingDown && previousItem !== null && isPreviousExpanded;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Creates a position for dropping into an expanded item as first child
|
|
158
|
+
*/
|
|
159
|
+
function createFirstChildPosition(parentId: string): TargetPosition {
|
|
160
|
+
return { targetParentId: parentId, adjustedIndex: 0 };
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Calculates position for cross-parent drag operations
|
|
165
|
+
*/
|
|
166
|
+
function calculateCrossParentPosition<T extends HierarchicalItem>(
|
|
167
|
+
targetItem: T,
|
|
168
|
+
sourceParentId: string,
|
|
169
|
+
items: T[],
|
|
170
|
+
): TargetPosition | null {
|
|
171
|
+
const targetItemParentId = getItemParentId(targetItem);
|
|
172
|
+
|
|
173
|
+
if (!targetItemParentId || targetItemParentId === sourceParentId) {
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const targetSiblings = getItemSiblings(items, targetItemParentId);
|
|
178
|
+
const adjustedIndex = targetSiblings.findIndex(i => i.id === targetItem.id);
|
|
179
|
+
|
|
180
|
+
return { targetParentId: targetItemParentId, adjustedIndex };
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Calculates position when dropping at the end of the list
|
|
185
|
+
*/
|
|
186
|
+
function calculateDropAtEndPosition<T extends HierarchicalItem>(
|
|
187
|
+
previousItem: T | null,
|
|
188
|
+
sourceParentId: string,
|
|
189
|
+
items: T[],
|
|
190
|
+
): TargetPosition | null {
|
|
191
|
+
if (!previousItem) {
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const previousItemParentId = getItemParentId(previousItem);
|
|
196
|
+
|
|
197
|
+
if (!previousItemParentId || previousItemParentId === sourceParentId) {
|
|
198
|
+
return null;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const targetSiblings = getItemSiblings(items, previousItemParentId);
|
|
202
|
+
return { targetParentId: previousItemParentId, adjustedIndex: targetSiblings.length };
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Determines the target parent and index for a hierarchical drag and drop operation
|
|
207
|
+
*/
|
|
208
|
+
export function calculateDragTargetPosition<T extends HierarchicalItem>(params: {
|
|
209
|
+
item: T;
|
|
210
|
+
oldIndex: number;
|
|
211
|
+
newIndex: number;
|
|
212
|
+
items: T[];
|
|
213
|
+
sourceParentId: string;
|
|
214
|
+
expanded: ExpandedState;
|
|
215
|
+
}): TargetPosition {
|
|
216
|
+
const { item, oldIndex, newIndex, items, sourceParentId, expanded } = params;
|
|
217
|
+
|
|
218
|
+
const targetItem = items[newIndex];
|
|
219
|
+
const previousItem = newIndex > 0 ? items[newIndex - 1] : null;
|
|
220
|
+
|
|
221
|
+
const context: DragContext<T> = {
|
|
222
|
+
item,
|
|
223
|
+
targetItem,
|
|
224
|
+
previousItem,
|
|
225
|
+
isDraggingDown: oldIndex < newIndex,
|
|
226
|
+
isTargetExpanded: targetItem ? !!expanded[targetItem.id as keyof ExpandedState] : false,
|
|
227
|
+
isPreviousExpanded: previousItem ? !!expanded[previousItem.id as keyof ExpandedState] : false,
|
|
228
|
+
sourceParentId,
|
|
229
|
+
items,
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
// Handle dropping into expanded items (becomes first child)
|
|
233
|
+
if (isDroppingIntoExpandedTarget(context)) {
|
|
234
|
+
return createFirstChildPosition(targetItem.id);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (previousItem && isDroppingIntoExpandedPreviousChildren(context)) {
|
|
238
|
+
return createFirstChildPosition(previousItem.id);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (previousItem && isDroppingIntoExpandedPreviousWhenDraggingUp(context)) {
|
|
242
|
+
return createFirstChildPosition(previousItem.id);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Handle cross-parent drag operations
|
|
246
|
+
if (targetItem?.id !== item.id) {
|
|
247
|
+
const crossParentPosition = calculateCrossParentPosition(targetItem, sourceParentId, items);
|
|
248
|
+
if (crossParentPosition) {
|
|
249
|
+
return crossParentPosition;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Handle dropping at the end of the list
|
|
254
|
+
if (!targetItem && previousItem) {
|
|
255
|
+
const dropAtEndPosition = calculateDropAtEndPosition(previousItem, sourceParentId, items);
|
|
256
|
+
if (dropAtEndPosition) {
|
|
257
|
+
return dropAtEndPosition;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Default: stay in the same parent at the beginning
|
|
262
|
+
return { targetParentId: sourceParentId, adjustedIndex: 0 };
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Calculates the adjusted sibling index when reordering within the same parent
|
|
267
|
+
*/
|
|
268
|
+
export function calculateSiblingIndex<T extends HierarchicalItem>(params: {
|
|
269
|
+
item: T;
|
|
270
|
+
oldIndex: number;
|
|
271
|
+
newIndex: number;
|
|
272
|
+
items: T[];
|
|
273
|
+
parentId: string;
|
|
274
|
+
}): number {
|
|
275
|
+
const { item, oldIndex, newIndex, items, parentId } = params;
|
|
276
|
+
|
|
277
|
+
const siblings = getItemSiblings(items, parentId);
|
|
278
|
+
const oldSiblingIndex = siblings.findIndex(i => i.id === item.id);
|
|
279
|
+
const isDraggingDown = oldIndex < newIndex;
|
|
280
|
+
|
|
281
|
+
let newSiblingIndex = oldSiblingIndex;
|
|
282
|
+
const [start, end] = isDraggingDown ? [oldIndex + 1, newIndex] : [newIndex, oldIndex - 1];
|
|
283
|
+
|
|
284
|
+
for (let i = start; i <= end; i++) {
|
|
285
|
+
if (getItemParentId(items[i]) === parentId) {
|
|
286
|
+
newSiblingIndex += isDraggingDown ? 1 : -1;
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
return newSiblingIndex;
|
|
291
|
+
}
|