@lodashventure/medusa-banner 0.0.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.
@@ -0,0 +1,1298 @@
1
+ "use strict";
2
+ const jsxRuntime = require("react/jsx-runtime");
3
+ const adminSdk = require("@medusajs/admin-sdk");
4
+ const icons = require("@medusajs/icons");
5
+ const core = require("@dnd-kit/core");
6
+ const React = require("react");
7
+ const ui = require("@medusajs/ui");
8
+ const lucideReact = require("lucide-react");
9
+ const reactQuery = require("@tanstack/react-query");
10
+ const reactDropzone = require("react-dropzone");
11
+ const _interopDefault = (e) => e && e.__esModule ? e : { default: e };
12
+ const React__default = /* @__PURE__ */ _interopDefault(React);
13
+ function useCombinedRefs() {
14
+ for (var _len = arguments.length, refs = new Array(_len), _key = 0; _key < _len; _key++) {
15
+ refs[_key] = arguments[_key];
16
+ }
17
+ return React.useMemo(
18
+ () => (node) => {
19
+ refs.forEach((ref) => ref(node));
20
+ },
21
+ // eslint-disable-next-line react-hooks/exhaustive-deps
22
+ refs
23
+ );
24
+ }
25
+ const canUseDOM = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined";
26
+ function isWindow(element) {
27
+ const elementString = Object.prototype.toString.call(element);
28
+ return elementString === "[object Window]" || // In Electron context the Window object serializes to [object global]
29
+ elementString === "[object global]";
30
+ }
31
+ function isNode(node) {
32
+ return "nodeType" in node;
33
+ }
34
+ function getWindow(target) {
35
+ var _target$ownerDocument, _target$ownerDocument2;
36
+ if (!target) {
37
+ return window;
38
+ }
39
+ if (isWindow(target)) {
40
+ return target;
41
+ }
42
+ if (!isNode(target)) {
43
+ return window;
44
+ }
45
+ return (_target$ownerDocument = (_target$ownerDocument2 = target.ownerDocument) == null ? void 0 : _target$ownerDocument2.defaultView) != null ? _target$ownerDocument : window;
46
+ }
47
+ const useIsomorphicLayoutEffect = canUseDOM ? React.useLayoutEffect : React.useEffect;
48
+ let ids = {};
49
+ function useUniqueId(prefix, value) {
50
+ return React.useMemo(() => {
51
+ if (value) {
52
+ return value;
53
+ }
54
+ const id = ids[prefix] == null ? 0 : ids[prefix] + 1;
55
+ ids[prefix] = id;
56
+ return prefix + "-" + id;
57
+ }, [prefix, value]);
58
+ }
59
+ function createAdjustmentFn(modifier) {
60
+ return function(object) {
61
+ for (var _len = arguments.length, adjustments = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
62
+ adjustments[_key - 1] = arguments[_key];
63
+ }
64
+ return adjustments.reduce((accumulator, adjustment) => {
65
+ const entries = Object.entries(adjustment);
66
+ for (const [key, valueAdjustment] of entries) {
67
+ const value = accumulator[key];
68
+ if (value != null) {
69
+ accumulator[key] = value + modifier * valueAdjustment;
70
+ }
71
+ }
72
+ return accumulator;
73
+ }, {
74
+ ...object
75
+ });
76
+ };
77
+ }
78
+ const subtract = /* @__PURE__ */ createAdjustmentFn(-1);
79
+ function isKeyboardEvent(event) {
80
+ if (!event) {
81
+ return false;
82
+ }
83
+ const {
84
+ KeyboardEvent
85
+ } = getWindow(event.target);
86
+ return KeyboardEvent && event instanceof KeyboardEvent;
87
+ }
88
+ const CSS = /* @__PURE__ */ Object.freeze({
89
+ Translate: {
90
+ toString(transform) {
91
+ if (!transform) {
92
+ return;
93
+ }
94
+ const {
95
+ x,
96
+ y
97
+ } = transform;
98
+ return "translate3d(" + (x ? Math.round(x) : 0) + "px, " + (y ? Math.round(y) : 0) + "px, 0)";
99
+ }
100
+ },
101
+ Scale: {
102
+ toString(transform) {
103
+ if (!transform) {
104
+ return;
105
+ }
106
+ const {
107
+ scaleX,
108
+ scaleY
109
+ } = transform;
110
+ return "scaleX(" + scaleX + ") scaleY(" + scaleY + ")";
111
+ }
112
+ },
113
+ Transform: {
114
+ toString(transform) {
115
+ if (!transform) {
116
+ return;
117
+ }
118
+ return [CSS.Translate.toString(transform), CSS.Scale.toString(transform)].join(" ");
119
+ }
120
+ },
121
+ Transition: {
122
+ toString(_ref) {
123
+ let {
124
+ property,
125
+ duration,
126
+ easing
127
+ } = _ref;
128
+ return property + " " + duration + "ms " + easing;
129
+ }
130
+ }
131
+ });
132
+ function arrayMove(array, from, to) {
133
+ const newArray = array.slice();
134
+ newArray.splice(to < 0 ? newArray.length + to : to, 0, newArray.splice(from, 1)[0]);
135
+ return newArray;
136
+ }
137
+ function getSortedRects(items, rects) {
138
+ return items.reduce((accumulator, id, index) => {
139
+ const rect = rects.get(id);
140
+ if (rect) {
141
+ accumulator[index] = rect;
142
+ }
143
+ return accumulator;
144
+ }, Array(items.length));
145
+ }
146
+ function isValidIndex(index) {
147
+ return index !== null && index >= 0;
148
+ }
149
+ function itemsEqual(a, b) {
150
+ if (a === b) {
151
+ return true;
152
+ }
153
+ if (a.length !== b.length) {
154
+ return false;
155
+ }
156
+ for (let i = 0; i < a.length; i++) {
157
+ if (a[i] !== b[i]) {
158
+ return false;
159
+ }
160
+ }
161
+ return true;
162
+ }
163
+ function normalizeDisabled(disabled) {
164
+ if (typeof disabled === "boolean") {
165
+ return {
166
+ draggable: disabled,
167
+ droppable: disabled
168
+ };
169
+ }
170
+ return disabled;
171
+ }
172
+ const rectSortingStrategy = (_ref) => {
173
+ let {
174
+ rects,
175
+ activeIndex,
176
+ overIndex,
177
+ index
178
+ } = _ref;
179
+ const newRects = arrayMove(rects, overIndex, activeIndex);
180
+ const oldRect = rects[index];
181
+ const newRect = newRects[index];
182
+ if (!newRect || !oldRect) {
183
+ return null;
184
+ }
185
+ return {
186
+ x: newRect.left - oldRect.left,
187
+ y: newRect.top - oldRect.top,
188
+ scaleX: newRect.width / oldRect.width,
189
+ scaleY: newRect.height / oldRect.height
190
+ };
191
+ };
192
+ const ID_PREFIX = "Sortable";
193
+ const Context = /* @__PURE__ */ React__default.default.createContext({
194
+ activeIndex: -1,
195
+ containerId: ID_PREFIX,
196
+ disableTransforms: false,
197
+ items: [],
198
+ overIndex: -1,
199
+ useDragOverlay: false,
200
+ sortedRects: [],
201
+ strategy: rectSortingStrategy,
202
+ disabled: {
203
+ draggable: false,
204
+ droppable: false
205
+ }
206
+ });
207
+ function SortableContext(_ref) {
208
+ let {
209
+ children,
210
+ id,
211
+ items: userDefinedItems,
212
+ strategy = rectSortingStrategy,
213
+ disabled: disabledProp = false
214
+ } = _ref;
215
+ const {
216
+ active,
217
+ dragOverlay,
218
+ droppableRects,
219
+ over,
220
+ measureDroppableContainers
221
+ } = core.useDndContext();
222
+ const containerId = useUniqueId(ID_PREFIX, id);
223
+ const useDragOverlay = Boolean(dragOverlay.rect !== null);
224
+ const items = React.useMemo(() => userDefinedItems.map((item) => typeof item === "object" && "id" in item ? item.id : item), [userDefinedItems]);
225
+ const isDragging = active != null;
226
+ const activeIndex = active ? items.indexOf(active.id) : -1;
227
+ const overIndex = over ? items.indexOf(over.id) : -1;
228
+ const previousItemsRef = React.useRef(items);
229
+ const itemsHaveChanged = !itemsEqual(items, previousItemsRef.current);
230
+ const disableTransforms = overIndex !== -1 && activeIndex === -1 || itemsHaveChanged;
231
+ const disabled = normalizeDisabled(disabledProp);
232
+ useIsomorphicLayoutEffect(() => {
233
+ if (itemsHaveChanged && isDragging) {
234
+ measureDroppableContainers(items);
235
+ }
236
+ }, [itemsHaveChanged, items, isDragging, measureDroppableContainers]);
237
+ React.useEffect(() => {
238
+ previousItemsRef.current = items;
239
+ }, [items]);
240
+ const contextValue = React.useMemo(
241
+ () => ({
242
+ activeIndex,
243
+ containerId,
244
+ disabled,
245
+ disableTransforms,
246
+ items,
247
+ overIndex,
248
+ useDragOverlay,
249
+ sortedRects: getSortedRects(items, droppableRects),
250
+ strategy
251
+ }),
252
+ // eslint-disable-next-line react-hooks/exhaustive-deps
253
+ [activeIndex, containerId, disabled.draggable, disabled.droppable, disableTransforms, items, overIndex, droppableRects, useDragOverlay, strategy]
254
+ );
255
+ return React__default.default.createElement(Context.Provider, {
256
+ value: contextValue
257
+ }, children);
258
+ }
259
+ const defaultNewIndexGetter = (_ref) => {
260
+ let {
261
+ id,
262
+ items,
263
+ activeIndex,
264
+ overIndex
265
+ } = _ref;
266
+ return arrayMove(items, activeIndex, overIndex).indexOf(id);
267
+ };
268
+ const defaultAnimateLayoutChanges = (_ref2) => {
269
+ let {
270
+ containerId,
271
+ isSorting,
272
+ wasDragging,
273
+ index,
274
+ items,
275
+ newIndex,
276
+ previousItems,
277
+ previousContainerId,
278
+ transition
279
+ } = _ref2;
280
+ if (!transition || !wasDragging) {
281
+ return false;
282
+ }
283
+ if (previousItems !== items && index === newIndex) {
284
+ return false;
285
+ }
286
+ if (isSorting) {
287
+ return true;
288
+ }
289
+ return newIndex !== index && containerId === previousContainerId;
290
+ };
291
+ const defaultTransition = {
292
+ duration: 200,
293
+ easing: "ease"
294
+ };
295
+ const transitionProperty = "transform";
296
+ const disabledTransition = /* @__PURE__ */ CSS.Transition.toString({
297
+ property: transitionProperty,
298
+ duration: 0,
299
+ easing: "linear"
300
+ });
301
+ const defaultAttributes = {
302
+ roleDescription: "sortable"
303
+ };
304
+ function useDerivedTransform(_ref) {
305
+ let {
306
+ disabled,
307
+ index,
308
+ node,
309
+ rect
310
+ } = _ref;
311
+ const [derivedTransform, setDerivedtransform] = React.useState(null);
312
+ const previousIndex = React.useRef(index);
313
+ useIsomorphicLayoutEffect(() => {
314
+ if (!disabled && index !== previousIndex.current && node.current) {
315
+ const initial = rect.current;
316
+ if (initial) {
317
+ const current = core.getClientRect(node.current, {
318
+ ignoreTransform: true
319
+ });
320
+ const delta = {
321
+ x: initial.left - current.left,
322
+ y: initial.top - current.top,
323
+ scaleX: initial.width / current.width,
324
+ scaleY: initial.height / current.height
325
+ };
326
+ if (delta.x || delta.y) {
327
+ setDerivedtransform(delta);
328
+ }
329
+ }
330
+ }
331
+ if (index !== previousIndex.current) {
332
+ previousIndex.current = index;
333
+ }
334
+ }, [disabled, index, node, rect]);
335
+ React.useEffect(() => {
336
+ if (derivedTransform) {
337
+ setDerivedtransform(null);
338
+ }
339
+ }, [derivedTransform]);
340
+ return derivedTransform;
341
+ }
342
+ function useSortable(_ref) {
343
+ let {
344
+ animateLayoutChanges = defaultAnimateLayoutChanges,
345
+ attributes: userDefinedAttributes,
346
+ disabled: localDisabled,
347
+ data: customData,
348
+ getNewIndex = defaultNewIndexGetter,
349
+ id,
350
+ strategy: localStrategy,
351
+ resizeObserverConfig,
352
+ transition = defaultTransition
353
+ } = _ref;
354
+ const {
355
+ items,
356
+ containerId,
357
+ activeIndex,
358
+ disabled: globalDisabled,
359
+ disableTransforms,
360
+ sortedRects,
361
+ overIndex,
362
+ useDragOverlay,
363
+ strategy: globalStrategy
364
+ } = React.useContext(Context);
365
+ const disabled = normalizeLocalDisabled(localDisabled, globalDisabled);
366
+ const index = items.indexOf(id);
367
+ const data = React.useMemo(() => ({
368
+ sortable: {
369
+ containerId,
370
+ index,
371
+ items
372
+ },
373
+ ...customData
374
+ }), [containerId, customData, index, items]);
375
+ const itemsAfterCurrentSortable = React.useMemo(() => items.slice(items.indexOf(id)), [items, id]);
376
+ const {
377
+ rect,
378
+ node,
379
+ isOver,
380
+ setNodeRef: setDroppableNodeRef
381
+ } = core.useDroppable({
382
+ id,
383
+ data,
384
+ disabled: disabled.droppable,
385
+ resizeObserverConfig: {
386
+ updateMeasurementsFor: itemsAfterCurrentSortable,
387
+ ...resizeObserverConfig
388
+ }
389
+ });
390
+ const {
391
+ active,
392
+ activatorEvent,
393
+ activeNodeRect,
394
+ attributes,
395
+ setNodeRef: setDraggableNodeRef,
396
+ listeners,
397
+ isDragging,
398
+ over,
399
+ setActivatorNodeRef,
400
+ transform
401
+ } = core.useDraggable({
402
+ id,
403
+ data,
404
+ attributes: {
405
+ ...defaultAttributes,
406
+ ...userDefinedAttributes
407
+ },
408
+ disabled: disabled.draggable
409
+ });
410
+ const setNodeRef = useCombinedRefs(setDroppableNodeRef, setDraggableNodeRef);
411
+ const isSorting = Boolean(active);
412
+ const displaceItem = isSorting && !disableTransforms && isValidIndex(activeIndex) && isValidIndex(overIndex);
413
+ const shouldDisplaceDragSource = !useDragOverlay && isDragging;
414
+ const dragSourceDisplacement = shouldDisplaceDragSource && displaceItem ? transform : null;
415
+ const strategy = localStrategy != null ? localStrategy : globalStrategy;
416
+ const finalTransform = displaceItem ? dragSourceDisplacement != null ? dragSourceDisplacement : strategy({
417
+ rects: sortedRects,
418
+ activeNodeRect,
419
+ activeIndex,
420
+ overIndex,
421
+ index
422
+ }) : null;
423
+ const newIndex = isValidIndex(activeIndex) && isValidIndex(overIndex) ? getNewIndex({
424
+ id,
425
+ items,
426
+ activeIndex,
427
+ overIndex
428
+ }) : index;
429
+ const activeId = active == null ? void 0 : active.id;
430
+ const previous = React.useRef({
431
+ activeId,
432
+ items,
433
+ newIndex,
434
+ containerId
435
+ });
436
+ const itemsHaveChanged = items !== previous.current.items;
437
+ const shouldAnimateLayoutChanges = animateLayoutChanges({
438
+ active,
439
+ containerId,
440
+ isDragging,
441
+ isSorting,
442
+ id,
443
+ index,
444
+ items,
445
+ newIndex: previous.current.newIndex,
446
+ previousItems: previous.current.items,
447
+ previousContainerId: previous.current.containerId,
448
+ transition,
449
+ wasDragging: previous.current.activeId != null
450
+ });
451
+ const derivedTransform = useDerivedTransform({
452
+ disabled: !shouldAnimateLayoutChanges,
453
+ index,
454
+ node,
455
+ rect
456
+ });
457
+ React.useEffect(() => {
458
+ if (isSorting && previous.current.newIndex !== newIndex) {
459
+ previous.current.newIndex = newIndex;
460
+ }
461
+ if (containerId !== previous.current.containerId) {
462
+ previous.current.containerId = containerId;
463
+ }
464
+ if (items !== previous.current.items) {
465
+ previous.current.items = items;
466
+ }
467
+ }, [isSorting, newIndex, containerId, items]);
468
+ React.useEffect(() => {
469
+ if (activeId === previous.current.activeId) {
470
+ return;
471
+ }
472
+ if (activeId && !previous.current.activeId) {
473
+ previous.current.activeId = activeId;
474
+ return;
475
+ }
476
+ const timeoutId = setTimeout(() => {
477
+ previous.current.activeId = activeId;
478
+ }, 50);
479
+ return () => clearTimeout(timeoutId);
480
+ }, [activeId]);
481
+ return {
482
+ active,
483
+ activeIndex,
484
+ attributes,
485
+ data,
486
+ rect,
487
+ index,
488
+ newIndex,
489
+ items,
490
+ isOver,
491
+ isSorting,
492
+ isDragging,
493
+ listeners,
494
+ node,
495
+ overIndex,
496
+ over,
497
+ setNodeRef,
498
+ setActivatorNodeRef,
499
+ setDroppableNodeRef,
500
+ setDraggableNodeRef,
501
+ transform: derivedTransform != null ? derivedTransform : finalTransform,
502
+ transition: getTransition()
503
+ };
504
+ function getTransition() {
505
+ if (
506
+ // Temporarily disable transitions for a single frame to set up derived transforms
507
+ derivedTransform || // Or to prevent items jumping to back to their "new" position when items change
508
+ itemsHaveChanged && previous.current.newIndex === index
509
+ ) {
510
+ return disabledTransition;
511
+ }
512
+ if (shouldDisplaceDragSource && !isKeyboardEvent(activatorEvent) || !transition) {
513
+ return void 0;
514
+ }
515
+ if (isSorting || shouldAnimateLayoutChanges) {
516
+ return CSS.Transition.toString({
517
+ ...transition,
518
+ property: transitionProperty
519
+ });
520
+ }
521
+ return void 0;
522
+ }
523
+ }
524
+ function normalizeLocalDisabled(localDisabled, globalDisabled) {
525
+ var _localDisabled$dragga, _localDisabled$droppa;
526
+ if (typeof localDisabled === "boolean") {
527
+ return {
528
+ draggable: localDisabled,
529
+ // Backwards compatibility
530
+ droppable: false
531
+ };
532
+ }
533
+ return {
534
+ draggable: (_localDisabled$dragga = localDisabled == null ? void 0 : localDisabled.draggable) != null ? _localDisabled$dragga : globalDisabled.draggable,
535
+ droppable: (_localDisabled$droppa = localDisabled == null ? void 0 : localDisabled.droppable) != null ? _localDisabled$droppa : globalDisabled.droppable
536
+ };
537
+ }
538
+ function hasSortableData(entry) {
539
+ if (!entry) {
540
+ return false;
541
+ }
542
+ const data = entry.data.current;
543
+ if (data && "sortable" in data && typeof data.sortable === "object" && "containerId" in data.sortable && "items" in data.sortable && "index" in data.sortable) {
544
+ return true;
545
+ }
546
+ return false;
547
+ }
548
+ const directions = [core.KeyboardCode.Down, core.KeyboardCode.Right, core.KeyboardCode.Up, core.KeyboardCode.Left];
549
+ const sortableKeyboardCoordinates = (event, _ref) => {
550
+ let {
551
+ context: {
552
+ active,
553
+ collisionRect,
554
+ droppableRects,
555
+ droppableContainers,
556
+ over,
557
+ scrollableAncestors
558
+ }
559
+ } = _ref;
560
+ if (directions.includes(event.code)) {
561
+ event.preventDefault();
562
+ if (!active || !collisionRect) {
563
+ return;
564
+ }
565
+ const filteredContainers = [];
566
+ droppableContainers.getEnabled().forEach((entry) => {
567
+ if (!entry || entry != null && entry.disabled) {
568
+ return;
569
+ }
570
+ const rect = droppableRects.get(entry.id);
571
+ if (!rect) {
572
+ return;
573
+ }
574
+ switch (event.code) {
575
+ case core.KeyboardCode.Down:
576
+ if (collisionRect.top < rect.top) {
577
+ filteredContainers.push(entry);
578
+ }
579
+ break;
580
+ case core.KeyboardCode.Up:
581
+ if (collisionRect.top > rect.top) {
582
+ filteredContainers.push(entry);
583
+ }
584
+ break;
585
+ case core.KeyboardCode.Left:
586
+ if (collisionRect.left > rect.left) {
587
+ filteredContainers.push(entry);
588
+ }
589
+ break;
590
+ case core.KeyboardCode.Right:
591
+ if (collisionRect.left < rect.left) {
592
+ filteredContainers.push(entry);
593
+ }
594
+ break;
595
+ }
596
+ });
597
+ const collisions = core.closestCorners({
598
+ active,
599
+ collisionRect,
600
+ droppableRects,
601
+ droppableContainers: filteredContainers,
602
+ pointerCoordinates: null
603
+ });
604
+ let closestId = core.getFirstCollision(collisions, "id");
605
+ if (closestId === (over == null ? void 0 : over.id) && collisions.length > 1) {
606
+ closestId = collisions[1].id;
607
+ }
608
+ if (closestId != null) {
609
+ const activeDroppable = droppableContainers.get(active.id);
610
+ const newDroppable = droppableContainers.get(closestId);
611
+ const newRect = newDroppable ? droppableRects.get(newDroppable.id) : null;
612
+ const newNode = newDroppable == null ? void 0 : newDroppable.node.current;
613
+ if (newNode && newRect && activeDroppable && newDroppable) {
614
+ const newScrollAncestors = core.getScrollableAncestors(newNode);
615
+ const hasDifferentScrollAncestors = newScrollAncestors.some((element, index) => scrollableAncestors[index] !== element);
616
+ const hasSameContainer = isSameContainer(activeDroppable, newDroppable);
617
+ const isAfterActive = isAfter(activeDroppable, newDroppable);
618
+ const offset = hasDifferentScrollAncestors || !hasSameContainer ? {
619
+ x: 0,
620
+ y: 0
621
+ } : {
622
+ x: isAfterActive ? collisionRect.width - newRect.width : 0,
623
+ y: isAfterActive ? collisionRect.height - newRect.height : 0
624
+ };
625
+ const rectCoordinates = {
626
+ x: newRect.left,
627
+ y: newRect.top
628
+ };
629
+ const newCoordinates = offset.x && offset.y ? rectCoordinates : subtract(rectCoordinates, offset);
630
+ return newCoordinates;
631
+ }
632
+ }
633
+ }
634
+ return void 0;
635
+ };
636
+ function isSameContainer(a, b) {
637
+ if (!hasSortableData(a) || !hasSortableData(b)) {
638
+ return false;
639
+ }
640
+ return a.data.current.sortable.containerId === b.data.current.sortable.containerId;
641
+ }
642
+ function isAfter(a, b) {
643
+ if (!hasSortableData(a) || !hasSortableData(b)) {
644
+ return false;
645
+ }
646
+ if (!isSameContainer(a, b)) {
647
+ return false;
648
+ }
649
+ return a.data.current.sortable.index < b.data.current.sortable.index;
650
+ }
651
+ const useBanners = () => {
652
+ const getUploadedFiles = async () => {
653
+ try {
654
+ const response = await fetch("/admin/banners", {
655
+ method: "GET",
656
+ credentials: "include"
657
+ });
658
+ if (!response.ok) {
659
+ throw new Error(`HTTP error! Status: ${response.status}`);
660
+ }
661
+ const data = await response.json();
662
+ return data ?? {
663
+ banners: [],
664
+ count: 0
665
+ };
666
+ } catch (error) {
667
+ console.error("Error fetching banners:", error);
668
+ throw error;
669
+ }
670
+ };
671
+ return reactQuery.useQuery({
672
+ queryKey: ["banners"],
673
+ queryFn: getUploadedFiles,
674
+ // No need for the arrow function wrapper
675
+ retry: false
676
+ });
677
+ };
678
+ const DraggableItem = ({ banner }) => {
679
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg shadow-md border border-gray-200 opacity-80 scale-105", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
680
+ /* @__PURE__ */ jsxRuntime.jsx(
681
+ "img",
682
+ {
683
+ src: banner.url,
684
+ alt: `Banner ${banner.id}`,
685
+ className: "object-cover w-full h-48 rounded-t-lg"
686
+ }
687
+ ),
688
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2 text-sm truncate", children: banner.id })
689
+ ] }) });
690
+ };
691
+ const GridItem = ({
692
+ banner,
693
+ isSelected,
694
+ onClick,
695
+ onSelect
696
+ }) => {
697
+ return /* @__PURE__ */ jsxRuntime.jsxs(
698
+ "div",
699
+ {
700
+ className: `
701
+ relative overflow-hidden rounded-lg shadow-md cursor-pointer hover:shadow-lg
702
+ transition-all duration-200 ease-in-out
703
+ ${isSelected ? "ring-2 ring-offset-2 ring-blue-500" : ""}
704
+ `,
705
+ onClick,
706
+ children: [
707
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
708
+ /* @__PURE__ */ jsxRuntime.jsx(
709
+ "img",
710
+ {
711
+ src: banner.url || "/placeholder.svg?height=200&width=300",
712
+ alt: `Banner ${banner.id}`,
713
+ className: "object-cover w-full h-48"
714
+ }
715
+ ),
716
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "truncate p-2 text-sm", children: banner.id })
717
+ ] }),
718
+ /* @__PURE__ */ jsxRuntime.jsx(
719
+ "div",
720
+ {
721
+ className: `
722
+ absolute top-2 left-2 w-6 h-6 rounded-md flex items-center justify-center
723
+ ${isSelected ? "bg-blue-500 text-white" : "bg-white/80 border border-gray-300"}
724
+ ${isSelected ? "visible" : "invisible group-hover:visible"}
725
+ transition-opacity duration-200
726
+ `,
727
+ onClick: onSelect,
728
+ children: isSelected && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-4 w-4" })
729
+ }
730
+ )
731
+ ]
732
+ }
733
+ );
734
+ };
735
+ const SortableItem = ({ banner }) => {
736
+ const {
737
+ attributes,
738
+ listeners,
739
+ setNodeRef,
740
+ transform,
741
+ transition,
742
+ isDragging
743
+ } = useSortable({ id: banner.id });
744
+ const style = {
745
+ transform: CSS.Transform.toString(transform),
746
+ transition,
747
+ zIndex: isDragging ? 10 : 1,
748
+ opacity: isDragging ? 0.5 : 1
749
+ };
750
+ return /* @__PURE__ */ jsxRuntime.jsx(
751
+ "div",
752
+ {
753
+ ref: setNodeRef,
754
+ style,
755
+ className: "rounded-lg shadow-md border border-gray-200 hover:border-gray-300 transition-all relative",
756
+ ...attributes,
757
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { ...listeners, children: [
758
+ /* @__PURE__ */ jsxRuntime.jsx(
759
+ "img",
760
+ {
761
+ src: banner.url,
762
+ alt: `Banner ${banner.id}`,
763
+ className: "object-cover w-full h-48 rounded-t-lg"
764
+ }
765
+ ),
766
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2 text-sm truncate", children: banner.id })
767
+ ] })
768
+ }
769
+ );
770
+ };
771
+ const UploadBannerDrawerContent = ({
772
+ maxFileSizeMb = 10,
773
+ onSuccess
774
+ }) => {
775
+ const [files, setFiles] = React.useState([]);
776
+ const [isLoading, setIsLoading] = React.useState(false);
777
+ const onDrop = React.useCallback((acceptedFiles) => {
778
+ const newFiles = acceptedFiles.map((file) => {
779
+ const id = crypto.randomUUID();
780
+ let preview;
781
+ if (file.type.startsWith("image/")) {
782
+ preview = URL.createObjectURL(file);
783
+ }
784
+ return {
785
+ file,
786
+ id,
787
+ preview
788
+ };
789
+ });
790
+ setFiles((prev) => [...prev, ...newFiles]);
791
+ }, []);
792
+ const removeFile = (id) => {
793
+ setFiles((files2) => {
794
+ const fileToRemove = files2.find((f) => f.id === id);
795
+ if (fileToRemove == null ? void 0 : fileToRemove.preview) {
796
+ URL.revokeObjectURL(fileToRemove.preview);
797
+ }
798
+ return files2.filter((f) => f.id !== id);
799
+ });
800
+ };
801
+ const handleResetFiles = () => {
802
+ setFiles([]);
803
+ };
804
+ const handleUploadFiles = async () => {
805
+ setIsLoading(true);
806
+ try {
807
+ const formData = new FormData();
808
+ files.forEach((file) => {
809
+ if (!file.file) {
810
+ return;
811
+ }
812
+ formData.append("files", file.file);
813
+ });
814
+ const { uploadedFiles } = await fetch("/admin/banners", {
815
+ method: "POST",
816
+ credentials: "include",
817
+ body: formData
818
+ }).then((res) => res.json());
819
+ onSuccess(uploadedFiles);
820
+ return {
821
+ files,
822
+ uploadedFiles
823
+ };
824
+ } catch (error) {
825
+ console.error(error);
826
+ alert("Error uploading files");
827
+ } finally {
828
+ setIsLoading(false);
829
+ }
830
+ };
831
+ const {
832
+ getRootProps,
833
+ getInputProps,
834
+ isDragActive,
835
+ isDragAccept,
836
+ isDragReject,
837
+ isFocused
838
+ } = reactDropzone.useDropzone({
839
+ onDrop,
840
+ accept: {
841
+ "image/*": []
842
+ },
843
+ maxSize: maxFileSizeMb * 1024 * 1024
844
+ // maxFileSizeMb
845
+ });
846
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-6", children: [
847
+ /* @__PURE__ */ jsxRuntime.jsxs(
848
+ "div",
849
+ {
850
+ ...getRootProps(),
851
+ className: ui.clx(
852
+ "border-2 border-dashed rounded-xl p-10 transition-all duration-150 ease-in-out cursor-pointer",
853
+ "flex flex-col items-center justify-center gap-4",
854
+ isDragActive ? "bg-primary/5 border-primary/50" : "bg-background hover:bg-muted/50",
855
+ isDragAccept ? "border-green-500 bg-green-50 dark:bg-green-950/20" : "",
856
+ isDragReject ? "border-red-500 bg-red-50 dark:bg-red-950/20" : "",
857
+ isFocused ? "ring-2 ring-ring ring-offset-2" : "",
858
+ "focus-visible:outline-none"
859
+ ),
860
+ children: [
861
+ /* @__PURE__ */ jsxRuntime.jsx("input", { ...getInputProps(), disabled: isLoading }),
862
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-full bg-primary/10 p-4", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Upload, { className: "h-8 w-8 text-primary" }) }),
863
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center space-y-2", children: [
864
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "font-medium text-lg", children: isDragActive ? isDragAccept ? "Drop files to upload" : "This file type is not supported" : "Drag & drop images here" }),
865
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground", children: [
866
+ "or ",
867
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-primary font-medium", children: "browse images" }),
868
+ " ",
869
+ "from your computer"
870
+ ] }),
871
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-muted-foreground", children: [
872
+ "(max ",
873
+ maxFileSizeMb,
874
+ "MB)"
875
+ ] })
876
+ ] })
877
+ ]
878
+ }
879
+ ),
880
+ files.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
881
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
882
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline flex items-center gap-4", children: [
883
+ /* @__PURE__ */ jsxRuntime.jsxs("h3", { className: "text-lg font-medium", children: [
884
+ "Selected Files (",
885
+ files.length,
886
+ ")"
887
+ ] }),
888
+ /* @__PURE__ */ jsxRuntime.jsx(
889
+ ui.Button,
890
+ {
891
+ isLoading,
892
+ variant: "primary",
893
+ onClick: handleUploadFiles,
894
+ children: "Confirm Upload"
895
+ }
896
+ )
897
+ ] }),
898
+ /* @__PURE__ */ jsxRuntime.jsx(
899
+ ui.Button,
900
+ {
901
+ isLoading,
902
+ variant: "secondary",
903
+ onClick: handleResetFiles,
904
+ children: "Clear All"
905
+ }
906
+ )
907
+ ] }),
908
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid gap-4 grid-cols-2 sm:grid-cols-3", children: files.map((fileItem) => /* @__PURE__ */ jsxRuntime.jsxs(
909
+ "div",
910
+ {
911
+ className: "group relative rounded-lg border bg-card text-card-foreground shadow-sm overflow-hidden",
912
+ children: [
913
+ fileItem.preview ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "aspect-square w-full overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
914
+ "img",
915
+ {
916
+ src: fileItem.preview || "/placeholder.svg",
917
+ alt: fileItem.file.name,
918
+ className: "h-full w-full object-contain transition-all hover:scale-105"
919
+ }
920
+ ) }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "aspect-square w-full flex items-center justify-center bg-muted/50", children: [
921
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ImageIcon, { className: "h-6 w-6 text-primary" }),
922
+ ";"
923
+ ] }),
924
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start justify-between gap-2", children: [
925
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1 overflow-hidden", children: [
926
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "truncate text-sm font-medium", children: fileItem.file.name }),
927
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-muted-foreground", children: [
928
+ (fileItem.file.size / 1024).toFixed(1),
929
+ " KB"
930
+ ] })
931
+ ] }),
932
+ /* @__PURE__ */ jsxRuntime.jsxs(
933
+ ui.Button,
934
+ {
935
+ isLoading,
936
+ variant: "secondary",
937
+ className: "size-7 rounded-full p-0.5 text-red-400 shrink-0",
938
+ onClick: (e) => {
939
+ e.stopPropagation();
940
+ removeFile(fileItem.id);
941
+ },
942
+ children: [
943
+ /* @__PURE__ */ jsxRuntime.jsx(icons.Trash, {}),
944
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Remove file" })
945
+ ]
946
+ }
947
+ )
948
+ ] }) })
949
+ ]
950
+ },
951
+ fileItem.id
952
+ )) })
953
+ ] })
954
+ ] });
955
+ };
956
+ const BannerPage = () => {
957
+ const [open, setOpen] = React.useState(false);
958
+ const [selectedImage, setSelectedImage] = React.useState(null);
959
+ const [selectedIds, setSelectedIds] = React.useState(/* @__PURE__ */ new Set());
960
+ const [reorderMode, setReorderMode] = React.useState(false);
961
+ const [orderedBanners, setOrderedBanners] = React.useState([]);
962
+ const [activeBanner, setActiveBanner] = React.useState(null);
963
+ const [isLoading, setIsLoading] = React.useState(false);
964
+ const dialog = ui.usePrompt();
965
+ const { data: bannerData, refetch } = useBanners();
966
+ const { count = 0, banners = [] } = bannerData || {};
967
+ const sensors = core.useSensors(
968
+ core.useSensor(core.PointerSensor, {
969
+ activationConstraint: {
970
+ distance: 8
971
+ // 8px movement required before drag starts
972
+ }
973
+ }),
974
+ core.useSensor(core.KeyboardSensor, {
975
+ coordinateGetter: sortableKeyboardCoordinates
976
+ })
977
+ );
978
+ const toggleImageSelection = (e, id) => {
979
+ e.stopPropagation();
980
+ const newSelectedIds = new Set(selectedIds);
981
+ if (newSelectedIds.has(id)) {
982
+ newSelectedIds.delete(id);
983
+ } else {
984
+ newSelectedIds.add(id);
985
+ }
986
+ setSelectedIds(newSelectedIds);
987
+ };
988
+ const selectAll = () => {
989
+ const allIds = banners.map((banner) => banner.id);
990
+ setSelectedIds(new Set(allIds));
991
+ };
992
+ const deselectAll = () => {
993
+ setSelectedIds(/* @__PURE__ */ new Set());
994
+ };
995
+ const openLightbox = (banner) => {
996
+ setSelectedImage(banner);
997
+ };
998
+ const closeLightbox = () => {
999
+ setSelectedImage(null);
1000
+ };
1001
+ const toggleReorderMode = async () => {
1002
+ if (reorderMode) {
1003
+ const confirmed = await dialog({
1004
+ title: "Save Changes?",
1005
+ description: "Do you want to save your reordering changes?",
1006
+ variant: "confirmation",
1007
+ confirmText: "Save",
1008
+ cancelText: "Discard"
1009
+ });
1010
+ if (confirmed) {
1011
+ saveNewOrder();
1012
+ } else {
1013
+ setOrderedBanners([]);
1014
+ setReorderMode(false);
1015
+ }
1016
+ } else {
1017
+ setOrderedBanners([...banners]);
1018
+ setReorderMode(true);
1019
+ }
1020
+ };
1021
+ const handleDragStart = (event) => {
1022
+ const { active } = event;
1023
+ const activeBanner2 = orderedBanners.find(
1024
+ (banner) => banner.id === active.id
1025
+ );
1026
+ if (activeBanner2) {
1027
+ setActiveBanner(activeBanner2);
1028
+ }
1029
+ };
1030
+ const handleDragEnd = (event) => {
1031
+ const { active, over } = event;
1032
+ if (over && active.id !== over.id) {
1033
+ setOrderedBanners((items) => {
1034
+ const oldIndex = items.findIndex((item) => item.id === active.id);
1035
+ const newIndex = items.findIndex((item) => item.id === over.id);
1036
+ return arrayMove(items, oldIndex, newIndex);
1037
+ });
1038
+ }
1039
+ setActiveBanner(null);
1040
+ };
1041
+ const saveNewOrder = async () => {
1042
+ try {
1043
+ await fetch("/admin/banners/reorder", {
1044
+ method: "POST",
1045
+ credentials: "include",
1046
+ headers: {
1047
+ "Content-Type": "application/json",
1048
+ Accept: "application/json"
1049
+ },
1050
+ body: JSON.stringify({
1051
+ ids: orderedBanners.map((banner) => banner.id)
1052
+ })
1053
+ });
1054
+ setReorderMode(false);
1055
+ refetch();
1056
+ } catch (error) {
1057
+ console.error("Failed to save new order:", error);
1058
+ }
1059
+ };
1060
+ const handleDeleteMultiple = async () => {
1061
+ const isConfirmed = await dialog({
1062
+ title: "Confirm Deletion",
1063
+ description: `Are you sure you want to delete ${selectedIds.size} selected images? This action cannot be undone.`,
1064
+ confirmText: "Delete",
1065
+ cancelText: "Cancel"
1066
+ });
1067
+ if (!isConfirmed) return;
1068
+ const ids2 = Array.from(selectedIds);
1069
+ setIsLoading(true);
1070
+ try {
1071
+ await fetch("/admin/banners", {
1072
+ method: "DELETE",
1073
+ credentials: "include",
1074
+ headers: {
1075
+ "Content-Type": "application/json",
1076
+ Accept: "application/json"
1077
+ },
1078
+ body: JSON.stringify({ ids: ids2 })
1079
+ });
1080
+ setSelectedIds(/* @__PURE__ */ new Set());
1081
+ refetch();
1082
+ } catch {
1083
+ console.error("Failed to delete banners");
1084
+ } finally {
1085
+ setIsLoading(false);
1086
+ }
1087
+ };
1088
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-6", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "container mx-auto px-4 py-8", children: [
1089
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between mb-6", children: [
1090
+ /* @__PURE__ */ jsxRuntime.jsxs("h2", { className: "text-2xl font-bold", children: [
1091
+ "Banners (",
1092
+ count,
1093
+ ")"
1094
+ ] }),
1095
+ /* @__PURE__ */ jsxRuntime.jsxs(
1096
+ ui.Drawer,
1097
+ {
1098
+ open,
1099
+ onOpenChange: (openChanged) => setOpen(openChanged),
1100
+ children: [
1101
+ /* @__PURE__ */ jsxRuntime.jsx(
1102
+ ui.Drawer.Trigger,
1103
+ {
1104
+ onClick: () => {
1105
+ setOpen(true);
1106
+ },
1107
+ asChild: true,
1108
+ children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { isLoading, children: "Upload new banner" })
1109
+ }
1110
+ ),
1111
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Drawer.Content, { children: [
1112
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Title, { children: "Upload new banner" }) }),
1113
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Body, { children: /* @__PURE__ */ jsxRuntime.jsx(
1114
+ UploadBannerDrawerContent,
1115
+ {
1116
+ maxFileSizeMb: 10,
1117
+ onSuccess: () => {
1118
+ setOpen(false);
1119
+ refetch();
1120
+ }
1121
+ }
1122
+ ) })
1123
+ ] })
1124
+ ]
1125
+ }
1126
+ )
1127
+ ] }),
1128
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "container mx-auto px-4 py-8", children: [
1129
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center mb-6", children: [
1130
+ selectedIds.size > 0 && !reorderMode && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-2", children: /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1131
+ /* @__PURE__ */ jsxRuntime.jsx(
1132
+ ui.Button,
1133
+ {
1134
+ isLoading,
1135
+ onClick: selectAll,
1136
+ disabled: count === 0,
1137
+ children: "Select All"
1138
+ }
1139
+ ),
1140
+ /* @__PURE__ */ jsxRuntime.jsx(
1141
+ ui.Button,
1142
+ {
1143
+ isLoading,
1144
+ onClick: deselectAll,
1145
+ disabled: selectedIds.size === 0,
1146
+ children: "Deselect All"
1147
+ }
1148
+ ),
1149
+ /* @__PURE__ */ jsxRuntime.jsxs(
1150
+ ui.Button,
1151
+ {
1152
+ isLoading,
1153
+ variant: "danger",
1154
+ onClick: () => handleDeleteMultiple(),
1155
+ disabled: selectedIds.size === 0,
1156
+ children: [
1157
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-4 w-4" }),
1158
+ "Delete (",
1159
+ selectedIds.size,
1160
+ ")"
1161
+ ]
1162
+ }
1163
+ )
1164
+ ] }) }),
1165
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ml-auto", children: [
1166
+ banners.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
1167
+ ui.Button,
1168
+ {
1169
+ isLoading,
1170
+ onClick: toggleReorderMode,
1171
+ variant: reorderMode ? "secondary" : "primary",
1172
+ children: [
1173
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MoveHorizontal, { className: "h-4 w-4 mr-2" }),
1174
+ reorderMode ? "Exit Reorder" : "Reorder"
1175
+ ]
1176
+ }
1177
+ ),
1178
+ reorderMode && /* @__PURE__ */ jsxRuntime.jsxs(
1179
+ ui.Button,
1180
+ {
1181
+ isLoading,
1182
+ onClick: saveNewOrder,
1183
+ variant: "primary",
1184
+ className: "ml-2",
1185
+ children: [
1186
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "h-4 w-4 mr-2" }),
1187
+ "Save Order"
1188
+ ]
1189
+ }
1190
+ )
1191
+ ] })
1192
+ ] }),
1193
+ reorderMode ? /* @__PURE__ */ jsxRuntime.jsxs(
1194
+ core.DndContext,
1195
+ {
1196
+ sensors,
1197
+ collisionDetection: core.closestCenter,
1198
+ onDragStart: handleDragStart,
1199
+ onDragEnd: handleDragEnd,
1200
+ children: [
1201
+ /* @__PURE__ */ jsxRuntime.jsx(
1202
+ SortableContext,
1203
+ {
1204
+ items: orderedBanners.map((banner) => banner.id),
1205
+ strategy: rectSortingStrategy,
1206
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4 isolate", children: orderedBanners.map((banner) => /* @__PURE__ */ jsxRuntime.jsx(SortableItem, { banner }, banner.id)) })
1207
+ }
1208
+ ),
1209
+ /* @__PURE__ */ jsxRuntime.jsx(core.DragOverlay, { children: activeBanner ? /* @__PURE__ */ jsxRuntime.jsx(DraggableItem, { banner: activeBanner }) : null })
1210
+ ]
1211
+ }
1212
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4 group", children: banners.map((banner) => /* @__PURE__ */ jsxRuntime.jsx(
1213
+ GridItem,
1214
+ {
1215
+ banner,
1216
+ isSelected: selectedIds.has(banner.id),
1217
+ onClick: () => openLightbox(banner),
1218
+ onSelect: (e) => toggleImageSelection(e, banner.id)
1219
+ },
1220
+ banner.id
1221
+ )) }),
1222
+ selectedImage && /* @__PURE__ */ jsxRuntime.jsxs(
1223
+ "div",
1224
+ {
1225
+ className: "fixed inset-0 bg-black/80 z-50 flex items-center justify-center p-4",
1226
+ onClick: closeLightbox,
1227
+ children: [
1228
+ /* @__PURE__ */ jsxRuntime.jsx(
1229
+ ui.Button,
1230
+ {
1231
+ isLoading,
1232
+ className: "absolute top-4 right-4 text-white bg-black/50 p-2 rounded-full hover:bg-black/70",
1233
+ onClick: (e) => {
1234
+ e.stopPropagation();
1235
+ closeLightbox();
1236
+ },
1237
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-6 w-6" })
1238
+ }
1239
+ ),
1240
+ /* @__PURE__ */ jsxRuntime.jsx(
1241
+ "div",
1242
+ {
1243
+ className: "relative max-w-screen-xl max-h-screen overflow-auto",
1244
+ onClick: (e) => e.stopPropagation(),
1245
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1246
+ "img",
1247
+ {
1248
+ src: selectedImage.url || "/placeholder.svg",
1249
+ alt: `Banner ${selectedImage.id}`,
1250
+ className: "max-h-[90vh] max-w-full object-contain mx-auto"
1251
+ }
1252
+ )
1253
+ }
1254
+ )
1255
+ ]
1256
+ }
1257
+ )
1258
+ ] })
1259
+ ] }) });
1260
+ };
1261
+ const BannerUpload = () => {
1262
+ return /* @__PURE__ */ jsxRuntime.jsx(BannerPage, {});
1263
+ };
1264
+ const config = adminSdk.defineRouteConfig({
1265
+ label: "Banner",
1266
+ icon: icons.StackPerspective
1267
+ });
1268
+ const widgetModule = { widgets: [] };
1269
+ const routeModule = {
1270
+ routes: [
1271
+ {
1272
+ Component: BannerUpload,
1273
+ path: "/banners"
1274
+ }
1275
+ ]
1276
+ };
1277
+ const menuItemModule = {
1278
+ menuItems: [
1279
+ {
1280
+ label: config.label,
1281
+ icon: config.icon,
1282
+ path: "/banners",
1283
+ nested: void 0
1284
+ }
1285
+ ]
1286
+ };
1287
+ const formModule = { customFields: {} };
1288
+ const displayModule = {
1289
+ displays: {}
1290
+ };
1291
+ const plugin = {
1292
+ widgetModule,
1293
+ routeModule,
1294
+ menuItemModule,
1295
+ formModule,
1296
+ displayModule
1297
+ };
1298
+ module.exports = plugin;