tree-element 0.2.0 → 0.3.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.
Files changed (123) hide show
  1. package/README.md +14 -6
  2. package/lib/animation.d.ts +2 -2
  3. package/lib/animation.d.ts.map +1 -1
  4. package/lib/animation.js +13 -9
  5. package/lib/animation.js.map +1 -1
  6. package/lib/dataLoader.d.ts +1 -0
  7. package/lib/dataLoader.d.ts.map +1 -1
  8. package/lib/dataLoader.js +8 -0
  9. package/lib/dataLoader.js.map +1 -1
  10. package/lib/dragAndDropHandler/dragElement.d.ts.map +1 -1
  11. package/lib/dragAndDropHandler/dragElement.js +2 -1
  12. package/lib/dragAndDropHandler/dragElement.js.map +1 -1
  13. package/lib/dragAndDropHandler/index.d.ts.map +1 -1
  14. package/lib/dragAndDropHandler/index.js +56 -65
  15. package/lib/dragAndDropHandler/index.js.map +1 -1
  16. package/lib/dragAndDropHandler/iterateVisibleNodes.d.ts.map +1 -1
  17. package/lib/dragAndDropHandler/iterateVisibleNodes.js +16 -15
  18. package/lib/dragAndDropHandler/iterateVisibleNodes.js.map +1 -1
  19. package/lib/elementsRenderer.d.ts +5 -1
  20. package/lib/elementsRenderer.d.ts.map +1 -1
  21. package/lib/elementsRenderer.js +62 -39
  22. package/lib/elementsRenderer.js.map +1 -1
  23. package/lib/events.d.ts +44 -11
  24. package/lib/events.d.ts.map +1 -1
  25. package/lib/index.d.ts +31 -8
  26. package/lib/index.d.ts.map +1 -1
  27. package/lib/index.js +162 -122
  28. package/lib/index.js.map +1 -1
  29. package/lib/keyHandler.d.ts +11 -5
  30. package/lib/keyHandler.d.ts.map +1 -1
  31. package/lib/keyHandler.js +87 -33
  32. package/lib/keyHandler.js.map +1 -1
  33. package/lib/methodTypes.d.ts +2 -2
  34. package/lib/methodTypes.d.ts.map +1 -1
  35. package/lib/mouseHandler.d.ts +1 -1
  36. package/lib/mouseHandler.d.ts.map +1 -1
  37. package/lib/mouseHandler.js +10 -7
  38. package/lib/mouseHandler.js.map +1 -1
  39. package/lib/node.d.ts +45 -15
  40. package/lib/node.d.ts.map +1 -1
  41. package/lib/node.js +136 -139
  42. package/lib/node.js.map +1 -1
  43. package/lib/nodeElement/folderElement.d.ts +1 -1
  44. package/lib/nodeElement/folderElement.d.ts.map +1 -1
  45. package/lib/nodeElement/folderElement.js +46 -57
  46. package/lib/nodeElement/folderElement.js.map +1 -1
  47. package/lib/nodeElement/ghostDropHint.d.ts.map +1 -1
  48. package/lib/nodeElement/ghostDropHint.js +8 -4
  49. package/lib/nodeElement/ghostDropHint.js.map +1 -1
  50. package/lib/nodeElement/index.d.ts.map +1 -1
  51. package/lib/nodeElement/index.js +6 -6
  52. package/lib/nodeElement/index.js.map +1 -1
  53. package/lib/nodeUtils.d.ts.map +1 -1
  54. package/lib/nodeUtils.js +1 -1
  55. package/lib/nodeUtils.js.map +1 -1
  56. package/lib/options.d.ts +23 -6
  57. package/lib/options.d.ts.map +1 -1
  58. package/lib/requestUrl.d.ts +0 -1
  59. package/lib/requestUrl.d.ts.map +1 -1
  60. package/lib/requestUrl.js +4 -22
  61. package/lib/requestUrl.js.map +1 -1
  62. package/lib/saveStateHandler.d.ts.map +1 -1
  63. package/lib/saveStateHandler.js +21 -41
  64. package/lib/saveStateHandler.js.map +1 -1
  65. package/lib/scrollHandler/containerScrollParent.d.ts.map +1 -1
  66. package/lib/scrollHandler/containerScrollParent.js +3 -8
  67. package/lib/scrollHandler/containerScrollParent.js.map +1 -1
  68. package/lib/scrollHandler/createScrollParent.d.ts.map +1 -1
  69. package/lib/scrollHandler/createScrollParent.js +4 -5
  70. package/lib/scrollHandler/createScrollParent.js.map +1 -1
  71. package/lib/scrollHandler/documentScrollParent.d.ts.map +1 -1
  72. package/lib/scrollHandler/documentScrollParent.js +3 -9
  73. package/lib/scrollHandler/documentScrollParent.js.map +1 -1
  74. package/lib/scrollHandler/scrollParent.d.ts.map +1 -1
  75. package/lib/scrollHandler/scrollParent.js +19 -17
  76. package/lib/scrollHandler/scrollParent.js.map +1 -1
  77. package/lib/selectNodeHandler.d.ts +3 -1
  78. package/lib/selectNodeHandler.d.ts.map +1 -1
  79. package/lib/selectNodeHandler.js +27 -37
  80. package/lib/selectNodeHandler.js.map +1 -1
  81. package/lib/setDefaultOptions.d.ts +3 -0
  82. package/lib/setDefaultOptions.d.ts.map +1 -1
  83. package/lib/setDefaultOptions.js +21 -20
  84. package/lib/setDefaultOptions.js.map +1 -1
  85. package/lib/util.d.ts.map +1 -1
  86. package/lib/util.js +1 -1
  87. package/lib/util.js.map +1 -1
  88. package/lib/version.d.ts +1 -1
  89. package/lib/version.js +1 -1
  90. package/lib/version.js.map +1 -1
  91. package/package.json +44 -35
  92. package/src/animation.ts +13 -11
  93. package/src/dataLoader.ts +11 -0
  94. package/src/dragAndDropHandler/dragElement.ts +2 -1
  95. package/src/dragAndDropHandler/index.ts +70 -75
  96. package/src/dragAndDropHandler/iterateVisibleNodes.ts +18 -16
  97. package/src/elementsRenderer.ts +76 -46
  98. package/src/events.ts +44 -11
  99. package/src/index.ts +210 -150
  100. package/src/keyHandler.ts +95 -41
  101. package/src/methodTypes.ts +3 -3
  102. package/src/mouseHandler.ts +10 -7
  103. package/src/node.ts +155 -148
  104. package/src/nodeElement/folderElement.ts +54 -63
  105. package/src/nodeElement/ghostDropHint.ts +4 -2
  106. package/src/nodeElement/index.ts +9 -15
  107. package/src/nodeUtils.ts +1 -1
  108. package/src/options.ts +23 -6
  109. package/src/requestUrl.ts +4 -25
  110. package/src/saveStateHandler.ts +29 -43
  111. package/src/scrollHandler/containerScrollParent.ts +3 -9
  112. package/src/scrollHandler/createScrollParent.ts +1 -2
  113. package/src/scrollHandler/documentScrollParent.ts +5 -11
  114. package/src/scrollHandler/scrollParent.ts +29 -25
  115. package/src/selectNodeHandler.ts +34 -38
  116. package/src/setDefaultOptions.ts +31 -19
  117. package/src/util.ts +1 -2
  118. package/src/version.ts +1 -1
  119. package/tree_element.css +87 -69
  120. package/tree_element.debug.js +717 -659
  121. package/tree_element.debug.js.map +1 -1
  122. package/tree_element.js +2 -2
  123. package/tree_element.js.map +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"setDefaultOptions.js","sources":["../src/setDefaultOptions.ts"],"sourcesContent":["import type { TreeElementOptions } from \"./options\";\n\nimport { DEFAULT_CLASS_PREFIX } from \"./classNames\";\nimport { Node } from \"./node\";\n\nconst defaults: TreeElementOptions = {\n animationSpeed: \"fast\",\n autoEscape: true,\n autoOpen: false, // true / false / int (open n levels starting at 0)\n buttonLeft: true,\n classPrefix: DEFAULT_CLASS_PREFIX, // the prefix of all css classes\n // The symbol to use for a closed node - ► BLACK RIGHT-POINTING POINTER\n // http://www.fileformat.info/info/unicode/char/25ba/index.htm\n // closedIcon: undefined,\n // commonClassName: undefined, // the class of every element; the default is \"<classPrefix>-common\"\n // data: undefined,\n // dataFilter: undefined,\n // dataUrl: undefined,\n dragAndDrop: false,\n keyboardSupport: true,\n nodeClass: Node,\n // onCanMove: undefined, // Can this node be moved?\n // onCanMoveTo: undefined, // Can this node be moved to this position? function(moved_node, target_node, position)\n // onCanSelectNode: undefined,\n // onCreateLi: undefined,\n // onDragMove: undefined,\n // onDragStop: undefined,\n // onGetStateFromStorage: undefined,\n // onIsMoveHandle: undefined,\n // onSetStateFromStorage: undefined,\n // openedIcon: undefined,\n openFolderDelay: 500, // The delay for opening a folder during drag and drop; the value is in milliseconds\n // The symbol to use for an open node - ▼ BLACK DOWN-POINTING TRIANGLE\n // http://www.fileformat.info/info/unicode/char/25bc/index.htm\n // rtl: undefined, // right-to-left support; true / false (default)\n saveState: false, // true / false / string (local storage key; the default key is \"tree\")\n selectable: true,\n showEmptyFolder: false,\n slide: true, // must display slide animation?\n startDndDelay: 300, // The delay for starting dnd (in milliseconds)\n tabIndex: 0,\n // treeClassName: undefined, // the class of the root element; the default is classPrefix\n useContextMenu: true,\n};\n\nconst setDefaultOptions = (\n htmlElement: HTMLElement,\n inputOptions: Partial<TreeElementOptions>,\n): TreeElementOptions => {\n const options = { ...defaults, ...inputOptions };\n\n options.dataUrl ??= htmlElement.dataset.url;\n options.rtl ??= getRtlOptionFromHTMLElement(htmlElement);\n options.closedIcon ??= getDefaultClosedIcon(options);\n options.openedIcon ??= \"&#x25bc;\";\n\n return options;\n};\n\nconst getDefaultClosedIcon = (options: TreeElementOptions): string => {\n if (options.rtl) {\n // triangle to the left\n return \"&#x25c0;\";\n } else {\n // triangle to the right\n return \"&#x25ba;\";\n }\n};\n\nconst getRtlOptionFromHTMLElement = (htmlElement: HTMLElement): boolean => {\n const dataRtl = htmlElement.dataset.rtl;\n\n if (dataRtl == \"\") {\n return true;\n } else if (dataRtl === \"false\") {\n return false;\n } else {\n return Boolean(dataRtl);\n }\n};\n\nexport default setDefaultOptions;\n"],"names":[],"mappings":";;;AAKA,IAAM,QAA4B,GAAG;AACnC,EAAA,cAAc,EAAE,MAAM;AACtB,EAAA,UAAU,EAAE,IAAI;AAChB,EAAA,QAAQ,EAAE,KAAK;AAAE;AACjB,EAAA,UAAU,EAAE,IAAI;AAChB,EAAA,WAAW,EAAE,oBAAoB;AAAE;AACnC;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAA,WAAW,EAAE,KAAK;AAClB,EAAA,eAAe,EAAE,IAAI;AACrB,EAAA,SAAS,EAAE,IAAI;AACf;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAA,eAAe,EAAE,GAAG;AAAE;AACtB;AACA;AACA;AACA,EAAA,SAAS,EAAE,KAAK;AAAE;AAClB,EAAA,UAAU,EAAE,IAAI;AAChB,EAAA,eAAe,EAAE,KAAK;AACtB,EAAA,KAAK,EAAE,IAAI;AAAE;AACb,EAAA,aAAa,EAAE,GAAG;AAAE;AACpB,EAAA,QAAQ,EAAE,CAAC;AACX;AACA,EAAA,cAAc,EAAE;AAClB,CAAC;AAED,IAAM,iBAAiB,GAAG,CACxB,WAAwB,EACxB,YAAyC,KAClB;AACvB,EAAA,IAAM,OAAO,GAAG;AAAE,IAAA,GAAG,QAAQ;IAAE,GAAG;GAAc;AAEhD,EAAA,OAAO,CAAC,OAAO,KAAK,WAAW,CAAC,OAAO,CAAC,GAAG;AAC3C,EAAA,OAAO,CAAC,GAAG,KAAK,2BAA2B,CAAC,WAAW,CAAC;AACxD,EAAA,OAAO,CAAC,UAAU,KAAK,oBAAoB,CAAC,OAAO,CAAC;EACpD,OAAO,CAAC,UAAU,KAAK,UAAU;AAEjC,EAAA,OAAO,OAAO;AAChB;AAEA,IAAM,oBAAoB,GAAI,OAA2B,IAAa;EACpE,IAAI,OAAO,CAAC,GAAG,EAAE;AACf;AACA,IAAA,OAAO,UAAU;AACnB,EAAA,CAAC,MAAM;AACL;AACA,IAAA,OAAO,UAAU;AACnB,EAAA;AACF,CAAC;AAED,IAAM,2BAA2B,GAAI,WAAwB,IAAc;AACzE,EAAA,IAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,GAAG;EAEvC,IAAI,OAAO,IAAI,EAAE,EAAE;AACjB,IAAA,OAAO,IAAI;AACb,EAAA,CAAC,MAAM,IAAI,OAAO,KAAK,OAAO,EAAE;AAC9B,IAAA,OAAO,KAAK;AACd,EAAA,CAAC,MAAM;IACL,OAAO,OAAO,CAAC,OAAO,CAAC;AACzB,EAAA;AACF,CAAC;;"}
