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-alpha.5 to 1.0.0-alpha.7

index.js

524

dist/web.cjs.js

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

function useMatchMedia(query) {
const mediaQueryList = runtimeCore.ref(matchMedia(query));
const matches = runtimeCore.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);
runtimeCore.onUnmounted(remove);
return {
mediaQueryList,
remove,
matches
};
}
function useBreakpoint(breakpoints) {
const result = {};
const map = new Map();
const current = runtimeCore.ref();
let sorted = [];
const removeMedia = [];
for (const key in breakpoints) {
const bp = breakpoints[key];
if (core.isNumber(bp)) {
const r = runtimeCore.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);
runtimeCore.onMounted(() => {
resize();
window.addEventListener("resize", processResize, {
passive: true
});
});
runtimeCore.onUnmounted(() => {
remove();
removeMedia.forEach(x => x());
});
return {
...result,
remove,
current
};
}
function useFetch(options) {

@@ -313,62 +241,419 @@ const json = runtimeCore.ref(null);

// 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)) ||
runtimeCore.ref(null);
if (json && !k) {
try {
storage.value = JSON.parse(json);
lazy = false;
function useNetworkInformation() {
const connection = navigator.connection ||
navigator.mozConnection ||
navigator.webkitConnection;
const supported = runtimeCore.computed(() => !!connection);
const downlink = runtimeCore.ref(0);
const downlinkMax = runtimeCore.ref(0);
const effectiveType = runtimeCore.ref("none");
const rtt = runtimeCore.ref(0);
const saveData = runtimeCore.ref(false);
const type = runtimeCore.ref("none");
let handler = core.NO_OP;
let remove = core.NO_OP;
/* istanbul ignore else */
if (connection) {
handler = () => {
downlink.value = connection.downlink;
downlinkMax.value = connection.downlinkMax;
effectiveType.value = connection.effectiveType;
rtt.value = connection.rtt;
saveData.value = connection.saveData;
type.value = connection.type;
};
remove = useEvent(connection, "change", handler, { passive: true });
handler();
}
else {
/* istanbul ignore else */
{
console.warn("[navigator.connection] not found, networkInformation not available.");
}
catch (e) {
/* istanbul ignore next */
console.warn("[useLocalStorage] error parsing value from localStorage", key, e);
}
return {
supported,
downlink,
downlinkMax,
effectiveType,
rtt,
saveData,
type,
remove
};
}
let online = undefined;
function useOnline() {
const supported = "onLine" in navigator;
// not sure how to test this :/
if (!supported) {
online = runtimeCore.ref(false);
}
if (!online) {
online = runtimeCore.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 = runtimeCore.ref(document.hidden);
}
if (!visibility) {
visibility = runtimeCore.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 = runtimeCore.ref(navigator.language);
}
if (!languages) {
languages = runtimeCore.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 = runtimeCore.ref(matchMedia(query));
const matches = runtimeCore.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);
runtimeCore.onUnmounted(remove);
return {
mediaQueryList,
remove,
matches
};
}
function useBreakpoint(breakpoints) {
const result = {};
const map = new Map();
const current = runtimeCore.ref();
let sorted = [];
const removeMedia = [];
for (const key in breakpoints) {
const bp = breakpoints[key];
if (core.isNumber(bp)) {
const r = runtimeCore.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);
}
}
// do not watch if we already created the instance
if (!k) {
k = {};
keyedMap.set(key, k);
weakMap.set(k, storage);
runtimeCore.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);
runtimeCore.onMounted(() => {
resize();
window.addEventListener("resize", processResize, {
passive: true
});
});
runtimeCore.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 = runtimeCore.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 = runtimeCore.watch(() => reference, core.debounce((r) => {
save(k, r.value);
}, 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 = runtimeCore.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;

@@ -378,7 +663,14 @@ exports.useEvent = useEvent;

exports.useIntersectionObserver = useIntersectionObserver;
exports.useLanguage = useLanguage;
exports.useLocalStorage = useLocalStorage;
exports.useMatchMedia = useMatchMedia;
exports.useNetworkInformation = useNetworkInformation;
exports.useOnMouseMove = useOnMouseMove;
exports.useOnResize = useOnResize;
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 = runtimeCore.ref(matchMedia(query));
const matches = runtimeCore.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);
runtimeCore.onUnmounted(remove);
return {
mediaQueryList,
remove,
matches
};
}
function useBreakpoint(breakpoints) {
const result = {};
const map = new Map();
const current = runtimeCore.ref();
let sorted = [];
const removeMedia = [];
for (const key in breakpoints) {
const bp = breakpoints[key];
if (core.isNumber(bp)) {
const r = runtimeCore.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);
runtimeCore.onMounted(() => {
resize();
window.addEventListener("resize", processResize, {
passive: true
});
});
runtimeCore.onUnmounted(() => {
remove();
removeMedia.forEach(x => x());
});
return {
...result,
remove,
current
};
}
function useFetch(options) {

@@ -301,62 +229,397 @@ const json = runtimeCore.ref(null);

// 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)) ||
runtimeCore.ref(null);
if (json && !k) {
try {
storage.value = JSON.parse(json);
lazy = false;
function useNetworkInformation() {
const connection = navigator.connection ||
navigator.mozConnection ||
navigator.webkitConnection;
const supported = runtimeCore.computed(() => !!connection);
const downlink = runtimeCore.ref(0);
const downlinkMax = runtimeCore.ref(0);
const effectiveType = runtimeCore.ref("none");
const rtt = runtimeCore.ref(0);
const saveData = runtimeCore.ref(false);
const type = runtimeCore.ref("none");
let handler = core.NO_OP;
let remove = core.NO_OP;
/* istanbul ignore else */
if (connection) {
handler = () => {
downlink.value = connection.downlink;
downlinkMax.value = connection.downlinkMax;
effectiveType.value = connection.effectiveType;
rtt.value = connection.rtt;
saveData.value = connection.saveData;
type.value = connection.type;
};
remove = useEvent(connection, "change", handler, { passive: true });
handler();
}
return {
supported,
downlink,
downlinkMax,
effectiveType,
rtt,
saveData,
type,
remove
};
}
let online = undefined;
function useOnline() {
const supported = "onLine" in navigator;
// not sure how to test this :/
if (!supported) {
online = runtimeCore.ref(false);
}
if (!online) {
online = runtimeCore.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 = runtimeCore.ref(document.hidden);
}
if (!visibility) {
visibility = runtimeCore.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 = runtimeCore.ref(navigator.language);
}
if (!languages) {
languages = runtimeCore.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 = runtimeCore.ref(matchMedia(query));
const matches = runtimeCore.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);
runtimeCore.onUnmounted(remove);
return {
mediaQueryList,
remove,
matches
};
}
function useBreakpoint(breakpoints) {
const result = {};
const map = new Map();
const current = runtimeCore.ref();
let sorted = [];
const removeMedia = [];
for (const key in breakpoints) {
const bp = breakpoints[key];
if (core.isNumber(bp)) {
const r = runtimeCore.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);
runtimeCore.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);
runtimeCore.onMounted(() => {
resize();
window.addEventListener("resize", processResize, {
passive: true
});
});
runtimeCore.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 = runtimeCore.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 = runtimeCore.watch(() => reference, core.debounce((r) => {
save(k, r.value);
}, 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 = runtimeCore.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;

@@ -366,7 +629,14 @@ exports.useEvent = useEvent;

exports.useIntersectionObserver = useIntersectionObserver;
exports.useLanguage = useLanguage;
exports.useLocalStorage = useLocalStorage;
exports.useMatchMedia = useMatchMedia;
exports.useNetworkInformation = useNetworkInformation;
exports.useOnMouseMove = useOnMouseMove;
exports.useOnResize = useOnResize;
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/runtime-core';

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;

@@ -41,2 +46,54 @@ export declare interface MouseMoveResult {

export declare interface NetworkInformation {
readonly downlink: number;
readonly downlinkMax: number;
readonly effectiveType: NetworkInformationEffectiveType;
readonly rtt: number;
readonly saveData: Boolean;
readonly type: NetworkInformationType;
onchange: (this: NetworkInformation, ev: Event) => void;
addEventListener<K extends keyof NetworkInformationEventMap>(type: K, listener: (this: NetworkInformation, ev: NetworkInformationEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
removeEventListener<K extends keyof NetworkInformationEventMap>(type: K, listener: (this: NetworkInformation, ev: NetworkInformationEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}
declare type NetworkInformationEffectiveType = "slow-2g" | "2g" | "3g" | "4g" | "none";
declare interface NetworkInformationEventMap {
change: Event;
}
declare interface NetworkInformationReturn {
readonly supported: Ref<boolean>;
/**
* @description Returns the effective bandwidth estimate in megabits per second, rounded to the nearest multiple of 25 kilobits per seconds
*/
readonly downlink: Ref<number>;
/**
* @description Returns the maximum downlink speed, in megabits per second (Mbps), for the underlying connection technology.
*/
readonly downlinkMax: Ref<number>;
/**
* @description Returns the effective type of the connection meaning one of 'slow-2g', '2g', '3g', or '4g'. This value is determined using a combination of recently observed round-trip time and downlink values.
*/
readonly effectiveType: Ref<NetworkInformationEffectiveType>;
/**
* @description Returns the estimated effective round-trip time of the current connection, rounded to the nearest multiple of 25 milliseconds.
*/
readonly rtt: Ref<number>;
/**
* @description Returns true if the user has set a reduced data usage option on the user agent.
*/
readonly saveData: Ref<Boolean>;
/**
* @description Returns the type of connection a device is using to communicate with the network. It will be one of the following values:
* @enum { NetworkInformationType}
*/
readonly type: Ref<NetworkInformationType>;
remove: RemoveEventFunction;
}
declare type NetworkInformationType = "bluetooth" | "cellular" | "ethernet" | "mixed" | "none" | "other" | "unknown" | "wifi" | "wimax";
export declare type RemoveEventFunction = () => void;

@@ -56,2 +113,9 @@

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>> & {

@@ -62,2 +126,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;

@@ -96,4 +170,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): {

@@ -105,2 +186,9 @@ mediaQueryList: import("@vue/reactivity").Ref<MediaQueryList>;

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

@@ -130,2 +218,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[]): {

@@ -143,2 +244,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/runtime-core';
import { wrap, useDebounce, isNumber, usePromise, isElement, unwrap, 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) {

@@ -309,62 +237,418 @@ const json = ref(null);

// 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;
function useNetworkInformation() {
const connection = navigator.connection ||
navigator.mozConnection ||
navigator.webkitConnection;
const supported = computed(() => !!connection);
const downlink = ref(0);
const downlinkMax = ref(0);
const effectiveType = ref("none");
const rtt = ref(0);
const saveData = ref(false);
const type = ref("none");
let handler = NO_OP;
let remove = NO_OP;
/* istanbul ignore else */
if (connection) {
handler = () => {
downlink.value = connection.downlink;
downlinkMax.value = connection.downlinkMax;
effectiveType.value = connection.effectiveType;
rtt.value = connection.rtt;
saveData.value = connection.saveData;
type.value = connection.type;
};
remove = useEvent(connection, "change", handler, { passive: true });
handler();
}
else {
/* istanbul ignore else */
if ((true !== 'production')) {
console.warn("[navigator.connection] not found, networkInformation not available.");
}
catch (e) {
/* istanbul ignore next */
console.warn("[useLocalStorage] error parsing value from localStorage", key, e);
}
return {
supported,
downlink,
downlinkMax,
effectiveType,
rtt,
saveData,
type,
remove
};
}
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);
}
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.value);
}, 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, 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 };
{
"name": "@vue-composable/web",
"version": "1.0.0-alpha.5",
"version": "1.0.0-alpha.7",
"description": "@vue-composable/web",

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

"dependencies": {
"@vue-composable/core": "1.0.0-alpha.5",
"@vue/runtime-core": "^3.0.0-alpha.1"
"@vue-composable/core": "1.0.0-alpha.7",
"@vue/runtime-core": "^3.0.0-alpha.2"
}
}

@@ -36,6 +36,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](https://pikax.me/vue-composable/composable/storage/webStorage) - Reactive access to `Storage API`, `useLocalStorage` and `useSessionStorage` use this
- [storage](https://pikax.me/vue-composable/composable/storage/storage) - uses `localStorage` or on safari private it uses `sessionStorage`
- [localStorage](https://pikax.me/vue-composable/composable/storage/localStorage) - Reactive access to a `localStorage`
- [sessionStorage](https://pikax.me/vue-composable/composable/storage/sessionStorage) - Reactive access to a `sessionStorage`
### Web

@@ -46,2 +52,6 @@

- [IntersectionObserver](https://pikax.me/vue-composable/composable/web/intersectionObserver) - reactive `IntersectionObserver`
- [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`

@@ -48,0 +58,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