jqtree 1.8.11 → 1.9.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/bower.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jqTree",
3
- "version": "1.8.11",
3
+ "version": "1.9.0",
4
4
  "main": ["jqtree.css", "jqtree-circle.png", "tree.jquery.js"],
5
5
  "dependencies": {
6
6
  "jquery": ">=1.9"
package/eslint.config.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import cspellESLintPluginRecommended from "@cspell/eslint-plugin/recommended";
2
2
  import eslint from "@eslint/js";
3
3
  import tseslint from "typescript-eslint";
4
- import importPlugin from "eslint-plugin-import";
4
+ import importPlugin from "eslint-plugin-import-x";
5
5
  import jestDomPlugin from "eslint-plugin-jest-dom";
6
6
  import jestExtendedPlugin from "eslint-plugin-jest-extended";
7
7
  import perfectionistPlugin from "eslint-plugin-perfectionist";
@@ -25,6 +25,7 @@ export default [
25
25
  },
26
26
  },
27
27
  rules: {
28
+ "@typescript-eslint/consistent-type-imports": "error",
28
29
  "@typescript-eslint/explicit-function-return-type": "off",
29
30
  "@typescript-eslint/interface-name-prefix": "off",
30
31
  "@typescript-eslint/no-empty-object-type": "off",
@@ -60,12 +61,14 @@ export default [
60
61
  },
61
62
  },
62
63
  {
63
- files: ["src/test/**/*.ts"],
64
+ files: ["test/**/*.ts"],
64
65
  ...vitestPlugin.configs.all,
65
66
  },
66
67
  {
67
- files: ["src/test/**/*.ts"],
68
+ files: ["test/**/*.ts"],
68
69
  rules: {
70
+ "import-x/no-named-as-default": "off",
71
+ "import-x/no-named-as-default-member": "off",
69
72
  "vitest/no-duplicate-hooks": "off",
70
73
  "vitest/no-hooks": "off",
71
74
  "vitest/no-identical-title": "off",
@@ -80,19 +83,30 @@ export default [
80
83
  },
81
84
  },
82
85
  {
83
- files: ["src/test/**/*.ts"],
86
+ files: ["test/**/*.ts"],
84
87
  ...testingLibraryPlugin.configs["flat/dom"],
85
88
  },
86
89
  {
87
- files: ["src/test/**/*.ts"],
90
+ files: ["test/**/*.ts"],
88
91
  ...jestDomPlugin.configs["flat/recommended"],
89
92
  },
90
93
  {
91
- files: ["src/test/**/*.ts"],
94
+ files: ["test/**/*.ts"],
92
95
  ...jestExtendedPlugin.configs["flat/all"],
93
96
  },
94
97
  {
95
- files: ["src/playwright/**/*.ts"],
98
+ files: ["test/**/*.ts"],
99
+ rules: {
100
+ "perfectionist/sort-imports": [
101
+ "error",
102
+ {
103
+ internalPattern: ["^app"],
104
+ },
105
+ ],
106
+ },
107
+ },
108
+ {
109
+ files: ["playwright/**/*.ts"],
96
110
  ...playwrightPlugin.configs["flat/recommended"],
97
111
  },
98
112
  ];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jqtree",
3
- "version": "1.8.11",
3
+ "version": "1.9.0",
4
4
  "description": "Tree widget for jQuery",