1
+ {"version":3,"file":"setDefaultOptions.js","sources":["../src/setDefaultOptions.ts"],"sourcesContent":["import type { AnimationSpeed } from \"./animation\";\nimport type { TreeElementOptions } from \"./options\";\n\nimport { DEFAULT_CLASS_PREFIX } from \"./classNames\";\nimport { Node } from \"./node\";\n\n/* The default icons are svg instead of text: the triangle characters come\n * from different fonts on each platform, so they differ in shape and size.\n * They are sized in em to follow the font size, and use currentColor to follow\n * --tree-element-toggler-color.\n */\nconst triangle = (points: string): string =>\n `<svg width=\"0.7em\" height=\"0.7em\" viewBox=\"0 0 10 10\" focusable=\"false\"><polygon points=\"${points}\" fill=\"currentColor\"/></svg>`;\n\nexport const triangleDown = triangle(\"0.5,1.5 9.5,1.5 5,9\");\nexport const triangleLeft = triangle(\"9,0.5 9,9.5 1.5,5\");\nexport const triangleRight = triangle(\"1,0.5 1,9.5 8.5,5\");\n\nconst defaults: TreeElementOptions = {\n animationSpeed: \"fast\",\n autoEscape: true,\n autoOpen: false, // true / false / int (open n levels starting at 0)\n buttonLeft: true,\n classPrefix: DEFAULT_CLASS_PREFIX, // the prefix of all css classes\n // closedIcon: undefined, // the default is a triangle; see getDefaultClosedIcon\n // commonClassName: undefined, // the class of every element; the default is \"<classPrefix>-common\"\n // data: undefined,\n // dataFilter: undefined,\n // dataUrl: undefined,\n dragAndDrop: false,\n keyboardSupport: true,\n nodeClass: Node,\n // onCanMove: undefined, // Can this node be moved?\n // onCanMoveTo: undefined, // Can this node be moved to this position? function(moved_node, target_node, position)\n // onCanSelectNode: undefined,\n // onCreateLi: undefined,\n // onDragMove: undefined,\n // onDragStop: undefined,\n // onGetStateFromStorage: undefined,\n // onIsMoveHandle: undefined,\n // onSetStateFromStorage: undefined,\n // openedIcon: undefined, // the default is a triangle pointing down\n openFolderDelay: 500, // The delay for opening a folder during drag and drop; the value is in milliseconds\n // rtl: undefined, // right-to-left support; true / false (default)\n saveState: false, // true / false / string (local storage key; the default key is \"tree\")\n selectable: true,\n showEmptyFolder: false,\n slide: true, // must display slide animation?\n startDndDelay: 300, // The delay for starting dnd (in milliseconds)\n tabIndex: 0,\n // treeClassName: undefined, // the class of the root element; the default is classPrefix\n useContextMenu: true,\n};\n\nconst setDefaultOptions = (\n htmlElement: HTMLElement,\n inputOptions: Partial<TreeElementOptions>,\n): TreeElementOptions => {\n const options = {\n ...defaults,\n ...inputOptions,\n animationSpeed: inputOptions.animationSpeed ?? getDefaultAnimationSpeed(),\n };\n\n options.dataUrl ??= htmlElement.dataset.url;\n options.rtl ??= getRtlOptionFromHTMLElement(htmlElement);\n options.closedIcon ??= getDefaultClosedIcon(options);\n options.openedIcon ??= triangleDown;\n\n return options;\n};\n\n// No animation when the user asked the system for reduced motion\nconst getDefaultAnimationSpeed = (): AnimationSpeed =>\n prefersReducedMotion() ? 0 : defaults.animationSpeed;\n\nconst prefersReducedMotion = (): boolean =>\n typeof window.matchMedia === \"function\" &&\n window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n\nconst getDefaultClosedIcon = (options: TreeElementOptions): string => {\n return options.rtl ? triangleLeft : triangleRight;\n};\n\nconst getRtlOptionFromHTMLElement = (htmlElement: HTMLElement): boolean => {\n const dataRtl = htmlElement.dataset.rtl;\n\n if (dataRtl == \"\") {\n return true;\n }\n return dataRtl === \"false\" ? false : Boolean(dataRtl);\n};\n\nexport default setDefaultOptions;\n"],"names":[],"mappings":";;;AAMA;AACA;AACA;AACA;AACA;AACA,IAAM,QAAQ,GAAI,MAAc,IAC9B,CAAA,yFAAA,EAA4F,MAAM,CAAA,6BAAA,CAA+B;IAEtH,YAAY,GAAG,QAAQ,CAAC,qBAAqB;IAC7C,YAAY,GAAG,QAAQ,CAAC,mBAAmB;IAC3C,aAAa,GAAG,QAAQ,CAAC,mBAAmB;AAEzD,IAAM,QAA4B,GAAG;AACnC,EAAA,cAAc,EAAE,MAAM;AACtB,EAAA,UAAU,EAAE,IAAI;AAChB,EAAA,QAAQ,EAAE,KAAK;AAAE;AACjB,EAAA,UAAU,EAAE,IAAI;AAChB,EAAA,WAAW,EAAE,oBAAoB;AAAE;AACnC;AACA;AACA;AACA;AACA;AACA,EAAA,WAAW,EAAE,KAAK;AAClB,EAAA,eAAe,EAAE,IAAI;AACrB,EAAA,SAAS,EAAE,IAAI;AACf;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,EAAA,eAAe,EAAE,GAAG;AAAE;AACtB;AACA,EAAA,SAAS,EAAE,KAAK;AAAE;AAClB,EAAA,UAAU,EAAE,IAAI;AAChB,EAAA,eAAe,EAAE,KAAK;AACtB,EAAA,KAAK,EAAE,IAAI;AAAE;AACb,EAAA,aAAa,EAAE,GAAG;AAAE;AACpB,EAAA,QAAQ,EAAE,CAAC;AACX;AACA,EAAA,cAAc,EAAE;AAClB,CAAC;AAED,IAAM,iBAAiB,GAAG,CACxB,WAAwB,EACxB,YAAyC,KAClB;AACvB,EAAA,IAAM,OAAO,GAAG;AACd,IAAA,GAAG,QAAQ;AACX,IAAA,GAAG,YAAY;AACf,IAAA,cAAc,EAAE,YAAY,CAAC,cAAc,IAAI,wBAAwB;GACxE;AAED,EAAA,OAAO,CAAC,OAAO,KAAK,WAAW,CAAC,OAAO,CAAC,GAAG;AAC3C,EAAA,OAAO,CAAC,GAAG,KAAK,2BAA2B,CAAC,WAAW,CAAC;AACxD,EAAA,OAAO,CAAC,UAAU,KAAK,oBAAoB,CAAC,OAAO,CAAC;EACpD,OAAO,CAAC,UAAU,KAAK,YAAY;AAEnC,EAAA,OAAO,OAAO;AAChB;;AAEA;AACA,IAAM,wBAAwB,GAAG,MAC/B,oBAAoB,EAAE,GAAG,CAAC,GAAG,QAAQ,CAAC,cAAc;AAEtD,IAAM,oBAAoB,GAAG,MAC3B,OAAO,MAAM,CAAC,UAAU,KAAK,UAAU,IACvC,MAAM,CAAC,UAAU,CAAC,kCAAkC,CAAC,CAAC,OAAO;AAE/D,IAAM,oBAAoB,GAAI,OAA2B,IAAa;AACpE,EAAA,OAAO,OAAO,CAAC,GAAG,GAAG,YAAY,GAAG,aAAa;AACnD,CAAC;AAED,IAAM,2BAA2B,GAAI,WAAwB,IAAc;AACzE,EAAA,IAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC,GAAG;EAEvC,IAAI,OAAO,IAAI,EAAE,EAAE;AACjB,IAAA,OAAO,IAAI;AACb,EAAA;EACA,OAAO,OAAO,KAAK,OAAO,GAAG,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC;AACvD,CAAC;;"}
package/lib/util.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,GAAI,GAAG,OAAO,KAAG,OACG,CAAC;AAEvC,eAAO,MAAM,aAAa,GAAI,OAAO,OAAO,KAAG,MACrB,CAAC"}
1
+ {"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,KAAK,GAAI,GAAG,OAAO,KAAG,OAA8B,CAAC;AAElE,eAAO,MAAM,aAAa,GAAI,OAAO,OAAO,KAAG,MACrB,CAAC"}
package/lib/util.js CHANGED
@@ -1,4 +1,4 @@
1
- let isInt = n => typeof n === "number" && n % 1 === 0;
1
+ let isInt = n => Number.isInteger(n);
2
2
  let getBoolString = value => value ? "true" : "false";
