| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869 |
- // =============================================================================
- // Devtools Active Flag
- // =============================================================================
- //
- // A tiny module-level counter that adapters increment while devtools is
- // mounted. Framework renderers read it to decide whether to add the
- // `data-jr-key` attribute that lets the picker map DOM nodes back to
- // spec element keys.
- //
- // Purely opt-in; when no devtools is mounted the counter stays at 0 and
- // renderers behave exactly as before.
- // =============================================================================
- let activeCount = 0;
- const listeners = new Set<() => void>();
- /**
- * Mark devtools as active. Returns a release function. Safe to call
- * multiple times (nested counter).
- *
- * @example
- * ```ts
- * // In a devtools adapter:
- * useEffect(() => markDevtoolsActive(), []);
- * ```
- */
- export function markDevtoolsActive(): () => void {
- activeCount += 1;
- notifyDevtoolsActiveChange();
- let released = false;
- return () => {
- if (released) return;
- released = true;
- activeCount = Math.max(0, activeCount - 1);
- notifyDevtoolsActiveChange();
- };
- }
- /**
- * True when at least one devtools adapter is mounted in the page.
- * Cheap to call; a plain integer comparison.
- */
- export function isDevtoolsActive(): boolean {
- return activeCount > 0;
- }
- /**
- * Subscribe to changes in the devtools-active flag. Framework renderers
- * that need to re-render on state change (e.g. React's `useSyncExternalStore`)
- * subscribe here; most can just read `isDevtoolsActive()` on render.
- */
- export function subscribeDevtoolsActive(listener: () => void): () => void {
- listeners.add(listener);
- return () => {
- listeners.delete(listener);
- };
- }
- function notifyDevtoolsActiveChange() {
- for (const l of listeners) {
- try {
- l();
- } catch (err) {
- if (process.env.NODE_ENV !== "production") {
- console.error("[json-render] devtools-active listener threw:", err);
- }
- }
- }
- }
|