Skip to content

packages/core/src/lib/manipulation/manipulable.ts

Read as Markdown

This is the source snapshot used to build these API details. View this revision on GitHub.

Back to reference

1 import { createElement } from "../element/create-element.js";
2 import type { PibblNode } from "../element/types.js";
3 import type { WritableSignal } from "../signals/types.js";
4 import { useManipulation } from "./controller.js";
5 import type {
6   PibblManipulationOptions,
7   PibblManipulationMoveInput,
8   PibblManipulationResizeInput,
9   PibblManipulationRotateInput,
10 } from "./controller-types.js";
11 import { ManipulationFrame } from "./frame.js";
12 import { DragHandle, ResizeHandles, RotationHandle } from "./handles.js";
13 import type {
14   PibblResizeHandlesProps,
15   PibblDragHandleProps,
16   PibblDragHandleStyle,
17   PibblRotationHandleProps,
18   PibblRotationHandleStyle,
19 } from "./handles.js";
20 import type { PibblManipulationBox } from "./types.js";
21 
22 /**
23  * Authored inputs for Manipulable, including the declared data and presentation options.
24  *
25  * @see {@link PibblManipulationOptions}
26  * @see {@link WritableSignal}
27  * @see {@link PibblManipulationBox}
28  * @see {@link PibblManipulationMoveInput}
29  * @see {@link PibblManipulationResizeInput}
30  * @see {@link PibblManipulationRotateInput}
31  * @see {@link PibblResizeHandlesProps}
32  * @see {@link PibblRotationHandleProps}
33  * @see {@link PibblRotationHandleStyle}
34  * @see {@link PibblDragHandleProps}
35  * @see {@link PibblDragHandleStyle}
36  * @see {@link PibblNode}
37  * @see {@link Manipulable}
38  */
39 export interface PibblManipulableProps extends Pick<
40   PibblManipulationOptions,
41   "rotation" | "onStart" | "onChange" | "onCommit" | "onCancel"
42 > {
43   /**
44    * Declared presentation and layout properties. See {@link WritableSignal},
45    * {@link PibblManipulationBox}.
46    */
47   readonly style: WritableSignal<PibblManipulationBox>;
48   /** Enables or configures translation of the target. See {@link PibblManipulationMoveInput}. */
49   readonly draggable?: boolean | PibblManipulationMoveInput;
50   /** Enables or configures resizing of the target. See {@link PibblManipulationResizeInput}. */
51   readonly resizable?: boolean | PibblManipulationResizeInput;
52   /** Enables or configures rotation of the target. See {@link PibblManipulationRotateInput}. */
53   readonly rotatable?: boolean | PibblManipulationRotateInput;
54   /** Configuration of the target's resize handles. See {@link PibblResizeHandlesProps}. */
55   readonly resizeHandles?:
56     PibblResizeHandlesProps["positions"] | Omit<PibblResizeHandlesProps, "controller">;
57   /**
58    * Configuration of the target's rotation handle. See {@link PibblRotationHandleProps},
59    * {@link PibblRotationHandleStyle}.
60    */
61   readonly rotationHandle?: Omit<PibblRotationHandleProps, "controller" | "children"> & {
62     /** Declared presentation and layout properties. See {@link PibblRotationHandleStyle}. */
63     readonly style?: PibblRotationHandleStyle;
64   };
65   /**
66    * Configuration of the target's drag handle. See {@link PibblDragHandleProps},
67    * {@link PibblDragHandleStyle}.
68    */
69   readonly dragHandle?: Omit<PibblDragHandleProps, "controller" | "children"> & {
70     /** Declared presentation and layout properties. See {@link PibblDragHandleStyle}. */
71     readonly style?: PibblDragHandleStyle;
72   };
73   /** Descendant content or the callback that supplies it. See {@link PibblNode}. */
74   readonly children?: PibblNode;
75 }
76 function operation<T>(value: boolean | T | undefined): T | undefined {
77   return value === undefined || value === false
78     ? undefined
79     : value === true
80       ? ({} as T)
81       : value;
82 }
83 /**
84  * Compose the same signal-owned frame and handles used by useManipulation.
85  *
86  * @param props - Manipulation controller and child content. See {@link PibblManipulableProps}.
87  * @returns Child content with manipulation interaction applied. See {@link PibblNode}.
88  *
89  * @see {@link PibblManipulableProps}
90  * @see {@link PibblNode}
91  */
92 export function Manipulable(props: PibblManipulableProps): PibblNode {
93   const controller = useManipulation({
94     box: props.style,
95     rotation: props.rotation,
96     move: operation(props.draggable),
97     resize: operation(props.resizable),
98     rotate: operation(props.rotatable),
99     onStart: props.onStart,
100     onChange: props.onChange,
101     onCommit: props.onCommit,
102     onCancel: props.onCancel,
103   });
104   const resizeHandles =
105     Array.isArray(props.resizeHandles) ||
106     props.resizeHandles === "corners" ||
107     props.resizeHandles === "edges-and-corners"
108       ? { positions: props.resizeHandles }
109       : props.resizeHandles;
110   return createElement(ManipulationFrame, {
111     ...controller.frameProps,
112     children: [
113       createElement(DragHandle, {
114         key: "content",
115         controller,
116         ...props.dragHandle,
117         style: { width: "100%", height: "100%", ...props.dragHandle?.style },
118         children: props.children,
119       }),
120       props.resizable &&
121         createElement(ResizeHandles, {
122           key: "resize",
123           controller,
124           ...resizeHandles,
125         }),
126       props.rotatable &&
127         createElement(RotationHandle, {
128           key: "rotate",
129           controller,
130           ...props.rotationHandle,
131         }),
132     ],
133   });
134 }
135 

Documentation built with @pibbl/core 0.0.2, revision 2dccb19. ALPHA — NOT FOR PRODUCTION USE.