New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@vue-composable/web

Package Overview
Dependencies
Maintainers
1
Versions
25
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@vue-composable/web - npm Package Compare versions

Comparing version 1.0.0-dev.4 to 1.0.0-dev.6

490

dist/web.cjs.js

@@ -79,74 +79,2 @@ 'use strict';

function useMatchMedia(query) {
const mediaQueryList = compositionApi.ref(matchMedia(query));
const matches = compositionApi.ref(mediaQueryList.value.matches);
const process = (e) => {
matches.value = e.matches;
};
mediaQueryList.value.addEventListener("change", process, { passive: true });
const remove = () => mediaQueryList.value.removeEventListener("change", process);
compositionApi.onUnmounted(remove);
return {
mediaQueryList,
remove,
matches
};
}
function useBreakpoint(breakpoints) {
const result = {};
const map = new Map();
const current = compositionApi.ref();
let sorted = [];
const removeMedia = [];
for (const key in breakpoints) {
const bp = breakpoints[key];
if (core.isNumber(bp)) {
const r = compositionApi.ref(false);
result[key] = r;
map.set(bp, {
name: key,
valid: r
});
sorted.push(bp);
}
else {
const { matches, remove } = useMatchMedia(bp);
result[key] = matches;
removeMedia.push(remove);
}
}
sorted = sorted.sort((a, b) => b - a);
const resize = () => {
const width = window.innerWidth;
let c = undefined;
for (let i = 0; i < sorted.length; i++) {
const bp = sorted[i];
const r = map.get(bp);
r.valid.value = width >= bp;
if (width >= bp && c === undefined) {
c = r.name;
}
}
current.value = c;
};
const processResize = core.useDebounce(resize, 10);
const remove = () => window.removeEventListener("resize", processResize);
compositionApi.onMounted(() => {
resize();
window.addEventListener("resize", processResize, {
passive: true
});
});
compositionApi.onUnmounted(() => {
remove();
removeMedia.forEach(x => x());
});
return {
...result,
remove,
current
};
}
function useFetch(options) {

@@ -334,11 +262,10 @@ const json = compositionApi.ref(null);

};
remove = () => {
connection.removeEventListener("change", handler);
};
connection.addEventListener("change", handler, { passive: true });
remove = useEvent(connection, "change", handler, { passive: true });
handler();
compositionApi.onUnmounted(remove);
}
else {
console.warn("[navigator.connection] not found, networkInformation not available.");
/* istanbul ignore else */
{
console.warn("[navigator.connection] not found, networkInformation not available.");
}
}

