@kwiz/fluentui 1.0.22 → 1.0.24

Sign up to get free protection for your applications and to get access to all the features.
Files changed (31) hide show
  1. package/.github/workflows/npm-publish.yml +3 -14
  2. package/dist/controls/dropdown.d.ts +8 -3
  3. package/dist/controls/dropdown.js +28 -21
  4. package/dist/controls/dropdown.js.map +1 -1
  5. package/dist/helpers/drag-drop/drag-drop-container.d.ts +15 -0
  6. package/dist/helpers/drag-drop/drag-drop-container.js +13 -0
  7. package/dist/helpers/drag-drop/drag-drop-container.js.map +1 -0
  8. package/dist/helpers/drag-drop/drag-drop-context.d.ts +30 -0
  9. package/dist/helpers/drag-drop/drag-drop-context.js +47 -0
  10. package/dist/helpers/drag-drop/drag-drop-context.js.map +1 -0
  11. package/dist/helpers/drag-drop/exports.d.ts +4 -0
  12. package/dist/helpers/drag-drop/exports.js +3 -0
  13. package/dist/helpers/drag-drop/exports.js.map +1 -0
  14. package/dist/helpers/drag-drop/use-draggable.d.ts +13 -0
  15. package/dist/helpers/drag-drop/use-draggable.js +33 -0
  16. package/dist/helpers/drag-drop/use-draggable.js.map +1 -0
  17. package/dist/helpers/drag-drop/use-droppable.d.ts +14 -0
  18. package/dist/helpers/drag-drop/use-droppable.js +28 -0
  19. package/dist/helpers/drag-drop/use-droppable.js.map +1 -0
  20. package/dist/index.d.ts +1 -0
  21. package/dist/index.js +1 -0
  22. package/dist/index.js.map +1 -1
  23. package/package.json +3 -1
  24. package/src/controls/dropdown.tsx +33 -28
  25. package/src/helpers/drag-drop/drag-drop-container.tsx +47 -0
  26. package/src/helpers/drag-drop/drag-drop-context.tsx +67 -0
  27. package/src/helpers/drag-drop/exports.ts +4 -0
  28. package/src/helpers/drag-drop/readme.md +76 -0
  29. package/src/helpers/drag-drop/use-draggable.ts +56 -0
  30. package/src/helpers/drag-drop/use-droppable.ts +48 -0
  31. package/src/index.ts +1 -0
@@ -9,27 +9,16 @@ on:
9
9
  - 'v*.*.*' # run every time we commit with a new version number
10
10
 
11
11
  jobs:
12
- build:
12
+ build-publish-npm:
13
13
  runs-on: ubuntu-latest
14
14
  steps:
15
15
  - uses: actions/checkout@v4
16
16
  - uses: actions/setup-node@v4
17
17
  with:
18
- node-version: 20
19
- - run: npm ci
20
- - run: npm test
21
-
22
- publish-npm:
23
- needs: build
24
- runs-on: ubuntu-latest
25
- steps:
26
- - uses: actions/checkout@v4
27
- - uses: actions/setup-node@v4
28
- with:
29
- node-version: 20
18
+ node-version: 18
30
19
  registry-url: https://registry.npmjs.org/
31
20
  - run: npm ci
32
21
  - run: npm run build
33
- - run: npm publish
22
+ - run: npm run npm-publish
34
23
  env:
35
24
  NODE_AUTH_TOKEN: ${{secrets.KWIZ_NPM_TOKEN}}
@@ -25,7 +25,12 @@ interface IProps<dataType, keyType extends string = string> extends ForwardProps
25
25
  data?: dataType;
26
26
  }[]) => void;
27
27
  }
28
- /** issue: figure out how to use forward ref with typed controls */
29
- export declare function DropdownEXTypedNoForwardRef<keyType extends string = string, dataType = never>(props: IProps<dataType, keyType>, ref: React.ForwardedRef<HTMLButtonElement>): import("react/jsx-runtime").JSX.Element;
30
- export declare const DropdownEX: React.ForwardRefExoticComponent<IProps<unknown, string> & React.RefAttributes<HTMLButtonElement>>;
28
+ /** get a DropdownEX typed with forward ref. Usage:
29
+ * const MyDropdownEX = DropdownEX3<myKeyType, myDataType>();
30
+ * ...
31
+ * <MyDropdownEX ... />
32
+ */
33
+ export declare function getDropdownEX<keyType extends string = string, dataType = never>(): React.ForwardRefExoticComponent<IProps<dataType, keyType> & React.RefAttributes<HTMLButtonElement>>;
34
+ /** to get typed keys use getDropdownEX */
35
+ export declare const DropdownEX: React.ForwardRefExoticComponent<IProps<never, string> & React.RefAttributes<HTMLButtonElement>>;
31
36
  export {};
@@ -3,26 +3,33 @@ import { Dropdown, Option } from '@fluentui/react-components';
3
3
  import { filterEmptyEntries, firstOrNull, isNullOrUndefined } from '@kwiz/common';
4
4
  import React from 'react';
5
5
  import { useKWIZFluentContext } from '../helpers/context';
