@appulsauce/svelte-grid 2.0.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.
@@ -0,0 +1,23 @@
1
+ export function assertGridOptions(options) {
2
+ const { cols, rows, itemSize, collision } = options;
3
+ if (rows !== 0 && collision && collision !== 'none') {
4
+ console.warn('`rows` is ignored and setted to 0 when `collision` is not `none`');
5
+ }
6
+ if (collision && collision !== 'none' && itemSize?.height === undefined) {
7
+ throw new Error('If `collision` is not `none`, the `itemSize.height` parameter must be specified');
8
+ }
9
+ if ((cols === 0 && itemSize?.width === undefined) ||
10
+ (typeof cols === 'object' && Object.values(cols).includes(0) && itemSize?.width === undefined)) {
11
+ throw new Error('If `cols` === `0`, the `itemSize.width` parameter must be specified');
12
+ }
13
+ if ((rows === 0 && itemSize?.height === undefined) ||
14
+ (typeof rows === 'object' && Object.values(rows).includes(0) && itemSize?.height === undefined)) {
15
+ throw new Error('If `rows` === `0`, the `itemSize.height` parameter must be specified');
16
+ }
17
+ if (typeof cols === 'number' && cols < 0) {
18
+ throw new Error('`cols` must be greater than or equal to `0`');
19
+ }
20
+ if (typeof rows === 'number' && rows < 0) {
21
+ throw new Error('`rows` must be greater than or equal to `0`');
22
+ }
23
+ }
@@ -0,0 +1,2 @@
1
+ import type { Breakpoints, GridSize } from '../types';
2
+ export declare function findGridSize(cols: GridSize, width: number, breakpoints: Breakpoints): number;
@@ -0,0 +1,9 @@
1
+ export function findGridSize(cols, width, breakpoints) {
2
+ if (typeof cols == 'number') {
3
+ return cols;
4
+ }
5
+ return Object.entries(cols).reduce((acc, obj) => Math.abs(width - breakpoints[obj[0]]) <
6
+ Math.abs(width - breakpoints[acc[0]])
7
+ ? obj
8
+ : acc)[1];
9
+ }
@@ -0,0 +1,9 @@
1
+ import type { GridDimensions, LayoutItem } from '../types';
2
+ export declare function isItemColliding(item: LayoutItem, otherItem: LayoutItem): boolean;
3
+ export declare function getCollisions(currentItem: LayoutItem, items: LayoutItem[]): LayoutItem[];
4
+ export declare function hasCollisions(currentItem: LayoutItem, items: LayoutItem[]): boolean;
5
+ export declare function getGridDimensions(items: LayoutItem[]): GridDimensions;
6
+ export declare function getAvailablePosition(currentItem: LayoutItem, items: LayoutItem[], maxCols: number, maxRows: number): {
7
+ x: number;
8
+ y: number;
9
+ } | null;
@@ -0,0 +1,43 @@
1
+ export function isItemColliding(item, otherItem) {
2
+ return (item.id !== otherItem.id &&
3
+ item.x <= otherItem.x + otherItem.w - 1 &&
4
+ item.y <= otherItem.y + otherItem.h - 1 &&
5
+ item.x + item.w - 1 >= otherItem.x &&
6
+ item.y + item.h - 1 >= otherItem.y);
7
+ }
8
+ export function getCollisions(currentItem, items) {
9
+ return items.filter((item) => isItemColliding(currentItem, item));
10
+ }
11
+ export function hasCollisions(currentItem, items) {
12
+ return items.some((item) => isItemColliding(currentItem, item));
13
+ }
14
+ export function getGridDimensions(items) {
15
+ let cols = 0;
16
+ let rows = 0;
17
+ items.forEach((item) => {
18
+ cols = Math.max(cols, item.x + item.w);
19
+ rows = Math.max(rows, item.y + item.h);
20
+ });
21
+ return { cols, rows };
22
+ }
23
+ export function getAvailablePosition(currentItem, items, maxCols, maxRows) {
24
+ let { cols, rows } = getGridDimensions(items);
25
+ if (maxCols < Infinity)
26
+ cols = maxCols;
27
+ if (maxRows < Infinity)
28
+ rows = maxRows;
29
+ for (let y = 0; y <= rows - currentItem.h; y++) {
30
+ for (let x = 0; x <= cols - currentItem.w; x++) {
31
+ const item = { ...currentItem, x, y };
32
+ if (!hasCollisions(item, items)) {
33
+ const newPosition = { x, y };
34
+ return newPosition;
35
+ }
36
+ }
37
+ }
38
+ if (maxRows === Infinity)
39
+ return { x: 0, y: rows };
40
+ if (maxCols === Infinity)
41
+ return { x: cols, y: 0 };
42
+ return null;
43
+ }
@@ -0,0 +1,13 @@
1
+ import type { GridParams, LayoutItem, ItemPosition, ItemSize, Position, Size } from '../types';
2
+ export declare function coordinate2position(coordinate: number, cellSize: number, gap: number): number;
3
+ export declare function coordinate2size(coordinate: number, cellSize: number, gap: number): number;
4
+ export declare function position2coordinate(position: number, cellSize: number, gap: number): number;
5
+ export declare function size2coordinate(size: number, cellSize: number, gap: number): number;
6
+ export type SnapGridParams = Required<Pick<GridParams, 'itemSize' | 'gap' | 'maxCols' | 'maxRows'>>;
7
+ export declare function snapOnMove(left: number, top: number, item: LayoutItem, gridParams: SnapGridParams): Position;
8
+ export declare function snapOnResize(width: number, height: number, item: LayoutItem, gridParams: SnapGridParams): Size;
9
+ export declare function calcPosition(item: LayoutItem, options: {
10
+ itemSize: ItemSize;
11
+ gap: number;
12
+ }): ItemPosition & ItemSize;
13
+ export declare function clamp(num: number, min: number, max: number): number;
@@ -0,0 +1,42 @@
1
+ export function coordinate2position(coordinate, cellSize, gap) {
2
+ return coordinate * cellSize + (coordinate + 1) * gap;
3
+ }
4
+ export function coordinate2size(coordinate, cellSize, gap) {
5
+ return coordinate * cellSize + (coordinate - 1) * gap;
6
+ }
7
+ export function position2coordinate(position, cellSize, gap) {
8
+ return Math.round(position / (cellSize + gap));
9
+ }
10
+ export function size2coordinate(size, cellSize, gap) {
11
+ return position2coordinate(size + gap * 2, cellSize, gap);
12
+ }
13
+ export function snapOnMove(left, top, item, gridParams) {
14
+ const { itemSize, gap } = gridParams;
15
+ const { w, h } = item;
16
+ let x = position2coordinate(left, itemSize.width, gap);
17
+ let y = position2coordinate(top, itemSize.height, gap);
18
+ x = clamp(x, 0, gridParams.maxCols - w);
19
+ y = clamp(y, 0, gridParams.maxRows - h);
20
+ return { x, y };
21
+ }
22
+ export function snapOnResize(width, height, item, gridParams) {
23
+ const { itemSize, gap } = gridParams;
24
+ const { x, y } = item;
25
+ let w = position2coordinate(width + gap * 2, itemSize.width, gap);
26
+ let h = position2coordinate(height + gap * 2, itemSize.height, gap);
27
+ w = clamp(w, 0, gridParams.maxCols - x);
28
+ h = clamp(h, 0, gridParams.maxRows - y);
29
+ return { w, h };
30
+ }
31
+ export function calcPosition(item, options) {
32
+ const { itemSize, gap } = options;
33
+ return {
34
+ left: coordinate2position(item.x, itemSize.width, gap),
35
+ top: coordinate2position(item.y, itemSize.height, gap),
36
+ width: coordinate2size(item.w, itemSize.width, gap),
37
+ height: coordinate2size(item.h, itemSize.height, gap)
38
+ };
39
+ }
40
+ export function clamp(num, min, max) {
41
+ return Math.max(Math.min(num, max), min);
42
+ }
@@ -0,0 +1,3 @@
1
+ export type RequireAtLeastOne<T> = {
2
+ [K in keyof T]-?: Required<Pick<T, K>> & Partial<Pick<T, Exclude<keyof T, K>>>;
3
+ }[keyof T];
@@ -0,0 +1 @@
1
+ export {};
package/package.json ADDED
@@ -0,0 +1,94 @@
1
+ {
2
+ "name": "@appulsauce/svelte-grid",
3
+ "version": "2.0.0",
4
+ "description": "A draggable and resizable grid layout, for Svelte 5",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "git+https://github.com/KaiErikNiermann/svelte-grid-extended.git"
8
+ },
9
+ "scripts": {
10
+ "dev": "vite dev",
11
+ "build": "vite build && pnpm package",
12
+ "preview": "vite preview",
13
+ "package": "svelte-kit sync && svelte-package && publint",
14
+ "prepublishOnly": "pnpm package",
15
+ "test": "vitest",
16
+ "test:unit": "vitest run",
17
+ "coverage": "vitest run --coverage",
18
+ "e2e": "playwright test",
19
+ "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
20
+ "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
21
+ "lint": "prettier --check . && eslint .",
22
+ "format": "prettier --write .",
23
+ "prepare": "husky"
24
+ },
25
+ "exports": {
26
+ ".": {
27
+ "types": "./dist/index.d.ts",
28
+ "svelte": "./dist/index.js",
29
+ "default": "./dist/index.js"
30
+ },
31
+ "./package.json": "./package.json"
32
+ },
33
+ "files": [
34
+ "dist",
35
+ "!dist/**/*.test.*",
36
+ "!dist/**/*.spec.*"
37
+ ],
38
+ "keywords": [
39
+ "svelte",
40
+ "svelte5",
41
+ "grid",
42
+ "drag",
43
+ "draggable",
44
+ "resize",
45
+ "resizable",
46
+ "fluid",
47
+ "responsive"
48
+ ],
49
+ "author": "cuire <garwes@icloud.com>",
50
+ "license": "MIT",
51
+ "bugs": {
52
+ "url": "https://github.com/KaiErikNiermann/svelte-grid-extended/issues"
53
+ },
54
+ "homepage": "https://github.com/KaiErikNiermann/svelte-grid-extended#readme",
55
+ "peerDependencies": {
56
+ "svelte": "^5.0.0"
57
+ },
58
+ "devDependencies": {
59
+ "@playwright/test": "^1.49.0",
60
+ "@sveltejs/adapter-auto": "^3.3.1",
61
+ "@sveltejs/kit": "^2.15.0",
62
+ "@sveltejs/package": "^2.3.7",
63
+ "@sveltejs/vite-plugin-svelte": "^5.0.0",
64
+ "@testing-library/svelte": "^5.2.6",
65
+ "@vitest/coverage-v8": "^2.1.0",
66
+ "autoprefixer": "^10.4.20",
67
+ "daisyui": "^4.12.0",
68
+ "eslint": "^9.17.0",
69
+ "eslint-config-prettier": "^9.1.0",
70
+ "eslint-plugin-svelte": "^2.46.0",
71
+ "globals": "^15.14.0",
72
+ "husky": "^9.1.0",
73
+ "jsdom": "^25.0.1",
74
+ "postcss": "^8.4.49",
75
+ "prettier": "^3.4.2",
76
+ "prettier-plugin-svelte": "^3.3.2",
77
+ "publint": "^0.2.12",
78
+ "svelte": "^5.16.0",
79
+ "svelte-check": "^4.1.0",
80
+ "tailwindcss": "^3.4.17",
81
+ "tslib": "^2.8.1",
82
+ "typescript": "^5.7.2",
83
+ "typescript-eslint": "^8.18.0",
84
+ "vite": "^6.0.0",
85
+ "vitest": "^2.1.0"
86
+ },
87
+ "type": "module",
88
+ "publishConfig": {
89
+ "access": "public"
90
+ },
91
+ "svelte": "./dist/index.js",
92
+ "types": "./dist/index.d.ts",
93
+ "packageManager": "pnpm@9.15.0"
94
+ }