@drawnagency/primitives 0.1.60 → 0.1.61

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,166 @@
1
+ import {
2
+ EditableGrid,
3
+ EditablePlainText,
4
+ EditableRichText,
5
+ ImageDropZone,
6
+ LinkPopover,
7
+ MediaBlock,
8
+ ResolvedMedia,
9
+ defineHeadingSection,
10
+ useEditableCollection
11
+ } from "../../chunk-4OX3Z7SB.js";
12
+ import {
13
+ DeleteIcon,
14
+ DragHandle,
15
+ IconButton
16
+ } from "../../chunk-WLMJCNU7.js";
17
+ import "../../chunk-CBWK3KPV.js";
18
+ import "../../chunk-53DKVAB6.js";
19
+ import {
20
+ cn
21
+ } from "../../chunk-7EOSDFS3.js";
22
+ import "../../chunk-ZGFAYZWB.js";
23
+ import "../../chunk-VKAGMEKE.js";
24
+ import "../../chunk-BT7STGDW.js";
25
+ import "../../chunk-JSBRDJBE.js";
26
+
27
+ // src/components/primitives/EditableList.tsx
28
+ import { useRef, useEffect, useState } from "react";
29
+ import { jsx, jsxs } from "react/jsx-runtime";
30
+ function EditableList({
31
+ items,
32
+ onChange,
33
+ createItem,
34
+ isEditMode,
35
+ renderItem,
36
+ className
37
+ }) {
38
+ const { wrappedItems, onReorder, onAdd, onRemove } = useEditableCollection({
39
+ items,
40
+ onChange,
41
+ createItem
42
+ });
43
+ const [dragState, setDragState] = useState({ sourceId: null, targetId: null });
44
+ if (!isEditMode) {
45
+ return /* @__PURE__ */ jsx("div", { className: cn("flex flex-col gap-2", className), children: wrappedItems.map((wrapped, index) => /* @__PURE__ */ jsx("div", { children: renderItem(wrapped.data, { isEditMode: false, index }) }, wrapped.id)) });
46
+ }
47
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-2", className), children: [
48
+ wrappedItems.map((wrapped, index) => /* @__PURE__ */ jsx(
49
+ ListRow,
50
+ {
51
+ id: wrapped.id,
52
+ index,
53
+ onReorder,
54
+ onRemove,
55
+ dragState,
56
+ setDragState,
57
+ children: renderItem(wrapped.data, { isEditMode: true, index })
58
+ },
59
+ wrapped.id
60
+ )),
61
+ /* @__PURE__ */ jsx(
62
+ "button",
63
+ {
64
+ onClick: onAdd,
65
+ className: "cursor-pointer rounded border-2 border-dashed border-base-200 px-3 py-2 text-sm text-base-contrast-light hover:border-primary hover:text-primary",
66
+ children: "Add row"
67
+ }
68
+ )
69
+ ] });
70
+ }
71
+ function ListRow({
72
+ id,
73
+ index,
74
+ onReorder,
75
+ onRemove,
76
+ dragState,
77
+ setDragState,
78
+ children
79
+ }) {
80
+ const rowRef = useRef(null);
81
+ const handleRef = useRef(null);
82
+ useEffect(() => {
83
+ const row = rowRef.current;
84
+ const handle = handleRef.current;
85
+ if (!row || !handle) return;
86
+ let cleanup;
87
+ let cancelled = false;
88
+ import("../../adapter-HH47ZPGM.js").then(({ draggable, dropTargetForElements }) => {
89
+ if (cancelled) return;
90
+ const cleanupDraggable = draggable({
91
+ element: handle,
92
+ getInitialData: () => ({ dragType: "list-row", id, index }),
93
+ onDragStart: () => setDragState({ sourceId: id, targetId: null }),
94
+ onDrop: () => setDragState({ sourceId: null, targetId: null })
95
+ });
96
+ const cleanupDropTarget = dropTargetForElements({
97
+ element: row,
98
+ canDrop: ({ source }) => source.data.dragType === "list-row",
99
+ getData: () => ({ id, index }),
100
+ onDragEnter: () => setDragState((prev) => ({ ...prev, targetId: id })),
101
+ onDragLeave: () => setDragState((prev) => prev.targetId === id ? { ...prev, targetId: null } : prev),
102
+ onDrop: ({ source }) => {
103
+ const fromIndex = source.data.index;
104
+ if (fromIndex !== index) {
105
+ onReorder(fromIndex, index);
106
+ }
107
+ }
108
+ });
109
+ cleanup = () => {
110
+ cleanupDraggable();
111
+ cleanupDropTarget();
112
+ };
113
+ });
114
+ return () => {
115
+ cancelled = true;
116
+ cleanup?.();
117
+ };
118
+ }, [id, index, onReorder, setDragState]);
119
+ const isDropTarget = dragState.targetId === id && dragState.sourceId !== id;
120
+ return /* @__PURE__ */ jsxs(
121
+ "div",
122
+ {
123
+ ref: rowRef,
124
+ className: cn(
125
+ "group/row relative flex items-center gap-2",
126
+ isDropTarget && "border-t-2 border-primary"
127
+ ),
128
+ children: [
129
+ /* @__PURE__ */ jsx(
130
+ IconButton,
131
+ {
132
+ ref: handleRef,
133
+ icon: /* @__PURE__ */ jsx(DragHandle, { size: 14 }),
134
+ label: "Drag to reorder",
135
+ size: "sm",
136
+ className: "shrink-0 cursor-grab opacity-0 group-hover/row:opacity-100 no-hover:opacity-100",
137
+ tabIndex: -1
138
+ }
139
+ ),
140
+ /* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1", children }),
141
+ /* @__PURE__ */ jsx(
142
+ IconButton,
143
+ {
144
+ icon: /* @__PURE__ */ jsx(DeleteIcon, { size: 14 }),
145
+ label: "Delete item",
146
+ size: "sm",
147
+ intent: "destructive",
148
+ onClick: () => onRemove(id),
149
+ className: "shrink-0 opacity-0 group-hover/row:opacity-100 no-hover:opacity-100"
150
+ }
151
+ )
152
+ ]
153
+ }
154
+ );
155
+ }
156
+ export {
157
+ EditableGrid,
158
+ EditableList,
159
+ EditablePlainText,
160
+ EditableRichText,
161
+ ImageDropZone,
162
+ LinkPopover,
163
+ MediaBlock,
164
+ ResolvedMedia,
165
+ defineHeadingSection
166
+ };