1
0
mirror of https://github.com/robonen/tools.git synced 2026-03-21 03:14:43 +00:00

feat(web/vue): update version to 0.0.13 and add useTabLeader composable with tests

This commit is contained in:
2026-02-15 05:29:08 +07:00
parent 624e12ed96
commit c48de9a3d1
8 changed files with 940 additions and 23 deletions

View File

@@ -1,4 +1,15 @@
import { customRef, onScopeDispose } from 'vue';
import { customRef, ref } from 'vue';
import type { Ref } from 'vue';
import { defaultWindow } from '@/types';
import { tryOnScopeDispose } from '@/composables/lifecycle/tryOnScopeDispose';
export interface BroadcastedRefOptions {
/**
* Immediately broadcast the initial value to other tabs on creation
* @default false
*/
immediate?: boolean;
}
/**
* @name broadcastedRef
@@ -7,35 +18,51 @@ import { customRef, onScopeDispose } from 'vue';
*
* @param {string} key The channel key to use for broadcasting
* @param {T} initialValue The initial value of the ref
* @param {BroadcastedRefOptions} [options={}] Options
* @returns {Ref<T>} A custom ref that broadcasts value changes across tabs
*
* @example
* const count = broadcastedRef('counter', 0);
*
* @since 0.0.1
* @example
* const state = broadcastedRef('payment-status', { status: 'pending' });
*
* @since 0.0.13
*/
export function broadcastedRef<T>(key: string, initialValue: T) {
export function broadcastedRef<T>(key: string, initialValue: T, options: BroadcastedRefOptions = {}): Ref<T> {
const { immediate = false } = options;
if (!defaultWindow || typeof BroadcastChannel === 'undefined') {
return ref(initialValue) as Ref<T>;
}
const channel = new BroadcastChannel(key);
let value = initialValue;
onScopeDispose(channel.close);
return customRef<T>((track, trigger) => {
channel.onmessage = (event) => {
track();
return event.data;
const data = customRef<T>((track, trigger) => {
channel.onmessage = (event: MessageEvent<T>) => {
value = event.data;
trigger();
};
channel.postMessage(initialValue);
return {
get() {
return initialValue;
track();
return value;
},
set(newValue: T) {
initialValue = newValue;
value = newValue;
channel.postMessage(newValue);
trigger();
},
};
});
if (immediate) {
channel.postMessage(initialValue);
}
tryOnScopeDispose(() => channel.close());
return data;
}