react-native-gtkx 0.2.0-alpha.2 → 0.3.0-alpha.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/README.md +5 -2
- package/dist/aliases/index.d.ts +84 -0
- package/dist/aliases/index.js +208 -0
- package/dist/aliases/index.js.map +1 -0
- package/dist/animated/index.d.ts +2 -0
- package/dist/animated/index.js +5 -0
- package/dist/animated/index.js.map +1 -1
- package/dist/animated/types.d.ts +1 -0
- package/dist/animated/types.js.map +1 -1
- package/dist/animated/value-animation.js +17 -4
- package/dist/animated/value-animation.js.map +1 -1
- package/dist/apis/host.gtkx.js +9 -12
- package/dist/apis/host.gtkx.js.map +1 -1
- package/dist/apis/index.d.ts +4 -2
- package/dist/apis/index.js +2 -0
- package/dist/apis/index.js.map +1 -1
- package/dist/apis/keyboard.d.ts +60 -0
- package/dist/apis/keyboard.js +63 -0
- package/dist/apis/keyboard.js.map +1 -0
- package/dist/apis/log-box.d.ts +15 -0
- package/dist/apis/log-box.js +46 -0
- package/dist/apis/log-box.js.map +1 -0
- package/dist/apis/platform.d.ts +18 -1
- package/dist/apis/platform.js.map +1 -1
- package/dist/common/index.d.ts +0 -1
- package/dist/common/index.js +24 -1
- package/dist/common/index.js.map +1 -1
- package/dist/components/animated.d.ts +70 -6
- package/dist/components/animated.js +559 -46
- package/dist/components/animated.js.map +1 -1
- package/dist/components/driven-size.d.ts +27 -0
- package/dist/components/driven-size.js +85 -0
- package/dist/components/driven-size.js.map +1 -0
- package/dist/components/find-node-handle.d.ts +11 -0
- package/dist/components/find-node-handle.js +53 -0
- package/dist/components/find-node-handle.js.map +1 -0
- package/dist/components/flat-list.d.ts +3 -2
- package/dist/components/flat-list.js.map +1 -1
- package/dist/components/frame-scheduler.d.ts +16 -0
- package/dist/components/frame-scheduler.js +37 -0
- package/dist/components/frame-scheduler.js.map +1 -0
- package/dist/components/image.d.ts +6 -1
- package/dist/components/image.js +15 -4
- package/dist/components/image.js.map +1 -1
- package/dist/components/index.d.ts +7 -5
- package/dist/components/index.js +5 -3
- package/dist/components/index.js.map +1 -1
- package/dist/components/measure.d.ts +51 -1
- package/dist/components/measure.js +101 -2
- package/dist/components/measure.js.map +1 -1
- package/dist/components/pressable.d.ts +61 -1
- package/dist/components/pressable.js +151 -4
- package/dist/components/pressable.js.map +1 -1
- package/dist/components/rect-store.d.ts +58 -0
- package/dist/components/rect-store.js +124 -3
- package/dist/components/rect-store.js.map +1 -1
- package/dist/components/root.js +6 -1
- package/dist/components/root.js.map +1 -1
- package/dist/components/scroll-phase.d.ts +35 -0
- package/dist/components/scroll-phase.js +26 -0
- package/dist/components/scroll-phase.js.map +1 -0
- package/dist/components/scroll-view.d.ts +39 -3
- package/dist/components/scroll-view.js +378 -43
- package/dist/components/scroll-view.js.map +1 -1
- package/dist/components/text-input.js +9 -25
- package/dist/components/text-input.js.map +1 -1
- package/dist/components/text.d.ts +6 -2
- package/dist/components/text.js +43 -8
- package/dist/components/text.js.map +1 -1
- package/dist/components/use-focus.d.ts +27 -0
- package/dist/components/use-focus.js +116 -0
- package/dist/components/use-focus.js.map +1 -0
- package/dist/components/use-layout-child.d.ts +13 -1
- package/dist/components/use-layout-child.js +188 -5
- package/dist/components/use-layout-child.js.map +1 -1
- package/dist/components/view.d.ts +5 -2
- package/dist/components/view.js +18 -13
- package/dist/components/view.js.map +1 -1
- package/dist/components/virtualized-list.d.ts +45 -5
- package/dist/components/virtualized-list.js +90 -24
- package/dist/components/virtualized-list.js.map +1 -1
- package/dist/components/wheel-scroll-session.d.ts +7 -0
- package/dist/components/wheel-scroll-session.js +53 -0
- package/dist/components/wheel-scroll-session.js.map +1 -0
- package/dist/components/widget-retention.d.ts +35 -0
- package/dist/components/widget-retention.js +169 -0
- package/dist/components/widget-retention.js.map +1 -0
- package/dist/contracts.d.ts +4 -0
- package/dist/contracts.js.map +1 -1
- package/dist/dnd/context.d.ts +69 -0
- package/dist/dnd/context.js +149 -0
- package/dist/dnd/context.js.map +1 -0
- package/dist/dnd/draggable.d.ts +59 -0
- package/dist/dnd/draggable.js +149 -0
- package/dist/dnd/draggable.js.map +1 -0
- package/dist/dnd/droppable.d.ts +24 -0
- package/dist/dnd/droppable.js +74 -0
- package/dist/dnd/droppable.js.map +1 -0
- package/dist/dnd/gtk-controllers.d.ts +39 -0
- package/dist/dnd/gtk-controllers.js +110 -0
- package/dist/dnd/gtk-controllers.js.map +1 -0
- package/dist/dnd/index.d.ts +6 -0
- package/dist/dnd/index.js +31 -0
- package/dist/dnd/index.js.map +1 -0
- package/dist/dnd/order.d.ts +7 -0
- package/dist/dnd/order.js +20 -0
- package/dist/dnd/order.js.map +1 -0
- package/dist/dnd/payload.d.ts +14 -0
- package/dist/dnd/payload.js +41 -0
- package/dist/dnd/payload.js.map +1 -0
- package/dist/dnd/sortable.d.ts +49 -0
- package/dist/dnd/sortable.js +307 -0
- package/dist/dnd/sortable.js.map +1 -0
- package/dist/dnd/types.d.ts +290 -0
- package/dist/dnd/types.js +25 -0
- package/dist/dnd/types.js.map +1 -0
- package/dist/gesture-handler-compat/builder.d.ts +251 -0
- package/dist/gesture-handler-compat/builder.js +513 -0
- package/dist/gesture-handler-compat/builder.js.map +1 -0
- package/dist/gesture-handler-compat/composition.d.ts +23 -0
- package/dist/gesture-handler-compat/composition.js +111 -0
- package/dist/gesture-handler-compat/composition.js.map +1 -0
- package/dist/gesture-handler-compat/deciders.d.ts +3 -0
- package/dist/gesture-handler-compat/deciders.js +47 -0
- package/dist/gesture-handler-compat/deciders.js.map +1 -0
- package/dist/gesture-handler-compat/detector-runtime.d.ts +44 -0
- package/dist/gesture-handler-compat/detector-runtime.js +374 -0
- package/dist/gesture-handler-compat/detector-runtime.js.map +1 -0
- package/dist/gesture-handler-compat/detector.d.ts +22 -0
- package/dist/gesture-handler-compat/detector.js +104 -0
- package/dist/gesture-handler-compat/detector.js.map +1 -0
- package/dist/gesture-handler-compat/fling.d.ts +24 -0
- package/dist/gesture-handler-compat/fling.js +123 -0
- package/dist/gesture-handler-compat/fling.js.map +1 -0
- package/dist/gesture-handler-compat/force-touch.d.ts +13 -0
- package/dist/gesture-handler-compat/force-touch.js +40 -0
- package/dist/gesture-handler-compat/force-touch.js.map +1 -0
- package/dist/gesture-handler-compat/hooks.d.ts +157 -0
- package/dist/gesture-handler-compat/hooks.js +268 -0
- package/dist/gesture-handler-compat/hooks.js.map +1 -0
- package/dist/gesture-handler-compat/hover.d.ts +2 -0
- package/dist/gesture-handler-compat/hover.js +22 -0
- package/dist/gesture-handler-compat/hover.js.map +1 -0
- package/dist/gesture-handler-compat/index.d.ts +98 -0
- package/dist/gesture-handler-compat/index.js +255 -0
- package/dist/gesture-handler-compat/index.js.map +1 -0
- package/dist/gesture-handler-compat/long-press.d.ts +6 -0
- package/dist/gesture-handler-compat/long-press.js +21 -0
- package/dist/gesture-handler-compat/long-press.js.map +1 -0
- package/dist/gesture-handler-compat/manual.d.ts +2 -0
- package/dist/gesture-handler-compat/manual.js +18 -0
- package/dist/gesture-handler-compat/manual.js.map +1 -0
- package/dist/gesture-handler-compat/native.d.ts +7 -0
- package/dist/gesture-handler-compat/native.js +34 -0
- package/dist/gesture-handler-compat/native.js.map +1 -0
- package/dist/gesture-handler-compat/orchestrator.d.ts +77 -0
- package/dist/gesture-handler-compat/orchestrator.js +284 -0
- package/dist/gesture-handler-compat/orchestrator.js.map +1 -0
- package/dist/gesture-handler-compat/pan.d.ts +23 -0
- package/dist/gesture-handler-compat/pan.js +116 -0
- package/dist/gesture-handler-compat/pan.js.map +1 -0
- package/dist/gesture-handler-compat/recognizer.d.ts +268 -0
- package/dist/gesture-handler-compat/recognizer.js +1056 -0
- package/dist/gesture-handler-compat/recognizer.js.map +1 -0
- package/dist/gesture-handler-compat/relations.d.ts +43 -0
- package/dist/gesture-handler-compat/relations.js +128 -0
- package/dist/gesture-handler-compat/relations.js.map +1 -0
- package/dist/gesture-handler-compat/tap.d.ts +6 -0
- package/dist/gesture-handler-compat/tap.js +29 -0
- package/dist/gesture-handler-compat/tap.js.map +1 -0
- package/dist/gesture-handler-compat/touchpad.d.ts +41 -0
- package/dist/gesture-handler-compat/touchpad.js +64 -0
- package/dist/gesture-handler-compat/touchpad.js.map +1 -0
- package/dist/gesture-handler-compat/types.d.ts +441 -0
- package/dist/gesture-handler-compat/types.js +167 -0
- package/dist/gesture-handler-compat/types.js.map +1 -0
- package/dist/gtk/controllers.d.ts +39 -0
- package/dist/gtk/controllers.js +92 -0
- package/dist/gtk/controllers.js.map +1 -0
- package/dist/gtk/index.d.ts +2 -1
- package/dist/gtk/index.js +7 -1
- package/dist/gtk/index.js.map +1 -1
- package/dist/gtkx/bridge/geometry.js +6 -4
- package/dist/gtkx/bridge/geometry.js.map +1 -1
- package/dist/gtkx/bridge/index.d.ts +5 -3
- package/dist/gtkx/bridge/index.js +6 -3
- package/dist/gtkx/bridge/index.js.map +1 -1
- package/dist/gtkx/bridge/slot-portal.js.map +1 -1
- package/dist/gtkx/bridge/use-signal.js +1 -1
- package/dist/gtkx/bridge/use-signal.js.map +1 -1
- package/dist/gtkx/bridge/view-box.d.ts +56 -0
- package/dist/gtkx/bridge/view-box.js +394 -9
- package/dist/gtkx/bridge/view-box.js.map +1 -1
- package/dist/gtkx/bridge/widget-css.d.ts +17 -0
- package/dist/gtkx/bridge/widget-css.js +72 -0
- package/dist/gtkx/bridge/widget-css.js.map +1 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/layout/driven-size.d.ts +12 -0
- package/dist/layout/driven-size.js +70 -0
- package/dist/layout/driven-size.js.map +1 -0
- package/dist/layout/engine.d.ts +17 -1
- package/dist/layout/engine.js +3 -20
- package/dist/layout/engine.js.map +1 -1
- package/dist/layout/node.d.ts +13 -0
- package/dist/layout/node.js +14 -0
- package/dist/layout/node.js.map +1 -1
- package/dist/layout/yoga.d.ts +3 -2
- package/dist/layout/yoga.js +5 -2
- package/dist/layout/yoga.js.map +1 -1
- package/dist/mcp/data/generated.d.ts +257 -60
- package/dist/mcp/data/generated.js +306 -62
- package/dist/mcp/data/generated.js.map +1 -1
- package/dist/metro/index.d.ts +10 -0
- package/dist/metro/index.js +21 -12
- package/dist/metro/index.js.map +1 -1
- package/dist/navigation/sidebar.d.ts +16 -0
- package/dist/navigation/sidebar.js +65 -1
- package/dist/navigation/sidebar.js.map +1 -1
- package/dist/reanimated-compat/animated-ref.d.ts +32 -0
- package/dist/reanimated-compat/animated-ref.js +57 -0
- package/dist/reanimated-compat/animated-ref.js.map +1 -0
- package/dist/reanimated-compat/animation.d.ts +177 -0
- package/dist/reanimated-compat/animation.js +540 -0
- package/dist/reanimated-compat/animation.js.map +1 -0
- package/dist/reanimated-compat/color.d.ts +28 -0
- package/dist/reanimated-compat/color.js +249 -0
- package/dist/reanimated-compat/color.js.map +1 -0
- package/dist/reanimated-compat/decay.d.ts +39 -0
- package/dist/reanimated-compat/decay.js +96 -0
- package/dist/reanimated-compat/decay.js.map +1 -0
- package/dist/reanimated-compat/easing.d.ts +30 -0
- package/dist/reanimated-compat/easing.js +76 -0
- package/dist/reanimated-compat/easing.js.map +1 -0
- package/dist/reanimated-compat/hooks.d.ts +14 -0
- package/dist/reanimated-compat/hooks.js +217 -0
- package/dist/reanimated-compat/hooks.js.map +1 -0
- package/dist/reanimated-compat/index.d.ts +258 -0
- package/dist/reanimated-compat/index.js +464 -0
- package/dist/reanimated-compat/index.js.map +1 -0
- package/dist/reanimated-compat/interpolation.d.ts +18 -0
- package/dist/reanimated-compat/interpolation.js +122 -0
- package/dist/reanimated-compat/interpolation.js.map +1 -0
- package/dist/reanimated-compat/layout-animation-config.d.ts +43 -0
- package/dist/reanimated-compat/layout-animation-config.js +78 -0
- package/dist/reanimated-compat/layout-animation-config.js.map +1 -0
- package/dist/reanimated-compat/layout-animation-presets.d.ts +117 -0
- package/dist/reanimated-compat/layout-animation-presets.js +498 -0
- package/dist/reanimated-compat/layout-animation-presets.js.map +1 -0
- package/dist/reanimated-compat/layout-animation-runtime.d.ts +21 -0
- package/dist/reanimated-compat/layout-animation-runtime.js +311 -0
- package/dist/reanimated-compat/layout-animation-runtime.js.map +1 -0
- package/dist/reanimated-compat/layout-animation-view.d.ts +27 -0
- package/dist/reanimated-compat/layout-animation-view.js +266 -0
- package/dist/reanimated-compat/layout-animation-view.js.map +1 -0
- package/dist/reanimated-compat/layout-animation.d.ts +171 -0
- package/dist/reanimated-compat/layout-animation.js +469 -0
- package/dist/reanimated-compat/layout-animation.js.map +1 -0
- package/dist/reanimated-compat/layout-transitions.d.ts +83 -0
- package/dist/reanimated-compat/layout-transitions.js +350 -0
- package/dist/reanimated-compat/layout-transitions.js.map +1 -0
- package/dist/reanimated-compat/mutable.d.ts +29 -0
- package/dist/reanimated-compat/mutable.js +139 -0
- package/dist/reanimated-compat/mutable.js.map +1 -0
- package/dist/reanimated-compat/props.d.ts +18 -0
- package/dist/reanimated-compat/props.js +111 -0
- package/dist/reanimated-compat/props.js.map +1 -0
- package/dist/reanimated-compat/scroll-handler.d.ts +119 -0
- package/dist/reanimated-compat/scroll-handler.js +274 -0
- package/dist/reanimated-compat/scroll-handler.js.map +1 -0
- package/dist/reanimated-compat/scroll-offset.d.ts +12 -0
- package/dist/reanimated-compat/scroll-offset.js +104 -0
- package/dist/reanimated-compat/scroll-offset.js.map +1 -0
- package/dist/reanimated-compat/style.d.ts +90 -0
- package/dist/reanimated-compat/style.js +452 -0
- package/dist/reanimated-compat/style.js.map +1 -0
- package/dist/reanimated-compat/test-timers.d.ts +28 -0
- package/dist/reanimated-compat/test-timers.js +136 -0
- package/dist/reanimated-compat/test-timers.js.map +1 -0
- package/dist/reanimated-compat/threads.d.ts +13 -0
- package/dist/reanimated-compat/threads.js +41 -0
- package/dist/reanimated-compat/threads.js.map +1 -0
- package/dist/reanimated-compat/tracking.d.ts +41 -0
- package/dist/reanimated-compat/tracking.js +106 -0
- package/dist/reanimated-compat/tracking.js.map +1 -0
- package/dist/reanimated-compat/updater-animations.d.ts +36 -0
- package/dist/reanimated-compat/updater-animations.js +273 -0
- package/dist/reanimated-compat/updater-animations.js.map +1 -0
- package/dist/responder/system.d.ts +80 -7
- package/dist/responder/system.js +143 -23
- package/dist/responder/system.js.map +1 -1
- package/dist/responder/use-responder.d.ts +11 -0
- package/dist/responder/use-responder.js +225 -6
- package/dist/responder/use-responder.js.map +1 -1
- package/dist/runner/host-dev.js +1 -1
- package/dist/runner/host-dev.js.map +1 -1
- package/dist/runner/host.js +1 -1
- package/dist/runner/host.js.map +1 -1
- package/dist/runner/index.js +3 -3
- package/dist/runner/index.js.map +1 -1
- package/dist/sea/gtkx-config-module.js +1 -1
- package/dist/sea/gtkx-config-module.js.map +1 -1
- package/dist/style/absolute-insets.d.ts +26 -0
- package/dist/style/absolute-insets.js +113 -0
- package/dist/style/absolute-insets.js.map +1 -0
- package/dist/style/animated-size.d.ts +25 -0
- package/dist/style/animated-size.js +225 -0
- package/dist/style/animated-size.js.map +1 -0
- package/dist/style/colors.d.ts +17 -0
- package/dist/style/colors.js +25 -6
- package/dist/style/colors.js.map +1 -1
- package/dist/style/imperative-css.d.ts +21 -0
- package/dist/style/imperative-css.js +63 -0
- package/dist/style/imperative-css.js.map +1 -0
- package/dist/style/index.d.ts +2 -1
- package/dist/style/index.js +2 -1
- package/dist/style/index.js.map +1 -1
- package/dist/style/split-style.js +5 -0
- package/dist/style/split-style.js.map +1 -1
- package/dist/testing/index.js.map +1 -1
- package/dist/unsupported-export.d.ts +8 -0
- package/dist/unsupported-export.js +66 -0
- package/dist/unsupported-export.js.map +1 -0
- package/dist/vite/index.d.ts +21 -8
- package/dist/vite/index.js +127 -82
- package/dist/vite/index.js.map +1 -1
- package/dist/vitest/index.d.ts +2 -2
- package/dist/vitest/index.js.map +1 -1
- package/dist/worklets-compat/index.d.ts +4 -0
- package/dist/worklets-compat/index.js +28 -0
- package/dist/worklets-compat/index.js.map +1 -0
- package/dist/worklets-compat/surface.d.ts +110 -0
- package/dist/worklets-compat/surface.js +153 -0
- package/dist/worklets-compat/surface.js.map +1 -0
- package/package.json +25 -9
- package/types.d.ts +9 -0
- package/dist/common/list.d.ts +0 -82
- package/dist/common/list.js +0 -166
- package/dist/common/list.js.map +0 -1
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// `Droppable` and `useDroppable`.
|
|
3
|
+
//
|
|
4
|
+
// Upstream registers a rectangle with the provider and the dragged item's
|
|
5
|
+
// own maths decides whether it landed inside. Here GDK decides, against the
|
|
6
|
+
// real widget tree — which is why `collisionAlgorithm` has nothing to
|
|
7
|
+
// configure and why a zone that is full can REFUSE a drop outright (the
|
|
8
|
+
// pointer then shows the no-drop cursor) rather than silently ignoring it.
|
|
9
|
+
import { useCallback, useEffect, useState } from "react";
|
|
10
|
+
import { View } from "../components/view";
|
|
11
|
+
import { useDropContext } from "./context";
|
|
12
|
+
import { DropTargetControllers } from "./gtk-controllers";
|
|
13
|
+
import { FREE_SCOPE, nextDraggableId } from "./payload";
|
|
14
|
+
/** The drop half of the module, as a hook, for a component that owns its own
|
|
15
|
+
* view. `viewProps.children` are the GTK controllers; spread them into the
|
|
16
|
+
* view the zone should cover. */
|
|
17
|
+
export const useDroppable = (options) => {
|
|
18
|
+
const { onDrop, dropDisabled = false, onActiveChange, activeStyle, droppableId, capacity = Number.POSITIVE_INFINITY, } = options;
|
|
19
|
+
const context = useDropContext();
|
|
20
|
+
const [isActive, setIsActive] = useState(false);
|
|
21
|
+
// Lazy initial state rather than a ref: stable for the component's
|
|
22
|
+
// lifetime, and a ref may not be read during render.
|
|
23
|
+
const [generatedId] = useState(nextDraggableId);
|
|
24
|
+
const id = droppableId ?? generatedId;
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
context.registerDroppable({ droppableId: id, capacity });
|
|
27
|
+
return () => context.unregisterDroppable(id);
|
|
28
|
+
}, [context, id, capacity]);
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
onActiveChange?.(isActive);
|
|
31
|
+
}, [isActive, onActiveChange]);
|
|
32
|
+
// A zone only accepts a free-standing draggable. A `SortableItem` carries
|
|
33
|
+
// its list's own scope so that dragging a row does not light up every drop
|
|
34
|
+
// zone on the screen — upstream keeps the two mechanisms apart in the same
|
|
35
|
+
// way, by never registering sortable items as slots.
|
|
36
|
+
const accepts = useCallback((payload) => payload.scope === FREE_SCOPE &&
|
|
37
|
+
context.dataFor(payload.id).found &&
|
|
38
|
+
context.hasAvailableCapacity(id), [context, id]);
|
|
39
|
+
const handleDrop = useCallback((payload) => {
|
|
40
|
+
setIsActive(false);
|
|
41
|
+
const { found, data } = context.dataFor(payload.id);
|
|
42
|
+
if (!found) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
context.registerDroppedItem(payload.id, id, data);
|
|
46
|
+
onDrop(data);
|
|
47
|
+
}, [context, id, onDrop]);
|
|
48
|
+
const controllers = dropDisabled ? null : (_jsx(DropTargetControllers, { accepts: accepts, onEnter: () => setIsActive(true), onLeave: () => setIsActive(false), onDrop: handleDrop }));
|
|
49
|
+
return { viewProps: { children: controllers }, isActive, activeStyle };
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* A zone that accepts a `Draggable`'s `data`.
|
|
53
|
+
*
|
|
54
|
+
* ```tsx
|
|
55
|
+
* <Droppable
|
|
56
|
+
* onDrop={(task) => assign(task)}
|
|
57
|
+
* activeStyle={{ borderColor: "accent" }}
|
|
58
|
+
* >
|
|
59
|
+
* <View style={styles.zone}>
|
|
60
|
+
* <Text>Assign to me</Text>
|
|
61
|
+
* </View>
|
|
62
|
+
* </Droppable>
|
|
63
|
+
* ```
|
|
64
|
+
*
|
|
65
|
+
* `capacity` is enforced at GDK level: once the zone is full it refuses the
|
|
66
|
+
* drop, so the cursor says so before the user lets go.
|
|
67
|
+
*/
|
|
68
|
+
export const Droppable = ({ children, style, testID, ...options }) => {
|
|
69
|
+
const droppable = useDroppable(options);
|
|
70
|
+
return (_jsxs(View, { style: droppable.isActive && droppable.activeStyle
|
|
71
|
+
? [style, droppable.activeStyle]
|
|
72
|
+
: style, testID: testID, children: [droppable.viewProps.children, children] }));
|
|
73
|
+
};
|
|
74
|
+
//# sourceMappingURL=droppable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"droppable.js","sourceRoot":"","sources":["../../src/dnd/droppable.tsx"],"names":[],"mappings":"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","sourcesContent":["// `Droppable` and `useDroppable`.\n//\n// Upstream registers a rectangle with the provider and the dragged item's\n// own maths decides whether it landed inside. Here GDK decides, against the\n// real widget tree — which is why `collisionAlgorithm` has nothing to\n// configure and why a zone that is full can REFUSE a drop outright (the\n// pointer then shows the no-drop cursor) rather than silently ignoring it.\nimport { useCallback, useEffect, useState, type ReactNode } from \"react\"\nimport { View } from \"../components/view\"\nimport { useDropContext } from \"./context\"\nimport { DropTargetControllers } from \"./gtk-controllers\"\nimport { FREE_SCOPE, nextDraggableId } from \"./payload\"\nimport type {\n DroppableProps,\n UseDroppableOptions,\n UseDroppableReturn,\n} from \"./types\"\n\n/** The drop half of the module, as a hook, for a component that owns its own\n * view. `viewProps.children` are the GTK controllers; spread them into the\n * view the zone should cover. */\nexport const useDroppable = <TData,>(\n options: UseDroppableOptions<TData>,\n): UseDroppableReturn => {\n const {\n onDrop,\n dropDisabled = false,\n onActiveChange,\n activeStyle,\n droppableId,\n capacity = Number.POSITIVE_INFINITY,\n } = options\n\n const context = useDropContext()\n const [isActive, setIsActive] = useState(false)\n\n // Lazy initial state rather than a ref: stable for the component's\n // lifetime, and a ref may not be read during render.\n const [generatedId] = useState(nextDraggableId)\n const id = droppableId ?? generatedId\n\n useEffect(() => {\n context.registerDroppable({ droppableId: id, capacity })\n return () => context.unregisterDroppable(id)\n }, [context, id, capacity])\n\n useEffect(() => {\n onActiveChange?.(isActive)\n }, [isActive, onActiveChange])\n\n // A zone only accepts a free-standing draggable. A `SortableItem` carries\n // its list's own scope so that dragging a row does not light up every drop\n // zone on the screen — upstream keeps the two mechanisms apart in the same\n // way, by never registering sortable items as slots.\n const accepts = useCallback(\n (payload: { scope: string; id: string }) =>\n payload.scope === FREE_SCOPE &&\n context.dataFor(payload.id).found &&\n context.hasAvailableCapacity(id),\n [context, id],\n )\n\n const handleDrop = useCallback(\n (payload: { scope: string; id: string }) => {\n setIsActive(false)\n const { found, data } = context.dataFor(payload.id)\n if (!found) {\n return\n }\n context.registerDroppedItem(payload.id, id, data)\n onDrop(data as TData)\n },\n [context, id, onDrop],\n )\n\n const controllers = dropDisabled ? null : (\n <DropTargetControllers\n accepts={accepts}\n onEnter={() => setIsActive(true)}\n onLeave={() => setIsActive(false)}\n onDrop={handleDrop}\n />\n )\n\n return { viewProps: { children: controllers }, isActive, activeStyle }\n}\n\n/**\n * A zone that accepts a `Draggable`'s `data`.\n *\n * ```tsx\n * <Droppable\n * onDrop={(task) => assign(task)}\n * activeStyle={{ borderColor: \"accent\" }}\n * >\n * <View style={styles.zone}>\n * <Text>Assign to me</Text>\n * </View>\n * </Droppable>\n * ```\n *\n * `capacity` is enforced at GDK level: once the zone is full it refuses the\n * drop, so the cursor says so before the user lets go.\n */\nexport const Droppable = <TData,>({\n children,\n style,\n testID,\n ...options\n}: DroppableProps<TData>): ReactNode => {\n const droppable = useDroppable<TData>(options)\n\n return (\n <View\n style={\n droppable.isActive && droppable.activeStyle\n ? [style, droppable.activeStyle]\n : style\n }\n testID={testID}\n >\n {droppable.viewProps.children}\n {children}\n </View>\n )\n}\n"]}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import { type DragPayload } from "./payload";
|
|
3
|
+
export type DragSourceControllersProps = {
|
|
4
|
+
payload: DragPayload;
|
|
5
|
+
/** Reports the grab point in the source widget's own coordinates, which is
|
|
6
|
+
* where the drag icon's hotspot goes and where `tx`/`ty` start from. */
|
|
7
|
+
onGrab?: (x: number, y: number) => void;
|
|
8
|
+
onDragBegin?: () => void;
|
|
9
|
+
/** `dropped` is what GDK's own `drag-end` reports: whether a target took
|
|
10
|
+
* it. `drag-cancel` reports the negative case separately, so both are
|
|
11
|
+
* folded into one callback here. */
|
|
12
|
+
onDragEnd?: (dropped: boolean) => void;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* A `GtkDragSource` on the enclosing React Native component's widget.
|
|
16
|
+
*
|
|
17
|
+
* The drag icon is a `Gtk.WidgetPaintable` of that widget, offset by where
|
|
18
|
+
* inside it the drag began — so the thing appears to lift off under the
|
|
19
|
+
* cursor rather than jump to it. That is the visual no JS drag can produce,
|
|
20
|
+
* and the reason this module is built on GDK at all.
|
|
21
|
+
*/
|
|
22
|
+
export declare const DragSourceControllers: ({ payload, onGrab, onDragBegin, onDragEnd, }: DragSourceControllersProps) => ReactNode;
|
|
23
|
+
export type DropTargetControllersProps = {
|
|
24
|
+
/** Return false to refuse — GDK then shows the no-drop cursor, which is
|
|
25
|
+
* better feedback than upstream's silent skip. */
|
|
26
|
+
accepts: (payload: DragPayload) => boolean;
|
|
27
|
+
onDrop: (payload: DragPayload, x: number, y: number) => void;
|
|
28
|
+
onEnter?: (payload: DragPayload) => void;
|
|
29
|
+
onMotion?: (payload: DragPayload, x: number, y: number) => void;
|
|
30
|
+
onLeave?: () => void;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* A `GtkDropTarget` on the enclosing React Native component's widget,
|
|
34
|
+
* accepting the string payload this module encodes.
|
|
35
|
+
*
|
|
36
|
+
* The payload is decoded before `accepts` is consulted, so a string dragged
|
|
37
|
+
* in from a text editor is refused rather than mistaken for a draggable.
|
|
38
|
+
*/
|
|
39
|
+
export declare const DropTargetControllers: ({ accepts, onDrop, onEnter, onMotion, onLeave, }: DropTargetControllersProps) => ReactNode;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
// The two GTK controllers everything in this module is built from, wrapped
|
|
3
|
+
// once so `Draggable`, `Droppable` and `SortableItem` do not each re-derive
|
|
4
|
+
// the drag-icon and payload details.
|
|
5
|
+
//
|
|
6
|
+
// Both go through `Controllers` from react-native-gtkx/gtk — the same public
|
|
7
|
+
// door an app would use. Nothing here is reachable only from inside the
|
|
8
|
+
// platform, which is the property `List`/`ListRow` already established
|
|
9
|
+
// (docs/platform-layer.md).
|
|
10
|
+
import { useRef } from "react";
|
|
11
|
+
import { Controllers } from "../gtk/controllers";
|
|
12
|
+
import { Gdk, GObject, Gtk, GtkDragSource, GtkDropTarget, } from "../gtkx/bridge/index";
|
|
13
|
+
import { decodePayload, encodePayload } from "./payload";
|
|
14
|
+
/**
|
|
15
|
+
* A `GtkDragSource` on the enclosing React Native component's widget.
|
|
16
|
+
*
|
|
17
|
+
* The drag icon is a `Gtk.WidgetPaintable` of that widget, offset by where
|
|
18
|
+
* inside it the drag began — so the thing appears to lift off under the
|
|
19
|
+
* cursor rather than jump to it. That is the visual no JS drag can produce,
|
|
20
|
+
* and the reason this module is built on GDK at all.
|
|
21
|
+
*/
|
|
22
|
+
export const DragSourceControllers = ({ payload, onGrab, onDragBegin, onDragEnd, }) => {
|
|
23
|
+
// GDK emits `drag-cancel` AND then `drag-end` for a refused drop, so the
|
|
24
|
+
// cancel is recorded and read by the end handler rather than reported
|
|
25
|
+
// twice.
|
|
26
|
+
const cancelled = useRef(false);
|
|
27
|
+
return (_jsx(Controllers, { children: _jsx(GtkDragSource, { actions: Gdk.DragAction.MOVE, onPrepare: (x, y, self) => {
|
|
28
|
+
const widget = self.getWidget();
|
|
29
|
+
if (widget) {
|
|
30
|
+
self.setIcon(Gtk.WidgetPaintable.new(widget), Math.round(x), Math.round(y));
|
|
31
|
+
}
|
|
32
|
+
onGrab?.(x, y);
|
|
33
|
+
return Gdk.ContentProvider.newForValue(GObject.buildValue(GObject.TYPE_STRING, (value) => value.setString(encodePayload(payload))));
|
|
34
|
+
}, onDragBegin: () => {
|
|
35
|
+
cancelled.current = false;
|
|
36
|
+
onDragBegin?.();
|
|
37
|
+
}, onDragCancel: () => {
|
|
38
|
+
cancelled.current = true;
|
|
39
|
+
// false: let GTK play its own "snap back" animation, which is the
|
|
40
|
+
// platform's way of saying the drop was refused.
|
|
41
|
+
return false;
|
|
42
|
+
}, onDragEnd: () => onDragEnd?.(!cancelled.current) }) }));
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* A `GtkDropTarget` on the enclosing React Native component's widget,
|
|
46
|
+
* accepting the string payload this module encodes.
|
|
47
|
+
*
|
|
48
|
+
* The payload is decoded before `accepts` is consulted, so a string dragged
|
|
49
|
+
* in from a text editor is refused rather than mistaken for a draggable.
|
|
50
|
+
*/
|
|
51
|
+
export const DropTargetControllers = ({ accepts, onDrop, onEnter, onMotion, onLeave, }) => {
|
|
52
|
+
// The payload of the drag currently overhead, sampled on `::enter` and kept
|
|
53
|
+
// for `::motion` (which is not handed the target).
|
|
54
|
+
const hovering = useRef(null);
|
|
55
|
+
return (_jsx(Controllers, { children: _jsx(GtkDropTarget, { actions: Gdk.DragAction.MOVE, types: [GObject.TYPE_STRING],
|
|
56
|
+
// Without this `gtk_drop_target_get_value()` returns NULL until the
|
|
57
|
+
// drop itself, so `::enter` could not tell one drag from another and
|
|
58
|
+
// every zone would light up for every payload. Preloading is exactly
|
|
59
|
+
// the property GTK provides for reading the data during the drag; the
|
|
60
|
+
// cost it warns about (fetching data from another process on hover)
|
|
61
|
+
// does not apply, because the payload is a short string this process
|
|
62
|
+
// wrote.
|
|
63
|
+
preload: true, onEnter: (_x, _y, self) => {
|
|
64
|
+
const payload = payloadOf(self);
|
|
65
|
+
hovering.current = payload;
|
|
66
|
+
// A payload that is not readable yet is NOT refused: refusing in
|
|
67
|
+
// `::enter` ends the drag for this target permanently, while
|
|
68
|
+
// accepting and re-checking at drop time is recoverable. Only a
|
|
69
|
+
// payload we can read AND reject is turned away.
|
|
70
|
+
if (payload && !accepts(payload)) {
|
|
71
|
+
return Gdk.DragAction.NONE;
|
|
72
|
+
}
|
|
73
|
+
if (payload) {
|
|
74
|
+
onEnter?.(payload);
|
|
75
|
+
}
|
|
76
|
+
return Gdk.DragAction.MOVE;
|
|
77
|
+
}, onMotion: (x, y) => {
|
|
78
|
+
const payload = hovering.current;
|
|
79
|
+
if (payload && !accepts(payload)) {
|
|
80
|
+
return Gdk.DragAction.NONE;
|
|
81
|
+
}
|
|
82
|
+
if (payload) {
|
|
83
|
+
onMotion?.(payload, x, y);
|
|
84
|
+
}
|
|
85
|
+
return Gdk.DragAction.MOVE;
|
|
86
|
+
}, onLeave: () => {
|
|
87
|
+
hovering.current = null;
|
|
88
|
+
onLeave?.();
|
|
89
|
+
}, onDrop: (value, x, y) => {
|
|
90
|
+
hovering.current = null;
|
|
91
|
+
const payload = decodePayload(value.getString());
|
|
92
|
+
if (!payload || !accepts(payload)) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
onDrop(payload, x, y);
|
|
96
|
+
return true;
|
|
97
|
+
} }) }));
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* The payload of the drag currently over a drop target, readable during the
|
|
101
|
+
* drag because the target above sets `preload`.
|
|
102
|
+
*/
|
|
103
|
+
const payloadOf = (target) => {
|
|
104
|
+
const value = target.getValue();
|
|
105
|
+
if (!value) {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
return decodePayload(value.getString());
|
|
109
|
+
};
|
|
110
|
+
//# sourceMappingURL=gtk-controllers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gtk-controllers.js","sourceRoot":"","sources":["../../src/dnd/gtk-controllers.tsx"],"names":[],"mappings":";AAAA,2EAA2E;AAC3E,4EAA4E;AAC5E,qCAAqC;AACrC,EAAE;AACF,6EAA6E;AAC7E,wEAAwE;AACxE,uEAAuE;AACvE,4BAA4B;AAC5B,OAAO,EAAE,MAAM,EAAkB,MAAM,OAAO,CAAA;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAChD,OAAO,EACL,GAAG,EACH,OAAO,EACP,GAAG,EACH,aAAa,EACb,aAAa,GACd,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,aAAa,EAAE,aAAa,EAAoB,MAAM,WAAW,CAAA;AAc1E;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,EACpC,OAAO,EACP,MAAM,EACN,WAAW,EACX,SAAS,GACkB,EAAa,EAAE;IAC1C,yEAAyE;IACzE,sEAAsE;IACtE,SAAS;IACT,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,CAAA;IAE/B,OAAO,CACL,KAAC,WAAW,cACV,KAAC,aAAa,IACZ,OAAO,EAAE,GAAG,CAAC,UAAU,CAAC,IAAI,EAC5B,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE;gBACxB,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAA;gBAC/B,IAAI,MAAM,EAAE,CAAC;oBACX,IAAI,CAAC,OAAO,CACV,GAAG,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,EAC/B,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EACb,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CACd,CAAA;gBACH,CAAC;gBACD,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;gBACd,OAAO,GAAG,CAAC,eAAe,CAAC,WAAW,CACpC,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,EAAE,CAChD,KAAK,CAAC,SAAS,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CACxC,CACF,CAAA;YACH,CAAC,EACD,WAAW,EAAE,GAAG,EAAE;gBAChB,SAAS,CAAC,OAAO,GAAG,KAAK,CAAA;gBACzB,WAAW,EAAE,EAAE,CAAA;YACjB,CAAC,EACD,YAAY,EAAE,GAAG,EAAE;gBACjB,SAAS,CAAC,OAAO,GAAG,IAAI,CAAA;gBACxB,kEAAkE;gBAClE,iDAAiD;gBACjD,OAAO,KAAK,CAAA;YACd,CAAC,EACD,SAAS,EAAE,GAAG,EAAE,CAAC,SAAS,EAAE,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,GAChD,GACU,CACf,CAAA;AACH,CAAC,CAAA;AAYD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,EACpC,OAAO,EACP,MAAM,EACN,OAAO,EACP,QAAQ,EACR,OAAO,GACoB,EAAa,EAAE;IAC1C,4EAA4E;IAC5E,mDAAmD;IACnD,MAAM,QAAQ,GAAG,MAAM,CAAqB,IAAI,CAAC,CAAA;IAEjD,OAAO,CACL,KAAC,WAAW,cACV,KAAC,aAAa,IACZ,OAAO,EAAE,GAAG,CAAC,UAAU,CAAC,IAAI,EAC5B,KAAK,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC;YAC5B,oEAAoE;YACpE,qEAAqE;YACrE,qEAAqE;YACrE,sEAAsE;YACtE,oEAAoE;YACpE,qEAAqE;YACrE,SAAS;YACT,OAAO,QACP,OAAO,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;gBACxB,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,CAAA;gBAC/B,QAAQ,CAAC,OAAO,GAAG,OAAO,CAAA;gBAC1B,iEAAiE;gBACjE,6DAA6D;gBAC7D,gEAAgE;gBAChE,iDAAiD;gBACjD,IAAI,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;oBACjC,OAAO,GAAG,CAAC,UAAU,CAAC,IAAI,CAAA;gBAC5B,CAAC;gBACD,IAAI,OAAO,EAAE,CAAC;oBACZ,OAAO,EAAE,CAAC,OAAO,CAAC,CAAA;gBACpB,CAAC;gBACD,OAAO,GAAG,CAAC,UAAU,CAAC,IAAI,CAAA;YAC5B,CAAC,EACD,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;gBACjB,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAA;gBAChC,IAAI,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;oBACjC,OAAO,GAAG,CAAC,UAAU,CAAC,IAAI,CAAA;gBAC5B,CAAC;gBACD,IAAI,OAAO,EAAE,CAAC;oBACZ,QAAQ,EAAE,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;gBAC3B,CAAC;gBACD,OAAO,GAAG,CAAC,UAAU,CAAC,IAAI,CAAA;YAC5B,CAAC,EACD,OAAO,EAAE,GAAG,EAAE;gBACZ,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAA;gBACvB,OAAO,EAAE,EAAE,CAAA;YACb,CAAC,EACD,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;gBACtB,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAA;gBACvB,MAAM,OAAO,GAAG,aAAa,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,CAAA;gBAChD,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;oBAClC,OAAO,KAAK,CAAA;gBACd,CAAC;gBACD,MAAM,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;gBACrB,OAAO,IAAI,CAAA;YACb,CAAC,GACD,GACU,CACf,CAAA;AACH,CAAC,CAAA;AAED;;;GAGG;AACH,MAAM,SAAS,GAAG,CAAC,MAAsB,EAAsB,EAAE;IAC/D,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAA;IAC/B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,IAAI,CAAA;IACb,CAAC;IACD,OAAO,aAAa,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC,CAAA;AACzC,CAAC,CAAA","sourcesContent":["// The two GTK controllers everything in this module is built from, wrapped\n// once so `Draggable`, `Droppable` and `SortableItem` do not each re-derive\n// the drag-icon and payload details.\n//\n// Both go through `Controllers` from react-native-gtkx/gtk — the same public\n// door an app would use. Nothing here is reachable only from inside the\n// platform, which is the property `List`/`ListRow` already established\n// (docs/platform-layer.md).\nimport { useRef, type ReactNode } from \"react\"\nimport { Controllers } from \"../gtk/controllers\"\nimport {\n Gdk,\n GObject,\n Gtk,\n GtkDragSource,\n GtkDropTarget,\n} from \"../gtkx/bridge/index\"\nimport { decodePayload, encodePayload, type DragPayload } from \"./payload\"\n\nexport type DragSourceControllersProps = {\n payload: DragPayload\n /** Reports the grab point in the source widget's own coordinates, which is\n * where the drag icon's hotspot goes and where `tx`/`ty` start from. */\n onGrab?: (x: number, y: number) => void\n onDragBegin?: () => void\n /** `dropped` is what GDK's own `drag-end` reports: whether a target took\n * it. `drag-cancel` reports the negative case separately, so both are\n * folded into one callback here. */\n onDragEnd?: (dropped: boolean) => void\n}\n\n/**\n * A `GtkDragSource` on the enclosing React Native component's widget.\n *\n * The drag icon is a `Gtk.WidgetPaintable` of that widget, offset by where\n * inside it the drag began — so the thing appears to lift off under the\n * cursor rather than jump to it. That is the visual no JS drag can produce,\n * and the reason this module is built on GDK at all.\n */\nexport const DragSourceControllers = ({\n payload,\n onGrab,\n onDragBegin,\n onDragEnd,\n}: DragSourceControllersProps): ReactNode => {\n // GDK emits `drag-cancel` AND then `drag-end` for a refused drop, so the\n // cancel is recorded and read by the end handler rather than reported\n // twice.\n const cancelled = useRef(false)\n\n return (\n <Controllers>\n <GtkDragSource\n actions={Gdk.DragAction.MOVE}\n onPrepare={(x, y, self) => {\n const widget = self.getWidget()\n if (widget) {\n self.setIcon(\n Gtk.WidgetPaintable.new(widget),\n Math.round(x),\n Math.round(y),\n )\n }\n onGrab?.(x, y)\n return Gdk.ContentProvider.newForValue(\n GObject.buildValue(GObject.TYPE_STRING, (value) =>\n value.setString(encodePayload(payload)),\n ),\n )\n }}\n onDragBegin={() => {\n cancelled.current = false\n onDragBegin?.()\n }}\n onDragCancel={() => {\n cancelled.current = true\n // false: let GTK play its own \"snap back\" animation, which is the\n // platform's way of saying the drop was refused.\n return false\n }}\n onDragEnd={() => onDragEnd?.(!cancelled.current)}\n />\n </Controllers>\n )\n}\n\nexport type DropTargetControllersProps = {\n /** Return false to refuse — GDK then shows the no-drop cursor, which is\n * better feedback than upstream's silent skip. */\n accepts: (payload: DragPayload) => boolean\n onDrop: (payload: DragPayload, x: number, y: number) => void\n onEnter?: (payload: DragPayload) => void\n onMotion?: (payload: DragPayload, x: number, y: number) => void\n onLeave?: () => void\n}\n\n/**\n * A `GtkDropTarget` on the enclosing React Native component's widget,\n * accepting the string payload this module encodes.\n *\n * The payload is decoded before `accepts` is consulted, so a string dragged\n * in from a text editor is refused rather than mistaken for a draggable.\n */\nexport const DropTargetControllers = ({\n accepts,\n onDrop,\n onEnter,\n onMotion,\n onLeave,\n}: DropTargetControllersProps): ReactNode => {\n // The payload of the drag currently overhead, sampled on `::enter` and kept\n // for `::motion` (which is not handed the target).\n const hovering = useRef<DragPayload | null>(null)\n\n return (\n <Controllers>\n <GtkDropTarget\n actions={Gdk.DragAction.MOVE}\n types={[GObject.TYPE_STRING]}\n // Without this `gtk_drop_target_get_value()` returns NULL until the\n // drop itself, so `::enter` could not tell one drag from another and\n // every zone would light up for every payload. Preloading is exactly\n // the property GTK provides for reading the data during the drag; the\n // cost it warns about (fetching data from another process on hover)\n // does not apply, because the payload is a short string this process\n // wrote.\n preload\n onEnter={(_x, _y, self) => {\n const payload = payloadOf(self)\n hovering.current = payload\n // A payload that is not readable yet is NOT refused: refusing in\n // `::enter` ends the drag for this target permanently, while\n // accepting and re-checking at drop time is recoverable. Only a\n // payload we can read AND reject is turned away.\n if (payload && !accepts(payload)) {\n return Gdk.DragAction.NONE\n }\n if (payload) {\n onEnter?.(payload)\n }\n return Gdk.DragAction.MOVE\n }}\n onMotion={(x, y) => {\n const payload = hovering.current\n if (payload && !accepts(payload)) {\n return Gdk.DragAction.NONE\n }\n if (payload) {\n onMotion?.(payload, x, y)\n }\n return Gdk.DragAction.MOVE\n }}\n onLeave={() => {\n hovering.current = null\n onLeave?.()\n }}\n onDrop={(value, x, y) => {\n hovering.current = null\n const payload = decodePayload(value.getString())\n if (!payload || !accepts(payload)) {\n return false\n }\n onDrop(payload, x, y)\n return true\n }}\n />\n </Controllers>\n )\n}\n\n/**\n * The payload of the drag currently over a drop target, readable during the\n * drag because the target above sets `preload`.\n */\nconst payloadOf = (target: Gtk.DropTarget): DragPayload | null => {\n const value = target.getValue()\n if (!value) {\n return null\n }\n return decodePayload(value.getString())\n}\n"]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { DropProvider, useDropContext } from "./context";
|
|
2
|
+
export { Draggable, DraggableHandle, useDraggable, type UseDraggableResult, } from "./draggable";
|
|
3
|
+
export { Droppable, useDroppable } from "./droppable";
|
|
4
|
+
export { clamp, listToObject, objectMove } from "./order";
|
|
5
|
+
export { Sortable, SortableItem, useSortable, useSortableList, } from "./sortable";
|
|
6
|
+
export { DraggableState, HorizontalScrollDirection, ScrollDirection, SortableDirection, type AnimationFunction, type CollisionAlgorithm, type DraggableHandleProps, type DraggableProps, type DropAlignment, type DroppableProps, type DroppedItemsMap, type DropOffset, type DropProviderProps, type DropProviderRef, type SharedValueLike, type SortableData, type SortableHandleProps, type SortableItemProps, type SortableProps, type SortableRenderItemProps, type UseDraggableOptions, type UseDraggableReturn, type UseDroppableOptions, type UseDroppableReturn, type UseSortableListOptions, type UseSortableListReturn, type UseSortableOptions, type UseSortableReturn, } from "./types";
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// react-native-gtkx/dnd — `react-native-reanimated-dnd`'s API, on GTK's own
|
|
2
|
+
// drag-and-drop.
|
|
3
|
+
//
|
|
4
|
+
// WHY this is a subpath of its own rather than part of `common` or `gtk`.
|
|
5
|
+
// `common` is Adwaita's LOOK written in portable React Native; this is
|
|
6
|
+
// behaviour, and GTK behaviour at that. `gtk` exists on the premise that the
|
|
7
|
+
// import is the signal an app is crossing into Linux-only code — and this
|
|
8
|
+
// module's premise is the exact opposite: the app's import should not change
|
|
9
|
+
// at all, so the specifier has to be ALIASABLE. `react-native-gtkx/svg` is
|
|
10
|
+
// the precedent, and the Metro and Vite presets rewrite
|
|
11
|
+
// `react-native-reanimated-dnd` onto this the same way they rewrite
|
|
12
|
+
// `react-native-svg`.
|
|
13
|
+
//
|
|
14
|
+
// The library itself cannot run here: Reanimated 4, worklets and RNGH at
|
|
15
|
+
// module scope in twelve of its files, with the sort algorithm inside
|
|
16
|
+
// `useAnimatedReaction` and the row layout inside `useAnimatedStyle`. The
|
|
17
|
+
// evidence, and the prop-by-prop account of what this mirror honours and
|
|
18
|
+
// what it deliberately does not, is in docs/research/drag-and-drop.md.
|
|
19
|
+
export { DropProvider, useDropContext } from "./context";
|
|
20
|
+
export { Draggable, DraggableHandle, useDraggable, } from "./draggable";
|
|
21
|
+
export { Droppable, useDroppable } from "./droppable";
|
|
22
|
+
export { clamp, listToObject, objectMove } from "./order";
|
|
23
|
+
export { Sortable, SortableItem, useSortable, useSortableList, } from "./sortable";
|
|
24
|
+
export { DraggableState, HorizontalScrollDirection, ScrollDirection, SortableDirection, } from "./types";
|
|
25
|
+
// Upstream exports these from `components/sortableUtils`; they are worklet
|
|
26
|
+
// helpers there, plain functions here. `setPosition` and `setAutoScroll`
|
|
27
|
+
// mutate a SharedValue during a UI-thread gesture — there is no gesture on
|
|
28
|
+
// the UI thread here, so they would have nothing to drive and are NOT
|
|
29
|
+
// re-exported. An app that imported them was reaching into upstream's
|
|
30
|
+
// internals; the build failing at that import is the correct outcome.
|
|
31
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/dnd/index.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,iBAAiB;AACjB,EAAE;AACF,0EAA0E;AAC1E,uEAAuE;AACvE,6EAA6E;AAC7E,0EAA0E;AAC1E,6EAA6E;AAC7E,2EAA2E;AAC3E,wDAAwD;AACxD,oEAAoE;AACpE,sBAAsB;AACtB,EAAE;AACF,yEAAyE;AACzE,sEAAsE;AACtE,0EAA0E;AAC1E,yEAAyE;AACzE,uEAAuE;AAEvE,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAExD,OAAO,EACL,SAAS,EACT,eAAe,EACf,YAAY,GASb,MAAM,aAAa,CAAA;AAEpB,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAErD,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AAEzD,OAAO,EACL,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,eAAe,GAChB,MAAM,YAAY,CAAA;AAEnB,OAAO,EACL,cAAc,EACd,yBAAyB,EACzB,eAAe,EACf,iBAAiB,GAyBlB,MAAM,SAAS,CAAA;AAEhB,2EAA2E;AAC3E,yEAAyE;AACzE,2EAA2E;AAC3E,sEAAsE;AACtE,sEAAsE;AACtE,sEAAsE","sourcesContent":["// react-native-gtkx/dnd — `react-native-reanimated-dnd`'s API, on GTK's own\n// drag-and-drop.\n//\n// WHY this is a subpath of its own rather than part of `common` or `gtk`.\n// `common` is Adwaita's LOOK written in portable React Native; this is\n// behaviour, and GTK behaviour at that. `gtk` exists on the premise that the\n// import is the signal an app is crossing into Linux-only code — and this\n// module's premise is the exact opposite: the app's import should not change\n// at all, so the specifier has to be ALIASABLE. `react-native-gtkx/svg` is\n// the precedent, and the Metro and Vite presets rewrite\n// `react-native-reanimated-dnd` onto this the same way they rewrite\n// `react-native-svg`.\n//\n// The library itself cannot run here: Reanimated 4, worklets and RNGH at\n// module scope in twelve of its files, with the sort algorithm inside\n// `useAnimatedReaction` and the row layout inside `useAnimatedStyle`. The\n// evidence, and the prop-by-prop account of what this mirror honours and\n// what it deliberately does not, is in docs/research/drag-and-drop.md.\n\nexport { DropProvider, useDropContext } from \"./context\"\n\nexport {\n Draggable,\n DraggableHandle,\n useDraggable,\n // What `useDraggable` actually returns. `UseDraggableReturn` below is the\n // mirrored half (upstream's field names); this adds the two fields a\n // caller rendering its own view cannot do without — the measurable ref and\n // the drag source itself. Unexported, the hook's own documented use case\n // (\"for a component that owns its own view\") could not be typed by the\n // component that owns it; porting upstream's `CustomDraggable` is what\n // found that.\n type UseDraggableResult,\n} from \"./draggable\"\n\nexport { Droppable, useDroppable } from \"./droppable\"\n\nexport { clamp, listToObject, objectMove } from \"./order\"\n\nexport {\n Sortable,\n SortableItem,\n useSortable,\n useSortableList,\n} from \"./sortable\"\n\nexport {\n DraggableState,\n HorizontalScrollDirection,\n ScrollDirection,\n SortableDirection,\n type AnimationFunction,\n type CollisionAlgorithm,\n type DraggableHandleProps,\n type DraggableProps,\n type DropAlignment,\n type DroppableProps,\n type DroppedItemsMap,\n type DropOffset,\n type DropProviderProps,\n type DropProviderRef,\n type SharedValueLike,\n type SortableData,\n type SortableHandleProps,\n type SortableItemProps,\n type SortableProps,\n type SortableRenderItemProps,\n type UseDraggableOptions,\n type UseDraggableReturn,\n type UseDroppableOptions,\n type UseDroppableReturn,\n type UseSortableListOptions,\n type UseSortableListReturn,\n type UseSortableOptions,\n type UseSortableReturn,\n} from \"./types\"\n\n// Upstream exports these from `components/sortableUtils`; they are worklet\n// helpers there, plain functions here. `setPosition` and `setAutoScroll`\n// mutate a SharedValue during a UI-thread gesture — there is no gesture on\n// the UI thread here, so they would have nothing to drive and are NOT\n// re-exported. An app that imported them was reaching into upstream's\n// internals; the build failing at that import is the correct outcome.\n"]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { SortableData } from "./types";
|
|
2
|
+
/** `["a", "b"]` → `{ a: 0, b: 1 }`. Upstream's takes objects with an `id`;
|
|
3
|
+
* both shapes are accepted so no call site has to convert. */
|
|
4
|
+
export declare const listToObject: (items: readonly (string | SortableData)[]) => Record<string, number>;
|
|
5
|
+
/** Moves the entry at `from` to `to`, returning a new position map. */
|
|
6
|
+
export declare const objectMove: (positions: Record<string, number>, from: number, to: number) => Record<string, number>;
|
|
7
|
+
export declare const clamp: (value: number, lower: number, upper: number) => number;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** `["a", "b"]` → `{ a: 0, b: 1 }`. Upstream's takes objects with an `id`;
|
|
2
|
+
* both shapes are accepted so no call site has to convert. */
|
|
3
|
+
export const listToObject = (items) => {
|
|
4
|
+
const result = {};
|
|
5
|
+
items.forEach((item, index) => {
|
|
6
|
+
result[typeof item === "string" ? item : item.id] = index;
|
|
7
|
+
});
|
|
8
|
+
return result;
|
|
9
|
+
};
|
|
10
|
+
/** Moves the entry at `from` to `to`, returning a new position map. */
|
|
11
|
+
export const objectMove = (positions, from, to) => {
|
|
12
|
+
const ids = Object.keys(positions).sort((a, b) => (positions[a] ?? 0) - (positions[b] ?? 0));
|
|
13
|
+
const [moved] = ids.splice(from, 1);
|
|
14
|
+
if (moved !== undefined) {
|
|
15
|
+
ids.splice(to, 0, moved);
|
|
16
|
+
}
|
|
17
|
+
return listToObject(ids);
|
|
18
|
+
};
|
|
19
|
+
export const clamp = (value, lower, upper) => Math.min(Math.max(value, lower), upper);
|
|
20
|
+
//# sourceMappingURL=order.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"order.js","sourceRoot":"","sources":["../../src/dnd/order.ts"],"names":[],"mappings":"AASA;+DAC+D;AAC/D,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,KAAyC,EACjB,EAAE;IAC1B,MAAM,MAAM,GAA2B,EAAE,CAAA;IACzC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QAC5B,MAAM,CAAC,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,KAAK,CAAA;IAC3D,CAAC,CAAC,CAAA;IACF,OAAO,MAAM,CAAA;AACf,CAAC,CAAA;AAED,uEAAuE;AACvE,MAAM,CAAC,MAAM,UAAU,GAAG,CACxB,SAAiC,EACjC,IAAY,EACZ,EAAU,EACc,EAAE;IAC1B,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CACrC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CACpD,CAAA;IACD,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAA;IACnC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,CAAA;IAC1B,CAAC;IACD,OAAO,YAAY,CAAC,GAAG,CAAC,CAAA;AAC1B,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,KAAa,EAAE,KAAa,EAAE,KAAa,EAAU,EAAE,CAC3E,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,KAAK,CAAC,CAAA","sourcesContent":["// The order arithmetic, kept free of every GTK import.\n//\n// Upstream's equivalents live in `components/sortableUtils` and are worklets;\n// here they are plain functions, and they are in their own module so the unit\n// test project — which has no GTK runtime — can import them. `sortable.tsx`\n// re-exports them, so an app still imports them from the subpath root exactly\n// as it does upstream.\nimport type { SortableData } from \"./types\"\n\n/** `[\"a\", \"b\"]` → `{ a: 0, b: 1 }`. Upstream's takes objects with an `id`;\n * both shapes are accepted so no call site has to convert. */\nexport const listToObject = (\n items: readonly (string | SortableData)[],\n): Record<string, number> => {\n const result: Record<string, number> = {}\n items.forEach((item, index) => {\n result[typeof item === \"string\" ? item : item.id] = index\n })\n return result\n}\n\n/** Moves the entry at `from` to `to`, returning a new position map. */\nexport const objectMove = (\n positions: Record<string, number>,\n from: number,\n to: number,\n): Record<string, number> => {\n const ids = Object.keys(positions).sort(\n (a, b) => (positions[a] ?? 0) - (positions[b] ?? 0),\n )\n const [moved] = ids.splice(from, 1)\n if (moved !== undefined) {\n ids.splice(to, 0, moved)\n }\n return listToObject(ids)\n}\n\nexport const clamp = (value: number, lower: number, upper: number): number =>\n Math.min(Math.max(value, lower), upper)\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Draggables and droppables that are not part of a `Sortable`. */
|
|
2
|
+
export declare const FREE_SCOPE = "free";
|
|
3
|
+
export type DragPayload = {
|
|
4
|
+
scope: string;
|
|
5
|
+
id: string;
|
|
6
|
+
};
|
|
7
|
+
/** `rngtkx-dnd/<scope>/<id>` — the id may itself contain slashes, so only
|
|
8
|
+
* the first two separators are structural. */
|
|
9
|
+
export declare const encodePayload: ({ scope, id }: DragPayload) => string;
|
|
10
|
+
export declare const decodePayload: (raw: string | null) => DragPayload | null;
|
|
11
|
+
/** Upstream generates `draggable-<random>` when no `draggableId` is given.
|
|
12
|
+
* A counter rather than `Math.random()` so two ids can never collide and a
|
|
13
|
+
* test can read them. */
|
|
14
|
+
export declare const nextDraggableId: () => string;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// What actually crosses GDK during a drag.
|
|
2
|
+
//
|
|
3
|
+
// A GdkContentProvider carries a GValue of a negotiated type, not arbitrary
|
|
4
|
+
// JavaScript — so a `Draggable`'s `data` (an object, a closure, anything)
|
|
5
|
+
// cannot travel on the wire. What travels is a STRING that names the drag:
|
|
6
|
+
// the scope it belongs to and the draggable's id. The `data` itself stays in
|
|
7
|
+
// the provider's own registry on the JS side and is looked up on drop.
|
|
8
|
+
//
|
|
9
|
+
// The consequence worth knowing: a drop that arrives from ANOTHER process
|
|
10
|
+
// carries a string this module did not write, so it resolves to no data and
|
|
11
|
+
// is refused. Cross-application drops are a real capability of the layer
|
|
12
|
+
// underneath (see docs/research/drag-and-drop.md) but they are not what the
|
|
13
|
+
// mirrored API describes, so they are not silently mapped onto it.
|
|
14
|
+
/** Prefix, so a string dragged in from a text editor is never mistaken for
|
|
15
|
+
* one of ours. */
|
|
16
|
+
const MARK = "rngtkx-dnd";
|
|
17
|
+
/** Draggables and droppables that are not part of a `Sortable`. */
|
|
18
|
+
export const FREE_SCOPE = "free";
|
|
19
|
+
/** `rngtkx-dnd/<scope>/<id>` — the id may itself contain slashes, so only
|
|
20
|
+
* the first two separators are structural. */
|
|
21
|
+
export const encodePayload = ({ scope, id }) => `${MARK}/${scope}/${id}`;
|
|
22
|
+
export const decodePayload = (raw) => {
|
|
23
|
+
if (!raw) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
const first = raw.indexOf("/");
|
|
27
|
+
if (first === -1 || raw.slice(0, first) !== MARK) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
const second = raw.indexOf("/", first + 1);
|
|
31
|
+
if (second === -1) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
return { scope: raw.slice(first + 1, second), id: raw.slice(second + 1) };
|
|
35
|
+
};
|
|
36
|
+
let counter = 0;
|
|
37
|
+
/** Upstream generates `draggable-<random>` when no `draggableId` is given.
|
|
38
|
+
* A counter rather than `Math.random()` so two ids can never collide and a
|
|
39
|
+
* test can read them. */
|
|
40
|
+
export const nextDraggableId = () => `draggable-${++counter}`;
|
|
41
|
+
//# sourceMappingURL=payload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payload.js","sourceRoot":"","sources":["../../src/dnd/payload.ts"],"names":[],"mappings":"AAAA,2CAA2C;AAC3C,EAAE;AACF,4EAA4E;AAC5E,0EAA0E;AAC1E,2EAA2E;AAC3E,6EAA6E;AAC7E,uEAAuE;AACvE,EAAE;AACF,0EAA0E;AAC1E,4EAA4E;AAC5E,yEAAyE;AACzE,4EAA4E;AAC5E,mEAAmE;AAEnE;mBACmB;AACnB,MAAM,IAAI,GAAG,YAAY,CAAA;AAEzB,mEAAmE;AACnE,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAA;AAIhC;+CAC+C;AAC/C,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,EAAE,KAAK,EAAE,EAAE,EAAe,EAAU,EAAE,CAClE,GAAG,IAAI,IAAI,KAAK,IAAI,EAAE,EAAE,CAAA;AAE1B,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,GAAkB,EAAsB,EAAE;IACtE,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO,IAAI,CAAA;IACb,CAAC;IACD,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;IAC9B,IAAI,KAAK,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC;QACjD,OAAO,IAAI,CAAA;IACb,CAAC;IACD,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,GAAG,CAAC,CAAC,CAAA;IAC1C,IAAI,MAAM,KAAK,CAAC,CAAC,EAAE,CAAC;QAClB,OAAO,IAAI,CAAA;IACb,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAA;AAC3E,CAAC,CAAA;AAED,IAAI,OAAO,GAAG,CAAC,CAAA;AAEf;;0BAE0B;AAC1B,MAAM,CAAC,MAAM,eAAe,GAAG,GAAW,EAAE,CAAC,aAAa,EAAE,OAAO,EAAE,CAAA","sourcesContent":["// What actually crosses GDK during a drag.\n//\n// A GdkContentProvider carries a GValue of a negotiated type, not arbitrary\n// JavaScript — so a `Draggable`'s `data` (an object, a closure, anything)\n// cannot travel on the wire. What travels is a STRING that names the drag:\n// the scope it belongs to and the draggable's id. The `data` itself stays in\n// the provider's own registry on the JS side and is looked up on drop.\n//\n// The consequence worth knowing: a drop that arrives from ANOTHER process\n// carries a string this module did not write, so it resolves to no data and\n// is refused. Cross-application drops are a real capability of the layer\n// underneath (see docs/research/drag-and-drop.md) but they are not what the\n// mirrored API describes, so they are not silently mapped onto it.\n\n/** Prefix, so a string dragged in from a text editor is never mistaken for\n * one of ours. */\nconst MARK = \"rngtkx-dnd\"\n\n/** Draggables and droppables that are not part of a `Sortable`. */\nexport const FREE_SCOPE = \"free\"\n\nexport type DragPayload = { scope: string; id: string }\n\n/** `rngtkx-dnd/<scope>/<id>` — the id may itself contain slashes, so only\n * the first two separators are structural. */\nexport const encodePayload = ({ scope, id }: DragPayload): string =>\n `${MARK}/${scope}/${id}`\n\nexport const decodePayload = (raw: string | null): DragPayload | null => {\n if (!raw) {\n return null\n }\n const first = raw.indexOf(\"/\")\n if (first === -1 || raw.slice(0, first) !== MARK) {\n return null\n }\n const second = raw.indexOf(\"/\", first + 1)\n if (second === -1) {\n return null\n }\n return { scope: raw.slice(first + 1, second), id: raw.slice(second + 1) }\n}\n\nlet counter = 0\n\n/** Upstream generates `draggable-<random>` when no `draggableId` is given.\n * A counter rather than `Math.random()` so two ids can never collide and a\n * test can read them. */\nexport const nextDraggableId = (): string => `draggable-${++counter}`\n"]}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import { type SortableData, type SortableItemProps, type SortableProps, type UseSortableListOptions, type UseSortableListReturn, type UseSortableOptions, type UseSortableReturn } from "./types";
|
|
3
|
+
export { clamp, listToObject, objectMove } from "./order";
|
|
4
|
+
/**
|
|
5
|
+
* Owns the order of a sortable list, for an app rendering its own container.
|
|
6
|
+
*
|
|
7
|
+
* **The order half only.** Upstream's rows get their drag wiring through the
|
|
8
|
+
* props `getItemProps` hands them; here it travels in context, which only
|
|
9
|
+
* `Sortable` provides — so rows still have to be inside a `Sortable`, and a
|
|
10
|
+
* `SortableItem` outside one throws rather than quietly not dragging. This
|
|
11
|
+
* hook is for reading the order and the `SharedValueLike` boxes, which is
|
|
12
|
+
* what most callers of it actually want.
|
|
13
|
+
*/
|
|
14
|
+
export declare const useSortableList: <TData extends SortableData>(options: UseSortableListOptions<TData>) => UseSortableListReturn<TData>;
|
|
15
|
+
/**
|
|
16
|
+
* A list whose rows reorder by dragging.
|
|
17
|
+
*
|
|
18
|
+
* ```tsx
|
|
19
|
+
* <Sortable
|
|
20
|
+
* data={tasks}
|
|
21
|
+
* onDrop={(id, position, all) => save(all)}
|
|
22
|
+
* renderItem={({ item, id, ...rest }) => (
|
|
23
|
+
* <SortableItem key={id} id={id} data={item} {...rest}>
|
|
24
|
+
* <View style={styles.row}>
|
|
25
|
+
* <Text>{item.title}</Text>
|
|
26
|
+
* <SortableItem.Handle>
|
|
27
|
+
* <Text>⠿</Text>
|
|
28
|
+
* </SortableItem.Handle>
|
|
29
|
+
* </View>
|
|
30
|
+
* </SortableItem>
|
|
31
|
+
* )}
|
|
32
|
+
* />
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* The rows carry a real GTK drag icon — a picture of the row itself, lifted
|
|
36
|
+
* at the point it was grabbed — and the list rearranges live underneath it.
|
|
37
|
+
*/
|
|
38
|
+
export declare const Sortable: <TData extends SortableData>({ data, renderItem, itemKeyExtractor, style, contentContainerStyle, testID, direction, onMove, onDragStart, onDrop, onDragging, }: SortableProps<TData>) => ReactNode;
|
|
39
|
+
/**
|
|
40
|
+
* The reorder half of the module, as a hook, for a row that owns its own
|
|
41
|
+
* view. Render `children` inside that view.
|
|
42
|
+
*/
|
|
43
|
+
export declare const useSortable: <TData>(options: UseSortableOptions<TData>) => UseSortableReturn;
|
|
44
|
+
/** One row of a {@link Sortable}. Both a drag source and a drop target: the
|
|
45
|
+
* row you drag onto is the position the dragged row takes. */
|
|
46
|
+
export declare const SortableItem: {
|
|
47
|
+
<TData>({ id, data, children, style, animatedStyle, testID, onMove, onDragStart, onDrop, onDragging, }: SortableItemProps<TData>): ReactNode;
|
|
48
|
+
Handle: ({ children, style, testID, }: import("./types").DraggableHandleProps) => ReactNode;
|
|
49
|
+
};
|