@ladder-ui/select 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -5,6 +5,11 @@ var react = require('react');
5
5
  var reactDom = require('react-dom');
6
6
  var concatClassNames = require('@ladder-ui/core/concatClassNames');
7
7
 
8
+ // useLayoutEffect runs synchronously after DOM mutations but before the browser
9
+ // paints. This eliminates the double-paint flash that useEffect causes for
10
+ // position-critical work like dropdown placement.
11
+ // Falls back to useEffect in SSR environments (no DOM = no layout to measure).
12
+ const useIsomorphicLayoutEffect = typeof window !== "undefined" ? react.useLayoutEffect : react.useEffect;
8
13
  // ─── Inline SVG icons ────────────────────────────────────────────────────────
9
14
  function ChevronDownIcon({ className }) {
10
15
  return (jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", className: className, children: jsxRuntime.jsx("path", { d: "m6 9 6 6 6-6" }) }));
@@ -150,8 +155,8 @@ function SelectContent({ ref, className, children, position = "item-aligned", })
150
155
  // Pass 2 — compute correct position, set isPositioned=true → visibility:visible.
151
156
  const [isPositioned, setIsPositioned] = react.useState(false);
152
157
  const [coords, setCoords] = react.useState({ top: 0, left: 0, width: 0 });
153
- // Pass 1→2: measure and position after first render
154
- react.useEffect(() => {
158
+ // Pass 1→2: measure and position synchronously before browser paint
159
+ useIsomorphicLayoutEffect(() => {
155
160
  if (!ctx.open || !contentRef.current || !ctx.triggerRef.current)
156
161
  return;
157
162
  const triggerRect = ctx.triggerRef.current.getBoundingClientRect();
package/dist/index.mjs CHANGED
@@ -1,8 +1,13 @@
1
1
  import { jsx, jsxs } from 'react/jsx-runtime';
2
- import { createContext, useState, useId, useRef, useCallback, use, useEffect, Children, isValidElement } from 'react';
2
+ import { createContext, useState, useId, useRef, useCallback, use, useEffect, Children, isValidElement, useLayoutEffect } from 'react';
3
3
  import { createPortal } from 'react-dom';
4
4
  import concatClassNames from '@ladder-ui/core/concatClassNames';
5
5
 
6
+ // useLayoutEffect runs synchronously after DOM mutations but before the browser
7
+ // paints. This eliminates the double-paint flash that useEffect causes for
8
+ // position-critical work like dropdown placement.
9
+ // Falls back to useEffect in SSR environments (no DOM = no layout to measure).
10
+ const useIsomorphicLayoutEffect = typeof window !== "undefined" ? useLayoutEffect : useEffect;
6
11
  // ─── Inline SVG icons ────────────────────────────────────────────────────────
7
12
  function ChevronDownIcon({ className }) {
8
13
  return (jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", className: className, children: jsx("path", { d: "m6 9 6 6 6-6" }) }));
@@ -148,8 +153,8 @@ function SelectContent({ ref, className, children, position = "item-aligned", })
148
153
  // Pass 2 — compute correct position, set isPositioned=true → visibility:visible.
149
154
  const [isPositioned, setIsPositioned] = useState(false);
150
155
  const [coords, setCoords] = useState({ top: 0, left: 0, width: 0 });
151
- // Pass 1→2: measure and position after first render
152
- useEffect(() => {
156
+ // Pass 1→2: measure and position synchronously before browser paint
157
+ useIsomorphicLayoutEffect(() => {
153
158
  if (!ctx.open || !contentRef.current || !ctx.triggerRef.current)
154
159
  return;
155
160
  const triggerRect = ctx.triggerRef.current.getBoundingClientRect();
package/dist/select.css CHANGED
@@ -91,6 +91,8 @@
91
91
  font-family: var(--lui-font-family);
92
92
  }
93
93
  .lui-select-item {
94
+ content-visibility: auto;
95
+ contain-intrinsic-size: auto 36px;
94
96
  position: relative;
95
97
  display: flex;
96
98
  align-items: center;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ladder-ui/select",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -49,7 +49,7 @@
49
49
  "sass": "^1.90.0",
50
50
  "tslib": "^2.6.2",
51
51
  "typescript": "^5.3.3",
52
- "@ladder-ui/core": "0.2.0"
52
+ "@ladder-ui/core": "0.3.0"
53
53
  },
54
54
  "peerDependencies": {
55
55
  "@ladder-ui/core": ">=0.0.0",