@blockbite/libraries 0.11.7 → 0.12.1
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/Sortable.d.ts +27 -0
- package/dist/index.css +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/libraries.js +4167 -1057
- package/dist/libraries.js.map +1 -1
- package/dist/libraries.umd.cjs +14 -5
- package/dist/libraries.umd.cjs.map +1 -1
- package/dist/react-shim.d.ts +19 -0
- package/package.json +8 -3
- package/src/Sortable.tsx +257 -0
- package/src/index.ts +4 -1
- package/src/react-shim.d.ts +19 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
declare module '../@wordpress/element' {
|
|
2
|
+
export * from '@wordpress/element';
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
declare module '../@wordpress/element/jsx-runtime' {
|
|
6
|
+
export const jsx: any;
|
|
7
|
+
export const jsxs: any;
|
|
8
|
+
export const jsxDEV: any;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
declare module 'react' {
|
|
12
|
+
import React = require('wp.element');
|
|
13
|
+
export = React;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
declare module 'react/jsx-runtime' {
|
|
17
|
+
import * as ReactJSX from 'wp.element/jsx-runtime';
|
|
18
|
+
export = ReactJSX;
|
|
19
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blockbite/libraries",
|
|
3
3
|
"title": "react-bundled-libraries",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.12.1",
|
|
5
5
|
"website": "",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"type": "module",
|
|
@@ -23,14 +23,19 @@
|
|
|
23
23
|
"LICENSE"
|
|
24
24
|
],
|
|
25
25
|
"dependencies": {
|
|
26
|
+
"@dnd-kit/core": "^6.3.1",
|
|
27
|
+
"@dnd-kit/sortable": "^10.0.0",
|
|
28
|
+
"@dnd-kit/utilities": "^3.2.2",
|
|
26
29
|
"@tailwindcss/vite": "^4.1.11",
|
|
27
30
|
"@vitejs/plugin-react": "^5.0.0",
|
|
31
|
+
"@wordpress/element": "^6.36.0",
|
|
28
32
|
"allotment": "^1.20.4",
|
|
33
|
+
"classnames": "^2.5.1",
|
|
29
34
|
"react-grid-drag-resize": "^0.12.4",
|
|
30
35
|
"rollup-plugin-external-globals": "^0.13.0",
|
|
31
36
|
"vite-plugin-dts": "^4.5.3",
|
|
32
|
-
"@blockbite/shared-utils": "2.
|
|
33
|
-
"@blockbite/types": "0.
|
|
37
|
+
"@blockbite/shared-utils": "2.1.1",
|
|
38
|
+
"@blockbite/types": "0.2.0"
|
|
34
39
|
},
|
|
35
40
|
"peerDependencies": {
|
|
36
41
|
"tailwindcss": "^4.0.0",
|
package/src/Sortable.tsx
ADDED
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import {
|
|
2
|
+
closestCenter,
|
|
3
|
+
DndContext,
|
|
4
|
+
DragOverlay,
|
|
5
|
+
KeyboardSensor,
|
|
6
|
+
PointerSensor,
|
|
7
|
+
useSensor,
|
|
8
|
+
useSensors,
|
|
9
|
+
type DragEndEvent,
|
|
10
|
+
type DragStartEvent,
|
|
11
|
+
type UniqueIdentifier,
|
|
12
|
+
} from '@dnd-kit/core';
|
|
13
|
+
import {
|
|
14
|
+
arrayMove,
|
|
15
|
+
SortableContext,
|
|
16
|
+
sortableKeyboardCoordinates,
|
|
17
|
+
useSortable,
|
|
18
|
+
verticalListSortingStrategy,
|
|
19
|
+
} from '@dnd-kit/sortable';
|
|
20
|
+
import { CSS } from '@dnd-kit/utilities';
|
|
21
|
+
import { useMemo, useState } from '@wordpress/element';
|
|
22
|
+
import classNames from 'classnames';
|
|
23
|
+
|
|
24
|
+
export type SortableListRenderCtx = {
|
|
25
|
+
/** Spread these on the element you want to use as the drag handle */
|
|
26
|
+
dragHandleProps: Record<string, any>;
|
|
27
|
+
/** True when this specific item is being dragged */
|
|
28
|
+
isDragging: boolean;
|
|
29
|
+
/** True when another item is being dragged over this one */
|
|
30
|
+
isDragOver: boolean;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export type SortableListProps<T> = {
|
|
34
|
+
items: T[];
|
|
35
|
+
onChange: (next: T[]) => void;
|
|
36
|
+
|
|
37
|
+
/** Must be stable across renders and reorders */
|
|
38
|
+
getId: (item: T) => UniqueIdentifier;
|
|
39
|
+
|
|
40
|
+
/** Render any component for the row */
|
|
41
|
+
renderItem: (item: T, ctx: SortableListRenderCtx) => React.ReactNode;
|
|
42
|
+
|
|
43
|
+
/** Optional: validate proposed new order; return string to block reorder */
|
|
44
|
+
validateReorder?: (next: T[]) => string | null;
|
|
45
|
+
|
|
46
|
+
/** Optional: render an error message somewhere */
|
|
47
|
+
renderError?: (msg: string) => React.ReactNode;
|
|
48
|
+
|
|
49
|
+
disabled?: boolean;
|
|
50
|
+
|
|
51
|
+
className?: string;
|
|
52
|
+
itemWrapperClassName?: string;
|
|
53
|
+
/** @deprecated No longer used with dnd-kit (uses CSS transforms instead) */
|
|
54
|
+
dragOverClassName?: string;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
type SortableItemProps<T> = {
|
|
58
|
+
id: UniqueIdentifier;
|
|
59
|
+
item: T;
|
|
60
|
+
renderItem: SortableListProps<T>['renderItem'];
|
|
61
|
+
disabled: boolean;
|
|
62
|
+
itemWrapperClassName?: string;
|
|
63
|
+
activeId: UniqueIdentifier | null;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
function SortableItem<T>({
|
|
67
|
+
id,
|
|
68
|
+
item,
|
|
69
|
+
renderItem,
|
|
70
|
+
disabled,
|
|
71
|
+
itemWrapperClassName,
|
|
72
|
+
activeId,
|
|
73
|
+
}: SortableItemProps<T>) {
|
|
74
|
+
const {
|
|
75
|
+
attributes,
|
|
76
|
+
listeners,
|
|
77
|
+
setNodeRef,
|
|
78
|
+
setActivatorNodeRef,
|
|
79
|
+
transform,
|
|
80
|
+
transition,
|
|
81
|
+
isDragging,
|
|
82
|
+
over,
|
|
83
|
+
} = useSortable({ id, disabled });
|
|
84
|
+
|
|
85
|
+
const style: React.CSSProperties = {
|
|
86
|
+
transform: CSS.Transform.toString(transform),
|
|
87
|
+
transition,
|
|
88
|
+
opacity: isDragging ? 0.5 : 1,
|
|
89
|
+
zIndex: isDragging ? 1 : 0,
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const isDragOver = over?.id === id && activeId !== id;
|
|
93
|
+
|
|
94
|
+
// Create drag handle props that can be spread on any element
|
|
95
|
+
const dragHandleProps = {
|
|
96
|
+
ref: setActivatorNodeRef,
|
|
97
|
+
...listeners,
|
|
98
|
+
...attributes,
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
return (
|
|
102
|
+
<div
|
|
103
|
+
ref={setNodeRef}
|
|
104
|
+
style={style}
|
|
105
|
+
className={classNames(itemWrapperClassName)}
|
|
106
|
+
data-sortable-wrapper="true"
|
|
107
|
+
>
|
|
108
|
+
{renderItem(item, { dragHandleProps, isDragging, isDragOver })}
|
|
109
|
+
</div>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Drag overlay item - rendered in a portal during drag
|
|
114
|
+
function DragOverlayItem<T>({
|
|
115
|
+
item,
|
|
116
|
+
renderItem,
|
|
117
|
+
itemWrapperClassName,
|
|
118
|
+
}: {
|
|
119
|
+
item: T;
|
|
120
|
+
renderItem: SortableListProps<T>['renderItem'];
|
|
121
|
+
itemWrapperClassName?: string;
|
|
122
|
+
}) {
|
|
123
|
+
// Dummy handle props for the overlay (not interactive)
|
|
124
|
+
const dragHandleProps: Record<string, any> = {};
|
|
125
|
+
|
|
126
|
+
return (
|
|
127
|
+
<div
|
|
128
|
+
className={classNames(itemWrapperClassName, 'bg-white')}
|
|
129
|
+
style={{
|
|
130
|
+
boxShadow: '0 4px 12px rgba(0,0,0,0.15)',
|
|
131
|
+
transform: 'scale(1.02)',
|
|
132
|
+
cursor: 'grabbing',
|
|
133
|
+
}}
|
|
134
|
+
>
|
|
135
|
+
{renderItem(item, {
|
|
136
|
+
dragHandleProps,
|
|
137
|
+
isDragging: true,
|
|
138
|
+
isDragOver: false,
|
|
139
|
+
})}
|
|
140
|
+
</div>
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function SortableList<T>(props: SortableListProps<T>) {
|
|
145
|
+
const {
|
|
146
|
+
items,
|
|
147
|
+
onChange,
|
|
148
|
+
getId,
|
|
149
|
+
renderItem,
|
|
150
|
+
validateReorder,
|
|
151
|
+
renderError,
|
|
152
|
+
disabled = false,
|
|
153
|
+
className,
|
|
154
|
+
itemWrapperClassName,
|
|
155
|
+
} = props;
|
|
156
|
+
|
|
157
|
+
const [activeId, setActiveId] = useState<UniqueIdentifier | null>(null);
|
|
158
|
+
const [error, setError] = useState<string | null>(null);
|
|
159
|
+
|
|
160
|
+
const ids = useMemo(() => items.map(getId), [items, getId]);
|
|
161
|
+
|
|
162
|
+
const sensors = useSensors(
|
|
163
|
+
useSensor(PointerSensor, {
|
|
164
|
+
activationConstraint: {
|
|
165
|
+
distance: 5, // 5px movement required before drag starts
|
|
166
|
+
},
|
|
167
|
+
}),
|
|
168
|
+
useSensor(KeyboardSensor, {
|
|
169
|
+
coordinateGetter: sortableKeyboardCoordinates,
|
|
170
|
+
})
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
const handleDragStart = (event: DragStartEvent) => {
|
|
174
|
+
setActiveId(event.active.id);
|
|
175
|
+
setError(null);
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
const handleDragEnd = (event: DragEndEvent) => {
|
|
179
|
+
const { active, over } = event;
|
|
180
|
+
|
|
181
|
+
setActiveId(null);
|
|
182
|
+
|
|
183
|
+
if (!over || active.id === over.id) {
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const oldIndex = ids.indexOf(active.id);
|
|
188
|
+
const newIndex = ids.indexOf(over.id);
|
|
189
|
+
|
|
190
|
+
if (oldIndex === -1 || newIndex === -1) {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
const next = arrayMove(items, oldIndex, newIndex);
|
|
195
|
+
|
|
196
|
+
if (validateReorder) {
|
|
197
|
+
const msg = validateReorder(next);
|
|
198
|
+
if (msg) {
|
|
199
|
+
setError(msg);
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
setError(null);
|
|
205
|
+
onChange(next);
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
const handleDragCancel = () => {
|
|
209
|
+
setActiveId(null);
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
const activeItem =
|
|
213
|
+
activeId !== null ? items.find((item) => getId(item) === activeId) : null;
|
|
214
|
+
|
|
215
|
+
return (
|
|
216
|
+
<div className={className}>
|
|
217
|
+
{error && renderError ? renderError(error) : null}
|
|
218
|
+
|
|
219
|
+
<DndContext
|
|
220
|
+
sensors={sensors}
|
|
221
|
+
collisionDetection={closestCenter}
|
|
222
|
+
onDragStart={handleDragStart}
|
|
223
|
+
onDragEnd={handleDragEnd}
|
|
224
|
+
onDragCancel={handleDragCancel}
|
|
225
|
+
>
|
|
226
|
+
<SortableContext items={ids} strategy={verticalListSortingStrategy}>
|
|
227
|
+
<div className="flex flex-col gap-2">
|
|
228
|
+
{items.map((item) => {
|
|
229
|
+
const id = getId(item);
|
|
230
|
+
return (
|
|
231
|
+
<SortableItem
|
|
232
|
+
key={id}
|
|
233
|
+
id={id}
|
|
234
|
+
item={item}
|
|
235
|
+
renderItem={renderItem}
|
|
236
|
+
disabled={disabled}
|
|
237
|
+
itemWrapperClassName={itemWrapperClassName}
|
|
238
|
+
activeId={activeId}
|
|
239
|
+
/>
|
|
240
|
+
);
|
|
241
|
+
})}
|
|
242
|
+
</div>
|
|
243
|
+
</SortableContext>
|
|
244
|
+
|
|
245
|
+
<DragOverlay>
|
|
246
|
+
{activeItem ? (
|
|
247
|
+
<DragOverlayItem
|
|
248
|
+
item={activeItem}
|
|
249
|
+
renderItem={renderItem}
|
|
250
|
+
itemWrapperClassName={itemWrapperClassName}
|
|
251
|
+
/>
|
|
252
|
+
) : null}
|
|
253
|
+
</DragOverlay>
|
|
254
|
+
</DndContext>
|
|
255
|
+
</div>
|
|
256
|
+
);
|
|
257
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { Allotment } from 'allotment';
|
|
2
|
+
import 'allotment/dist/style.css';
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
import { SortableList } from './Sortable.js';
|
|
5
|
+
export { Allotment, SortableList };
|
|
4
6
|
|
|
5
7
|
export type { AllotmentProps as ExternalAllotmentProps } from 'allotment';
|
|
8
|
+
export type { SortableListProps as ExternalSortableListProps } from './Sortable.js';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
declare module 'wp.element' {
|
|
2
|
+
export * from '@wordpress/element';
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
declare module 'wp.element/jsx-runtime' {
|
|
6
|
+
export const jsx: any;
|
|
7
|
+
export const jsxs: any;
|
|
8
|
+
export const jsxDEV: any;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
declare module 'react' {
|
|
12
|
+
import React = require('wp.element');
|
|
13
|
+
export = React;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
declare module 'react/jsx-runtime' {
|
|
17
|
+
import * as ReactJSX from 'wp.element/jsx-runtime';
|
|
18
|
+
export = ReactJSX;
|
|
19
|
+
}
|