callskit
Version:
A toolkit for building call experience using Cloudflare Realtime
364 lines (344 loc) • 11.6 kB
JavaScript
import { EventsHandler, __async, createCallClient } from './chunk-TOUUHMUN.js';
import React, { useState, useCallback } from 'react';
import invariant from 'tiny-invariant';
// ../node_modules/lodash-es/isObject.js
function isObject(value) {
var type = typeof value;
return value != null && (type == "object" || type == "function");
}
var isObject_default = isObject;
// ../node_modules/lodash-es/_freeGlobal.js
var freeGlobal = typeof global == "object" && global && global.Object === Object && global;
var freeGlobal_default = freeGlobal;
// ../node_modules/lodash-es/_root.js
var freeSelf = typeof self == "object" && self && self.Object === Object && self;
var root = freeGlobal_default || freeSelf || Function("return this")();
var root_default = root;
// ../node_modules/lodash-es/now.js
var now = function() {
return root_default.Date.now();
};
var now_default = now;
// ../node_modules/lodash-es/_trimmedEndIndex.js
var reWhitespace = /\s/;
function trimmedEndIndex(string) {
var index = string.length;
while (index-- && reWhitespace.test(string.charAt(index))) {
}
return index;
}
var trimmedEndIndex_default = trimmedEndIndex;
// ../node_modules/lodash-es/_baseTrim.js
var reTrimStart = /^\s+/;
function baseTrim(string) {
return string ? string.slice(0, trimmedEndIndex_default(string) + 1).replace(reTrimStart, "") : string;
}
var baseTrim_default = baseTrim;
// ../node_modules/lodash-es/_Symbol.js
var Symbol2 = root_default.Symbol;
var Symbol_default = Symbol2;
// ../node_modules/lodash-es/_getRawTag.js
var objectProto = Object.prototype;
var hasOwnProperty = objectProto.hasOwnProperty;
var nativeObjectToString = objectProto.toString;
var symToStringTag = Symbol_default ? Symbol_default.toStringTag : void 0;
function getRawTag(value) {
var isOwn = hasOwnProperty.call(value, symToStringTag), tag = value[symToStringTag];
try {
value[symToStringTag] = void 0;
var unmasked = true;
} catch (e) {
}
var result = nativeObjectToString.call(value);
if (unmasked) {
if (isOwn) {
value[symToStringTag] = tag;
} else {
delete value[symToStringTag];
}
}
return result;
}
var getRawTag_default = getRawTag;
// ../node_modules/lodash-es/_objectToString.js
var objectProto2 = Object.prototype;
var nativeObjectToString2 = objectProto2.toString;
function objectToString(value) {
return nativeObjectToString2.call(value);
}
var objectToString_default = objectToString;
// ../node_modules/lodash-es/_baseGetTag.js
var nullTag = "[object Null]";
var undefinedTag = "[object Undefined]";
var symToStringTag2 = Symbol_default ? Symbol_default.toStringTag : void 0;
function baseGetTag(value) {
if (value == null) {
return value === void 0 ? undefinedTag : nullTag;
}
return symToStringTag2 && symToStringTag2 in Object(value) ? getRawTag_default(value) : objectToString_default(value);
}
var baseGetTag_default = baseGetTag;
// ../node_modules/lodash-es/isObjectLike.js
function isObjectLike(value) {
return value != null && typeof value == "object";
}
var isObjectLike_default = isObjectLike;
// ../node_modules/lodash-es/isSymbol.js
var symbolTag = "[object Symbol]";
function isSymbol(value) {
return typeof value == "symbol" || isObjectLike_default(value) && baseGetTag_default(value) == symbolTag;
}
var isSymbol_default = isSymbol;
// ../node_modules/lodash-es/toNumber.js
var NAN = 0 / 0;
var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
var reIsBinary = /^0b[01]+$/i;
var reIsOctal = /^0o[0-7]+$/i;
var freeParseInt = parseInt;
function toNumber(value) {
if (typeof value == "number") {
return value;
}
if (isSymbol_default(value)) {
return NAN;
}
if (isObject_default(value)) {
var other = typeof value.valueOf == "function" ? value.valueOf() : value;
value = isObject_default(other) ? other + "" : other;
}
if (typeof value != "string") {
return value === 0 ? value : +value;
}
value = baseTrim_default(value);
var isBinary = reIsBinary.test(value);
return isBinary || reIsOctal.test(value) ? freeParseInt(value.slice(2), isBinary ? 2 : 8) : reIsBadHex.test(value) ? NAN : +value;
}
var toNumber_default = toNumber;
// ../node_modules/lodash-es/debounce.js
var FUNC_ERROR_TEXT = "Expected a function";
var nativeMax = Math.max;
var nativeMin = Math.min;
function debounce(func, wait, options) {
var lastArgs, lastThis, maxWait, result, timerId, lastCallTime, lastInvokeTime = 0, leading = false, maxing = false, trailing = true;
if (typeof func != "function") {
throw new TypeError(FUNC_ERROR_TEXT);
}
wait = toNumber_default(wait) || 0;
if (isObject_default(options)) {
leading = !!options.leading;
maxing = "maxWait" in options;
maxWait = maxing ? nativeMax(toNumber_default(options.maxWait) || 0, wait) : maxWait;
trailing = "trailing" in options ? !!options.trailing : trailing;
}
function invokeFunc(time) {
var args = lastArgs, thisArg = lastThis;
lastArgs = lastThis = void 0;
lastInvokeTime = time;
result = func.apply(thisArg, args);
return result;
}
function leadingEdge(time) {
lastInvokeTime = time;
timerId = setTimeout(timerExpired, wait);
return leading ? invokeFunc(time) : result;
}
function remainingWait(time) {
var timeSinceLastCall = time - lastCallTime, timeSinceLastInvoke = time - lastInvokeTime, timeWaiting = wait - timeSinceLastCall;
return maxing ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke) : timeWaiting;
}
function shouldInvoke(time) {
var timeSinceLastCall = time - lastCallTime, timeSinceLastInvoke = time - lastInvokeTime;
return lastCallTime === void 0 || timeSinceLastCall >= wait || timeSinceLastCall < 0 || maxing && timeSinceLastInvoke >= maxWait;
}
function timerExpired() {
var time = now_default();
if (shouldInvoke(time)) {
return trailingEdge(time);
}
timerId = setTimeout(timerExpired, remainingWait(time));
}
function trailingEdge(time) {
timerId = void 0;
if (trailing && lastArgs) {
return invokeFunc(time);
}
lastArgs = lastThis = void 0;
return result;
}
function cancel() {
if (timerId !== void 0) {
clearTimeout(timerId);
}
lastInvokeTime = 0;
lastArgs = lastCallTime = lastThis = timerId = void 0;
}
function flush() {
return timerId === void 0 ? result : trailingEdge(now_default());
}
function debounced() {
var time = now_default(), isInvoking = shouldInvoke(time);
lastArgs = arguments;
lastThis = this;
lastCallTime = time;
if (isInvoking) {
if (timerId === void 0) {
return leadingEdge(lastCallTime);
}
if (maxing) {
clearTimeout(timerId);
timerId = setTimeout(timerExpired, wait);
return invokeFunc(lastCallTime);
}
}
if (timerId === void 0) {
timerId = setTimeout(timerExpired, wait);
}
return result;
}
debounced.cancel = cancel;
debounced.flush = flush;
return debounced;
}
var debounce_default = debounce;
// ../node_modules/lodash-es/throttle.js
var FUNC_ERROR_TEXT2 = "Expected a function";
function throttle(func, wait, options) {
var leading = true, trailing = true;
if (typeof func != "function") {
throw new TypeError(FUNC_ERROR_TEXT2);
}
if (isObject_default(options)) {
leading = "leading" in options ? !!options.leading : leading;
trailing = "trailing" in options ? !!options.trailing : trailing;
}
return debounce_default(func, wait, {
"leading": leading,
"maxWait": wait,
"trailing": trailing
});
}
var throttle_default = throttle;
// src/react/shallow.ts
var isIterable = (obj) => Symbol.iterator in obj;
var hasIterableEntries = (value) => (
// HACK: avoid checking entries type
"entries" in value
);
var compareEntries = (valueA, valueB) => {
const mapA = valueA instanceof Map ? valueA : new Map(valueA.entries());
const mapB = valueB instanceof Map ? valueB : new Map(valueB.entries());
if (mapA.size !== mapB.size) {
return false;
}
for (const [key, value] of mapA) {
if (!Object.is(value, mapB.get(key))) {
return false;
}
}
return true;
};
var compareIterables = (valueA, valueB) => {
const iteratorA = valueA[Symbol.iterator]();
const iteratorB = valueB[Symbol.iterator]();
let nextA = iteratorA.next();
let nextB = iteratorB.next();
while (!nextA.done && !nextB.done) {
if (!Object.is(nextA.value, nextB.value)) {
return false;
}
nextA = iteratorA.next();
nextB = iteratorB.next();
}
return !!nextA.done && !!nextB.done;
};
function shallow(valueA, valueB) {
if (Object.is(valueA, valueB)) {
return true;
}
if (typeof valueA !== "object" || valueA === null || typeof valueB !== "object" || valueB === null) {
return false;
}
if (!isIterable(valueA) || !isIterable(valueB)) {
return compareEntries(
{ entries: () => Object.entries(valueA) },
{ entries: () => Object.entries(valueB) }
);
}
if (hasIterableEntries(valueA) && hasIterableEntries(valueB)) {
return compareEntries(valueA, valueB);
}
return compareIterables(valueA, valueB);
}
// src/react/context.tsx
var CallContext = React.createContext(void 0);
function CallProvider({
call,
fallback,
children
}) {
const callbacks = React.useRef(/* @__PURE__ */ new Set());
const subscribe = React.useCallback((callback) => {
callbacks.current.add(callback);
return () => callbacks.current.delete(callback);
}, []);
React.useEffect(() => {
if (!call) return;
const onCallback = throttle_default(() => {
callbacks.current.forEach((cb) => cb());
}, 180);
const unsubscribeCall = call.subscribeAll(onCallback);
const unsubscribeSelf = call.self.subscribeAll(onCallback);
const unsubscribeChat = call.chat.subscribeAll(onCallback);
return () => {
unsubscribeCall();
unsubscribeSelf();
unsubscribeChat();
};
}, [call]);
return /* @__PURE__ */ React.createElement(CallContext.Provider, { value: { call, subscribe } }, call ? children : fallback);
}
function useCall() {
const ctx = React.useContext(CallContext);
invariant(ctx == null ? void 0 : ctx.call, "useCall must be used within a CallProvider");
return ctx.call;
}
function useCallSelector(selector) {
const ctx = React.useContext(CallContext);
invariant(ctx == null ? void 0 : ctx.call, "useCallSelector must be used within a CallProvider");
const { call, subscribe } = ctx;
const [, forceUpdate] = React.useReducer((x) => x + 1, 0);
const selectorRef = React.useRef(selector);
selectorRef.current = selector;
const slice = selectorRef.current(call);
const sliceRef = React.useRef(slice);
sliceRef.current = slice;
React.useEffect(() => {
const unsubscribe = subscribe(() => {
const nextSlice = selectorRef.current(call);
if (!shallow(sliceRef.current, nextSlice)) {
forceUpdate();
}
});
return unsubscribe;
}, [subscribe, call]);
React.useEffect(() => {
if (slice instanceof EventsHandler) {
const unsubscribe = slice.subscribeAll(() => {
forceUpdate();
});
return unsubscribe;
}
}, [slice]);
return slice;
}
// src/react/index.ts
function useCreateCall() {
const [call, setCall] = useState();
const createCall = useCallback((options) => __async(null, null, function* () {
const call2 = yield createCallClient(options);
setCall(call2);
return call2;
}), []);
return [call, createCall];
}
export { CallProvider, useCall, useCallSelector, useCreateCall };