5
5
  "keywords": [
6
6
  "jquery-plugin",
@@ -12,78 +12,72 @@
12
12
  "types": "./src/tree.jquery.d.ts",
13
13
  "repository": {
14
14
  "type": "git",
15
- "url": "https://github.com/mbraak/jqtree"
15
+ "url": "git+https://github.com/mbraak/jqtree.git"
16
16
  },
17
17
  "scripts": {
18
18
  "ci": "pnpm lint && pnpm tsc && pnpm test",
19
- "vitest": "vitest run --coverage --config config/vitest.config.ts",
20
- "vitest-watch": "vitest --config config/vitest.config.ts",
21
- "lint": "eslint src",
19
+ "vitest": "vitest run --coverage --config test/vitest.config.ts",
20
+ "vitest-watch": "vitest --config test/vitest.config.ts",
21
+ "lint": "eslint src playwright test",
22
22
  "production": "./config/production",
23
23
  "devserver": "SERVE=true rollup --config config/rollup.config.mjs --watch",
24
24
  "devserver-with-coverage": "COVERAGE=true SERVE=true rollup --config config/rollup.config.mjs",
25
25
  "build-with-coverage": "COVERAGE=true rollup --config config/rollup.config.mjs",
26
26
  "prettier": "prettier src/*.ts --write --tab-width 4",
27
27
  "tsc": "tsc --noEmit --project tsconfig.json",
28
- "playwright": "pnpm build-with-coverage && playwright test --config config/playwright.config.js",
28
+ "playwright": "pnpm build-with-coverage && playwright test --config playwright/playwright.config.js",
29
29
  "test": "pnpm vitest && pnpm playwright"
30
30
  },
31
31
  "peerDependencies": {
32
32
  "jquery": ">= 3"
33
33
  },
34
34
  "devDependencies": {
35
- "@babel/cli": "^7.28.6",
36
- "@babel/core": "^7.28.6",
37
- "@babel/preset-env": "^7.28.6",
38
- "@babel/preset-typescript": "^7.28.5",
39
- "@cspell/eslint-plugin": "^9.6.0",
40
- "@eslint/js": "^9.39.2",
41
- "@playwright/test": "^1.57.0",
42
- "@rollup/plugin-babel": "^6.1.0",
35
+ "@babel/cli": "^8.0.4",
36
+ "@babel/core": "^8.0.1",
37
+ "@babel/preset-env": "^8.0.2",
38
+ "@babel/preset-typescript": "^8.0.1",
39
+ "@cspell/eslint-plugin": "^10.0.1",
40
+ "@eslint/js": "^9.39.5",
41
+ "@playwright/test": "^1.62.0",
42
+ "@rollup/plugin-babel": "^7.1.0",
43
43
  "@rollup/plugin-node-resolve": "^16.0.3",
44
- "@rollup/plugin-terser": "^0.4.4",
44
+ "@rollup/plugin-terser": "^1.0.0",
45
45
  "@testing-library/dom": "^10.4.1",
46
- "@testing-library/jest-dom": "^6.9.1",
46
+ "@testing-library/jest-dom": "^7.0.0",
47
47
  "@testing-library/user-event": "^14.6.1",
48
- "@types/debug": "^4.1.12",
49
- "@types/jquery": "^3.5.33",
50
- "@types/node": "^25.0.10",
51
- "@vitest/coverage-istanbul": "^4.0.18",
52
- "@vitest/eslint-plugin": "^1.6.6",
53
- "autoprefixer": "^10.4.23",
54
- "axe-core": "^4.11.1",
55
- "babel-plugin-istanbul": "^7.0.1",
56
- "eslint": "^9.39.2",
57
- "eslint-plugin-import": "^2.32.0",
48
+ "@types/debug": "^4.1.13",
49
+ "@types/jquery": "^4.0.1",
50
+ "@types/node": "^26.1.1",
51
+ "@vitest/coverage-istanbul": "^4.1.10",
52
+ "@vitest/eslint-plugin": "^1.6.24",
53
+ "autoprefixer": "^10.5.4",
54
+ "axe-core": "^4.12.1",
55
+ "babel-plugin-istanbul": "^8.0.0",
56
+ "eslint": "^9.39.5",
57
+ "eslint-import-resolver-typescript": "^4.4.5",
58
+ "eslint-plugin-import-x": "^4.17.1",
58
59
  "eslint-plugin-jest-dom": "^5.5.0",
59
60
  "eslint-plugin-jest-extended": "^3.0.1",
60
- "eslint-plugin-perfectionist": "^5.4.0",
61
- "eslint-plugin-playwright": "^2.5.0",
62
- "eslint-plugin-testing-library": "^7.15.4",
63
- "givens": "^1.3.9",
61
+ "eslint-plugin-perfectionist": "^5.10.0",
62
+ "eslint-plugin-playwright": "^2.10.5",
63
+ "eslint-plugin-testing-library": "^7.16.2",
64
64
  "jest-extended": "^7.0.0",
65
+ "jsdom": "^29.1.1",
65
66
  "jsdom-testing-mocks": "^1.16.0",
66
- "jsonfile": "^6.2.0",
67
- "lodash": "^4.17.23",
68
- "msw": "^2.12.7",
69
- "postcss": "^8.5.6",
67
+ "jsonfile": "^6.2.1",
68
+ "lodash": "^4.18.1",
69
+ "msw": "^2.15.0",
70
+ "postcss": "^8.5.23",
70
71
  "postcss-cli": "^11.0.1",
71
72
  "postcss-import": "^16.1.1",
72
73
  "postcss-load-config": "^6.0.1",
73
74
  "postcss-nested": "^7.0.2",
74
- "prettier": "^3.8.1",
75
- "rollup": "^4.56.0",
75
+ "prettier": "^3.9.6",
76
+ "rollup": "^4.62.2",
76
77
  "rollup-plugin-serve": "^3.0.0",
77
78
  "tslib": "^2.8.1",
78
- "typescript": "^5.9.3",
79
- "typescript-eslint": "^8.53.1",
80
- "vitest": "^4.0.18"
81
- },
82
- "pnpm": {
83
- "onlyBuiltDependencies": [
84
- "esbuild",
85
- "msw",
86
- "unrs-resolver"
87
- ]
79
+ "typescript": "^6.0.3",
80
+ "typescript-eslint": "^8.65.0",
81
+ "vitest": "^4.1.10"
88
82
  }
89
83
  }