3
3
 
4
4
  export { getBoolString, isInt };
package/lib/util.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"util.js","sources":["../src/util.ts"],"sourcesContent":["export const isInt = (n: unknown): boolean =>\n typeof n === \"number\" && n % 1 === 0;\n\nexport const getBoolString = (value: unknown): string =>\n value ? \"true\" : \"false\";\n"],"names":[],"mappings":"AAAO,IAAM,KAAK,GAAI,CAAU,IAC9B,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,GAAG,CAAC,KAAK;AAE9B,IAAM,aAAa,GAAI,KAAc,IAC1C,KAAK,GAAG,MAAM,GAAG;;"}
1
+ {"version":3,"file":"util.js","sources":["../src/util.ts"],"sourcesContent":["export const isInt = (n: unknown): boolean => Number.isInteger(n);\n\nexport const getBoolString = (value: unknown): string =>\n value ? \"true\" : \"false\";\n"],"names":[],"mappings":"AAAO,IAAM,KAAK,GAAI,CAAU,IAAc,MAAM,CAAC,SAAS,CAAC,CAAC;AAEzD,IAAM,aAAa,GAAI,KAAc,IAC1C,KAAK,GAAG,MAAM,GAAG;;"}
package/lib/version.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- declare const version = "0.2.0";
1
+ declare const version = "0.3.1";
2
2
  export default version;
