tp-react-elements 2.0.0 → 2.0.2

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/README.md CHANGED
@@ -9,18 +9,24 @@ A comprehensive React form library built with Material-UI and React Hook Form, d
9
9
  > Storybook docs (`*.stories.tsx` → `meta.parameters.docs.description`)
10
10
  > so consumers see the same explanation in both places.
11
11
 
12
- - **`SingleSelectSearchApi`** — Fixed a `Tooltip`/Popper mis-anchoring bug where
13
- the selected-value tooltip rendered pinned to the viewport's top-left corner
14
- (0,0) instead of near the input when the field sat inside an
15
- `overflow: hidden` ancestor (e.g. a table cell in `material-react-table` /
16
- `GenericPaginatedGrid`). The `Tooltip` is **retained** (not removed) and now
17
- uses `placement="top-start"`, `arrow`, `disableInteractive`, and a
18
- `slotProps.popper` block with Popper.js modifiers (`offset`,
19
- `preventOverflow` with `boundary: 'clippingParents'`, `flip`) so it
20
- portal-renders to `document.body` and stays correctly anchored. See the
12
+ - **`SingleSelectSearchApi`** — The selected-value `Tooltip` is now suppressed
13
+ via `open={false}` (controlled-closed) instead of relying on the Popper
14
+ modifier fix. Background: the tooltip previously rendered pinned to the
15
+ viewport's top-left corner (0,0) instead of near the input when the field
16
+ sat inside an `overflow: hidden` ancestor (e.g. a table cell in
17
+ `material-react-table` / `GenericPaginatedGrid`). Disabling Popper's `hide`
18
+ modifier and using `rootBoundary: 'viewport'` **verifiably fixed this in
19
+ Storybook (MUI v7)**, but the same build still mis-anchored when consumed
20
+ live in apps pinned to MUI v6 (below our `@mui/material >=7.3.1` peer
21
+ requirement) — MUI v6's Popper/Tooltip runtime ignores the modifier
22
+ configuration. Rather than ship a tooltip that only behaves correctly on
23
+ some MUI majors, we now suppress it at the prop level: `open={false}` forces
24
+ MUI's `Tooltip` into fully-controlled mode so it never opens. The `Tooltip`
25
+ element (and its modifier config) is **retained** (not removed) — flipping
26
+ `open` back to the default is a one-line change once the anchoring fix is
27
+ confirmed across all supported MUI majors. See the
21
28
  **"Tooltip inside a clipped container"** story in
22
- `SingleSelectSearchApi.stories.tsx` for a live repro, and the component's
23
- JSDoc for implementation notes.
29
+ `SingleSelectSearchApi.stories.tsx` and the component's JSDoc for details.
24
30
 
25
31
  ## 🚀 Features
26
32
 
