svelte-flexiboards 0.4.0 → 0.4.2
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.
- package/LICENSE.md +21 -0
- package/README.md +15 -15
- package/dist/components/flexi-add.svelte +74 -86
- package/dist/components/flexi-add.svelte.d.ts +0 -12
- package/dist/components/flexi-announcer.svelte +24 -24
- package/dist/components/flexi-board.svelte +58 -58
- package/dist/components/flexi-delete.svelte +54 -66
- package/dist/components/flexi-grab.svelte +28 -28
- package/dist/components/flexi-grid.svelte +27 -27
- package/dist/components/flexi-layout-loader.svelte +10 -10
- package/dist/components/flexi-portal.svelte +14 -14
- package/dist/components/flexi-resize.svelte +30 -30
- package/dist/components/flexi-target-loader.svelte +14 -14
- package/dist/components/flexi-target.svelte +104 -104
- package/dist/components/flexi-widget.svelte +81 -81
- package/dist/components/rendered-flexi-widget.svelte +64 -64
- package/dist/components/responsive-flexi-board.svelte +83 -83
- package/dist/components/widget-transition-placeholder.svelte +12 -12
- package/dist/system/board/controller.svelte.d.ts +8 -8
- package/dist/system/board/controller.svelte.js +4 -0
- package/dist/system/internal-types.d.ts +109 -0
- package/dist/system/internal-types.js +1 -0
- package/dist/system/misc/adder.svelte.d.ts +2 -2
- package/dist/system/portal.d.ts +3 -3
- package/dist/system/shared/event-bus.d.ts +15 -14
- package/dist/system/shared/utils.svelte.d.ts +6 -3
- package/dist/system/shared/utils.svelte.js +49 -32
- package/dist/system/target/controller.svelte.d.ts +12 -11
- package/dist/system/target/controller.svelte.js +25 -22
- package/dist/system/target/types.d.ts +2 -2
- package/dist/system/types.d.ts +26 -27
- package/dist/system/widget/controller.svelte.d.ts +6 -6
- package/dist/system/widget/controller.svelte.js +1 -2
- package/dist/system/widget/triggers.svelte.js +9 -0
- package/package.json +60 -61
|
@@ -1,83 +1,83 @@
|
|
|
1
|
-
<script module lang="ts">
|
|
2
|
-
import { onDestroy, type Snippet } from 'svelte';
|
|
3
|
-
import type { FlexiCommonProps } from '../system/types.js';
|
|
4
|
-
import type { ResponsiveFlexiBoardController } from '../system/responsive/base.svelte.js';
|
|
5
|
-
import type { ResponsiveFlexiBoardConfiguration } from '../system/responsive/types.js';
|
|
6
|
-
|
|
7
|
-
export type BreakpointSnippetParams = { currentBreakpoint: string };
|
|
8
|
-
|
|
9
|
-
export type ResponsiveFlexiBoardProps = FlexiCommonProps<ResponsiveFlexiBoardController> & {
|
|
10
|
-
config?: ResponsiveFlexiBoardConfiguration;
|
|
11
|
-
/**
|
|
12
|
-
* Snippet for large breakpoint (no params - breakpoint is implicit).
|
|
13
|
-
*/
|
|
14
|
-
lg?: Snippet;
|
|
15
|
-
/**
|
|
16
|
-
* Snippet for medium breakpoint (no params - breakpoint is implicit).
|
|
17
|
-
*/
|
|
18
|
-
md?: Snippet;
|
|
19
|
-
/**
|
|
20
|
-
* Snippet for small breakpoint (no params - breakpoint is implicit).
|
|
21
|
-
*/
|
|
22
|
-
sm?: Snippet;
|
|
23
|
-
/**
|
|
24
|
-
* Snippet for extra-small breakpoint (no params - breakpoint is implicit).
|
|
25
|
-
*/
|
|
26
|
-
xs?: Snippet;
|
|
27
|
-
/**
|
|
28
|
-
* Children snippet used as fallback when no specific breakpoint snippet matches.
|
|
29
|
-
* Receives `{ currentBreakpoint: string }` as a parameter.
|
|
30
|
-
*/
|
|
31
|
-
children?: Snippet<[BreakpointSnippetParams]>;
|
|
32
|
-
};
|
|
33
|
-
</script>
|
|
34
|
-
|
|
35
|
-
<script lang="ts">
|
|
36
|
-
import { responsiveflexiboard } from '../system/responsive/index.js';
|
|
37
|
-
|
|
38
|
-
let {
|
|
39
|
-
controller = $bindable(),
|
|
40
|
-
onfirstcreate,
|
|
41
|
-
config,
|
|
42
|
-
lg,
|
|
43
|
-
md,
|
|
44
|
-
sm,
|
|
45
|
-
xs,
|
|
46
|
-
children
|
|
47
|
-
}: ResponsiveFlexiBoardProps = $props();
|
|
48
|
-
|
|
49
|
-
const board = responsiveflexiboard({ config });
|
|
50
|
-
controller = board;
|
|
51
|
-
|
|
52
|
-
// Load layouts immediately so child FlexiBoards can access them
|
|
53
|
-
board.oninitialloadcomplete();
|
|
54
|
-
|
|
55
|
-
onfirstcreate?.(board);
|
|
56
|
-
|
|
57
|
-
// Map breakpoint names to snippets (without params)
|
|
58
|
-
const snippets: Record<string, Snippet | undefined> = $derived({
|
|
59
|
-
lg,
|
|
60
|
-
md,
|
|
61
|
-
sm,
|
|
62
|
-
xs
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
// Cleanup when component is destroyed
|
|
66
|
-
onDestroy(() => {
|
|
67
|
-
board.destroy();
|
|
68
|
-
});
|
|
69
|
-
</script>
|
|
70
|
-
|
|
71
|
-
<!--
|
|
72
|
-
Key on currentBreakpoint to force re-render when breakpoint changes.
|
|
73
|
-
This ensures the board is re-created with the correct breakpoint context.
|
|
74
|
-
-->
|
|
75
|
-
{#key board.currentBreakpoint}
|
|
76
|
-
{#if snippets[board.currentBreakpoint]}
|
|
77
|
-
<!-- Specific breakpoint snippet (no params) -->
|
|
78
|
-
{@render snippets[board.currentBreakpoint]!()}
|
|
79
|
-
{:else if children}
|
|
80
|
-
<!-- Children snippet receives { currentBreakpoint } -->
|
|
81
|
-
{@render children({ currentBreakpoint: board.currentBreakpoint })}
|
|
82
|
-
{/if}
|
|
83
|
-
{/key}
|
|
1
|
+
<script module lang="ts">
|
|
2
|
+
import { onDestroy, type Snippet } from 'svelte';
|
|
3
|
+
import type { FlexiCommonProps } from '../system/types.js';
|
|
4
|
+
import type { ResponsiveFlexiBoardController } from '../system/responsive/base.svelte.js';
|
|
5
|
+
import type { ResponsiveFlexiBoardConfiguration } from '../system/responsive/types.js';
|
|
6
|
+
|
|
7
|
+
export type BreakpointSnippetParams = { currentBreakpoint: string };
|
|
8
|
+
|
|
9
|
+
export type ResponsiveFlexiBoardProps = FlexiCommonProps<ResponsiveFlexiBoardController> & {
|
|
10
|
+
config?: ResponsiveFlexiBoardConfiguration;
|
|
11
|
+
/**
|
|
12
|
+
* Snippet for large breakpoint (no params - breakpoint is implicit).
|
|
13
|
+
*/
|
|
14
|
+
lg?: Snippet;
|
|
15
|
+
/**
|
|
16
|
+
* Snippet for medium breakpoint (no params - breakpoint is implicit).
|
|
17
|
+
*/
|
|
18
|
+
md?: Snippet;
|
|
19
|
+
/**
|
|
20
|
+
* Snippet for small breakpoint (no params - breakpoint is implicit).
|
|
21
|
+
*/
|
|
22
|
+
sm?: Snippet;
|
|
23
|
+
/**
|
|
24
|
+
* Snippet for extra-small breakpoint (no params - breakpoint is implicit).
|
|
25
|
+
*/
|
|
26
|
+
xs?: Snippet;
|
|
27
|
+
/**
|
|
28
|
+
* Children snippet used as fallback when no specific breakpoint snippet matches.
|
|
29
|
+
* Receives `{ currentBreakpoint: string }` as a parameter.
|
|
30
|
+
*/
|
|
31
|
+
children?: Snippet<[BreakpointSnippetParams]>;
|
|
32
|
+
};
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
<script lang="ts">
|
|
36
|
+
import { responsiveflexiboard } from '../system/responsive/index.js';
|
|
37
|
+
|
|
38
|
+
let {
|
|
39
|
+
controller = $bindable(),
|
|
40
|
+
onfirstcreate,
|
|
41
|
+
config,
|
|
42
|
+
lg,
|
|
43
|
+
md,
|
|
44
|
+
sm,
|
|
45
|
+
xs,
|
|
46
|
+
children
|
|
47
|
+
}: ResponsiveFlexiBoardProps = $props();
|
|
48
|
+
|
|
49
|
+
const board = responsiveflexiboard({ config });
|
|
50
|
+
controller = board;
|
|
51
|
+
|
|
52
|
+
// Load layouts immediately so child FlexiBoards can access them
|
|
53
|
+
board.oninitialloadcomplete();
|
|
54
|
+
|
|
55
|
+
onfirstcreate?.(board);
|
|
56
|
+
|
|
57
|
+
// Map breakpoint names to snippets (without params)
|
|
58
|
+
const snippets: Record<string, Snippet | undefined> = $derived({
|
|
59
|
+
lg,
|
|
60
|
+
md,
|
|
61
|
+
sm,
|
|
62
|
+
xs
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// Cleanup when component is destroyed
|
|
66
|
+
onDestroy(() => {
|
|
67
|
+
board.destroy();
|
|
68
|
+
});
|
|
69
|
+
</script>
|
|
70
|
+
|
|
71
|
+
<!--
|
|
72
|
+
Key on currentBreakpoint to force re-render when breakpoint changes.
|
|
73
|
+
This ensures the board is re-created with the correct breakpoint context.
|
|
74
|
+
-->
|
|
75
|
+
{#key board.currentBreakpoint}
|
|
76
|
+
{#if snippets[board.currentBreakpoint]}
|
|
77
|
+
<!-- Specific breakpoint snippet (no params) -->
|
|
78
|
+
{@render snippets[board.currentBreakpoint]!()}
|
|
79
|
+
{:else if children}
|
|
80
|
+
<!-- Children snippet receives { currentBreakpoint } -->
|
|
81
|
+
{@render children({ currentBreakpoint: board.currentBreakpoint })}
|
|
82
|
+
{/if}
|
|
83
|
+
{/key}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { getFlexiwidgetInterpolatorCtx } from '../system/widget/index.js';
|
|
3
|
-
import { onMount } from 'svelte';
|
|
4
|
-
|
|
5
|
-
const interpolator = getFlexiwidgetInterpolatorCtx();
|
|
6
|
-
|
|
7
|
-
let ref: HTMLElement;
|
|
8
|
-
|
|
9
|
-
onMount(() => interpolator.onPlaceholderMount(ref));
|
|
10
|
-
</script>
|
|
11
|
-
|
|
12
|
-
<div style={interpolator.placeholderStyle} bind:this={ref}></div>
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { getFlexiwidgetInterpolatorCtx } from '../system/widget/index.js';
|
|
3
|
+
import { onMount } from 'svelte';
|
|
4
|
+
|
|
5
|
+
const interpolator = getFlexiwidgetInterpolatorCtx();
|
|
6
|
+
|
|
7
|
+
let ref: HTMLElement;
|
|
8
|
+
|
|
9
|
+
onMount(() => interpolator.onPlaceholderMount(ref));
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<div style={interpolator.placeholderStyle} bind:this={ref}></div>
|
|
@@ -3,7 +3,7 @@ import type { AriaPoliteness, FlexiAnnouncerController } from '../announcer.svel
|
|
|
3
3
|
import type { FlexiPortalController } from '../portal.js';
|
|
4
4
|
import { InternalFlexiTargetController } from '../target/controller.svelte.js';
|
|
5
5
|
import type { FlexiTargetPartialConfiguration } from '../target/types.js';
|
|
6
|
-
import type {
|
|
6
|
+
import type { InternalTargetEvent, InternalWidgetAction, InternalWidgetEvent, InternalWidgetGrabbedEvent, InternalWidgetResizingEvent } from '../internal-types.js';
|
|
7
7
|
import type { FlexiBoardController } from './base.svelte.js';
|
|
8
8
|
import type { FlexiBoardConfiguration, FlexiRegistryEntry, FlexiLayout } from './types.js';
|
|
9
9
|
import type { InternalFlexiWidgetController } from '../widget/controller.svelte.js';
|
|
@@ -22,14 +22,14 @@ export declare class InternalFlexiBoardController implements FlexiBoardControlle
|
|
|
22
22
|
get ref(): HTMLElement | null;
|
|
23
23
|
set ref(ref: HTMLElement | null);
|
|
24
24
|
createTarget(config?: FlexiTargetPartialConfiguration, key?: string): InternalFlexiTargetController;
|
|
25
|
-
onPointerEnterTarget(event:
|
|
26
|
-
onPointerLeaveTarget(event:
|
|
25
|
+
onPointerEnterTarget(event: InternalTargetEvent): void;
|
|
26
|
+
onPointerLeaveTarget(event: InternalTargetEvent): void;
|
|
27
27
|
onenterdeleter(): void;
|
|
28
28
|
onleavedeleter(): void;
|
|
29
|
-
onWidgetGrabbed(event:
|
|
30
|
-
onWidgetResizing(event:
|
|
31
|
-
handleWidgetRelease(event:
|
|
32
|
-
handleWidgetCancel(event:
|
|
29
|
+
onWidgetGrabbed(event: InternalWidgetGrabbedEvent): void;
|
|
30
|
+
onWidgetResizing(event: InternalWidgetResizingEvent): void;
|
|
31
|
+
handleWidgetRelease(event: InternalWidgetEvent): void;
|
|
32
|
+
handleWidgetCancel(event: InternalWidgetEvent): void;
|
|
33
33
|
attachAnnouncer(announcer: FlexiAnnouncerController): void;
|
|
34
34
|
announce(message: string, politeness?: AriaPoliteness): void;
|
|
35
35
|
oninitialloadcomplete(): void;
|
|
@@ -54,7 +54,7 @@ export declare class InternalFlexiBoardController implements FlexiBoardControlle
|
|
|
54
54
|
* @param to The target to move the widget to.
|
|
55
55
|
*/
|
|
56
56
|
moveWidget(widget: InternalFlexiWidgetController, from: InternalFlexiTargetController | undefined, to: InternalFlexiTargetController): boolean;
|
|
57
|
-
get currentWidgetAction():
|
|
57
|
+
get currentWidgetAction(): InternalWidgetAction | null;
|
|
58
58
|
/**
|
|
59
59
|
* Returns the parent responsive controller if this board is within a ResponsiveFlexiBoard.
|
|
60
60
|
*/
|
|
@@ -58,6 +58,10 @@ export class InternalFlexiBoardController {
|
|
|
58
58
|
if (event.board !== this) {
|
|
59
59
|
return;
|
|
60
60
|
}
|
|
61
|
+
// No point exporting if nobody is listening
|
|
62
|
+
if (!this.config?.onLayoutChange && !this.#responsiveController) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
61
65
|
// Debounce the callback
|
|
62
66
|
if (this.#layoutChangeTimeout) {
|
|
63
67
|
clearTimeout(this.#layoutChangeTimeout);
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import type { FlexiLayout } from './board/types.js';
|
|
2
|
+
import type { InternalFlexiBoardController } from './board/controller.svelte.js';
|
|
3
|
+
import type { InternalFlexiAddController } from './misc/adder.svelte.js';
|
|
4
|
+
import type { InternalResponsiveFlexiBoardController } from './responsive/controller.svelte.js';
|
|
5
|
+
import type { InternalFlexiTargetController } from './target/controller.svelte.js';
|
|
6
|
+
import type { InternalFlexiWidgetController } from './widget/controller.svelte.js';
|
|
7
|
+
import type { Position } from './types.js';
|
|
8
|
+
export type InternalWidgetGrabAction = {
|
|
9
|
+
action: 'grab';
|
|
10
|
+
widget: InternalFlexiWidgetController;
|
|
11
|
+
offsetX: number;
|
|
12
|
+
offsetY: number;
|
|
13
|
+
capturedHeightPx: number;
|
|
14
|
+
capturedWidthPx: number;
|
|
15
|
+
};
|
|
16
|
+
export type InternalWidgetResizeAction = {
|
|
17
|
+
action: 'resize';
|
|
18
|
+
widget: InternalFlexiWidgetController;
|
|
19
|
+
offsetX: number;
|
|
20
|
+
offsetY: number;
|
|
21
|
+
left: number;
|
|
22
|
+
top: number;
|
|
23
|
+
capturedHeightPx: number;
|
|
24
|
+
capturedWidthPx: number;
|
|
25
|
+
initialHeightUnits: number;
|
|
26
|
+
initialWidthUnits: number;
|
|
27
|
+
};
|
|
28
|
+
export type InternalWidgetAction = InternalWidgetGrabAction | InternalWidgetResizeAction;
|
|
29
|
+
export type InternalWidgetGrabbedParams = {
|
|
30
|
+
widget: InternalFlexiWidgetController;
|
|
31
|
+
ref: HTMLElement;
|
|
32
|
+
xOffset: number;
|
|
33
|
+
yOffset: number;
|
|
34
|
+
clientX: number;
|
|
35
|
+
clientY: number;
|
|
36
|
+
capturedHeight: number;
|
|
37
|
+
capturedWidth: number;
|
|
38
|
+
};
|
|
39
|
+
export type InternalWidgetStartResizeParams = {
|
|
40
|
+
widget: InternalFlexiWidgetController;
|
|
41
|
+
xOffset: number;
|
|
42
|
+
yOffset: number;
|
|
43
|
+
left: number;
|
|
44
|
+
top: number;
|
|
45
|
+
heightPx: number;
|
|
46
|
+
widthPx: number;
|
|
47
|
+
};
|
|
48
|
+
export type InternalAdderWidgetReadyEvent = {
|
|
49
|
+
adder: InternalFlexiAddController;
|
|
50
|
+
widget: InternalFlexiWidgetController;
|
|
51
|
+
};
|
|
52
|
+
export type InternalWidgetEvent = {
|
|
53
|
+
target?: InternalFlexiTargetController;
|
|
54
|
+
board: InternalFlexiBoardController;
|
|
55
|
+
widget: InternalFlexiWidgetController;
|
|
56
|
+
};
|
|
57
|
+
export type InternalWidgetGrabbedEvent = InternalWidgetEvent & {
|
|
58
|
+
clientX: number;
|
|
59
|
+
clientY: number;
|
|
60
|
+
xOffset: number;
|
|
61
|
+
yOffset: number;
|
|
62
|
+
capturedHeightPx: number;
|
|
63
|
+
capturedWidthPx: number;
|
|
64
|
+
};
|
|
65
|
+
export type InternalWidgetResizingEvent = InternalWidgetEvent & {
|
|
66
|
+
target: InternalFlexiTargetController;
|
|
67
|
+
offsetX: number;
|
|
68
|
+
offsetY: number;
|
|
69
|
+
clientX: number;
|
|
70
|
+
clientY: number;
|
|
71
|
+
left: number;
|
|
72
|
+
top: number;
|
|
73
|
+
capturedHeightPx: number;
|
|
74
|
+
capturedWidthPx: number;
|
|
75
|
+
};
|
|
76
|
+
export type InternalWidgetDroppedEvent = {
|
|
77
|
+
widget: InternalFlexiWidgetController;
|
|
78
|
+
board: InternalFlexiBoardController;
|
|
79
|
+
oldTarget?: InternalFlexiTargetController;
|
|
80
|
+
newTarget?: InternalFlexiTargetController;
|
|
81
|
+
};
|
|
82
|
+
export type InternalWidgetStartResizeEvent = InternalWidgetStartResizeParams & {
|
|
83
|
+
target: InternalFlexiTargetController;
|
|
84
|
+
};
|
|
85
|
+
export type InternalWidgetOverEvent = {
|
|
86
|
+
widget: InternalFlexiWidgetController;
|
|
87
|
+
mousePosition: Position;
|
|
88
|
+
};
|
|
89
|
+
export type InternalWidgetOutEvent = {
|
|
90
|
+
widget: InternalFlexiWidgetController;
|
|
91
|
+
};
|
|
92
|
+
export type InternalTargetEvent = {
|
|
93
|
+
board: InternalFlexiBoardController;
|
|
94
|
+
target: InternalFlexiTargetController;
|
|
95
|
+
};
|
|
96
|
+
export type InternalGrabbedWidgetMouseEvent = {
|
|
97
|
+
widget: InternalFlexiWidgetController;
|
|
98
|
+
};
|
|
99
|
+
export type InternalHoveredTargetEvent = {
|
|
100
|
+
target: InternalFlexiTargetController;
|
|
101
|
+
};
|
|
102
|
+
export type InternalBoardLayoutChangeEvent = {
|
|
103
|
+
board: InternalFlexiBoardController;
|
|
104
|
+
layout: FlexiLayout;
|
|
105
|
+
breakpoint?: string;
|
|
106
|
+
};
|
|
107
|
+
export type InternalResponsiveLayoutImportEvent = {
|
|
108
|
+
responsiveController: InternalResponsiveFlexiBoardController;
|
|
109
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ClassValue } from 'svelte/elements';
|
|
2
2
|
import type { InternalFlexiBoardController } from '../board/controller.svelte.js';
|
|
3
|
-
import type {
|
|
3
|
+
import type { InternalAdderWidgetReadyEvent } from '../internal-types.js';
|
|
4
4
|
import { InternalFlexiWidgetController } from '../widget/controller.svelte.js';
|
|
5
5
|
import type { FlexiWidgetConfiguration } from '../widget/index.js';
|
|
6
6
|
export type FlexiAddWidgetFn = () => AdderWidgetConfiguration | null;
|
|
@@ -29,7 +29,7 @@ export declare class InternalFlexiAddController implements FlexiAddController {
|
|
|
29
29
|
constructor(provider: InternalFlexiBoardController, addWidgetFn: FlexiAddWidgetFn);
|
|
30
30
|
onpointerdown(event: PointerEvent): void;
|
|
31
31
|
onkeydown(event: KeyboardEvent): void;
|
|
32
|
-
onWidgetReady(event:
|
|
32
|
+
onWidgetReady(event: InternalAdderWidgetReadyEvent): void;
|
|
33
33
|
onWidgetDragInComplete(event: {
|
|
34
34
|
widget: InternalFlexiWidgetController;
|
|
35
35
|
}): void;
|
package/dist/system/portal.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { InternalWidgetEvent, InternalWidgetGrabbedEvent } from './internal-types.js';
|
|
2
2
|
import type { FlexiWidgetController } from './widget/index.js';
|
|
3
3
|
/**
|
|
4
4
|
* GrabbedPortal manages a single container in the DOM where grabbed/resizing
|
|
@@ -8,8 +8,8 @@ export declare class FlexiPortalController {
|
|
|
8
8
|
#private;
|
|
9
9
|
constructor();
|
|
10
10
|
createPortal(): void;
|
|
11
|
-
onWidgetGrabbed(event:
|
|
12
|
-
onWidgetRelease(event:
|
|
11
|
+
onWidgetGrabbed(event: InternalWidgetGrabbedEvent): void;
|
|
12
|
+
onWidgetRelease(event: InternalWidgetEvent): void;
|
|
13
13
|
/**
|
|
14
14
|
* Moves a widget's DOM element to the portal container
|
|
15
15
|
*/
|
|
@@ -1,19 +1,20 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { InternalAdderWidgetReadyEvent, InternalBoardLayoutChangeEvent, InternalResponsiveLayoutImportEvent, InternalTargetEvent, InternalWidgetDroppedEvent, InternalWidgetEvent, InternalWidgetGrabbedEvent, InternalWidgetResizingEvent } from '../internal-types.js';
|
|
2
|
+
import type { PointerMovedEvent } from '../types.js';
|
|
2
3
|
export interface EventMap {
|
|
3
|
-
'widget:grabbed':
|
|
4
|
-
'widget:resizing':
|
|
5
|
-
'widget:release':
|
|
6
|
-
'widget:cancel':
|
|
7
|
-
'widget:dropped':
|
|
8
|
-
'widget:delete':
|
|
9
|
-
'target:pointerenter':
|
|
10
|
-
'target:pointerleave':
|
|
11
|
-
'widget:entertarget':
|
|
12
|
-
'widget:leavetarget':
|
|
13
|
-
'adder:widgetready':
|
|
4
|
+
'widget:grabbed': InternalWidgetGrabbedEvent;
|
|
5
|
+
'widget:resizing': InternalWidgetResizingEvent;
|
|
6
|
+
'widget:release': InternalWidgetEvent;
|
|
7
|
+
'widget:cancel': InternalWidgetEvent;
|
|
8
|
+
'widget:dropped': InternalWidgetDroppedEvent;
|
|
9
|
+
'widget:delete': InternalWidgetEvent;
|
|
10
|
+
'target:pointerenter': InternalTargetEvent;
|
|
11
|
+
'target:pointerleave': InternalTargetEvent;
|
|
12
|
+
'widget:entertarget': InternalWidgetEvent;
|
|
13
|
+
'widget:leavetarget': InternalWidgetEvent;
|
|
14
|
+
'adder:widgetready': InternalAdderWidgetReadyEvent;
|
|
14
15
|
'pointer:moved': PointerMovedEvent;
|
|
15
|
-
'board:layoutchange':
|
|
16
|
-
'responsive:layoutimport':
|
|
16
|
+
'board:layoutchange': InternalBoardLayoutChangeEvent;
|
|
17
|
+
'responsive:layoutimport': InternalResponsiveLayoutImportEvent;
|
|
17
18
|
}
|
|
18
19
|
type EventListener<T> = (data: T) => void;
|
|
19
20
|
export declare class FlexiEventBus {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { InternalWidgetEvent } from '../internal-types.js';
|
|
2
|
+
import type { Position, ProxiedValue } from '../types.js';
|
|
2
3
|
import type { FlexiGrid } from '../grid/base.svelte.js';
|
|
3
4
|
import type { FlexiTargetConfiguration } from '../target/types.js';
|
|
4
5
|
/**
|
|
@@ -34,8 +35,8 @@ export declare class AutoScrollService {
|
|
|
34
35
|
#private;
|
|
35
36
|
shouldAutoScroll: boolean;
|
|
36
37
|
constructor(ref: ProxiedValue<HTMLElement | null>);
|
|
37
|
-
startAutoScroll(event:
|
|
38
|
-
stopAutoScroll(event:
|
|
38
|
+
startAutoScroll(event: InternalWidgetEvent): void;
|
|
39
|
+
stopAutoScroll(event: InternalWidgetEvent): void;
|
|
39
40
|
get ref(): HTMLElement | null;
|
|
40
41
|
/**
|
|
41
42
|
* Manually stop continuous scrolling. Useful for external control.
|
|
@@ -60,6 +61,8 @@ export declare class GridDimensionTracker {
|
|
|
60
61
|
refreshScrollListeners(): void;
|
|
61
62
|
getCellFromPointerPosition(clientX: number, clientY: number): CellPosition | null;
|
|
62
63
|
}
|
|
64
|
+
export declare function contentSize(axisCoordinates: number[], gap: number): number;
|
|
65
|
+
export declare function findCell(pointerLocation: number, start: number, size: number, gap: number, axisCoordinates: number[]): number;
|
|
63
66
|
export declare function generateUniqueId(prefix?: string): string;
|
|
64
67
|
export declare const assistiveTextStyle = "\n\tposition: absolute;\n\twidth: 1px;\n\theight: 1px;\n\tpadding: 0;\n\tmargin: -1px;\n\toverflow: hidden;\n\tclip: rect(0, 0, 0, 0);\n\twhite-space: nowrap;\n\tborder-width: 0;\n";
|
|
65
68
|
export declare function getElementMidpoint(element: HTMLElement): {
|
|
@@ -48,7 +48,11 @@ export class PointerService {
|
|
|
48
48
|
isPointerInside(element) {
|
|
49
49
|
const rect = element.getBoundingClientRect();
|
|
50
50
|
const { x, y } = this.#position;
|
|
51
|
-
|
|
51
|
+
// Use scrollWidth/scrollHeight to account for content that overflows the element
|
|
52
|
+
// (e.g. grid columns that extend beyond a scrollable parent with overflow: hidden).
|
|
53
|
+
const width = Math.max(rect.width, element.scrollWidth);
|
|
54
|
+
const height = Math.max(rect.height, element.scrollHeight);
|
|
55
|
+
return x >= rect.left && x <= rect.left + width && y >= rect.top && y <= rect.top + height;
|
|
52
56
|
}
|
|
53
57
|
get keyboardControlsActive() {
|
|
54
58
|
return this.#keyboardController.active;
|
|
@@ -557,9 +561,9 @@ export class GridDimensionTracker {
|
|
|
557
561
|
const style = window.getComputedStyle(parent);
|
|
558
562
|
const overflowY = style.getPropertyValue('overflow-y');
|
|
559
563
|
const overflowX = style.getPropertyValue('overflow-x');
|
|
560
|
-
const isScrollable = ((overflowY === 'auto' || overflowY === 'scroll') &&
|
|
564
|
+
const isScrollable = ((overflowY === 'auto' || overflowY === 'scroll' || overflowY === 'hidden') &&
|
|
561
565
|
parent.scrollHeight > parent.clientHeight) ||
|
|
562
|
-
((overflowX === 'auto' || overflowX === 'scroll') &&
|
|
566
|
+
((overflowX === 'auto' || overflowX === 'scroll' || overflowX === 'hidden') &&
|
|
563
567
|
parent.scrollWidth > parent.clientWidth);
|
|
564
568
|
if (isScrollable) {
|
|
565
569
|
ancestors.push(parent);
|
|
@@ -574,48 +578,61 @@ export class GridDimensionTracker {
|
|
|
574
578
|
}
|
|
575
579
|
this.#pointerPosition.x = clientX;
|
|
576
580
|
this.#pointerPosition.y = clientY;
|
|
577
|
-
|
|
578
|
-
|
|
581
|
+
// DEBUG: trace scroll offset issue
|
|
582
|
+
const gridRef = this.#grid.ref;
|
|
583
|
+
const freshRect = gridRef.getBoundingClientRect();
|
|
584
|
+
// Walk up to find the scrollable parent (board element)
|
|
585
|
+
let scrollParent = gridRef.parentElement;
|
|
586
|
+
while (scrollParent && scrollParent.scrollLeft === 0 && scrollParent !== document.documentElement) {
|
|
587
|
+
scrollParent = scrollParent.parentElement;
|
|
588
|
+
}
|
|
589
|
+
let xCell = findCell(clientX, this.#dimensions.left, contentSize(this.#dimensions.columns, this.#dimensions.columnGap), this.#dimensions.columnGap, this.#dimensions.columns);
|
|
590
|
+
let yCell = findCell(clientY, this.#dimensions.top, contentSize(this.#dimensions.rows, this.#dimensions.rowGap), this.#dimensions.rowGap, this.#dimensions.rows);
|
|
579
591
|
return {
|
|
580
592
|
row: yCell,
|
|
581
593
|
column: xCell
|
|
582
594
|
};
|
|
583
595
|
}
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
const proportionAlong = (pointerLocation - base) / (subtotal - base);
|
|
597
|
-
if (pointerLocation < subtotal) {
|
|
598
|
-
return i + proportionAlong;
|
|
599
|
-
}
|
|
600
|
-
}
|
|
596
|
+
}
|
|
597
|
+
export function contentSize(axisCoordinates, gap) {
|
|
598
|
+
const totalCells = axisCoordinates.reduce((sum, size) => sum + size, 0);
|
|
599
|
+
const totalGaps = Math.max(0, axisCoordinates.length - 1) * gap;
|
|
600
|
+
return totalCells + totalGaps;
|
|
601
|
+
}
|
|
602
|
+
export function findCell(pointerLocation, start, size, gap, axisCoordinates) {
|
|
603
|
+
// If outside the axis, then return the ends.
|
|
604
|
+
if (pointerLocation < start) {
|
|
605
|
+
return 0;
|
|
606
|
+
}
|
|
607
|
+
if (pointerLocation >= start + size) {
|
|
601
608
|
return axisCoordinates.length;
|
|
602
609
|
}
|
|
610
|
+
let subtotal = start - gap / 2;
|
|
611
|
+
for (let i = 0; i < axisCoordinates.length; i++) {
|
|
612
|
+
const base = subtotal;
|
|
613
|
+
subtotal += axisCoordinates[i] + gap;
|
|
614
|
+
const proportionAlong = (pointerLocation - base) / (subtotal - base);
|
|
615
|
+
if (pointerLocation < subtotal) {
|
|
616
|
+
return i + proportionAlong;
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
return axisCoordinates.length;
|
|
603
620
|
}
|
|
604
621
|
let uniqueIdIndex = 0;
|
|
605
622
|
export function generateUniqueId(prefix = 'flexi-') {
|
|
606
623
|
return prefix + uniqueIdIndex++;
|
|
607
624
|
}
|
|
608
625
|
/* Adapted from TailwindCSS sr-only */
|
|
609
|
-
export const assistiveTextStyle = `
|
|
610
|
-
position: absolute;
|
|
611
|
-
width: 1px;
|
|
612
|
-
height: 1px;
|
|
613
|
-
padding: 0;
|
|
614
|
-
margin: -1px;
|
|
615
|
-
overflow: hidden;
|
|
616
|
-
clip: rect(0, 0, 0, 0);
|
|
617
|
-
white-space: nowrap;
|
|
618
|
-
border-width: 0;
|
|
626
|
+
export const assistiveTextStyle = `
|
|
627
|
+
position: absolute;
|
|
628
|
+
width: 1px;
|
|
629
|
+
height: 1px;
|
|
630
|
+
padding: 0;
|
|
631
|
+
margin: -1px;
|
|
632
|
+
overflow: hidden;
|
|
633
|
+
clip: rect(0, 0, 0, 0);
|
|
634
|
+
white-space: nowrap;
|
|
635
|
+
border-width: 0;
|
|
619
636
|
`;
|
|
620
637
|
export function getElementMidpoint(element) {
|
|
621
638
|
const rect = element.getBoundingClientRect();
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { FlexiGrid } from '../grid/index.js';
|
|
2
|
-
import type {
|
|
2
|
+
import type { InternalTargetEvent, InternalWidgetDroppedEvent, InternalWidgetEvent, InternalWidgetGrabbedEvent, InternalWidgetResizingEvent } from '../internal-types.js';
|
|
3
|
+
import type { MouseGridCellMoveEvent } from '../types.js';
|
|
3
4
|
import { FlexiWidgetController } from '../widget/base.svelte.js';
|
|
4
5
|
import { InternalFlexiWidgetController } from '../widget/controller.svelte.js';
|
|
5
6
|
import type { FlexiWidgetConfiguration, FlexiWidgetDefaults } from '../widget/types.js';
|
|
@@ -19,7 +20,7 @@ export declare class InternalFlexiTargetController implements FlexiTargetControl
|
|
|
19
20
|
createGrid(): FlexiGrid;
|
|
20
21
|
createWidget(config: FlexiWidgetConfiguration): InternalFlexiWidgetController | undefined;
|
|
21
22
|
registerWidget(config: FlexiWidgetConfiguration, onCreated?: (widget: FlexiWidgetController) => void): void;
|
|
22
|
-
onWidgetDelete(event:
|
|
23
|
+
onWidgetDelete(event: InternalWidgetEvent): void;
|
|
23
24
|
/**
|
|
24
25
|
* Deletes the given widget from this target, if it exists.
|
|
25
26
|
* @returns Whether the widget was deleted.
|
|
@@ -36,8 +37,8 @@ export declare class InternalFlexiTargetController implements FlexiTargetControl
|
|
|
36
37
|
* @returns The layout of widgets.
|
|
37
38
|
*/
|
|
38
39
|
exportLayout(): FlexiWidgetLayoutEntry[];
|
|
39
|
-
onPointerEnterTarget(event:
|
|
40
|
-
onPointerLeaveTarget(event:
|
|
40
|
+
onPointerEnterTarget(event: InternalTargetEvent): void;
|
|
41
|
+
onPointerLeaveTarget(event: InternalTargetEvent): void;
|
|
41
42
|
restorePreGrabSnapshot(): void;
|
|
42
43
|
forgetPreGrabSnapshot(): void;
|
|
43
44
|
hasPreGrabSnapshot(): boolean;
|
|
@@ -45,13 +46,13 @@ export declare class InternalFlexiTargetController implements FlexiTargetControl
|
|
|
45
46
|
cancelDrop(): void;
|
|
46
47
|
tryDropWidget(widget: InternalFlexiWidgetController): boolean;
|
|
47
48
|
onmousegridcellmove(event: MouseGridCellMoveEvent): void;
|
|
48
|
-
onWidgetGrabbed(event:
|
|
49
|
-
onWidgetResizing(event:
|
|
50
|
-
onWidgetCancel(event:
|
|
51
|
-
onWidgetRelease(event:
|
|
52
|
-
onWidgetDropped(event:
|
|
53
|
-
onWidgetEnterTarget(event:
|
|
54
|
-
onWidgetLeaveTarget(event:
|
|
49
|
+
onWidgetGrabbed(event: InternalWidgetGrabbedEvent): void;
|
|
50
|
+
onWidgetResizing(event: InternalWidgetResizingEvent): void;
|
|
51
|
+
onWidgetCancel(event: InternalWidgetEvent): void;
|
|
52
|
+
onWidgetRelease(event: InternalWidgetEvent): void;
|
|
53
|
+
onWidgetDropped(event: InternalWidgetDroppedEvent): void;
|
|
54
|
+
onWidgetEnterTarget(event: InternalWidgetEvent): void;
|
|
55
|
+
onWidgetLeaveTarget(event: InternalWidgetEvent): void;
|
|
55
56
|
oninitialloadcomplete(): void;
|
|
56
57
|
/**
|
|
57
58
|
* Whether the target is currently being hovered over by the mouse.
|