@idealyst/components 1.2.135 → 1.2.136

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@idealyst/components",
3
- "version": "1.2.135",
3
+ "version": "1.2.136",
4
4
  "description": "Shared component library for React and React Native",
5
5
  "documentation": "https://github.com/IdealystIO/idealyst-framework/tree/main/packages/components#readme",
6
6
  "readme": "README.md",
@@ -56,7 +56,7 @@
56
56
  "publish:npm": "npm publish"
57
57
  },
58
58
  "peerDependencies": {
59
- "@idealyst/theme": "^1.2.135",
59
+ "@idealyst/theme": "^1.2.136",
60
60
  "@mdi/js": ">=7.0.0",
61
61
  "@mdi/react": ">=1.0.0",
62
62
  "@react-native-vector-icons/common": ">=12.0.0",
@@ -111,8 +111,8 @@
111
111
  },
112
112
  "devDependencies": {
113
113
  "@idealyst/blur": "^1.2.40",
114
- "@idealyst/theme": "^1.2.135",
115
- "@idealyst/tooling": "^1.2.135",
114
+ "@idealyst/theme": "^1.2.136",
115
+ "@idealyst/tooling": "^1.2.136",
116
116
  "@mdi/react": "^1.6.1",
117
117
  "@types/react": "^19.1.0",
118
118
  "react": "^19.1.0",
@@ -160,16 +160,16 @@ export const PositionedPortal: React.FC<PositionedPortalProps> = ({
160
160
  const [position, setPosition] = useState<Position>({ top: 0, left: 0 });
161
161
  const [isPositioned, setIsPositioned] = useState(false);
162
162
 
163
- // Calculate position
163
+ // Calculate position from current DOM measurements
164
164
  const updatePosition = useCallback(() => {
165
- if (!contentRef.current || !anchor.current) {
166
- return;
167
- }
165
+ if (!contentRef.current || !anchor.current) return;
168
166
 
169
167
  const anchorRect = anchor.current.getBoundingClientRect();
170
168
  const contentRect = contentRef.current.getBoundingClientRect();
171
169
 
172
- // Use actual measured size from the DOM
170
+ // Skip if content hasn't laid out yet
171
+ if (contentRect.width === 0 && contentRect.height === 0) return;
172
+
173
173
  const newPosition = calculatePosition(
174
174
  anchorRect,
175
175
  { width: contentRect.width, height: contentRect.height },
@@ -182,14 +182,26 @@ export const PositionedPortal: React.FC<PositionedPortalProps> = ({
182
182
  setIsPositioned(true);
183
183
  }, [anchor, placement, offset, matchWidth]);
184
184
 
185
- // Position after DOM is ready
185
+ // Observe content size changes so we re-position once children lay out
186
+ useEffect(() => {
187
+ if (!open || !contentRef.current) return;
188
+
189
+ const observer = new ResizeObserver(() => {
190
+ updatePosition();
191
+ });
192
+ observer.observe(contentRef.current);
193
+
194
+ return () => observer.disconnect();
195
+ }, [open, updatePosition]);
196
+
197
+ // Initial positioning after portal mounts
186
198
  useLayoutEffect(() => {
187
199
  if (open) {
188
- // Use requestAnimationFrame to ensure ref is attached and layout is complete
200
+ // Double-rAF to ensure portal content is in the DOM and laid out
189
201
  const rafId = requestAnimationFrame(() => {
190
- if (contentRef.current && anchor.current) {
202
+ requestAnimationFrame(() => {
191
203
  updatePosition();
192
- }
204
+ });
193
205
  });
194
206
  return () => cancelAnimationFrame(rafId);
195
207
  } else {
@@ -197,12 +209,10 @@ export const PositionedPortal: React.FC<PositionedPortalProps> = ({
197
209
  }
198
210
  }, [open, updatePosition]);
199
211
 
200
- // Update position on scroll/resize
212
+ // Re-position on scroll/resize
201
213
  useEffect(() => {
202
214
  if (!open) return;
203
215
 
204
- updatePosition();
205
-
206
216
  const handleUpdate = () => updatePosition();
207
217
  window.addEventListener('resize', handleUpdate);
208
218
  window.addEventListener('scroll', handleUpdate, true);