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,204 @@
1
+ import { useEffect, useRef, useState } from "react";
2
+ import {
3
+ Breakpoint,
4
+ Breakpoints,
5
+ Layout,
6
+ ResponsiveGridLayoutProps,
7
+ ResponsiveGridLayoutStateType,
8
+ } from "./types";
9
+ import {
10
+ cloneLayout,
11
+ noop,
12
+ synchronizeLayoutWithChildren,
13
+ } from "./utils/renderHelpers";
14
+ import {
15
+ findOrGenerateResponsiveLayout,
16
+ getBreakpointFromWidth,
17
+ getColsFromBreakpoint,
18
+ } from "./utils/responsiveUtils";
19
+ import { isEqual } from "lodash";
20
+ import { PropsWithChildren } from "../../utils/types";
21
+ import ReactGridLayout from "./ReactGridLayout";
22
+
23
+ /**
24
+ * Get a value of margin or containerPadding.
25
+ *
26
+ * @param {Array | Object} param Margin | containerPadding, e.g. [10, 10] | {lg: [10, 10], ...}.
27
+ * @param {String} breakpoint Breakpoint: lg, md, sm, xs and etc.
28
+ * @return {Array}
29
+ */
30
+ function getIndentationValue<T extends [number, number]>(
31
+ param: Record<string, T> | T,
32
+ breakpoint: Breakpoint
33
+ ): T {
34
+ return Array.isArray(param) ? param : param[breakpoint];
35
+ }
36
+
37
+ export const ResponsiveGridLayout = ({
38
+ children,
39
+ ...props
40
+ }: PropsWithChildren<ResponsiveGridLayoutProps>) => {
41
+ const {
42
+ breakpoint,
43
+ compactType,
44
+ breakpoints = { lg: 1200, md: 996, sm: 768, xs: 480, xxs: 0 },
45
+ cols = { lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 },
46
+ containerPadding = {},
47
+ layouts = {},
48
+ width = 0,
49
+ margin = [10, 10],
50
+ onBreakpointChange = noop,
51
+ onLayoutChange = noop,
52
+ onWidthChange = noop,
53
+ ...restProps
54
+ } = props;
55
+
56
+ const [prevProps, setPrevProps] = useState<{
57
+ width: number;
58
+ breakpoints: Breakpoints<Breakpoint>;
59
+ cols: Record<Breakpoint, number>;
60
+ }>({ width, breakpoints, cols });
61
+
62
+ const generateInitialState = (): ResponsiveGridLayoutStateType => {
63
+ const breakpoint = getBreakpointFromWidth(breakpoints, width);
64
+ const colNo = getColsFromBreakpoint(breakpoint, cols);
65
+ const compactType = props.compactType;
66
+ const initialLayout = findOrGenerateResponsiveLayout(
67
+ layouts,
68
+ breakpoints,
69
+ breakpoint,
70
+ breakpoint,
71
+ colNo,
72
+ compactType || "vertical",
73
+ false
74
+ );
75
+
76
+ return {
77
+ layout: initialLayout,
78
+ layouts,
79
+ breakpoint: breakpoint,
80
+ cols: colNo,
81
+ };
82
+ };
83
+
84
+ const [state, setState] = useState<ResponsiveGridLayoutStateType>(() =>
85
+ generateInitialState()
86
+ );
87
+ const emittedBreakpointChangeOnce = useRef(breakpoint != null);
88
+
89
+ useEffect(() => {
90
+ if (!state || !isEqual(state.layouts, layouts)) {
91
+ setState(generateInitialState());
92
+ }
93
+ }, [layouts]);
94
+
95
+ useEffect(() => {
96
+ onWidthChangeHandler();
97
+ }, [width, breakpoint, JSON.stringify(breakpoints), cols]);
98
+
99
+ const onLayoutChangeHandler: (layout: Layout) => void = (layout: Layout) => {
100
+ const newLayouts = {
101
+ ...layouts,
102
+ [state.breakpoint]: layout,
103
+ };
104
+
105
+ setState({
106
+ breakpoint: state.breakpoint,
107
+ cols: state.cols,
108
+ layout,
109
+ layouts: newLayouts,
110
+ });
111
+
112
+ onLayoutChange({
113
+ layout,
114
+ layouts: newLayouts,
115
+ });
116
+ };
117
+
118
+ const onWidthChangeHandler = () => {
119
+ const newBreakpoint =
120
+ breakpoint || getBreakpointFromWidth(breakpoints, width);
121
+
122
+ const lastBreakpoint = state.breakpoint;
123
+ const newCols: number = getColsFromBreakpoint(newBreakpoint, cols);
124
+ const newLayouts = { ...layouts };
125
+
126
+ if (
127
+ !emittedBreakpointChangeOnce.current ||
128
+ lastBreakpoint !== newBreakpoint ||
129
+ !isEqual(prevProps.breakpoints, breakpoints) ||
130
+ !isEqual(prevProps.cols, cols)
131
+ ) {
132
+ emittedBreakpointChangeOnce.current = true;
133
+
134
+ if (!(lastBreakpoint in newLayouts)) {
135
+ newLayouts[lastBreakpoint] = cloneLayout(state.layout);
136
+ }
137
+
138
+ const newBreakpointIsBiggerOrEqual =
139
+ lastBreakpoint === newBreakpoint ||
140
+ breakpoints[newBreakpoint] > breakpoints[lastBreakpoint];
141
+
142
+ const isNewLayout = layouts[newBreakpoint] == null;
143
+
144
+ let overlap =
145
+ !!props.allowOverlap && (!isNewLayout || newBreakpointIsBiggerOrEqual); // allow resize overlap only if we are going into a larger screen
146
+
147
+ let layout = findOrGenerateResponsiveLayout(
148
+ newLayouts,
149
+ breakpoints,
150
+ newBreakpoint,
151
+ lastBreakpoint,
152
+ newCols,
153
+ compactType || "vertical",
154
+ overlap
155
+ );
156
+
157
+ layout = synchronizeLayoutWithChildren(
158
+ layout,
159
+ children,
160
+ newCols,
161
+ compactType || "vertical",
162
+ overlap
163
+ );
164
+
165
+ newLayouts[newBreakpoint] = layout;
166
+
167
+ setState({
168
+ breakpoint: newBreakpoint,
169
+ layout: layout,
170
+ layouts: newLayouts,
171
+ cols: newCols,
172
+ });
173
+
174
+ onLayoutChange({ layout, layouts: newLayouts });
175
+ onBreakpointChange(newBreakpoint, newCols);
176
+ }
177
+
178
+ setPrevProps({ breakpoints, cols, width: width });
179
+
180
+ let modifiedMargin = getIndentationValue(margin, newBreakpoint);
181
+
182
+ const containerPaddingModified = getIndentationValue(
183
+ containerPadding,
184
+ newBreakpoint
185
+ );
186
+
187
+ onWidthChange(width, modifiedMargin!, newCols, containerPaddingModified);
188
+ };
189
+
190
+ return (
191
+ <ReactGridLayout
192
+ {...restProps}
193
+ children={children}
194
+ width={width}
195
+ margin={getIndentationValue(margin, state.breakpoint)}
196
+ containerPadding={getIndentationValue(containerPadding, state.breakpoint)}
197
+ onLayoutChange={onLayoutChangeHandler}
198
+ layout={state.layout}
199
+ cols={state.cols}
200
+ />
201
+ );
202
+ };
203
+
204
+ export default ResponsiveGridLayout;
@@ -0,0 +1,9 @@
1
+ export { ResponsiveGridLayout as ResponsiveGridEditor } from "./ResponsiveGridLayout";
2
+ export { default as GridEditor } from "./ReactGridLayout";
3
+ export type {
4
+ Breakpoint,
5
+ Breakpoints,
6
+ DefaultBreakpoints,
7
+ OnLayoutChangeCallback,
8
+ ResponsiveLayout,
9
+ } from "./types";
@@ -0,0 +1,133 @@
1
+ .react-grid-layout {
2
+ position: relative;
3
+ }
4
+ .react-grid-item {
5
+ position: absolute;
6
+ top: 0;
7
+ left: 0;
8
+ }
9
+
10
+ .react-grid-item img {
11
+ pointer-events: none;
12
+ user-select: none;
13
+ }
14
+
15
+ .react-grid-item.isResizing {
16
+ visibility: hidden;
17
+ }
18
+
19
+ .react-grid-item.react-draggable.isDragging {
20
+ visibility: hidden;
21
+ }
22
+
23
+ .react-grid-item.dropping {
24
+ visibility: hidden;
25
+ }
26
+
27
+ .react-grid-item.static::after {
28
+ content: "this is static, can't drag";
29
+ position: absolute;
30
+ top: 50%;
31
+ left: 50%;
32
+ transform: translate(-50%, -50%);
33
+ color: red;
34
+ }
35
+
36
+ /* .react-grid-item.cssTransforms {
37
+ transition-property: transform;
38
+ }
39
+
40
+ .react-grid-item.resizing {
41
+ z-index: 1;
42
+ will-change: width, height;
43
+ }
44
+
45
+ .react-grid-item.react-grid-item.react-draggable.react-draggable-dragging {
46
+ transition: none;
47
+ z-index: 3;
48
+ will-change: transform;
49
+ } */
50
+
51
+ .react-grid-item.placeholder {
52
+ z-index: 9999;
53
+ background-color: blue;
54
+ opacity: 0.5;
55
+ -webkit-user-select: none;
56
+ -moz-user-select: none;
57
+ -ms-user-select: none;
58
+ -o-user-select: none;
59
+ user-select: none;
60
+ }
61
+
62
+ /* .react-grid-item > .react-resizable-handle {
63
+ position: absolute;
64
+ width: 20px;
65
+ height: 20px;
66
+ } */
67
+
68
+ .react-grid-item > .react-resizable-handle::after {
69
+ content: "";
70
+ position: absolute;
71
+ right: 3px;
72
+ bottom: 3px;
73
+ width: 5px;
74
+ height: 5px;
75
+ border-right: 2px solid rgba(0, 0, 0, 0.4);
76
+ border-bottom: 2px solid rgba(0, 0, 0, 0.4);
77
+ }
78
+
79
+ .react-resizable-hide > .react-resizable-handle {
80
+ display: none;
81
+ }
82
+
83
+ /* .react-grid-item > .react-resizable-handle.react-resizable-handle-sw {
84
+ bottom: 0;
85
+ left: 0;
86
+ cursor: sw-resize;
87
+ transform: rotate(90deg);
88
+ }
89
+ .react-grid-item > .react-resizable-handle.react-resizable-handle-se {
90
+ bottom: 0;
91
+ right: 0;
92
+ cursor: se-resize;
93
+ }
94
+ .react-grid-item > .react-resizable-handle.react-resizable-handle-nw {
95
+ top: 0;
96
+ left: 0;
97
+ cursor: nw-resize;
98
+ transform: rotate(180deg);
99
+ }
100
+ .react-grid-item > .react-resizable-handle.react-resizable-handle-ne {
101
+ top: 0;
102
+ right: 0;
103
+ cursor: ne-resize;
104
+ transform: rotate(270deg);
105
+ }
106
+ .react-grid-item > .react-resizable-handle.react-resizable-handle-w,
107
+ .react-grid-item > .react-resizable-handle.react-resizable-handle-e {
108
+ top: 50%;
109
+ margin-top: -10px;
110
+ cursor: ew-resize;
111
+ }
112
+ .react-grid-item > .react-resizable-handle.react-resizable-handle-w {
113
+ left: 0;
114
+ transform: rotate(135deg);
115
+ }
116
+ .react-grid-item > .react-resizable-handle.react-resizable-handle-e {
117
+ right: 0;
118
+ transform: rotate(315deg);
119
+ }
120
+ .react-grid-item > .react-resizable-handle.react-resizable-handle-n,
121
+ .react-grid-item > .react-resizable-handle.react-resizable-handle-s {
122
+ left: 50%;
123
+ margin-left: -10px;
124
+ cursor: ns-resize;
125
+ }
126
+ .react-grid-item > .react-resizable-handle.react-resizable-handle-n {
127
+ top: 0;
128
+ transform: rotate(225deg);
129
+ }
130
+ .react-grid-item > .react-resizable-handle.react-resizable-handle-s {
131
+ bottom: 0;
132
+ transform: rotate(45deg);
133
+ } */
@@ -0,0 +1,199 @@
1
+ import { DragEvent, ReactElement, RefObject } from "react";
2
+ import { ResizeHandleAxis, ResizeHandleType } from "../Resizable/types";
3
+ import { ResizeEventType } from "../GridItem/types";
4
+
5
+ export type CompactType = "vertical" | "horizontal";
6
+
7
+ export type LayoutItem = {
8
+ w: number;
9
+ h: number;
10
+ x: number;
11
+ y: number;
12
+ z?: number;
13
+ i: string;
14
+ minW?: number;
15
+ minH?: number;
16
+ maxW?: number;
17
+ maxH?: number;
18
+ moved?: boolean;
19
+ static?: boolean;
20
+ isDraggable?: boolean;
21
+ isResizable?: boolean;
22
+ resizeHandles?: ResizeHandleAxis[];
23
+ isBounded?: boolean;
24
+ };
25
+
26
+ export type Layout = LayoutItem[];
27
+
28
+ export type DroppedEvent = {
29
+ layout: Layout;
30
+ item?: LayoutItem;
31
+ event?: DragEvent<HTMLDivElement>;
32
+ };
33
+
34
+ export type ReactGridLayoutProps = {
35
+ children: ReactElement<any> | ReactElement[];
36
+ className?: string;
37
+ style?: Object;
38
+ width?: number;
39
+ autoSize?: boolean;
40
+ cols: number;
41
+ draggableCancel?: string;
42
+ draggableHandle?: string;
43
+ verticalCompact?: boolean;
44
+ compactType?: CompactType;
45
+ layout: Layout;
46
+ margin: [number, number];
47
+ containerPadding?: [number, number] | null;
48
+ rowHeight: number;
49
+ maxRows?: number;
50
+ isBounded?: boolean;
51
+ isDraggable?: boolean;
52
+ isResizable?: boolean;
53
+ isDroppable?: boolean;
54
+ preventCollision?: boolean;
55
+ useCSSTransforms?: boolean;
56
+ transformScale?: number;
57
+ droppingItem?: Partial<LayoutItem>;
58
+ resizeHandles?: ResizeHandleAxis[];
59
+ resizeHandle?: ResizeHandleType;
60
+ allowOverlap?: boolean;
61
+ onLayoutChange?: (layout: Layout) => void;
62
+ onDrag?: EventCallback;
63
+ onDragStart?: EventCallback;
64
+ onDragStop?: EventCallback;
65
+ onResize?: EventCallback;
66
+ onResizeStart?: EventCallback;
67
+ onResizeStop?: EventCallback;
68
+ onDropDragOver?: (
69
+ e: DragOverEvent
70
+ ) => ({ w?: number; h?: number } | false) | null;
71
+ onDrop?: (
72
+ layout: Layout,
73
+ item: LayoutItem | null,
74
+ e: ResizeEventType
75
+ ) => void;
76
+ // onDrop?: (layout: Layout, item: LayoutItem | null, e: Event) => void;
77
+ isHiddenVisibility?: boolean;
78
+ innerRef?: RefObject<HTMLDivElement>;
79
+ };
80
+
81
+ export type DragOverEvent = MouseEvent & {
82
+ nativeEvent: {
83
+ layerX: number;
84
+ layerY: number;
85
+ } & Event;
86
+ };
87
+
88
+ export type EventCallback = (properties: {
89
+ layout: Layout;
90
+ prev?: LayoutItem;
91
+ item?: LayoutItem;
92
+ placeholder?: LayoutItem;
93
+ e?: ResizeEventType;
94
+ node?: HTMLElement;
95
+ }) => void;
96
+
97
+ export type RowHeight = number | ((width: number) => number);
98
+
99
+ export type Position = {
100
+ left: number;
101
+ top: number;
102
+ z?: number;
103
+ width: number;
104
+ height: number;
105
+ };
106
+
107
+ export type PositionParams = {
108
+ margin: [number, number];
109
+ containerPadding: [number, number];
110
+ containerWidth: number;
111
+ cols: number;
112
+ rowHeight: RowHeight;
113
+ maxRows: number;
114
+ };
115
+
116
+ // ResponsiveGridLayout
117
+ export type ResponsiveGridLayoutStateType = {
118
+ breakpoint: string;
119
+ cols: number;
120
+ layout: Layout;
121
+ layouts?: ResponsiveLayout<string>;
122
+ };
123
+
124
+ type CoreType = Omit<
125
+ ReactGridLayoutProps,
126
+ | "cols"
127
+ | "layout"
128
+ | "margin"
129
+ | "containerPadding"
130
+ | "transformScale"
131
+ | "onLayoutChange"
132
+ | "isHiddenVisibility"
133
+ >;
134
+
135
+ export type ResponsiveGridLayoutProps = {
136
+ breakpoint?: Breakpoint;
137
+ breakpoints?: Breakpoints<Breakpoint>;
138
+ cols?: Record<Breakpoint, number>;
139
+ layouts?: ResponsiveLayout<Breakpoint>;
140
+ margin?: Record<Breakpoint, [number, number]> | [number, number] | undefined;
141
+ containerPadding?:
142
+ | Record<Breakpoint, [number, number]>
143
+ | [number, number]
144
+ | undefined;
145
+ onBreakpointChange?: OnBreakpointChangeCallback;
146
+ onLayoutChange?: OnLayoutChangeCallback;
147
+ onWidthChange?: OnWidthChangeCallback;
148
+ } & CoreType;
149
+
150
+ // type Modify<T, R> = Omit<T, keyof R> & R;
151
+
152
+ // export type ResponsiveGridLayoutProps<Breakpoint extends string = string> =
153
+ // Modify<
154
+ // ReactGridLayoutProps,
155
+ // {
156
+ // // Responsive config
157
+ // breakpoint?: Breakpoint;
158
+ // breakpoints: Breakpoints<Breakpoint>;
159
+ // cols: Record<Breakpoint, number>;
160
+ // layouts: ResponsiveLayout<Breakpoint>;
161
+ // width: number;
162
+ // margin?:
163
+ // | Record<Breakpoint, [number, number]>
164
+ // | [number, number]
165
+ // | undefined;
166
+ // containerPadding?:
167
+ // | Record<Breakpoint, [number, number]>
168
+ // | [number, number]
169
+ // | undefined;
170
+
171
+ // // Callbacks
172
+ // onBreakpointChange: OnBreakpointChangeCallback;
173
+ // onLayoutChange: OnLayoutChangeCallback;
174
+ // onWidthChange: OnWidthChangeCallback;
175
+ // }
176
+ // >;
177
+
178
+ export type Breakpoint = string;
179
+ export type DefaultBreakpoints = "lg" | "md" | "sm" | "xs" | "xxs";
180
+
181
+ export type ResponsiveLayout<T extends Breakpoint> = Record<T, Layout>;
182
+ export type Breakpoints<T extends Breakpoint> = Record<T, number>;
183
+
184
+ export type OnLayoutChangeCallback = (properties: {
185
+ layout: Layout;
186
+ layouts: ResponsiveLayout<Breakpoint>;
187
+ }) => void;
188
+
189
+ export type OnBreakpointChangeCallback = (
190
+ breakpoint: Breakpoint,
191
+ cols: number
192
+ ) => void;
193
+
194
+ export type OnWidthChangeCallback = (
195
+ containerWidth: number,
196
+ margin: [number, number],
197
+ cols: number,
198
+ containerPadding?: [number, number]
199
+ ) => void;