@x-plat/design-system 0.14.7 → 0.14.9

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.
@@ -48,10 +48,18 @@ var Portal_default = Portal;
48
48
 
49
49
  // src/tokens/hooks/useAutoPosition.ts
50
50
  var import_react = __toESM(require("react"), 1);
51
+ var findScrollParent = (el) => {
52
+ for (let p = el.parentElement; p; p = p.parentElement) {
53
+ const { overflowY, overflowX } = getComputedStyle(p);
54
+ if (/(auto|scroll)/.test(overflowY) || /(auto|scroll)/.test(overflowX)) return p;
55
+ }
56
+ return null;
57
+ };
51
58
  var useAutoPosition = (triggerRef, popRef, enabled = true) => {
52
59
  const [direction, setDirection] = import_react.default.useState("bottom");
53
60
  const directionRef = import_react.default.useRef("bottom");
54
61
  const sizeRef = import_react.default.useRef(null);
62
+ const scrollParentRef = import_react.default.useRef(null);
55
63
  const calculatePosition = import_react.default.useCallback((remeasure = false) => {
56
64
  const pop = popRef.current;
57
65
  if (!triggerRef.current || !pop) return;
@@ -60,26 +68,38 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
60
68
  }
61
69
  const { w: popW, h: popH } = sizeRef.current;
62
70
  const triggerRect = triggerRef.current.getBoundingClientRect();
63
- const viewportHeight = window.innerHeight;
64
- const viewportWidth = window.innerWidth;
65
71
  if (popH === 0 || popW === 0) {
66
72
  sizeRef.current = null;
67
73
  return;
68
74
  }
69
- let next = "bottom";
75
+ const parentRect = scrollParentRef.current?.getBoundingClientRect();
76
+ const clip = {
77
+ top: Math.max(parentRect?.top ?? 0, 0),
78
+ bottom: Math.min(parentRect?.bottom ?? window.innerHeight, window.innerHeight),
79
+ left: Math.max(parentRect?.left ?? 0, 0),
80
+ right: Math.min(parentRect?.right ?? window.innerWidth, window.innerWidth)
81
+ };
82
+ const roomBelow = clip.bottom - triggerRect.bottom;
83
+ const roomAbove = triggerRect.top - clip.top;
84
+ let next;
70
85
  let top;
71
- let left;
72
- if (triggerRect.bottom + popH > viewportHeight && triggerRect.top - popH > 0) {
86
+ if (popH <= roomBelow) {
87
+ next = "bottom";
88
+ top = triggerRect.bottom;
89
+ } else if (popH <= roomAbove) {
73
90
  next = "top";
74
91
  top = triggerRect.top - popH;
75
92
  } else {
76
- top = triggerRect.bottom;
93
+ next = roomBelow >= roomAbove ? "bottom" : "top";
94
+ top = next === "bottom" ? triggerRect.bottom : triggerRect.top - popH;
95
+ top = Math.min(top, Math.max(clip.top, clip.bottom - popH));
96
+ top = Math.max(top, clip.top);
77
97
  }
78
- left = triggerRect.left;
79
- if (left + popW > viewportWidth - 8) {
98
+ let left = triggerRect.left;
99
+ if (left + popW > clip.right - 8) {
80
100
  left = triggerRect.right - popW;
81
101
  }
82
- if (left < 8) left = 8;
102
+ if (left < clip.left + 8) left = clip.left + 8;
83
103
  pop.style.top = `${top + window.scrollY}px`;
84
104
  pop.style.left = `${left + window.scrollX}px`;
85
105
  if (next !== directionRef.current) {
@@ -90,12 +110,16 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
90
110
  import_react.default.useLayoutEffect(() => {
91
111
  if (!enabled) {
92
112
  sizeRef.current = null;
113
+ scrollParentRef.current = null;
93
114
  return;
94
115
  }
116
+ if (triggerRef.current) {
117
+ scrollParentRef.current = findScrollParent(triggerRef.current);
118
+ }
95
119
  calculatePosition(true);
96
120
  const raf = requestAnimationFrame(() => calculatePosition(true));
97
121
  return () => cancelAnimationFrame(raf);
98
- }, [calculatePosition, enabled]);
122
+ }, [calculatePosition, enabled, triggerRef]);
99
123
  import_react.default.useEffect(() => {
100
124
  if (!enabled || !popRef.current) return;
101
125
  const observer = new ResizeObserver(() => {
@@ -12,10 +12,18 @@ var Portal_default = Portal;
12
12
 
13
13
  // src/tokens/hooks/useAutoPosition.ts
14
14
  import React from "react";
15
+ var findScrollParent = (el) => {
16
+ for (let p = el.parentElement; p; p = p.parentElement) {
17
+ const { overflowY, overflowX } = getComputedStyle(p);
18
+ if (/(auto|scroll)/.test(overflowY) || /(auto|scroll)/.test(overflowX)) return p;
19
+ }
20
+ return null;
21
+ };
15
22
  var useAutoPosition = (triggerRef, popRef, enabled = true) => {
16
23
  const [direction, setDirection] = React.useState("bottom");
17
24
  const directionRef = React.useRef("bottom");
18
25
  const sizeRef = React.useRef(null);
26
+ const scrollParentRef = React.useRef(null);
19
27
  const calculatePosition = React.useCallback((remeasure = false) => {
20
28
  const pop = popRef.current;
21
29
  if (!triggerRef.current || !pop) return;
@@ -24,26 +32,38 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
24
32
  }
25
33
  const { w: popW, h: popH } = sizeRef.current;
26
34
  const triggerRect = triggerRef.current.getBoundingClientRect();
27
- const viewportHeight = window.innerHeight;
28
- const viewportWidth = window.innerWidth;
29
35
  if (popH === 0 || popW === 0) {
30
36
  sizeRef.current = null;
31
37
  return;
32
38
  }
33
- let next = "bottom";
39
+ const parentRect = scrollParentRef.current?.getBoundingClientRect();
40
+ const clip = {
41
+ top: Math.max(parentRect?.top ?? 0, 0),
42
+ bottom: Math.min(parentRect?.bottom ?? window.innerHeight, window.innerHeight),
43
+ left: Math.max(parentRect?.left ?? 0, 0),
44
+ right: Math.min(parentRect?.right ?? window.innerWidth, window.innerWidth)
45
+ };
46
+ const roomBelow = clip.bottom - triggerRect.bottom;
47
+ const roomAbove = triggerRect.top - clip.top;
48
+ let next;
34
49
  let top;
35
- let left;
36
- if (triggerRect.bottom + popH > viewportHeight && triggerRect.top - popH > 0) {
50
+ if (popH <= roomBelow) {
51
+ next = "bottom";
52
+ top = triggerRect.bottom;
53
+ } else if (popH <= roomAbove) {
37
54
  next = "top";
38
55
  top = triggerRect.top - popH;
39
56
  } else {
40
- top = triggerRect.bottom;
57
+ next = roomBelow >= roomAbove ? "bottom" : "top";
58
+ top = next === "bottom" ? triggerRect.bottom : triggerRect.top - popH;
59
+ top = Math.min(top, Math.max(clip.top, clip.bottom - popH));
60
+ top = Math.max(top, clip.top);
41
61
  }
42
- left = triggerRect.left;
43
- if (left + popW > viewportWidth - 8) {
62
+ let left = triggerRect.left;
63
+ if (left + popW > clip.right - 8) {
44
64
  left = triggerRect.right - popW;
45
65
  }
46
- if (left < 8) left = 8;
66
+ if (left < clip.left + 8) left = clip.left + 8;
47
67
  pop.style.top = `${top + window.scrollY}px`;
48
68
  pop.style.left = `${left + window.scrollX}px`;
49
69
  if (next !== directionRef.current) {
@@ -54,12 +74,16 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
54
74
  React.useLayoutEffect(() => {
55
75
  if (!enabled) {
56
76
  sizeRef.current = null;
77
+ scrollParentRef.current = null;
57
78
  return;
58
79
  }
80
+ if (triggerRef.current) {
81
+ scrollParentRef.current = findScrollParent(triggerRef.current);
82
+ }
59
83
  calculatePosition(true);
60
84
  const raf = requestAnimationFrame(() => calculatePosition(true));
61
85
  return () => cancelAnimationFrame(raf);
62
- }, [calculatePosition, enabled]);
86
+ }, [calculatePosition, enabled, triggerRef]);
63
87
  React.useEffect(() => {
64
88
  if (!enabled || !popRef.current) return;
65
89
  const observer = new ResizeObserver(() => {
@@ -48,10 +48,18 @@ var Portal_default = Portal;
48
48
 
49
49
  // src/tokens/hooks/useAutoPosition.ts
50
50
  var import_react = __toESM(require("react"), 1);
51
+ var findScrollParent = (el) => {
52
+ for (let p = el.parentElement; p; p = p.parentElement) {
53
+ const { overflowY, overflowX } = getComputedStyle(p);
54
+ if (/(auto|scroll)/.test(overflowY) || /(auto|scroll)/.test(overflowX)) return p;
55
+ }
56
+ return null;
57
+ };
51
58
  var useAutoPosition = (triggerRef, popRef, enabled = true) => {
52
59
  const [direction, setDirection] = import_react.default.useState("bottom");
53
60
  const directionRef = import_react.default.useRef("bottom");
54
61
  const sizeRef = import_react.default.useRef(null);
62
+ const scrollParentRef = import_react.default.useRef(null);
55
63
  const calculatePosition = import_react.default.useCallback((remeasure = false) => {
56
64
  const pop = popRef.current;
57
65
  if (!triggerRef.current || !pop) return;
@@ -60,26 +68,38 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
60
68
  }
61
69
  const { w: popW, h: popH } = sizeRef.current;
62
70
  const triggerRect = triggerRef.current.getBoundingClientRect();
63
- const viewportHeight = window.innerHeight;
64
- const viewportWidth = window.innerWidth;
65
71
  if (popH === 0 || popW === 0) {
66
72
  sizeRef.current = null;
67
73
  return;
68
74
  }
69
- let next = "bottom";
75
+ const parentRect = scrollParentRef.current?.getBoundingClientRect();
76
+ const clip = {
77
+ top: Math.max(parentRect?.top ?? 0, 0),
78
+ bottom: Math.min(parentRect?.bottom ?? window.innerHeight, window.innerHeight),
79
+ left: Math.max(parentRect?.left ?? 0, 0),
80
+ right: Math.min(parentRect?.right ?? window.innerWidth, window.innerWidth)
81
+ };
82
+ const roomBelow = clip.bottom - triggerRect.bottom;
83
+ const roomAbove = triggerRect.top - clip.top;
84
+ let next;
70
85
  let top;
71
- let left;
72
- if (triggerRect.bottom + popH > viewportHeight && triggerRect.top - popH > 0) {
86
+ if (popH <= roomBelow) {
87
+ next = "bottom";
88
+ top = triggerRect.bottom;
89
+ } else if (popH <= roomAbove) {
73
90
  next = "top";
74
91
  top = triggerRect.top - popH;
75
92
  } else {
76
- top = triggerRect.bottom;
93
+ next = roomBelow >= roomAbove ? "bottom" : "top";
94
+ top = next === "bottom" ? triggerRect.bottom : triggerRect.top - popH;
95
+ top = Math.min(top, Math.max(clip.top, clip.bottom - popH));
96
+ top = Math.max(top, clip.top);
77
97
  }
78
- left = triggerRect.left;
79
- if (left + popW > viewportWidth - 8) {
98
+ let left = triggerRect.left;
99
+ if (left + popW > clip.right - 8) {
80
100
  left = triggerRect.right - popW;
81
101
  }
82
- if (left < 8) left = 8;
102
+ if (left < clip.left + 8) left = clip.left + 8;
83
103
  pop.style.top = `${top + window.scrollY}px`;
84
104
  pop.style.left = `${left + window.scrollX}px`;
85
105
  if (next !== directionRef.current) {
@@ -90,12 +110,16 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
90
110
  import_react.default.useLayoutEffect(() => {
91
111
  if (!enabled) {
92
112
  sizeRef.current = null;
113
+ scrollParentRef.current = null;
93
114
  return;
94
115
  }
116
+ if (triggerRef.current) {
117
+ scrollParentRef.current = findScrollParent(triggerRef.current);
118
+ }
95
119
  calculatePosition(true);
96
120
  const raf = requestAnimationFrame(() => calculatePosition(true));
97
121
  return () => cancelAnimationFrame(raf);
98
- }, [calculatePosition, enabled]);
122
+ }, [calculatePosition, enabled, triggerRef]);
99
123
  import_react.default.useEffect(() => {
100
124
  if (!enabled || !popRef.current) return;
101
125
  const observer = new ResizeObserver(() => {
@@ -12,10 +12,18 @@ var Portal_default = Portal;
12
12
 
13
13
  // src/tokens/hooks/useAutoPosition.ts
14
14
  import React from "react";
15
+ var findScrollParent = (el) => {
16
+ for (let p = el.parentElement; p; p = p.parentElement) {
17
+ const { overflowY, overflowX } = getComputedStyle(p);
18
+ if (/(auto|scroll)/.test(overflowY) || /(auto|scroll)/.test(overflowX)) return p;
19
+ }
20
+ return null;
21
+ };
15
22
  var useAutoPosition = (triggerRef, popRef, enabled = true) => {
16
23
  const [direction, setDirection] = React.useState("bottom");
17
24
  const directionRef = React.useRef("bottom");
18
25
  const sizeRef = React.useRef(null);
26
+ const scrollParentRef = React.useRef(null);
19
27
  const calculatePosition = React.useCallback((remeasure = false) => {
20
28
  const pop = popRef.current;
21
29
  if (!triggerRef.current || !pop) return;
@@ -24,26 +32,38 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
24
32
  }
25
33
  const { w: popW, h: popH } = sizeRef.current;
26
34
  const triggerRect = triggerRef.current.getBoundingClientRect();
27
- const viewportHeight = window.innerHeight;
28
- const viewportWidth = window.innerWidth;
29
35
  if (popH === 0 || popW === 0) {
30
36
  sizeRef.current = null;
31
37
  return;
32
38
  }
33
- let next = "bottom";
39
+ const parentRect = scrollParentRef.current?.getBoundingClientRect();
40
+ const clip = {
41
+ top: Math.max(parentRect?.top ?? 0, 0),
42
+ bottom: Math.min(parentRect?.bottom ?? window.innerHeight, window.innerHeight),
43
+ left: Math.max(parentRect?.left ?? 0, 0),
44
+ right: Math.min(parentRect?.right ?? window.innerWidth, window.innerWidth)
45
+ };
46
+ const roomBelow = clip.bottom - triggerRect.bottom;
47
+ const roomAbove = triggerRect.top - clip.top;
48
+ let next;
34
49
  let top;
35
- let left;
36
- if (triggerRect.bottom + popH > viewportHeight && triggerRect.top - popH > 0) {
50
+ if (popH <= roomBelow) {
51
+ next = "bottom";
52
+ top = triggerRect.bottom;
53
+ } else if (popH <= roomAbove) {
37
54
  next = "top";
38
55
  top = triggerRect.top - popH;
39
56
  } else {
40
- top = triggerRect.bottom;
57
+ next = roomBelow >= roomAbove ? "bottom" : "top";
58
+ top = next === "bottom" ? triggerRect.bottom : triggerRect.top - popH;
59
+ top = Math.min(top, Math.max(clip.top, clip.bottom - popH));
60
+ top = Math.max(top, clip.top);
41
61
  }
42
- left = triggerRect.left;
43
- if (left + popW > viewportWidth - 8) {
62
+ let left = triggerRect.left;
63
+ if (left + popW > clip.right - 8) {
44
64
  left = triggerRect.right - popW;
45
65
  }
46
- if (left < 8) left = 8;
66
+ if (left < clip.left + 8) left = clip.left + 8;
47
67
  pop.style.top = `${top + window.scrollY}px`;
48
68
  pop.style.left = `${left + window.scrollX}px`;
49
69
  if (next !== directionRef.current) {
@@ -54,12 +74,16 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
54
74
  React.useLayoutEffect(() => {
55
75
  if (!enabled) {
56
76
  sizeRef.current = null;
77
+ scrollParentRef.current = null;
57
78
  return;
58
79
  }
80
+ if (triggerRef.current) {
81
+ scrollParentRef.current = findScrollParent(triggerRef.current);
82
+ }
59
83
  calculatePosition(true);
60
84
  const raf = requestAnimationFrame(() => calculatePosition(true));
61
85
  return () => cancelAnimationFrame(raf);
62
- }, [calculatePosition, enabled]);
86
+ }, [calculatePosition, enabled, triggerRef]);
63
87
  React.useEffect(() => {
64
88
  if (!enabled || !popRef.current) return;
65
89
  const observer = new ResizeObserver(() => {
@@ -49,10 +49,18 @@ var Portal_default = Portal;
49
49
 
50
50
  // src/tokens/hooks/useAutoPosition.ts
51
51
  var import_react = __toESM(require("react"), 1);
52
+ var findScrollParent = (el) => {
53
+ for (let p = el.parentElement; p; p = p.parentElement) {
54
+ const { overflowY, overflowX } = getComputedStyle(p);
55
+ if (/(auto|scroll)/.test(overflowY) || /(auto|scroll)/.test(overflowX)) return p;
56
+ }
57
+ return null;
58
+ };
52
59
  var useAutoPosition = (triggerRef, popRef, enabled = true) => {
53
60
  const [direction, setDirection] = import_react.default.useState("bottom");
54
61
  const directionRef = import_react.default.useRef("bottom");
55
62
  const sizeRef = import_react.default.useRef(null);
63
+ const scrollParentRef = import_react.default.useRef(null);
56
64
  const calculatePosition = import_react.default.useCallback((remeasure = false) => {
57
65
  const pop = popRef.current;
58
66
  if (!triggerRef.current || !pop) return;
@@ -61,26 +69,38 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
61
69
  }
62
70
  const { w: popW, h: popH } = sizeRef.current;
63
71
  const triggerRect = triggerRef.current.getBoundingClientRect();
64
- const viewportHeight = window.innerHeight;
65
- const viewportWidth = window.innerWidth;
66
72
  if (popH === 0 || popW === 0) {
67
73
  sizeRef.current = null;
68
74
  return;
69
75
  }
70
- let next = "bottom";
76
+ const parentRect = scrollParentRef.current?.getBoundingClientRect();
77
+ const clip = {
78
+ top: Math.max(parentRect?.top ?? 0, 0),
79
+ bottom: Math.min(parentRect?.bottom ?? window.innerHeight, window.innerHeight),
80
+ left: Math.max(parentRect?.left ?? 0, 0),
81
+ right: Math.min(parentRect?.right ?? window.innerWidth, window.innerWidth)
82
+ };
83
+ const roomBelow = clip.bottom - triggerRect.bottom;
84
+ const roomAbove = triggerRect.top - clip.top;
85
+ let next;
71
86
  let top;
72
- let left;
73
- if (triggerRect.bottom + popH > viewportHeight && triggerRect.top - popH > 0) {
87
+ if (popH <= roomBelow) {
88
+ next = "bottom";
89
+ top = triggerRect.bottom;
90
+ } else if (popH <= roomAbove) {
74
91
  next = "top";
75
92
  top = triggerRect.top - popH;
76
93
  } else {
77
- top = triggerRect.bottom;
94
+ next = roomBelow >= roomAbove ? "bottom" : "top";
95
+ top = next === "bottom" ? triggerRect.bottom : triggerRect.top - popH;
96
+ top = Math.min(top, Math.max(clip.top, clip.bottom - popH));
97
+ top = Math.max(top, clip.top);
78
98
  }
79
- left = triggerRect.left;
80
- if (left + popW > viewportWidth - 8) {
99
+ let left = triggerRect.left;
100
+ if (left + popW > clip.right - 8) {
81
101
  left = triggerRect.right - popW;
82
102
  }
83
- if (left < 8) left = 8;
103
+ if (left < clip.left + 8) left = clip.left + 8;
84
104
  pop.style.top = `${top + window.scrollY}px`;
85
105
  pop.style.left = `${left + window.scrollX}px`;
86
106
  if (next !== directionRef.current) {
@@ -91,12 +111,16 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
91
111
  import_react.default.useLayoutEffect(() => {
92
112
  if (!enabled) {
93
113
  sizeRef.current = null;
114
+ scrollParentRef.current = null;
94
115
  return;
95
116
  }
117
+ if (triggerRef.current) {
118
+ scrollParentRef.current = findScrollParent(triggerRef.current);
119
+ }
96
120
  calculatePosition(true);
97
121
  const raf = requestAnimationFrame(() => calculatePosition(true));
98
122
  return () => cancelAnimationFrame(raf);
99
- }, [calculatePosition, enabled]);
123
+ }, [calculatePosition, enabled, triggerRef]);
100
124
  import_react.default.useEffect(() => {
101
125
  if (!enabled || !popRef.current) return;
102
126
  const observer = new ResizeObserver(() => {
@@ -251,6 +251,7 @@
251
251
  }
252
252
  .lib-xplat-select-content .select-item {
253
253
  padding: var(--spacing-space-2) var(--spacing-space-3);
254
+ overflow-wrap: anywhere;
254
255
  font-family: var(--semantic-typo-label-2-m-font);
255
256
  font-size: var(--semantic-typo-label-2-m-size);
256
257
  line-height: var(--semantic-typo-label-2-m-lh);
@@ -12,10 +12,18 @@ var Portal_default = Portal;
12
12
 
13
13
  // src/tokens/hooks/useAutoPosition.ts
14
14
  import React from "react";
15
+ var findScrollParent = (el) => {
16
+ for (let p = el.parentElement; p; p = p.parentElement) {
17
+ const { overflowY, overflowX } = getComputedStyle(p);
18
+ if (/(auto|scroll)/.test(overflowY) || /(auto|scroll)/.test(overflowX)) return p;
19
+ }
20
+ return null;
21
+ };
15
22
  var useAutoPosition = (triggerRef, popRef, enabled = true) => {
16
23
  const [direction, setDirection] = React.useState("bottom");
17
24
  const directionRef = React.useRef("bottom");
18
25
  const sizeRef = React.useRef(null);
26
+ const scrollParentRef = React.useRef(null);
19
27
  const calculatePosition = React.useCallback((remeasure = false) => {
20
28
  const pop = popRef.current;
21
29
  if (!triggerRef.current || !pop) return;
@@ -24,26 +32,38 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
24
32
  }
25
33
  const { w: popW, h: popH } = sizeRef.current;
26
34
  const triggerRect = triggerRef.current.getBoundingClientRect();
27
- const viewportHeight = window.innerHeight;
28
- const viewportWidth = window.innerWidth;
29
35
  if (popH === 0 || popW === 0) {
30
36
  sizeRef.current = null;
31
37
  return;
32
38
  }
33
- let next = "bottom";
39
+ const parentRect = scrollParentRef.current?.getBoundingClientRect();
40
+ const clip = {
41
+ top: Math.max(parentRect?.top ?? 0, 0),
42
+ bottom: Math.min(parentRect?.bottom ?? window.innerHeight, window.innerHeight),
43
+ left: Math.max(parentRect?.left ?? 0, 0),
44
+ right: Math.min(parentRect?.right ?? window.innerWidth, window.innerWidth)
45
+ };
46
+ const roomBelow = clip.bottom - triggerRect.bottom;
47
+ const roomAbove = triggerRect.top - clip.top;
48
+ let next;
34
49
  let top;
35
- let left;
36
- if (triggerRect.bottom + popH > viewportHeight && triggerRect.top - popH > 0) {
50
+ if (popH <= roomBelow) {
51
+ next = "bottom";
52
+ top = triggerRect.bottom;
53
+ } else if (popH <= roomAbove) {
37
54
  next = "top";
38
55
  top = triggerRect.top - popH;
39
56
  } else {
40
- top = triggerRect.bottom;
57
+ next = roomBelow >= roomAbove ? "bottom" : "top";
58
+ top = next === "bottom" ? triggerRect.bottom : triggerRect.top - popH;
59
+ top = Math.min(top, Math.max(clip.top, clip.bottom - popH));
60
+ top = Math.max(top, clip.top);
41
61
  }
42
- left = triggerRect.left;
43
- if (left + popW > viewportWidth - 8) {
62
+ let left = triggerRect.left;
63
+ if (left + popW > clip.right - 8) {
44
64
  left = triggerRect.right - popW;
45
65
  }
46
- if (left < 8) left = 8;
66
+ if (left < clip.left + 8) left = clip.left + 8;
47
67
  pop.style.top = `${top + window.scrollY}px`;
48
68
  pop.style.left = `${left + window.scrollX}px`;
49
69
  if (next !== directionRef.current) {
@@ -54,12 +74,16 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
54
74
  React.useLayoutEffect(() => {
55
75
  if (!enabled) {
56
76
  sizeRef.current = null;
77
+ scrollParentRef.current = null;
57
78
  return;
58
79
  }
80
+ if (triggerRef.current) {
81
+ scrollParentRef.current = findScrollParent(triggerRef.current);
82
+ }
59
83
  calculatePosition(true);
60
84
  const raf = requestAnimationFrame(() => calculatePosition(true));
61
85
  return () => cancelAnimationFrame(raf);
62
- }, [calculatePosition, enabled]);
86
+ }, [calculatePosition, enabled, triggerRef]);
63
87
  React.useEffect(() => {
64
88
  if (!enabled || !popRef.current) return;
65
89
  const observer = new ResizeObserver(() => {
@@ -48,10 +48,18 @@ var Portal_default = Portal;
48
48
 
49
49
  // src/tokens/hooks/useAutoPosition.ts
50
50
  var import_react = __toESM(require("react"), 1);
51
+ var findScrollParent = (el) => {
52
+ for (let p = el.parentElement; p; p = p.parentElement) {
53
+ const { overflowY, overflowX } = getComputedStyle(p);
54
+ if (/(auto|scroll)/.test(overflowY) || /(auto|scroll)/.test(overflowX)) return p;
55
+ }
56
+ return null;
57
+ };
51
58
  var useAutoPosition = (triggerRef, popRef, enabled = true) => {
52
59
  const [direction, setDirection] = import_react.default.useState("bottom");
53
60
  const directionRef = import_react.default.useRef("bottom");
54
61
  const sizeRef = import_react.default.useRef(null);
62
+ const scrollParentRef = import_react.default.useRef(null);
55
63
  const calculatePosition = import_react.default.useCallback((remeasure = false) => {
56
64
  const pop = popRef.current;
57
65
  if (!triggerRef.current || !pop) return;
@@ -60,26 +68,38 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
60
68
  }
61
69
  const { w: popW, h: popH } = sizeRef.current;
62
70
  const triggerRect = triggerRef.current.getBoundingClientRect();
63
- const viewportHeight = window.innerHeight;
64
- const viewportWidth = window.innerWidth;
65
71
  if (popH === 0 || popW === 0) {
66
72
  sizeRef.current = null;
67
73
  return;
68
74
  }
69
- let next = "bottom";
75
+ const parentRect = scrollParentRef.current?.getBoundingClientRect();
76
+ const clip = {
77
+ top: Math.max(parentRect?.top ?? 0, 0),
78
+ bottom: Math.min(parentRect?.bottom ?? window.innerHeight, window.innerHeight),
79
+ left: Math.max(parentRect?.left ?? 0, 0),
80
+ right: Math.min(parentRect?.right ?? window.innerWidth, window.innerWidth)
81
+ };
82
+ const roomBelow = clip.bottom - triggerRect.bottom;
83
+ const roomAbove = triggerRect.top - clip.top;
84
+ let next;
70
85
  let top;
71
- let left;
72
- if (triggerRect.bottom + popH > viewportHeight && triggerRect.top - popH > 0) {
86
+ if (popH <= roomBelow) {
87
+ next = "bottom";
88
+ top = triggerRect.bottom;
89
+ } else if (popH <= roomAbove) {
73
90
  next = "top";
74
91
  top = triggerRect.top - popH;
75
92
  } else {
76
- top = triggerRect.bottom;
93
+ next = roomBelow >= roomAbove ? "bottom" : "top";
94
+ top = next === "bottom" ? triggerRect.bottom : triggerRect.top - popH;
95
+ top = Math.min(top, Math.max(clip.top, clip.bottom - popH));
96
+ top = Math.max(top, clip.top);
77
97
  }
78
- left = triggerRect.left;
79
- if (left + popW > viewportWidth - 8) {
98
+ let left = triggerRect.left;
99
+ if (left + popW > clip.right - 8) {
80
100
  left = triggerRect.right - popW;
81
101
  }
82
- if (left < 8) left = 8;
102
+ if (left < clip.left + 8) left = clip.left + 8;
83
103
  pop.style.top = `${top + window.scrollY}px`;
84
104
  pop.style.left = `${left + window.scrollX}px`;
85
105
  if (next !== directionRef.current) {
@@ -90,12 +110,16 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
90
110
  import_react.default.useLayoutEffect(() => {
91
111
  if (!enabled) {
92
112
  sizeRef.current = null;
113
+ scrollParentRef.current = null;
93
114
  return;
94
115
  }
116
+ if (triggerRef.current) {
117
+ scrollParentRef.current = findScrollParent(triggerRef.current);
118
+ }
95
119
  calculatePosition(true);
96
120
  const raf = requestAnimationFrame(() => calculatePosition(true));
97
121
  return () => cancelAnimationFrame(raf);
98
- }, [calculatePosition, enabled]);
122
+ }, [calculatePosition, enabled, triggerRef]);
99
123
  import_react.default.useEffect(() => {
100
124
  if (!enabled || !popRef.current) return;
101
125
  const observer = new ResizeObserver(() => {
@@ -137,6 +137,7 @@
137
137
  }
138
138
  .lib-xplat-time-picker-content .time-picker-item {
139
139
  padding: var(--spacing-space-2) var(--spacing-space-3);
140
+ overflow-wrap: anywhere;
140
141
  cursor: pointer;
141
142
  outline: none;
142
143
  color: var(--semantic-text-primary);
@@ -12,10 +12,18 @@ var Portal_default = Portal;
12
12
 
13
13
  // src/tokens/hooks/useAutoPosition.ts
14
14
  import React from "react";
15
+ var findScrollParent = (el) => {
16
+ for (let p = el.parentElement; p; p = p.parentElement) {
17
+ const { overflowY, overflowX } = getComputedStyle(p);
18
+ if (/(auto|scroll)/.test(overflowY) || /(auto|scroll)/.test(overflowX)) return p;
19
+ }
20
+ return null;
21
+ };
15
22
  var useAutoPosition = (triggerRef, popRef, enabled = true) => {
16
23
  const [direction, setDirection] = React.useState("bottom");
17
24
  const directionRef = React.useRef("bottom");
18
25
  const sizeRef = React.useRef(null);
26
+ const scrollParentRef = React.useRef(null);
19
27
  const calculatePosition = React.useCallback((remeasure = false) => {
20
28
  const pop = popRef.current;
21
29
  if (!triggerRef.current || !pop) return;
@@ -24,26 +32,38 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
24
32
  }
25
33
  const { w: popW, h: popH } = sizeRef.current;
26
34
  const triggerRect = triggerRef.current.getBoundingClientRect();
27
- const viewportHeight = window.innerHeight;
28
- const viewportWidth = window.innerWidth;
29
35
  if (popH === 0 || popW === 0) {
30
36
  sizeRef.current = null;
31
37
  return;
32
38
  }
33
- let next = "bottom";
39
+ const parentRect = scrollParentRef.current?.getBoundingClientRect();
40
+ const clip = {
41
+ top: Math.max(parentRect?.top ?? 0, 0),
42
+ bottom: Math.min(parentRect?.bottom ?? window.innerHeight, window.innerHeight),
43
+ left: Math.max(parentRect?.left ?? 0, 0),
44
+ right: Math.min(parentRect?.right ?? window.innerWidth, window.innerWidth)
45
+ };
46
+ const roomBelow = clip.bottom - triggerRect.bottom;
47
+ const roomAbove = triggerRect.top - clip.top;
48
+ let next;
34
49
  let top;
35
- let left;
36
- if (triggerRect.bottom + popH > viewportHeight && triggerRect.top - popH > 0) {
50
+ if (popH <= roomBelow) {
51
+ next = "bottom";
52
+ top = triggerRect.bottom;
53
+ } else if (popH <= roomAbove) {
37
54
  next = "top";
38
55
  top = triggerRect.top - popH;
39
56
  } else {
40
- top = triggerRect.bottom;
57
+ next = roomBelow >= roomAbove ? "bottom" : "top";
58
+ top = next === "bottom" ? triggerRect.bottom : triggerRect.top - popH;
59
+ top = Math.min(top, Math.max(clip.top, clip.bottom - popH));
60
+ top = Math.max(top, clip.top);
41
61
  }
42
- left = triggerRect.left;
43
- if (left + popW > viewportWidth - 8) {
62
+ let left = triggerRect.left;
63
+ if (left + popW > clip.right - 8) {
44
64
  left = triggerRect.right - popW;
45
65
  }
46
- if (left < 8) left = 8;
66
+ if (left < clip.left + 8) left = clip.left + 8;
47
67
  pop.style.top = `${top + window.scrollY}px`;
48
68
  pop.style.left = `${left + window.scrollX}px`;
49
69
  if (next !== directionRef.current) {
@@ -54,12 +74,16 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
54
74
  React.useLayoutEffect(() => {
55
75
  if (!enabled) {
56
76
  sizeRef.current = null;
77
+ scrollParentRef.current = null;
57
78
  return;
58
79
  }
80
+ if (triggerRef.current) {
81
+ scrollParentRef.current = findScrollParent(triggerRef.current);
82
+ }
59
83
  calculatePosition(true);
60
84
  const raf = requestAnimationFrame(() => calculatePosition(true));
61
85
  return () => cancelAnimationFrame(raf);
62
- }, [calculatePosition, enabled]);
86
+ }, [calculatePosition, enabled, triggerRef]);
63
87
  React.useEffect(() => {
64
88
  if (!enabled || !popRef.current) return;
65
89
  const observer = new ResizeObserver(() => {
@@ -3992,10 +3992,18 @@ var Portal_default = Portal;
3992
3992
 
3993
3993
  // src/tokens/hooks/useAutoPosition.ts
3994
3994
  var import_react19 = __toESM(require("react"), 1);
3995
+ var findScrollParent = (el) => {
3996
+ for (let p = el.parentElement; p; p = p.parentElement) {
3997
+ const { overflowY, overflowX } = getComputedStyle(p);
3998
+ if (/(auto|scroll)/.test(overflowY) || /(auto|scroll)/.test(overflowX)) return p;
3999
+ }
4000
+ return null;
4001
+ };
3995
4002
  var useAutoPosition = (triggerRef, popRef, enabled = true) => {
3996
4003
  const [direction, setDirection] = import_react19.default.useState("bottom");
3997
4004
  const directionRef = import_react19.default.useRef("bottom");
3998
4005
  const sizeRef = import_react19.default.useRef(null);
4006
+ const scrollParentRef = import_react19.default.useRef(null);
3999
4007
  const calculatePosition = import_react19.default.useCallback((remeasure = false) => {
4000
4008
  const pop = popRef.current;
4001
4009
  if (!triggerRef.current || !pop) return;
@@ -4004,26 +4012,38 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
4004
4012
  }
4005
4013
  const { w: popW, h: popH } = sizeRef.current;
4006
4014
  const triggerRect = triggerRef.current.getBoundingClientRect();
4007
- const viewportHeight = window.innerHeight;
4008
- const viewportWidth = window.innerWidth;
4009
4015
  if (popH === 0 || popW === 0) {
4010
4016
  sizeRef.current = null;
4011
4017
  return;
4012
4018
  }
4013
- let next = "bottom";
4019
+ const parentRect = scrollParentRef.current?.getBoundingClientRect();
4020
+ const clip = {
4021
+ top: Math.max(parentRect?.top ?? 0, 0),
4022
+ bottom: Math.min(parentRect?.bottom ?? window.innerHeight, window.innerHeight),
4023
+ left: Math.max(parentRect?.left ?? 0, 0),
4024
+ right: Math.min(parentRect?.right ?? window.innerWidth, window.innerWidth)
4025
+ };
4026
+ const roomBelow = clip.bottom - triggerRect.bottom;
4027
+ const roomAbove = triggerRect.top - clip.top;
4028
+ let next;
4014
4029
  let top;
4015
- let left;
4016
- if (triggerRect.bottom + popH > viewportHeight && triggerRect.top - popH > 0) {
4030
+ if (popH <= roomBelow) {
4031
+ next = "bottom";
4032
+ top = triggerRect.bottom;
4033
+ } else if (popH <= roomAbove) {
4017
4034
  next = "top";
4018
4035
  top = triggerRect.top - popH;
4019
4036
  } else {
4020
- top = triggerRect.bottom;
4037
+ next = roomBelow >= roomAbove ? "bottom" : "top";
4038
+ top = next === "bottom" ? triggerRect.bottom : triggerRect.top - popH;
4039
+ top = Math.min(top, Math.max(clip.top, clip.bottom - popH));
4040
+ top = Math.max(top, clip.top);
4021
4041
  }
4022
- left = triggerRect.left;
4023
- if (left + popW > viewportWidth - 8) {
4042
+ let left = triggerRect.left;
4043
+ if (left + popW > clip.right - 8) {
4024
4044
  left = triggerRect.right - popW;
4025
4045
  }
4026
- if (left < 8) left = 8;
4046
+ if (left < clip.left + 8) left = clip.left + 8;
4027
4047
  pop.style.top = `${top + window.scrollY}px`;
4028
4048
  pop.style.left = `${left + window.scrollX}px`;
4029
4049
  if (next !== directionRef.current) {
@@ -4034,12 +4054,16 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
4034
4054
  import_react19.default.useLayoutEffect(() => {
4035
4055
  if (!enabled) {
4036
4056
  sizeRef.current = null;
4057
+ scrollParentRef.current = null;
4037
4058
  return;
4038
4059
  }
4060
+ if (triggerRef.current) {
4061
+ scrollParentRef.current = findScrollParent(triggerRef.current);
4062
+ }
4039
4063
  calculatePosition(true);
4040
4064
  const raf = requestAnimationFrame(() => calculatePosition(true));
4041
4065
  return () => cancelAnimationFrame(raf);
4042
- }, [calculatePosition, enabled]);
4066
+ }, [calculatePosition, enabled, triggerRef]);
4043
4067
  import_react19.default.useEffect(() => {
4044
4068
  if (!enabled || !popRef.current) return;
4045
4069
  const observer = new ResizeObserver(() => {
@@ -4552,6 +4552,7 @@
4552
4552
  }
4553
4553
  .lib-xplat-select-content .select-item {
4554
4554
  padding: var(--spacing-space-2) var(--spacing-space-3);
4555
+ overflow-wrap: anywhere;
4555
4556
  font-family: var(--semantic-typo-label-2-m-font);
4556
4557
  font-size: var(--semantic-typo-label-2-m-size);
4557
4558
  line-height: var(--semantic-typo-label-2-m-lh);
@@ -5639,6 +5640,7 @@
5639
5640
  }
5640
5641
  .lib-xplat-time-picker-content .time-picker-item {
5641
5642
  padding: var(--spacing-space-2) var(--spacing-space-3);
5643
+ overflow-wrap: anywhere;
5642
5644
  cursor: pointer;
5643
5645
  outline: none;
5644
5646
  color: var(--semantic-text-primary);
@@ -3890,10 +3890,18 @@ var Portal_default = Portal;
3890
3890
 
3891
3891
  // src/tokens/hooks/useAutoPosition.ts
3892
3892
  import React19 from "react";
3893
+ var findScrollParent = (el) => {
3894
+ for (let p = el.parentElement; p; p = p.parentElement) {
3895
+ const { overflowY, overflowX } = getComputedStyle(p);
3896
+ if (/(auto|scroll)/.test(overflowY) || /(auto|scroll)/.test(overflowX)) return p;
3897
+ }
3898
+ return null;
3899
+ };
3893
3900
  var useAutoPosition = (triggerRef, popRef, enabled = true) => {
3894
3901
  const [direction, setDirection] = React19.useState("bottom");
3895
3902
  const directionRef = React19.useRef("bottom");
3896
3903
  const sizeRef = React19.useRef(null);
3904
+ const scrollParentRef = React19.useRef(null);
3897
3905
  const calculatePosition = React19.useCallback((remeasure = false) => {
3898
3906
  const pop = popRef.current;
3899
3907
  if (!triggerRef.current || !pop) return;
@@ -3902,26 +3910,38 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
3902
3910
  }
3903
3911
  const { w: popW, h: popH } = sizeRef.current;
3904
3912
  const triggerRect = triggerRef.current.getBoundingClientRect();
3905
- const viewportHeight = window.innerHeight;
3906
- const viewportWidth = window.innerWidth;
3907
3913
  if (popH === 0 || popW === 0) {
3908
3914
  sizeRef.current = null;
3909
3915
  return;
3910
3916
  }
3911
- let next = "bottom";
3917
+ const parentRect = scrollParentRef.current?.getBoundingClientRect();
3918
+ const clip = {
3919
+ top: Math.max(parentRect?.top ?? 0, 0),
3920
+ bottom: Math.min(parentRect?.bottom ?? window.innerHeight, window.innerHeight),
3921
+ left: Math.max(parentRect?.left ?? 0, 0),
3922
+ right: Math.min(parentRect?.right ?? window.innerWidth, window.innerWidth)
3923
+ };
3924
+ const roomBelow = clip.bottom - triggerRect.bottom;
3925
+ const roomAbove = triggerRect.top - clip.top;
3926
+ let next;
3912
3927
  let top;
3913
- let left;
3914
- if (triggerRect.bottom + popH > viewportHeight && triggerRect.top - popH > 0) {
3928
+ if (popH <= roomBelow) {
3929
+ next = "bottom";
3930
+ top = triggerRect.bottom;
3931
+ } else if (popH <= roomAbove) {
3915
3932
  next = "top";
3916
3933
  top = triggerRect.top - popH;
3917
3934
  } else {
3918
- top = triggerRect.bottom;
3935
+ next = roomBelow >= roomAbove ? "bottom" : "top";
3936
+ top = next === "bottom" ? triggerRect.bottom : triggerRect.top - popH;
3937
+ top = Math.min(top, Math.max(clip.top, clip.bottom - popH));
3938
+ top = Math.max(top, clip.top);
3919
3939
  }
3920
- left = triggerRect.left;
3921
- if (left + popW > viewportWidth - 8) {
3940
+ let left = triggerRect.left;
3941
+ if (left + popW > clip.right - 8) {
3922
3942
  left = triggerRect.right - popW;
3923
3943
  }
3924
- if (left < 8) left = 8;
3944
+ if (left < clip.left + 8) left = clip.left + 8;
3925
3945
  pop.style.top = `${top + window.scrollY}px`;
3926
3946
  pop.style.left = `${left + window.scrollX}px`;
3927
3947
  if (next !== directionRef.current) {
@@ -3932,12 +3952,16 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
3932
3952
  React19.useLayoutEffect(() => {
3933
3953
  if (!enabled) {
3934
3954
  sizeRef.current = null;
3955
+ scrollParentRef.current = null;
3935
3956
  return;
3936
3957
  }
3958
+ if (triggerRef.current) {
3959
+ scrollParentRef.current = findScrollParent(triggerRef.current);
3960
+ }
3937
3961
  calculatePosition(true);
3938
3962
  const raf = requestAnimationFrame(() => calculatePosition(true));
3939
3963
  return () => cancelAnimationFrame(raf);
3940
- }, [calculatePosition, enabled]);
3964
+ }, [calculatePosition, enabled, triggerRef]);
3941
3965
  React19.useEffect(() => {
3942
3966
  if (!enabled || !popRef.current) return;
3943
3967
  const observer = new ResizeObserver(() => {
package/dist/index.cjs CHANGED
@@ -8404,10 +8404,18 @@ var Portal_default = Portal;
8404
8404
 
8405
8405
  // src/tokens/hooks/useAutoPosition.ts
8406
8406
  var import_react19 = __toESM(require("react"), 1);
8407
+ var findScrollParent = (el) => {
8408
+ for (let p = el.parentElement; p; p = p.parentElement) {
8409
+ const { overflowY, overflowX } = getComputedStyle(p);
8410
+ if (/(auto|scroll)/.test(overflowY) || /(auto|scroll)/.test(overflowX)) return p;
8411
+ }
8412
+ return null;
8413
+ };
8407
8414
  var useAutoPosition = (triggerRef, popRef, enabled = true) => {
8408
8415
  const [direction, setDirection] = import_react19.default.useState("bottom");
8409
8416
  const directionRef = import_react19.default.useRef("bottom");
8410
8417
  const sizeRef = import_react19.default.useRef(null);
8418
+ const scrollParentRef = import_react19.default.useRef(null);
8411
8419
  const calculatePosition = import_react19.default.useCallback((remeasure = false) => {
8412
8420
  const pop = popRef.current;
8413
8421
  if (!triggerRef.current || !pop) return;
@@ -8416,26 +8424,38 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
8416
8424
  }
8417
8425
  const { w: popW, h: popH } = sizeRef.current;
8418
8426
  const triggerRect = triggerRef.current.getBoundingClientRect();
8419
- const viewportHeight = window.innerHeight;
8420
- const viewportWidth = window.innerWidth;
8421
8427
  if (popH === 0 || popW === 0) {
8422
8428
  sizeRef.current = null;
8423
8429
  return;
8424
8430
  }
8425
- let next = "bottom";
8431
+ const parentRect = scrollParentRef.current?.getBoundingClientRect();
8432
+ const clip = {
8433
+ top: Math.max(parentRect?.top ?? 0, 0),
8434
+ bottom: Math.min(parentRect?.bottom ?? window.innerHeight, window.innerHeight),
8435
+ left: Math.max(parentRect?.left ?? 0, 0),
8436
+ right: Math.min(parentRect?.right ?? window.innerWidth, window.innerWidth)
8437
+ };
8438
+ const roomBelow = clip.bottom - triggerRect.bottom;
8439
+ const roomAbove = triggerRect.top - clip.top;
8440
+ let next;
8426
8441
  let top;
8427
- let left;
8428
- if (triggerRect.bottom + popH > viewportHeight && triggerRect.top - popH > 0) {
8442
+ if (popH <= roomBelow) {
8443
+ next = "bottom";
8444
+ top = triggerRect.bottom;
8445
+ } else if (popH <= roomAbove) {
8429
8446
  next = "top";
8430
8447
  top = triggerRect.top - popH;
8431
8448
  } else {
8432
- top = triggerRect.bottom;
8449
+ next = roomBelow >= roomAbove ? "bottom" : "top";
8450
+ top = next === "bottom" ? triggerRect.bottom : triggerRect.top - popH;
8451
+ top = Math.min(top, Math.max(clip.top, clip.bottom - popH));
8452
+ top = Math.max(top, clip.top);
8433
8453
  }
8434
- left = triggerRect.left;
8435
- if (left + popW > viewportWidth - 8) {
8454
+ let left = triggerRect.left;
8455
+ if (left + popW > clip.right - 8) {
8436
8456
  left = triggerRect.right - popW;
8437
8457
  }
8438
- if (left < 8) left = 8;
8458
+ if (left < clip.left + 8) left = clip.left + 8;
8439
8459
  pop.style.top = `${top + window.scrollY}px`;
8440
8460
  pop.style.left = `${left + window.scrollX}px`;
8441
8461
  if (next !== directionRef.current) {
@@ -8446,12 +8466,16 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
8446
8466
  import_react19.default.useLayoutEffect(() => {
8447
8467
  if (!enabled) {
8448
8468
  sizeRef.current = null;
8469
+ scrollParentRef.current = null;
8449
8470
  return;
8450
8471
  }
8472
+ if (triggerRef.current) {
8473
+ scrollParentRef.current = findScrollParent(triggerRef.current);
8474
+ }
8451
8475
  calculatePosition(true);
8452
8476
  const raf = requestAnimationFrame(() => calculatePosition(true));
8453
8477
  return () => cancelAnimationFrame(raf);
8454
- }, [calculatePosition, enabled]);
8478
+ }, [calculatePosition, enabled, triggerRef]);
8455
8479
  import_react19.default.useEffect(() => {
8456
8480
  if (!enabled || !popRef.current) return;
8457
8481
  const observer = new ResizeObserver(() => {
package/dist/index.css CHANGED
@@ -4552,6 +4552,7 @@
4552
4552
  }
4553
4553
  .lib-xplat-select-content .select-item {
4554
4554
  padding: var(--spacing-space-2) var(--spacing-space-3);
4555
+ overflow-wrap: anywhere;
4555
4556
  font-family: var(--semantic-typo-label-2-m-font);
4556
4557
  font-size: var(--semantic-typo-label-2-m-size);
4557
4558
  line-height: var(--semantic-typo-label-2-m-lh);
@@ -5639,6 +5640,7 @@
5639
5640
  }
5640
5641
  .lib-xplat-time-picker-content .time-picker-item {
5641
5642
  padding: var(--spacing-space-2) var(--spacing-space-3);
5643
+ overflow-wrap: anywhere;
5642
5644
  cursor: pointer;
5643
5645
  outline: none;
5644
5646
  color: var(--semantic-text-primary);
package/dist/index.js CHANGED
@@ -7993,10 +7993,18 @@ var Portal_default = Portal;
7993
7993
 
7994
7994
  // src/tokens/hooks/useAutoPosition.ts
7995
7995
  import React19 from "react";
7996
+ var findScrollParent = (el) => {
7997
+ for (let p = el.parentElement; p; p = p.parentElement) {
7998
+ const { overflowY, overflowX } = getComputedStyle(p);
7999
+ if (/(auto|scroll)/.test(overflowY) || /(auto|scroll)/.test(overflowX)) return p;
8000
+ }
8001
+ return null;
8002
+ };
7996
8003
  var useAutoPosition = (triggerRef, popRef, enabled = true) => {
7997
8004
  const [direction, setDirection] = React19.useState("bottom");
7998
8005
  const directionRef = React19.useRef("bottom");
7999
8006
  const sizeRef = React19.useRef(null);
8007
+ const scrollParentRef = React19.useRef(null);
8000
8008
  const calculatePosition = React19.useCallback((remeasure = false) => {
8001
8009
  const pop = popRef.current;
8002
8010
  if (!triggerRef.current || !pop) return;
@@ -8005,26 +8013,38 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
8005
8013
  }
8006
8014
  const { w: popW, h: popH } = sizeRef.current;
8007
8015
  const triggerRect = triggerRef.current.getBoundingClientRect();
8008
- const viewportHeight = window.innerHeight;
8009
- const viewportWidth = window.innerWidth;
8010
8016
  if (popH === 0 || popW === 0) {
8011
8017
  sizeRef.current = null;
8012
8018
  return;
8013
8019
  }
8014
- let next = "bottom";
8020
+ const parentRect = scrollParentRef.current?.getBoundingClientRect();
8021
+ const clip = {
8022
+ top: Math.max(parentRect?.top ?? 0, 0),
8023
+ bottom: Math.min(parentRect?.bottom ?? window.innerHeight, window.innerHeight),
8024
+ left: Math.max(parentRect?.left ?? 0, 0),
8025
+ right: Math.min(parentRect?.right ?? window.innerWidth, window.innerWidth)
8026
+ };
8027
+ const roomBelow = clip.bottom - triggerRect.bottom;
8028
+ const roomAbove = triggerRect.top - clip.top;
8029
+ let next;
8015
8030
  let top;
8016
- let left;
8017
- if (triggerRect.bottom + popH > viewportHeight && triggerRect.top - popH > 0) {
8031
+ if (popH <= roomBelow) {
8032
+ next = "bottom";
8033
+ top = triggerRect.bottom;
8034
+ } else if (popH <= roomAbove) {
8018
8035
  next = "top";
8019
8036
  top = triggerRect.top - popH;
8020
8037
  } else {
8021
- top = triggerRect.bottom;
8038
+ next = roomBelow >= roomAbove ? "bottom" : "top";
8039
+ top = next === "bottom" ? triggerRect.bottom : triggerRect.top - popH;
8040
+ top = Math.min(top, Math.max(clip.top, clip.bottom - popH));
8041
+ top = Math.max(top, clip.top);
8022
8042
  }
8023
- left = triggerRect.left;
8024
- if (left + popW > viewportWidth - 8) {
8043
+ let left = triggerRect.left;
8044
+ if (left + popW > clip.right - 8) {
8025
8045
  left = triggerRect.right - popW;
8026
8046
  }
8027
- if (left < 8) left = 8;
8047
+ if (left < clip.left + 8) left = clip.left + 8;
8028
8048
  pop.style.top = `${top + window.scrollY}px`;
8029
8049
  pop.style.left = `${left + window.scrollX}px`;
8030
8050
  if (next !== directionRef.current) {
@@ -8035,12 +8055,16 @@ var useAutoPosition = (triggerRef, popRef, enabled = true) => {
8035
8055
  React19.useLayoutEffect(() => {
8036
8056
  if (!enabled) {
8037
8057
  sizeRef.current = null;
8058
+ scrollParentRef.current = null;
8038
8059
  return;
8039
8060
  }
8061
+ if (triggerRef.current) {
8062
+ scrollParentRef.current = findScrollParent(triggerRef.current);
8063
+ }
8040
8064
  calculatePosition(true);
8041
8065
  const raf = requestAnimationFrame(() => calculatePosition(true));
8042
8066
  return () => cancelAnimationFrame(raf);
8043
- }, [calculatePosition, enabled]);
8067
+ }, [calculatePosition, enabled, triggerRef]);
8044
8068
  React19.useEffect(() => {
8045
8069
  if (!enabled || !popRef.current) return;
8046
8070
  const observer = new ResizeObserver(() => {
@@ -392,10 +392,19 @@ export { Button, Input, Select, SideBar /* 쓰는 것만 */ } from "@x-plat/desi
392
392
  | | 상태 |
393
393
  |---|---|
394
394
  | 오버레이 열림/닫힘 애니메이션 (0.14.2) | **사람이 화면에서 확인함** — 셀렉트가 부드럽게 내려온다 |
395
+ | 안쪽 상자 스크롤 시 닫힘 (0.14.7) | **사람이 화면에서 확인함** |
396
+ | 팝업 목록 안에서 휠 → 안 닫힘 (0.14.7) | **사람이 화면에서 확인함** |
397
+ | 긴 항목 줄바꿈 (0.14.8) | **사람이 화면에서 확인함** — 두세 줄로 떨어진다 |
398
+ | 페이지(문서) 스크롤 시 안 닫힘 (0.14.7) | **확인 안 됨.** 규칙상 맞지만 그 조건의 화면에 고르개가 없어 볼 자리가 없었다 |
395
399
  | `Layout` 타입 (0.14.2) | 소비자 흉내 프로젝트로 타입 검사 통과 |
396
400
  | `ToggleChip` 커서·초점 테두리 | 마크업·CSS 만 확인. 눌러 본 사람 없음 |
397
401
  | Editor | 아래 |
398
402
 
403
+ > 확인할 때는 **배포가 앉은 뒤에** 볼 것. 한 번은 "안 닫힌다" 로 나왔다가
404
+ > 다시 보니 닫혔다 — 반쯤 배포된 화면이었다. 그리고 버전 번호가 아니라
405
+ > 받은 파일 안을 열어 확인하는 편이 낫다(0.14.1 은 번호만 올라가고 내용이
406
+ > 안 온 적이 있다).
407
+
399
408
  **Editor 는 브라우저에서 검증되지 않았다.** `contentEditable`·`execCommand`·IME 는
400
409
  자동 테스트로 흉내 낼 수 없다. 특히 아래 넷은 직접 눌러 봐야 한다.
401
410
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@x-plat/design-system",
3
- "version": "0.14.7",
3
+ "version": "0.14.9",
4
4
  "description": "XPLAT UI Design System",
5
5
  "author": "XPLAT WOONG",
6
6
  "main": "dist/index.cjs",