@kwiz/fluentui 1.0.22 → 1.0.24

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 (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