@proyecto-viviana/solidaria 0.2.4 → 0.2.8

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 (219) hide show
  1. package/LICENSE +21 -0
  2. package/dist/actiongroup/createActionGroup.d.ts +29 -0
  3. package/dist/actiongroup/createActionGroup.d.ts.map +1 -0
  4. package/dist/actiongroup/index.d.ts +2 -0
  5. package/dist/actiongroup/index.d.ts.map +1 -0
  6. package/dist/autocomplete/createAutocomplete.d.ts +6 -2
  7. package/dist/autocomplete/createAutocomplete.d.ts.map +1 -1
  8. package/dist/breadcrumbs/createBreadcrumbs.d.ts +2 -0
  9. package/dist/breadcrumbs/createBreadcrumbs.d.ts.map +1 -1
  10. package/dist/button/createToggleButtonGroup.d.ts +32 -0
  11. package/dist/button/createToggleButtonGroup.d.ts.map +1 -0
  12. package/dist/button/index.d.ts +2 -0
  13. package/dist/button/index.d.ts.map +1 -1
  14. package/dist/calendar/createCalendarCell.d.ts +2 -0
  15. package/dist/calendar/createCalendarCell.d.ts.map +1 -1
  16. package/dist/calendar/createCalendarGrid.d.ts.map +1 -1
  17. package/dist/calendar/createRangeCalendarCell.d.ts +3 -1
  18. package/dist/calendar/createRangeCalendarCell.d.ts.map +1 -1
  19. package/dist/checkbox/createCheckboxGroup.d.ts +5 -1
  20. package/dist/checkbox/createCheckboxGroup.d.ts.map +1 -1
  21. package/dist/collections/index.d.ts +56 -0
  22. package/dist/collections/index.d.ts.map +1 -0
  23. package/dist/color/createColorArea.d.ts.map +1 -1
  24. package/dist/color/createColorSlider.d.ts.map +1 -1
  25. package/dist/color/createColorWheel.d.ts.map +1 -1
  26. package/dist/combobox/createComboBox.d.ts +6 -0
  27. package/dist/combobox/createComboBox.d.ts.map +1 -1
  28. package/dist/datepicker/createDatePicker.d.ts +6 -0
  29. package/dist/datepicker/createDatePicker.d.ts.map +1 -1
  30. package/dist/datepicker/createDateRangePicker.d.ts +40 -0
  31. package/dist/datepicker/createDateRangePicker.d.ts.map +1 -0
  32. package/dist/datepicker/createDateSegment.d.ts +1 -1
  33. package/dist/datepicker/createDateSegment.d.ts.map +1 -1
  34. package/dist/datepicker/createTimeSegment.d.ts +29 -0
  35. package/dist/datepicker/createTimeSegment.d.ts.map +1 -0
  36. package/dist/datepicker/index.d.ts +2 -0
  37. package/dist/datepicker/index.d.ts.map +1 -1
  38. package/dist/disclosure/createDisclosureGroup.d.ts +2 -1
  39. package/dist/disclosure/createDisclosureGroup.d.ts.map +1 -1
  40. package/dist/dnd/createDrag.d.ts.map +1 -1
  41. package/dist/dnd/createDraggableCollection.d.ts +4 -0
  42. package/dist/dnd/createDraggableCollection.d.ts.map +1 -1
  43. package/dist/dnd/createDraggableItem.d.ts.map +1 -1
  44. package/dist/dnd/createDrop.d.ts.map +1 -1
  45. package/dist/dnd/createDroppableCollection.d.ts +32 -1
  46. package/dist/dnd/createDroppableCollection.d.ts.map +1 -1
  47. package/dist/dnd/createDroppableItem.d.ts.map +1 -1
  48. package/dist/dnd/index.d.ts +1 -1
  49. package/dist/dnd/index.d.ts.map +1 -1
  50. package/dist/grid/createGrid.d.ts.map +1 -1
  51. package/dist/gridlist/createGridList.d.ts.map +1 -1
  52. package/dist/index.d.ts +6 -4
  53. package/dist/index.d.ts.map +1 -1
  54. package/dist/index.js +4659 -3452
  55. package/dist/index.js.map +1 -7
  56. package/dist/index.ssr.js +4659 -3452
  57. package/dist/index.ssr.js.map +1 -7
  58. package/dist/interactions/createFocus.d.ts.map +1 -1
  59. package/dist/interactions/createFocusWithin.d.ts.map +1 -1
  60. package/dist/link/createLink.d.ts +10 -0
  61. package/dist/link/createLink.d.ts.map +1 -1
  62. package/dist/listbox/createListBox.d.ts +1 -0
  63. package/dist/listbox/createListBox.d.ts.map +1 -1
  64. package/dist/listbox/createOption.d.ts.map +1 -1
  65. package/dist/menu/createMenu.d.ts +1 -0
  66. package/dist/menu/createMenu.d.ts.map +1 -1
  67. package/dist/meter/createMeter.d.ts.map +1 -1
  68. package/dist/numberfield/createNumberField.d.ts +18 -0
  69. package/dist/numberfield/createNumberField.d.ts.map +1 -1
  70. package/dist/overlays/createModal.d.ts +16 -0
  71. package/dist/overlays/createModal.d.ts.map +1 -1
  72. package/dist/overlays/createOverlay.d.ts.map +1 -1
  73. package/dist/overlays/index.d.ts +1 -1
  74. package/dist/overlays/index.d.ts.map +1 -1
  75. package/dist/popover/createOverlayPosition.d.ts.map +1 -1
  76. package/dist/popover/createPopover.d.ts.map +1 -1
  77. package/dist/progress/createProgressBar.d.ts.map +1 -1
  78. package/dist/radio/createRadioGroup.d.ts +2 -2
  79. package/dist/radio/createRadioGroup.d.ts.map +1 -1
  80. package/dist/searchfield/createSearchField.d.ts.map +1 -1
  81. package/dist/select/createHiddenSelect.d.ts.map +1 -1
  82. package/dist/select/createSelect.d.ts.map +1 -1
  83. package/dist/slider/createSlider.d.ts.map +1 -1
  84. package/dist/table/createTable.d.ts.map +1 -1
  85. package/dist/tabs/createTabs.d.ts +1 -1
  86. package/dist/tabs/createTabs.d.ts.map +1 -1
  87. package/dist/tag/createTag.d.ts.map +1 -1
  88. package/dist/tag/createTagGroup.d.ts.map +1 -1
  89. package/dist/toast/createToast.d.ts +4 -0
  90. package/dist/toast/createToast.d.ts.map +1 -1
  91. package/dist/toast/createToastRegion.d.ts.map +1 -1
  92. package/dist/toolbar/createToolbar.d.ts.map +1 -1
  93. package/dist/tooltip/createTooltipTrigger.d.ts.map +1 -1
  94. package/dist/tree/createTree.d.ts.map +1 -1
  95. package/dist/tree/createTreeItem.d.ts.map +1 -1
  96. package/dist/tree/types.d.ts +4 -0
  97. package/dist/tree/types.d.ts.map +1 -1
  98. package/dist/utils/env.d.ts +1 -1
  99. package/dist/utils/env.d.ts.map +1 -1
  100. package/dist/utils/platform.d.ts.map +1 -1
  101. package/dist/visually-hidden/createVisuallyHidden.d.ts.map +1 -1
  102. package/package.json +8 -6
  103. package/src/actiongroup/createActionGroup.ts +324 -0
  104. package/src/actiongroup/index.ts +8 -0
  105. package/src/autocomplete/createAutocomplete.ts +32 -9
  106. package/src/breadcrumbs/createBreadcrumbs.ts +10 -15
  107. package/src/button/createButton.ts +1 -1
  108. package/src/button/createToggleButtonGroup.ts +128 -0
  109. package/src/button/index.ts +9 -0
  110. package/src/calendar/createCalendarCell.ts +6 -4
  111. package/src/calendar/createCalendarGrid.ts +27 -18
  112. package/src/calendar/createRangeCalendarCell.ts +26 -9
  113. package/src/checkbox/createCheckboxGroup.ts +21 -4
  114. package/src/collections/index.ts +242 -0
  115. package/src/color/createColorArea.ts +380 -314
  116. package/src/color/createColorField.ts +137 -137
  117. package/src/color/createColorSlider.ts +286 -197
  118. package/src/color/createColorSwatch.ts +40 -40
  119. package/src/color/createColorWheel.ts +218 -208
  120. package/src/color/index.ts +24 -24
  121. package/src/color/types.ts +116 -116
  122. package/src/combobox/createComboBox.ts +670 -647
  123. package/src/combobox/index.ts +6 -6
  124. package/src/datepicker/createDatePicker.ts +54 -16
  125. package/src/datepicker/createDateRangePicker.ts +246 -0
  126. package/src/datepicker/createDateSegment.ts +185 -31
  127. package/src/datepicker/createTimeSegment.ts +370 -0
  128. package/src/datepicker/index.ts +14 -0
  129. package/src/dialog/createDialog.ts +120 -120
  130. package/src/dialog/index.ts +2 -2
  131. package/src/dialog/types.ts +19 -19
  132. package/src/disclosure/createDisclosureGroup.ts +5 -2
  133. package/src/dnd/createDrag.ts +224 -209
  134. package/src/dnd/createDraggableCollection.ts +96 -63
  135. package/src/dnd/createDraggableItem.ts +259 -243
  136. package/src/dnd/createDrop.ts +322 -321
  137. package/src/dnd/createDroppableCollection.ts +682 -293
  138. package/src/dnd/createDroppableItem.ts +215 -213
  139. package/src/dnd/index.ts +55 -47
  140. package/src/dnd/types.ts +89 -89
  141. package/src/dnd/utils.ts +294 -294
  142. package/src/focus/createAutoFocus.ts +321 -321
  143. package/src/focus/createFocusRestore.ts +313 -313
  144. package/src/focus/createVirtualFocus.ts +396 -396
  145. package/src/form/createFormValidation.ts +224 -224
  146. package/src/form/index.ts +11 -11
  147. package/src/grid/createGrid.ts +3 -1
  148. package/src/gridlist/createGridList.ts +16 -0
  149. package/src/gridlist/createGridListItem.ts +1 -1
  150. package/src/i18n/NumberFormatter.ts +266 -266
  151. package/src/i18n/createCollator.ts +79 -79
  152. package/src/i18n/createDateFormatter.ts +83 -83
  153. package/src/i18n/createFilter.ts +131 -131
  154. package/src/i18n/createNumberFormatter.ts +52 -52
  155. package/src/i18n/index.ts +40 -40
  156. package/src/i18n/locale.tsx +188 -188
  157. package/src/i18n/utils.ts +99 -99
  158. package/src/index.ts +51 -0
  159. package/src/interactions/createFocus.ts +6 -5
  160. package/src/interactions/createFocusWithin.ts +6 -5
  161. package/src/interactions/createLongPress.ts +174 -174
  162. package/src/interactions/createMove.ts +289 -289
  163. package/src/interactions/createPress.ts +5 -5
  164. package/src/landmark/createLandmark.ts +377 -377
  165. package/src/landmark/index.ts +8 -8
  166. package/src/link/createLink.ts +23 -8
  167. package/src/listbox/createListBox.ts +308 -269
  168. package/src/listbox/createOption.ts +162 -151
  169. package/src/listbox/index.ts +12 -12
  170. package/src/live-announcer/announce.ts +322 -322
  171. package/src/live-announcer/index.ts +9 -9
  172. package/src/menu/createMenu.ts +405 -396
  173. package/src/menu/createMenuItem.ts +149 -149
  174. package/src/menu/createMenuTrigger.ts +88 -88
  175. package/src/menu/index.ts +18 -18
  176. package/src/meter/createMeter.ts +1 -6
  177. package/src/numberfield/createNumberField.ts +311 -268
  178. package/src/numberfield/index.ts +5 -5
  179. package/src/overlays/ariaHideOutside.ts +219 -219
  180. package/src/overlays/createInteractOutside.ts +149 -149
  181. package/src/overlays/createModal.tsx +238 -202
  182. package/src/overlays/createOverlay.ts +165 -155
  183. package/src/overlays/createOverlayTrigger.ts +85 -85
  184. package/src/overlays/createPreventScroll.ts +266 -266
  185. package/src/overlays/index.ts +48 -44
  186. package/src/popover/calculatePosition.ts +6 -6
  187. package/src/popover/createOverlayPosition.ts +7 -4
  188. package/src/popover/createPopover.ts +21 -7
  189. package/src/progress/createProgressBar.ts +6 -1
  190. package/src/radio/createRadioGroup.ts +88 -14
  191. package/src/searchfield/createSearchField.ts +241 -186
  192. package/src/searchfield/index.ts +2 -2
  193. package/src/select/createHiddenSelect.tsx +263 -236
  194. package/src/select/createSelect.ts +373 -395
  195. package/src/select/index.ts +14 -14
  196. package/src/slider/createSlider.ts +364 -349
  197. package/src/slider/index.ts +2 -2
  198. package/src/ssr/index.tsx +370 -370
  199. package/src/table/createTable.ts +3 -1
  200. package/src/table/createTableColumnHeader.ts +1 -1
  201. package/src/table/createTableRow.ts +1 -1
  202. package/src/tabs/createTabs.ts +80 -51
  203. package/src/tag/createTag.ts +135 -6
  204. package/src/tag/createTagGroup.ts +7 -2
  205. package/src/toast/createToast.ts +8 -2
  206. package/src/toast/createToastRegion.ts +0 -1
  207. package/src/toolbar/createToolbar.ts +75 -1
  208. package/src/tooltip/createTooltip.ts +79 -79
  209. package/src/tooltip/createTooltipTrigger.ts +226 -222
  210. package/src/tooltip/index.ts +6 -6
  211. package/src/tree/createTree.ts +261 -246
  212. package/src/tree/createTreeItem.ts +282 -233
  213. package/src/tree/createTreeSelectionCheckbox.ts +68 -68
  214. package/src/tree/index.ts +16 -16
  215. package/src/tree/types.ts +91 -87
  216. package/src/utils/env.ts +55 -54
  217. package/src/utils/platform.ts +16 -6
  218. package/src/visually-hidden/createVisuallyHidden.ts +139 -124
  219. package/src/visually-hidden/index.ts +6 -6