6
- /** issue: figure out how to use forward ref with typed controls */
7
- export function DropdownEXTypedNoForwardRef(props, ref) {
8
- const ctx = useKWIZFluentContext();
9
- const selected = Array.isArray(props.selected) ? props.selected : isNullOrUndefined(props.selected) ? [] : [props.selected];
10
- //sometimes control will lose value when re-rendered
11
- //use case: public forms when editing other fields after the dropdown was set
12
- //re-set the text value manually to fix
13
- let text = filterEmptyEntries((Array.isArray(props.selected) ? props.selected : [props.selected]).map(s => {
14
- let v = firstOrNull(props.items, i => i.key === s);
15
- return v ? v.value : '';
16
- })).join(', ');
17
- return (_jsx(Dropdown, Object.assign({}, props, { onSelect: undefined, ref: ref, clearable: !props.required && !props.multiselect, appearance: ctx.inputAppearance, mountNode: ctx.mountNode, selectedOptions: selected, value: text, onOptionSelect: (e, data) => {
18
- let o = firstOrNull(props.items, i => i.key === data.optionValue);
19
- if (props.multiselect) {
20
- let current = data.selectedOptions.map(s => firstOrNull(props.items, i => i.key === s));
21
- props.onSelect(o, current);
22
- }
23
- else
24
- props.onSelect(o);
25
- }, children: props.items.map(i => _jsx(Option, { value: i.key, text: i.value, children: i.option ? i.option : i.value }, i.key)) })));
6
+ /** get a DropdownEX typed with forward ref. Usage:
7
+ * const MyDropdownEX = DropdownEX3<myKeyType, myDataType>();
8
+ * ...
9
+ * <MyDropdownEX ... />
10
+ */
11
+ export function getDropdownEX() {
12
+ return React.forwardRef((props, ref) => {
13
+ const ctx = useKWIZFluentContext();
14
+ const selected = Array.isArray(props.selected) ? props.selected : isNullOrUndefined(props.selected) ? [] : [props.selected];
15
+ //sometimes control will lose value when re-rendered
16
+ //use case: public forms when editing other fields after the dropdown was set
17
+ //re-set the text value manually to fix
18
+ let text = filterEmptyEntries((Array.isArray(props.selected) ? props.selected : [props.selected]).map(s => {
19
+ let v = firstOrNull(props.items, i => i.key === s);
20
+ return v ? v.value : '';
21
+ })).join(', ');
22
+ return (_jsx(Dropdown, Object.assign({}, props, { onSelect: undefined, ref: ref, clearable: !props.required && !props.multiselect, appearance: ctx.inputAppearance, mountNode: ctx.mountNode, selectedOptions: selected, value: text, onOptionSelect: (e, data) => {
23
+ let o = firstOrNull(props.items, i => i.key === data.optionValue);
24
+ if (props.multiselect) {
25
+ let current = data.selectedOptions.map(s => firstOrNull(props.items, i => i.key === s));
26
+ props.onSelect(o, current);
27
+ }
28
+ else
29
+ props.onSelect(o);
30
+ }, children: props.items.map(i => _jsx(Option, { value: i.key, text: i.value, children: i.option ? i.option : i.value }, i.key)) })));
31
+ });
26
32
  }
27
- export const DropdownEX = React.forwardRef(DropdownEXTypedNoForwardRef);
33
+ /** to get typed keys use getDropdownEX */
34
+ export const DropdownEX = getDropdownEX();
28
35
  //# sourceMappingURL=dropdown.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dropdown.js","sourceRoot":"","sources":["../../src/controls/dropdown.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAiB,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAC7E,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAClF,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAmB1D,mEAAmE;AACnE,MAAM,UAAU,2BAA2B,CAAoD,KAAgC,EAAE,GAA0C;IACvK,MAAM,GAAG,GAAG,oBAAoB,EAAE,CAAC;IACnC,MAAM,QAAQ,GAAc,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,iBAAiB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAEvI,oDAAoD;IACpD,6EAA6E;IAC7E,uCAAuC;IACvC,IAAI,IAAI,GAAG,kBAAkB,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;QACtG,IAAI,CAAC,GAAG,WAAW,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;QACnD,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAA;IAC3B,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEf,OAAO,CACH,KAAC,QAAQ,oBAAU,KAAK,IAAE,QAAQ,EAAE,SAAS,EAAI,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,KAAK,CAAC,QAAQ,IAAI,CAAC,KAAK,CAAC,WAAW,EACvG,UAAU,EAAE,GAAG,CAAC,eAAe,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EACzD,eAAe,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE;YAChE,IAAI,CAAC,GAAG,WAAW,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,CAAC,WAAW,CAAC,CAAC;YAClE,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;gBACpB,IAAI,OAAO,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;gBACxF,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YAC/B,CAAC;;gBACI,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAC3B,CAAC,YACA,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAC,MAAM,IAAa,KAAK,EAAE,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,YAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,IAAlE,CAAC,CAAC,GAAG,CAAuE,CAAC,IACzG,CAEd,CAAC;AACN,CAAC;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC,2BAA2B,CAAC,CAAC"}
1
+ {"version":3,"file":"dropdown.js","sourceRoot":"","sources":["../../src/controls/dropdown.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import { iDraggedItemType, iDraggableProps } from "./use-draggable";
2
+ import { iDroppableProps } from "./use-droppable";
3
+ interface one<DragItemType extends iDraggedItemType<string>> {
4
+ dragInfo: iDraggableProps<DragItemType>;
5
+ }
6
+ interface other<DropInfoTypes extends string = never, DropInfoItemTypes extends iDraggedItemType<DropInfoTypes> = never> {
7
+ dropInfo: iDroppableProps<DropInfoTypes, DropInfoItemTypes>;
8
+ }
9
+ type iDragDropProps<DragItemType extends iDraggedItemType<string>, DropInfoTypes extends string = never, DropInfoItemTypes extends iDraggedItemType<DropInfoTypes> = never> = one<DragItemType> | other<DropInfoTypes, DropInfoItemTypes> | (one<DragItemType> & other<DropInfoTypes, DropInfoItemTypes>);
10
+ type iProps<DragItemType extends iDraggedItemType<string>, DropInfoTypes extends string, DropInfoItemTypes extends iDraggedItemType<DropInfoTypes>> = Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
11
+ onDraggingClassName?: string;
12
+ onDragOverClassName?: string;
13
+ } & iDragDropProps<DragItemType, DropInfoTypes, DropInfoItemTypes>;
14
+ export declare function DragDropContainer<DragItemType extends iDraggedItemType<string> = never, DropInfoTypes extends string = never, DropInfoItemTypes extends iDraggedItemType<DropInfoTypes> = never>(props: React.PropsWithChildren<iProps<DragItemType, DropInfoTypes, DropInfoItemTypes>>): import("react/jsx-runtime").JSX.Element;
15
+ export {};
@@ -0,0 +1,13 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { isNullOrEmptyString } from "@kwiz/common";
3
+ import { useDragDropContext } from "./drag-drop-context";
4
+ export function DragDropContainer(props) {
5
+ const { drag, drop, dragDropRef } = useDragDropContext(props);
6
+ const classNames = isNullOrEmptyString(props.className) ? [] : props.className.split(' ');
7
+ if (drag.isDragging && props.onDraggingClassName)
8
+ classNames.push(props.onDraggingClassName);
9
+ if (drop.isOver && props.onDragOverClassName)
10
+ classNames.push(props.onDragOverClassName);
11
+ return _jsx("div", Object.assign({}, (props || {}), { ref: dragDropRef, className: classNames.join(' '), children: props.children }));
12
+ }
13
+ //# sourceMappingURL=drag-drop-container.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drag-drop-container.js","sourceRoot":"","sources":["../../../src/helpers/drag-drop/drag-drop-container.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAgCzD,MAAM,UAAU,iBAAiB,CAI/B,KAAsF;IAEpF,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAE9D,MAAM,UAAU,GAAa,mBAAmB,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACpG,IAAI,IAAI,CAAC,UAAU,IAAI,KAAK,CAAC,mBAAmB;QAAE,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;IAC7F,IAAI,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC,mBAAmB;QAAE,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;IAEzF,OAAO,8BAAS,CAAC,KAAK,IAAI,EAAE,CAAC,IAAE,GAAG,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,YAAG,KAAK,CAAC,QAAQ,IAAO,CAAC;AAC7G,CAAC"}
@@ -0,0 +1,30 @@
1
+ import React from "react";
2
+ import { iDraggableProps, iDraggedItemType } from "./use-draggable";
3
+ import { iDroppableProps } from "./use-droppable";
4
+ export interface iDragDropContext {
5
+ isDragging: boolean;
6
+ setIsDragging: (value: boolean) => void;
7
+ }
8
+ export declare const DragDropContext: React.Context<iDragDropContext>;
9
+ export declare function useDragDropContextInternal(): iDragDropContext;
10
+ export declare function useDragDropContext<DragItemType extends iDraggedItemType<string> = never, DropInfoType extends iDroppableProps<string, any> = never>(info: {
11
+ dragInfo?: iDraggableProps<DragItemType>;
12
+ dropInfo?: DropInfoType;
13
+ }): {
14
+ dragDropContext: iDragDropContext;
15
+ drag: {
16
+ isDragging: boolean;
17
+ dragRef: import("react-dnd").ConnectDragSource;
18
+ };
19
+ drop: {
20
+ canDrop: boolean;
21
+ isOver: boolean;
22
+ dropRef: import("react-dnd").ConnectDropTarget;
23
+ };
24
+ dragDropRef: import("react-dnd").ConnectDragSource;
25
+ };
26
+ export declare function useDragDropContextProvider(): iDragDropContext;
27
+ interface iProps {
28
+ }
29
+ export declare const DragDropContextProvider: React.FunctionComponent<React.PropsWithChildren<iProps>>;
30
+ export {};
@@ -0,0 +1,47 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { isNullOrUndefined } from "@kwiz/common";
3
+ import React, { useContext } from "react";
4
+ import { DndProvider } from "react-dnd";
5
+ import { HTML5Backend } from "react-dnd-html5-backend";
6
+ import { useStateEX } from "../hooks";
7
+ import { useDraggable } from "./use-draggable";
8
+ import useDroppable from "./use-droppable";
9
+ //create context
10
+ export const DragDropContext = React.createContext(null);
11
+ //use context from within controls
12
+ export function useDragDropContextInternal() {
13
+ const dragDropContext = useContext(DragDropContext);
14
+ return dragDropContext;
15
+ }
16
+ export function useDragDropContext(info) {
17
+ const dragDropContext = useDragDropContextInternal();
18
+ const isDraggable = !isNullOrUndefined(info.dragInfo);
19
+ const isDroppable = !isNullOrUndefined(info.dropInfo);
20
+ const drag = useDraggable(info === null || info === void 0 ? void 0 : info.dragInfo);
21
+ const drop = useDroppable(info === null || info === void 0 ? void 0 : info.dropInfo);
22
+ const acceptDrops = isDroppable && !drag.isDragging && dragDropContext.isDragging;
23
+ return {
24
+ dragDropContext,
25
+ drag,
26
+ drop,
27
+ dragDropRef: isDraggable && !isDroppable
28
+ ? drag.dragRef
29
+ : !isDraggable && isDroppable
30
+ ? drop.dropRef
31
+ //both drag and drop allowed
32
+ : acceptDrops ? drop.dropRef : drag.dragRef
33
+ };
34
+ }
35
+ export function useDragDropContextProvider() {
36
+ const [isDragging, setIsDragging] = useStateEX(false);
37
+ //build context
38
+ const ctx = {
39
+ isDragging, setIsDragging
40
+ };
41
+ return ctx;
42
+ }
43
+ export const DragDropContextProvider = (props) => {
44
+ const provider = useDragDropContextProvider();
45
+ return _jsx(DragDropContext.Provider, { value: provider, children: _jsx(DndProvider, { backend: HTML5Backend, children: props.children }) });
46
+ };
47
+ //# sourceMappingURL=drag-drop-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drag-drop-context.js","sourceRoot":"","sources":["../../../src/helpers/drag-drop/drag-drop-context.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAqC,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAClF,OAAO,YAAiC,MAAM,iBAAiB,CAAC;AAMhE,gBAAgB;AAChB,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC,aAAa,CAAmB,IAAI,CAAC,CAAC;AAC3E,kCAAkC;AAClC,MAAM,UAAU,0BAA0B;IACtC,MAAM,eAAe,GAAG,UAAU,CAAC,eAAe,CAAC,CAAC;IACpD,OAAO,eAAe,CAAC;AAC3B,CAAC;AACD,MAAM,UAAU,kBAAkB,CAGhC,IAGD;IACG,MAAM,eAAe,GAAG,0BAA0B,EAAE,CAAC;IACrD,MAAM,WAAW,GAAG,CAAC,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACtD,MAAM,WAAW,GAAG,CAAC,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACtD,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,QAAQ,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,YAAY,CAAC,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,QAAQ,CAAC,CAAC;IAC1C,MAAM,WAAW,GAAG,WAAW,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,eAAe,CAAC,UAAU,CAAC;IAElF,OAAO;QACH,eAAe;QACf,IAAI;QACJ,IAAI;QACJ,WAAW,EAAE,WAAW,IAAI,CAAC,WAAW;YACpC,CAAC,CAAC,IAAI,CAAC,OAAO;YACd,CAAC,CAAC,CAAC,WAAW,IAAI,WAAW;gBACzB,CAAC,CAAC,IAAI,CAAC,OAAO;gBACd,4BAA4B;gBAC5B,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO;KACtD,CAAC;AACN,CAAC;AACD,MAAM,UAAU,0BAA0B;IACtC,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAEtD,eAAe;IACf,MAAM,GAAG,GAAqB;QAC1B,UAAU,EAAE,aAAa;KAC5B,CAAC;IAGF,OAAO,GAAG,CAAC;AACf,CAAC;AAID,MAAM,CAAC,MAAM,uBAAuB,GAA6D,CAAC,KAAK,EAAE,EAAE;IACvG,MAAM,QAAQ,GAAG,0BAA0B,EAAE,CAAC;IAC9C,OAAO,KAAC,eAAe,CAAC,QAAQ,IAAC,KAAK,EAAE,QAAQ,YAC5C,KAAC,WAAW,IAAC,OAAO,EAAE,YAAY,YAC7B,KAAK,CAAC,QAAQ,GACL,GACS,CAAC;AAChC,CAAC,CAAA"}
@@ -0,0 +1,4 @@
1
+ export { DragDropContainer } from './drag-drop-container';
2
+ export { DragDropContextProvider, useDragDropContext } from "./drag-drop-context";
3
+ export type { iDraggedItemType } from "./use-draggable";
4
+ export type { iDroppableProps } from "./use-droppable";
@@ -0,0 +1,3 @@
1
+ export { DragDropContainer } from './drag-drop-container';
2
+ export { DragDropContextProvider, useDragDropContext } from "./drag-drop-context";
3
+ //# sourceMappingURL=exports.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exports.js","sourceRoot":"","sources":["../../../src/helpers/drag-drop/exports.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { ConnectDragSource } from 'react-dnd';
2
+ export interface iDraggedItemType<DragType extends string> {
3
+ type: DragType;
4
+ }
5
+ export interface iDraggableProps<ItemType extends iDraggedItemType<string>> {
6
+ item: ItemType;
7
+ onBeginDrag?: () => void;
8
+ onEndDrag?: (dropResult: any) => void;
9
+ }
10
+ export declare function useDraggable<ItemType extends iDraggedItemType<string>>(props?: iDraggableProps<ItemType>): {
11
+ isDragging: boolean;
12
+ dragRef: ConnectDragSource;
13
+ };
@@ -0,0 +1,33 @@
1
+ import { useEffect } from 'react';
2
+ import { useDrag } from 'react-dnd';
3
+ import { useDragDropContextInternal } from './drag-drop-context';
4
+ export function useDraggable(props) {
5
+ const { item, onBeginDrag, onEndDrag, } = props || {
6
+ item: {
7
+ type: "~invalid~"
8
+ }
9
+ };
10
+ const dragDropContext = useDragDropContextInternal();
11
+ const [{ isDragging }, dragRef] = useDrag(() => ({
12
+ type: item.type,
13
+ item,
14
+ collect: (monitor) => ({
15
+ isDragging: monitor.isDragging(),
16
+ }),
17
+ end: (item, monitor) => {
18
+ dragDropContext.setIsDragging(false);
19
+ onEndDrag && onEndDrag(monitor.getDropResult());
20
+ },
21
+ }), [item, item.type]);
22
+ useEffect(() => {
23
+ if (isDragging) {
24
+ dragDropContext.setIsDragging(true);
25
+ onBeginDrag && onBeginDrag();
26
+ }
27
+ }, [isDragging, onBeginDrag]);
28
+ return {
29
+ isDragging,
30
+ dragRef,
31
+ };
32
+ }
33
+ //# sourceMappingURL=use-draggable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-draggable.js","sourceRoot":"","sources":["../../../src/helpers/drag-drop/use-draggable.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAClC,OAAO,EAAwC,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1E,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAWjE,MAAM,UAAU,YAAY,CAA4C,KAAiC;IAIrG,MAAM,EACF,IAAI,EACJ,WAAW,EACX,SAAS,GACZ,GAAG,KAAK,IAAI;QACT,IAAI,EAAE;YACF,IAAI,EAAE,WAAW;SACpB;KACJ,CAAC;IAEF,MAAM,eAAe,GAAG,0BAA0B,EAAE,CAAC;IAErD,MAAM,CAAC,EAAE,UAAU,EAAE,EAAE,OAAO,CAAC,GAAG,OAAO,CACrC,GAAG,EAAE,CAAC,CAAC;QACH,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,IAAI;QACJ,OAAO,EAAE,CAAC,OAA0B,EAAE,EAAE,CAAC,CAAC;YACtC,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE;SACnC,CAAC;QACF,GAAG,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE;YACnB,eAAe,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;YACrC,SAAS,IAAI,SAAS,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;QACpD,CAAC;KACJ,CAAC,EACF,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CACpB,CAAC;IAEF,SAAS,CAAC,GAAG,EAAE;QACX,IAAI,UAAU,EAAE,CAAC;YACb,eAAe,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;YACpC,WAAW,IAAI,WAAW,EAAE,CAAC;QACjC,CAAC;IACL,CAAC,EAAE,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC,CAAA;IAE7B,OAAO;QACH,UAAU;QACV,OAAO;KACV,CAAC;AACN,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { ConnectDropTarget } from 'react-dnd';
2
+ import { iDraggedItemType } from './use-draggable';
3
+ export interface iDroppableProps<DropTypes extends string, ItemTypes extends iDraggedItemType<DropTypes>> {
4
+ acceptTypes: DropTypes[];
5
+ onItemDrop: (item: ItemTypes) => void;
6
+ onHover?: (item: ItemTypes) => void;
7
+ onDrop?: () => void;
8
+ }
9
+ declare function useDroppable<DropType extends string, ItemType extends iDraggedItemType<DropType>>(props?: iDroppableProps<DropType, ItemType>): {
10
+ canDrop: boolean;
11
+ isOver: boolean;
12
+ dropRef: ConnectDropTarget;
13
+ };
14
+ export default useDroppable;
@@ -0,0 +1,28 @@
1
+ import { useDrop } from 'react-dnd';
2
+ function useDroppable(props) {
3
+ const { acceptTypes, onItemDrop, onHover, onDrop, } = props || {
4
+ acceptTypes: [],
5
+ onItemDrop: () => { }
6
+ };
7
+ const [{ canDrop, isOver }, dropRef] = useDrop({
8
+ accept: acceptTypes,
9
+ drop: (item) => {
10
+ onItemDrop(item);
11
+ onDrop === null || onDrop === void 0 ? void 0 : onDrop();
12
+ },
13
+ hover: (item) => {
14
+ onHover === null || onHover === void 0 ? void 0 : onHover(item);
15
+ },
16
+ collect: (monitor) => ({
17
+ canDrop: monitor.canDrop(),
18
+ isOver: monitor.isOver(),
19
+ }),
20
+ });
21
+ return {
22
+ canDrop,
23
+ isOver,
24
+ dropRef,
25
+ };
26
+ }
27
+ export default useDroppable;
28
+ //# sourceMappingURL=use-droppable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-droppable.js","sourceRoot":"","sources":["../../../src/helpers/drag-drop/use-droppable.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwC,OAAO,EAAE,MAAM,WAAW,CAAC;AAU1E,SAAS,YAAY,CAAuE,KAA2C;IAKnI,MAAM,EACF,WAAW,EACX,UAAU,EACV,OAAO,EACP,MAAM,GACT,GAAG,KAAK,IAAI;QACT,WAAW,EAAE,EAAE;QACf,UAAU,EAAE,GAAG,EAAE,GAAG,CAAC;KACxB,CAAC;IAEF,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC;QAC3C,MAAM,EAAE,WAAW;QACnB,IAAI,EAAE,CAAC,IAAc,EAAE,EAAE;YACrB,UAAU,CAAC,IAAI,CAAC,CAAC;YACjB,MAAM,aAAN,MAAM,uBAAN,MAAM,EAAI,CAAC;QACf,CAAC;QACD,KAAK,EAAE,CAAC,IAAc,EAAE,EAAE;YACtB,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAG,IAAI,CAAC,CAAC;QACpB,CAAC;QACD,OAAO,EAAE,CAAC,OAA0B,EAAE,EAAE,CAAC,CAAC;YACtC,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE;YAC1B,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE;SAC3B,CAAC;KACL,CAAC,CAAC;IAEH,OAAO;QACH,OAAO;QACP,MAAM;QACN,OAAO;KACV,CAAC;AACN,CAAC;AAED,eAAe,YAAY,CAAC"}
package/dist/index.d.ts CHANGED
@@ -21,5 +21,6 @@ export * from './controls/vertical';
21
21
  export * from './controls/vertical-content';
22
22
  export { KWIZFluentContext, useKWIZFluentContext } from './helpers/context';
23
23
  export type { iKWIZFluentContext } from './helpers/context';
24
+ export * from './helpers/drag-drop/exports';
24
25
  export * from './helpers/hooks';
25
26
  export { KnownClassNames } from './styles/styles';
package/dist/index.js CHANGED
@@ -20,6 +20,7 @@ export * from './controls/toolbar';
20
20
  export * from './controls/vertical';
21
21
  export * from './controls/vertical-content';
22
22
  export { KWIZFluentContext, useKWIZFluentContext } from './helpers/context';
23
+ export * from './helpers/drag-drop/exports';
23
24
  export * from './helpers/hooks';
24
25
  export { KnownClassNames } from './styles/styles';
25
26
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,kBAAkB,CAAC;AACjC,cAAc,yBAAyB,CAAC;AACxC,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAE5E,cAAc,iBAAiB,CAAC;AAChC,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,kBAAkB,CAAC;AACjC,cAAc,yBAAyB,CAAC;AACxC,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AACnC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,6BAA6B,CAAC;AAC5C,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAE5E,cAAc,6BAA6B,CAAC;AAC5C,cAAc,iBAAiB,CAAC;AAChC,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kwiz/fluentui",
3
- "version": "1.0.22",
3
+ "version": "1.0.24",
4
4
  "description": "KWIZ common controls for FluentUI",
5
5
  "module": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -59,6 +59,8 @@
59
59
  "@kwiz/common": "^1.0.58",
60
60
  "esbuild": "^0.19.12",
61
61
  "get-tsconfig": "^4.7.2",
62
+ "react-dnd": "^16.0.1",
63
+ "react-dnd-html5-backend": "^16.0.1",
62
64
  "resolve-pkg-maps": "^1.0.0"
63
65
  },
64
66
  "peerDependencies": {
@@ -20,34 +20,39 @@ interface IProps<dataType, keyType extends string = string> extends ForwardProps
20
20
  options?: { key: keyType, value: string, data?: dataType }[]) => void;
21
21
  }
