publ-echo 0.0.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.
Files changed (57) hide show
  1. package/README.md +29 -0
  2. package/bin/cli.js +8 -0
  3. package/bitbucket-pipelines.yml +35 -0
  4. package/package.json +51 -0
  5. package/public/favicon.ico +0 -0
  6. package/public/index.html +43 -0
  7. package/public/logo192.png +0 -0
  8. package/public/logo512.png +0 -0
  9. package/public/manifest.json +25 -0
  10. package/public/robots.txt +3 -0
  11. package/src/App.tsx +28 -0
  12. package/src/examples/ReactGridLayout/ReactGridLayoutShowcase01.tsx +80 -0
  13. package/src/examples/ReactGridLayout/index.ts +1 -0
  14. package/src/examples/ResponsiveGridLayout/ResponsiveGridLayoutShowcase01.tsx +114 -0
  15. package/src/examples/ResponsiveGridLayout/index.ts +1 -0
  16. package/src/examples/index.ts +2 -0
  17. package/src/examples/utils.ts +15 -0
  18. package/src/index.tsx +21 -0
  19. package/src/lib/Draggable/Draggable.tsx +303 -0
  20. package/src/lib/Draggable/DraggableCore.tsx +352 -0
  21. package/src/lib/Draggable/constants.ts +12 -0
  22. package/src/lib/Draggable/index.ts +2 -0
  23. package/src/lib/Draggable/types.ts +74 -0
  24. package/src/lib/Draggable/utils/domHelpers.ts +284 -0
  25. package/src/lib/Draggable/utils/getPrefix.ts +42 -0
  26. package/src/lib/Draggable/utils/positionHelpers.ts +49 -0
  27. package/src/lib/Draggable/utils/types.ts +41 -0
  28. package/src/lib/Draggable/utils/validationHelpers.ts +23 -0
  29. package/src/lib/GridItem/GridItem.tsx +493 -0
  30. package/src/lib/GridItem/index.ts +1 -0
  31. package/src/lib/GridItem/types.ts +121 -0
  32. package/src/lib/GridItem/utils/calculateUtils.ts +173 -0
  33. package/src/lib/GridLayoutEditor/ReactGridLayout.tsx +662 -0
  34. package/src/lib/GridLayoutEditor/ResponsiveGridLayout.tsx +204 -0
  35. package/src/lib/GridLayoutEditor/index.ts +9 -0
  36. package/src/lib/GridLayoutEditor/styles/styles.css +133 -0
  37. package/src/lib/GridLayoutEditor/types.ts +199 -0
  38. package/src/lib/GridLayoutEditor/utils/renderHelpers.ts +737 -0
  39. package/src/lib/GridLayoutEditor/utils/responsiveUtils.ts +111 -0
  40. package/src/lib/PreviewGLE/ReactGridLayoutPreview.tsx +46 -0
  41. package/src/lib/PreviewGLE/ResponsiveGridLayoutPreview.tsx +54 -0
  42. package/src/lib/PreviewGLE/index.ts +2 -0
  43. package/src/lib/Resizable/Resizable.tsx +323 -0
  44. package/src/lib/Resizable/ResizableBox.tsx +109 -0
  45. package/src/lib/Resizable/index.ts +1 -0
  46. package/src/lib/Resizable/styles/styles.css +76 -0
  47. package/src/lib/Resizable/types.ts +96 -0
  48. package/src/lib/Resizable/utils/cloneElement.ts +15 -0
  49. package/src/lib/components/WidthProvider.tsx +71 -0
  50. package/src/lib/components/index.ts +1 -0
  51. package/src/lib/components/types.ts +19 -0
  52. package/src/lib/index.ts +4 -0
  53. package/src/react-app-env.d.ts +1 -0
  54. package/src/reportWebVitals.ts +15 -0
  55. package/src/setupTests.ts +5 -0
  56. package/src/utils/types.ts +3 -0
  57. package/tsconfig.json +26 -0
