@jsenv/dom 0.1.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.
Files changed (101) hide show
  1. package/dist/jsenv_dom.js +9653 -0
  2. package/index.js +101 -0
  3. package/package.json +47 -0
  4. package/src/attr/add_attribute_effect.js +93 -0
  5. package/src/attr/attributes.js +32 -0
  6. package/src/demos/3_columns_resize_demo.html +84 -0
  7. package/src/demos/3_rows_resize_demo.html +89 -0
  8. package/src/demos/aside_and_main_demo.html +93 -0
  9. package/src/demos/coordinates_demo.html +450 -0
  10. package/src/demos/document_autoscroll_demo.html +517 -0
  11. package/src/demos/drag_gesture_constraints_demo.html +701 -0
  12. package/src/demos/drag_gesture_demo.html +1047 -0
  13. package/src/demos/drag_gesture_element_to_impact_demo.html +445 -0
  14. package/src/demos/drag_reference_element_demo.html +480 -0
  15. package/src/demos/flex_details_set_demo.html +302 -0
  16. package/src/demos/flex_details_set_demo_2.html +315 -0
  17. package/src/demos/visible_rect_demo.html +525 -0
  18. package/src/interaction/drag/constraint_feedback_line.js +92 -0
  19. package/src/interaction/drag/drag_constraint.js +659 -0
  20. package/src/interaction/drag/drag_debug_markers.js +635 -0
  21. package/src/interaction/drag/drag_element_positioner.js +382 -0
  22. package/src/interaction/drag/drag_gesture.js +566 -0
  23. package/src/interaction/drag/drag_resize_demo.html +571 -0
  24. package/src/interaction/drag/drag_to_move.js +301 -0
  25. package/src/interaction/drag/drag_to_resize_gesture.js +68 -0
  26. package/src/interaction/drag/drop_target_detection.js +148 -0
  27. package/src/interaction/drag/sticky_frontiers.js +160 -0
  28. package/src/interaction/element_log.js +8 -0
  29. package/src/interaction/event_marker.js +14 -0
  30. package/src/interaction/focus/active_element.js +33 -0
  31. package/src/interaction/focus/arrow_navigation.js +599 -0
  32. package/src/interaction/focus/element_is_focusable.js +57 -0
  33. package/src/interaction/focus/element_is_visible.js +36 -0
  34. package/src/interaction/focus/find_focusable.js +21 -0
  35. package/src/interaction/focus/focus_group.js +91 -0
  36. package/src/interaction/focus/focus_group_registry.js +12 -0
  37. package/src/interaction/focus/focus_nav.js +12 -0
  38. package/src/interaction/focus/focus_nav_event_marker.js +14 -0
  39. package/src/interaction/focus/focus_trap.js +105 -0
  40. package/src/interaction/focus/tab_navigation.js +128 -0
  41. package/src/interaction/focus/tests/focus_group_skip_tab_test.html +206 -0
  42. package/src/interaction/focus/tests/tree_focus_test.html +304 -0
  43. package/src/interaction/focus/tests/tree_focus_test.jsx +261 -0
  44. package/src/interaction/focus/tests/tree_focus_test_preact.html +13 -0
  45. package/src/interaction/isolate_interactions.js +161 -0
  46. package/src/interaction/keyboard.js +26 -0
  47. package/src/interaction/scroll/capture_scroll.js +47 -0
  48. package/src/interaction/scroll/is_scrollable.js +159 -0
  49. package/src/interaction/scroll/scroll_container.js +110 -0
  50. package/src/interaction/scroll/scroll_trap.js +44 -0
  51. package/src/interaction/scroll/scrollbar_size.js +20 -0
  52. package/src/interaction/scroll/wheel_through.js +138 -0
  53. package/src/iterable_weak_set.js +66 -0
  54. package/src/position/dom_coords.js +340 -0
  55. package/src/position/offset_parent.js +15 -0
  56. package/src/position/position_fixed.js +15 -0
  57. package/src/position/position_sticky.js +213 -0
  58. package/src/position/sticky_rect.js +79 -0
  59. package/src/position/visible_rect.js +482 -0
  60. package/src/pub_sub.js +28 -0
  61. package/src/size/can_take_size.js +11 -0
  62. package/src/size/details_content_full_height.js +63 -0
  63. package/src/size/flex_details_set.js +974 -0
  64. package/src/size/get_available_height.js +22 -0
  65. package/src/size/get_available_width.js +22 -0
  66. package/src/size/get_border_sizes.js +14 -0
  67. package/src/size/get_height.js +4 -0
  68. package/src/size/get_inner_height.js +15 -0
  69. package/src/size/get_inner_width.js +15 -0
  70. package/src/size/get_margin_sizes.js +10 -0
  71. package/src/size/get_max_height.js +57 -0
  72. package/src/size/get_max_width.js +47 -0
  73. package/src/size/get_min_height.js +14 -0
  74. package/src/size/get_min_width.js +14 -0
  75. package/src/size/get_padding_sizes.js +10 -0
  76. package/src/size/get_width.js +4 -0
  77. package/src/size/hooks/use_available_height.js +27 -0
  78. package/src/size/hooks/use_available_width.js +27 -0
  79. package/src/size/hooks/use_max_height.js +10 -0
  80. package/src/size/hooks/use_max_width.js +10 -0
  81. package/src/size/hooks/use_resize_status.js +62 -0
  82. package/src/size/resize.js +695 -0
  83. package/src/size/resolve_css_size.js +32 -0
  84. package/src/style/dom_styles.js +97 -0
  85. package/src/style/style_composition.js +78 -0
  86. package/src/style/style_controller.js +345 -0
  87. package/src/style/style_parsing.js +317 -0
  88. package/src/transition/demos/animation_resumption_test.xhtml +500 -0
  89. package/src/transition/demos/height_toggle_test.xhtml +515 -0
  90. package/src/transition/dom_transition.js +254 -0
  91. package/src/transition/easing.js +48 -0
  92. package/src/transition/group_transition.js +261 -0
  93. package/src/transition/transform_style_parser.js +32 -0
  94. package/src/transition/transition_playback.js +366 -0
  95. package/src/transition/transition_timeline.js +79 -0
  96. package/src/traversal.js +247 -0
  97. package/src/ui_transition/demos/content_states_transition_demo.html +628 -0
  98. package/src/ui_transition/demos/smooth_height_transition_demo.html +149 -0
  99. package/src/ui_transition/demos/transition_testing.html +354 -0
  100. package/src/ui_transition/ui_transition.js +1492 -0
  101. package/src/utils.js +69 -0