@@ -357,62 +284,375 @@ return {

// used to store all the instances of weakMap
const keyedMap = new Map();
const weakMap = new WeakMap();
function useLocalStorage(key, defaultValue) {
let lazy = false;
let k = keyedMap.get(key);
const json = localStorage.getItem(key);
const storage = (k && weakMap.get(k)) ||
(!!defaultValue && core.wrap(defaultValue)) ||
compositionApi.ref(null);
if (json && !k) {
try {
storage.value = JSON.parse(json);
lazy = false;
let online = undefined;
function useOnline() {
const supported = "onLine" in navigator;
// not sure how to test this :/
if (!supported) {
online = compositionApi.ref(false);
}
if (!online) {
online = compositionApi.ref(navigator.onLine);
window.addEventListener("offline", () => (online.value = false), {
passive: true
});
window.addEventListener("online", () => (online.value = true), {
passive: true
});
}
return {
supported,
online
};
}
let visibility = undefined;
let hidden = undefined;
function usePageVisibility() {
if (!hidden) {
hidden = compositionApi.ref(document.hidden);
}
if (!visibility) {
visibility = compositionApi.ref(document.visibilityState);
document.addEventListener("visibilitychange", () => {
visibility.value = document.visibilityState;
hidden.value = document.hidden;
}, { passive: true }
// true
);
}
return {
visibility,
hidden
};
}
let language = undefined;
let languages = undefined;
function useLanguage() {
if (!language) {
language = compositionApi.ref(navigator.language);
}
if (!languages) {
languages = compositionApi.ref(navigator.languages);
const change = () => {
language.value = navigator.language;
languages.value = navigator.languages;
};
window.addEventListener('languagechange', change, { passive: true });
}
return {
language,
languages
};
}
function useMatchMedia(query) {
const mediaQueryList = compositionApi.ref(matchMedia(query));
const matches = compositionApi.ref(mediaQueryList.value.matches);
const process = (e) => {
matches.value = e.matches;
};
mediaQueryList.value.addEventListener("change", process, { passive: true });
const remove = () => mediaQueryList.value.removeEventListener("change", process);
compositionApi.onUnmounted(remove);
return {
mediaQueryList,
remove,
matches
};
}
function useBreakpoint(breakpoints) {
const result = {};
const map = new Map();
const current = compositionApi.ref();
let sorted = [];
const removeMedia = [];
for (const key in breakpoints) {
const bp = breakpoints[key];
if (core.isNumber(bp)) {
const r = compositionApi.ref(false);
result[key] = r;
map.set(bp, {
name: key,
valid: r
});
sorted.push(bp);
}
catch (e) {
/* istanbul ignore next */
console.warn("[useLocalStorage] error parsing value from localStorage", key, e);
else {
const { matches, remove } = useMatchMedia(bp);
result[key] = matches;
removeMedia.push(remove);
}
}
// do not watch if we already created the instance
if (!k) {
k = {};
keyedMap.set(key, k);
weakMap.set(k, storage);
compositionApi.watch(storage, storage => {
if (storage === undefined) {
localStorage.removeItem(key);
return;
sorted = sorted.sort((a, b) => b - a);
const resize = () => {
const width = window.innerWidth;
let c = undefined;
for (let i = 0; i < sorted.length; i++) {
const bp = sorted[i];
const r = map.get(bp);
r.valid.value = width >= bp;
if (width >= bp && c === undefined) {
c = r.name;
}
// do not overflow localStorage with updates nor keep doing stringify
core.debounce(() => localStorage.setItem(key, JSON.stringify(storage)), 100)();
}, {
deep: true,
lazy
}
current.value = c;
};
const processResize = core.useDebounce(resize, 10);
const remove = () => window.removeEventListener("resize", processResize);
compositionApi.onMounted(() => {
resize();
window.addEventListener("resize", processResize, {
passive: true
});
});
compositionApi.onUnmounted(() => {
remove();
removeMedia.forEach(x => x());
});
return {
...result,
remove,
current
};
}
/* istanbul ignore next */
function isQuotaExceededError(e, storage) {
return e instanceof DOMException && (
// everything except Firefox
e.code === 22 ||
// Firefox
e.code === 1014 ||
// test name field too, because code might not be present
// everything except Firefox
e.name === 'QuotaExceededError' ||
// Firefox
e.name === 'NS_ERROR_DOM_QUOTA_REACHED') &&
// acknowledge QuotaExceededError only if there's something already stored
(storage && storage.length !== 0);
}
// based on https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API
function storageAvailable(storage) {
try {
const x = '__storage_test__';
storage.setItem(x, x);
storage.removeItem(x);
return true;
}
const clear = () => {
keyedMap.forEach((v) => {
const obj = weakMap.get(v);
/* istanbul ignore else */
if (obj) {
obj.value = undefined;
catch (e) {
return isQuotaExceededError(e, storage);
}
}
function safeParse(serializer, value) {
try {
return serializer.parse(value);
}
catch {
return value;
}
}
let storageMap = undefined;
function useWebStorage(type, serializer = JSON, ms = 10) {
const storage = window[type];
const supported = storageAvailable(storage);
const remove = () => storageMap.delete(type);
if (!storageMap) {
storageMap = new Map();
window.addEventListener('storage', (e) => {
if (e.newValue === e.oldValue) {
return;
}
weakMap.delete(v);
let webStore = storageMap.get('localStorage');
if (e.storageArea === window.localStorage) {
webStore = storageMap.get('localStorage');
}
else {
webStore = storageMap.get('sessionStorage');
}
if (webStore && Object.keys(webStore.$syncKeys).length > 0) {
if (e.key === null) {
webStore.clear();
}
else if (webStore.$syncKeys[e.key]) {
if (e.newValue === null) {
webStore.removeItem(e.key);
}
else {
webStore.updateItem(e.key, e.newValue);
}
}
}
});
keyedMap.clear();
}
let store = storageMap.get(type);
let quotaError;
if (supported) {
if (!store) {
quotaError = compositionApi.ref(false);
store = {
$refMap: new Map(),
$watchHandlers: new Map(),
$syncKeys: {},
$quotaError: quotaError,
key: storage.key,
length: storage.length,
setSync(key, sync) {
if (sync) {
this.$syncKeys[key] = true;
}
else {
delete this.$syncKeys[key];
}
},
clear() {
this.$refMap.forEach((_, k) => this.removeItem(k));
},
removeItem(k) {
const item = this.$refMap.get(k);
// remove the object value if item deleted
if (item) {
item.value = undefined;
}
// clear the watch
const stop = this.$watchHandlers.get(k);
if (stop) {
stop();
}
delete this.$syncKeys[k];
this.$refMap.delete(k);
storage.removeItem(k);
},
getItem(k) {
let r = this.$refMap.get(k);
if (r) {
return r;
}
const data = storage.getItem(k);
if (!data) {
return null;
}
return this.setItem(k, safeParse(serializer, data));
},
setItem(k, v) {
const reference = core.wrap(v);
this.$refMap.set(k, reference);
const save = (key, value) => {
try {
const data = core.isString(value) ? value : serializer.stringify(value);
storage.setItem(key, data);
}
catch (e) {
quotaError.value = isQuotaExceededError(e, storage);
}
};
save(k, v);
const stop = compositionApi.watch(reference, core.debounce((r) => {
save(k, r);
}, ms), {
lazy: true,
deep: true
});
this.$watchHandlers.set(k, stop);
return reference;
},
updateItem(k, data) {
let r = this.$refMap.get(k);
if (r) {
r.value = safeParse(serializer, data);
}
}
};
storageMap.set(type, store);
}
else {
quotaError = store.$quotaError;
}
}
else {
quotaError = compositionApi.ref(false);
store = {};
}
return {
supported,
quotaError,
store,
remove
};
const remove = () => {
keyedMap.delete(key);
weakMap.delete(k);
storage.value = undefined;
}
function useLocalStorage(key, defaultValue) {
const { supported, store } = useWebStorage('localStorage');
let remove = core.NO_OP;
let clear = core.NO_OP;
let setSync = core.NO_OP;
let storage = undefined;
if (supported && store) {
setSync = (s) => store.setSync(key, s);
remove = () => store.removeItem(key);
clear = () => store.clear();
storage = store.getItem(key);
if (!storage) {
storage = store.setItem(key, defaultValue);
}
}
else {
/* istanbul ignore else */
{
console.warn('[localStorage] is not available');
}
}
return {
supported,
storage,
clear,
remove,
setSync,
};
}
function useSessionStorage(key, defaultValue) {
const { supported, store } = useWebStorage('sessionStorage');
let remove = core.NO_OP;
let clear = core.NO_OP;
let setSync = core.FALSE_OP;
let storage = undefined;
if (supported && store) {
/* istanbul ignore else */
{
setSync = () => console.warn('sync is not supported, please `useLocalStorage` instead');
}
remove = () => store.removeItem(key);
clear = () => store.clear();
storage = store.getItem(key);
if (!storage) {
storage = store.setItem(key, defaultValue);
}
}
else {
/* istanbul ignore else */
{
console.warn('[sessionStorage] is not available');
}
}
return {
supported,
storage,
clear,
remove
remove,
setSync
};
}
let canUseLocalStorage = undefined;
function useStorage(key, defaultValue) {
if (canUseLocalStorage === undefined) {
canUseLocalStorage = useWebStorage('localStorage').supported;
}
return canUseLocalStorage
? useLocalStorage(key, defaultValue)
: useSessionStorage(key, defaultValue);
}
exports.storageAvailable = storageAvailable;
exports.useBreakpoint = useBreakpoint;

@@ -422,2 +662,3 @@ exports.useEvent = useEvent;

exports.useIntersectionObserver = useIntersectionObserver;
exports.useLanguage = useLanguage;
exports.useLocalStorage = useLocalStorage;

@@ -429,2 +670,7 @@ exports.useMatchMedia = useMatchMedia;

exports.useOnScroll = useOnScroll;
exports.useOnline = useOnline;
exports.usePageVisibility = usePageVisibility;
exports.useSessionStorage = useSessionStorage;
exports.useStorage = useStorage;
exports.useWebSocket = useWebSocket;
exports.useWebStorage = useWebStorage;

@@ -79,74 +79,2 @@ 'use strict';

function useMatchMedia(query) {
const mediaQueryList = compositionApi.ref(matchMedia(query));
const matches = compositionApi.ref(mediaQueryList.value.matches);
const process = (e) => {
matches.value = e.matches;
};
mediaQueryList.value.addEventListener("change", process, { passive: true });
const remove = () => mediaQueryList.value.removeEventListener("change", process);
compositionApi.onUnmounted(remove);
return {
mediaQueryList,
remove,
matches
};
}
function useBreakpoint(breakpoints) {
const result = {};
const map = new Map();
const current = compositionApi.ref();
let sorted = [];
const removeMedia = [];
for (const key in breakpoints) {
const bp = breakpoints[key];
if (core.isNumber(bp)) {
const r = compositionApi.ref(false);
result[key] = r;
map.set(bp, {
name: key,
valid: r
});
sorted.push(bp);
}
else {
const { matches, remove } = useMatchMedia(bp);
result[key] = matches;
removeMedia.push(remove);
}
}
sorted = sorted.sort((a, b) => b - a);
const resize = () => {
const width = window.innerWidth;
let c = undefined;
for (let i = 0; i < sorted.length; i++) {
const bp = sorted[i];
const r = map.get(bp);
r.valid.value = width >= bp;
if (width >= bp && c === undefined) {
c = r.name;
}
}
current.value = c;
};
const processResize = core.useDebounce(resize, 10);
const remove = () => window.removeEventListener("resize", processResize);
compositionApi.onMounted(() => {
resize();
window.addEventListener("resize", processResize, {
passive: true
});
});
compositionApi.onUnmounted(() => {
remove();
removeMedia.forEach(x => x());
});
return {
...result,
remove,
current
};
}
function useFetch(options) {

@@ -322,8 +250,4 @@ const json = compositionApi.ref(null);

};
remove = () => {
connection.removeEventListener("change", handler);
};
connection.addEventListener("change", handler, { passive: true });
remove = useEvent(connection, "change", handler, { passive: true });
handler();
compositionApi.onUnmounted(remove);
}

@@ -342,62 +266,359 @@ return {

// used to store all the instances of weakMap
const keyedMap = new Map();
const weakMap = new WeakMap();
function useLocalStorage(key, defaultValue) {
let lazy = false;
let k = keyedMap.get(key);
const json = localStorage.getItem(key);
const storage = (k && weakMap.get(k)) ||
(!!defaultValue && core.wrap(defaultValue)) ||
compositionApi.ref(null);
if (json && !k) {
try {
storage.value = JSON.parse(json);
lazy = false;
let online = undefined;
function useOnline() {
const supported = "onLine" in navigator;
// not sure how to test this :/
if (!supported) {
online = compositionApi.ref(false);
}
if (!online) {
online = compositionApi.ref(navigator.onLine);
window.addEventListener("offline", () => (online.value = false), {
passive: true
});
window.addEventListener("online", () => (online.value = true), {
passive: true
});
}
return {
supported,
online
};
}
let visibility = undefined;
let hidden = undefined;
function usePageVisibility() {
if (!hidden) {
hidden = compositionApi.ref(document.hidden);
}
if (!visibility) {
visibility = compositionApi.ref(document.visibilityState);
document.addEventListener("visibilitychange", () => {
visibility.value = document.visibilityState;
hidden.value = document.hidden;
}, { passive: true }
// true
);
}
return {
visibility,
hidden
};
}
let language = undefined;
let languages = undefined;
function useLanguage() {
if (!language) {
language = compositionApi.ref(navigator.language);
}
if (!languages) {
languages = compositionApi.ref(navigator.languages);
const change = () => {
language.value = navigator.language;
languages.value = navigator.languages;
};
window.addEventListener('languagechange', change, { passive: true });
}
return {
language,
languages
};
}
function useMatchMedia(query) {
const mediaQueryList = compositionApi.ref(matchMedia(query));
const matches = compositionApi.ref(mediaQueryList.value.matches);
const process = (e) => {
matches.value = e.matches;
};
mediaQueryList.value.addEventListener("change", process, { passive: true });
const remove = () => mediaQueryList.value.removeEventListener("change", process);
compositionApi.onUnmounted(remove);
return {
mediaQueryList,
remove,
matches
};
}
function useBreakpoint(breakpoints) {
const result = {};
const map = new Map();
const current = compositionApi.ref();
let sorted = [];
const removeMedia = [];
for (const key in breakpoints) {
const bp = breakpoints[key];
if (core.isNumber(bp)) {
const r = compositionApi.ref(false);
result[key] = r;
map.set(bp, {
name: key,
valid: r
});
sorted.push(bp);
}
catch (e) {
/* istanbul ignore next */
console.warn("[useLocalStorage] error parsing value from localStorage", key, e);
else {
const { matches, remove } = useMatchMedia(bp);
result[key] = matches;
removeMedia.push(remove);
}
}
// do not watch if we already created the instance
if (!k) {
k = {};
keyedMap.set(key, k);
weakMap.set(k, storage);
compositionApi.watch(storage, storage => {
if (storage === undefined) {
localStorage.removeItem(key);
return;
sorted = sorted.sort((a, b) => b - a);
const resize = () => {
const width = window.innerWidth;
let c = undefined;
for (let i = 0; i < sorted.length; i++) {
const bp = sorted[i];
const r = map.get(bp);
r.valid.value = width >= bp;
if (width >= bp && c === undefined) {
c = r.name;
}
// do not overflow localStorage with updates nor keep doing stringify
core.debounce(() => localStorage.setItem(key, JSON.stringify(storage)), 100)();
}, {
deep: true,
lazy
}
current.value = c;
};
const processResize = core.useDebounce(resize, 10);
const remove = () => window.removeEventListener("resize", processResize);
compositionApi.onMounted(() => {
resize();
window.addEventListener("resize", processResize, {
passive: true
});
});
compositionApi.onUnmounted(() => {
remove();
removeMedia.forEach(x => x());
});
return {
...result,
remove,
current
};
}
/* istanbul ignore next */
function isQuotaExceededError(e, storage) {
return e instanceof DOMException && (
// everything except Firefox
e.code === 22 ||
// Firefox
e.code === 1014 ||
// test name field too, because code might not be present
// everything except Firefox
e.name === 'QuotaExceededError' ||
// Firefox
e.name === 'NS_ERROR_DOM_QUOTA_REACHED') &&
// acknowledge QuotaExceededError only if there's something already stored
(storage && storage.length !== 0);
}
// based on https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API
function storageAvailable(storage) {
try {
const x = '__storage_test__';
storage.setItem(x, x);
storage.removeItem(x);
return true;
}
const clear = () => {
keyedMap.forEach((v) => {
const obj = weakMap.get(v);
/* istanbul ignore else */
if (obj) {
obj.value = undefined;
catch (e) {
return isQuotaExceededError(e, storage);
}
}
function safeParse(serializer, value) {
try {
return serializer.parse(value);
}
catch {
return value;
}
}
let storageMap = undefined;
function useWebStorage(type, serializer = JSON, ms = 10) {
const storage = window[type];
const supported = storageAvailable(storage);
const remove = () => storageMap.delete(type);
if (!storageMap) {
storageMap = new Map();
window.addEventListener('storage', (e) => {
if (e.newValue === e.oldValue) {
return;
}
weakMap.delete(v);
let webStore = storageMap.get('localStorage');
if (e.storageArea === window.localStorage) {
webStore = storageMap.get('localStorage');
}
else {
webStore = storageMap.get('sessionStorage');
}
if (webStore && Object.keys(webStore.$syncKeys).length > 0) {
if (e.key === null) {
webStore.clear();
}
else if (webStore.$syncKeys[e.key]) {
if (e.newValue === null) {
webStore.removeItem(e.key);
}
else {
webStore.updateItem(e.key, e.newValue);
}
}
}
});
keyedMap.clear();
}
let store = storageMap.get(type);
let quotaError;
if (supported) {
if (!store) {
quotaError = compositionApi.ref(false);
store = {
$refMap: new Map(),
$watchHandlers: new Map(),
$syncKeys: {},
$quotaError: quotaError,
key: storage.key,
length: storage.length,
setSync(key, sync) {
if (sync) {
this.$syncKeys[key] = true;
}
else {
delete this.$syncKeys[key];
}
},
clear() {
this.$refMap.forEach((_, k) => this.removeItem(k));
},
removeItem(k) {
const item = this.$refMap.get(k);
// remove the object value if item deleted
if (item) {
item.value = undefined;
}
// clear the watch
const stop = this.$watchHandlers.get(k);
if (stop) {
stop();
}
delete this.$syncKeys[k];
this.$refMap.delete(k);
storage.removeItem(k);
},
getItem(k) {
let r = this.$refMap.get(k);
if (r) {
return r;
}
const data = storage.getItem(k);
if (!data) {
return null;
}
return this.setItem(k, safeParse(serializer, data));
},
setItem(k, v) {
const reference = core.wrap(v);
this.$refMap.set(k, reference);
const save = (key, value) => {
try {
const data = core.isString(value) ? value : serializer.stringify(value);
storage.setItem(key, data);
}
catch (e) {
quotaError.value = isQuotaExceededError(e, storage);
}
};
save(k, v);
const stop = compositionApi.watch(reference, core.debounce((r) => {
save(k, r);
}, ms), {
lazy: true,
deep: true
});
this.$watchHandlers.set(k, stop);
return reference;
},
updateItem(k, data) {
let r = this.$refMap.get(k);
if (r) {
r.value = safeParse(serializer, data);
}
}
};
storageMap.set(type, store);
}
else {
quotaError = store.$quotaError;
}
}
else {
quotaError = compositionApi.ref(false);
store = {};
}
return {
supported,
quotaError,
store,
remove
};
const remove = () => {
keyedMap.delete(key);
weakMap.delete(k);
storage.value = undefined;
}
function useLocalStorage(key, defaultValue) {
const { supported, store } = useWebStorage('localStorage');
let remove = core.NO_OP;
let clear = core.NO_OP;
let setSync = core.NO_OP;
let storage = undefined;
if (supported && store) {
setSync = (s) => store.setSync(key, s);
remove = () => store.removeItem(key);
clear = () => store.clear();
storage = store.getItem(key);
if (!storage) {
storage = store.setItem(key, defaultValue);
}
}
return {
supported,
storage,
clear,
remove,
setSync,
};
}
function useSessionStorage(key, defaultValue) {
const { supported, store } = useWebStorage('sessionStorage');
let remove = core.NO_OP;
let clear = core.NO_OP;
let setSync = core.FALSE_OP;
let storage = undefined;
if (supported && store) {
remove = () => store.removeItem(key);
clear = () => store.clear();
storage = store.getItem(key);
if (!storage) {
storage = store.setItem(key, defaultValue);
}
}
return {
supported,
storage,
clear,
remove
remove,
setSync
};
}
let canUseLocalStorage = undefined;
function useStorage(key, defaultValue) {
if (canUseLocalStorage === undefined) {
canUseLocalStorage = useWebStorage('localStorage').supported;
}
return canUseLocalStorage
? useLocalStorage(key, defaultValue)
: useSessionStorage(key, defaultValue);
}
exports.storageAvailable = storageAvailable;
exports.useBreakpoint = useBreakpoint;

@@ -407,2 +628,3 @@ exports.useEvent = useEvent;

exports.useIntersectionObserver = useIntersectionObserver;
exports.useLanguage = useLanguage;
exports.useLocalStorage = useLocalStorage;

@@ -414,2 +636,7 @@ exports.useMatchMedia = useMatchMedia;

exports.useOnScroll = useOnScroll;
exports.useOnline = useOnline;
exports.usePageVisibility = usePageVisibility;
exports.useSessionStorage = useSessionStorage;
exports.useStorage = useStorage;
exports.useWebSocket = useWebSocket;
exports.useWebStorage = useWebStorage;

@@ -20,2 +20,3 @@ import { Ref } from '@vue/composition-api';

export declare interface LocalStorageReturn<T> {
supported: boolean;
storage: Ref<T>;

@@ -30,5 +31,9 @@ /**

clear: () => void;
/**
* @description Enable cross tab syncing
*/
setSync: (sync: boolean) => void;
}
export declare type LocalStorageTyped<T> = string;
export declare type LocalStorageTyped<T extends object> = string;

@@ -107,2 +112,9 @@ export declare interface MouseMoveResult {

export declare function storageAvailable(storage: Storage): boolean;
export declare interface StorageSerializer<T = any> {
stringify(item: T): string;
parse(data: string): T;
}
export declare function useBreakpoint<T>(breakpoints: Record<keyof T, number | string>): Record<keyof T, Ref<boolean>> & {

@@ -113,2 +125,12 @@ remove: RemoveEventFunction;

export declare function useEvent<T extends {
addEventListener: (name: string, listener: EventListenerOrEventListenerObject) => any;
removeEventListener: Function;
}, M, K extends keyof M>(el: RefTyped<T>, name: K, listener: (this: T, ev: M[K]) => any): RemoveEventFunction;
export declare function useEvent<T extends {
addEventListener: (name: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions) => any;
removeEventListener: Function;
}, M, K extends keyof M>(el: RefTyped<T>, name: K, listener: (this: T, ev: M[K]) => any, options?: boolean | AddEventListenerOptions): RemoveEventFunction;
export declare function useEvent<K extends keyof WindowEventMap>(el: RefTyped<Window>, name: K, listener: (this: Document, ev: WindowEventMap[K]) => any, options?: boolean | AddEventListenerOptions): RemoveEventFunction;

@@ -147,4 +169,11 @@

export declare function useLocalStorage<T = any>(key: LocalStorageTyped<T> | string, defaultValue?: RefTyped<T>): LocalStorageReturn<T>;
export declare function useLanguage(): {
language: Ref<String>;
languages: Ref<readonly String[]>;
};
export declare function useLocalStorage(key: string, defaultValue?: RefTyped<string>): LocalStorageReturn<string>;
export declare function useLocalStorage<T extends object = any>(key: LocalStorageTyped<T> | string, defaultValue?: RefTyped<T>): LocalStorageReturn<T>;
export declare function useMatchMedia(query: string): {

@@ -158,2 +187,7 @@ mediaQueryList: import("@vue/composition-api").Ref<MediaQueryList>;

export declare function useOnline(): {
supported: boolean;
online: Ref<boolean>;
};
export declare function useOnMouseMove(el: RefTyped<Window>, wait: number): MouseMoveResult;

@@ -183,2 +217,15 @@

export declare function usePageVisibility(): {
visibility: Ref<VisibilityState>;
hidden: Ref<boolean>;
};
export declare function useSessionStorage(key: string, defaultValue?: RefTyped<string>): LocalStorageReturn<string>;
export declare function useSessionStorage<T extends object = object>(key: LocalStorageTyped<T> | string, defaultValue?: RefTyped<T>): LocalStorageReturn<T>;
export declare function useStorage(key: string, defaultValue?: RefTyped<string>): LocalStorageReturn<string>;
export declare function useStorage<T extends object = any>(key: LocalStorageTyped<T> | string, defaultValue?: RefTyped<T>): LocalStorageReturn<T>;
export declare function useWebSocket(url: string, protocols?: string | string[]): {

@@ -196,2 +243,46 @@ ws: WebSocket;

export declare function useWebStorage(type: WebStorageType, serializer?: StorageSerializer, ms?: number): {
supported: boolean;
quotaError: Ref<boolean>;
store: WebStorage;
remove: () => boolean;
};
export declare interface WebStorage {
$refMap: Map<string, Ref<any>>;
$watchHandlers: Map<string, Function>;
$syncKeys: Record<string, boolean>;
$quotaError: Ref<boolean>;
updateItem(key: string, value: string): void;
setSync(key: string, sync: boolean): void;
/**
* Returns the number of key/value pairs currently present in the list associated with the object.
*/
readonly length: number;
/**
* Empties the list associated with the object of all key/value pairs, if there are any.
*/
clear(): void;
/**
* Returns the current value associated with the given key, or null if the given key does not exist in the list associated with the object.
*/
getItem<T = any>(key: string): Ref<T> | null;
/**
* Returns the name of the nth key in the list, or null if n is greater than or equal to the number of key/value pairs in the object.
*/
key(index: number): string | null;
/**
* Removes the key/value pair with the given key from the list associated with the object, if a key/value pair with the given key exists.
*/
removeItem(key: string): void;
/**
* Sets the value of the pair identified by key to value, creating a new key/value pair if none existed for key previously.
*
* Throws a "QuotaExceededError" DOMException exception if the new value couldn't be set. (Setting could fail if, e.g., the user has disabled storage for the site, or if the quota has been exceeded.)
*/
setItem<T>(key: string, value: T): Ref<T>;
}
declare type WebStorageType = 'localStorage' | 'sessionStorage';
export { }
import { onMounted, onUnmounted, ref, computed, watch } from '@vue/composition-api';
import { wrap, useDebounce, isNumber, usePromise, isElement, unwrap, NO_OP, debounce } from '@vue-composable/core';
import { wrap, useDebounce, usePromise, isElement, unwrap, NO_OP, isNumber, debounce, isString, FALSE_OP } from '@vue-composable/core';

@@ -75,74 +75,2 @@ function useEvent(el, name, listener, options) {

function useMatchMedia(query) {
const mediaQueryList = ref(matchMedia(query));
const matches = ref(mediaQueryList.value.matches);
const process = (e) => {
matches.value = e.matches;
};
mediaQueryList.value.addEventListener("change", process, { passive: true });
const remove = () => mediaQueryList.value.removeEventListener("change", process);
onUnmounted(remove);
return {
mediaQueryList,
remove,
matches
};
}
function useBreakpoint(breakpoints) {
const result = {};
const map = new Map();
const current = ref();
let sorted = [];
const removeMedia = [];
for (const key in breakpoints) {
const bp = breakpoints[key];
if (isNumber(bp)) {
const r = ref(false);
result[key] = r;
map.set(bp, {
name: key,
valid: r
});
sorted.push(bp);
}
else {
const { matches, remove } = useMatchMedia(bp);
result[key] = matches;
removeMedia.push(remove);
}
}
sorted = sorted.sort((a, b) => b - a);
const resize = () => {
const width = window.innerWidth;
let c = undefined;
for (let i = 0; i < sorted.length; i++) {
const bp = sorted[i];
const r = map.get(bp);
r.valid.value = width >= bp;
if (width >= bp && c === undefined) {
c = r.name;
}
}
current.value = c;
};
const processResize = useDebounce(resize, 10);
const remove = () => window.removeEventListener("resize", processResize);
onMounted(() => {
resize();
window.addEventListener("resize", processResize, {
passive: true
});
});
onUnmounted(() => {
remove();
removeMedia.forEach(x => x());
});
return {
...result,
remove,
current
};
}
function useFetch(options) {

@@ -330,11 +258,10 @@ const json = ref(null);

};
remove = () => {
connection.removeEventListener("change", handler);
};
connection.addEventListener("change", handler, { passive: true });
remove = useEvent(connection, "change", handler, { passive: true });
handler();
onUnmounted(remove);
}
else if ((true !== 'production')) {
console.warn("[navigator.connection] not found, networkInformation not available.");
else {
/* istanbul ignore else */
if ((true !== 'production')) {
console.warn("[navigator.connection] not found, networkInformation not available.");
}
}

@@ -353,62 +280,374 @@ return {

// used to store all the instances of weakMap
const keyedMap = new Map();
const weakMap = new WeakMap();
function useLocalStorage(key, defaultValue) {
let lazy = false;
let k = keyedMap.get(key);
const json = localStorage.getItem(key);
const storage = (k && weakMap.get(k)) ||
(!!defaultValue && wrap(defaultValue)) ||
ref(null);
if (json && !k) {
try {
storage.value = JSON.parse(json);
lazy = false;
let online = undefined;
function useOnline() {
const supported = "onLine" in navigator;
// not sure how to test this :/
if (!supported) {
online = ref(false);
}
if (!online) {
online = ref(navigator.onLine);
window.addEventListener("offline", () => (online.value = false), {
passive: true
});
window.addEventListener("online", () => (online.value = true), {
passive: true
});
}
return {
supported,
online
};
}
let visibility = undefined;
let hidden = undefined;
function usePageVisibility() {
if (!hidden) {
hidden = ref(document.hidden);
}
if (!visibility) {
visibility = ref(document.visibilityState);
document.addEventListener("visibilitychange", () => {
visibility.value = document.visibilityState;
hidden.value = document.hidden;
}, { passive: true }
// true
);
}
return {
visibility,
hidden
};
}
let language = undefined;
let languages = undefined;
function useLanguage() {
if (!language) {
language = ref(navigator.language);
}
if (!languages) {
languages = ref(navigator.languages);
const change = () => {
language.value = navigator.language;
languages.value = navigator.languages;
};
window.addEventListener('languagechange', change, { passive: true });
}
return {
language,
languages
};
}
function useMatchMedia(query) {
const mediaQueryList = ref(matchMedia(query));
const matches = ref(mediaQueryList.value.matches);
const process = (e) => {
matches.value = e.matches;
};
mediaQueryList.value.addEventListener("change", process, { passive: true });
const remove = () => mediaQueryList.value.removeEventListener("change", process);
onUnmounted(remove);
return {
mediaQueryList,
remove,
matches
};
}
function useBreakpoint(breakpoints) {
const result = {};
const map = new Map();
const current = ref();
let sorted = [];
const removeMedia = [];
for (const key in breakpoints) {
const bp = breakpoints[key];
if (isNumber(bp)) {
const r = ref(false);
result[key] = r;
map.set(bp, {
name: key,
valid: r
});
sorted.push(bp);
}
catch (e) {
/* istanbul ignore next */
console.warn("[useLocalStorage] error parsing value from localStorage", key, e);
else {
const { matches, remove } = useMatchMedia(bp);
result[key] = matches;
removeMedia.push(remove);
}
}
// do not watch if we already created the instance
if (!k) {
k = {};
keyedMap.set(key, k);
weakMap.set(k, storage);
watch(storage, storage => {
if (storage === undefined) {
localStorage.removeItem(key);
return;
sorted = sorted.sort((a, b) => b - a);
const resize = () => {
const width = window.innerWidth;
let c = undefined;
for (let i = 0; i < sorted.length; i++) {
const bp = sorted[i];
const r = map.get(bp);
r.valid.value = width >= bp;
if (width >= bp && c === undefined) {
c = r.name;
}
// do not overflow localStorage with updates nor keep doing stringify
debounce(() => localStorage.setItem(key, JSON.stringify(storage)), 100)();
}, {
deep: true,
lazy
}
current.value = c;
};
const processResize = useDebounce(resize, 10);
const remove = () => window.removeEventListener("resize", processResize);
onMounted(() => {
resize();
window.addEventListener("resize", processResize, {
passive: true
});
});
onUnmounted(() => {
remove();
removeMedia.forEach(x => x());
});
return {
...result,
remove,
current
};
}
/* istanbul ignore next */
function isQuotaExceededError(e, storage) {
return e instanceof DOMException && (
// everything except Firefox
e.code === 22 ||
// Firefox
e.code === 1014 ||
// test name field too, because code might not be present
// everything except Firefox
e.name === 'QuotaExceededError' ||
// Firefox
e.name === 'NS_ERROR_DOM_QUOTA_REACHED') &&
// acknowledge QuotaExceededError only if there's something already stored
(storage && storage.length !== 0);
}
// based on https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API
function storageAvailable(storage) {
try {
const x = '__storage_test__';
storage.setItem(x, x);
storage.removeItem(x);
return true;
}
const clear = () => {
keyedMap.forEach((v) => {
const obj = weakMap.get(v);
/* istanbul ignore else */
if (obj) {
obj.value = undefined;
catch (e) {
return isQuotaExceededError(e, storage);
}
}
function safeParse(serializer, value) {
try {
return serializer.parse(value);
}
catch {
return value;
}
}
let storageMap = undefined;
function useWebStorage(type, serializer = JSON, ms = 10) {
const storage = window[type];
const supported = storageAvailable(storage);
const remove = () => storageMap.delete(type);
if (!storageMap) {
storageMap = new Map();
window.addEventListener('storage', (e) => {
if (e.newValue === e.oldValue) {
return;
}
weakMap.delete(v);
let webStore = storageMap.get('localStorage');
if (e.storageArea === window.localStorage) {
webStore = storageMap.get('localStorage');
}
else {
webStore = storageMap.get('sessionStorage');
}
if (webStore && Object.keys(webStore.$syncKeys).length > 0) {
if (e.key === null) {
webStore.clear();
}
else if (webStore.$syncKeys[e.key]) {
if (e.newValue === null) {
webStore.removeItem(e.key);
}
else {
webStore.updateItem(e.key, e.newValue);
}
}
}
});
keyedMap.clear();
}
let store = storageMap.get(type);
let quotaError;
if (supported) {
if (!store) {
quotaError = ref(false);
store = {
$refMap: new Map(),
$watchHandlers: new Map(),
$syncKeys: {},
$quotaError: quotaError,
key: storage.key,
length: storage.length,
setSync(key, sync) {
if (sync) {
this.$syncKeys[key] = true;
}
else {
delete this.$syncKeys[key];
}
},
clear() {
this.$refMap.forEach((_, k) => this.removeItem(k));
},
removeItem(k) {
const item = this.$refMap.get(k);
// remove the object value if item deleted
if (item) {
item.value = undefined;
}
// clear the watch
const stop = this.$watchHandlers.get(k);
if (stop) {
stop();
}
delete this.$syncKeys[k];
this.$refMap.delete(k);
storage.removeItem(k);
},
getItem(k) {
let r = this.$refMap.get(k);
if (r) {
return r;
}
const data = storage.getItem(k);
if (!data) {
return null;
}
return this.setItem(k, safeParse(serializer, data));
},
setItem(k, v) {
const reference = wrap(v);
this.$refMap.set(k, reference);
const save = (key, value) => {
try {
const data = isString(value) ? value : serializer.stringify(value);
storage.setItem(key, data);
}
catch (e) {
quotaError.value = isQuotaExceededError(e, storage);
}
};
save(k, v);
const stop = watch(reference, debounce((r) => {
save(k, r);
}, ms), {
lazy: true,
deep: true
});
this.$watchHandlers.set(k, stop);
return reference;
},
updateItem(k, data) {
let r = this.$refMap.get(k);
if (r) {
r.value = safeParse(serializer, data);
}
}
};
storageMap.set(type, store);
}
else {
quotaError = store.$quotaError;
}
}
else {
quotaError = ref(false);
store = {};
}
return {
supported,
quotaError,
store,
remove
};
const remove = () => {
keyedMap.delete(key);
weakMap.delete(k);
storage.value = undefined;
}
function useLocalStorage(key, defaultValue) {
const { supported, store } = useWebStorage('localStorage');
let remove = NO_OP;
let clear = NO_OP;
let setSync = NO_OP;
let storage = undefined;
if (supported && store) {
setSync = (s) => store.setSync(key, s);
remove = () => store.removeItem(key);
clear = () => store.clear();
storage = store.getItem(key);
if (!storage) {
storage = store.setItem(key, defaultValue);
}
}
else {
/* istanbul ignore else */
if ((true !== 'production')) {
console.warn('[localStorage] is not available');
}
}
return {
supported,
storage,
clear,
remove,
setSync,
};
}
function useSessionStorage(key, defaultValue) {
const { supported, store } = useWebStorage('sessionStorage');
let remove = NO_OP;
let clear = NO_OP;
let setSync = FALSE_OP;
let storage = undefined;
if (supported && store) {
/* istanbul ignore else */
if ((true !== 'production')) {
setSync = () => console.warn('sync is not supported, please `useLocalStorage` instead');
}
remove = () => store.removeItem(key);
clear = () => store.clear();
storage = store.getItem(key);
if (!storage) {
storage = store.setItem(key, defaultValue);
}
}
else {
/* istanbul ignore else */
if ((true !== 'production')) {
console.warn('[sessionStorage] is not available');
}
}
return {
supported,
storage,
clear,
remove
remove,
setSync
};
}
export { useBreakpoint, useEvent, useFetch, useIntersectionObserver, useLocalStorage, useMatchMedia, useNetworkInformation, useOnMouseMove, useOnResize, useOnScroll, useWebSocket };
let canUseLocalStorage = undefined;
function useStorage(key, defaultValue) {
if (canUseLocalStorage === undefined) {
canUseLocalStorage = useWebStorage('localStorage').supported;
}
return canUseLocalStorage
? useLocalStorage(key, defaultValue)
: useSessionStorage(key, defaultValue);
}
export { storageAvailable, useBreakpoint, useEvent, useFetch, useIntersectionObserver, useLanguage, useLocalStorage, useMatchMedia, useNetworkInformation, useOnMouseMove, useOnResize, useOnScroll, useOnline, usePageVisibility, useSessionStorage, useStorage, useWebSocket, useWebStorage };

@@ -0,0 +0,0 @@ 'use strict'

{
"name": "@vue-composable/web",
"version": "1.0.0-dev.4",
"version": "1.0.0-dev.6",
"description": "@vue-composable/web",

@@ -38,3 +38,3 @@ "main": "index.js",

"dependencies": {
"@vue-composable/core": "1.0.0-dev.4",
"@vue-composable/core": "1.0.0-dev.6",
"@vue/composition-api": "^0.3.4",

@@ -41,0 +41,0 @@ "vue": "^2.6.10"

@@ -34,6 +34,12 @@ # @vue-composable/web

- [localStorage](https://pikax.me/vue-composable/composable/misc/localStorage) - Reactive access to a `localStorage`
- [matchMedia](https://pikax.me/vue-composable/composable/misc/matchMedia) - Reactive `matchMedia`
- [breakpoint](https://pikax.me/vue-composable/composable/misc/breakpoint) - reactive `breakpoints` based on `window.innerWidth`
### Storage
- [WebStorage](composable/misc/webStorage) - Reactive access to `Storage API`, `useLocalStorage` and `useSessionStorage` use this
- [storage](composable/misc/storage) - uses `localStorage` or on safari private it uses `sessionStorage`
- [localStorage](composable/misc/localStorage) - Reactive access to a `localStorage`
- [sessionStorage](composable/misc/sessionStorage) - Reactive access to a `sessionStorage`
### Web

@@ -45,2 +51,5 @@

- [NetworkInformation](https://pikax.me/vue-composable/composable/web/networkInformation) - reactive `NetworkInformation` wrapper
- [Online](<[composable/web](https://pikax.me/vue-composable/composable/web)/online>) - reactive `navigator.onLine` wrapper
- [PageVisibility](https://pikax.me/vue-composable/composable/web/pageVisibility) - reactive `Page Visibility API`
- [Language](https://pikax.me/vue-composable/composable/web/language) - reactive `NavigatorLanguage`

@@ -47,0 +56,0 @@ ## Contributing

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc