From d0c5e99558f274db8b45d0a12cfaac5458731d87 Mon Sep 17 00:00:00 2001 From: Sean Colsen Date: Tue, 22 Mar 2022 09:17:54 -0400 Subject: [PATCH 1/5] Add ContextMenu component --- .../common/actions/popper.ts | 70 +++++++------- .../context-menu/ContextMenu.svelte | 96 +++++++++++++++++++ .../__meta__/ContextMenu.stories.svelte | 64 +++++++++++++ 3 files changed, 196 insertions(+), 34 deletions(-) create mode 100644 mathesar_ui/src/component-library/context-menu/ContextMenu.svelte create mode 100644 mathesar_ui/src/component-library/context-menu/__meta__/ContextMenu.stories.svelte diff --git a/mathesar_ui/src/component-library/common/actions/popper.ts b/mathesar_ui/src/component-library/common/actions/popper.ts index ed92898192..956a95cc45 100644 --- a/mathesar_ui/src/component-library/common/actions/popper.ts +++ b/mathesar_ui/src/component-library/common/actions/popper.ts @@ -4,55 +4,57 @@ import type { ModifierArguments, Options, Instance, + VirtualElement, } from '@popperjs/core/lib/types'; import type { Action } from './types'; export default function popper( node: HTMLElement, actionOpts: { - reference: HTMLElement; + reference: VirtualElement; options?: Partial; }, ): Action { let popperInstance: Instance; let prevReference: HTMLElement | undefined; - function create(reference: HTMLElement, options?: Partial) { - if (reference) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-call - popperInstance = createPopper(reference, node, { - placement: options?.placement || 'bottom-start', - modifiers: [ - { - name: 'setMinWidth', - enabled: true, - phase: 'beforeWrite', - requires: ['computeStyles'], - // @ts-ignore: https://github.com/centerofci/mathesar/issues/1055 - fn: (obj: ModifierArguments): void => { - // eslint-disable-next-line no-param-reassign - obj.state.styles.popper.minWidth = `${obj.state.rects.reference.width}px`; - }, - // @ts-ignore: https://github.com/centerofci/mathesar/issues/1055 - effect: (obj: ModifierArguments): void => { - const width = (obj.state.elements.reference as HTMLElement) - .offsetWidth; - // eslint-disable-next-line no-param-reassign - obj.state.elements.popper.style.minWidth = `${width}px`; - }, + function create(reference?: VirtualElement, options?: Partial) { + if (!reference) { + return; + } + // eslint-disable-next-line @typescript-eslint/no-unsafe-call + popperInstance = createPopper(reference, node, { + placement: options?.placement || 'bottom-start', + modifiers: [ + { + name: 'setMinWidth', + enabled: true, + phase: 'beforeWrite', + requires: ['computeStyles'], + // @ts-ignore: https://github.com/centerofci/mathesar/issues/1055 + fn: (obj: ModifierArguments): void => { + // eslint-disable-next-line no-param-reassign + obj.state.styles.popper.minWidth = `${obj.state.rects.reference.width}px`; }, - { - name: 'flip', + // @ts-ignore: https://github.com/centerofci/mathesar/issues/1055 + effect: (obj: ModifierArguments): void => { + const width = (obj.state.elements.reference as HTMLElement) + .offsetWidth; + // eslint-disable-next-line no-param-reassign + obj.state.elements.popper.style.minWidth = `${width}px`; }, - { - name: 'offset', - options: { - offset: [0, 0], - }, + }, + { + name: 'flip', + }, + { + name: 'offset', + options: { + offset: [0, 0], }, - ], - }) as Instance; - } + }, + ], + }) as Instance; } function destroy() { diff --git a/mathesar_ui/src/component-library/context-menu/ContextMenu.svelte b/mathesar_ui/src/component-library/context-menu/ContextMenu.svelte new file mode 100644 index 0000000000..98b4cf6a6b --- /dev/null +++ b/mathesar_ui/src/component-library/context-menu/ContextMenu.svelte @@ -0,0 +1,96 @@ + + +
+ {#if isVisible} + + {/if} +
+ + diff --git a/mathesar_ui/src/component-library/context-menu/__meta__/ContextMenu.stories.svelte b/mathesar_ui/src/component-library/context-menu/__meta__/ContextMenu.stories.svelte new file mode 100644 index 0000000000..31a1d1a999 --- /dev/null +++ b/mathesar_ui/src/component-library/context-menu/__meta__/ContextMenu.stories.svelte @@ -0,0 +1,64 @@ + + + + + +
+

This box does not have a context menu.

+
+ +
+

This box has a context menu.

+

The count is: {count}.

+ + + + Use Background + + + Increment Counter + + +
+ +
+

This box does not have a context menu.

+
+
+ + From 8dce98987810e8c4b2c2e081bee8c44f1559b277 Mon Sep 17 00:00:00 2001 From: Sean Colsen Date: Tue, 22 Mar 2022 12:06:19 -0400 Subject: [PATCH 2/5] Add ContextMenu to index.ts --- mathesar_ui/src/component-library/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/mathesar_ui/src/component-library/index.ts b/mathesar_ui/src/component-library/index.ts index 7d26293397..51f02a5e33 100644 --- a/mathesar_ui/src/component-library/index.ts +++ b/mathesar_ui/src/component-library/index.ts @@ -10,6 +10,7 @@ export { default as Button } from './button/Button.svelte'; export { default as CancelOrProceedButtonPair } from './cancel-or-proceed-button-pair/CancelOrProceedButtonPair.svelte'; export { default as Checkbox } from './checkbox/Checkbox.svelte'; export { default as CheckboxGroup } from './checkbox-group/CheckboxGroup.svelte'; +export { default as ContextMenu } from './context-menu/ContextMenu.svelte'; export { default as Help } from './help/Help.svelte'; export { default as Icon } from './icon/Icon.svelte'; export { InputGroup, InputGroupText } from './input-group'; From 8e89315034fa0caf5b0621d4f354ccdbd760c573 Mon Sep 17 00:00:00 2001 From: Sean Colsen Date: Tue, 22 Mar 2022 13:59:00 -0400 Subject: [PATCH 3/5] Close old context menus on open new context menu Make sure that multiple context menus can't be open at the same time. --- .../common/actions/clickOffBounds.ts | 4 ++-- .../__meta__/ContextMenu.stories.svelte | 13 ++++++++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/mathesar_ui/src/component-library/common/actions/clickOffBounds.ts b/mathesar_ui/src/component-library/common/actions/clickOffBounds.ts index 3cb3d27353..7c511b2a30 100644 --- a/mathesar_ui/src/component-library/common/actions/clickOffBounds.ts +++ b/mathesar_ui/src/component-library/common/actions/clickOffBounds.ts @@ -25,7 +25,7 @@ export default function clickOffBounds( } } - document.body.addEventListener('click', outOfBoundsListener, true); + document.body.addEventListener('pointerdown', outOfBoundsListener, true); function update(opts: Options) { callback = opts.callback; @@ -33,7 +33,7 @@ export default function clickOffBounds( } function destroy() { - document.body.removeEventListener('click', outOfBoundsListener, true); + document.body.removeEventListener('pointerdown', outOfBoundsListener, true); } return { diff --git a/mathesar_ui/src/component-library/context-menu/__meta__/ContextMenu.stories.svelte b/mathesar_ui/src/component-library/context-menu/__meta__/ContextMenu.stories.svelte index 31a1d1a999..b380a47bcd 100644 --- a/mathesar_ui/src/component-library/context-menu/__meta__/ContextMenu.stories.svelte +++ b/mathesar_ui/src/component-library/context-menu/__meta__/ContextMenu.stories.svelte @@ -1,5 +1,9 @@