@@ -0,0 +1,22 @@
1
+ import { getBorderSizes } from "./get_border_sizes.js";
2
+ import { getHeight } from "./get_height.js";
3
+ import { getPaddingSizes } from "./get_padding_sizes.js";
4
+
5
+ export const getAvailableHeight = (
6
+ element,
7
+ parentHeight = getHeight(element.parentElement),
8
+ ) => {
9
+ const parentElement = element.parentElement;
10
+ const paddingSizes = getPaddingSizes(parentElement);
11
+ const borderSizes = getBorderSizes(parentElement);
12
+ let availableHeight = parentHeight;
13
+ availableHeight -=
14
+ paddingSizes.top +
15
+ paddingSizes.bottom +
16
+ borderSizes.top +
17
+ borderSizes.bottom;
18
+ if (availableHeight < 0) {
19
+ availableHeight = 0;
20
+ }
21
+ return availableHeight;
22
+ };
@@ -0,0 +1,22 @@
1
+ import { getBorderSizes } from "./get_border_sizes.js";
2
+ import { getPaddingSizes } from "./get_padding_sizes.js";
3
+ import { getWidth } from "./get_width.js";
4
+
5
+ export const getAvailableWidth = (
6
+ element,
7
+ parentWidth = getWidth(element.parentElement),
8
+ ) => {
9
+ const parentElement = element.parentElement;
10
+ const paddingSizes = getPaddingSizes(parentElement);
11
+ const borderSizes = getBorderSizes(parentElement);
12
+ let availableWidth = parentWidth;
13
+ availableWidth -=
14
+ paddingSizes.left +
15
+ paddingSizes.right +
16
+ borderSizes.left +
17
+ borderSizes.right;
18
+ if (availableWidth < 0) {
19
+ availableWidth = 0;
20
+ }
21
+ return availableWidth;
22
+ };
@@ -0,0 +1,14 @@
1
+ export const getBorderSizes = (element) => {
2
+ const {
3
+ borderLeftWidth,
4
+ borderRightWidth,
5
+ borderTopWidth,
6
+ borderBottomWidth,
7
+ } = window.getComputedStyle(element, null);
8
+ return {
9
+ left: parseFloat(borderLeftWidth),
10
+ right: parseFloat(borderRightWidth),
11
+ top: parseFloat(borderTopWidth),
12
+ bottom: parseFloat(borderBottomWidth),
13
+ };
14
+ };
@@ -0,0 +1,4 @@
1
+ export const getHeight = (element) => {
2
+ const { height } = element.getBoundingClientRect();
3
+ return height;
4
+ };
@@ -0,0 +1,15 @@
1
+ import { getBorderSizes } from "./get_border_sizes.js";
2
+ import { getHeight } from "./get_height.js";
3
+ import { getPaddingSizes } from "./get_padding_sizes.js";
4
+
5
+ export const getInnerHeight = (element) => {
6
+ // Always subtract paddings and borders to get the content height
7
+ const paddingSizes = getPaddingSizes(element);
8
+ const borderSizes = getBorderSizes(element);
9
+ const height = getHeight(element);
10
+ const verticalSpaceTakenByPaddings = paddingSizes.top + paddingSizes.bottom;
11
+ const verticalSpaceTakenByBorders = borderSizes.top + borderSizes.bottom;
12
+ const innerHeight =
13
+ height - verticalSpaceTakenByPaddings - verticalSpaceTakenByBorders;
14
+ return innerHeight;
15
+ };
@@ -0,0 +1,15 @@
1
+ import { getBorderSizes } from "./get_border_sizes.js";
2
+ import { getPaddingSizes } from "./get_padding_sizes.js";
3
+ import { getWidth } from "./get_width.js";
4
+
5
+ export const getInnerWidth = (element) => {
6
+ // Always subtract paddings and borders to get the content width
7
+ const paddingSizes = getPaddingSizes(element);
8
+ const borderSizes = getBorderSizes(element);
9
+ const width = getWidth(element);
10
+ const horizontalSpaceTakenByPaddings = paddingSizes.left + paddingSizes.right;
11
+ const horizontalSpaceTakenByBorders = borderSizes.left + borderSizes.right;
12
+ const innerWidth =
13
+ width - horizontalSpaceTakenByPaddings - horizontalSpaceTakenByBorders;
14
+ return innerWidth;
15
+ };
@@ -0,0 +1,10 @@
1
+ export const getMarginSizes = (element) => {
2
+ const { marginLeft, marginRight, marginTop, marginBottom } =
3
+ window.getComputedStyle(element, null);
4
+ return {
5
+ left: parseFloat(marginLeft),
6
+ right: parseFloat(marginRight),
7
+ top: parseFloat(marginTop),
8
+ bottom: parseFloat(marginBottom),
9
+ };
10
+ };
@@ -0,0 +1,57 @@
1
+ import { getAvailableHeight } from "./get_available_height.js";
2
+ import { getHeight } from "./get_height.js";
3
+ import { getMarginSizes } from "./get_margin_sizes.js";
4
+ import { getMinHeight } from "./get_min_height.js";
5
+
6
+ export const getMaxHeight = (
7
+ element,
8
+ availableHeight = getAvailableHeight(element),
9
+ ) => {
10
+ let maxHeight = availableHeight;
11
+ const marginSizes = getMarginSizes(element);
12
+ maxHeight -= marginSizes.top;
13
+ maxHeight -= marginSizes.bottom;
14
+
15
+ const parentElement = element.parentElement;
16
+ const parentElementComputedStyle = window.getComputedStyle(parentElement);
17
+ if (
18
+ parentElementComputedStyle.display === "flex" &&
19
+ parentElementComputedStyle.flexDirection === "column"
20
+ ) {
21
+ let previousSibling = element.previousElementSibling;
22
+ while (previousSibling) {
23
+ if (canTakeSpace(previousSibling)) {
24
+ const previousSiblingHeight = getHeight(previousSibling);
25
+ maxHeight -= previousSiblingHeight;
26
+ const previousSiblingMarginSizes = getMarginSizes(previousSibling);
27
+ maxHeight -= previousSiblingMarginSizes.top;
28
+ maxHeight -= previousSiblingMarginSizes.bottom;
29
+ }
30
+ previousSibling = previousSibling.previousElementSibling;
31
+ }
32
+ let nextSibling = element.nextElementSibling;
33
+ while (nextSibling) {
34
+ if (canTakeSpace(nextSibling)) {
35
+ const nextSiblingMinHeight = getMinHeight(nextSibling, availableHeight);
36
+ maxHeight -= nextSiblingMinHeight;
37
+ const nextSiblingMarginSizes = getMarginSizes(nextSibling);
38
+ maxHeight -= nextSiblingMarginSizes.top;
39
+ maxHeight -= nextSiblingMarginSizes.bottom;
40
+ }
41
+ nextSibling = nextSibling.nextElementSibling;
42
+ }
43
+ }
44
+ return maxHeight;
45
+ };
46
+
47
+ const canTakeSpace = (element) => {
48
+ const computedStyle = window.getComputedStyle(element);
49
+
50
+ if (computedStyle.display === "none") {
51
+ return false;
52
+ }
53
+ if (computedStyle.position === "absolute") {
54
+ return false;
55
+ }
56
+ return true;
57
+ };
@@ -0,0 +1,47 @@
1
+ import { canTakeSize } from "./can_take_size.js";
2
+ import { getAvailableWidth } from "./get_available_width.js";
3
+ import { getMarginSizes } from "./get_margin_sizes.js";
4
+ import { getMinWidth } from "./get_min_width.js";
5
+ import { getWidth } from "./get_width.js";
6
+
7
+ export const getMaxWidth = (
8
+ element,
9
+ availableWidth = getAvailableWidth(element),
10
+ ) => {
11
+ let maxWidth = availableWidth;
12
+
13
+ const marginSizes = getMarginSizes(element);
14
+ maxWidth -= marginSizes.left;
15
+ maxWidth -= marginSizes.right;
16
+
17
+ const parentElement = element.parentElement;
18
+ const parentElementComputedStyle = window.getComputedStyle(parentElement);
19
+ if (
20
+ parentElementComputedStyle.display === "flex" &&
21
+ parentElementComputedStyle.flexDirection === "row"
22
+ ) {
23
+ let previousSibling = element.previousElementSibling;
24
+ while (previousSibling) {
25
+ if (canTakeSize(previousSibling)) {
26
+ const previousSiblingWidth = getWidth(previousSibling);
27
+ maxWidth -= previousSiblingWidth;
28
+ const previousSiblingMarginSizes = getMarginSizes(previousSibling);
29
+ maxWidth -= previousSiblingMarginSizes.left;
30
+ maxWidth -= previousSiblingMarginSizes.right;
31
+ }
32
+ previousSibling = previousSibling.previousElementSibling;
33
+ }
34
+ let nextSibling = element.nextElementSibling;
35
+ while (nextSibling) {
36
+ if (canTakeSize(nextSibling)) {
37
+ const nextSiblingMinWidth = getMinWidth(nextSibling, availableWidth);
38
+ maxWidth -= nextSiblingMinWidth;
39
+ const nextSiblingMarginSizes = getMarginSizes(nextSibling);
40
+ maxWidth -= nextSiblingMarginSizes.left;
41
+ maxWidth -= nextSiblingMarginSizes.right;
42
+ }
43
+ nextSibling = nextSibling.nextElementSibling;
44
+ }
45
+ }
46
+ return maxWidth;
47
+ };
@@ -0,0 +1,14 @@
1
+ import { getAvailableHeight } from "./get_available_height.js";
2
+ import { resolveCSSSize } from "./resolve_css_size.js";
3
+
4
+ export const getMinHeight = (element, availableHeight) => {
5
+ const computedStyle = window.getComputedStyle(element);
6
+ const { minHeight, fontSize } = computedStyle;
7
+ return resolveCSSSize(minHeight, {
8
+ availableSize:
9
+ availableHeight === undefined
10
+ ? getAvailableHeight(element)
11
+ : availableHeight,
12
+ fontSize,
13
+ });
14
+ };
@@ -0,0 +1,14 @@
1
+ import { getAvailableWidth } from "./get_available_width.js";
2
+ import { resolveCSSSize } from "./resolve_css_size.js";
3
+
4
+ export const getMinWidth = (element, availableWidth) => {
5
+ const computedStyle = window.getComputedStyle(element);
6
+ const { minWidth, fontSize } = computedStyle;
7
+ return resolveCSSSize(minWidth, {
8
+ availableSize:
9
+ availableWidth === undefined
10
+ ? getAvailableWidth(element)
11
+ : availableWidth,
12
+ fontSize,
13
+ });
14
+ };
@@ -0,0 +1,10 @@
1
+ export const getPaddingSizes = (element) => {
2
+ const { paddingLeft, paddingRight, paddingTop, paddingBottom } =
3
+ window.getComputedStyle(element, null);
4
+ return {
5
+ left: parseFloat(paddingLeft),
6
+ right: parseFloat(paddingRight),
7
+ top: parseFloat(paddingTop),
8
+ bottom: parseFloat(paddingBottom),
9
+ };
10
+ };
@@ -0,0 +1,4 @@
1
+ export const getWidth = (element) => {
2
+ const { width } = element.getBoundingClientRect();
3
+ return width;
4
+ };
@@ -0,0 +1,27 @@
1
+ import { useLayoutEffect, useState } from "preact/hooks";
2
+ import { getAvailableHeight } from "../get_available_height.js";
3
+
4
+ export const useAvailableHeight = (elementRef) => {
5
+ const [availableHeight, availableHeightSetter] = useState(-1);
6
+
7
+ useLayoutEffect(() => {
8
+ const element = elementRef.current;
9
+ const parentElement = element.parentElement;
10
+ let raf;
11
+ const resizeObserver = new ResizeObserver((entries) => {
12
+ const [entry] = entries;
13
+ const parentHeight = entry.contentRect.height;
14
+ const availableH = getAvailableHeight(element, parentHeight);
15
+ raf = requestAnimationFrame(() => {
16
+ availableHeightSetter(availableH);
17
+ });
18
+ });
19
+ resizeObserver.observe(parentElement);
20
+ return () => {
21
+ resizeObserver.disconnect();
22
+ cancelAnimationFrame(raf);
23
+ };
24
+ }, []);
25
+
26
+ return availableHeight;
27
+ };
@@ -0,0 +1,27 @@
1
+ import { useLayoutEffect, useState } from "preact/hooks";
2
+ import { getAvailableWidth } from "../get_available_width.js";
3
+
4
+ export const useAvailableWidth = (elementRef) => {
5
+ const [availableWidth, availableWidthSetter] = useState(-1);
6
+
7
+ useLayoutEffect(() => {
8
+ const element = elementRef.current;
9
+ const parentElement = element.parentElement;
10
+ let raf;
11
+ const resizeObserver = new ResizeObserver((entries) => {
12
+ const [entry] = entries;
13
+ const parentWidth = entry.contentRect.width;
14
+ const availableW = getAvailableWidth(element, parentWidth);
15
+ raf = requestAnimationFrame(() => {
16
+ availableWidthSetter(availableW);
17
+ });
18
+ });
19
+ resizeObserver.observe(parentElement);
20
+ return () => {
21
+ resizeObserver.disconnect();
22
+ cancelAnimationFrame(raf);
23
+ };
24
+ }, []);
25
+
26
+ return availableWidth;
27
+ };
@@ -0,0 +1,10 @@
1
+ import { getMaxHeight } from "../get_max_height.js";
2
+
3
+ export const useMaxHeight = (elementRef, availableHeight) => {
4
+ const element = elementRef.current;
5
+ if (!element) {
6
+ return -1;
7
+ }
8
+ const maxWidth = getMaxHeight(element, availableHeight);
9
+ return maxWidth;
10
+ };
@@ -0,0 +1,10 @@
1
+ import { getMaxWidth } from "../get_max_width.js";
2
+
3
+ export const useMaxWidth = (elementRef, availableWidth) => {
4
+ const element = elementRef.current;
5
+ if (!element) {
6
+ return -1;
7
+ }
8
+ const maxWidth = getMaxWidth(element, availableWidth);
9
+ return maxWidth;
10
+ };
@@ -0,0 +1,62 @@
1
+ import { useLayoutEffect, useState } from "preact/hooks";
2
+
3
+ export const useResizeStatus = (elementRef, { as = "number" } = {}) => {
4
+ const [resizing, setIsResizing] = useState(false);
5
+ const [resizeWidth, setResizeWidth] = useState(null);
6
+ const [resizeHeight, setResizeHeight] = useState(null);
7
+
8
+ useLayoutEffect(() => {
9
+ const element = elementRef.current;
10
+
11
+ const onresizestart = (e) => {
12
+ const sizeInfo = e.detail;
13
+ setResizeWidth(
14
+ as === "number" ? sizeInfo.width : sizeInfo.widthAsPercentage,
15
+ );
16
+ setResizeHeight(
17
+ as === "number" ? sizeInfo.height : sizeInfo.heightAsPercentage,
18
+ );
19
+ setIsResizing(true);
20
+ };
21
+ const onresize = (e) => {
22
+ const sizeInfo = e.detail;
23
+ setResizeWidth(
24
+ as === "number" ? sizeInfo.width : sizeInfo.widthAsPercentage,
25
+ );
26
+ setResizeHeight(
27
+ as === "number" ? sizeInfo.height : sizeInfo.heightAsPercentage,
28
+ );
29
+ };
30
+ const onresizeend = () => {
31
+ setIsResizing(false);
32
+ };
33
+
34
+ element.addEventListener("resizestart", onresizestart);
35
+ element.addEventListener("resize", onresize);
36
+ element.addEventListener("resizeend", onresizeend);
37
+ return () => {
38
+ element.removeEventListener("resizestart", onresizestart);
39
+ element.removeEventListener("resize", onresize);
40
+ element.removeEventListener("resizeend", onresizeend);
41
+ };
42
+ }, [as]);
43
+
44
+ return {
45
+ resizing,
46
+ resizeWidth,
47
+ resizeHeight,
48
+ };
49
+ };
50
+
51
+ // to use when width is set as percentage
52
+ export const useInitialWidth = (width, elementRef) => {
53
+ const [initialWidth, setInitialWidth] = useState(null);
54
+ useLayoutEffect(() => {
55
+ const element = elementRef.current;
56
+ const availableWidth = element.parentElement.offsetWidth;
57
+ setInitialWidth(
58
+ width.endsWith("%") ? (parseFloat(width) / 100) * availableWidth : width,
59
+ );
60
+ }, [width]);
61
+ return initialWidth;
62
+ };