package/src/dnd/utils.ts CHANGED
@@ -1,294 +1,294 @@
1
- /**
2
- * Drag and Drop utilities for solidaria.
3
- */
4
-
5
- import type {
6
- DragItem,
7
- DropItem,
8
- TextDropItem,
9
- FileDropItem,
10
- DirectoryDropItem,
11
- DropOperation,
12
- } from '@proyecto-viviana/solid-stately';
13
-
14
- // Native drag types that can be transferred between applications
15
- export const NATIVE_DRAG_TYPES: Set<string> = new Set([
16
- 'text/plain',
17
- 'text/uri-list',
18
- 'text/html',
19
- ]);
20
-
21
- // Custom drag type for serializing multiple items
22
- export const CUSTOM_DRAG_TYPE = 'application/vnd.solidaria.items+json';
23
-
24
- // Generic type for unknown file types
25
- export const GENERIC_TYPE = 'application/octet-stream';
26
-
27
- // Drop operation bit flags
28
- export enum DROP_OPERATION {
29
- none = 0,
30
- cancel = 0,
31
- move = 1 << 0,
32
- copy = 1 << 1,
33
- link = 1 << 2,
34
- all = (1 << 0) | (1 << 1) | (1 << 2),
35
- }
36
-
37
- // Map from effectAllowed to DROP_OPERATION
38
- export const DROP_OPERATION_ALLOWED: Record<string, number> = {
39
- none: DROP_OPERATION.none,
40
- copy: DROP_OPERATION.copy,
41
- copyLink: DROP_OPERATION.copy | DROP_OPERATION.link,
42
- copyMove: DROP_OPERATION.copy | DROP_OPERATION.move,
43
- link: DROP_OPERATION.link,
44
- linkMove: DROP_OPERATION.link | DROP_OPERATION.move,
45
- move: DROP_OPERATION.move,
46
- all: DROP_OPERATION.all,
47
- uninitialized: DROP_OPERATION.all,
48
- };
49
-
50
- // Map from DROP_OPERATION to effectAllowed
51
- export const EFFECT_ALLOWED: Record<number, string> = {
52
- [DROP_OPERATION.none]: 'none',
53
- [DROP_OPERATION.move]: 'move',
54
- [DROP_OPERATION.copy]: 'copy',
55
- [DROP_OPERATION.copy | DROP_OPERATION.move]: 'copyMove',
56
- [DROP_OPERATION.link]: 'link',
57
- [DROP_OPERATION.link | DROP_OPERATION.move]: 'linkMove',
58
- [DROP_OPERATION.copy | DROP_OPERATION.link]: 'copyLink',
59
- [DROP_OPERATION.all]: 'all',
60
- };
61
-
62
- // Map from dropEffect to DropOperation
63
- export const DROP_EFFECT_TO_DROP_OPERATION: Record<string, DropOperation> = {
64
- none: 'cancel',
65
- link: 'link',
66
- copy: 'copy',
67
- move: 'move',
68
- };
69
-
70
- // Map from DropOperation to dropEffect
71
- export const DROP_OPERATION_TO_DROP_EFFECT: Record<DropOperation, string> = {
72
- cancel: 'none',
73
- link: 'link',
74
- copy: 'copy',
75
- move: 'move',
76
- };
77
-
78
- /**
79
- * Get the types present in drag items.
80
- */
81
- export function getTypes(items: DragItem[]): Set<string> {
82
- const types = new Set<string>();
83
- for (const item of items) {
84
- for (const type of Object.keys(item)) {
85
- types.add(type);
86
- }
87
- }
88
- return types;
89
- }
90
-
91
- /**
92
- * Write drag items to a DataTransfer object.
93
- */
94
- export function writeToDataTransfer(
95
- dataTransfer: DataTransfer,
96
- items: DragItem[]
97
- ): void {
98
- const groupedByType = new Map<string, string[]>();
99
- let needsCustomData = false;
100
- const customData: object[] = [];
101
-
102
- for (const item of items) {
103
- const types = Object.keys(item);
104
- if (types.length > 1) {
105
- needsCustomData = true;
106
- }
107
-
108
- const dataByType: Record<string, string> = {};
109
- for (const type of types) {
110
- let typeItems = groupedByType.get(type);
111
- if (!typeItems) {
112
- typeItems = [];
113
- groupedByType.set(type, typeItems);
114
- } else {
115
- needsCustomData = true;
116
- }
117
-
118
- const data = item[type];
119
- dataByType[type] = data;
120
- typeItems.push(data);
121
- }
122
-
123
- customData.push(dataByType);
124
- }
125
-
126
- for (const [type, typeItems] of groupedByType) {
127
- if (NATIVE_DRAG_TYPES.has(type)) {
128
- // Join all items of this type with newlines
129
- const data = typeItems.join('\n');
130
- dataTransfer.items.add(data, type);
131
- } else {
132
- // Set first item for non-native types
133
- dataTransfer.items.add(typeItems[0], type);
134
- }
135
- }
136
-
137
- if (needsCustomData) {
138
- const data = JSON.stringify(customData);
139
- dataTransfer.items.add(data, CUSTOM_DRAG_TYPE);
140
- }
141
- }
142
-
143
- /**
144
- * Read drop items from a DataTransfer object.
145
- */
146
- export function readFromDataTransfer(dataTransfer: DataTransfer): DropItem[] {
147
- const items: DropItem[] = [];
148
-
149
- if (!dataTransfer) {
150
- return items;
151
- }
152
-
153
- // Check for custom drag type first
154
- let hasCustomType = false;
155
- if (dataTransfer.types.includes(CUSTOM_DRAG_TYPE)) {
156
- try {
157
- const data = dataTransfer.getData(CUSTOM_DRAG_TYPE);
158
- const parsed = JSON.parse(data);
159
- for (const item of parsed) {
160
- items.push({
161
- kind: 'text',
162
- types: new Set(Object.keys(item)),
163
- getText: (type) => Promise.resolve(item[type]),
164
- });
165
- }
166
- hasCustomType = true;
167
- } catch {
168
- // ignore parsing errors
169
- }
170
- }
171
-
172
- // Fall back to native items
173
- if (!hasCustomType) {
174
- const stringItems = new Map<string, string>();
175
-
176
- for (const item of dataTransfer.items) {
177
- if (item.kind === 'string') {
178
- const type = item.type || GENERIC_TYPE;
179
- stringItems.set(type, dataTransfer.getData(item.type));
180
- } else if (item.kind === 'file') {
181
- const file = item.getAsFile();
182
- if (file) {
183
- items.push(createFileItem(file));
184
- }
185
- }
186
- }
187
-
188
- if (stringItems.size > 0) {
189
- items.push({
190
- kind: 'text',
191
- types: new Set(stringItems.keys()),
192
- getText: (type) => Promise.resolve(stringItems.get(type) ?? ''),
193
- });
194
- }
195
- }
196
-
197
- return items;
198
- }
199
-
200
- /**
201
- * Create a FileDropItem from a File object.
202
- */
203
- function createFileItem(file: File): FileDropItem {
204
- return {
205
- kind: 'file',
206
- type: file.type || GENERIC_TYPE,
207
- name: file.name,
208
- getText: () => file.text(),
209
- getFile: () => Promise.resolve(file),
210
- };
211
- }
212
-
213
- /**
214
- * DragTypes implementation for checking drag types.
215
- */
216
- export class DragTypesImpl {
217
- private types: Set<string>;
218
- private includesUnknownTypes: boolean;
219
-
220
- constructor(dataTransfer: DataTransfer) {
221
- this.types = new Set<string>();
222
- let hasFiles = false;
223
-
224
- for (const item of dataTransfer.items) {
225
- if (item.type !== CUSTOM_DRAG_TYPE) {
226
- if (item.kind === 'file') {
227
- hasFiles = true;
228
- }
229
- if (item.type) {
230
- this.types.add(item.type);
231
- } else {
232
- this.types.add(GENERIC_TYPE);
233
- }
234
- }
235
- }
236
-
237
- // Safari doesn't expose file types until drop
238
- this.includesUnknownTypes =
239
- !hasFiles && dataTransfer.types.includes('Files');
240
- }
241
-
242
- has(type: string | symbol): boolean {
243
- if (
244
- this.includesUnknownTypes ||
245
- (typeof type === 'symbol' && this.types.has(GENERIC_TYPE))
246
- ) {
247
- return true;
248
- }
249
- return typeof type === 'string' && this.types.has(type);
250
- }
251
- }
252
-
253
- /**
254
- * Check if a drop item is a text item.
255
- */
256
- export function isTextDropItem(dropItem: DropItem): dropItem is TextDropItem {
257
- return dropItem.kind === 'text';
258
- }
259
-
260
- /**
261
- * Check if a drop item is a file item.
262
- */
263
- export function isFileDropItem(dropItem: DropItem): dropItem is FileDropItem {
264
- return dropItem.kind === 'file';
265
- }
266
-
267
- /**
268
- * Check if a drop item is a directory item.
269
- */
270
- export function isDirectoryDropItem(
271
- dropItem: DropItem
272
- ): dropItem is DirectoryDropItem {
273
- return dropItem.kind === 'directory';
274
- }
275
-
276
- // Global state for tracking drag operations
277
- let globalDropEffect: string | undefined;
278
- let globalAllowedDropOperations: number = DROP_OPERATION.none;
279
-
280
- export function setGlobalDropEffect(effect: string | undefined): void {
281
- globalDropEffect = effect;
282
- }
283
-
284
- export function getGlobalDropEffect(): string | undefined {
285
- return globalDropEffect;
286
- }
287
-
288
- export function setGlobalAllowedDropOperations(ops: number): void {
289
- globalAllowedDropOperations = ops;
290
- }
291
-
292
- export function getGlobalAllowedDropOperations(): number {
293
- return globalAllowedDropOperations;
294
- }
1
+ /**
2
+ * Drag and Drop utilities for solidaria.
3
+ */
4
+
5
+ import type {
6
+ DragItem,
7
+ DropItem,
8
+ TextDropItem,
9
+ FileDropItem,
10
+ DirectoryDropItem,
11
+ DropOperation,
12
+ } from '@proyecto-viviana/solid-stately';
13
+
14
+ // Native drag types that can be transferred between applications
15
+ export const NATIVE_DRAG_TYPES: Set<string> = new Set([
16
+ 'text/plain',
17
+ 'text/uri-list',
18
+ 'text/html',
19
+ ]);
20
+
21
+ // Custom drag type for serializing multiple items
22
+ export const CUSTOM_DRAG_TYPE = 'application/vnd.solidaria.items+json';
23
+
24
+ // Generic type for unknown file types
25
+ export const GENERIC_TYPE = 'application/octet-stream';
26
+
27
+ // Drop operation bit flags
28
+ export enum DROP_OPERATION {
29
+ none = 0,
30
+ cancel = 0,
31
+ move = 1 << 0,
32
+ copy = 1 << 1,
33
+ link = 1 << 2,
34
+ all = (1 << 0) | (1 << 1) | (1 << 2),
35
+ }
36
+
37
+ // Map from effectAllowed to DROP_OPERATION
38
+ export const DROP_OPERATION_ALLOWED: Record<string, number> = {
39
+ none: DROP_OPERATION.none,
40
+ copy: DROP_OPERATION.copy,
41
+ copyLink: DROP_OPERATION.copy | DROP_OPERATION.link,
42
+ copyMove: DROP_OPERATION.copy | DROP_OPERATION.move,
43
+ link: DROP_OPERATION.link,
44
+ linkMove: DROP_OPERATION.link | DROP_OPERATION.move,
45
+ move: DROP_OPERATION.move,
46
+ all: DROP_OPERATION.all,
47
+ uninitialized: DROP_OPERATION.all,
48
+ };
49
+
50
+ // Map from DROP_OPERATION to effectAllowed
51
+ export const EFFECT_ALLOWED: Record<number, string> = {
52
+ [DROP_OPERATION.none]: 'none',
53
+ [DROP_OPERATION.move]: 'move',
54
+ [DROP_OPERATION.copy]: 'copy',
55
+ [DROP_OPERATION.copy | DROP_OPERATION.move]: 'copyMove',
56
+ [DROP_OPERATION.link]: 'link',
57
+ [DROP_OPERATION.link | DROP_OPERATION.move]: 'linkMove',
58
+ [DROP_OPERATION.copy | DROP_OPERATION.link]: 'copyLink',
59
+ [DROP_OPERATION.all]: 'all',
60
+ };
61
+
62
+ // Map from dropEffect to DropOperation
63
+ export const DROP_EFFECT_TO_DROP_OPERATION: Record<string, DropOperation> = {
64
+ none: 'cancel',
65
+ link: 'link',
66
+ copy: 'copy',
67
+ move: 'move',
68
+ };
69
+
70
+ // Map from DropOperation to dropEffect
71
+ export const DROP_OPERATION_TO_DROP_EFFECT: Record<DropOperation, string> = {
72
+ cancel: 'none',
73
+ link: 'link',
74
+ copy: 'copy',
75
+ move: 'move',
76
+ };
77
+
78
+ /**
79
+ * Get the types present in drag items.
80
+ */
81
+ export function getTypes(items: DragItem[]): Set<string> {
82
+ const types = new Set<string>();
83
+ for (const item of items) {
84
+ for (const type of Object.keys(item)) {
85
+ types.add(type);
86
+ }
87
+ }
88
+ return types;
89
+ }
90
+
91
+ /**
92
+ * Write drag items to a DataTransfer object.
93
+ */
94
+ export function writeToDataTransfer(
95
+ dataTransfer: DataTransfer,
96
+ items: DragItem[]
97
+ ): void {
98
+ const groupedByType = new Map<string, string[]>();
99
+ let needsCustomData = false;
100
+ const customData: object[] = [];
101
+
102
+ for (const item of items) {
103
+ const types = Object.keys(item);
104
+ if (types.length > 1) {
105
+ needsCustomData = true;
106
+ }
107
+
108
+ const dataByType: Record<string, string> = {};
109
+ for (const type of types) {
110
+ let typeItems = groupedByType.get(type);
111
+ if (!typeItems) {
112
+ typeItems = [];
113
+ groupedByType.set(type, typeItems);
114
+ } else {
115
+ needsCustomData = true;
116
+ }
117
+
118
+ const data = item[type];
119
+ dataByType[type] = data;
120
+ typeItems.push(data);
121
+ }
122
+
123
+ customData.push(dataByType);
124
+ }
125
+
126
+ for (const [type, typeItems] of groupedByType) {
127
+ if (NATIVE_DRAG_TYPES.has(type)) {
128
+ // Join all items of this type with newlines
129
+ const data = typeItems.join('\n');
130
+ dataTransfer.items.add(data, type);
131
+ } else {
132
+ // Set first item for non-native types
133
+ dataTransfer.items.add(typeItems[0], type);
134
+ }
135
+ }
136
+
137
+ if (needsCustomData) {
138
+ const data = JSON.stringify(customData);
139
+ dataTransfer.items.add(data, CUSTOM_DRAG_TYPE);
140
+ }
141
+ }
142
+
143
+ /**
144
+ * Read drop items from a DataTransfer object.
145
+ */
146
+ export function readFromDataTransfer(dataTransfer: DataTransfer): DropItem[] {
147
+ const items: DropItem[] = [];
148
+
149
+ if (!dataTransfer) {
150
+ return items;
151
+ }
152
+
153
+ // Check for custom drag type first
154
+ let hasCustomType = false;
155
+ if (dataTransfer.types.includes(CUSTOM_DRAG_TYPE)) {
156
+ try {
157
+ const data = dataTransfer.getData(CUSTOM_DRAG_TYPE);
158
+ const parsed = JSON.parse(data);
159
+ for (const item of parsed) {
160
+ items.push({
161
+ kind: 'text',
162
+ types: new Set(Object.keys(item)),
163
+ getText: (type) => Promise.resolve(item[type]),
164
+ });
165
+ }
166
+ hasCustomType = true;
167
+ } catch {
168
+ // ignore parsing errors
169
+ }
170
+ }
171
+
172
+ // Fall back to native items
173
+ if (!hasCustomType) {
174
+ const stringItems = new Map<string, string>();
175
+
176
+ for (const item of dataTransfer.items) {
177
+ if (item.kind === 'string') {
178
+ const type = item.type || GENERIC_TYPE;
179
+ stringItems.set(type, dataTransfer.getData(item.type));
180
+ } else if (item.kind === 'file') {
181
+ const file = item.getAsFile();
182
+ if (file) {
183
+ items.push(createFileItem(file));
184
+ }
185
+ }
186
+ }
187
+
188
+ if (stringItems.size > 0) {
189
+ items.push({
190
+ kind: 'text',
191
+ types: new Set(stringItems.keys()),
192
+ getText: (type) => Promise.resolve(stringItems.get(type) ?? ''),
193
+ });
194
+ }
195
+ }
196
+
197
+ return items;
198
+ }
199
+
200
+ /**
201
+ * Create a FileDropItem from a File object.
202
+ */
203
+ function createFileItem(file: File): FileDropItem {
204
+ return {
205
+ kind: 'file',
206
+ type: file.type || GENERIC_TYPE,
207
+ name: file.name,
208
+ getText: () => file.text(),
209
+ getFile: () => Promise.resolve(file),
210
+ };
211
+ }
212
+
213
+ /**
214
+ * DragTypes implementation for checking drag types.
215
+ */
216
+ export class DragTypesImpl {
217
+ private types: Set<string>;
218
+ private includesUnknownTypes: boolean;
219
+
220
+ constructor(dataTransfer: DataTransfer) {
221
+ this.types = new Set<string>();
222
+ let hasFiles = false;
223
+
224
+ for (const item of dataTransfer.items) {
225
+ if (item.type !== CUSTOM_DRAG_TYPE) {
226
+ if (item.kind === 'file') {
227
+ hasFiles = true;
228
+ }
229
+ if (item.type) {
230
+ this.types.add(item.type);
231
+ } else {
232
+ this.types.add(GENERIC_TYPE);
233
+ }
234
+ }
235
+ }
236
+
237
+ // Safari doesn't expose file types until drop
238
+ this.includesUnknownTypes =
239
+ !hasFiles && dataTransfer.types.includes('Files');
240
+ }
241
+
242
+ has(type: string | symbol): boolean {
243
+ if (
244
+ this.includesUnknownTypes ||
245
+ (typeof type === 'symbol' && this.types.has(GENERIC_TYPE))
246
+ ) {
247
+ return true;
248
+ }
249
+ return typeof type === 'string' && this.types.has(type);
250
+ }
251
+ }
252
+
253
+ /**
254
+ * Check if a drop item is a text item.
255
+ */
256
+ export function isTextDropItem(dropItem: DropItem): dropItem is TextDropItem {
257
+ return dropItem.kind === 'text';
258
+ }
259
+
260
+ /**
261
+ * Check if a drop item is a file item.
262
+ */
263
+ export function isFileDropItem(dropItem: DropItem): dropItem is FileDropItem {
264
+ return dropItem.kind === 'file';
265
+ }
266
+
267
+ /**
268
+ * Check if a drop item is a directory item.
269
+ */
270
+ export function isDirectoryDropItem(
271
+ dropItem: DropItem
272
+ ): dropItem is DirectoryDropItem {
273
+ return dropItem.kind === 'directory';
274
+ }
275
+
276
+ // Global state for tracking drag operations
277
+ let globalDropEffect: string | undefined;
278
+ let globalAllowedDropOperations: number = DROP_OPERATION.none;
279
+
280
+ export function setGlobalDropEffect(effect: string | undefined): void {
281
+ globalDropEffect = effect;
282
+ }
283
+
284
+ export function getGlobalDropEffect(): string | undefined {
285
+ return globalDropEffect;
286
+ }
287
+
288
+ export function setGlobalAllowedDropOperations(ops: number): void {
289
+ globalAllowedDropOperations = ops;
290
+ }
291
+
292
+ export function getGlobalAllowedDropOperations(): number {
293
+ return globalAllowedDropOperations;
294
+ }