@@ -0,0 +1,4 @@
1
+ allowBuilds:
2
+ esbuild: true
3
+ msw: true
4
+ unrs-resolver: true
@@ -0,0 +1,48 @@
1
+ export type AnimationSpeed = "fast" | "slow" | number;
2
+
3
+ export const getAnimationDuration = (duration: AnimationSpeed): number => {
4
+ if (typeof duration === "number") {
5
+ return duration;
6
+ }
7
+
8
+ return duration === "slow" ? 600 : 200;
9
+ };
10
+
11
+ export const slideDown = (
12
+ element: HTMLElement,
13
+ animationSpeed: AnimationSpeed,
14
+ onFinished: () => void,
15
+ ): void => {
16
+ element.style.display = "block";
17
+
18
+ const animation = element.animate(
19
+ [
20
+ { height: "0", overflow: "hidden" },
21
+ { height: `${element.scrollHeight}px`, overflow: "hidden" },
22
+ ],
23
+ { duration: getAnimationDuration(animationSpeed) },
24
+ );
25
+
26
+ animation.onfinish = () => {
27
+ onFinished();
28
+ };
29
+ };
30
+
31
+ export const slideUp = (
32
+ element: HTMLElement,
33
+ animationSpeed: AnimationSpeed,
34
+ onFinished: () => void,
35
+ ): void => {
36
+ const animation = element.animate(
37
+ [
38
+ { height: `${element.scrollHeight}px`, overflow: "hidden" },
39
+ { height: "0", overflow: "hidden" },
40
+ ],
41
+ { duration: getAnimationDuration(animationSpeed) },
42
+ );
43
+
44
+ animation.onfinish = () => {
45
+ element.style.display = "none";
46
+ onFinished();
47
+ };
48
+ };
package/src/dataLoader.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { LoadData, TriggerEvent } from "./jqtreeMethodTypes";
2
- import { DataFilter, OnLoadFailed, OnLoading } from "./jqtreeOptions";
3
- import { Node } from "./node";
1
+ import type { LoadData, TriggerEvent } from "./jqtreeMethodTypes";
2
+ import type { DataFilter, OnLoadFailed, OnLoading } from "./jqtreeOptions";
3
+ import type { Node } from "./node";
4
4
 
5
5
  export type HandleFinishedLoading = () => void;