@@ -0,0 +1,74 @@
1
+ import { ReactElement, RefObject } from "react";
2
+ import {
3
+ ControlPosition,
4
+ DraggableEventHandler,
5
+ PositionOffsetControlPosition,
6
+ } from "./utils/types";
7
+
8
+ // draggableCore
9
+ export type DraggableCoreState = {
10
+ dragging: boolean;
11
+ lastX: number;
12
+ lastY: number;
13
+ touchIdentifier?: number | null;
14
+ };
15
+
16
+ export type DraggableData = {
17
+ node: HTMLElement;
18
+ x: number;
19
+ y: number;
20
+ deltaX: number;
21
+ deltaY: number;
22
+ lastX: number;
23
+ lastY: number;
24
+ };
25
+
26
+ export type DraggableCoreDefaultProps = {
27
+ allowAnyClick?: boolean;
28
+ disabled?: boolean;
29
+ enableUserSelectHack?: boolean;
30
+ onStart?: DraggableEventHandler | Function;
31
+ onDrag?: DraggableEventHandler | Function;
32
+ onStop?: DraggableEventHandler | Function;
33
+ onMouseDown?: (e: MouseEvent) => void;
34
+ scale?: number;
35
+ cancel?: string;
36
+ children: ReactElement<any>;
37
+ offsetParent?: HTMLElement;
38
+ grid?: [number, number];
39
+ handle?: string;
40
+ nodeRef?: RefObject<HTMLElement>;
41
+ className?: string;
42
+ style?: Object;
43
+ };
44
+
45
+ // draggable type
46
+ export type DraggableState = {
47
+ dragging: boolean;
48
+ dragged: boolean;
49
+ x: number;
50
+ y: number;
51
+ slackX: number;
52
+ slackY: number;
53
+ isElementSVG: boolean;
54
+ prevPropsPosition?: ControlPosition;
55
+ };
56
+
57
+ export type DraggablePositionType = {
58
+ positionOffset?: PositionOffsetControlPosition;
59
+ position?: ControlPosition;
60
+ };
61
+
62
+ export type DraggableProps = DraggablePositionType & DraggableCoreDefaultProps;
63
+
64
+ export type PropsWithChildren<P> = P & {
65
+ children: ReactElement<any>;
66
+ };
67
+
68
+ export type AxisType = "both" | "x" | "y" | "none";
69
+
70
+ export type DraggableEvent =
71
+ | React.MouseEvent<HTMLElement | SVGElement>
72
+ | React.TouchEvent<HTMLElement | SVGElement>
73
+ | MouseEvent
74
+ | TouchEvent;
@@ -0,0 +1,284 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-vars */
2
+ import browserPrefix, { browserPrefixToKey } from "./getPrefix";
3
+ import type {
4
+ ControlPosition,
5
+ PositionOffsetControlPosition,
6
+ MouseTouchEvent,
7
+ EventWithOffset,
8
+ EventHandler,
9
+ } from "./types";
10
+ import { findInArray, int, isFunction } from "./validationHelpers";
11
+
12
+ export const matchSelector = (el: Node, selector: string): boolean => {
13
+ let matchedSelector = "";
14
+ const selectors = [
15
+ "matches",
16
+ "webkitMatchesSelector",
17
+ // "mozMatchesSelector",
18
+ // "msMatchesSelector",
19
+ // "oMatchesSelector",
20
+ ];
21
+ const callback = (method: keyof Element) => {
22
+ return isFunction((el as Element)[method]);
23
+ };
24
+
25
+ if (!matchedSelector) {
26
+ matchedSelector = findInArray(selectors, callback);
27
+
28
+ if (
29
+ matchedSelector === "matches" ||
30
+ matchedSelector === "webkitMatchesSelector"
31
+ ) {
32
+ return (el as Element)[matchedSelector](selector);
33
+ }
34
+ }
35
+
36
+ return false;
37
+ };
38
+
39
+ export const matchSelectorAndParentsTo = (
40
+ el: Node,
41
+ selector: string,
42
+ baseNode: Node
43
+ ): boolean => {
44
+ let node = el;
45
+
46
+ do {
47
+ if (matchSelector(node, selector)) return true;
48
+ if (node === baseNode) return false;
49
+ if (node.parentNode) node = node.parentNode;
50
+ } while (node);
51
+
52
+ return false;
53
+ };
54
+
55
+ export const addEvent = (
56
+ el: Node,
57
+ eventType: string,
58
+ handler: EventHandler<any>,
59
+ inputOptions?: Object
60
+ ): void => {
61
+ if (!el) return;
62
+
63
+ const options = { capture: true, ...inputOptions };
64
+
65
+ if (el.addEventListener) {
66
+ el.addEventListener(eventType, handler, options);
67
+ }
68
+ // if (el.addEventListener) {
69
+ // el.addEventListener(eventType, handler, options);
70
+ // } else {
71
+ // (el as { [key: string]: any })['on' + eventType] = handler;
72
+ // }
73
+ };
74
+
75
+ export const removeEvent = (
76
+ el: Node,
77
+ eventType: string,
78
+ handler: EventHandler<any>,
79
+ inputOptions?: Object
80
+ ): void => {
81
+ if (!el) return;
82
+
83
+ const options = { capture: true, ...inputOptions };
84
+
85
+ if (el.removeEventListener) {
86
+ el.removeEventListener(eventType, handler, options);
87
+ }
88
+ // if (el.removeEventListener) {
89
+ // el.removeEventListener(eventType, handler, options);
90
+ // } else {
91
+ // (el as { [key: string]: any })['on' + eventType] = null;
92
+ // }
93
+ };
94
+
95
+ export const outerHeight = (node: HTMLElement): number => {
96
+ let height = node.clientHeight;
97
+ const computedStyle = node.ownerDocument.defaultView?.getComputedStyle(node);
98
+
99
+ if (computedStyle) {
100
+ height += int(computedStyle.borderTopWidth);
101
+ height += int(computedStyle.borderBottomWidth);
102
+ return height;
103
+ } else {
104
+ return height;
105
+ }
106
+ };
107
+
108
+ export const outerWidth = (node: HTMLElement): number => {
109
+ let width = node.clientWidth;
110
+ const computedStyle = node.ownerDocument.defaultView?.getComputedStyle(node);
111
+
112
+ if (computedStyle) {
113
+ width += int(computedStyle.borderLeftWidth);
114
+ width += int(computedStyle.borderRightWidth);
115
+ return width;
116
+ } else {
117
+ return width;
118
+ }
119
+ };
120
+ export const innerHeight = (node: HTMLElement): number => {
121
+ let height = node.clientHeight;
122
+ const computedStyle = node.ownerDocument.defaultView?.getComputedStyle(node);
123
+
124
+ if (computedStyle) {
125
+ height -= int(computedStyle.paddingTop);
126
+ height -= int(computedStyle.paddingBottom);
127
+ return height;
128
+ } else {
129
+ return height;
130
+ }
131
+ };
132
+
133
+ export const innerWidth = (node: HTMLElement): number => {
134
+ let width = node.clientWidth;
135
+
136
+ const computedStyle = node.ownerDocument.defaultView?.getComputedStyle(node);
137
+
138
+ if (computedStyle) {
139
+ width -= int(computedStyle.paddingLeft);
140
+ width -= int(computedStyle.paddingRight);
141
+
142
+ return width;
143
+ } else {
144
+ return width;
145
+ }
146
+ };
147
+
148
+ export const offsetXYFromParent = (
149
+ evt: EventWithOffset,
150
+ offsetParent: Element,
151
+ scale: number
152
+ ): ControlPosition => {
153
+ const isBody = offsetParent.ownerDocument.body;
154
+ const offsetParentRect = isBody
155
+ ? { left: 0, top: 0 }
156
+ : offsetParent.getBoundingClientRect();
157
+
158
+ const x =
159
+ (evt.clientX + offsetParent.scrollLeft - offsetParentRect.left) / scale;
160
+ const y =
161
+ (evt.clientY + offsetParent.scrollTop - offsetParentRect.top) / scale;
162
+
163
+ return { x, y };
164
+ };
165
+
166
+ export const createCSSTransform = (
167
+ controlPos: ControlPosition,
168
+ positionOffset?: PositionOffsetControlPosition
169
+ ): Object => {
170
+ const translation = getTranslation(controlPos, "px", positionOffset);
171
+ return { [browserPrefixToKey("transform", browserPrefix)]: translation };
172
+ };
173
+
174
+ export const createSVGTransform = (
175
+ controlPos: ControlPosition,
176
+ positionOffset?: PositionOffsetControlPosition
177
+ ): string => {
178
+ const translation = getTranslation(controlPos, "", positionOffset);
179
+
180
+ return translation;
181
+ };
182
+
183
+ export const getTranslation = (
184
+ { x, y }: ControlPosition,
185
+ unitSuffix: string,
186
+ positionOffset?: PositionOffsetControlPosition
187
+ ): string => {
188
+ let translation = `translate(${x}${unitSuffix},${y}${unitSuffix})`;
189
+
190
+ if (positionOffset) {
191
+ const defaultX = `${
192
+ typeof positionOffset.x === "string"
193
+ ? positionOffset.x
194
+ : positionOffset.x + unitSuffix
195
+ }`;
196
+ const defaultY = `${
197
+ typeof positionOffset.y === "string"
198
+ ? positionOffset.y
199
+ : positionOffset.y + unitSuffix
200
+ }`;
201
+
202
+ translation = `translate(${defaultX}, ${defaultY})` + translation;
203
+ }
204
+
205
+ return translation;
206
+ };
207
+
208
+ export const getTouch = (
209
+ e: MouseTouchEvent,
210
+ identifier: number
211
+ ): { clientX: number; clientY: number } => {
212
+ return (
213
+ (e.targetTouches &&
214
+ findInArray(e.targetTouches, (t: any) => identifier === t.identifier)) ||
215
+ (e.changedTouches &&
216
+ findInArray(e.changedTouches, (t: any) => identifier === t.identifier))
217
+ );
218
+ };
219
+
220
+ export const getTouchIdentifier = (e: MouseTouchEvent): number | undefined => {
221
+ if (e.targetTouches && e.targetTouches[0]) {
222
+ return e.targetTouches[0].identifier;
223
+ }
224
+
225
+ if (e.changedTouches && e.changedTouches[0]) {
226
+ return e.changedTouches[0].identifier;
227
+ }
228
+ };
229
+
230
+ export const addUserSelectStyles = (doc?: Document) => {
231
+ if (!doc) return;
232
+
233
+ let styleEl = doc.getElementById("react-draggable-style-el");
234
+
235
+ if (!styleEl) {
236
+ styleEl = doc.createElement("style");
237
+ styleEl.id = "react-draggable-style-el";
238
+ styleEl.innerHTML =
239
+ ".react-draggable-transparent-selection *::-moz-selection {all: inherit;}\n";
240
+ styleEl.innerHTML +=
241
+ ".react-draggable-transparent-selection *::selection {all: inherit;}\n";
242
+ doc.getElementsByTagName("head")[0].appendChild(styleEl);
243
+ }
244
+
245
+ if (doc.body) addClassName(doc.body, "react-draggable-transparent-selection");
246
+ };
247
+
248
+ export const removeUserSelectStyles = (doc?: Document) => {
249
+ if (!doc) return;
250
+
251
+ if (doc.body) {
252
+ removeClassName(doc.body, "react-draggable-transparent-selection");
253
+ }
254
+
255
+ if (doc.getSelection()) {
256
+ doc.getSelection()?.empty();
257
+ } else {
258
+ const selection = (doc.defaultView || window).getSelection();
259
+ if (selection && selection.type !== "Caret") {
260
+ selection.removeAllRanges();
261
+ }
262
+ }
263
+ };
264
+
265
+ export const addClassName = (el: HTMLElement, className: string) => {
266
+ if (el.classList) {
267
+ el.classList.add(className);
268
+ } else {
269
+ if (!el.className.match(new RegExp(`(?:^|\\s)${className}(?!\\S)`))) {
270
+ el.className += ` ${className}`;
271
+ }
272
+ }
273
+ };
274
+
275
+ export const removeClassName = (el: HTMLElement, className: string) => {
276
+ if (el.classList) {
277
+ el.classList.remove(className);
278
+ } else {
279
+ el.className = el.className.replace(
280
+ new RegExp(`(?:^|\\s)${className}(?!\\S)`, "g"),
281
+ ""
282
+ );
283
+ }
284
+ };
@@ -0,0 +1,42 @@
1
+ const prefixes = ["Moz", "Webkit", "O", "ms"];
2
+
3
+ export function getPrefix(prop: string = "transform"): string {
4
+ if (typeof window === "undefined") return "";
5
+
6
+ const style = window.document?.documentElement?.style;
7
+ if (!style) return "";
8
+
9
+ if (prop in style) return "";
10
+
11
+ for (let i = 0; i < prefixes.length; i++) {
12
+ if (browserPrefixToKey(prop, prefixes[i]) in style) return prefixes[i];
13
+ }
14
+
15
+ return "";
16
+ }
17
+
18
+ export function browserPrefixToKey(prop: string, prefix: string): string {
19
+ return prefix ? `${prefix}${kebabToTitleCase(prop)}` : prop;
20
+ }
21
+
22
+ export function browserPrefixToStyle(prop: string, prefix: string): string {
23
+ return prefix ? `-${prefix.toLowerCase()}-${prop}` : prop;
24
+ }
25
+
26
+ function kebabToTitleCase(str: string): string {
27
+ let out = "";
28
+ let shouldCapitalize = true;
29
+ for (let i = 0; i < str.length; i++) {
30
+ if (shouldCapitalize) {
31
+ out += str[i].toUpperCase();
32
+ shouldCapitalize = false;
33
+ } else if (str[i] === "-") {
34
+ shouldCapitalize = true;
35
+ } else {
36
+ out += str[i];
37
+ }
38
+ }
39
+ return out;
40
+ }
41
+
42
+ export default getPrefix();
@@ -0,0 +1,49 @@
1
+ import { AxisType, DraggableData, DraggableState } from "./../types";
2
+ import type { Bounds } from "./types";
3
+
4
+ export function snapToGrid(
5
+ grid: [number, number],
6
+ pendingX: number,
7
+ pendingY: number
8
+ ): [number, number] {
9
+ const x = Math.round(pendingX / grid[0]) * grid[0];
10
+ const y = Math.round(pendingY / grid[1]) * grid[1];
11
+
12
+ return [x, y];
13
+ }
14
+
15
+ export function canDragX(axis: AxisType): boolean {
16
+ return axis === "both" || axis === "x";
17
+ }
18
+
19
+ export function canDragY(axis: AxisType): boolean {
20
+ return axis === "both" || axis === "y";
21
+ }
22
+
23
+ export const cloneBounds = (bounds: Bounds): Bounds => {
24
+ return {
25
+ left: bounds.left,
26
+ top: bounds.top,
27
+ right: bounds.right,
28
+ bottom: bounds.bottom,
29
+ };
30
+ };
31
+
32
+ export const createDraggableData = (
33
+ draggableState: DraggableState,
34
+ scale: number,
35
+ coreData: DraggableData
36
+ ): DraggableData => {
37
+ const deltaX = coreData.deltaX / scale;
38
+ const deltaY = coreData.deltaY / scale;
39
+
40
+ return {
41
+ node: coreData.node,
42
+ x: draggableState.x + deltaX,
43
+ y: draggableState.y + deltaY,
44
+ deltaX,
45
+ deltaY,
46
+ lastX: draggableState.x,
47
+ lastY: draggableState.y,
48
+ };
49
+ };
@@ -0,0 +1,41 @@
1
+ import { DraggableData } from "../types";
2
+
3
+ export type DraggableEvent =
4
+ | React.MouseEvent<HTMLElement | SVGElement>
5
+ | React.TouchEvent<HTMLElement | SVGElement>
6
+ | MouseEvent
7
+ | TouchEvent;
8
+
9
+ export type DraggableEventHandler = (
10
+ e: MouseEvent,
11
+ data: DraggableData,
12
+ el?: HTMLElement | null
13
+ ) => void | false;
14
+
15
+ export type Bounds = {
16
+ left: number;
17
+ top: number;
18
+ right: number;
19
+ bottom: number;
20
+ };
21
+
22
+ export type ControlPosition = { x: number; y: number };
23
+ export type PositionOffsetControlPosition = {
24
+ x: number | string;
25
+ y: number | string;
26
+ };
27
+ export type EventHandler<T> = (e: T) => void | false;
28
+
29
+ export interface SVGElement extends HTMLElement {}
30
+
31
+ export interface TouchEvent2 extends TouchEvent {
32
+ changedTouches: TouchList;
33
+ targetTouches: TouchList;
34
+ }
35
+
36
+ export type MouseTouchEvent = MouseEvent & TouchEvent2;
37
+
38
+ export type EventWithOffset = {
39
+ clientX: number;
40
+ clientY: number;
41
+ };
@@ -0,0 +1,23 @@
1
+ export const findInArray = (
2
+ array: Array<any> | TouchList,
3
+ callback: Function
4
+ ): any => {
5
+ for (let i = 0, length = array.length; i < length; i++) {
6
+ if (callback.apply(callback, [array[i], i, array])) return array[i];
7
+ }
8
+ };
9
+
10
+ export const isFunction = (func: any): boolean => {
11
+ return (
12
+ typeof func === "function" ||
13
+ Object.prototype.toString.call(func) === "[object Function]"
14
+ );
15
+ };
16
+
17
+ export const isNum = (num: any): boolean => {
18
+ return typeof num === "number" && !isNaN(num);
19
+ };
20
+
21
+ export const int = (a: string): number => {
22
+ return parseInt(a, 10);
23
+ };