Drop unmaintained micro-deps in favor of Hoist-owned utils#4397
Merged
Conversation
The seznam package was last published in 2022. Drop the dep and inline a faithful behavior-preserving `composeRefs` in `utils/react/`, with pairwise WeakMap caching for ref-identity stability across renders. All 17 callsites migrated to a named import from `@xh/hoist/utils/react`. No behavior change. TODO left in source noting the React 19 upgrade path (cleanup forwarding + `useComposedRefs` hook). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The clipboard-copy package was last published in 2022. Drop the dep and inline a faithful behavior-preserving `copyToClipboard` in `utils/js/ClipboardUtils.ts`, using the async Clipboard API with the legacy execCommand fallback intact. All 4 callsites migrated to a named import from `@xh/hoist/utils/js`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The execCommand fallback has no concrete removal trigger - browsers have shown no urgency in actually removing the deprecated API. The "why" comment above already explains the fallback's purpose; the TODO added nothing actionable. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Comment narrows to the actual reason for the fallback (non-secure context), drops the misleading "older browsers" framing. Restores a terse TODO with a concrete trigger - drop the fallback once Hoist requires a secure context. Switches the internal NotAllowedError construction from raw `DOMException` to `XH.exception` for consistency with the rest of the framework. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The nested catch's `|| apiErr || notAllowed()` was dead code - `cmdErr` is always truthy when entering the catch (we only get there because something threw). Inherited from the original `clipboard-copy` source, which was being paranoid about `throw null` / `throw undefined`. Collapse to a single try/catch and let the execCommand fallback's own throw propagate. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
XH.exception() accepts a bare message string, so the helper and the explicit name field add nothing. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Expand the doc comment to mention that the execCommand fallback also catches secure-context writeText() rejections (no user activation, unfocused document, Permissions Policy denial) - not just non-secure contexts. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Left dead after the writeText call was inlined into copyToClipboard. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The debounce-promise package was last published in 2022. Drop the dep and inline a trailing-edge promise debouncer in `@xh/hoist/promise`, matching the only mode Hoist callsites use (shared promise across coalesced calls, resolved with the result of the underlying fn called with the most recent args). Leading-edge and accumulate modes were not used and have been omitted. Both callsites (desktop and mobile `Select`) migrated to the named import. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
TomTirapani
reviewed
Jun 5, 2026
TomTirapani
reviewed
Jun 5, 2026
Member
|
Looks good! We should remember to add lines to the upgrade notes to help agents migrate the imports |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Sweep to remove small, unmaintained transitive deps in favor of Hoist-owned utilities. Behavior preserved at every callsite; original packages credited in source comments under their MIT licenses.
@seznam/compose-react-refs(last published 2022) →composeRefsinutils/react/ComposeRefs.ts. Faithful port: variadic, pairwise WeakMap-cached for ref-identity stability across renders. 17 callsites migrated. TODO left in source noting the React 19 upgrade path (forward cleanup returns + add auseComposedRefshook variant).clipboard-copy(last published 2022) →copyToClipboardinutils/js/ClipboardUtils.ts. Async Clipboard API withexecCommandfallback retained for non-secure contexts and secure-context permission/focus failures. 4 callsites migrated. TODO left noting the fallback can be dropped once Hoist requires a secure context.debounce-promise(last published 2022) →debouncePromisein@xh/hoist/promise. Trimmed to the only mode Hoist uses: trailing-edge debouncer where all calls in a quiet window share a single Promise that resolves with the result of one invocation using the most recent args. Leading-edge and accumulate modes omitted. 2 callsites migrated (desktop and mobileSelect).Test plan
npx tsc --noEmitcleanyarn lint(code + styles) cleanClipboardButton, About dialog, grid copy-cell menu, admin badge double-click)SelectwithqueryFnstill debounces queries correctly while typing🤖 Generated with Claude Code