22
22
 
23
- /** issue: figure out how to use forward ref with typed controls */
24
- export function DropdownEXTypedNoForwardRef<keyType extends string = string, dataType = never>(props: IProps<dataType, keyType>, ref: React.ForwardedRef<HTMLButtonElement>) {
25
- const ctx = useKWIZFluentContext();
26
- const selected: keyType[] = Array.isArray(props.selected) ? props.selected : isNullOrUndefined(props.selected) ? [] : [props.selected];
23
+ /** get a DropdownEX typed with forward ref. Usage:
24
+ * const MyDropdownEX = DropdownEX3<myKeyType, myDataType>();
25
+ * ...
26
+ * <MyDropdownEX ... />
27
+ */
28
+ export function getDropdownEX<keyType extends string = string, dataType = never>() {
29
+ return React.forwardRef<HTMLButtonElement, (IProps<dataType, keyType>)>((props, ref) => {
30
+ const ctx = useKWIZFluentContext();
31
+ const selected: keyType[] = Array.isArray(props.selected) ? props.selected : isNullOrUndefined(props.selected) ? [] : [props.selected];
27
32
 
28
- //sometimes control will lose value when re-rendered
29
- //use case: public forms when editing other fields after the dropdown was set
30
- //re-set the text value manually to fix
31
- let text = filterEmptyEntries((Array.isArray(props.selected) ? props.selected : [props.selected]).map(s => {
32
- let v = firstOrNull(props.items, i => i.key === s);
33
- return v ? v.value : ''
34
- })).join(', ');
33
+ //sometimes control will lose value when re-rendered
34
+ //use case: public forms when editing other fields after the dropdown was set
35
+ //re-set the text value manually to fix
36
+ let text = filterEmptyEntries((Array.isArray(props.selected) ? props.selected : [props.selected]).map(s => {
37
+ let v = firstOrNull(props.items, i => i.key === s);
38
+ return v ? v.value : ''
39
+ })).join(', ');
35
40
 
36
- return (
37
- <Dropdown {...{ ...props, onSelect: undefined }} ref={ref} clearable={!props.required && !props.multiselect}
38
- appearance={ctx.inputAppearance} mountNode={ctx.mountNode}
39
- selectedOptions={selected} value={text} onOptionSelect={(e, data) => {
40
- let o = firstOrNull(props.items, i => i.key === data.optionValue);
41
- if (props.multiselect) {
42
- let current = data.selectedOptions.map(s => firstOrNull(props.items, i => i.key === s));
43
- props.onSelect(o, current);
44
- }
45
- else props.onSelect(o);
46
- }}>
47
- {props.items.map(i => <Option key={i.key} value={i.key} text={i.value}>{i.option ? i.option : i.value}</Option>)}
48
- </Dropdown>
49
-
50
- );
41
+ return (
42
+ <Dropdown {...{ ...props, onSelect: undefined }} ref={ref} clearable={!props.required && !props.multiselect}
43
+ appearance={ctx.inputAppearance} mountNode={ctx.mountNode}
44
+ selectedOptions={selected} value={text} onOptionSelect={(e, data) => {
45
+ let o = firstOrNull(props.items, i => i.key === data.optionValue);
46
+ if (props.multiselect) {
47
+ let current = data.selectedOptions.map(s => firstOrNull(props.items, i => i.key === s));
48
+ props.onSelect(o, current);
49
+ }
50
+ else props.onSelect(o);
51
+ }}>
52
+ {props.items.map(i => <Option key={i.key} value={i.key} text={i.value}>{i.option ? i.option : i.value}</Option>)}
53
+ </Dropdown>
54
+ );
55
+ });
51
56
  }
52
-
53
- export const DropdownEX = React.forwardRef(DropdownEXTypedNoForwardRef);
57
+ /** to get typed keys use getDropdownEX */
58
+ export const DropdownEX = getDropdownEX();
@@ -0,0 +1,47 @@
1
+ import { isNullOrEmptyString } from "@kwiz/common";
2
+ import { useDragDropContext } from "./drag-drop-context";
3
+ import { iDraggedItemType, iDraggableProps } from "./use-draggable";
4
+ import { iDroppableProps } from "./use-droppable";
5
+
6
+ interface one<DragItemType extends iDraggedItemType<string>> {
7
+ dragInfo: iDraggableProps<DragItemType>;
8
+ }
9
+ interface other<
10
+ DropInfoTypes extends string = never,
11
+ DropInfoItemTypes extends iDraggedItemType<DropInfoTypes> = never,
12
+ > {
13
+ dropInfo: iDroppableProps<DropInfoTypes, DropInfoItemTypes>;
14
+ }
15
+ type iDragDropProps<
16
+ DragItemType extends iDraggedItemType<string>,
17
+ DropInfoTypes extends string = never,
18
+ DropInfoItemTypes extends iDraggedItemType<DropInfoTypes> = never,
19
+ > = one<DragItemType>
20
+ | other<DropInfoTypes, DropInfoItemTypes>
21
+ | (one<DragItemType> & other<DropInfoTypes, DropInfoItemTypes>);
22
+
23
+ type iProps<DragItemType extends iDraggedItemType<string>, DropInfoTypes extends string, DropInfoItemTypes extends iDraggedItemType<DropInfoTypes>> =
24
+ //all DIV props, except ref - we need ref.
25
+ Omit<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">
26
+ //pass drag class names
27
+ & {
28
+ onDraggingClassName?: string;
29
+ onDragOverClassName?: string;
30
+ }
31
+ //drag/drop info
32
+ & iDragDropProps<DragItemType, DropInfoTypes, DropInfoItemTypes>
33
+
34
+ export function DragDropContainer<
35
+ DragItemType extends iDraggedItemType<string> = never,
36
+ DropInfoTypes extends string = never,
37
+ DropInfoItemTypes extends iDraggedItemType<DropInfoTypes> = never
38
+ >(props: React.PropsWithChildren<iProps<DragItemType, DropInfoTypes, DropInfoItemTypes>>) {
39
+
40
+ const { drag, drop, dragDropRef } = useDragDropContext(props);
41
+
42
+ const classNames: string[] = isNullOrEmptyString(props.className) ? [] : props.className.split(' ');
43
+ if (drag.isDragging && props.onDraggingClassName) classNames.push(props.onDraggingClassName);
44
+ if (drop.isOver && props.onDragOverClassName) classNames.push(props.onDragOverClassName);
45
+
46
+ return <div {...(props || {})} ref={dragDropRef} className={classNames.join(' ')}>{props.children}</div>;
47
+ }
@@ -0,0 +1,67 @@
1
+ import { isNullOrUndefined } from "@kwiz/common";
2
+ import React, { useContext } from "react";
3
+ import { DndProvider } from "react-dnd";
4
+ import { HTML5Backend } from "react-dnd-html5-backend";
5
+ import { useStateEX } from "../hooks";
6
+ import { iDraggableProps, iDraggedItemType, useDraggable } from "./use-draggable";
7
+ import useDroppable, { iDroppableProps } from "./use-droppable";
8
+
9
+ export interface iDragDropContext {
10
+ isDragging: boolean;
11
+ setIsDragging: (value: boolean) => void;
12
+ }
13
+ //create context
14
+ export const DragDropContext = React.createContext<iDragDropContext>(null);
15
+ //use context from within controls
16
+ export function useDragDropContextInternal() {
17
+ const dragDropContext = useContext(DragDropContext);
18
+ return dragDropContext;
19
+ }
20
+ export function useDragDropContext<
21
+ DragItemType extends iDraggedItemType<string> = never,
22
+ DropInfoType extends iDroppableProps<string, any> = never
23
+ >(info: {
24
+ dragInfo?: iDraggableProps<DragItemType>;
25
+ dropInfo?: DropInfoType;
26
+ }) {
27
+ const dragDropContext = useDragDropContextInternal();
28
+ const isDraggable = !isNullOrUndefined(info.dragInfo);
29
+ const isDroppable = !isNullOrUndefined(info.dropInfo);
30
+ const drag = useDraggable(info?.dragInfo);
31
+ const drop = useDroppable(info?.dropInfo);
32
+ const acceptDrops = isDroppable && !drag.isDragging && dragDropContext.isDragging;
33
+
34
+ return {
35
+ dragDropContext,
36
+ drag,
37
+ drop,
38
+ dragDropRef: isDraggable && !isDroppable
39
+ ? drag.dragRef
40
+ : !isDraggable && isDroppable
41
+ ? drop.dropRef
42
+ //both drag and drop allowed
43
+ : acceptDrops ? drop.dropRef : drag.dragRef
44
+ };
45
+ }
46
+ export function useDragDropContextProvider(): iDragDropContext {
47
+ const [isDragging, setIsDragging] = useStateEX(false);
48
+
49
+ //build context
50
+ const ctx: iDragDropContext = {
51
+ isDragging, setIsDragging
52
+ };
53
+
54
+
55
+ return ctx;
56
+ }
57
+
58
+ interface iProps {
59
+ }
60
+ export const DragDropContextProvider: React.FunctionComponent<React.PropsWithChildren<iProps>> = (props) => {
61
+ const provider = useDragDropContextProvider();
62
+ return <DragDropContext.Provider value={provider}>
63
+ <DndProvider backend={HTML5Backend}>
64
+ {props.children}
65
+ </DndProvider>
66
+ </DragDropContext.Provider>;
67
+ }
@@ -0,0 +1,4 @@
1
+ export { DragDropContainer } from './drag-drop-container';
2
+ export { DragDropContextProvider, useDragDropContext } from "./drag-drop-context";
3
+ export type { iDraggedItemType } from "./use-draggable";
4
+ export type { iDroppableProps } from "./use-droppable";
@@ -0,0 +1,76 @@
1
+ Use drag drop with types examples:
2
+
3
+ Wrap everything within drag/drop context:
4
+ ```tsx
5
+ <DragDropContextProvider>
6
+ ...
7
+ </DragDropContextProvider>
8
+ ```
9
+
10
+ Define the types you want to allow drag/drop:
11
+ ```tsx
12
+ export type dragColumnType = "column";
13
+ export type dragCellType = "cell";
14
+ export interface dragColumn extends iDraggedItemType<dragColumnType> {
15
+ data: iDesignerContextFields
16
+ }
17
+
18
+ export interface dragCell extends iDraggedItemType<dragCellType> {
19
+ row: number;
20
+ cell: number;
21
+ }
22
+ export interface dropCellOrColumn extends iDroppableProps<dragColumnType | dragCellType, dragColumn | dragCell> {
23
+ }
24
+ ```
25
+
26
+ use within a control:
27
+ ```tsx
28
+ const { drag, drop, dragDropRef } = useDragDropContext<
29
+ dragCell, dropCellOrColumn
30
+ >({
31
+ dragInfo: {
32
+ item: {
33
+ type: "cell",
34
+ cell: props.index,
35
+ row: props.rowIndex
36
+ },
37
+ },
38
+ dropInfo: {
39
+ acceptTypes: ["cell", "column"],
40
+ onItemDrop: item => {
41
+ switch (item.type) {
42
+ case "cell":
43
+ alert(item.cell);
44
+ break;
45
+ case "column":
46
+ alert(item.data.title);
47
+ break;
48
+ }
49
+ }
50
+ }
51
+ });
52
+
53
+ ...
54
+
55
+ <Section css={[
56
+ drop.isOver && classes.hover,
57
+ drag.isDragging && classes.dragging
58
+ ]}
59
+ ref={dragDropRef}>
60
+ ...
61
+ </Section>
62
+ ```
63
+
64
+ Use with a wrapper:
65
+
66
+ ```tsx
67
+ <DragDropContainer<dragColumn>
68
+ dragInfo={{
69
+ item: {
70
+ type: "column",
71
+ data: f
72
+ }
73
+ }}>
74
+ <ButtonEX ... />
75
+ </DragDropContainer>
76
+ ```
@@ -0,0 +1,56 @@
1
+ import { useEffect } from 'react';
2
+ import { ConnectDragSource, DragSourceMonitor, useDrag } from 'react-dnd';
3
+ import { useDragDropContextInternal } from './drag-drop-context';
4
+
5
+ export interface iDraggedItemType<DragType extends string> {
6
+ type: DragType;
7
+ }
8
+ export interface iDraggableProps<ItemType extends iDraggedItemType<string>> {
9
+ item: ItemType;
10
+ onBeginDrag?: () => void;
11
+ onEndDrag?: (dropResult: any) => void;
12
+ }
13
+
14
+ export function useDraggable<ItemType extends iDraggedItemType<string>>(props?: iDraggableProps<ItemType>): {
15
+ isDragging: boolean;
16
+ dragRef: ConnectDragSource
17
+ } {
18
+ const {
19
+ item,
20
+ onBeginDrag,
21
+ onEndDrag,
22
+ } = props || {
23
+ item: {
24
+ type: "~invalid~"
25
+ }
26
+ };
27
+
28
+ const dragDropContext = useDragDropContextInternal();
29
+
30
+ const [{ isDragging }, dragRef] = useDrag(
31
+ () => ({
32
+ type: item.type,
33
+ item,
34
+ collect: (monitor: DragSourceMonitor) => ({
35
+ isDragging: monitor.isDragging(),
36
+ }),
37
+ end: (item, monitor) => {
38
+ dragDropContext.setIsDragging(false);
39
+ onEndDrag && onEndDrag(monitor.getDropResult());
40
+ },
41
+ }),
42
+ [item, item.type]
43
+ );
44
+
45
+ useEffect(() => {
46
+ if (isDragging) {
47
+ dragDropContext.setIsDragging(true);
48
+ onBeginDrag && onBeginDrag();
49
+ }
50
+ }, [isDragging, onBeginDrag])
51
+
52
+ return {
53
+ isDragging,
54
+ dragRef,
55
+ };
56
+ }
@@ -0,0 +1,48 @@
1
+ import { ConnectDropTarget, DropTargetMonitor, useDrop } from 'react-dnd';
2
+ import { iDraggedItemType } from './use-draggable';
3
+
4
+ export interface iDroppableProps<DropTypes extends string, ItemTypes extends iDraggedItemType<DropTypes>> {
5
+ acceptTypes: DropTypes[];
6
+ onItemDrop: (item: ItemTypes) => void;
7
+ onHover?: (item: ItemTypes) => void;
8
+ onDrop?: () => void;
9
+ }
10
+
11
+ function useDroppable<DropType extends string, ItemType extends iDraggedItemType<DropType>>(props?: iDroppableProps<DropType, ItemType>): {
12
+ canDrop: boolean;
13
+ isOver: boolean;
14
+ dropRef: ConnectDropTarget;
15
+ } {
16
+ const {
17
+ acceptTypes,
18
+ onItemDrop,
19
+ onHover,
20
+ onDrop,
21
+ } = props || {
22
+ acceptTypes: [],
23
+ onItemDrop: () => { }
24
+ };
25
+
26
+ const [{ canDrop, isOver }, dropRef] = useDrop({
27
+ accept: acceptTypes,
28
+ drop: (item: ItemType) => {
29
+ onItemDrop(item);
30
+ onDrop?.();
31
+ },
32
+ hover: (item: ItemType) => {
33
+ onHover?.(item);
34
+ },
35
+ collect: (monitor: DropTargetMonitor) => ({
36
+ canDrop: monitor.canDrop(),
37
+ isOver: monitor.isOver(),
38
+ }),
39
+ });
40
+
41
+ return {
42
+ canDrop,
43
+ isOver,
44
+ dropRef,
45
+ };
46
+ }
47
+
48
+ export default useDroppable;
package/src/index.ts CHANGED
@@ -21,6 +21,7 @@ export * from './controls/vertical';
21
21
  export * from './controls/vertical-content';
22
22
  export { KWIZFluentContext, useKWIZFluentContext } from './helpers/context';
23
23
  export type { iKWIZFluentContext } from './helpers/context';
24
+ export * from './helpers/drag-drop/exports';
24
25
  export * from './helpers/hooks';
25
26
  export { KnownClassNames } from './styles/styles';
26
27