6
6
 
@@ -14,12 +14,12 @@ interface DataLoaderParams {
14
14
  }
15
15
 
16
16
  export default class DataLoader {
17
- private dataFilter?: DataFilter;
18
- private loadData: LoadData;
19
- private onLoadFailed?: OnLoadFailed;
20
- private onLoading?: OnLoading;
21
- private treeElement: HTMLElement;
22
- private triggerEvent: TriggerEvent;
17
+ private _dataFilter?: DataFilter;
18
+ private _loadData: LoadData;
19
+ private _onLoadFailed?: OnLoadFailed;
20
+ private _onLoading?: OnLoading;
21
+ private _treeElement: HTMLElement;
22
+ private _triggerEvent: TriggerEvent;
23
23
 
24
24
  constructor({
25
25
  dataFilter,
@@ -29,12 +29,12 @@ export default class DataLoader {
29
29
  treeElement,
30
30
  triggerEvent,
31
31
  }: DataLoaderParams) {
32
- this.dataFilter = dataFilter;
33
- this.loadData = loadData;
34
- this.onLoadFailed = onLoadFailed;
35
- this.onLoading = onLoading;
36
- this.treeElement = treeElement;
37
- this.triggerEvent = triggerEvent;
32
+ this._dataFilter = dataFilter;
33
+ this._loadData = loadData;
34
+ this._onLoadFailed = onLoadFailed;
35
+ this._onLoading = onLoading;
36
+ this._treeElement = treeElement;
37
+ this._triggerEvent = triggerEvent;
38
38
  }
39
39
 
40
40
  public loadFromUrl(
@@ -46,18 +46,18 @@ export default class DataLoader {
46
46
  return;
47
47
  }
48
48
 
49
- const element = this.getDomElement(parentNode);
50
- this.addLoadingClass(element);
51
- this.notifyLoading(true, parentNode, element);
49
+ const element = this._getDomElement(parentNode);
50
+ this._addLoadingClass(element);
51
+ this._notifyLoading(true, parentNode, element);
52
52
 
53
53
  const stopLoading = (): void => {
54
- this.removeLoadingClass(element);
55
- this.notifyLoading(false, parentNode, element);
54
+ this._removeLoadingClass(element);
55
+ this._notifyLoading(false, parentNode, element);
56
56
  };
57
57
 
58
- const handleSuccess = (data: NodeData[] | string): void => {
58
+ const handleSuccess = (data: NodeData[]): void => {
59
59
  stopLoading();
60
- this.loadData(this.parseData(data), parentNode);
60
+ this._loadData(this._parseData(data), parentNode);
61
61
 
62
62
  if (onFinished && typeof onFinished === "function") {
63
63
  onFinished();
@@ -67,67 +67,57 @@ export default class DataLoader {
67
67
  const handleError = (jqXHR: JQuery.jqXHR): void => {
68
68
  stopLoading();
69
69
 
70
- if (this.onLoadFailed) {
71
- this.onLoadFailed(jqXHR);
70
+ if (this._onLoadFailed) {
71
+ this._onLoadFailed(jqXHR);
72
72
  }
73
73
  };
74
74
 
75
- this.submitRequest(urlInfo, handleSuccess, handleError);
75
+ this._submitRequest(urlInfo, handleSuccess, handleError);
76
76
  }
77
77
 
78
- private addLoadingClass(element: HTMLElement): void {
78
+ private _addLoadingClass(element: HTMLElement): void {
79
79
  element.classList.add("jqtree-loading");
80
80
  }
81
81
 
82
- private getDomElement(parentNode: Node | null): HTMLElement {
82
+ private _getDomElement(parentNode: Node | null): HTMLElement {
83
83
  if (parentNode?.element) {
84
84
  return parentNode.element;
85
85
  } else {
86
- return this.treeElement;
86
+ return this._treeElement;
87
87
  }
88
88
  }
89
89
 
90
- private notifyLoading(
90
+ private _notifyLoading(
91
91
  isLoading: boolean,
92
92
  node: Node | null,
93
93
  element: HTMLElement,
94
94
  ): void {
95
95
  const $el = jQuery(element);
96
96
 
97
- if (this.onLoading) {
98
- this.onLoading(isLoading, node, $el);
97
+ if (this._onLoading) {
98
+ this._onLoading(isLoading, node, $el);
99
99
  }
100
100
 
101
- this.triggerEvent("tree.loading_data", {
101
+ this._triggerEvent("tree.loading_data", {
102
102
  $el,
103
103
  isLoading,
104
104
  node,
105
105
  });
106
106
  }
107
107
 
108
- private parseData(data: NodeData[] | string): NodeData[] {
109
- const getParsedData = () => {
110
- if (typeof data === "string") {
111
- return JSON.parse(data) as NodeData[];
112
- } else {
113
- return data;
114
- }
115
- };
116
-
117
- const parsedData = getParsedData();
118
-
119
- if (this.dataFilter) {
120
- return this.dataFilter(parsedData);
108
+ private _parseData(data: NodeData[]): NodeData[] {
109
+ if (this._dataFilter) {
110
+ return this._dataFilter(data);
121
111
  } else {
122
- return parsedData;
112
+ return data;
123
113
  }
124
114
  }
125
115
 
126
- private removeLoadingClass(element: HTMLElement): void {
116
+ private _removeLoadingClass(element: HTMLElement): void {
127
117
  element.classList.remove("jqtree-loading");
128
118
  }
129
119
 
130
- private submitRequest(
120
+ private _submitRequest(
131
121
  urlInfoInput: JQuery.AjaxSettings | string,
132
122
  handleSuccess: JQuery.Ajax.SuccessCallback<any>,
133
123
  handleError: JQuery.Ajax.ErrorCallback<any>,
@@ -7,9 +7,9 @@ interface DragElementParams {
7
7
  }
8
8
 
9
9
  class DragElement {
10
- private element: HTMLElement;
11
- private offsetX: number;
12
- private offsetY: number;
10
+ private _element: HTMLElement;
11
+ private _offsetX: number;
12
+ private _offsetY: number;
13
13
 
14
14
  constructor({
15
15
  autoEscape,
@@ -18,24 +18,24 @@ class DragElement {
18
18
  offsetY,
19
19
  treeElement,
20
20
  }: DragElementParams) {
21
- this.offsetX = offsetX;
22
- this.offsetY = offsetY;
21
+ this._offsetX = offsetX;
22
+ this._offsetY = offsetY;
23
23
 
24
- this.element = this.createElement(nodeName, autoEscape);
24
+ this._element = this._createElement(nodeName, autoEscape);
25
25
 
26
- treeElement.appendChild(this.element);
26
+ treeElement.appendChild(this._element);
27
27
  }
28
28
 
29
29
  public move(pageX: number, pageY: number): void {
30
- this.element.style.left = `${pageX - this.offsetX}px`;
31
- this.element.style.top = `${pageY - this.offsetY}px`;
30
+ this._element.style.left = `${pageX - this._offsetX}px`;
31
+ this._element.style.top = `${pageY - this._offsetY}px`;
32
32
  }
33
33
 
34
34
  public remove(): void {
35
- this.element.remove();
35
+ this._element.remove();
36
36
  }
37
37
 
38
- private createElement(nodeName: string, autoEscape: boolean) {
38
+ private _createElement(nodeName: string, autoEscape: boolean) {
39
39
  const element = document.createElement("span");
40
40
  element.classList.add("jqtree-title", "jqtree-dragging");
41
41
 
@@ -1,7 +1,8 @@
1
- import { Node, Position } from "../node";
2
- import { getOffsetTop } from "../util";
1
+ import type { Node, Position } from "../node";
2
+ import type { HitArea } from "./types";
3
+
4
+ import { getOffsetTop } from "../positionUtils";
3
5
  import iterateVisibleNodes from "./iterateVisibleNodes";
4
- import { HitArea } from "./types";
5
6
 
6
7
  interface HitPosition {
7
8
  node: Node;