svelte-flexiboards 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/flexi-add.svelte +2 -14
- package/dist/components/flexi-add.svelte.d.ts +0 -12
- package/dist/components/flexi-delete.svelte +0 -12
- package/dist/system/board/controller.svelte.js +4 -0
- package/dist/system/shared/utils.svelte.d.ts +2 -0
- package/dist/system/shared/utils.svelte.js +39 -22
- package/dist/system/target/controller.svelte.js +24 -21
- package/package.json +1 -1
|
@@ -10,21 +10,9 @@
|
|
|
10
10
|
import RenderedFlexiWidget from './rendered-flexi-widget.svelte';
|
|
11
11
|
import { assistiveTextStyle, generateUniqueId } from '../system/shared/utils.svelte.js';
|
|
12
12
|
|
|
13
|
-
/** @deprecated FlexiAdd's children props are now redundant and will be removed in v0.4. */
|
|
14
|
-
type FlexiAddChildrenProps = {
|
|
15
|
-
/**
|
|
16
|
-
* @deprecated This has been replaced with internal pointer management and is redundant. This event will be removed in v0.4.
|
|
17
|
-
*/
|
|
18
|
-
onpointerdown: (event: PointerEvent) => void;
|
|
19
|
-
/**
|
|
20
|
-
* @deprecated This has been moved to the internal button so is now redundant. It will be removed in v0.4.
|
|
21
|
-
*/
|
|
22
|
-
style: string;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
13
|
export type FlexiAddProps = FlexiCommonProps<FlexiAddController> & {
|
|
26
14
|
class?: FlexiAddClasses;
|
|
27
|
-
children?: Snippet<[{ adder: FlexiAddController
|
|
15
|
+
children?: Snippet<[{ adder: FlexiAddController }]>;
|
|
28
16
|
addWidget: FlexiAddWidgetFn;
|
|
29
17
|
};
|
|
30
18
|
</script>
|
|
@@ -75,7 +63,7 @@
|
|
|
75
63
|
<span style={assistiveTextStyle} id={assistiveTextId}>
|
|
76
64
|
Press Enter to drag a new widget into this board.
|
|
77
65
|
</span>
|
|
78
|
-
{@render children?.({ adder
|
|
66
|
+
{@render children?.({ adder })}
|
|
79
67
|
</button>
|
|
80
68
|
|
|
81
69
|
<div style="display: none;">
|
|
@@ -1,22 +1,10 @@
|
|
|
1
1
|
import { type FlexiAddController, type FlexiAddClasses, type FlexiAddWidgetFn } from '../system/misc/adder.svelte.js';
|
|
2
2
|
import { type Snippet } from 'svelte';
|
|
3
3
|
import type { FlexiCommonProps } from '../system/types.js';
|
|
4
|
-
/** @deprecated FlexiAdd's children props are now redundant and will be removed in v0.4. */
|
|
5
|
-
type FlexiAddChildrenProps = {
|
|
6
|
-
/**
|
|
7
|
-
* @deprecated This has been replaced with internal pointer management and is redundant. This event will be removed in v0.4.
|
|
8
|
-
*/
|
|
9
|
-
onpointerdown: (event: PointerEvent) => void;
|
|
10
|
-
/**
|
|
11
|
-
* @deprecated This has been moved to the internal button so is now redundant. It will be removed in v0.4.
|
|
12
|
-
*/
|
|
13
|
-
style: string;
|
|
14
|
-
};
|
|
15
4
|
export type FlexiAddProps = FlexiCommonProps<FlexiAddController> & {
|
|
16
5
|
class?: FlexiAddClasses;
|
|
17
6
|
children?: Snippet<[{
|
|
18
7
|
adder: FlexiAddController;
|
|
19
|
-
props: FlexiAddChildrenProps;
|
|
20
8
|
}]>;
|
|
21
9
|
addWidget: FlexiAddWidgetFn;
|
|
22
10
|
};
|
|
@@ -8,18 +8,6 @@
|
|
|
8
8
|
} from '../system/misc/deleter.svelte.js';
|
|
9
9
|
import { assistiveTextStyle, generateUniqueId } from '../system/shared/utils.svelte.js';
|
|
10
10
|
|
|
11
|
-
/** @deprecated FlexiDelete's children props are now redundant and will be removed in v0.4. */
|
|
12
|
-
type FlexiDeleteChildrenProps = {
|
|
13
|
-
/**
|
|
14
|
-
* @deprecated This has been replaced with internal pointer management and is redundant. These events will be removed in v0.4.
|
|
15
|
-
*/
|
|
16
|
-
onpointerenter: (event: PointerEvent) => void;
|
|
17
|
-
/**
|
|
18
|
-
* @deprecated This has been replaced with internal pointer management and is redundant. These events will be removed in v0.4.
|
|
19
|
-
*/
|
|
20
|
-
onpointerleave: (event: PointerEvent) => void;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
11
|
export type FlexiDeleteProps = FlexiCommonProps<FlexiDeleteController> & {
|
|
24
12
|
class?: FlexiDeleteClasses;
|
|
25
13
|
children?: Snippet<[{ deleter: FlexiDeleteController }]>;
|
|
@@ -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);
|
|
@@ -60,6 +60,8 @@ export declare class GridDimensionTracker {
|
|
|
60
60
|
refreshScrollListeners(): void;
|
|
61
61
|
getCellFromPointerPosition(clientX: number, clientY: number): CellPosition | null;
|
|
62
62
|
}
|
|
63
|
+
export declare function contentSize(axisCoordinates: number[], gap: number): number;
|
|
64
|
+
export declare function findCell(pointerLocation: number, start: number, size: number, gap: number, axisCoordinates: number[]): number;
|
|
63
65
|
export declare function generateUniqueId(prefix?: string): string;
|
|
64
66
|
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
67
|
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,32 +578,45 @@ 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-') {
|
|
@@ -223,28 +223,31 @@ export class InternalFlexiTargetController {
|
|
|
223
223
|
* @returns The layout of widgets.
|
|
224
224
|
*/
|
|
225
225
|
exportLayout() {
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
226
|
+
// Prevent reactive subscriptions onto exportLayout directly - they should use onLayoutChange.
|
|
227
|
+
return untrack(() => {
|
|
228
|
+
const result = [];
|
|
229
|
+
// Likely much more information than needed, but we've got it.
|
|
230
|
+
for (const widget of this.internalWidgets) {
|
|
231
|
+
if (!widget.type) {
|
|
232
|
+
console.warn('exportLayout(): widget has no type, it will be skipped.');
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
const entry = {
|
|
236
|
+
type: widget.type,
|
|
237
|
+
width: widget.width,
|
|
238
|
+
height: widget.height,
|
|
239
|
+
x: widget.x,
|
|
240
|
+
y: widget.y,
|
|
241
|
+
metadata: widget.metadata
|
|
242
|
+
};
|
|
243
|
+
// Only include id if user provided one
|
|
244
|
+
if (widget.userProvidedId) {
|
|
245
|
+
entry.id = widget.userProvidedId;
|
|
246
|
+
}
|
|
247
|
+
result.push(entry);
|
|
244
248
|
}
|
|
245
|
-
result
|
|
246
|
-
}
|
|
247
|
-
return result;
|
|
249
|
+
return result;
|
|
250
|
+
});
|
|
248
251
|
}
|
|
249
252
|
#createShadow(of, action) {
|
|
250
253
|
const shadow = new InternalFlexiWidgetController({
|