svelte-tiler 0.0.1 → 0.2.0
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/{context.svelte.d.ts → context.d.ts} +19 -12
- package/dist/context.js +92 -0
- package/dist/debug.svelte +11 -0
- package/dist/debug.svelte.d.ts +8 -0
- package/dist/dnd.d.ts +19 -4
- package/dist/dnd.js +31 -6
- package/dist/index.d.ts +3 -2
- package/dist/index.js +3 -2
- package/dist/model.d.ts +18 -1
- package/dist/model.js +32 -1
- package/dist/panel.svelte.d.ts +1 -1
- package/dist/render.svelte +4 -10
- package/dist/render.svelte.d.ts +1 -1
- package/dist/tiler.svelte +1 -1
- package/dist/tiler.svelte.d.ts +1 -1
- package/dist/tiles/leaf.svelte +2 -0
- package/dist/tiles/leaf.svelte.d.ts +1 -0
- package/dist/tiles/split.svelte +28 -19
- package/dist/tiles/split.svelte.d.ts +4 -4
- package/dist/tiles/tabs.svelte +62 -93
- package/dist/tiles/tabs.svelte.d.ts +11 -11
- package/package.json +3 -3
- package/dist/context.svelte.js +0 -57
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { DndContext } from './shared/dnd.svelte.ts';
|
|
2
|
-
import type { Tile, TileComponent, Tiles, TileType } from './model.
|
|
2
|
+
import type { Tile, TileComponent, TileInsertData, Tiles, TileType } from './model.js';
|
|
3
3
|
export declare const getTilerContext: () => TilerContext, setTilerContext: (context: TilerContext) => TilerContext;
|
|
4
4
|
export interface TileDefinition<T extends TileType> {
|
|
5
5
|
default: TileComponent<T>;
|
|
6
6
|
onRemoveChild: (ctx: TilerContext, tile: Tiles[T], index: number) => void;
|
|
7
|
+
onInsert: (ctx: TilerContext, tile: Tiles[T], index: number, data: TileInsertData<T>) => void;
|
|
7
8
|
onClear: (ctx: TilerContext, tile: Tiles[T]) => void;
|
|
8
9
|
}
|
|
9
10
|
export type TileDefinitions = {
|
|
@@ -13,29 +14,29 @@ export type TileEffects = {
|
|
|
13
14
|
[T in TileType]?: (tile: Tiles[T]) => void | (() => void);
|
|
14
15
|
};
|
|
15
16
|
export interface TilerContextOptions {
|
|
16
|
-
|
|
17
|
-
parents?: WeakMap<Tile, Tile>;
|
|
17
|
+
definitions: TileDefinitions;
|
|
18
18
|
dnd?: DndContext<Tile>;
|
|
19
19
|
effects?: TileEffects;
|
|
20
20
|
}
|
|
21
21
|
export declare class TilerContext {
|
|
22
22
|
protected definitions: TileDefinitions;
|
|
23
|
-
protected parents: WeakMap<Tile, Tile>;
|
|
24
23
|
protected effects: TileEffects;
|
|
25
24
|
protected updateRootFn: ((tile: Tile) => void) | undefined;
|
|
25
|
+
protected registry: FinalizationRegistry<string>;
|
|
26
|
+
protected tiles: Map<string, WeakRef<Tile>>;
|
|
27
|
+
protected parents: WeakMap<Tile, Tile>;
|
|
26
28
|
readonly dnd: DndContext<Tile>;
|
|
27
29
|
constructor(options: TilerContextOptions);
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
getTileEffect(tile: Tile): ((tile: import("./model.ts").TileBase<"leaf"> & {
|
|
30
|
+
registerTile(tile: Tile, parent: Tile | ((tile: Tile) => void)): void;
|
|
31
|
+
getTileEffect(tile: Tile): ((tile: import("./model.js").TileBase<"leaf"> & {
|
|
31
32
|
name: string;
|
|
32
|
-
}) => void | (() => void)) | ((tile: import("./model.
|
|
33
|
+
}) => void | (() => void)) | ((tile: import("./model.js").TileBase<"split"> & {
|
|
33
34
|
constraints: Array<import("./shared/constraints.ts").Constraint[]>;
|
|
34
35
|
weights: number[];
|
|
35
36
|
direction: import("./shared/spatial.ts").Direction;
|
|
36
37
|
resizer?: string;
|
|
37
38
|
gapPx: number;
|
|
38
|
-
}) => void | (() => void)) | ((tile: import("./model.
|
|
39
|
+
}) => void | (() => void)) | ((tile: import("./model.js").TileBase<"tabs"> & {
|
|
39
40
|
titles: string[];
|
|
40
41
|
selectedTab: number;
|
|
41
42
|
headersDirection: import("./tiles/tabs.svelte.ts").HeadersDirection;
|
|
@@ -44,7 +45,13 @@ export declare class TilerContext {
|
|
|
44
45
|
empty?: string;
|
|
45
46
|
}) => void | (() => void)) | undefined;
|
|
46
47
|
getTileComponent(tile: Tile): TileComponent<"leaf"> | TileComponent<"split"> | TileComponent<"tabs">;
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
replace(tile: Tile | undefined, replace: Tile): void;
|
|
49
|
+
replaceTile(tileId: string | undefined, replace: Tile): void;
|
|
50
|
+
insertInto<T extends TileType>(tile: Tiles[T], index: number, data: TileInsertData<T>): void;
|
|
51
|
+
insertIntoTile<T extends TileType>(tileId: string, type: T, index: number, data: TileInsertData<T>): void;
|
|
52
|
+
removeChildFrom(tile: Tile, index: number): void;
|
|
53
|
+
removeChildFromTile(tileId: string, index: number): void;
|
|
54
|
+
remove(tile: Tile): void;
|
|
55
|
+
removeTile(tileId: string): void;
|
|
56
|
+
protected getTileById(tileId: string): Tile;
|
|
50
57
|
}
|
package/dist/context.js
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { createContext } from 'svelte';
|
|
2
|
+
import { DndContext } from "./shared/dnd.svelte.js";
|
|
3
|
+
export const [getTilerContext, setTilerContext] = createContext();
|
|
4
|
+
export class TilerContext {
|
|
5
|
+
definitions;
|
|
6
|
+
effects;
|
|
7
|
+
updateRootFn;
|
|
8
|
+
registry = new FinalizationRegistry((id) => {
|
|
9
|
+
this.tiles.delete(id);
|
|
10
|
+
});
|
|
11
|
+
tiles = new Map();
|
|
12
|
+
parents = new WeakMap();
|
|
13
|
+
dnd;
|
|
14
|
+
constructor(options) {
|
|
15
|
+
this.definitions = options.definitions;
|
|
16
|
+
this.dnd = options.dnd ?? new DndContext();
|
|
17
|
+
this.effects = options.effects ?? {};
|
|
18
|
+
}
|
|
19
|
+
registerTile(tile, parent) {
|
|
20
|
+
this.tiles.set(tile.id, new WeakRef(tile));
|
|
21
|
+
this.registry.register(tile, tile.id);
|
|
22
|
+
if (typeof parent === 'function') {
|
|
23
|
+
this.parents.delete(tile);
|
|
24
|
+
this.updateRootFn = parent;
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
this.parents.set(tile, parent);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
getTileEffect(tile) {
|
|
31
|
+
return this.effects[tile.type];
|
|
32
|
+
}
|
|
33
|
+
getTileComponent(tile) {
|
|
34
|
+
return this.definitions[tile.type].default;
|
|
35
|
+
}
|
|
36
|
+
replace(tile, replace) {
|
|
37
|
+
if (tile) {
|
|
38
|
+
const parent = this.parents.get(tile);
|
|
39
|
+
if (parent) {
|
|
40
|
+
const index = parent.children.findIndex((c) => c.id === tile.id);
|
|
41
|
+
if (index < 0) {
|
|
42
|
+
throw new Error(`Invalid parent for "${tile.id}" tile`);
|
|
43
|
+
}
|
|
44
|
+
parent.children[index] = replace;
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
this.updateRootFn?.(replace);
|
|
49
|
+
}
|
|
50
|
+
replaceTile(tileId, replace) {
|
|
51
|
+
const tile = tileId && this.getTileById(tileId);
|
|
52
|
+
this.replace(tile || undefined, replace);
|
|
53
|
+
}
|
|
54
|
+
insertInto(tile, index, data) {
|
|
55
|
+
this.definitions[tile.type].onInsert(this, tile, index, data);
|
|
56
|
+
}
|
|
57
|
+
insertIntoTile(tileId, type, index, data) {
|
|
58
|
+
const tile = this.getTileById(tileId);
|
|
59
|
+
if (tile.type !== type) {
|
|
60
|
+
throw new Error(`Tile type mismatch: expected "${type}", but got "${tile.type}"`);
|
|
61
|
+
}
|
|
62
|
+
this.insertInto(tile, index, data);
|
|
63
|
+
}
|
|
64
|
+
removeChildFrom(tile, index) {
|
|
65
|
+
this.definitions[tile.type].onRemoveChild(this, tile, index);
|
|
66
|
+
}
|
|
67
|
+
removeChildFromTile(tileId, index) {
|
|
68
|
+
this.removeChildFrom(this.getTileById(tileId), index);
|
|
69
|
+
}
|
|
70
|
+
remove(tile) {
|
|
71
|
+
const parent = this.parents.get(tile);
|
|
72
|
+
if (parent === undefined) {
|
|
73
|
+
this.definitions[tile.type].onClear(this, tile);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const index = parent.children.findIndex((c) => c.id === tile.id);
|
|
77
|
+
if (index < 0) {
|
|
78
|
+
throw new Error(`Invalid parent for "${tile.id}" tile`);
|
|
79
|
+
}
|
|
80
|
+
this.removeChildFrom(parent, index);
|
|
81
|
+
}
|
|
82
|
+
removeTile(tileId) {
|
|
83
|
+
this.remove(this.getTileById(tileId));
|
|
84
|
+
}
|
|
85
|
+
getTileById(tileId) {
|
|
86
|
+
const tile = this.tiles.get(tileId)?.deref();
|
|
87
|
+
if (tile === undefined) {
|
|
88
|
+
throw new Error(`Unable to find tile with "${tileId}" id`);
|
|
89
|
+
}
|
|
90
|
+
return tile;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Tile } from './model.js';
|
|
3
|
+
import Self from './debug.svelte';
|
|
4
|
+
|
|
5
|
+
const { tile, level = 0 }: { tile: Tile; level?: number } = $props();
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<div style="padding-left: {level * 12}px;">{tile.type} ({tile.id})</div>
|
|
9
|
+
{#each tile.children as c (c.id)}
|
|
10
|
+
<Self tile={c} level={level + 1} />
|
|
11
|
+
{/each}
|
package/dist/dnd.d.ts
CHANGED
|
@@ -1,6 +1,21 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Draggable, Droppable, type DraggableOptions, type StopEvent } from './shared/dnd.svelte.js';
|
|
2
2
|
import type { Tile } from './model.js';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
import type { TilerContext } from './context.ts';
|
|
4
|
+
export declare class TileDropTarget<T extends Tile> extends Droppable<Tile, T> {
|
|
5
|
+
readonly tileId: string;
|
|
6
|
+
protected tilerCtx: TilerContext;
|
|
7
|
+
constructor(ctx: TilerContext, tileId: string);
|
|
8
|
+
getTargetTileId(): string | undefined;
|
|
9
|
+
protected isOwnChild(d: Draggable): d is TileDragSource;
|
|
10
|
+
}
|
|
11
|
+
export interface TileDragSourceOptions extends DraggableOptions<Tile> {
|
|
12
|
+
parentTileId: string;
|
|
13
|
+
childIndex: number;
|
|
14
|
+
}
|
|
15
|
+
export declare class TileDragSource extends Draggable<Tile> {
|
|
16
|
+
protected tilerCtx: TilerContext;
|
|
17
|
+
readonly parentTileId: string;
|
|
18
|
+
readonly childIndex: number;
|
|
19
|
+
constructor(ctx: TilerContext, options: TileDragSourceOptions);
|
|
20
|
+
protected onStop({ reason }: StopEvent): void;
|
|
6
21
|
}
|
package/dist/dnd.js
CHANGED
|
@@ -1,8 +1,33 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export class
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { Draggable, Droppable, } from './shared/dnd.svelte.js';
|
|
2
|
+
export class TileDropTarget extends Droppable {
|
|
3
|
+
tileId;
|
|
4
|
+
tilerCtx;
|
|
5
|
+
constructor(ctx, tileId) {
|
|
6
|
+
super(ctx.dnd);
|
|
7
|
+
this.tileId = tileId;
|
|
8
|
+
this.tilerCtx = ctx;
|
|
9
|
+
}
|
|
10
|
+
getTargetTileId() {
|
|
11
|
+
return this.tileId;
|
|
12
|
+
}
|
|
13
|
+
isOwnChild(d) {
|
|
14
|
+
return d instanceof TileDragSource && this.tileId === d.parentTileId;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export class TileDragSource extends Draggable {
|
|
18
|
+
tilerCtx;
|
|
19
|
+
parentTileId;
|
|
20
|
+
childIndex;
|
|
21
|
+
constructor(ctx, options) {
|
|
22
|
+
super(ctx.dnd, options);
|
|
23
|
+
this.tilerCtx = ctx;
|
|
24
|
+
this.parentTileId = options.parentTileId;
|
|
25
|
+
this.childIndex = options.childIndex;
|
|
26
|
+
}
|
|
27
|
+
onStop({ reason }) {
|
|
28
|
+
if (reason !== 'drop') {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
this.tilerCtx.removeChildFromTile(this.parentTileId, this.childIndex);
|
|
7
32
|
}
|
|
8
33
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export * from './context.
|
|
2
|
-
export * from './model.
|
|
1
|
+
export * from './context.ts';
|
|
2
|
+
export * from './model.js';
|
|
3
3
|
export * from './dnd.ts';
|
|
4
4
|
export { default as Panel } from './panel.svelte';
|
|
5
5
|
export { default as Tiler } from './tiler.svelte';
|
|
6
|
+
export { default as Debug } from './debug.svelte';
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
export * from "./context.
|
|
2
|
-
export * from
|
|
1
|
+
export * from "./context.js";
|
|
2
|
+
export * from './model.js';
|
|
3
3
|
export * from "./dnd.js";
|
|
4
4
|
export { default as Panel } from './panel.svelte';
|
|
5
5
|
export { default as Tiler } from './tiler.svelte';
|
|
6
|
+
export { default as Debug } from './debug.svelte';
|
package/dist/model.d.ts
CHANGED
|
@@ -11,10 +11,27 @@ export type Tiles = {
|
|
|
11
11
|
[T in TileType]: TileBase<T> & TileRegistry[T];
|
|
12
12
|
};
|
|
13
13
|
export type Tile = Tiles[TileType];
|
|
14
|
+
export interface TileInsertRequirements {
|
|
15
|
+
}
|
|
16
|
+
type WithOnlyRequired<T, K extends keyof T> = Required<Pick<T, K>> & Partial<Omit<T, K>>;
|
|
17
|
+
export type TileInsertData<T extends TileType> = WithOnlyRequired<Tiles[T], (T extends keyof TileInsertRequirements ? TileInsertRequirements[T] & keyof Tiles[T] : never) | 'children'>;
|
|
14
18
|
export type TileProps<T extends TileType> = {
|
|
15
19
|
tile: Tiles[T];
|
|
16
20
|
parent: Tile | undefined;
|
|
17
21
|
index: number;
|
|
18
22
|
child: Snippet<[number]>;
|
|
19
23
|
};
|
|
20
|
-
export type TileComponent<T extends TileType> = Component<TileProps<T>, {}, 'tile'
|
|
24
|
+
export type TileComponent<T extends TileType> = Component<TileProps<T>, {}, 'tile'>;
|
|
25
|
+
export type TileArrayProperties<T extends TileType> = {
|
|
26
|
+
[K in keyof Tiles[T] as Tiles[T][K] extends Array<any> ? K : never]: Tiles[T][K];
|
|
27
|
+
};
|
|
28
|
+
export type TileArrayProperty<T extends TileType> = keyof TileArrayProperties<T>;
|
|
29
|
+
/**
|
|
30
|
+
* @returns Returns the insertion position taking into account removed duplicates
|
|
31
|
+
*/
|
|
32
|
+
export declare function insertWithDeduplication<T extends TileType>(tile: Tiles[T], i: number, arrays: {
|
|
33
|
+
[K in Exclude<TileArrayProperty<T>, 'children'>]?: Tiles[T][K & keyof Tiles[T]];
|
|
34
|
+
} & {
|
|
35
|
+
children: Tile[];
|
|
36
|
+
}): number;
|
|
37
|
+
export {};
|
package/dist/model.js
CHANGED
|
@@ -1 +1,32 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @returns Returns the insertion position taking into account removed duplicates
|
|
3
|
+
*/
|
|
4
|
+
export function insertWithDeduplication(tile, i, arrays) {
|
|
5
|
+
const newIds = new Set(arrays.children.map((c) => c.id));
|
|
6
|
+
let write = 0;
|
|
7
|
+
let shift = 0;
|
|
8
|
+
const c = tile.children;
|
|
9
|
+
const l = c.length;
|
|
10
|
+
const keys = Object.keys(arrays);
|
|
11
|
+
const tileArrays = keys.map((arr) => tile[arr]);
|
|
12
|
+
for (let read = 0; read < l; read++) {
|
|
13
|
+
if (!newIds.has(c[read].id)) {
|
|
14
|
+
for (const arr of tileArrays) {
|
|
15
|
+
// @ts-expect-error ignore
|
|
16
|
+
arr[write] = arr[read];
|
|
17
|
+
}
|
|
18
|
+
write++;
|
|
19
|
+
}
|
|
20
|
+
else if (read < i) {
|
|
21
|
+
shift++;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
i -= shift;
|
|
25
|
+
for (const key of keys) {
|
|
26
|
+
// @ts-expect-error ignore
|
|
27
|
+
tile[key].length = write;
|
|
28
|
+
// @ts-expect-error ignore
|
|
29
|
+
tile[key].splice(i, 0, ...arrays[key]);
|
|
30
|
+
}
|
|
31
|
+
return i;
|
|
32
|
+
}
|
package/dist/panel.svelte.d.ts
CHANGED
package/dist/render.svelte
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import { getTilerContext } from './context.
|
|
2
|
+
import { getTilerContext } from './context.js';
|
|
3
3
|
import type { Tile } from './model.js';
|
|
4
4
|
import Self from './render.svelte';
|
|
5
5
|
|
|
@@ -15,13 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
const ctx = getTilerContext();
|
|
17
17
|
|
|
18
|
-
$effect(() =>
|
|
19
|
-
if (parent) {
|
|
20
|
-
ctx.registerParent(tile, parent);
|
|
21
|
-
} else {
|
|
22
|
-
ctx.setUpdateRoot(tile, (t) => (parent = t));
|
|
23
|
-
}
|
|
24
|
-
});
|
|
18
|
+
$effect(() => ctx.registerTile(tile, parent ?? ((t) => (parent = t))));
|
|
25
19
|
|
|
26
20
|
$effect(() => ctx.getTileEffect(tile)?.(tile as never));
|
|
27
21
|
|
|
@@ -29,7 +23,7 @@
|
|
|
29
23
|
</script>
|
|
30
24
|
|
|
31
25
|
{#snippet child(index: number)}
|
|
32
|
-
<Self
|
|
26
|
+
<Self parent={tile} bind:tile={tile.children[index]} {index} />
|
|
33
27
|
{/snippet}
|
|
34
28
|
|
|
35
|
-
<TileComponent
|
|
29
|
+
<TileComponent {parent} bind:tile={tile as never} {index} {child} />
|
package/dist/render.svelte.d.ts
CHANGED
package/dist/tiler.svelte
CHANGED
package/dist/tiler.svelte.d.ts
CHANGED
package/dist/tiles/leaf.svelte
CHANGED
|
@@ -12,6 +12,7 @@ type LeafContext<N extends string = string> = Registry<N, Snippet<[Tiles['leaf']
|
|
|
12
12
|
export declare function setup<N extends string>(leafs: LeafContext<N>): (name: N) => Tiles["leaf"];
|
|
13
13
|
export declare function onRemoveChild(): void;
|
|
14
14
|
export declare function onClear(): void;
|
|
15
|
+
export declare function onInsert(): void;
|
|
15
16
|
declare const Leaf: import("svelte").Component<TileProps<"leaf">, {}, "tile">;
|
|
16
17
|
type Leaf = ReturnType<typeof Leaf>;
|
|
17
18
|
export default Leaf;
|
package/dist/tiles/split.svelte
CHANGED
|
@@ -10,9 +10,15 @@
|
|
|
10
10
|
} from '../shared/constraints.js';
|
|
11
11
|
import type { Direction } from '../shared/spatial.js';
|
|
12
12
|
import { almostEqual } from '../shared/math.js';
|
|
13
|
-
import
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
import {
|
|
14
|
+
insertWithDeduplication,
|
|
15
|
+
type Tile,
|
|
16
|
+
type TileInsertData,
|
|
17
|
+
type TileProps,
|
|
18
|
+
type Tiles,
|
|
19
|
+
} from '../model.js';
|
|
20
|
+
import type { TilerContext } from '../context.js';
|
|
21
|
+
import { TileDropTarget } from '../dnd.js';
|
|
16
22
|
|
|
17
23
|
declare module '../model.js' {
|
|
18
24
|
interface TileRegistry {
|
|
@@ -88,11 +94,11 @@
|
|
|
88
94
|
ctx.dnd.targetId && ctx.dnd.droppables.get(ctx.dnd.targetId);
|
|
89
95
|
if (
|
|
90
96
|
!droppable ||
|
|
91
|
-
(droppable instanceof
|
|
92
|
-
tile.
|
|
97
|
+
(droppable instanceof TileDropTarget &&
|
|
98
|
+
tile.id !== droppable.getTargetTileId())
|
|
93
99
|
) {
|
|
94
100
|
tick().then(() => {
|
|
95
|
-
ctx.
|
|
101
|
+
ctx.replace(tile, tile.children[1 - i]);
|
|
96
102
|
});
|
|
97
103
|
return;
|
|
98
104
|
}
|
|
@@ -103,23 +109,26 @@
|
|
|
103
109
|
tile.constraints.splice(i, 1);
|
|
104
110
|
return;
|
|
105
111
|
}
|
|
106
|
-
ctx.
|
|
112
|
+
ctx.remove(tile);
|
|
107
113
|
}
|
|
108
114
|
|
|
109
|
-
export function onClear(
|
|
110
|
-
if (tile.children.length > 0) {
|
|
111
|
-
ctx.replaceWith(tile, tile.children[0]);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
115
|
+
export function onClear(_ctx: TilerContext, _tile: Tiles['split']) {}
|
|
114
116
|
|
|
115
|
-
export function
|
|
116
|
-
|
|
117
|
+
export function onInsert(
|
|
118
|
+
_ctx: TilerContext,
|
|
119
|
+
tile: Tiles['split'],
|
|
117
120
|
index: number,
|
|
118
|
-
{
|
|
121
|
+
{
|
|
122
|
+
children,
|
|
123
|
+
constraints = children.map(() => []),
|
|
124
|
+
weights = children.map(() => 1),
|
|
125
|
+
}: TileInsertData<'split'>
|
|
119
126
|
) {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
127
|
+
insertWithDeduplication<'split'>(tile, index, {
|
|
128
|
+
children,
|
|
129
|
+
constraints,
|
|
130
|
+
weights,
|
|
131
|
+
});
|
|
123
132
|
}
|
|
124
133
|
</script>
|
|
125
134
|
|
|
@@ -201,7 +210,7 @@
|
|
|
201
210
|
: currentPos > resizerRect.top
|
|
202
211
|
) {
|
|
203
212
|
if (currentDir !== lastDir) {
|
|
204
|
-
startPos =
|
|
213
|
+
startPos = currentPos;
|
|
205
214
|
this.syncWeights();
|
|
206
215
|
lastDir = currentDir;
|
|
207
216
|
}
|
|
@@ -3,8 +3,8 @@ import type { Registry } from '../shared/registry.js';
|
|
|
3
3
|
import { Draggable } from '../shared/dnd.svelte.js';
|
|
4
4
|
import { type Constraint } from '../shared/constraints.js';
|
|
5
5
|
import type { Direction } from '../shared/spatial.js';
|
|
6
|
-
import type
|
|
7
|
-
import type { TilerContext } from '../context.
|
|
6
|
+
import { type Tile, type TileInsertData, type TileProps, type Tiles } from '../model.js';
|
|
7
|
+
import type { TilerContext } from '../context.js';
|
|
8
8
|
declare module '../model.js' {
|
|
9
9
|
interface TileRegistry {
|
|
10
10
|
split: {
|
|
@@ -35,8 +35,8 @@ type SplitContext<R extends string = string> = {
|
|
|
35
35
|
};
|
|
36
36
|
export declare function setup<R extends string>(ctx: SplitContext<R>): (options: SplitOptions<R>) => Tiles["split"];
|
|
37
37
|
export declare function onRemoveChild(ctx: TilerContext, tile: Tiles['split'], i: number): void;
|
|
38
|
-
export declare function onClear(
|
|
39
|
-
export declare function
|
|
38
|
+
export declare function onClear(_ctx: TilerContext, _tile: Tiles['split']): void;
|
|
39
|
+
export declare function onInsert(_ctx: TilerContext, tile: Tiles['split'], index: number, { children, constraints, weights, }: TileInsertData<'split'>): void;
|
|
40
40
|
declare const Split: import("svelte").Component<TileProps<"split">, {}, "tile">;
|
|
41
41
|
type Split = ReturnType<typeof Split>;
|
|
42
42
|
export default Split;
|
package/dist/tiles/tabs.svelte
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
<script lang="ts" module>
|
|
2
2
|
import { getContext, setContext, type Snippet } from 'svelte';
|
|
3
3
|
|
|
4
|
+
import type { Draggable } from '../shared/dnd.svelte.js';
|
|
4
5
|
import type { Registry } from '../shared/registry.js';
|
|
5
|
-
import
|
|
6
|
-
|
|
6
|
+
import {
|
|
7
|
+
insertWithDeduplication,
|
|
8
|
+
type Tile,
|
|
9
|
+
type Tiles,
|
|
10
|
+
} from '../model.js';
|
|
11
|
+
import type { TilerContext } from '../context.js';
|
|
7
12
|
|
|
8
13
|
export type HeadersDirection = Direction | 'none';
|
|
9
14
|
|
|
@@ -18,6 +23,9 @@
|
|
|
18
23
|
empty?: string;
|
|
19
24
|
};
|
|
20
25
|
}
|
|
26
|
+
interface TileInsertRequirements {
|
|
27
|
+
tabs: 'titles';
|
|
28
|
+
}
|
|
21
29
|
}
|
|
22
30
|
|
|
23
31
|
export interface TabsOptions<
|
|
@@ -57,7 +65,7 @@
|
|
|
57
65
|
}
|
|
58
66
|
|
|
59
67
|
interface SplitOptions {
|
|
60
|
-
type:
|
|
68
|
+
type: Direction;
|
|
61
69
|
parent: Tile | undefined;
|
|
62
70
|
pivot: Tiles['tabs'];
|
|
63
71
|
offset: number;
|
|
@@ -69,7 +77,7 @@
|
|
|
69
77
|
E extends string = string,
|
|
70
78
|
A extends string = string,
|
|
71
79
|
> {
|
|
72
|
-
|
|
80
|
+
applySplit?: (options: SplitOptions) => void;
|
|
73
81
|
actions?: Registry<A, Snippet<[Tiles['tabs']]> | undefined>;
|
|
74
82
|
headers?: Registry<
|
|
75
83
|
H,
|
|
@@ -93,7 +101,7 @@
|
|
|
93
101
|
i: number
|
|
94
102
|
) {
|
|
95
103
|
if (tile.children.length < 2) {
|
|
96
|
-
ctx.
|
|
104
|
+
ctx.remove(tile);
|
|
97
105
|
return;
|
|
98
106
|
}
|
|
99
107
|
if (tile.selectedTab >= i) {
|
|
@@ -111,62 +119,30 @@
|
|
|
111
119
|
}
|
|
112
120
|
}
|
|
113
121
|
|
|
114
|
-
export function
|
|
122
|
+
export function onInsert(
|
|
123
|
+
_ctx: TilerContext,
|
|
115
124
|
tile: Tiles['tabs'],
|
|
116
125
|
i: number,
|
|
117
|
-
|
|
118
|
-
titles,
|
|
119
|
-
children,
|
|
120
|
-
}: {
|
|
121
|
-
titles: string[];
|
|
122
|
-
children: Tile[];
|
|
123
|
-
}
|
|
126
|
+
data: TileInsertData<'tabs'>
|
|
124
127
|
) {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
const t = tile.titles;
|
|
130
|
-
const l = t.length;
|
|
131
|
-
for (let read = 0; read < l; read++) {
|
|
132
|
-
if (!newIds.has(c[read].id)) {
|
|
133
|
-
t[write] = t[read];
|
|
134
|
-
c[write] = c[read];
|
|
135
|
-
write++;
|
|
136
|
-
} else if (read < i) {
|
|
137
|
-
shift++;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
c.length = write;
|
|
141
|
-
t.length = write;
|
|
142
|
-
i -= shift;
|
|
143
|
-
tile.children.splice(i, 0, ...children);
|
|
144
|
-
tile.titles.splice(i, 0, ...titles);
|
|
145
|
-
tile.selectedTab = i;
|
|
128
|
+
tile.selectedTab = insertWithDeduplication<'tabs'>(tile, i, {
|
|
129
|
+
titles: data.titles,
|
|
130
|
+
children: data.children,
|
|
131
|
+
});
|
|
146
132
|
}
|
|
147
133
|
</script>
|
|
148
134
|
|
|
149
135
|
<script lang="ts">
|
|
150
|
-
import {
|
|
151
|
-
DndContext,
|
|
152
|
-
Draggable,
|
|
153
|
-
type DraggableOptions,
|
|
154
|
-
type StopEvent,
|
|
155
|
-
} from '../shared/dnd.svelte.js';
|
|
156
136
|
import {
|
|
157
137
|
getRectParts,
|
|
158
138
|
type Direction,
|
|
159
139
|
type EdgePart,
|
|
160
140
|
} from '../shared/spatial.js';
|
|
161
|
-
import { getTilerContext } from '../context.
|
|
162
|
-
import type { TileProps } from '../model.js';
|
|
163
|
-
import {
|
|
141
|
+
import { getTilerContext } from '../context.js';
|
|
142
|
+
import type { TileInsertData, TileProps } from '../model.js';
|
|
143
|
+
import { TileDragSource, TileDropTarget } from '../dnd.js';
|
|
164
144
|
|
|
165
|
-
let {
|
|
166
|
-
tile = $bindable(),
|
|
167
|
-
parent = $bindable(),
|
|
168
|
-
child,
|
|
169
|
-
}: TileProps<'tabs'> = $props();
|
|
145
|
+
let { tile = $bindable(), parent, child }: TileProps<'tabs'> = $props();
|
|
170
146
|
|
|
171
147
|
const ctx = getTilerContext();
|
|
172
148
|
const tabsCtx = getContext<TabsContext | undefined>(TABS_CONTEXT_KEY);
|
|
@@ -182,35 +158,35 @@
|
|
|
182
158
|
const empty = $derived(
|
|
183
159
|
(tile.empty !== undefined && tabsCtx?.empty?.get(tile.empty)) || undefined
|
|
184
160
|
);
|
|
185
|
-
const edgeRatio = $derived(tabsCtx?.
|
|
161
|
+
const edgeRatio = $derived(tabsCtx?.applySplit ? 0.1 : 0);
|
|
186
162
|
|
|
187
|
-
class
|
|
163
|
+
class TabsTileDropTarget extends TileDropTarget<Tiles['tabs']> {
|
|
188
164
|
accepts(d: Draggable<Tile>): d is Draggable<Tiles['tabs']> {
|
|
189
165
|
const t = d.data;
|
|
190
166
|
return (
|
|
191
167
|
t?.type === 'tabs' &&
|
|
192
168
|
!(
|
|
169
|
+
this.isOwnChild(d) &&
|
|
193
170
|
t.children.length === 1 &&
|
|
194
171
|
tile.children.length === 1 &&
|
|
195
|
-
t.children[0].id === tile.children[0].id
|
|
196
|
-
d instanceof DraggableTab
|
|
172
|
+
t.children[0].id === tile.children[0].id
|
|
197
173
|
)
|
|
198
174
|
);
|
|
199
175
|
}
|
|
200
176
|
}
|
|
201
177
|
|
|
202
|
-
class
|
|
178
|
+
class SimpleTabsDropTarget extends TabsTileDropTarget {
|
|
203
179
|
protected onDrop(tabs: Tiles['tabs']): void {
|
|
204
|
-
|
|
180
|
+
ctx.insertInto<'tabs'>(tile, tile.children.length, tabs);
|
|
205
181
|
}
|
|
206
182
|
}
|
|
207
183
|
|
|
208
|
-
class
|
|
184
|
+
class SegmentedTabsTileDropTarget extends TabsTileDropTarget {
|
|
209
185
|
#edgeRatio: number;
|
|
210
186
|
hpart: EdgePart | undefined = $state.raw();
|
|
211
187
|
vpart: EdgePart | undefined = $state.raw();
|
|
212
188
|
|
|
213
|
-
constructor(ctx:
|
|
189
|
+
constructor(ctx: TilerContext, edgeRatio: number) {
|
|
214
190
|
super(ctx, tile.id);
|
|
215
191
|
this.#edgeRatio = edgeRatio;
|
|
216
192
|
}
|
|
@@ -224,11 +200,11 @@
|
|
|
224
200
|
}
|
|
225
201
|
}
|
|
226
202
|
|
|
227
|
-
class
|
|
203
|
+
class SegmentedTabDropTarget extends SegmentedTabsTileDropTarget {
|
|
228
204
|
#id: string;
|
|
229
205
|
#index: number;
|
|
230
206
|
|
|
231
|
-
constructor(ctx:
|
|
207
|
+
constructor(ctx: TilerContext, id: string, index: number) {
|
|
232
208
|
super(ctx, tile.headersDirection === 'none' ? 0 : 0.5);
|
|
233
209
|
this.#id = id;
|
|
234
210
|
this.#index = index;
|
|
@@ -242,25 +218,33 @@
|
|
|
242
218
|
tile.headersDirection !== 'none'
|
|
243
219
|
? (tile.headersDirection === 'row' ? this.hpart : this.vpart) ===
|
|
244
220
|
'end'
|
|
245
|
-
: d
|
|
221
|
+
: this.isOwnChild(d) && d.childIndex <= i
|
|
246
222
|
) {
|
|
247
223
|
i++;
|
|
248
224
|
}
|
|
249
|
-
|
|
225
|
+
ctx.insertInto<'tabs'>(tile, i, tabs);
|
|
250
226
|
}
|
|
251
227
|
}
|
|
252
228
|
|
|
253
|
-
class
|
|
229
|
+
class SegmentedContentDropTarget extends SegmentedTabsTileDropTarget {
|
|
230
|
+
get isCenter() {
|
|
231
|
+
return this.hpart === 'center' && this.vpart === 'center';
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
getTargetTileId(): string | undefined {
|
|
235
|
+
return this.isCenter ? tile.id : parent?.id;
|
|
236
|
+
}
|
|
237
|
+
|
|
254
238
|
protected onDrop(tabs: Tiles['tabs'], d: Draggable): void {
|
|
255
239
|
const id = tabs.children[0].id;
|
|
256
|
-
if (this.
|
|
240
|
+
if (this.isCenter) {
|
|
257
241
|
let i = tile.children.findIndex((t) => t.id === id);
|
|
258
|
-
if (i < 0 && d
|
|
259
|
-
i = d.
|
|
242
|
+
if (i < 0 && this.isOwnChild(d)) {
|
|
243
|
+
i = d.childIndex;
|
|
260
244
|
}
|
|
261
|
-
|
|
262
|
-
} else if (tabsCtx?.
|
|
263
|
-
|
|
245
|
+
ctx.insertInto<'tabs'>(tile, i < 0 ? tile.children.length : i, tabs);
|
|
246
|
+
} else if (tabsCtx?.applySplit) {
|
|
247
|
+
tabsCtx.applySplit({
|
|
264
248
|
parent,
|
|
265
249
|
type:
|
|
266
250
|
this.hpart === 'start' || this.hpart === 'end' ? 'row' : 'column',
|
|
@@ -279,26 +263,6 @@
|
|
|
279
263
|
}
|
|
280
264
|
}
|
|
281
265
|
|
|
282
|
-
interface DraggableTabOptions extends DraggableOptions<Tile> {
|
|
283
|
-
index: number;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
class DraggableTab extends Draggable<Tile> {
|
|
287
|
-
readonly index: number;
|
|
288
|
-
|
|
289
|
-
constructor(ctx: DndContext<Tile>, options: DraggableTabOptions) {
|
|
290
|
-
super(ctx, options);
|
|
291
|
-
this.index = options.index;
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
protected onStop({ reason }: StopEvent): void {
|
|
295
|
-
if (reason !== 'drop') {
|
|
296
|
-
return;
|
|
297
|
-
}
|
|
298
|
-
ctx.removeChild(tile, this.index);
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
|
|
302
266
|
function handleKeydown(e: KeyboardEvent & { currentTarget: HTMLElement }) {
|
|
303
267
|
if (e.key === 'Enter' || e.key === ' ') {
|
|
304
268
|
e.preventDefault();
|
|
@@ -306,9 +270,13 @@
|
|
|
306
270
|
}
|
|
307
271
|
}
|
|
308
272
|
|
|
309
|
-
const droppableSpacer = $derived(new
|
|
310
|
-
const droppableContent = $derived(
|
|
311
|
-
|
|
273
|
+
const droppableSpacer = $derived(new SimpleTabsDropTarget(ctx, tile.id));
|
|
274
|
+
const droppableContent = $derived(
|
|
275
|
+
new SegmentedContentDropTarget(ctx, edgeRatio)
|
|
276
|
+
);
|
|
277
|
+
const droppableEmpty = $derived(
|
|
278
|
+
new SegmentedContentDropTarget(ctx, edgeRatio)
|
|
279
|
+
);
|
|
312
280
|
</script>
|
|
313
281
|
|
|
314
282
|
{#snippet defaultTabHeader(t: Tiles['tabs'], index: number)}
|
|
@@ -320,9 +288,10 @@
|
|
|
320
288
|
<div data-tabs-bar>
|
|
321
289
|
<div data-tabs-list>
|
|
322
290
|
{#each tile.children as t, i (t.id)}
|
|
323
|
-
{@const droppable = new
|
|
324
|
-
{@const draggable = new
|
|
325
|
-
|
|
291
|
+
{@const droppable = new SegmentedTabDropTarget(ctx, t.id, i)}
|
|
292
|
+
{@const draggable = new TileDragSource(ctx, {
|
|
293
|
+
parentTileId: tile.id,
|
|
294
|
+
childIndex: i,
|
|
326
295
|
data: create({
|
|
327
296
|
...tile,
|
|
328
297
|
tabs: [[tile.titles[i], t]],
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { type Snippet } from 'svelte';
|
|
2
|
+
import type { Draggable } from '../shared/dnd.svelte.js';
|
|
2
3
|
import type { Registry } from '../shared/registry.js';
|
|
3
|
-
import type
|
|
4
|
-
import type { TilerContext } from '../context.
|
|
4
|
+
import { type Tile, type Tiles } from '../model.js';
|
|
5
|
+
import type { TilerContext } from '../context.js';
|
|
5
6
|
export type HeadersDirection = Direction | 'none';
|
|
6
7
|
declare module '../model.js' {
|
|
7
8
|
interface TileRegistry {
|
|
@@ -14,6 +15,9 @@ declare module '../model.js' {
|
|
|
14
15
|
empty?: string;
|
|
15
16
|
};
|
|
16
17
|
}
|
|
18
|
+
interface TileInsertRequirements {
|
|
19
|
+
tabs: 'titles';
|
|
20
|
+
}
|
|
17
21
|
}
|
|
18
22
|
export interface TabsOptions<H extends string, E extends string, A extends string> {
|
|
19
23
|
tabs: [string, Tile][];
|
|
@@ -26,14 +30,14 @@ export interface TabsOptions<H extends string, E extends string, A extends strin
|
|
|
26
30
|
}
|
|
27
31
|
export declare function create<H extends string, E extends string, A extends string>(options: TabsOptions<H, E, A>): Tiles['tabs'];
|
|
28
32
|
interface SplitOptions {
|
|
29
|
-
type:
|
|
33
|
+
type: Direction;
|
|
30
34
|
parent: Tile | undefined;
|
|
31
35
|
pivot: Tiles['tabs'];
|
|
32
36
|
offset: number;
|
|
33
37
|
adjacent: Tiles['tabs'];
|
|
34
38
|
}
|
|
35
39
|
interface TabsContext<H extends string = string, E extends string = string, A extends string = string> {
|
|
36
|
-
|
|
40
|
+
applySplit?: (options: SplitOptions) => void;
|
|
37
41
|
actions?: Registry<A, Snippet<[Tiles['tabs']]> | undefined>;
|
|
38
42
|
headers?: Registry<H, Snippet<[Tiles['tabs'], number, Draggable<Tile>]> | undefined>;
|
|
39
43
|
empty?: Registry<E, Snippet<[Tiles['tabs']]> | undefined>;
|
|
@@ -41,13 +45,9 @@ interface TabsContext<H extends string = string, E extends string = string, A ex
|
|
|
41
45
|
export declare function setup<H extends string, E extends string, A extends string>(ctx: TabsContext<H, E, A>): (options: TabsOptions<H, E, A>) => Tiles["tabs"];
|
|
42
46
|
export declare function onRemoveChild(ctx: TilerContext, tile: Tiles['tabs'], i: number): void;
|
|
43
47
|
export declare function onClear(_ctx: TilerContext, tile: Tiles['tabs']): void;
|
|
44
|
-
export declare function
|
|
45
|
-
titles: string[];
|
|
46
|
-
children: Tile[];
|
|
47
|
-
}): void;
|
|
48
|
-
import { Draggable } from '../shared/dnd.svelte.js';
|
|
48
|
+
export declare function onInsert(_ctx: TilerContext, tile: Tiles['tabs'], i: number, data: TileInsertData<'tabs'>): void;
|
|
49
49
|
import { type Direction } from '../shared/spatial.js';
|
|
50
|
-
import type { TileProps } from '../model.js';
|
|
51
|
-
declare const Tabs: import("svelte").Component<TileProps<"tabs">, {}, "tile"
|
|
50
|
+
import type { TileInsertData, TileProps } from '../model.js';
|
|
51
|
+
declare const Tabs: import("svelte").Component<TileProps<"tabs">, {}, "tile">;
|
|
52
52
|
type Tabs = ReturnType<typeof Tabs>;
|
|
53
53
|
export default Tabs;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "svelte-tiler",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "A small, unstyled library for building tiling user interfaces.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://github.com/x0k/svelte-tiler#readme",
|
|
@@ -61,14 +61,14 @@
|
|
|
61
61
|
"eslint": "^9.39.2",
|
|
62
62
|
"eslint-config-prettier": "^10.1.8",
|
|
63
63
|
"eslint-plugin-svelte": "^3.14.0",
|
|
64
|
-
"globals": "^17.
|
|
64
|
+
"globals": "^17.2.0",
|
|
65
65
|
"marked": "^17.0.1",
|
|
66
66
|
"playwright": "^1.58.0",
|
|
67
67
|
"prettier": "^3.8.1",
|
|
68
68
|
"prettier-plugin-svelte": "^3.4.1",
|
|
69
69
|
"publint": "^0.3.17",
|
|
70
70
|
"shiki": "^3.21.0",
|
|
71
|
-
"svelte": "^5.
|
|
71
|
+
"svelte": "^5.49.1",
|
|
72
72
|
"svelte-check": "^4.3.5",
|
|
73
73
|
"typescript": "^5.9.3",
|
|
74
74
|
"typescript-eslint": "^8.54.0",
|
package/dist/context.svelte.js
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { createContext } from 'svelte';
|
|
2
|
-
import { DndContext } from "./shared/dnd.svelte.js";
|
|
3
|
-
export const [getTilerContext, setTilerContext] = createContext();
|
|
4
|
-
export class TilerContext {
|
|
5
|
-
definitions;
|
|
6
|
-
parents;
|
|
7
|
-
effects;
|
|
8
|
-
updateRootFn;
|
|
9
|
-
dnd;
|
|
10
|
-
constructor(options) {
|
|
11
|
-
this.definitions = $derived(options.tiles);
|
|
12
|
-
this.dnd = $derived(options.dnd ?? new DndContext());
|
|
13
|
-
this.parents = $derived(options.parents ?? new WeakMap());
|
|
14
|
-
this.effects = $derived(options.effects ?? {});
|
|
15
|
-
}
|
|
16
|
-
registerParent(tile, parent) {
|
|
17
|
-
this.parents.set(tile, parent);
|
|
18
|
-
}
|
|
19
|
-
setUpdateRoot(tile, update) {
|
|
20
|
-
this.parents.delete(tile);
|
|
21
|
-
this.updateRootFn = update;
|
|
22
|
-
}
|
|
23
|
-
getTileEffect(tile) {
|
|
24
|
-
return this.effects[tile.type];
|
|
25
|
-
}
|
|
26
|
-
getTileComponent(tile) {
|
|
27
|
-
return this.definitions[tile.type].default;
|
|
28
|
-
}
|
|
29
|
-
replaceWith(tile, replace) {
|
|
30
|
-
const parent = this.parents.get(tile);
|
|
31
|
-
if (parent) {
|
|
32
|
-
const index = parent.children.findIndex((c) => c.id === tile.id);
|
|
33
|
-
if (index < 0) {
|
|
34
|
-
throw new Error(`Invalid parent for ${JSON.stringify($state.snapshot(tile))} tile`);
|
|
35
|
-
}
|
|
36
|
-
parent.children[index] = replace;
|
|
37
|
-
}
|
|
38
|
-
else {
|
|
39
|
-
this.updateRootFn?.(replace);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
removeChild(tile, index) {
|
|
43
|
-
return this.definitions[tile.type].onRemoveChild(this, tile, index);
|
|
44
|
-
}
|
|
45
|
-
destroy(tile) {
|
|
46
|
-
const parent = this.parents.get(tile);
|
|
47
|
-
if (parent === undefined) {
|
|
48
|
-
this.definitions[tile.type].onClear(this, tile);
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
const index = parent.children.findIndex((c) => c.id === tile.id);
|
|
52
|
-
if (index < 0) {
|
|
53
|
-
throw new Error(`Invalid parent for ${JSON.stringify($state.snapshot(tile))} tile`);
|
|
54
|
-
}
|
|
55
|
-
this.removeChild(parent, index);
|
|
56
|
-
}
|
|
57
|
-
}
|