3
3
  //# sourceMappingURL=version.d.ts.map
package/lib/version.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // Generated by config/generateVersion.mjs. Do not edit.
2
- let version = "0.2.0";
2
+ let version = "0.3.1";
3
3
 
4
4
  export { version as default };
5
5
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","sources":["../src/version.ts"],"sourcesContent":["// Generated by config/generateVersion.mjs. Do not edit.\nconst version = \"0.2.0\";\n\nexport default version;\n"],"names":[],"mappings":"AAAA;AACA,IAAM,OAAO,GAAG;;"}
1
+ {"version":3,"file":"version.js","sources":["../src/version.ts"],"sourcesContent":["// Generated by config/generateVersion.mjs. Do not edit.\nconst version = \"0.3.1\";\n\nexport default version;\n"],"names":[],"mappings":"AAAA;AACA,IAAM,OAAO,GAAG;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tree-element",
3
- "version": "0.2.0",
3
+ "version": "0.3.1",
4
4
  "description": "Tree widget in plain javascript",
5
5
  "keywords": [
6
6
  "tree"
@@ -20,6 +20,10 @@
20
20
  "./package.json": "./package.json"
21
21
  },
22
22
  "sideEffects": false,
23
+ "browserslist": [
24
+ "defaults",
25
+ "not op_mini all"
26
+ ],
23
27
  "files": [
24
28
  "tree_element.css",
25
29
  "tree_element.debug.js",
@@ -36,9 +40,9 @@
36
40
  "scripts": {
37
41
  "ci": "pnpm lint && pnpm tsc && pnpm docs-check && pnpm test",
38
42
  "build-debug": "DEBUG_BUILD=true rollup --config config/rollup.config.mjs",
39
- "vitest": "pnpm build-debug && vitest run --coverage --config test/vitest.config.mjs",
40
- "vitest-watch": "vitest --config test/vitest.config.mjs",
41
- "lint": "eslint config src playwright test",
43
+ "vitest": "pnpm build-debug && vitest run --coverage --config config/vitest.config.mjs",
44
+ "vitest-watch": "vitest --config config/vitest.config.mjs",
45
+ "lint": "eslint css src playwright test",
42
46
  "production": "./config/production",
43
47
  "devserver": "SERVE=true rollup --config config/rollup.config.mjs --watch",
44
48
  "docs-api": "typedoc && node docs/scripts/fixApiLinks.mjs",
@@ -47,68 +51,73 @@
47
51
  "docs-preview": "vitepress preview docs",
48
52
  "devserver-with-coverage": "COVERAGE=true SERVE=true rollup --config config/rollup.config.mjs",
49
53
  "build-with-coverage": "COVERAGE=true rollup --config config/rollup.config.mjs",
50
- "prettier": "prettier src/**/*.ts test/**/*.ts --write --tab-width 2",
54
+ "prettier": "prettier \"src/**/*.ts\" \"test/**/*.ts\" --write",
51
55
  "tsc": "tsc --noEmit --project tsconfig.json",
52
56
  "version": "node config/generateVersion.mjs && git add src/version.ts",
53
57
  "prepublishOnly": "pnpm run production",
54
58
  "release": "node config/release.mjs",
55
- "playwright": "pnpm build-with-coverage && playwright test --config playwright/playwright.config.js",
59
+ "playwright": "pnpm build-with-coverage && playwright test --config config/playwright.config.js",
56
60
  "test": "pnpm vitest && pnpm playwright",
57
61
  "docs-check": "kiira check"
58
62
  },
59
63
  "devDependencies": {
60
- "@babel/cli": "^8.0.4",
61
- "@babel/core": "^8.0.1",
62
- "@babel/preset-env": "^8.0.2",
63
- "@babel/preset-typescript": "^8.0.1",
64
- "@cspell/eslint-plugin": "^10.2.0",
65
- "@eslint/js": "^10",
66
- "@playwright/test": "^1.62.1",
64
+ "@axe-core/playwright": "^4.13.0",
65
+ "@babel/cli": "^8.0.6",
66
+ "@babel/core": "^8.0.7",
67
+ "@babel/preset-env": "^8.0.7",
68
+ "@babel/preset-typescript": "^8.0.7",
69
+ "@cspell/eslint-plugin": "^10.3.6",
70
+ "@eslint/css": "^2.0.0",
71
+ "@eslint/js": "^10.0.1",
72
+ "@playwright/test": "^1.64.0",
67
73
  "@rollup/plugin-babel": "^7.1.0",
68
74
  "@rollup/plugin-node-resolve": "^16.0.3",
69
75
  "@rollup/plugin-terser": "^1.0.0",
70
- "@testing-library/dom": "^10.4.1",
76
+ "@testing-library/dom": "^10.4.2",
71
77
  "@testing-library/jest-dom": "^7.0.1",
72
- "@testing-library/user-event": "^14.6.6",
78
+ "@testing-library/user-event": "^14.6.7",
73
79
  "@types/debug": "^4.1.13",
74
- "@types/node": "^26.4.0",
75
- "@vitest/coverage-istanbul": "^4.1.11",
80
+ "@types/node": "^26.6.5",
81
+ "@vitest/coverage-istanbul": "^5.0.3",
76
82
  "@vitest/eslint-plugin": "^1.6.27",
77
- "autoprefixer": "^10.5.4",
78
- "axe-core": "^4.13.0",
83
+ "axe-core": "^4.14.0",
79
84
  "babel-plugin-istanbul": "^8.0.0",
80
- "babel-plugin-prefix-private-members": "^0.2.0",
81
- "eslint": "^10",
85
+ "babel-plugin-prefix-private-members": "^0.3.1",
86
+ "eslint": "^10.12.0",
82
87
  "eslint-import-resolver-typescript": "^4.4.5",
88
+ "eslint-plugin-compat": "^7.0.2",
83
89
  "eslint-plugin-import-x": "^4.17.1",
84
90
  "eslint-plugin-jest-dom": "^5.10.1",
85
- "eslint-plugin-jest-extended": "^3.0.1",
86
- "eslint-plugin-perfectionist": "^5.11.0",
87
- "eslint-plugin-playwright": "^2.11.0",
91
+ "eslint-plugin-jest-extended": "github:mbraak/eslint-plugin-jest-extended#modernize",
92
+ "eslint-plugin-no-unsanitized": "^4.1.5",
93
+ "eslint-plugin-perfectionist": "^5.12.1",
94
+ "eslint-plugin-playwright": "^2.12.1",
88
95
  "eslint-plugin-testing-library": "^7.16.2",
96
+ "eslint-plugin-tsdoc": "^0.5.4",
97
+ "eslint-plugin-unicorn": "^77.0.0",
89
98
  "jest-extended": "^7.0.0",
90
- "jsdom": "^30",
99
+ "jsdom": "^30.1.2",
91
100
  "jsdom-testing-mocks": "^1.16.0",
92
101
  "jsonfile": "^6.2.1",
93
102
  "kiira": "^0.6.0",
94
103
  "kiira-core": "^0.6.0",
95
104
  "lodash": "^4.18.1",
96
- "msw": "^2.15.0",
97
- "postcss": "^8.5.26",
98
- "postcss-cli": "^11.0.1",
99
- "postcss-import": "^17",
105
+ "msw": "^3.0.3",
106
+ "postcss": "^8.5.29",
107
+ "postcss-cli": "^12.0.0",
108
+ "postcss-import": "^17.0.0",
100
109
  "postcss-load-config": "^6.0.1",
101
- "postcss-nested": "^8",
102
- "prettier": "^3.9.6",
103
- "rollup": "^4.63.1",
110
+ "postcss-nested": "^8.0.1",
111
+ "prettier": "^3.9.10",
112
+ "rollup": "^4.64.5",
104
113
  "rollup-plugin-serve": "^3.0.0",
105
114
  "rollup-plugin-tsconfig-paths": "^1.5.2",
106
115
  "tslib": "^2.8.1",
107
116
  "typedoc": "^0.28.20",
108
- "typedoc-plugin-markdown": "^4.13.0",
117
+ "typedoc-plugin-markdown": "^4.13.1",
109
118
  "typescript": "^6.0.3",
110
- "typescript-eslint": "^8.69.0",
119
+ "typescript-eslint": "^8.71.1",
111
120
  "vitepress": "^1.6.4",
112
- "vitest": "^4.1.11"
121
+ "vitest": "^5.0.3"
113
122
  }
114
123
  }
package/src/animation.ts CHANGED
@@ -11,8 +11,7 @@ export const getAnimationDuration = (duration: AnimationSpeed): number => {
11
11
  export const slideDown = (
12
12
  element: HTMLElement,
13
13
  animationSpeed: AnimationSpeed,
14
- onFinished: () => void,
15
- ): void => {
14
+ ): Promise<void> => {
16
15
  element.style.display = "block";
17
16
 
18
17
  const animation = element.animate(
@@ -23,16 +22,17 @@ export const slideDown = (
23
22
  { duration: getAnimationDuration(animationSpeed) },
24
23
  );
25
24
 
26
- animation.onfinish = () => {
27
- onFinished();
28
- };
25
+ return new Promise((resolve) => {
26
+ animation.onfinish = () => {
27
+ resolve();
28
+ };
29
+ });
29
30
  };
30
31
 
31
32
  export const slideUp = (
32
33
  element: HTMLElement,
33
34
  animationSpeed: AnimationSpeed,
34
- onFinished: () => void,
35
- ): void => {
35
+ ): Promise<void> => {
36
36
  const animation = element.animate(
37
37
  [
38
38
  { height: `${element.scrollHeight}px`, overflow: "hidden" },
@@ -41,8 +41,10 @@ export const slideUp = (
41
41
  { duration: getAnimationDuration(animationSpeed) },
42
42
  );
43
43
 
44
- animation.onfinish = () => {
45
- element.style.display = "none";
46
- onFinished();
47
- };
44
+ return new Promise((resolve) => {
45
+ animation.onfinish = () => {
46
+ element.style.display = "none";
47
+ resolve();
48
+ };
49
+ });
48
50
  };
package/src/dataLoader.ts CHANGED
@@ -43,6 +43,10 @@ export default class DataLoader {
43
43
  const element = node?.element ?? this.treeElement;
44
44
  element.classList.add(this.classNames.loading);
45
45
 
46
+ // Tell screen readers that the children of the folder are loading
47
+ const titleSpan = node ? this.getTitleSpan(element) : null;
48
+ titleSpan?.setAttribute("aria-busy", "true");
49
+
46
50
  this.triggerEvent("tree.loading_data", {
47
51
  element,
48
52
  node,
@@ -50,6 +54,7 @@ export default class DataLoader {
50
54
 
51
55
  const stopLoading = (): void => {
52
56
  element.classList.remove(this.classNames.loading);
57
+ titleSpan?.removeAttribute("aria-busy");
53
58
  this.triggerEvent("tree.loaded_data", {
54
59
  element,
55
60
  node,
@@ -87,4 +92,10 @@ export default class DataLoader {
87
92
  this.triggerEvent("tree.load_failed", { error });
88
93
  });
89
94
  }
95
+
96
+ private getTitleSpan(element: HTMLElement): HTMLElement | null {
97
+ return element.querySelector<HTMLElement>(
98
+ `:scope > .${this.classNames.element} > .${this.classNames.title}`,
99
+ );
100
+ }
90
101
  }
@@ -27,7 +27,7 @@ class DragElement {
27
27
 
28
28
  this.element = this.createElement(nodeName, autoEscape, classNames);
29
29
 
30
- treeElement.appendChild(this.element);
30
+ treeElement.append(this.element);
31
31
  }
32
32
 
33
33
  public move(pageX: number, pageY: number): void {
@@ -50,6 +50,7 @@ class DragElement {
50
50
  if (autoEscape) {
51
51
  element.textContent = nodeName;
52
52
  } else {
53
+ // eslint-disable-next-line no-unsanitized/property -- the user opted out of escaping with autoEscape: false
53
54
  element.innerHTML = nodeName;
54
55
  }
55
56
 
@@ -139,10 +139,8 @@ export class DragAndDropHandler {
139
139
 
140
140
  let nodeElement = this.getNodeElement(element);
141
141
 
142
- if (nodeElement && this.onCanMove) {
143
- if (!this.onCanMove(nodeElement.node)) {
144
- nodeElement = null;
145
- }
142
+ if (nodeElement && this.onCanMove && !this.onCanMove(nodeElement.node)) {
143
+ nodeElement = null;
146
144
  }
147
145
 
148
146
  this.currentItem = nodeElement;
@@ -181,10 +179,8 @@ export class DragAndDropHandler {
181
179
  this.hoveredArea = area;
182
180
  }
183
181
 
184
- if (!area) {
185
- if (this.onDragMove) {
186
- this.onDragMove(this.currentItem.node, positionInfo.originalEvent);
187
- }
182
+ if (!area && this.onDragMove) {
183
+ this.onDragMove(this.currentItem.node, positionInfo.originalEvent);
188
184
  }
189
185
 
190
186
  return true;
@@ -232,10 +228,8 @@ export class DragAndDropHandler {
232
228
 
233
229
  this.isDragging = false;
234
230
 
235
- if (!this.hoveredArea && currentItem) {
236
- if (this.onDragStop) {
237
- this.onDragStop(currentItem.node, positionInfo.originalEvent);
238
- }
231
+ if (!this.hoveredArea && currentItem && this.onDragStop) {
232
+ this.onDragStop(currentItem.node, positionInfo.originalEvent);
239
233
  }
240
234
 
241
235
  return false;
@@ -244,30 +238,32 @@ export class DragAndDropHandler {
244
238
  public refresh(): void {
245
239
  this.removeHitAreas();
246
240
 
247
- if (this.currentItem) {
248
- const currentNode = this.currentItem.node;
249
- this.generateHitAreas(currentNode);
250
- this.currentItem = this.getNodeElementForNode(currentNode);
241
+ if (!this.currentItem) {
242
+ return;
243
+ }
251
244
 
252
- if (this.isDragging) {
253
- this.currentItem.element.classList.add(this.classNames.moving);
254
- }
245
+ const currentNode = this.currentItem.node;
246
+ this.generateHitAreas(currentNode);
247
+ this.currentItem = this.getNodeElementForNode(currentNode);
248
+
249
+ if (this.isDragging) {
250
+ this.currentItem.element.classList.add(this.classNames.moving);
255
251
  }
256
252
  }
257
253
 
258
254
  private canMoveToArea(area: HitArea, currentItem: NodeElement): boolean {
259
- if (!this.onCanMoveTo) {
260
- return true;
261
- }
262
-
263
- return this.onCanMoveTo(currentItem.node, area.node, area.position);
255
+ return this.onCanMoveTo
256
+ ? this.onCanMoveTo(currentItem.node, area.node, area.position)
257
+ : true;
264
258
  }
265
259
 
266
260
  private clear(): void {
267
- if (this.dragElement) {
268
- this.dragElement.remove();
269
- this.dragElement = null;
261
+ if (!this.dragElement) {
262
+ return;
270
263
  }
264
+
265
+ this.dragElement.remove();
266
+ this.dragElement = null;
271
267
  }
272
268
 
273
269
  private findHoveredArea(x: number, y: number): HitArea | null {
@@ -285,26 +281,17 @@ export class DragAndDropHandler {
285
281
  return binarySearch<HitArea>(this.hitAreas, (area) => {
286
282
  if (y < area.top) {
287
283
  return 1;
288
- } else if (y > area.bottom) {
289
- return -1;
290
- } else {
291
- return 0;
292
284
  }
285
+ return y > area.bottom ? -1 : 0;
293
286
  });
294
287
  }
295
288
 
296
289
  private generateHitAreas(currentNode: Node): void {
297
290
  const tree = this.getTree();
298
291
 
299
- if (!tree) {
300
- this.hitAreas = [];
301
- } else {
302
- this.hitAreas = generateHitAreas(
303
- tree,
304
- currentNode,
305
- this.getTreeDimensions().bottom,
306
- );
307
- }
292
+ this.hitAreas = tree
293
+ ? generateHitAreas(tree, currentNode, this.getTreeDimensions().bottom)
294
+ : [];
308
295
  }
309
296
 
310
297
  private getTreeDimensions(): Dimensions {
@@ -322,47 +309,53 @@ export class DragAndDropHandler {
322
309
  };
323
310
  }
324
311
 
325
- /* Move the dragged node to the selected position in the tree. */
312
+ /*
313
+ Move the dragged node to the selected position in the tree.
314
+ */
326
315
  private moveItem(positionInfo: PositionInfo): void {
327
- if (
316
+ if (!(
328
317
  this.currentItem &&
329
318
  this.hoveredArea?.position &&
330
319
  this.canMoveToArea(this.hoveredArea, this.currentItem)
331
- ) {
332
- const movedNode = this.currentItem.node;
333
- const targetNode = this.hoveredArea.node;
334
- const position = this.hoveredArea.position;
335
- const previousParent = movedNode.parent;
320
+ )) {
321
+ return;
322
+ }
336
323
 
337
- if (position === "inside") {
338
- this.hoveredArea.node.is_open = true;
339
- }
324
+ const movedNode = this.currentItem.node;
325
+ const targetNode = this.hoveredArea.node;
326
+ const position = this.hoveredArea.position;
327
+ const previousParent = movedNode.parent;
340
328
 
341
- const doMove = (): void => {
342
- const tree = this.getTree();
329
+ if (position === "inside") {
330
+ this.hoveredArea.node.is_open = true;
331
+ }
343
332
 
344
- if (tree) {
345
- tree.moveNode(movedNode, targetNode, position);
333
+ const doMove = (): void => {
334
+ const tree = this.getTree();
346
335
 
347
- this.treeElement.textContent = "";
348
- this.refreshElements(null);
349
- }
350
- };
351
-
352
- if (
353
- this.triggerEvent("tree.move", {
354
- moveInfo: {
355
- doMove,
356
- movedNode,
357
- originalEvent: positionInfo.originalEvent,
358
- position,
359
- previousParent,
360
- targetNode,
361
- },
362
- })
363
- ) {
364
- doMove();
336
+ if (!tree) {
337
+ return;
365
338
  }
339
+
340
+ tree.moveNode(movedNode, targetNode, position);
341
+
342
+ this.treeElement.textContent = "";
343
+ this.refreshElements(null);
344
+ };
345
+
346
+ if (
347
+ this.triggerEvent("tree.move", {
348
+ moveInfo: {
349
+ doMove,
350
+ movedNode,
351
+ originalEvent: positionInfo.originalEvent,
352
+ position,
353
+ previousParent,
354
+ targetNode,
355
+ },
356
+ })
357
+ ) {
358
+ doMove();
366
359
  }
367
360
  }
368
361
 
@@ -412,10 +405,12 @@ export class DragAndDropHandler {
412
405
  }
413
406
 
414
407
  private stopOpenFolderTimer(): void {
415
- if (this.openFolderTimer) {
416
- clearTimeout(this.openFolderTimer);
417
- this.openFolderTimer = null;
408
+ if (!this.openFolderTimer) {
409
+ return;
418
410
  }
411
+
412
+ clearTimeout(this.openFolderTimer);
413
+ this.openFolderTimer = null;
419
414
  }
420
415
 
421
416
  private updateDropHint(): void {
@@ -57,28 +57,30 @@ const iterateVisibleNodes = (
57
57
  }
58
58
  }
59
59
 
60
- if (mustIterateInside) {
61
- const childrenLength = node.children.length;
62
- node.children.forEach((_, i) => {
63
- const child = node.children[i];
60
+ if (!mustIterateInside) {
61
+ return;
62
+ }
63
+
64
+ const childrenLength = node.children.length;
65
+ for (const i of node.children.keys()) {
66
+ const child = node.children[i];
64
67
 
65
- if (child) {
66
- if (i === childrenLength - 1) {
67
- iterate(child, null);
68
- } else {
69
- const nextChild = node.children[i + 1];
68
+ if (child) {
69
+ if (i === childrenLength - 1) {
70
+ iterate(child, null);
71
+ } else {
72
+ const nextChild = node.children[i + 1];
70
73
 
71
- if (nextChild) {
72
- iterate(child, nextChild);
73
- }
74
+ if (nextChild) {
75
+ iterate(child, nextChild);
74
76
  }
75
77
  }
76
- });
77
-
78
- if (node.is_open && element) {
79
- handleAfterOpenFolder(node, nextNode);
80
78
  }
81
79
  }
80
+
81
+ if (node.is_open && element) {
82
+ handleAfterOpenFolder(node, nextNode);
83
+ }
82
84
  };
83
85
 
84
86
  iterate(tree, null);