@seed-ship/mcp-ui-solid 2.0.1 → 2.1.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/components/AutocompleteDropdown.cjs +201 -0
- package/dist/components/AutocompleteDropdown.cjs.map +1 -0
- package/dist/components/AutocompleteDropdown.d.ts +71 -0
- package/dist/components/AutocompleteDropdown.d.ts.map +1 -0
- package/dist/components/AutocompleteDropdown.js +201 -0
- package/dist/components/AutocompleteDropdown.js.map +1 -0
- package/dist/components/AutocompleteFormField.cjs +289 -0
- package/dist/components/AutocompleteFormField.cjs.map +1 -0
- package/dist/components/AutocompleteFormField.d.ts +52 -0
- package/dist/components/AutocompleteFormField.d.ts.map +1 -0
- package/dist/components/AutocompleteFormField.js +289 -0
- package/dist/components/AutocompleteFormField.js.map +1 -0
- package/dist/components/DraggableGridItem.cjs +133 -0
- package/dist/components/DraggableGridItem.cjs.map +1 -0
- package/dist/components/DraggableGridItem.d.ts +95 -0
- package/dist/components/DraggableGridItem.d.ts.map +1 -0
- package/dist/components/DraggableGridItem.js +133 -0
- package/dist/components/DraggableGridItem.js.map +1 -0
- package/dist/components/EditableUIResourceRenderer.cjs +199 -0
- package/dist/components/EditableUIResourceRenderer.cjs.map +1 -0
- package/dist/components/EditableUIResourceRenderer.d.ts +43 -0
- package/dist/components/EditableUIResourceRenderer.d.ts.map +1 -0
- package/dist/components/EditableUIResourceRenderer.js +199 -0
- package/dist/components/EditableUIResourceRenderer.js.map +1 -0
- package/dist/components/GhostText.cjs +105 -0
- package/dist/components/GhostText.cjs.map +1 -0
- package/dist/components/GhostText.d.ts +113 -0
- package/dist/components/GhostText.d.ts.map +1 -0
- package/dist/components/GhostText.js +105 -0
- package/dist/components/GhostText.js.map +1 -0
- package/dist/components/ResizeHandle.cjs +177 -0
- package/dist/components/ResizeHandle.cjs.map +1 -0
- package/dist/components/ResizeHandle.d.ts +50 -0
- package/dist/components/ResizeHandle.d.ts.map +1 -0
- package/dist/components/ResizeHandle.js +177 -0
- package/dist/components/ResizeHandle.js.map +1 -0
- package/dist/context/AutocompleteContext.cjs +158 -0
- package/dist/context/AutocompleteContext.cjs.map +1 -0
- package/dist/context/AutocompleteContext.d.ts +77 -0
- package/dist/context/AutocompleteContext.d.ts.map +1 -0
- package/dist/context/AutocompleteContext.js +158 -0
- package/dist/context/AutocompleteContext.js.map +1 -0
- package/dist/hooks/index.d.ts +6 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/useAutocomplete.cjs +242 -0
- package/dist/hooks/useAutocomplete.cjs.map +1 -0
- package/dist/hooks/useAutocomplete.d.ts +119 -0
- package/dist/hooks/useAutocomplete.d.ts.map +1 -0
- package/dist/hooks/useAutocomplete.js +242 -0
- package/dist/hooks/useAutocomplete.js.map +1 -0
- package/dist/hooks/useDragDrop.cjs +170 -0
- package/dist/hooks/useDragDrop.cjs.map +1 -0
- package/dist/hooks/useDragDrop.d.ts +100 -0
- package/dist/hooks/useDragDrop.d.ts.map +1 -0
- package/dist/hooks/useDragDrop.js +170 -0
- package/dist/hooks/useDragDrop.js.map +1 -0
- package/dist/hooks/useResize.cjs +209 -0
- package/dist/hooks/useResize.cjs.map +1 -0
- package/dist/hooks/useResize.d.ts +87 -0
- package/dist/hooks/useResize.d.ts.map +1 -0
- package/dist/hooks/useResize.js +209 -0
- package/dist/hooks/useResize.js.map +1 -0
- package/dist/hooks.cjs +6 -0
- package/dist/hooks.cjs.map +1 -1
- package/dist/hooks.d.cts +6 -0
- package/dist/hooks.d.ts +6 -0
- package/dist/hooks.js +6 -0
- package/dist/hooks.js.map +1 -1
- package/dist/index.cjs +29 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -3
- package/dist/index.d.ts +18 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -1
- package/dist/plugins/duckdb.cjs +192 -0
- package/dist/plugins/duckdb.cjs.map +1 -0
- package/dist/plugins/duckdb.d.ts +20 -0
- package/dist/plugins/duckdb.d.ts.map +1 -0
- package/dist/plugins/duckdb.js +170 -0
- package/dist/plugins/duckdb.js.map +1 -0
- package/dist/plugins/groq.cjs +97 -0
- package/dist/plugins/groq.cjs.map +1 -0
- package/dist/plugins/groq.d.ts +13 -0
- package/dist/plugins/groq.d.ts.map +1 -0
- package/dist/plugins/groq.js +97 -0
- package/dist/plugins/groq.js.map +1 -0
- package/dist/plugins/index.d.ts +10 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/rest.cjs +92 -0
- package/dist/plugins/rest.cjs.map +1 -0
- package/dist/plugins/rest.d.ts +13 -0
- package/dist/plugins/rest.d.ts.map +1 -0
- package/dist/plugins/rest.js +92 -0
- package/dist/plugins/rest.js.map +1 -0
- package/dist/plugins/supabase.cjs +79 -0
- package/dist/plugins/supabase.cjs.map +1 -0
- package/dist/plugins/supabase.d.ts +13 -0
- package/dist/plugins/supabase.d.ts.map +1 -0
- package/dist/plugins/supabase.js +79 -0
- package/dist/plugins/supabase.js.map +1 -0
- package/dist/types/index.d.ts +430 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types.d.cts +430 -0
- package/dist/types.d.ts +430 -0
- package/esbuild-why-Full bundle (with deps).html +51 -0
- package/esbuild-why-Hooks only.html +51 -0
- package/esbuild-why-Streaming renderer.html +51 -0
- package/package.json +16 -1
- package/src/components/AutocompleteDropdown.tsx +329 -0
- package/src/components/AutocompleteFormField.tsx +288 -0
- package/src/components/DraggableGridItem.tsx +274 -0
- package/src/components/EditableUIResourceRenderer.tsx +268 -0
- package/src/components/GhostText.tsx +262 -0
- package/src/components/ResizeHandle.tsx +267 -0
- package/src/context/AutocompleteContext.tsx +317 -0
- package/src/hooks/index.ts +23 -0
- package/src/hooks/useAutocomplete.test.ts +334 -0
- package/src/hooks/useAutocomplete.ts +482 -0
- package/src/hooks/useDragDrop.test.ts +355 -0
- package/src/hooks/useDragDrop.ts +379 -0
- package/src/hooks/useResize.test.ts +313 -0
- package/src/hooks/useResize.ts +372 -0
- package/src/index.ts +71 -0
- package/src/plugins/duckdb.ts +269 -0
- package/src/plugins/groq.ts +137 -0
- package/src/plugins/index.ts +14 -0
- package/src/plugins/rest.ts +147 -0
- package/src/plugins/supabase.ts +120 -0
- package/src/styles/autocomplete.css +356 -0
- package/src/styles/drag-drop.css +297 -0
- package/src/styles/index.css +7 -0
- package/src/types/index.ts +529 -0
- package/src/vite-env.d.ts +18 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/vite.config.ts +2 -0
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { createSignal, onCleanup, batch } from "solid-js";
|
|
2
|
+
function getDropPosition(e, targetElement) {
|
|
3
|
+
const rect = targetElement.getBoundingClientRect();
|
|
4
|
+
const midY = rect.top + rect.height / 2;
|
|
5
|
+
return e.clientY < midY ? "before" : "after";
|
|
6
|
+
}
|
|
7
|
+
function reorderComponents(components, sourceId, targetId, position) {
|
|
8
|
+
const sourceIndex = components.findIndex((c) => c.id === sourceId);
|
|
9
|
+
const targetIndex = components.findIndex((c) => c.id === targetId);
|
|
10
|
+
if (sourceIndex === -1 || targetIndex === -1 || sourceIndex === targetIndex) {
|
|
11
|
+
return components;
|
|
12
|
+
}
|
|
13
|
+
const result = [...components];
|
|
14
|
+
const [sourceComponent] = result.splice(sourceIndex, 1);
|
|
15
|
+
let newTargetIndex = result.findIndex((c) => c.id === targetId);
|
|
16
|
+
if (position === "after") {
|
|
17
|
+
newTargetIndex += 1;
|
|
18
|
+
}
|
|
19
|
+
result.splice(newTargetIndex, 0, sourceComponent);
|
|
20
|
+
return recalculatePositions(result);
|
|
21
|
+
}
|
|
22
|
+
function recalculatePositions(components) {
|
|
23
|
+
let currentRow = 1;
|
|
24
|
+
const rowComponents = /* @__PURE__ */ new Map();
|
|
25
|
+
components.forEach((c, index) => {
|
|
26
|
+
const row = c.position.rowStart || index + 1;
|
|
27
|
+
if (!rowComponents.has(row)) {
|
|
28
|
+
rowComponents.set(row, []);
|
|
29
|
+
}
|
|
30
|
+
rowComponents.get(row).push(c);
|
|
31
|
+
});
|
|
32
|
+
const result = [];
|
|
33
|
+
const sortedRows = Array.from(rowComponents.keys()).sort((a, b) => a - b);
|
|
34
|
+
sortedRows.forEach((row) => {
|
|
35
|
+
const rowComps = rowComponents.get(row);
|
|
36
|
+
rowComps.forEach((c) => {
|
|
37
|
+
result.push({
|
|
38
|
+
...c,
|
|
39
|
+
position: {
|
|
40
|
+
...c.position,
|
|
41
|
+
rowStart: currentRow
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
currentRow += Math.max(...rowComps.map((c) => c.position.rowSpan || 1));
|
|
46
|
+
});
|
|
47
|
+
return result;
|
|
48
|
+
}
|
|
49
|
+
function useDragDrop(options) {
|
|
50
|
+
const {
|
|
51
|
+
components,
|
|
52
|
+
onReorder,
|
|
53
|
+
enabled = true
|
|
54
|
+
} = options;
|
|
55
|
+
const [draggedId, setDraggedId] = createSignal(null);
|
|
56
|
+
const [dropTargetId, setDropTargetId] = createSignal(null);
|
|
57
|
+
const [dropPosition, setDropPosition] = createSignal("after");
|
|
58
|
+
const isDragging = () => draggedId() !== null;
|
|
59
|
+
let dragCounter = 0;
|
|
60
|
+
const handleDragStart = (e, componentId) => {
|
|
61
|
+
if (!enabled) {
|
|
62
|
+
e.preventDefault();
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
const target = e.currentTarget;
|
|
66
|
+
e.dataTransfer.effectAllowed = "move";
|
|
67
|
+
e.dataTransfer.setData("text/plain", componentId);
|
|
68
|
+
if (target) {
|
|
69
|
+
const rect = target.getBoundingClientRect();
|
|
70
|
+
e.dataTransfer.setDragImage(target, rect.width / 2, 20);
|
|
71
|
+
}
|
|
72
|
+
requestAnimationFrame(() => {
|
|
73
|
+
setDraggedId(componentId);
|
|
74
|
+
});
|
|
75
|
+
};
|
|
76
|
+
const handleDragOver = (e, componentId) => {
|
|
77
|
+
if (!enabled || !draggedId() || draggedId() === componentId) {
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
e.preventDefault();
|
|
81
|
+
e.dataTransfer.dropEffect = "move";
|
|
82
|
+
const target = e.currentTarget;
|
|
83
|
+
const position = getDropPosition(e, target);
|
|
84
|
+
setDropPosition(position);
|
|
85
|
+
};
|
|
86
|
+
const handleDragEnter = (e, componentId) => {
|
|
87
|
+
if (!enabled || !draggedId() || draggedId() === componentId) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
e.preventDefault();
|
|
91
|
+
dragCounter++;
|
|
92
|
+
setDropTargetId(componentId);
|
|
93
|
+
};
|
|
94
|
+
const handleDragLeave = (_e) => {
|
|
95
|
+
if (!enabled) return;
|
|
96
|
+
dragCounter--;
|
|
97
|
+
if (dragCounter === 0) {
|
|
98
|
+
setDropTargetId(null);
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
const handleDrop = (e, targetId) => {
|
|
102
|
+
if (!enabled) return;
|
|
103
|
+
e.preventDefault();
|
|
104
|
+
dragCounter = 0;
|
|
105
|
+
const sourceId = e.dataTransfer.getData("text/plain");
|
|
106
|
+
if (!sourceId || sourceId === targetId) {
|
|
107
|
+
batch(() => {
|
|
108
|
+
setDraggedId(null);
|
|
109
|
+
setDropTargetId(null);
|
|
110
|
+
});
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const currentComponents = components();
|
|
114
|
+
const reordered = reorderComponents(
|
|
115
|
+
currentComponents,
|
|
116
|
+
sourceId,
|
|
117
|
+
targetId,
|
|
118
|
+
dropPosition()
|
|
119
|
+
);
|
|
120
|
+
batch(() => {
|
|
121
|
+
setDraggedId(null);
|
|
122
|
+
setDropTargetId(null);
|
|
123
|
+
});
|
|
124
|
+
onReorder(reordered);
|
|
125
|
+
};
|
|
126
|
+
const handleDragEnd = (_e) => {
|
|
127
|
+
dragCounter = 0;
|
|
128
|
+
batch(() => {
|
|
129
|
+
setDraggedId(null);
|
|
130
|
+
setDropTargetId(null);
|
|
131
|
+
});
|
|
132
|
+
};
|
|
133
|
+
const getDragProps = (componentId) => ({
|
|
134
|
+
draggable: enabled,
|
|
135
|
+
onDragStart: (e) => handleDragStart(e, componentId),
|
|
136
|
+
onDragOver: (e) => handleDragOver(e, componentId),
|
|
137
|
+
onDragEnter: (e) => handleDragEnter(e, componentId),
|
|
138
|
+
onDragLeave: handleDragLeave,
|
|
139
|
+
onDrop: (e) => handleDrop(e, componentId),
|
|
140
|
+
onDragEnd: handleDragEnd,
|
|
141
|
+
"data-component-id": componentId
|
|
142
|
+
});
|
|
143
|
+
const isComponentDragging = (componentId) => {
|
|
144
|
+
return draggedId() === componentId;
|
|
145
|
+
};
|
|
146
|
+
const isDropTarget = (componentId) => {
|
|
147
|
+
return dropTargetId() === componentId;
|
|
148
|
+
};
|
|
149
|
+
onCleanup(() => {
|
|
150
|
+
dragCounter = 0;
|
|
151
|
+
});
|
|
152
|
+
return {
|
|
153
|
+
draggedId,
|
|
154
|
+
dropTargetId,
|
|
155
|
+
isDragging,
|
|
156
|
+
handleDragStart,
|
|
157
|
+
handleDragOver,
|
|
158
|
+
handleDragEnter,
|
|
159
|
+
handleDragLeave,
|
|
160
|
+
handleDrop,
|
|
161
|
+
handleDragEnd,
|
|
162
|
+
getDragProps,
|
|
163
|
+
isComponentDragging,
|
|
164
|
+
isDropTarget
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
export {
|
|
168
|
+
useDragDrop
|
|
169
|
+
};
|
|
170
|
+
//# sourceMappingURL=useDragDrop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDragDrop.js","sources":["../../src/hooks/useDragDrop.ts"],"sourcesContent":["/**\n * useDragDrop Hook\n * Handles drag-and-drop reordering of grid components using HTML5 Drag-Drop API\n *\n * Sprint Drag-Drop Feature\n */\n\nimport { createSignal, Accessor, batch, onCleanup } from 'solid-js'\nimport type { UIComponent } from '../types'\n\n/**\n * Options for the useDragDrop hook\n */\nexport interface UseDragDropOptions {\n /**\n * Accessor for current components\n */\n components: Accessor<UIComponent[]>\n\n /**\n * Callback when components are reordered\n */\n onReorder: (newComponents: UIComponent[]) => void\n\n /**\n * Whether drag-drop is enabled\n */\n enabled?: boolean\n\n /**\n * Animation duration in ms\n */\n animationDuration?: number\n}\n\n/**\n * Props to apply to a draggable element\n */\nexport interface DragProps {\n draggable: boolean\n onDragStart: (e: DragEvent) => void\n onDragOver: (e: DragEvent) => void\n onDragEnter: (e: DragEvent) => void\n onDragLeave: (e: DragEvent) => void\n onDrop: (e: DragEvent) => void\n onDragEnd: (e: DragEvent) => void\n 'data-component-id': string\n}\n\n/**\n * Return type for the useDragDrop hook\n */\nexport interface UseDragDropReturn {\n /**\n * ID of the component currently being dragged\n */\n draggedId: Accessor<string | null>\n\n /**\n * ID of the current drop target\n */\n dropTargetId: Accessor<string | null>\n\n /**\n * Whether a drag operation is in progress\n */\n isDragging: Accessor<boolean>\n\n /**\n * Handle drag start event\n */\n handleDragStart: (e: DragEvent, componentId: string) => void\n\n /**\n * Handle drag over event\n */\n handleDragOver: (e: DragEvent, componentId: string) => void\n\n /**\n * Handle drag enter event\n */\n handleDragEnter: (e: DragEvent, componentId: string) => void\n\n /**\n * Handle drag leave event\n */\n handleDragLeave: (e: DragEvent) => void\n\n /**\n * Handle drop event\n */\n handleDrop: (e: DragEvent, targetId: string) => void\n\n /**\n * Handle drag end event\n */\n handleDragEnd: (e: DragEvent) => void\n\n /**\n * Get drag props for a component\n */\n getDragProps: (componentId: string) => DragProps\n\n /**\n * Check if a component is being dragged\n */\n isComponentDragging: (componentId: string) => boolean\n\n /**\n * Check if a component is a drop target\n */\n isDropTarget: (componentId: string) => boolean\n}\n\n/**\n * Calculate drop position based on mouse position relative to target\n */\nfunction getDropPosition(\n e: DragEvent,\n targetElement: HTMLElement\n): 'before' | 'after' {\n const rect = targetElement.getBoundingClientRect()\n const midY = rect.top + rect.height / 2\n return e.clientY < midY ? 'before' : 'after'\n}\n\n/**\n * Reorder components by inserting source at a position relative to target\n */\nfunction reorderComponents(\n components: UIComponent[],\n sourceId: string,\n targetId: string,\n position: 'before' | 'after'\n): UIComponent[] {\n const sourceIndex = components.findIndex(c => c.id === sourceId)\n const targetIndex = components.findIndex(c => c.id === targetId)\n\n if (sourceIndex === -1 || targetIndex === -1 || sourceIndex === targetIndex) {\n return components\n }\n\n // Create a copy and remove source\n const result = [...components]\n const [sourceComponent] = result.splice(sourceIndex, 1)\n\n // Find new target index (accounting for removal)\n let newTargetIndex = result.findIndex(c => c.id === targetId)\n if (position === 'after') {\n newTargetIndex += 1\n }\n\n // Insert at new position\n result.splice(newTargetIndex, 0, sourceComponent)\n\n // Recalculate row positions based on new order\n return recalculatePositions(result)\n}\n\n/**\n * Recalculate grid positions after reordering\n * Assigns sequential row positions while preserving column layout\n */\nfunction recalculatePositions(components: UIComponent[]): UIComponent[] {\n let currentRow = 1\n const rowComponents: Map<number, UIComponent[]> = new Map()\n\n // Group by original row\n components.forEach((c, index) => {\n const row = c.position.rowStart || index + 1\n if (!rowComponents.has(row)) {\n rowComponents.set(row, [])\n }\n rowComponents.get(row)!.push(c)\n })\n\n // Flatten with new row assignments\n const result: UIComponent[] = []\n const sortedRows = Array.from(rowComponents.keys()).sort((a, b) => a - b)\n\n sortedRows.forEach(row => {\n const rowComps = rowComponents.get(row)!\n rowComps.forEach(c => {\n result.push({\n ...c,\n position: {\n ...c.position,\n rowStart: currentRow\n }\n })\n })\n currentRow += Math.max(...rowComps.map(c => c.position.rowSpan || 1))\n })\n\n return result\n}\n\n/**\n * Hook for handling drag-and-drop reordering of grid components\n */\nexport function useDragDrop(options: UseDragDropOptions): UseDragDropReturn {\n const {\n components,\n onReorder,\n enabled = true\n } = options\n\n const [draggedId, setDraggedId] = createSignal<string | null>(null)\n const [dropTargetId, setDropTargetId] = createSignal<string | null>(null)\n const [dropPosition, setDropPosition] = createSignal<'before' | 'after'>('after')\n const isDragging = () => draggedId() !== null\n\n // Track drag counter for nested elements\n let dragCounter = 0\n\n /**\n * Handle drag start\n */\n const handleDragStart = (e: DragEvent, componentId: string) => {\n if (!enabled) {\n e.preventDefault()\n return\n }\n\n const target = e.currentTarget as HTMLElement\n\n // Set drag data\n e.dataTransfer!.effectAllowed = 'move'\n e.dataTransfer!.setData('text/plain', componentId)\n\n // Create drag image\n if (target) {\n const rect = target.getBoundingClientRect()\n e.dataTransfer!.setDragImage(target, rect.width / 2, 20)\n }\n\n // Delay setting state to allow drag image to be captured\n requestAnimationFrame(() => {\n setDraggedId(componentId)\n })\n }\n\n /**\n * Handle drag over\n */\n const handleDragOver = (e: DragEvent, componentId: string) => {\n if (!enabled || !draggedId() || draggedId() === componentId) {\n return\n }\n\n e.preventDefault()\n e.dataTransfer!.dropEffect = 'move'\n\n // Calculate drop position\n const target = e.currentTarget as HTMLElement\n const position = getDropPosition(e, target)\n setDropPosition(position)\n }\n\n /**\n * Handle drag enter\n */\n const handleDragEnter = (e: DragEvent, componentId: string) => {\n if (!enabled || !draggedId() || draggedId() === componentId) {\n return\n }\n\n e.preventDefault()\n dragCounter++\n setDropTargetId(componentId)\n }\n\n /**\n * Handle drag leave\n */\n const handleDragLeave = (_e: DragEvent) => {\n if (!enabled) return\n\n dragCounter--\n if (dragCounter === 0) {\n setDropTargetId(null)\n }\n }\n\n /**\n * Handle drop\n */\n const handleDrop = (e: DragEvent, targetId: string) => {\n if (!enabled) return\n\n e.preventDefault()\n dragCounter = 0\n\n const sourceId = e.dataTransfer!.getData('text/plain')\n if (!sourceId || sourceId === targetId) {\n batch(() => {\n setDraggedId(null)\n setDropTargetId(null)\n })\n return\n }\n\n // Reorder components\n const currentComponents = components()\n const reordered = reorderComponents(\n currentComponents,\n sourceId,\n targetId,\n dropPosition()\n )\n\n // Apply reorder\n batch(() => {\n setDraggedId(null)\n setDropTargetId(null)\n })\n\n onReorder(reordered)\n }\n\n /**\n * Handle drag end\n */\n const handleDragEnd = (_e: DragEvent) => {\n dragCounter = 0\n batch(() => {\n setDraggedId(null)\n setDropTargetId(null)\n })\n }\n\n /**\n * Get drag props for a component\n */\n const getDragProps = (componentId: string): DragProps => ({\n draggable: enabled,\n onDragStart: (e) => handleDragStart(e, componentId),\n onDragOver: (e) => handleDragOver(e, componentId),\n onDragEnter: (e) => handleDragEnter(e, componentId),\n onDragLeave: handleDragLeave,\n onDrop: (e) => handleDrop(e, componentId),\n onDragEnd: handleDragEnd,\n 'data-component-id': componentId\n })\n\n /**\n * Check if a component is being dragged\n */\n const isComponentDragging = (componentId: string): boolean => {\n return draggedId() === componentId\n }\n\n /**\n * Check if a component is a drop target\n */\n const isDropTarget = (componentId: string): boolean => {\n return dropTargetId() === componentId\n }\n\n // Cleanup on unmount\n onCleanup(() => {\n dragCounter = 0\n })\n\n return {\n draggedId,\n dropTargetId,\n isDragging,\n handleDragStart,\n handleDragOver,\n handleDragEnter,\n handleDragLeave,\n handleDrop,\n handleDragEnd,\n getDragProps,\n isComponentDragging,\n isDropTarget\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const solidJs = require("solid-js");
|
|
4
|
+
const web = require("solid-js/web");
|
|
5
|
+
function applyConstraints(position, constraints, gridColumns) {
|
|
6
|
+
let { colStart, colSpan, rowStart, rowSpan } = position;
|
|
7
|
+
const minColSpan = constraints.minColSpan ?? 1;
|
|
8
|
+
const maxColSpan = constraints.maxColSpan ?? gridColumns;
|
|
9
|
+
colSpan = Math.max(minColSpan, Math.min(maxColSpan, colSpan));
|
|
10
|
+
if (colStart + colSpan - 1 > gridColumns) {
|
|
11
|
+
colStart = gridColumns - colSpan + 1;
|
|
12
|
+
}
|
|
13
|
+
colStart = Math.max(1, colStart);
|
|
14
|
+
if (rowSpan !== void 0) {
|
|
15
|
+
const minRowSpan = constraints.minRowSpan ?? 1;
|
|
16
|
+
const maxRowSpan = constraints.maxRowSpan ?? 99;
|
|
17
|
+
rowSpan = Math.max(minRowSpan, Math.min(maxRowSpan, rowSpan));
|
|
18
|
+
}
|
|
19
|
+
if (rowStart !== void 0) {
|
|
20
|
+
rowStart = Math.max(1, rowStart);
|
|
21
|
+
}
|
|
22
|
+
return { colStart, colSpan, rowStart, rowSpan };
|
|
23
|
+
}
|
|
24
|
+
function useResize(options) {
|
|
25
|
+
const {
|
|
26
|
+
currentPosition,
|
|
27
|
+
onResize,
|
|
28
|
+
onResizePreview,
|
|
29
|
+
constraints = {},
|
|
30
|
+
gridContainer,
|
|
31
|
+
gridColumns = 12,
|
|
32
|
+
enabled = true
|
|
33
|
+
} = options;
|
|
34
|
+
const [isResizing, setIsResizing] = solidJs.createSignal(false);
|
|
35
|
+
const [resizeEdge, setResizeEdge] = solidJs.createSignal(null);
|
|
36
|
+
const [previewPosition, setPreviewPosition] = solidJs.createSignal(null);
|
|
37
|
+
const [startPosition, setStartPosition] = solidJs.createSignal(null);
|
|
38
|
+
const [startPointer, setStartPointer] = solidJs.createSignal(null);
|
|
39
|
+
if (web.isServer) {
|
|
40
|
+
return {
|
|
41
|
+
isResizing: () => false,
|
|
42
|
+
resizeEdge: () => null,
|
|
43
|
+
previewPosition: () => null,
|
|
44
|
+
handleResizeStart: () => {
|
|
45
|
+
},
|
|
46
|
+
getResizeHandleProps: () => ({
|
|
47
|
+
onPointerDown: () => {
|
|
48
|
+
},
|
|
49
|
+
style: {},
|
|
50
|
+
"data-resize-edge": "right"
|
|
51
|
+
})
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
const handlePointerMove = (e) => {
|
|
55
|
+
if (!isResizing() || !startPosition() || !startPointer()) return;
|
|
56
|
+
const edge = resizeEdge();
|
|
57
|
+
if (!edge) return;
|
|
58
|
+
const container = (gridContainer == null ? void 0 : gridContainer()) || document.querySelector("[data-grid-container]");
|
|
59
|
+
if (!container) return;
|
|
60
|
+
const containerRect = container.getBoundingClientRect();
|
|
61
|
+
const currentPos = startPosition();
|
|
62
|
+
const start = startPointer();
|
|
63
|
+
let newPosition = { ...currentPos };
|
|
64
|
+
const deltaX = e.clientX - start.x;
|
|
65
|
+
const columnWidth = containerRect.width / gridColumns;
|
|
66
|
+
const columnDelta = Math.round(deltaX / columnWidth);
|
|
67
|
+
if (constraints.lockHorizontal && (edge === "left" || edge === "right")) ;
|
|
68
|
+
else {
|
|
69
|
+
switch (edge) {
|
|
70
|
+
case "right": {
|
|
71
|
+
const newColSpan = currentPos.colSpan + columnDelta;
|
|
72
|
+
newPosition.colSpan = Math.max(1, Math.min(gridColumns - currentPos.colStart + 1, newColSpan));
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
case "left": {
|
|
76
|
+
const newColStart = currentPos.colStart + columnDelta;
|
|
77
|
+
const newColSpan = currentPos.colSpan - columnDelta;
|
|
78
|
+
if (newColStart >= 1 && newColSpan >= 1) {
|
|
79
|
+
newPosition.colStart = newColStart;
|
|
80
|
+
newPosition.colSpan = newColSpan;
|
|
81
|
+
}
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
case "top":
|
|
85
|
+
case "bottom": {
|
|
86
|
+
if (!constraints.lockVertical) {
|
|
87
|
+
const rowHeight = 100;
|
|
88
|
+
const deltaY = e.clientY - start.y;
|
|
89
|
+
const rowDelta = Math.round(deltaY / rowHeight);
|
|
90
|
+
if (edge === "bottom") {
|
|
91
|
+
const currentRowSpan = currentPos.rowSpan || 1;
|
|
92
|
+
const newRowSpan = currentRowSpan + rowDelta;
|
|
93
|
+
newPosition.rowSpan = Math.max(1, newRowSpan);
|
|
94
|
+
} else if (edge === "top") {
|
|
95
|
+
const currentRowStart = currentPos.rowStart || 1;
|
|
96
|
+
const currentRowSpan = currentPos.rowSpan || 1;
|
|
97
|
+
const newRowStart = currentRowStart + rowDelta;
|
|
98
|
+
const newRowSpan = currentRowSpan - rowDelta;
|
|
99
|
+
if (newRowStart >= 1 && newRowSpan >= 1) {
|
|
100
|
+
newPosition.rowStart = newRowStart;
|
|
101
|
+
newPosition.rowSpan = newRowSpan;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
newPosition = applyConstraints(newPosition, constraints, gridColumns);
|
|
110
|
+
setPreviewPosition(newPosition);
|
|
111
|
+
onResizePreview == null ? void 0 : onResizePreview(newPosition);
|
|
112
|
+
};
|
|
113
|
+
const handlePointerUp = (_e) => {
|
|
114
|
+
if (!isResizing()) return;
|
|
115
|
+
const preview = previewPosition();
|
|
116
|
+
if (preview) {
|
|
117
|
+
onResize(preview);
|
|
118
|
+
}
|
|
119
|
+
setIsResizing(false);
|
|
120
|
+
setResizeEdge(null);
|
|
121
|
+
setPreviewPosition(null);
|
|
122
|
+
setStartPosition(null);
|
|
123
|
+
setStartPointer(null);
|
|
124
|
+
document.removeEventListener("pointermove", handlePointerMove);
|
|
125
|
+
document.removeEventListener("pointerup", handlePointerUp);
|
|
126
|
+
document.body.style.cursor = "";
|
|
127
|
+
document.body.style.userSelect = "";
|
|
128
|
+
};
|
|
129
|
+
const handleResizeStart = (e, edge) => {
|
|
130
|
+
if (!enabled) return;
|
|
131
|
+
e.preventDefault();
|
|
132
|
+
e.stopPropagation();
|
|
133
|
+
setIsResizing(true);
|
|
134
|
+
setResizeEdge(edge);
|
|
135
|
+
setStartPosition(currentPosition());
|
|
136
|
+
setStartPointer({ x: e.clientX, y: e.clientY });
|
|
137
|
+
setPreviewPosition(currentPosition());
|
|
138
|
+
const cursors = {
|
|
139
|
+
left: "ew-resize",
|
|
140
|
+
right: "ew-resize",
|
|
141
|
+
top: "ns-resize",
|
|
142
|
+
bottom: "ns-resize"
|
|
143
|
+
};
|
|
144
|
+
document.body.style.cursor = cursors[edge];
|
|
145
|
+
document.body.style.userSelect = "none";
|
|
146
|
+
document.addEventListener("pointermove", handlePointerMove);
|
|
147
|
+
document.addEventListener("pointerup", handlePointerUp);
|
|
148
|
+
};
|
|
149
|
+
const getResizeHandleProps = (edge) => {
|
|
150
|
+
const baseStyle = {
|
|
151
|
+
position: "absolute",
|
|
152
|
+
zIndex: "10"
|
|
153
|
+
};
|
|
154
|
+
const edgeStyles = {
|
|
155
|
+
left: {
|
|
156
|
+
...baseStyle,
|
|
157
|
+
left: "-4px",
|
|
158
|
+
top: "0",
|
|
159
|
+
width: "8px",
|
|
160
|
+
height: "100%",
|
|
161
|
+
cursor: "ew-resize"
|
|
162
|
+
},
|
|
163
|
+
right: {
|
|
164
|
+
...baseStyle,
|
|
165
|
+
right: "-4px",
|
|
166
|
+
top: "0",
|
|
167
|
+
width: "8px",
|
|
168
|
+
height: "100%",
|
|
169
|
+
cursor: "ew-resize"
|
|
170
|
+
},
|
|
171
|
+
top: {
|
|
172
|
+
...baseStyle,
|
|
173
|
+
top: "-4px",
|
|
174
|
+
left: "0",
|
|
175
|
+
width: "100%",
|
|
176
|
+
height: "8px",
|
|
177
|
+
cursor: "ns-resize"
|
|
178
|
+
},
|
|
179
|
+
bottom: {
|
|
180
|
+
...baseStyle,
|
|
181
|
+
bottom: "-4px",
|
|
182
|
+
left: "0",
|
|
183
|
+
width: "100%",
|
|
184
|
+
height: "8px",
|
|
185
|
+
cursor: "ns-resize"
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
return {
|
|
189
|
+
onPointerDown: (e) => handleResizeStart(e, edge),
|
|
190
|
+
style: edgeStyles[edge],
|
|
191
|
+
"data-resize-edge": edge
|
|
192
|
+
};
|
|
193
|
+
};
|
|
194
|
+
solidJs.onCleanup(() => {
|
|
195
|
+
document.removeEventListener("pointermove", handlePointerMove);
|
|
196
|
+
document.removeEventListener("pointerup", handlePointerUp);
|
|
197
|
+
document.body.style.cursor = "";
|
|
198
|
+
document.body.style.userSelect = "";
|
|
199
|
+
});
|
|
200
|
+
return {
|
|
201
|
+
isResizing,
|
|
202
|
+
resizeEdge,
|
|
203
|
+
previewPosition,
|
|
204
|
+
handleResizeStart,
|
|
205
|
+
getResizeHandleProps
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
exports.useResize = useResize;
|
|
209
|
+
//# sourceMappingURL=useResize.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useResize.cjs","sources":["../../src/hooks/useResize.ts"],"sourcesContent":["/**\n * useResize Hook\n * Handles resizing of grid components by dragging edges\n *\n * Sprint Drag-Drop Feature\n */\n\nimport { createSignal, Accessor, onCleanup } from 'solid-js'\nimport { isServer } from 'solid-js/web'\nimport type { GridPosition, ResizeConstraints } from '../types'\n\n/**\n * Resize edge types\n */\nexport type ResizeEdge = 'left' | 'right' | 'top' | 'bottom'\n\n/**\n * Options for the useResize hook\n */\nexport interface UseResizeOptions {\n /**\n * Component ID being resized\n */\n componentId: string\n\n /**\n * Current grid position accessor\n */\n currentPosition: Accessor<GridPosition>\n\n /**\n * Callback when resize is complete\n */\n onResize: (newPosition: GridPosition) => void\n\n /**\n * Callback during resize (for preview)\n */\n onResizePreview?: (previewPosition: GridPosition) => void\n\n /**\n * Resize constraints\n */\n constraints?: ResizeConstraints\n\n /**\n * Grid container element for calculating column widths\n */\n gridContainer?: Accessor<HTMLElement | null>\n\n /**\n * Number of columns in the grid (default: 12)\n */\n gridColumns?: number\n\n /**\n * Whether resize is enabled\n */\n enabled?: boolean\n}\n\n/**\n * Return type for the useResize hook\n */\nexport interface UseResizeReturn {\n /**\n * Whether a resize is in progress\n */\n isResizing: Accessor<boolean>\n\n /**\n * Current resize edge\n */\n resizeEdge: Accessor<ResizeEdge | null>\n\n /**\n * Preview position during resize\n */\n previewPosition: Accessor<GridPosition | null>\n\n /**\n * Start resize operation\n */\n handleResizeStart: (e: PointerEvent, edge: ResizeEdge) => void\n\n /**\n * Get resize handle props for an edge\n */\n getResizeHandleProps: (edge: ResizeEdge) => ResizeHandleProps\n}\n\n/**\n * Props for resize handles\n */\nexport interface ResizeHandleProps {\n onPointerDown: (e: PointerEvent) => void\n style: Record<string, string>\n 'data-resize-edge': ResizeEdge\n}\n\n/**\n * Apply constraints to a position\n */\nfunction applyConstraints(\n position: GridPosition,\n constraints: ResizeConstraints,\n gridColumns: number\n): GridPosition {\n let { colStart, colSpan, rowStart, rowSpan } = position\n\n // Apply column constraints\n const minColSpan = constraints.minColSpan ?? 1\n const maxColSpan = constraints.maxColSpan ?? gridColumns\n\n colSpan = Math.max(minColSpan, Math.min(maxColSpan, colSpan))\n\n // Ensure colStart + colSpan doesn't exceed grid\n if (colStart + colSpan - 1 > gridColumns) {\n colStart = gridColumns - colSpan + 1\n }\n colStart = Math.max(1, colStart)\n\n // Apply row constraints\n if (rowSpan !== undefined) {\n const minRowSpan = constraints.minRowSpan ?? 1\n const maxRowSpan = constraints.maxRowSpan ?? 99\n rowSpan = Math.max(minRowSpan, Math.min(maxRowSpan, rowSpan))\n }\n\n if (rowStart !== undefined) {\n rowStart = Math.max(1, rowStart)\n }\n\n return { colStart, colSpan, rowStart, rowSpan }\n}\n\n/**\n * Hook for handling resize of grid components\n */\nexport function useResize(options: UseResizeOptions): UseResizeReturn {\n const {\n currentPosition,\n onResize,\n onResizePreview,\n constraints = {},\n gridContainer,\n gridColumns = 12,\n enabled = true\n } = options\n\n const [isResizing, setIsResizing] = createSignal(false)\n const [resizeEdge, setResizeEdge] = createSignal<ResizeEdge | null>(null)\n const [previewPosition, setPreviewPosition] = createSignal<GridPosition | null>(null)\n const [startPosition, setStartPosition] = createSignal<GridPosition | null>(null)\n const [startPointer, setStartPointer] = createSignal<{ x: number; y: number } | null>(null)\n\n // Skip on server\n if (isServer) {\n return {\n isResizing: () => false,\n resizeEdge: () => null,\n previewPosition: () => null,\n handleResizeStart: () => {},\n getResizeHandleProps: () => ({\n onPointerDown: () => {},\n style: {},\n 'data-resize-edge': 'right' as ResizeEdge\n })\n }\n }\n\n /**\n * Handle pointer move during resize\n */\n const handlePointerMove = (e: PointerEvent) => {\n if (!isResizing() || !startPosition() || !startPointer()) return\n\n const edge = resizeEdge()\n if (!edge) return\n\n // Get container for measurements\n const container = gridContainer?.() || document.querySelector('[data-grid-container]')\n if (!container) return\n\n const containerRect = container.getBoundingClientRect()\n const currentPos = startPosition()!\n const start = startPointer()!\n\n let newPosition: GridPosition = { ...currentPos }\n\n // Calculate delta in columns\n const deltaX = e.clientX - start.x\n const columnWidth = containerRect.width / gridColumns\n const columnDelta = Math.round(deltaX / columnWidth)\n\n if (constraints.lockHorizontal && (edge === 'left' || edge === 'right')) {\n // Horizontal resize is locked\n } else {\n switch (edge) {\n case 'right': {\n // Increase/decrease colSpan from the right\n const newColSpan = currentPos.colSpan + columnDelta\n newPosition.colSpan = Math.max(1, Math.min(gridColumns - currentPos.colStart + 1, newColSpan))\n break\n }\n case 'left': {\n // Increase/decrease from left (changes both colStart and colSpan)\n const newColStart = currentPos.colStart + columnDelta\n const newColSpan = currentPos.colSpan - columnDelta\n if (newColStart >= 1 && newColSpan >= 1) {\n newPosition.colStart = newColStart\n newPosition.colSpan = newColSpan\n }\n break\n }\n case 'top':\n case 'bottom': {\n // Row resizing - calculate based on Y movement\n if (!constraints.lockVertical) {\n const rowHeight = 100 // Approximate row height\n const deltaY = e.clientY - start.y\n const rowDelta = Math.round(deltaY / rowHeight)\n\n if (edge === 'bottom') {\n const currentRowSpan = currentPos.rowSpan || 1\n const newRowSpan = currentRowSpan + rowDelta\n newPosition.rowSpan = Math.max(1, newRowSpan)\n } else if (edge === 'top') {\n const currentRowStart = currentPos.rowStart || 1\n const currentRowSpan = currentPos.rowSpan || 1\n const newRowStart = currentRowStart + rowDelta\n const newRowSpan = currentRowSpan - rowDelta\n if (newRowStart >= 1 && newRowSpan >= 1) {\n newPosition.rowStart = newRowStart\n newPosition.rowSpan = newRowSpan\n }\n }\n }\n break\n }\n }\n }\n\n // Apply constraints\n newPosition = applyConstraints(newPosition, constraints, gridColumns)\n\n setPreviewPosition(newPosition)\n onResizePreview?.(newPosition)\n }\n\n /**\n * Handle pointer up to finish resize\n */\n const handlePointerUp = (_e: PointerEvent) => {\n if (!isResizing()) return\n\n const preview = previewPosition()\n if (preview) {\n onResize(preview)\n }\n\n // Cleanup\n setIsResizing(false)\n setResizeEdge(null)\n setPreviewPosition(null)\n setStartPosition(null)\n setStartPointer(null)\n\n // Remove listeners\n document.removeEventListener('pointermove', handlePointerMove)\n document.removeEventListener('pointerup', handlePointerUp)\n document.body.style.cursor = ''\n document.body.style.userSelect = ''\n }\n\n /**\n * Start resize operation\n */\n const handleResizeStart = (e: PointerEvent, edge: ResizeEdge) => {\n if (!enabled) return\n\n e.preventDefault()\n e.stopPropagation()\n\n setIsResizing(true)\n setResizeEdge(edge)\n setStartPosition(currentPosition())\n setStartPointer({ x: e.clientX, y: e.clientY })\n setPreviewPosition(currentPosition())\n\n // Set cursor\n const cursors: Record<ResizeEdge, string> = {\n left: 'ew-resize',\n right: 'ew-resize',\n top: 'ns-resize',\n bottom: 'ns-resize'\n }\n document.body.style.cursor = cursors[edge]\n document.body.style.userSelect = 'none'\n\n // Add document listeners\n document.addEventListener('pointermove', handlePointerMove)\n document.addEventListener('pointerup', handlePointerUp)\n }\n\n /**\n * Get resize handle props for an edge\n */\n const getResizeHandleProps = (edge: ResizeEdge): ResizeHandleProps => {\n const baseStyle: Record<string, string> = {\n position: 'absolute',\n zIndex: '10'\n }\n\n const edgeStyles: Record<ResizeEdge, Record<string, string>> = {\n left: {\n ...baseStyle,\n left: '-4px',\n top: '0',\n width: '8px',\n height: '100%',\n cursor: 'ew-resize'\n },\n right: {\n ...baseStyle,\n right: '-4px',\n top: '0',\n width: '8px',\n height: '100%',\n cursor: 'ew-resize'\n },\n top: {\n ...baseStyle,\n top: '-4px',\n left: '0',\n width: '100%',\n height: '8px',\n cursor: 'ns-resize'\n },\n bottom: {\n ...baseStyle,\n bottom: '-4px',\n left: '0',\n width: '100%',\n height: '8px',\n cursor: 'ns-resize'\n }\n }\n\n return {\n onPointerDown: (e) => handleResizeStart(e, edge),\n style: edgeStyles[edge],\n 'data-resize-edge': edge\n }\n }\n\n // Cleanup on unmount\n onCleanup(() => {\n document.removeEventListener('pointermove', handlePointerMove)\n document.removeEventListener('pointerup', handlePointerUp)\n document.body.style.cursor = ''\n document.body.style.userSelect = ''\n })\n\n return {\n isResizing,\n resizeEdge,\n previewPosition,\n handleResizeStart,\n getResizeHandleProps\n }\n}\n"],"names":["createSignal","isServer","onCleanup"],"mappings":"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"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useResize Hook
|
|
3
|
+
* Handles resizing of grid components by dragging edges
|
|
4
|
+
*
|
|
5
|
+
* Sprint Drag-Drop Feature
|
|
6
|
+
*/
|
|
7
|
+
import { Accessor } from 'solid-js';
|
|
8
|
+
import type { GridPosition, ResizeConstraints } from '../types';
|
|
9
|
+
/**
|
|
10
|
+
* Resize edge types
|
|
11
|
+
*/
|
|
12
|
+
export type ResizeEdge = 'left' | 'right' | 'top' | 'bottom';
|
|
13
|
+
/**
|
|
14
|
+
* Options for the useResize hook
|
|
15
|
+
*/
|
|
16
|
+
export interface UseResizeOptions {
|
|
17
|
+
/**
|
|
18
|
+
* Component ID being resized
|
|
19
|
+
*/
|
|
20
|
+
componentId: string;
|
|
21
|
+
/**
|
|
22
|
+
* Current grid position accessor
|
|
23
|
+
*/
|
|
24
|
+
currentPosition: Accessor<GridPosition>;
|
|
25
|
+
/**
|
|
26
|
+
* Callback when resize is complete
|
|
27
|
+
*/
|
|
28
|
+
onResize: (newPosition: GridPosition) => void;
|
|
29
|
+
/**
|
|
30
|
+
* Callback during resize (for preview)
|
|
31
|
+
*/
|
|
32
|
+
onResizePreview?: (previewPosition: GridPosition) => void;
|
|
33
|
+
/**
|
|
34
|
+
* Resize constraints
|
|
35
|
+
*/
|
|
36
|
+
constraints?: ResizeConstraints;
|
|
37
|
+
/**
|
|
38
|
+
* Grid container element for calculating column widths
|
|
39
|
+
*/
|
|
40
|
+
gridContainer?: Accessor<HTMLElement | null>;
|
|
41
|
+
/**
|
|
42
|
+
* Number of columns in the grid (default: 12)
|
|
43
|
+
*/
|
|
44
|
+
gridColumns?: number;
|
|
45
|
+
/**
|
|
46
|
+
* Whether resize is enabled
|
|
47
|
+
*/
|
|
48
|
+
enabled?: boolean;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Return type for the useResize hook
|
|
52
|
+
*/
|
|
53
|
+
export interface UseResizeReturn {
|
|
54
|
+
/**
|
|
55
|
+
* Whether a resize is in progress
|
|
56
|
+
*/
|
|
57
|
+
isResizing: Accessor<boolean>;
|
|
58
|
+
/**
|
|
59
|
+
* Current resize edge
|
|
60
|
+
*/
|
|
61
|
+
resizeEdge: Accessor<ResizeEdge | null>;
|
|
62
|
+
/**
|
|
63
|
+
* Preview position during resize
|
|
64
|
+
*/
|
|
65
|
+
previewPosition: Accessor<GridPosition | null>;
|
|
66
|
+
/**
|
|
67
|
+
* Start resize operation
|
|
68
|
+
*/
|
|
69
|
+
handleResizeStart: (e: PointerEvent, edge: ResizeEdge) => void;
|
|
70
|
+
/**
|
|
71
|
+
* Get resize handle props for an edge
|
|
72
|
+
*/
|
|
73
|
+
getResizeHandleProps: (edge: ResizeEdge) => ResizeHandleProps;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Props for resize handles
|
|
77
|
+
*/
|
|
78
|
+
export interface ResizeHandleProps {
|
|
79
|
+
onPointerDown: (e: PointerEvent) => void;
|
|
80
|
+
style: Record<string, string>;
|
|
81
|
+
'data-resize-edge': ResizeEdge;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Hook for handling resize of grid components
|
|
85
|
+
*/
|
|
86
|
+
export declare function useResize(options: UseResizeOptions): UseResizeReturn;
|
|
87
|
+
//# sourceMappingURL=useResize.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useResize.d.ts","sourceRoot":"","sources":["../../src/hooks/useResize.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAgB,QAAQ,EAAa,MAAM,UAAU,CAAA;AAE5D,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAA;AAE/D;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAA;AAE5D;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B;;OAEG;IACH,WAAW,EAAE,MAAM,CAAA;IAEnB;;OAEG;IACH,eAAe,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAA;IAEvC;;OAEG;IACH,QAAQ,EAAE,CAAC,WAAW,EAAE,YAAY,KAAK,IAAI,CAAA;IAE7C;;OAEG;IACH,eAAe,CAAC,EAAE,CAAC,eAAe,EAAE,YAAY,KAAK,IAAI,CAAA;IAEzD;;OAEG;IACH,WAAW,CAAC,EAAE,iBAAiB,CAAA;IAE/B;;OAEG;IACH,aAAa,CAAC,EAAE,QAAQ,CAAC,WAAW,GAAG,IAAI,CAAC,CAAA;IAE5C;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IAEpB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;OAEG;IACH,UAAU,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAA;IAE7B;;OAEG;IACH,UAAU,EAAE,QAAQ,CAAC,UAAU,GAAG,IAAI,CAAC,CAAA;IAEvC;;OAEG;IACH,eAAe,EAAE,QAAQ,CAAC,YAAY,GAAG,IAAI,CAAC,CAAA;IAE9C;;OAEG;IACH,iBAAiB,EAAE,CAAC,CAAC,EAAE,YAAY,EAAE,IAAI,EAAE,UAAU,KAAK,IAAI,CAAA;IAE9D;;OAEG;IACH,oBAAoB,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,iBAAiB,CAAA;CAC9D;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,aAAa,EAAE,CAAC,CAAC,EAAE,YAAY,KAAK,IAAI,CAAA;IACxC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7B,kBAAkB,EAAE,UAAU,CAAA;CAC/B;AAsCD;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,eAAe,CAwOpE"}
|