@tikitaki_gagarinbefree/svelte 0.0.0-stage → 0.1.4
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 +21 -0
- package/README.md +17 -2
- package/dist/config.d.ts +5 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +3 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +69 -0
- package/dist/index.js.map +1 -0
- package/package.json +42 -4
- package/src/config.ts +2 -0
- package/src/index.ts +77 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 gagarinbefree
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @tikitaki_gagarinbefree/svelte
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Optional Svelte 5 adapter for TikiTaki. The core remains independent of Svelte.
|
|
4
|
+
Create one `createSvelteCellAdapter<T>()` per engine view and pass `bridge.adapter`
|
|
5
|
+
to `createSwipeEngine`. Subscribe to `bridge.cells` in a keyed template and apply
|
|
6
|
+
`use:portal={cell.host}` to a framework-owned wrapper around each cell component.
|
|
7
|
+
|
|
8
|
+
The bridge exposes a readonly Svelte store of frozen snapshots. Surviving cells
|
|
9
|
+
retain their key, host, context, and component state when data changes. Removed
|
|
10
|
+
cells leave the keyed template and release their component lifecycle. The portal
|
|
11
|
+
action moves only its owned wrapper, cleans up idempotently, and never creates
|
|
12
|
+
per-cell Svelte roots. The engine owns host elements; Svelte owns their descendants.
|
|
13
|
+
|
|
14
|
+
Create the DOM engine in `onMount`, forward grid changes with `$effect`, and destroy
|
|
15
|
+
it in the mount cleanup. Keep mutable controller resources outside deep proxies.
|
|
16
|
+
See the [working demo](../../demos/svelte/EngineView.svelte) for complete ownership,
|
|
17
|
+
reactive updates, parent context, and teardown. Use `tick()` before asserting
|
|
18
|
+
framework content after engine operations.
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,eAAO,MAAM,cAAc;;EAAqE,CAAC"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,iDAAiD;AACjD,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,oBAAoB,EAAE,yBAAyB,EAAE,CAAC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type Readable } from 'svelte/store';
|
|
2
|
+
import type { Position } from 'tikitaki';
|
|
3
|
+
import type { CellAdapter } from 'tikitaki/dom';
|
|
4
|
+
/** Immutable host record retaining the identity of user-owned content. */
|
|
5
|
+
export interface SvelteCell<T> {
|
|
6
|
+
readonly key: string;
|
|
7
|
+
readonly host: HTMLElement;
|
|
8
|
+
readonly item: T;
|
|
9
|
+
readonly position: Position;
|
|
10
|
+
}
|
|
11
|
+
/** Readonly store consumed by keyed components under the owning Svelte application. */
|
|
12
|
+
export interface SvelteCellBridge<T> {
|
|
13
|
+
readonly adapter: CellAdapter<T>;
|
|
14
|
+
readonly cells: Readable<readonly SvelteCell<T>[]>;
|
|
15
|
+
}
|
|
16
|
+
/** Create one bridge per engine view; render its keyed cells with the portal action. */
|
|
17
|
+
export declare function createSvelteCellAdapter<T>(): SvelteCellBridge<T>;
|
|
18
|
+
/** Move a framework-owned wrapper into its host without creating another Svelte root. */
|
|
19
|
+
export declare function portal(node: HTMLElement, target: HTMLElement): {
|
|
20
|
+
/** Move the same component subtree when its host changes. */
|
|
21
|
+
update(next: HTMLElement): void;
|
|
22
|
+
/** Remove only the owned wrapper and leave unrelated host content untouched. */
|
|
23
|
+
destroy(): void;
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAC;AAEjE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAe,MAAM,cAAc,CAAC;AAE7D,0EAA0E;AAC1E,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IACjB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;CAC7B;AACD,uFAAuF;AACvF,MAAM,WAAW,gBAAgB,CAAC,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IACjC,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,SAAS,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;CACpD;AAKD,wFAAwF;AACxF,wBAAgB,uBAAuB,CAAC,CAAC,KAAK,gBAAgB,CAAC,CAAC,CAAC,CAkChE;AACD,yFAAyF;AACzF,wBAAgB,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,WAAW;IAKzD,6DAA6D;iBAChD,WAAW;IAKxB,gFAAgF;;EAOnF"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { readonly, writable } from 'svelte/store';
|
|
2
|
+
import { ADAPTER_CONFIG } from "./config.js";
|
|
3
|
+
/** Copy coordinates without cloning or freezing user-owned data. */
|
|
4
|
+
function entry(key, host, item, position) {
|
|
5
|
+
return Object.freeze({ key, host, item, position: Object.freeze({ row: position.row, col: position.col }) });
|
|
6
|
+
}
|
|
7
|
+
/** Create one bridge per engine view; render its keyed cells with the portal action. */
|
|
8
|
+
export function createSvelteCellAdapter() {
|
|
9
|
+
let cells = Object.freeze([]);
|
|
10
|
+
const store = writable(cells);
|
|
11
|
+
let id = 0;
|
|
12
|
+
/** Publish an immutable snapshot to active component subscriptions. */
|
|
13
|
+
function publish(next) {
|
|
14
|
+
cells = Object.freeze(next);
|
|
15
|
+
store.set(cells);
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
cells: readonly(store),
|
|
19
|
+
adapter: {
|
|
20
|
+
/** Own one host while letting Svelte manage its descendants and lifecycle. */
|
|
21
|
+
mount(host, item, position) {
|
|
22
|
+
if (cells.some((cell) => cell.host === host))
|
|
23
|
+
throw new TypeError(ADAPTER_CONFIG.duplicateHostMessage);
|
|
24
|
+
const key = String(++id);
|
|
25
|
+
publish([...cells, entry(key, host, item, position)]);
|
|
26
|
+
let mounted = true;
|
|
27
|
+
return {
|
|
28
|
+
/** Retain the key so component state survives item updates. */
|
|
29
|
+
update(next, coordinates) {
|
|
30
|
+
if (!mounted)
|
|
31
|
+
return;
|
|
32
|
+
publish(cells.map((cell) => (cell.key === key ? entry(key, host, next, coordinates) : cell)));
|
|
33
|
+
},
|
|
34
|
+
/** Release once; stale operations cannot revive a removed component. */
|
|
35
|
+
unmount() {
|
|
36
|
+
if (!mounted)
|
|
37
|
+
return;
|
|
38
|
+
mounted = false;
|
|
39
|
+
publish(cells.filter((cell) => cell.key !== key));
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/** Move a framework-owned wrapper into its host without creating another Svelte root. */
|
|
47
|
+
export function portal(node, target) {
|
|
48
|
+
let host = target;
|
|
49
|
+
let active = true;
|
|
50
|
+
host.append(node);
|
|
51
|
+
return {
|
|
52
|
+
/** Move the same component subtree when its host changes. */
|
|
53
|
+
update(next) {
|
|
54
|
+
if (!active || next === host)
|
|
55
|
+
return;
|
|
56
|
+
host = next;
|
|
57
|
+
host.append(node);
|
|
58
|
+
},
|
|
59
|
+
/** Remove only the owned wrapper and leave unrelated host content untouched. */
|
|
60
|
+
destroy() {
|
|
61
|
+
if (!active)
|
|
62
|
+
return;
|
|
63
|
+
active = false;
|
|
64
|
+
if (node.parentNode === host)
|
|
65
|
+
node.remove();
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,44 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tikitaki_gagarinbefree/svelte",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.4",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"types": "./dist/index.d.ts",
|
|
6
|
+
"exports": {
|
|
7
|
+
".": {
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"import": "./dist/index.js"
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dist",
|
|
14
|
+
"src",
|
|
15
|
+
"README.md"
|
|
16
|
+
],
|
|
17
|
+
"sideEffects": false,
|
|
18
|
+
"peerDependencies": {
|
|
19
|
+
"tikitaki": "^0.1.4",
|
|
20
|
+
"svelte": "^5.57.2"
|
|
21
|
+
},
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"author": "gagarinbefree",
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "git+https://github.com/gagarinbefree/TikiTaki.git",
|
|
27
|
+
"directory": "packages/svelte"
|
|
28
|
+
},
|
|
29
|
+
"homepage": "https://github.com/gagarinbefree/TikiTaki#readme",
|
|
30
|
+
"bugs": {
|
|
31
|
+
"url": "https://github.com/gagarinbefree/TikiTaki/issues"
|
|
32
|
+
},
|
|
33
|
+
"publishConfig": {
|
|
34
|
+
"access": "public",
|
|
35
|
+
"registry": "https://registry.npmjs.org/"
|
|
36
|
+
},
|
|
37
|
+
"keywords": [
|
|
38
|
+
"swipe",
|
|
39
|
+
"gestures",
|
|
40
|
+
"typescript",
|
|
41
|
+
"ragged-grid"
|
|
42
|
+
],
|
|
43
|
+
"description": "svelte rendering adapter for the TikiTaki swipe engine"
|
|
44
|
+
}
|
package/src/config.ts
ADDED
package/src/index.ts
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { readonly, writable, type Readable } from 'svelte/store';
|
|
2
|
+
import { ADAPTER_CONFIG } from './config';
|
|
3
|
+
import type { Position } from 'tikitaki';
|
|
4
|
+
import type { CellAdapter, MountedCell } from 'tikitaki/dom';
|
|
5
|
+
|
|
6
|
+
/** Immutable host record retaining the identity of user-owned content. */
|
|
7
|
+
export interface SvelteCell<T> {
|
|
8
|
+
readonly key: string;
|
|
9
|
+
readonly host: HTMLElement;
|
|
10
|
+
readonly item: T;
|
|
11
|
+
readonly position: Position;
|
|
12
|
+
}
|
|
13
|
+
/** Readonly store consumed by keyed components under the owning Svelte application. */
|
|
14
|
+
export interface SvelteCellBridge<T> {
|
|
15
|
+
readonly adapter: CellAdapter<T>;
|
|
16
|
+
readonly cells: Readable<readonly SvelteCell<T>[]>;
|
|
17
|
+
}
|
|
18
|
+
/** Copy coordinates without cloning or freezing user-owned data. */
|
|
19
|
+
function entry<T>(key: string, host: HTMLElement, item: T, position: Position): SvelteCell<T> {
|
|
20
|
+
return Object.freeze({ key, host, item, position: Object.freeze({ row: position.row, col: position.col }) });
|
|
21
|
+
}
|
|
22
|
+
/** Create one bridge per engine view; render its keyed cells with the portal action. */
|
|
23
|
+
export function createSvelteCellAdapter<T>(): SvelteCellBridge<T> {
|
|
24
|
+
let cells: readonly SvelteCell<T>[] = Object.freeze([]);
|
|
25
|
+
const store = writable(cells);
|
|
26
|
+
let id = 0;
|
|
27
|
+
/** Publish an immutable snapshot to active component subscriptions. */
|
|
28
|
+
function publish(next: readonly SvelteCell<T>[]) {
|
|
29
|
+
cells = Object.freeze(next);
|
|
30
|
+
store.set(cells);
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
cells: readonly(store),
|
|
34
|
+
adapter: {
|
|
35
|
+
/** Own one host while letting Svelte manage its descendants and lifecycle. */
|
|
36
|
+
mount(host: HTMLElement, item: T, position: Position): MountedCell<T> {
|
|
37
|
+
if (cells.some((cell) => cell.host === host)) throw new TypeError(ADAPTER_CONFIG.duplicateHostMessage);
|
|
38
|
+
const key = String(++id);
|
|
39
|
+
publish([...cells, entry(key, host, item, position)]);
|
|
40
|
+
let mounted = true;
|
|
41
|
+
return {
|
|
42
|
+
/** Retain the key so component state survives item updates. */
|
|
43
|
+
update(next, coordinates) {
|
|
44
|
+
if (!mounted) return;
|
|
45
|
+
publish(cells.map((cell) => (cell.key === key ? entry(key, host, next, coordinates) : cell)));
|
|
46
|
+
},
|
|
47
|
+
/** Release once; stale operations cannot revive a removed component. */
|
|
48
|
+
unmount() {
|
|
49
|
+
if (!mounted) return;
|
|
50
|
+
mounted = false;
|
|
51
|
+
publish(cells.filter((cell) => cell.key !== key));
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/** Move a framework-owned wrapper into its host without creating another Svelte root. */
|
|
59
|
+
export function portal(node: HTMLElement, target: HTMLElement) {
|
|
60
|
+
let host = target;
|
|
61
|
+
let active = true;
|
|
62
|
+
host.append(node);
|
|
63
|
+
return {
|
|
64
|
+
/** Move the same component subtree when its host changes. */
|
|
65
|
+
update(next: HTMLElement) {
|
|
66
|
+
if (!active || next === host) return;
|
|
67
|
+
host = next;
|
|
68
|
+
host.append(node);
|
|
69
|
+
},
|
|
70
|
+
/** Remove only the owned wrapper and leave unrelated host content untouched. */
|
|
71
|
+
destroy() {
|
|
72
|
+
if (!active) return;
|
|
73
|
+
active = false;
|
|
74
|
+
if (node.parentNode === host) node.remove();
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
}
|