@seed-ship/mcp-ui-solid 2.0.0 → 2.1.0

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.
Files changed (140) hide show
  1. package/README.md +50 -1
  2. package/dist/components/AutocompleteDropdown.cjs +201 -0
  3. package/dist/components/AutocompleteDropdown.cjs.map +1 -0
  4. package/dist/components/AutocompleteDropdown.d.ts +71 -0
  5. package/dist/components/AutocompleteDropdown.d.ts.map +1 -0
  6. package/dist/components/AutocompleteDropdown.js +201 -0
  7. package/dist/components/AutocompleteDropdown.js.map +1 -0
  8. package/dist/components/AutocompleteFormField.cjs +289 -0
  9. package/dist/components/AutocompleteFormField.cjs.map +1 -0
  10. package/dist/components/AutocompleteFormField.d.ts +52 -0
  11. package/dist/components/AutocompleteFormField.d.ts.map +1 -0
  12. package/dist/components/AutocompleteFormField.js +289 -0
  13. package/dist/components/AutocompleteFormField.js.map +1 -0
  14. package/dist/components/DraggableGridItem.cjs +133 -0
  15. package/dist/components/DraggableGridItem.cjs.map +1 -0
  16. package/dist/components/DraggableGridItem.d.ts +95 -0
  17. package/dist/components/DraggableGridItem.d.ts.map +1 -0
  18. package/dist/components/DraggableGridItem.js +133 -0
  19. package/dist/components/DraggableGridItem.js.map +1 -0
  20. package/dist/components/EditableUIResourceRenderer.cjs +203 -0
  21. package/dist/components/EditableUIResourceRenderer.cjs.map +1 -0
  22. package/dist/components/EditableUIResourceRenderer.d.ts +43 -0
  23. package/dist/components/EditableUIResourceRenderer.d.ts.map +1 -0
  24. package/dist/components/EditableUIResourceRenderer.js +203 -0
  25. package/dist/components/EditableUIResourceRenderer.js.map +1 -0
  26. package/dist/components/GhostText.cjs +105 -0
  27. package/dist/components/GhostText.cjs.map +1 -0
  28. package/dist/components/GhostText.d.ts +113 -0
  29. package/dist/components/GhostText.d.ts.map +1 -0
  30. package/dist/components/GhostText.js +105 -0
  31. package/dist/components/GhostText.js.map +1 -0
  32. package/dist/components/ResizeHandle.cjs +173 -0
  33. package/dist/components/ResizeHandle.cjs.map +1 -0
  34. package/dist/components/ResizeHandle.d.ts +50 -0
  35. package/dist/components/ResizeHandle.d.ts.map +1 -0
  36. package/dist/components/ResizeHandle.js +173 -0
  37. package/dist/components/ResizeHandle.js.map +1 -0
  38. package/dist/context/AutocompleteContext.cjs +158 -0
  39. package/dist/context/AutocompleteContext.cjs.map +1 -0
  40. package/dist/context/AutocompleteContext.d.ts +77 -0
  41. package/dist/context/AutocompleteContext.d.ts.map +1 -0
  42. package/dist/context/AutocompleteContext.js +158 -0
  43. package/dist/context/AutocompleteContext.js.map +1 -0
  44. package/dist/hooks/index.d.ts +6 -0
  45. package/dist/hooks/index.d.ts.map +1 -1
  46. package/dist/hooks/useAutocomplete.cjs +234 -0
  47. package/dist/hooks/useAutocomplete.cjs.map +1 -0
  48. package/dist/hooks/useAutocomplete.d.ts +119 -0
  49. package/dist/hooks/useAutocomplete.d.ts.map +1 -0
  50. package/dist/hooks/useAutocomplete.js +234 -0
  51. package/dist/hooks/useAutocomplete.js.map +1 -0
  52. package/dist/hooks/useDragDrop.cjs +170 -0
  53. package/dist/hooks/useDragDrop.cjs.map +1 -0
  54. package/dist/hooks/useDragDrop.d.ts +100 -0
  55. package/dist/hooks/useDragDrop.d.ts.map +1 -0
  56. package/dist/hooks/useDragDrop.js +170 -0
  57. package/dist/hooks/useDragDrop.js.map +1 -0
  58. package/dist/hooks/useResize.cjs +209 -0
  59. package/dist/hooks/useResize.cjs.map +1 -0
  60. package/dist/hooks/useResize.d.ts +87 -0
  61. package/dist/hooks/useResize.d.ts.map +1 -0
  62. package/dist/hooks/useResize.js +209 -0
  63. package/dist/hooks/useResize.js.map +1 -0
  64. package/dist/hooks.cjs +6 -0
  65. package/dist/hooks.cjs.map +1 -1
  66. package/dist/hooks.d.cts +6 -0
  67. package/dist/hooks.d.ts +6 -0
  68. package/dist/hooks.js +6 -0
  69. package/dist/hooks.js.map +1 -1
  70. package/dist/index.cjs +29 -0
  71. package/dist/index.cjs.map +1 -1
  72. package/dist/index.d.cts +18 -3
  73. package/dist/index.d.ts +18 -3
  74. package/dist/index.d.ts.map +1 -1
  75. package/dist/index.js +29 -0
  76. package/dist/index.js.map +1 -1
  77. package/dist/plugins/duckdb.cjs +192 -0
  78. package/dist/plugins/duckdb.cjs.map +1 -0
  79. package/dist/plugins/duckdb.d.ts +20 -0
  80. package/dist/plugins/duckdb.d.ts.map +1 -0
  81. package/dist/plugins/duckdb.js +170 -0
  82. package/dist/plugins/duckdb.js.map +1 -0
  83. package/dist/plugins/groq.cjs +97 -0
  84. package/dist/plugins/groq.cjs.map +1 -0
  85. package/dist/plugins/groq.d.ts +13 -0
  86. package/dist/plugins/groq.d.ts.map +1 -0
  87. package/dist/plugins/groq.js +97 -0
  88. package/dist/plugins/groq.js.map +1 -0
  89. package/dist/plugins/index.d.ts +10 -0
  90. package/dist/plugins/index.d.ts.map +1 -0
  91. package/dist/plugins/rest.cjs +92 -0
  92. package/dist/plugins/rest.cjs.map +1 -0
  93. package/dist/plugins/rest.d.ts +13 -0
  94. package/dist/plugins/rest.d.ts.map +1 -0
  95. package/dist/plugins/rest.js +92 -0
  96. package/dist/plugins/rest.js.map +1 -0
  97. package/dist/plugins/supabase.cjs +79 -0
  98. package/dist/plugins/supabase.cjs.map +1 -0
  99. package/dist/plugins/supabase.d.ts +13 -0
  100. package/dist/plugins/supabase.d.ts.map +1 -0
  101. package/dist/plugins/supabase.js +79 -0
  102. package/dist/plugins/supabase.js.map +1 -0
  103. package/dist/services/validation.cjs +40 -1
  104. package/dist/services/validation.cjs.map +1 -1
  105. package/dist/services/validation.d.ts.map +1 -1
  106. package/dist/services/validation.js +40 -1
  107. package/dist/services/validation.js.map +1 -1
  108. package/dist/types/index.d.ts +430 -0
  109. package/dist/types/index.d.ts.map +1 -1
  110. package/dist/types.d.cts +430 -0
  111. package/dist/types.d.ts +430 -0
  112. package/package.json +16 -1
  113. package/src/components/AutocompleteDropdown.tsx +329 -0
  114. package/src/components/AutocompleteFormField.tsx +288 -0
  115. package/src/components/DraggableGridItem.tsx +274 -0
  116. package/src/components/EditableUIResourceRenderer.tsx +273 -0
  117. package/src/components/GhostText.tsx +262 -0
  118. package/src/components/ResizeHandle.tsx +262 -0
  119. package/src/context/AutocompleteContext.tsx +317 -0
  120. package/src/hooks/index.ts +23 -0
  121. package/src/hooks/useAutocomplete.test.ts +334 -0
  122. package/src/hooks/useAutocomplete.ts +466 -0
  123. package/src/hooks/useDragDrop.test.ts +355 -0
  124. package/src/hooks/useDragDrop.ts +379 -0
  125. package/src/hooks/useResize.test.ts +313 -0
  126. package/src/hooks/useResize.ts +372 -0
  127. package/src/index.ts +71 -0
  128. package/src/plugins/duckdb.ts +269 -0
  129. package/src/plugins/groq.ts +137 -0
  130. package/src/plugins/index.ts +14 -0
  131. package/src/plugins/rest.ts +147 -0
  132. package/src/plugins/supabase.ts +120 -0
  133. package/src/services/validation.ts +46 -0
  134. package/src/styles/autocomplete.css +356 -0
  135. package/src/styles/drag-drop.css +297 -0
  136. package/src/styles/index.css +7 -0
  137. package/src/types/index.ts +529 -0
  138. package/src/vite-env.d.ts +18 -0
  139. package/tsconfig.tsbuildinfo +1 -1
  140. package/vite.config.ts +2 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAutocomplete.js","sources":["../../src/hooks/useAutocomplete.ts"],"sourcesContent":["/**\n * useAutocomplete Hook\n * Provides autocomplete functionality for form fields\n *\n * Sprint Autocomplete Feature\n */\n\nimport {\n createSignal,\n createEffect,\n on,\n Accessor,\n onCleanup,\n batch,\n createMemo\n} from 'solid-js'\nimport { isServer } from 'solid-js/web'\nimport { useAutocompleteContextSafe } from '../context/AutocompleteContext'\nimport type {\n AutocompleteOption,\n AutocompleteContext,\n FieldAutocompleteConfig\n} from '../types'\n\n/**\n * Options for the useAutocomplete hook\n */\nexport interface UseAutocompleteOptions {\n /**\n * Current input value accessor\n */\n inputValue: Accessor<string>\n\n /**\n * Plugin ID to use (overrides default)\n */\n pluginId?: string\n\n /**\n * Field configuration\n */\n fieldConfig?: FieldAutocompleteConfig\n\n /**\n * Context data for suggestions\n */\n context?: Accessor<AutocompleteContext>\n\n /**\n * Whether autocomplete is enabled\n */\n enabled?: boolean\n\n /**\n * Callback when input value should change (for accepting suggestions)\n */\n onInputChange?: (value: string) => void\n\n /**\n * Minimum characters before triggering\n */\n minChars?: number\n\n /**\n * Debounce delay in ms\n */\n debounceMs?: number\n}\n\n/**\n * Return type for the useAutocomplete hook\n */\nexport interface UseAutocompleteReturn {\n /**\n * Current completion text (for ghost text, LLM mode)\n */\n completion: Accessor<string | null>\n\n /**\n * Ghost text to show (remaining text after input)\n */\n ghostText: Accessor<string>\n\n /**\n * Accept the current completion\n */\n acceptCompletion: () => void\n\n /**\n * Current options (for dropdown, data mode)\n */\n options: Accessor<AutocompleteOption[]>\n\n /**\n * Currently selected option index\n */\n selectedIndex: Accessor<number>\n\n /**\n * Select an option by index\n */\n selectOption: (option: AutocompleteOption) => void\n\n /**\n * Navigate to next option\n */\n nextOption: () => void\n\n /**\n * Navigate to previous option\n */\n prevOption: () => void\n\n /**\n * Select current highlighted option\n */\n selectCurrentOption: () => void\n\n /**\n * Whether suggestions are loading\n */\n isLoading: Accessor<boolean>\n\n /**\n * Error message if any\n */\n error: Accessor<string | null>\n\n /**\n * Dismiss suggestions\n */\n dismiss: () => void\n\n /**\n * Whether suggestions are visible\n */\n isOpen: Accessor<boolean>\n\n /**\n * Result type ('completion' or 'options')\n */\n resultType: Accessor<'completion' | 'options' | null>\n\n /**\n * Open/show suggestions\n */\n open: () => void\n\n /**\n * Handle keyboard events\n */\n handleKeyDown: (e: KeyboardEvent) => boolean\n}\n\n/**\n * Debounce helper\n */\nfunction debounce<T extends (...args: any[]) => any>(\n fn: T,\n delay: number\n): { call: (...args: Parameters<T>) => void; cancel: () => void } {\n let timeoutId: ReturnType<typeof setTimeout> | null = null\n\n return {\n call: (...args: Parameters<T>) => {\n if (timeoutId) clearTimeout(timeoutId)\n timeoutId = setTimeout(() => {\n fn(...args)\n timeoutId = null\n }, delay)\n },\n cancel: () => {\n if (timeoutId) {\n clearTimeout(timeoutId)\n timeoutId = null\n }\n }\n }\n}\n\n/**\n * Hook for autocomplete functionality\n */\nexport function useAutocomplete(options: UseAutocompleteOptions): UseAutocompleteReturn {\n const {\n inputValue,\n pluginId,\n fieldConfig,\n context,\n enabled = true,\n onInputChange,\n minChars: minCharsOption,\n debounceMs: debounceOption\n } = options\n\n // Get context (may be undefined if no provider)\n const autocompleteCtx = useAutocompleteContextSafe()\n\n // State\n const [completion, setCompletion] = createSignal<string | null>(null)\n const [options_, setOptions] = createSignal<AutocompleteOption[]>([])\n const [selectedIndex, setSelectedIndex] = createSignal(-1)\n const [isLoading, setIsLoading] = createSignal(false)\n const [error, setError] = createSignal<string | null>(null)\n const [isOpen, setIsOpen] = createSignal(false)\n const [resultType, setResultType] = createSignal<'completion' | 'options' | null>(null)\n\n // Config with defaults from context/options\n const config = createMemo(() => ({\n minChars: minCharsOption ?? fieldConfig?.minChars ?? autocompleteCtx?.config.minChars ?? 1,\n debounceMs: debounceOption ?? fieldConfig?.debounceMs ?? autocompleteCtx?.config.debounceMs ?? 150\n }))\n\n // Ghost text (portion after current input)\n const ghostText = createMemo(() => {\n const comp = completion()\n const input = inputValue()\n\n if (!comp || !input) return ''\n\n // If completion starts with input, show the remaining part\n if (comp.toLowerCase().startsWith(input.toLowerCase())) {\n return comp.slice(input.length)\n }\n\n return ''\n })\n\n // Fetch suggestions\n const fetchSuggestions = async (input: string) => {\n if (!autocompleteCtx) {\n return\n }\n\n if (input.length < config().minChars) {\n batch(() => {\n setCompletion(null)\n setOptions([])\n setIsOpen(false)\n setResultType(null)\n })\n return\n }\n\n setIsLoading(true)\n setError(null)\n\n try {\n const targetPluginId = pluginId ?? fieldConfig?.plugin\n const contextData = context?.()\n\n const result = await autocompleteCtx.getSuggestions(\n input,\n targetPluginId,\n contextData\n )\n\n batch(() => {\n setResultType(result.type)\n\n if (result.type === 'completion') {\n setCompletion(result.completion || null)\n setOptions([])\n setIsOpen(!!result.completion)\n } else {\n setCompletion(null)\n setOptions(result.options || [])\n setSelectedIndex(-1)\n setIsOpen((result.options?.length || 0) > 0)\n }\n\n setIsLoading(false)\n })\n } catch (e) {\n batch(() => {\n setError(e instanceof Error ? e.message : 'Unknown error')\n setIsLoading(false)\n setIsOpen(false)\n })\n }\n }\n\n // Debounced fetch\n const debouncedFetch = debounce(fetchSuggestions, config().debounceMs)\n\n // Watch input value changes\n createEffect(\n on(inputValue, (value) => {\n if (!enabled || !autocompleteCtx || isServer) {\n return\n }\n\n debouncedFetch.call(value)\n })\n )\n\n // Cleanup\n onCleanup(() => {\n debouncedFetch.cancel()\n })\n\n /**\n * Accept the current completion\n */\n const acceptCompletion = () => {\n const comp = completion()\n if (comp && onInputChange) {\n onInputChange(comp)\n batch(() => {\n setCompletion(null)\n setIsOpen(false)\n })\n }\n }\n\n /**\n * Select an option\n */\n const selectOption = (option: AutocompleteOption) => {\n if (onInputChange) {\n onInputChange(option.value)\n }\n batch(() => {\n setOptions([])\n setSelectedIndex(-1)\n setIsOpen(false)\n })\n }\n\n /**\n * Navigate to next option\n */\n const nextOption = () => {\n const opts = options_()\n if (opts.length === 0) return\n\n setSelectedIndex((prev) => {\n const next = prev + 1\n return next >= opts.length ? 0 : next\n })\n }\n\n /**\n * Navigate to previous option\n */\n const prevOption = () => {\n const opts = options_()\n if (opts.length === 0) return\n\n setSelectedIndex((prev) => {\n const next = prev - 1\n return next < 0 ? opts.length - 1 : next\n })\n }\n\n /**\n * Select current highlighted option\n */\n const selectCurrentOption = () => {\n const idx = selectedIndex()\n const opts = options_()\n if (idx >= 0 && idx < opts.length) {\n selectOption(opts[idx])\n }\n }\n\n /**\n * Dismiss suggestions\n */\n const dismiss = () => {\n debouncedFetch.cancel()\n batch(() => {\n setCompletion(null)\n setOptions([])\n setSelectedIndex(-1)\n setIsOpen(false)\n setError(null)\n })\n }\n\n /**\n * Open suggestions\n */\n const open = () => {\n const input = inputValue()\n if (input.length >= config().minChars) {\n fetchSuggestions(input)\n }\n }\n\n /**\n * Handle keyboard events\n * Returns true if the event was handled\n */\n const handleKeyDown = (e: KeyboardEvent): boolean => {\n if (!isOpen()) return false\n\n const type = resultType()\n\n // Tab to accept completion\n if (e.key === 'Tab' && type === 'completion' && ghostText()) {\n e.preventDefault()\n acceptCompletion()\n return true\n }\n\n // Arrow keys for dropdown navigation\n if (type === 'options') {\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault()\n nextOption()\n return true\n\n case 'ArrowUp':\n e.preventDefault()\n prevOption()\n return true\n\n case 'Enter':\n if (selectedIndex() >= 0) {\n e.preventDefault()\n selectCurrentOption()\n return true\n }\n break\n\n case 'Tab':\n if (selectedIndex() >= 0) {\n e.preventDefault()\n selectCurrentOption()\n return true\n }\n break\n }\n }\n\n // Escape to dismiss\n if (e.key === 'Escape') {\n e.preventDefault()\n dismiss()\n return true\n }\n\n return false\n }\n\n return {\n completion,\n ghostText,\n acceptCompletion,\n options: options_,\n selectedIndex,\n selectOption,\n nextOption,\n prevOption,\n selectCurrentOption,\n isLoading,\n error,\n dismiss,\n isOpen,\n resultType,\n open,\n handleKeyDown\n }\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,170 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const solidJs = require("solid-js");
4
+ function getDropPosition(e, targetElement) {
5
+ const rect = targetElement.getBoundingClientRect();
6
+ const midY = rect.top + rect.height / 2;
7
+ return e.clientY < midY ? "before" : "after";
8
+ }
9
+ function reorderComponents(components, sourceId, targetId, position) {
10
+ const sourceIndex = components.findIndex((c) => c.id === sourceId);
11
+ const targetIndex = components.findIndex((c) => c.id === targetId);
12
+ if (sourceIndex === -1 || targetIndex === -1 || sourceIndex === targetIndex) {
13
+ return components;
14
+ }
15
+ const result = [...components];
16
+ const [sourceComponent] = result.splice(sourceIndex, 1);
17
+ let newTargetIndex = result.findIndex((c) => c.id === targetId);
18
+ if (position === "after") {
19
+ newTargetIndex += 1;
20
+ }
21
+ result.splice(newTargetIndex, 0, sourceComponent);
22
+ return recalculatePositions(result);
23
+ }
24
+ function recalculatePositions(components) {
25
+ let currentRow = 1;
26
+ const rowComponents = /* @__PURE__ */ new Map();
27
+ components.forEach((c, index) => {
28
+ const row = c.position.rowStart || index + 1;
29
+ if (!rowComponents.has(row)) {
30
+ rowComponents.set(row, []);
31
+ }
32
+ rowComponents.get(row).push(c);
33
+ });
34
+ const result = [];
35
+ const sortedRows = Array.from(rowComponents.keys()).sort((a, b) => a - b);
36
+ sortedRows.forEach((row) => {
37
+ const rowComps = rowComponents.get(row);
38
+ rowComps.forEach((c) => {
39
+ result.push({
40
+ ...c,
41
+ position: {
42
+ ...c.position,
43
+ rowStart: currentRow
44
+ }
45
+ });
46
+ });
47
+ currentRow += Math.max(...rowComps.map((c) => c.position.rowSpan || 1));
48
+ });
49
+ return result;
50
+ }
51
+ function useDragDrop(options) {
52
+ const {
53
+ components,
54
+ onReorder,
55
+ enabled = true
56
+ } = options;
57
+ const [draggedId, setDraggedId] = solidJs.createSignal(null);
58
+ const [dropTargetId, setDropTargetId] = solidJs.createSignal(null);
59
+ const [dropPosition, setDropPosition] = solidJs.createSignal("after");
60
+ const isDragging = () => draggedId() !== null;
61
+ let dragCounter = 0;
62
+ const handleDragStart = (e, componentId) => {
63
+ if (!enabled) {
64
+ e.preventDefault();
65
+ return;
66
+ }
67
+ const target = e.currentTarget;
68
+ e.dataTransfer.effectAllowed = "move";
69
+ e.dataTransfer.setData("text/plain", componentId);
70
+ if (target) {
71
+ const rect = target.getBoundingClientRect();
72
+ e.dataTransfer.setDragImage(target, rect.width / 2, 20);
73
+ }
74
+ requestAnimationFrame(() => {
75
+ setDraggedId(componentId);
76
+ });
77
+ };
78
+ const handleDragOver = (e, componentId) => {
79
+ if (!enabled || !draggedId() || draggedId() === componentId) {
80
+ return;
81
+ }
82
+ e.preventDefault();
83
+ e.dataTransfer.dropEffect = "move";
84
+ const target = e.currentTarget;
85
+ const position = getDropPosition(e, target);
86
+ setDropPosition(position);
87
+ };
88
+ const handleDragEnter = (e, componentId) => {
89
+ if (!enabled || !draggedId() || draggedId() === componentId) {
90
+ return;
91
+ }
92
+ e.preventDefault();
93
+ dragCounter++;
94
+ setDropTargetId(componentId);
95
+ };
96
+ const handleDragLeave = (_e) => {
97
+ if (!enabled) return;
98
+ dragCounter--;
99
+ if (dragCounter === 0) {
100
+ setDropTargetId(null);
101
+ }
102
+ };
103
+ const handleDrop = (e, targetId) => {
104
+ if (!enabled) return;
105
+ e.preventDefault();
106
+ dragCounter = 0;
107
+ const sourceId = e.dataTransfer.getData("text/plain");
108
+ if (!sourceId || sourceId === targetId) {
109
+ solidJs.batch(() => {
110
+ setDraggedId(null);
111
+ setDropTargetId(null);
112
+ });
113
+ return;
114
+ }
115
+ const currentComponents = components();
116
+ const reordered = reorderComponents(
117
+ currentComponents,
118
+ sourceId,
119
+ targetId,
120
+ dropPosition()
121
+ );
122
+ solidJs.batch(() => {
123
+ setDraggedId(null);
124
+ setDropTargetId(null);
125
+ });
126
+ onReorder(reordered);
127
+ };
128
+ const handleDragEnd = (_e) => {
129
+ dragCounter = 0;
130
+ solidJs.batch(() => {
131
+ setDraggedId(null);
132
+ setDropTargetId(null);
133
+ });
134
+ };
135
+ const getDragProps = (componentId) => ({
136
+ draggable: enabled,
137
+ onDragStart: (e) => handleDragStart(e, componentId),
138
+ onDragOver: (e) => handleDragOver(e, componentId),
139
+ onDragEnter: (e) => handleDragEnter(e, componentId),
140
+ onDragLeave: handleDragLeave,
141
+ onDrop: (e) => handleDrop(e, componentId),
142
+ onDragEnd: handleDragEnd,
143
+ "data-component-id": componentId
144
+ });
145
+ const isComponentDragging = (componentId) => {
146
+ return draggedId() === componentId;
147
+ };
148
+ const isDropTarget = (componentId) => {
149
+ return dropTargetId() === componentId;
150
+ };
151
+ solidJs.onCleanup(() => {
152
+ dragCounter = 0;
153
+ });
154
+ return {
155
+ draggedId,
156
+ dropTargetId,
157
+ isDragging,
158
+ handleDragStart,
159
+ handleDragOver,
160
+ handleDragEnter,
161
+ handleDragLeave,
162
+ handleDrop,
163
+ handleDragEnd,
164
+ getDragProps,
165
+ isComponentDragging,
166
+ isDropTarget
167
+ };
168
+ }
169
+ exports.useDragDrop = useDragDrop;
170
+ //# sourceMappingURL=useDragDrop.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDragDrop.cjs","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":["createSignal","batch","onCleanup"],"mappings":"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"}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * useDragDrop Hook
3
+ * Handles drag-and-drop reordering of grid components using HTML5 Drag-Drop API
4
+ *
5
+ * Sprint Drag-Drop Feature
6
+ */
7
+ import { Accessor } from 'solid-js';
8
+ import type { UIComponent } from '../types';
9
+ /**
10
+ * Options for the useDragDrop hook
11
+ */
12
+ export interface UseDragDropOptions {
13
+ /**
14
+ * Accessor for current components
15
+ */
16
+ components: Accessor<UIComponent[]>;
17
+ /**
18
+ * Callback when components are reordered
19
+ */
20
+ onReorder: (newComponents: UIComponent[]) => void;
21
+ /**
22
+ * Whether drag-drop is enabled
23
+ */
24
+ enabled?: boolean;
25
+ /**
26
+ * Animation duration in ms
27
+ */
28
+ animationDuration?: number;
29
+ }
30
+ /**
31
+ * Props to apply to a draggable element
32
+ */
33
+ export interface DragProps {
34
+ draggable: boolean;
35
+ onDragStart: (e: DragEvent) => void;
36
+ onDragOver: (e: DragEvent) => void;
37
+ onDragEnter: (e: DragEvent) => void;
38
+ onDragLeave: (e: DragEvent) => void;
39
+ onDrop: (e: DragEvent) => void;
40
+ onDragEnd: (e: DragEvent) => void;
41
+ 'data-component-id': string;
42
+ }
43
+ /**
44
+ * Return type for the useDragDrop hook
45
+ */
46
+ export interface UseDragDropReturn {
47
+ /**
48
+ * ID of the component currently being dragged
49
+ */
50
+ draggedId: Accessor<string | null>;
51
+ /**
52
+ * ID of the current drop target
53
+ */
54
+ dropTargetId: Accessor<string | null>;
55
+ /**
56
+ * Whether a drag operation is in progress
57
+ */
58
+ isDragging: Accessor<boolean>;
59
+ /**
60
+ * Handle drag start event
61
+ */
62
+ handleDragStart: (e: DragEvent, componentId: string) => void;
63
+ /**
64
+ * Handle drag over event
65
+ */
66
+ handleDragOver: (e: DragEvent, componentId: string) => void;
67
+ /**
68
+ * Handle drag enter event
69
+ */
70
+ handleDragEnter: (e: DragEvent, componentId: string) => void;
71
+ /**
72
+ * Handle drag leave event
73
+ */
74
+ handleDragLeave: (e: DragEvent) => void;
75
+ /**
76
+ * Handle drop event
77
+ */
78
+ handleDrop: (e: DragEvent, targetId: string) => void;
79
+ /**
80
+ * Handle drag end event
81
+ */
82
+ handleDragEnd: (e: DragEvent) => void;
83
+ /**
84
+ * Get drag props for a component
85
+ */
86
+ getDragProps: (componentId: string) => DragProps;
87
+ /**
88
+ * Check if a component is being dragged
89
+ */
90
+ isComponentDragging: (componentId: string) => boolean;
91
+ /**
92
+ * Check if a component is a drop target
93
+ */
94
+ isDropTarget: (componentId: string) => boolean;
95
+ }
96
+ /**
97
+ * Hook for handling drag-and-drop reordering of grid components
98
+ */
99
+ export declare function useDragDrop(options: UseDragDropOptions): UseDragDropReturn;
100
+ //# sourceMappingURL=useDragDrop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDragDrop.d.ts","sourceRoot":"","sources":["../../src/hooks/useDragDrop.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAgB,QAAQ,EAAoB,MAAM,UAAU,CAAA;AACnE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AAE3C;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,UAAU,EAAE,QAAQ,CAAC,WAAW,EAAE,CAAC,CAAA;IAEnC;;OAEG;IACH,SAAS,EAAE,CAAC,aAAa,EAAE,WAAW,EAAE,KAAK,IAAI,CAAA;IAEjD;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IAEjB;;OAEG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,SAAS,EAAE,OAAO,CAAA;IAClB,WAAW,EAAE,CAAC,CAAC,EAAE,SAAS,KAAK,IAAI,CAAA;IACnC,UAAU,EAAE,CAAC,CAAC,EAAE,SAAS,KAAK,IAAI,CAAA;IAClC,WAAW,EAAE,CAAC,CAAC,EAAE,SAAS,KAAK,IAAI,CAAA;IACnC,WAAW,EAAE,CAAC,CAAC,EAAE,SAAS,KAAK,IAAI,CAAA;IACnC,MAAM,EAAE,CAAC,CAAC,EAAE,SAAS,KAAK,IAAI,CAAA;IAC9B,SAAS,EAAE,CAAC,CAAC,EAAE,SAAS,KAAK,IAAI,CAAA;IACjC,mBAAmB,EAAE,MAAM,CAAA;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,SAAS,EAAE,QAAQ,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IAElC;;OAEG;IACH,YAAY,EAAE,QAAQ,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IAErC;;OAEG;IACH,UAAU,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAA;IAE7B;;OAEG;IACH,eAAe,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAA;IAE5D;;OAEG;IACH,cAAc,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAA;IAE3D;;OAEG;IACH,eAAe,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,KAAK,IAAI,CAAA;IAE5D;;OAEG;IACH,eAAe,EAAE,CAAC,CAAC,EAAE,SAAS,KAAK,IAAI,CAAA;IAEvC;;OAEG;IACH,UAAU,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAA;IAEpD;;OAEG;IACH,aAAa,EAAE,CAAC,CAAC,EAAE,SAAS,KAAK,IAAI,CAAA;IAErC;;OAEG;IACH,YAAY,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,SAAS,CAAA;IAEhD;;OAEG;IACH,mBAAmB,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAA;IAErD;;OAEG;IACH,YAAY,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,OAAO,CAAA;CAC/C;AAqFD;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,kBAAkB,GAAG,iBAAiB,CAkL1E"}
@@ -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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"}