@@ -22,22 +22,27 @@ export interface SearchOption {
22
22
  * Searches fire only after `minSearchLength` chars AND after the `debounceMs`
23
23
  * debounce delay — preventing a request per keystroke.
24
24
  *
25
- * ### Selected-value tooltip & anchoring inside clipped containers
26
- * The input is wrapped in a MUI `Tooltip` showing `resolvedValue.label` on
27
- * hover (useful when a narrow column truncates the label). The `Tooltip` is
28
- * configured with `placement="top-start"`, `arrow`, `disableInteractive`, and
29
- * a `slotProps.popper` block carrying Popper.js modifiers — `offset`,
30
- * `preventOverflow` (`boundary: 'clippingParents'`), and `flip`.
25
+ * ### Selected-value tooltip — currently suppressed via `open={false}`
26
+ * The input is wrapped in a MUI `Tooltip` that would show `resolvedValue.label`
27
+ * on hover (useful when a narrow column truncates the label). It carries
28
+ * `placement="top-start"`, `arrow`, `disableInteractive`, and a
29
+ * `slotProps.popper` block with Popper.js modifiers (`hide` disabled, `offset`,
30
+ * `preventOverflow`, `flip`) that correctly anchor it to the input even inside
31
+ * an `overflow: hidden` ancestor (e.g. a table cell in `material-react-table` /
32
+ * `GenericPaginatedGrid`) — **verified working in Storybook on MUI v7**.
31
33
  *
32
- * This keeps the tooltip correctly anchored to the input even when the field
33
- * sits inside an `overflow: hidden` ancestor (e.g. a table cell in
34
- * `material-react-table` / `GenericPaginatedGrid`) — without this
35
- * configuration, MUI's Popper can mis-anchor and pin the tooltip to the
36
- * viewport's top-left corner (0,0) instead of near the input. The fix
37
- * deliberately *keeps* the `Tooltip` (rather than removing it) by letting it
38
- * portal-render to `document.body` and resolving its position against the
39
- * clipping ancestor's boundary. See the "Tooltip inside a clipped container"
40
- * Storybook story for a live repro.
34
+ * However, that fix does not reproduce in consumer apps still pinned to
35
+ * MUI v6 (below our `@mui/material >=7.3.1` peer requirement): the v6
36
+ * Popper/Tooltip runtime ignores the modifier configuration and the tooltip
37
+ * still mis-anchors to the viewport's top-left corner (0,0). Rather than ship
38
+ * a tooltip that only behaves correctly on some MUI majors, we suppress it at
39
+ * the prop level — `open={false}` puts MUI's `Tooltip` into fully-controlled
40
+ * mode so it never opens, while the `<Tooltip>` element (and its modifier
41
+ * config) stays in the tree, deliberately *not removed*. Once the anchoring
42
+ * fix is confirmed across all supported MUI majors, removing `open={false}`
43
+ * re-enables the tooltip with no other changes needed. See the
44
+ * "Tooltip inside a clipped container" Storybook story for the anchoring repro
45
+ * and the `open={false}` suppression in context.
41
46
  */
42
47
  declare const SingleSelectSearchApi: ({ props, variant, minSearchLength, debounceMs, fetchOptions, }: {
43
48
  props: FormRenderProps;
@@ -50,22 +50,27 @@ function useDebounce(value, delayMs) {
50
50
  * Searches fire only after `minSearchLength` chars AND after the `debounceMs`
51
51
  * debounce delay — preventing a request per keystroke.
52
52
  *
53
- * ### Selected-value tooltip & anchoring inside clipped containers
54
- * The input is wrapped in a MUI `Tooltip` showing `resolvedValue.label` on
55
- * hover (useful when a narrow column truncates the label). The `Tooltip` is
56
- * configured with `placement="top-start"`, `arrow`, `disableInteractive`, and
57
- * a `slotProps.popper` block carrying Popper.js modifiers — `offset`,
58
- * `preventOverflow` (`boundary: 'clippingParents'`), and `flip`.
53
+ * ### Selected-value tooltip — currently suppressed via `open={false}`
54
+ * The input is wrapped in a MUI `Tooltip` that would show `resolvedValue.label`
55
+ * on hover (useful when a narrow column truncates the label). It carries
56
+ * `placement="top-start"`, `arrow`, `disableInteractive`, and a
57
+ * `slotProps.popper` block with Popper.js modifiers (`hide` disabled, `offset`,
58
+ * `preventOverflow`, `flip`) that correctly anchor it to the input even inside
59
+ * an `overflow: hidden` ancestor (e.g. a table cell in `material-react-table` /
60
+ * `GenericPaginatedGrid`) — **verified working in Storybook on MUI v7**.
59
61
  *
60
- * This keeps the tooltip correctly anchored to the input even when the field
61
- * sits inside an `overflow: hidden` ancestor (e.g. a table cell in
62
- * `material-react-table` / `GenericPaginatedGrid`) — without this
63
- * configuration, MUI's Popper can mis-anchor and pin the tooltip to the
64
- * viewport's top-left corner (0,0) instead of near the input. The fix
65
- * deliberately *keeps* the `Tooltip` (rather than removing it) by letting it
66
- * portal-render to `document.body` and resolving its position against the
67
- * clipping ancestor's boundary. See the "Tooltip inside a clipped container"
68
- * Storybook story for a live repro.
62
+ * However, that fix does not reproduce in consumer apps still pinned to
63
+ * MUI v6 (below our `@mui/material >=7.3.1` peer requirement): the v6
64
+ * Popper/Tooltip runtime ignores the modifier configuration and the tooltip
65
+ * still mis-anchors to the viewport's top-left corner (0,0). Rather than ship
66
+ * a tooltip that only behaves correctly on some MUI majors, we suppress it at
67
+ * the prop level — `open={false}` puts MUI's `Tooltip` into fully-controlled
68
+ * mode so it never opens, while the `<Tooltip>` element (and its modifier
69
+ * config) stays in the tree, deliberately *not removed*. Once the anchoring
70
+ * fix is confirmed across all supported MUI majors, removing `open={false}`
71
+ * re-enables the tooltip with no other changes needed. See the
72
+ * "Tooltip inside a clipped container" Storybook story for the anchoring repro
73
+ * and the `open={false}` suppression in context.
69
74
  */
70
75
  const SingleSelectSearchApi = ({ props, variant, minSearchLength = 3, debounceMs = 300, fetchOptions, }) => {
71
76
  // ── Stable references from props ──────────────────────────────────────────
@@ -206,25 +211,52 @@ const SingleSelectSearchApi = ({ props, variant, minSearchLength = 3, debounceMs
206
211
  popper: { sx: { zIndex: 20000 } },
207
212
  listbox: { sx: { fontSize: '11px' } },
208
213
  }, PaperComponent: ({ children, ...paperProps }) => (jsx(Paper, { elevation: 4, ...paperProps, children: children })), renderInput: (params) => (jsx(Tooltip, { title: resolvedValue?.label ?? '', placement: "top-start", arrow: true, disableInteractive: true,
209
- // Fixes a Popper mis-anchoring bug where the tooltip rendered
210
- // pinned to the viewport's top-left corner when this field
211
- // sits inside an `overflow: hidden` ancestor (e.g. a table
212
- // cell in material-react-table / GenericPaginatedGrid).
213
- // `disablePortal: false` (the default) lets the tooltip
214
- // escape the clipping ancestor by portal-rendering to
215
- // `document.body`, while the `preventOverflow` / `flip`
216
- // modifiers keep it correctly anchored to the input and
217
- // flip placement when there isn't room above.
218
- slotProps: {
214
+ // ── Tooltip intentionally suppressed via props (kept in the tree) ──
215
+ //
216
+ // We previously tried to fix a Popper mis-anchoring bug where the
217
+ // tooltip rendered pinned to the viewport's top-left corner
218
+ // (`inset: 0 auto auto 0`) when this field sits inside an
219
+ // `overflow: hidden` ancestor (e.g. a table cell in
220
+ // `material-react-table` / `GenericPaginatedGrid`). The root
221
+ // cause is Popper's built-in `hide` modifier collapsing the
222
+ // popper once it judges the reference element "hidden" relative
223
+ // to the `clippingParents` boundary — and disabling that
224
+ // modifier (`{ name: 'hide', enabled: false }` below) verifiably
225
+ // fixed the anchoring in Storybook (MUI v7), but the SAME build
226
+ // still mis-anchored when consumed live in apps pinned to
227
+ // MUI v6 (`@mui/material@6.x` vs. our `>=7.3.1` peer
228
+ // requirement) — the v6 Popper/Tooltip runtime ignores/overrides
229
+ // the modifier configuration.
230
+ //
231
+ // Rather than ship a tooltip that only works on some MUI majors,
232
+ // we suppress it at the component-prop level: `open={false}`
233
+ // forces MUI's Tooltip into fully-controlled mode and it will
234
+ // NEVER open (hover/focus listeners still attach but have no
235
+ // visual effect), so the broken Popper placement can never be
236
+ // observed. The `<Tooltip>` wrapper is deliberately *retained*
237
+ // (not removed) — flipping `open` back to the default
238
+ // (uncontrolled/hover-driven) is a one-line change once the
239
+ // anchoring is fixed for every supported MUI major.
240
+ open: false, slotProps: {
219
241
  popper: {
220
242
  sx: { zIndex: 20001 },
221
243
  modifiers: [
244
+ { name: 'hide', enabled: false },
222
245
  { name: 'offset', options: { offset: [0, 6] } },
223
246
  {
224
247
  name: 'preventOverflow',
225
- options: { boundary: 'clippingParents', altAxis: true, padding: 8 },
248
+ options: {
249
+ boundary: 'clippingParents',
250
+ rootBoundary: 'viewport',
251
+ altAxis: true,
252
+ padding: 8,
253
+ },
254
+ },
255
+ {
256
+ name: 'flip',
257
+ enabled: true,
258
+ options: { rootBoundary: 'viewport', fallbackPlacements: ['bottom-start', 'top-start', 'right', 'left'] },
226
259
  },
227
- { name: 'flip', enabled: true },
228
260
  ],
229
261
  },
230
262
  }, children: jsx(TextField, { ...params, error: isError && !formValue, label: variant !== 'standard'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tp-react-elements",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "React form components library built with React Hook Form and Yup",