(function (React$1, designSystem, adminjs, ReactDOM$1, require$$3, require$$4, styledComponents, PropTypes, reactRouter) { 'use strict'; function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; } function _interopNamespace(e) { if (e && e.__esModule) return e; var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n.default = e; return Object.freeze(n); } var React__namespace = /*#__PURE__*/_interopNamespace(React$1); var ReactDOM__namespace = /*#__PURE__*/_interopNamespace(ReactDOM$1); var require$$3__default = /*#__PURE__*/_interopDefault(require$$3); var require$$4__default = /*#__PURE__*/_interopDefault(require$$4); var PropTypes__default = /*#__PURE__*/_interopDefault(PropTypes); var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; function getDefaultExportFromCjs (x) { return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; } function getAugmentedNamespace(n) { if (n.__esModule) return n; var f = n.default; if (typeof f == "function") { var a = function a () { if (this instanceof a) { return Reflect.construct(f, arguments, this.constructor); } return f.apply(this, arguments); }; a.prototype = f.prototype; } else a = {}; Object.defineProperty(a, '__esModule', {value: true}); Object.keys(n).forEach(function (k) { var d = Object.getOwnPropertyDescriptor(n, k); Object.defineProperty(a, k, d.get ? d : { enumerable: true, get: function () { return n[k]; } }); }); return a; } var main$4 = {}; var SupabaseClient$1 = {}; var main$3 = {}; var FunctionsClient$1 = {}; var helper = {}; // ref: https://github.com/tc39/proposal-global var getGlobal = function() { // the only reliable means to get the global object is // `Function('return this')()` // However, this causes CSP violations in Chrome apps. if (typeof self !== 'undefined') { return self; } if (typeof window !== 'undefined') { return window; } if (typeof global !== 'undefined') { return global; } throw new Error('unable to locate global object'); }; var globalObject = getGlobal(); const fetch$4 = globalObject.fetch; var browser$2 = globalObject.fetch.bind(globalObject); const Headers$2 = globalObject.Headers; const Request = globalObject.Request; const Response$1 = globalObject.Response; var browser$3 = /*#__PURE__*/Object.freeze({ __proto__: null, Headers: Headers$2, Request: Request, Response: Response$1, default: browser$2, fetch: fetch$4 }); var require$$1 = /*@__PURE__*/getAugmentedNamespace(browser$3); var __createBinding$2 = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault$2 = (commonjsGlobal && commonjsGlobal.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar$2 = (commonjsGlobal && commonjsGlobal.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding$2(result, mod, k); __setModuleDefault$2(result, mod); return result; }; Object.defineProperty(helper, "__esModule", { value: true }); helper.resolveFetch = void 0; const resolveFetch = (customFetch) => { let _fetch; if (customFetch) { _fetch = customFetch; } else if (typeof fetch === 'undefined') { _fetch = (...args) => Promise.resolve().then(() => __importStar$2(require$$1)).then(({ default: fetch }) => fetch(...args)); } else { _fetch = fetch; } return (...args) => _fetch(...args); }; helper.resolveFetch = resolveFetch; var types$2 = {}; (function (exports) { Object.defineProperty(exports, "__esModule", { value: true }); exports.FunctionRegion = exports.FunctionsHttpError = exports.FunctionsRelayError = exports.FunctionsFetchError = exports.FunctionsError = void 0; class FunctionsError extends Error { constructor(message, name = 'FunctionsError', context) { super(message); this.name = name; this.context = context; } } exports.FunctionsError = FunctionsError; class FunctionsFetchError extends FunctionsError { constructor(context) { super('Failed to send a request to the Edge Function', 'FunctionsFetchError', context); } } exports.FunctionsFetchError = FunctionsFetchError; class FunctionsRelayError extends FunctionsError { constructor(context) { super('Relay Error invoking the Edge Function', 'FunctionsRelayError', context); } } exports.FunctionsRelayError = FunctionsRelayError; class FunctionsHttpError extends FunctionsError { constructor(context) { super('Edge Function returned a non-2xx status code', 'FunctionsHttpError', context); } } exports.FunctionsHttpError = FunctionsHttpError; (function (FunctionRegion) { FunctionRegion["Any"] = "any"; FunctionRegion["ApNortheast1"] = "ap-northeast-1"; FunctionRegion["ApNortheast2"] = "ap-northeast-2"; FunctionRegion["ApSouth1"] = "ap-south-1"; FunctionRegion["ApSoutheast1"] = "ap-southeast-1"; FunctionRegion["ApSoutheast2"] = "ap-southeast-2"; FunctionRegion["CaCentral1"] = "ca-central-1"; FunctionRegion["EuCentral1"] = "eu-central-1"; FunctionRegion["EuWest1"] = "eu-west-1"; FunctionRegion["EuWest2"] = "eu-west-2"; FunctionRegion["EuWest3"] = "eu-west-3"; FunctionRegion["SaEast1"] = "sa-east-1"; FunctionRegion["UsEast1"] = "us-east-1"; FunctionRegion["UsWest1"] = "us-west-1"; FunctionRegion["UsWest2"] = "us-west-2"; })(exports.FunctionRegion || (exports.FunctionRegion = {})); } (types$2)); var __awaiter$7 = (commonjsGlobal && commonjsGlobal.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(FunctionsClient$1, "__esModule", { value: true }); FunctionsClient$1.FunctionsClient = void 0; const helper_1 = helper; const types_1 = types$2; class FunctionsClient { constructor(url, { headers = {}, customFetch, region = types_1.FunctionRegion.Any, } = {}) { this.url = url; this.headers = headers; this.region = region; this.fetch = (0, helper_1.resolveFetch)(customFetch); } /** * Updates the authorization header * @param token - the new jwt token sent in the authorisation header */ setAuth(token) { this.headers.Authorization = `Bearer ${token}`; } /** * Invokes a function * @param functionName - The name of the Function to invoke. * @param options - Options for invoking the Function. */ invoke(functionName, options = {}) { var _a; return __awaiter$7(this, void 0, void 0, function* () { try { const { headers, method, body: functionArgs } = options; let _headers = {}; let { region } = options; if (!region) { region = this.region; } if (region && region !== 'any') { _headers['x-region'] = region; } let body; if (functionArgs && ((headers && !Object.prototype.hasOwnProperty.call(headers, 'Content-Type')) || !headers)) { if ((typeof Blob !== 'undefined' && functionArgs instanceof Blob) || functionArgs instanceof ArrayBuffer) { // will work for File as File inherits Blob // also works for ArrayBuffer as it is the same underlying structure as a Blob _headers['Content-Type'] = 'application/octet-stream'; body = functionArgs; } else if (typeof functionArgs === 'string') { // plain string _headers['Content-Type'] = 'text/plain'; body = functionArgs; } else if (typeof FormData !== 'undefined' && functionArgs instanceof FormData) { // don't set content-type headers // Request will automatically add the right boundary value body = functionArgs; } else { // default, assume this is JSON _headers['Content-Type'] = 'application/json'; body = JSON.stringify(functionArgs); } } const response = yield this.fetch(`${this.url}/${functionName}`, { method: method || 'POST', // headers priority is (high to low): // 1. invoke-level headers // 2. client-level headers // 3. default Content-Type header headers: Object.assign(Object.assign(Object.assign({}, _headers), this.headers), headers), body, }).catch((fetchError) => { throw new types_1.FunctionsFetchError(fetchError); }); const isRelayError = response.headers.get('x-relay-error'); if (isRelayError && isRelayError === 'true') { throw new types_1.FunctionsRelayError(response); } if (!response.ok) { throw new types_1.FunctionsHttpError(response); } let responseType = ((_a = response.headers.get('Content-Type')) !== null && _a !== void 0 ? _a : 'text/plain').split(';')[0].trim(); let data; if (responseType === 'application/json') { data = yield response.json(); } else if (responseType === 'application/octet-stream') { data = yield response.blob(); } else if (responseType === 'text/event-stream') { data = response; } else if (responseType === 'multipart/form-data') { data = yield response.formData(); } else { // default to text data = yield response.text(); } return { data, error: null }; } catch (error) { return { data: null, error }; } }); } } FunctionsClient$1.FunctionsClient = FunctionsClient; (function (exports) { Object.defineProperty(exports, "__esModule", { value: true }); exports.FunctionRegion = exports.FunctionsRelayError = exports.FunctionsHttpError = exports.FunctionsFetchError = exports.FunctionsError = exports.FunctionsClient = void 0; var FunctionsClient_1 = FunctionsClient$1; Object.defineProperty(exports, "FunctionsClient", { enumerable: true, get: function () { return FunctionsClient_1.FunctionsClient; } }); var types_1 = types$2; Object.defineProperty(exports, "FunctionsError", { enumerable: true, get: function () { return types_1.FunctionsError; } }); Object.defineProperty(exports, "FunctionsFetchError", { enumerable: true, get: function () { return types_1.FunctionsFetchError; } }); Object.defineProperty(exports, "FunctionsHttpError", { enumerable: true, get: function () { return types_1.FunctionsHttpError; } }); Object.defineProperty(exports, "FunctionsRelayError", { enumerable: true, get: function () { return types_1.FunctionsRelayError; } }); Object.defineProperty(exports, "FunctionRegion", { enumerable: true, get: function () { return types_1.FunctionRegion; } }); } (main$3)); var cjs = {}; var PostgrestClient$1 = {}; var PostgrestQueryBuilder$1 = {}; var PostgrestFilterBuilder$1 = {}; var PostgrestTransformBuilder$1 = {}; var PostgrestBuilder$1 = {}; var PostgrestError$1 = {}; Object.defineProperty(PostgrestError$1, "__esModule", { value: true }); /** * Error format * * {@link https://postgrest.org/en/stable/api.html?highlight=options#errors-and-http-status-codes} */ class PostgrestError extends Error { constructor(context) { super(context.message); this.name = 'PostgrestError'; this.details = context.details; this.hint = context.hint; this.code = context.code; } } PostgrestError$1.default = PostgrestError; var __importDefault$b = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(PostgrestBuilder$1, "__esModule", { value: true }); // @ts-ignore const node_fetch_1 = __importDefault$b(require$$1); const PostgrestError_1$1 = __importDefault$b(PostgrestError$1); class PostgrestBuilder { constructor(builder) { this.shouldThrowOnError = false; this.method = builder.method; this.url = builder.url; this.headers = builder.headers; this.schema = builder.schema; this.body = builder.body; this.shouldThrowOnError = builder.shouldThrowOnError; this.signal = builder.signal; this.isMaybeSingle = builder.isMaybeSingle; if (builder.fetch) { this.fetch = builder.fetch; } else if (typeof fetch === 'undefined') { this.fetch = node_fetch_1.default; } else { this.fetch = fetch; } } /** * If there's an error with the query, throwOnError will reject the promise by * throwing the error instead of returning it as part of a successful response. * * {@link https://github.com/supabase/supabase-js/issues/92} */ throwOnError() { this.shouldThrowOnError = true; return this; } /** * Set an HTTP header for the request. */ setHeader(name, value) { this.headers = Object.assign({}, this.headers); this.headers[name] = value; return this; } then(onfulfilled, onrejected) { // https://postgrest.org/en/stable/api.html#switching-schemas if (this.schema === undefined) ; else if (['GET', 'HEAD'].includes(this.method)) { this.headers['Accept-Profile'] = this.schema; } else { this.headers['Content-Profile'] = this.schema; } if (this.method !== 'GET' && this.method !== 'HEAD') { this.headers['Content-Type'] = 'application/json'; } // NOTE: Invoke w/o `this` to avoid illegal invocation error. // https://github.com/supabase/postgrest-js/pull/247 const _fetch = this.fetch; let res = _fetch(this.url.toString(), { method: this.method, headers: this.headers, body: JSON.stringify(this.body), signal: this.signal, }).then(async (res) => { var _a, _b, _c; let error = null; let data = null; let count = null; let status = res.status; let statusText = res.statusText; if (res.ok) { if (this.method !== 'HEAD') { const body = await res.text(); if (body === '') ; else if (this.headers['Accept'] === 'text/csv') { data = body; } else if (this.headers['Accept'] && this.headers['Accept'].includes('application/vnd.pgrst.plan+text')) { data = body; } else { data = JSON.parse(body); } } const countHeader = (_a = this.headers['Prefer']) === null || _a === void 0 ? void 0 : _a.match(/count=(exact|planned|estimated)/); const contentRange = (_b = res.headers.get('content-range')) === null || _b === void 0 ? void 0 : _b.split('/'); if (countHeader && contentRange && contentRange.length > 1) { count = parseInt(contentRange[1]); } // Temporary partial fix for https://github.com/supabase/postgrest-js/issues/361 // Issue persists e.g. for `.insert([...]).select().maybeSingle()` if (this.isMaybeSingle && this.method === 'GET' && Array.isArray(data)) { if (data.length > 1) { error = { // https://github.com/PostgREST/postgrest/blob/a867d79c42419af16c18c3fb019eba8df992626f/src/PostgREST/Error.hs#L553 code: 'PGRST116', details: `Results contain ${data.length} rows, application/vnd.pgrst.object+json requires 1 row`, hint: null, message: 'JSON object requested, multiple (or no) rows returned', }; data = null; count = null; status = 406; statusText = 'Not Acceptable'; } else if (data.length === 1) { data = data[0]; } else { data = null; } } } else { const body = await res.text(); try { error = JSON.parse(body); // Workaround for https://github.com/supabase/postgrest-js/issues/295 if (Array.isArray(error) && res.status === 404) { data = []; error = null; status = 200; statusText = 'OK'; } } catch (_d) { // Workaround for https://github.com/supabase/postgrest-js/issues/295 if (res.status === 404 && body === '') { status = 204; statusText = 'No Content'; } else { error = { message: body, }; } } if (error && this.isMaybeSingle && ((_c = error === null || error === void 0 ? void 0 : error.details) === null || _c === void 0 ? void 0 : _c.includes('0 rows'))) { error = null; status = 200; statusText = 'OK'; } if (error && this.shouldThrowOnError) { throw new PostgrestError_1$1.default(error); } } const postgrestResponse = { error, data, count, status, statusText, }; return postgrestResponse; }); if (!this.shouldThrowOnError) { res = res.catch((fetchError) => { var _a, _b, _c; return ({ error: { message: `${(_a = fetchError === null || fetchError === void 0 ? void 0 : fetchError.name) !== null && _a !== void 0 ? _a : 'FetchError'}: ${fetchError === null || fetchError === void 0 ? void 0 : fetchError.message}`, details: `${(_b = fetchError === null || fetchError === void 0 ? void 0 : fetchError.stack) !== null && _b !== void 0 ? _b : ''}`, hint: '', code: `${(_c = fetchError === null || fetchError === void 0 ? void 0 : fetchError.code) !== null && _c !== void 0 ? _c : ''}`, }, data: null, count: null, status: 0, statusText: '', }); }); } return res.then(onfulfilled, onrejected); } /** * Override the type of the returned `data`. * * @typeParam NewResult - The new result type to override with * @deprecated Use overrideTypes() method at the end of your call chain instead */ returns() { /* istanbul ignore next */ return this; } /** * Override the type of the returned `data` field in the response. * * @typeParam NewResult - The new type to cast the response data to * @typeParam Options - Optional type configuration (defaults to { merge: true }) * @typeParam Options.merge - When true, merges the new type with existing return type. When false, replaces the existing types entirely (defaults to true) * @example * ```typescript * // Merge with existing types (default behavior) * const query = supabase * .from('users') * .select() * .overrideTypes<{ custom_field: string }>() * * // Replace existing types completely * const replaceQuery = supabase * .from('users') * .select() * .overrideTypes<{ id: number; name: string }, { merge: false }>() * ``` * @returns A PostgrestBuilder instance with the new type */ overrideTypes() { return this; } } PostgrestBuilder$1.default = PostgrestBuilder; var __importDefault$a = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(PostgrestTransformBuilder$1, "__esModule", { value: true }); const PostgrestBuilder_1$1 = __importDefault$a(PostgrestBuilder$1); class PostgrestTransformBuilder extends PostgrestBuilder_1$1.default { /** * Perform a SELECT on the query result. * * By default, `.insert()`, `.update()`, `.upsert()`, and `.delete()` do not * return modified rows. By calling this method, modified rows are returned in * `data`. * * @param columns - The columns to retrieve, separated by commas */ select(columns) { // Remove whitespaces except when quoted let quoted = false; const cleanedColumns = (columns !== null && columns !== void 0 ? columns : '*') .split('') .map((c) => { if (/\s/.test(c) && !quoted) { return ''; } if (c === '"') { quoted = !quoted; } return c; }) .join(''); this.url.searchParams.set('select', cleanedColumns); if (this.headers['Prefer']) { this.headers['Prefer'] += ','; } this.headers['Prefer'] += 'return=representation'; return this; } /** * Order the query result by `column`. * * You can call this method multiple times to order by multiple columns. * * You can order referenced tables, but it only affects the ordering of the * parent table if you use `!inner` in the query. * * @param column - The column to order by * @param options - Named parameters * @param options.ascending - If `true`, the result will be in ascending order * @param options.nullsFirst - If `true`, `null`s appear first. If `false`, * `null`s appear last. * @param options.referencedTable - Set this to order a referenced table by * its columns * @param options.foreignTable - Deprecated, use `options.referencedTable` * instead */ order(column, { ascending = true, nullsFirst, foreignTable, referencedTable = foreignTable, } = {}) { const key = referencedTable ? `${referencedTable}.order` : 'order'; const existingOrder = this.url.searchParams.get(key); this.url.searchParams.set(key, `${existingOrder ? `${existingOrder},` : ''}${column}.${ascending ? 'asc' : 'desc'}${nullsFirst === undefined ? '' : nullsFirst ? '.nullsfirst' : '.nullslast'}`); return this; } /** * Limit the query result by `count`. * * @param count - The maximum number of rows to return * @param options - Named parameters * @param options.referencedTable - Set this to limit rows of referenced * tables instead of the parent table * @param options.foreignTable - Deprecated, use `options.referencedTable` * instead */ limit(count, { foreignTable, referencedTable = foreignTable, } = {}) { const key = typeof referencedTable === 'undefined' ? 'limit' : `${referencedTable}.limit`; this.url.searchParams.set(key, `${count}`); return this; } /** * Limit the query result by starting at an offset `from` and ending at the offset `to`. * Only records within this range are returned. * This respects the query order and if there is no order clause the range could behave unexpectedly. * The `from` and `to` values are 0-based and inclusive: `range(1, 3)` will include the second, third * and fourth rows of the query. * * @param from - The starting index from which to limit the result * @param to - The last index to which to limit the result * @param options - Named parameters * @param options.referencedTable - Set this to limit rows of referenced * tables instead of the parent table * @param options.foreignTable - Deprecated, use `options.referencedTable` * instead */ range(from, to, { foreignTable, referencedTable = foreignTable, } = {}) { const keyOffset = typeof referencedTable === 'undefined' ? 'offset' : `${referencedTable}.offset`; const keyLimit = typeof referencedTable === 'undefined' ? 'limit' : `${referencedTable}.limit`; this.url.searchParams.set(keyOffset, `${from}`); // Range is inclusive, so add 1 this.url.searchParams.set(keyLimit, `${to - from + 1}`); return this; } /** * Set the AbortSignal for the fetch request. * * @param signal - The AbortSignal to use for the fetch request */ abortSignal(signal) { this.signal = signal; return this; } /** * Return `data` as a single object instead of an array of objects. * * Query result must be one row (e.g. using `.limit(1)`), otherwise this * returns an error. */ single() { this.headers['Accept'] = 'application/vnd.pgrst.object+json'; return this; } /** * Return `data` as a single object instead of an array of objects. * * Query result must be zero or one row (e.g. using `.limit(1)`), otherwise * this returns an error. */ maybeSingle() { // Temporary partial fix for https://github.com/supabase/postgrest-js/issues/361 // Issue persists e.g. for `.insert([...]).select().maybeSingle()` if (this.method === 'GET') { this.headers['Accept'] = 'application/json'; } else { this.headers['Accept'] = 'application/vnd.pgrst.object+json'; } this.isMaybeSingle = true; return this; } /** * Return `data` as a string in CSV format. */ csv() { this.headers['Accept'] = 'text/csv'; return this; } /** * Return `data` as an object in [GeoJSON](https://geojson.org) format. */ geojson() { this.headers['Accept'] = 'application/geo+json'; return this; } /** * Return `data` as the EXPLAIN plan for the query. * * You need to enable the * [db_plan_enabled](https://supabase.com/docs/guides/database/debugging-performance#enabling-explain) * setting before using this method. * * @param options - Named parameters * * @param options.analyze - If `true`, the query will be executed and the * actual run time will be returned * * @param options.verbose - If `true`, the query identifier will be returned * and `data` will include the output columns of the query * * @param options.settings - If `true`, include information on configuration * parameters that affect query planning * * @param options.buffers - If `true`, include information on buffer usage * * @param options.wal - If `true`, include information on WAL record generation * * @param options.format - The format of the output, can be `"text"` (default) * or `"json"` */ explain({ analyze = false, verbose = false, settings = false, buffers = false, wal = false, format = 'text', } = {}) { var _a; const options = [ analyze ? 'analyze' : null, verbose ? 'verbose' : null, settings ? 'settings' : null, buffers ? 'buffers' : null, wal ? 'wal' : null, ] .filter(Boolean) .join('|'); // An Accept header can carry multiple media types but postgrest-js always sends one const forMediatype = (_a = this.headers['Accept']) !== null && _a !== void 0 ? _a : 'application/json'; this.headers['Accept'] = `application/vnd.pgrst.plan+${format}; for="${forMediatype}"; options=${options};`; if (format === 'json') return this; else return this; } /** * Rollback the query. * * `data` will still be returned, but the query is not committed. */ rollback() { var _a; if (((_a = this.headers['Prefer']) !== null && _a !== void 0 ? _a : '').trim().length > 0) { this.headers['Prefer'] += ',tx=rollback'; } else { this.headers['Prefer'] = 'tx=rollback'; } return this; } /** * Override the type of the returned `data`. * * @typeParam NewResult - The new result type to override with * @deprecated Use overrideTypes() method at the end of your call chain instead */ returns() { return this; } } PostgrestTransformBuilder$1.default = PostgrestTransformBuilder; var __importDefault$9 = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(PostgrestFilterBuilder$1, "__esModule", { value: true }); const PostgrestTransformBuilder_1$1 = __importDefault$9(PostgrestTransformBuilder$1); class PostgrestFilterBuilder extends PostgrestTransformBuilder_1$1.default { /** * Match only rows where `column` is equal to `value`. * * To check if the value of `column` is NULL, you should use `.is()` instead. * * @param column - The column to filter on * @param value - The value to filter with */ eq(column, value) { this.url.searchParams.append(column, `eq.${value}`); return this; } /** * Match only rows where `column` is not equal to `value`. * * @param column - The column to filter on * @param value - The value to filter with */ neq(column, value) { this.url.searchParams.append(column, `neq.${value}`); return this; } /** * Match only rows where `column` is greater than `value`. * * @param column - The column to filter on * @param value - The value to filter with */ gt(column, value) { this.url.searchParams.append(column, `gt.${value}`); return this; } /** * Match only rows where `column` is greater than or equal to `value`. * * @param column - The column to filter on * @param value - The value to filter with */ gte(column, value) { this.url.searchParams.append(column, `gte.${value}`); return this; } /** * Match only rows where `column` is less than `value`. * * @param column - The column to filter on * @param value - The value to filter with */ lt(column, value) { this.url.searchParams.append(column, `lt.${value}`); return this; } /** * Match only rows where `column` is less than or equal to `value`. * * @param column - The column to filter on * @param value - The value to filter with */ lte(column, value) { this.url.searchParams.append(column, `lte.${value}`); return this; } /** * Match only rows where `column` matches `pattern` case-sensitively. * * @param column - The column to filter on * @param pattern - The pattern to match with */ like(column, pattern) { this.url.searchParams.append(column, `like.${pattern}`); return this; } /** * Match only rows where `column` matches all of `patterns` case-sensitively. * * @param column - The column to filter on * @param patterns - The patterns to match with */ likeAllOf(column, patterns) { this.url.searchParams.append(column, `like(all).{${patterns.join(',')}}`); return this; } /** * Match only rows where `column` matches any of `patterns` case-sensitively. * * @param column - The column to filter on * @param patterns - The patterns to match with */ likeAnyOf(column, patterns) { this.url.searchParams.append(column, `like(any).{${patterns.join(',')}}`); return this; } /** * Match only rows where `column` matches `pattern` case-insensitively. * * @param column - The column to filter on * @param pattern - The pattern to match with */ ilike(column, pattern) { this.url.searchParams.append(column, `ilike.${pattern}`); return this; } /** * Match only rows where `column` matches all of `patterns` case-insensitively. * * @param column - The column to filter on * @param patterns - The patterns to match with */ ilikeAllOf(column, patterns) { this.url.searchParams.append(column, `ilike(all).{${patterns.join(',')}}`); return this; } /** * Match only rows where `column` matches any of `patterns` case-insensitively. * * @param column - The column to filter on * @param patterns - The patterns to match with */ ilikeAnyOf(column, patterns) { this.url.searchParams.append(column, `ilike(any).{${patterns.join(',')}}`); return this; } /** * Match only rows where `column` IS `value`. * * For non-boolean columns, this is only relevant for checking if the value of * `column` is NULL by setting `value` to `null`. * * For boolean columns, you can also set `value` to `true` or `false` and it * will behave the same way as `.eq()`. * * @param column - The column to filter on * @param value - The value to filter with */ is(column, value) { this.url.searchParams.append(column, `is.${value}`); return this; } /** * Match only rows where `column` is included in the `values` array. * * @param column - The column to filter on * @param values - The values array to filter with */ in(column, values) { const cleanedValues = Array.from(new Set(values)) .map((s) => { // handle postgrest reserved characters // https://postgrest.org/en/v7.0.0/api.html#reserved-characters if (typeof s === 'string' && new RegExp('[,()]').test(s)) return `"${s}"`; else return `${s}`; }) .join(','); this.url.searchParams.append(column, `in.(${cleanedValues})`); return this; } /** * Only relevant for jsonb, array, and range columns. Match only rows where * `column` contains every element appearing in `value`. * * @param column - The jsonb, array, or range column to filter on * @param value - The jsonb, array, or range value to filter with */ contains(column, value) { if (typeof value === 'string') { // range types can be inclusive '[', ']' or exclusive '(', ')' so just // keep it simple and accept a string this.url.searchParams.append(column, `cs.${value}`); } else if (Array.isArray(value)) { // array this.url.searchParams.append(column, `cs.{${value.join(',')}}`); } else { // json this.url.searchParams.append(column, `cs.${JSON.stringify(value)}`); } return this; } /** * Only relevant for jsonb, array, and range columns. Match only rows where * every element appearing in `column` is contained by `value`. * * @param column - The jsonb, array, or range column to filter on * @param value - The jsonb, array, or range value to filter with */ containedBy(column, value) { if (typeof value === 'string') { // range this.url.searchParams.append(column, `cd.${value}`); } else if (Array.isArray(value)) { // array this.url.searchParams.append(column, `cd.{${value.join(',')}}`); } else { // json this.url.searchParams.append(column, `cd.${JSON.stringify(value)}`); } return this; } /** * Only relevant for range columns. Match only rows where every element in * `column` is greater than any element in `range`. * * @param column - The range column to filter on * @param range - The range to filter with */ rangeGt(column, range) { this.url.searchParams.append(column, `sr.${range}`); return this; } /** * Only relevant for range columns. Match only rows where every element in * `column` is either contained in `range` or greater than any element in * `range`. * * @param column - The range column to filter on * @param range - The range to filter with */ rangeGte(column, range) { this.url.searchParams.append(column, `nxl.${range}`); return this; } /** * Only relevant for range columns. Match only rows where every element in * `column` is less than any element in `range`. * * @param column - The range column to filter on * @param range - The range to filter with */ rangeLt(column, range) { this.url.searchParams.append(column, `sl.${range}`); return this; } /** * Only relevant for range columns. Match only rows where every element in * `column` is either contained in `range` or less than any element in * `range`. * * @param column - The range column to filter on * @param range - The range to filter with */ rangeLte(column, range) { this.url.searchParams.append(column, `nxr.${range}`); return this; } /** * Only relevant for range columns. Match only rows where `column` is * mutually exclusive to `range` and there can be no element between the two * ranges. * * @param column - The range column to filter on * @param range - The range to filter with */ rangeAdjacent(column, range) { this.url.searchParams.append(column, `adj.${range}`); return this; } /** * Only relevant for array and range columns. Match only rows where * `column` and `value` have an element in common. * * @param column - The array or range column to filter on * @param value - The array or range value to filter with */ overlaps(column, value) { if (typeof value === 'string') { // range this.url.searchParams.append(column, `ov.${value}`); } else { // array this.url.searchParams.append(column, `ov.{${value.join(',')}}`); } return this; } /** * Only relevant for text and tsvector columns. Match only rows where * `column` matches the query string in `query`. * * @param column - The text or tsvector column to filter on * @param query - The query text to match with * @param options - Named parameters * @param options.config - The text search configuration to use * @param options.type - Change how the `query` text is interpreted */ textSearch(column, query, { config, type } = {}) { let typePart = ''; if (type === 'plain') { typePart = 'pl'; } else if (type === 'phrase') { typePart = 'ph'; } else if (type === 'websearch') { typePart = 'w'; } const configPart = config === undefined ? '' : `(${config})`; this.url.searchParams.append(column, `${typePart}fts${configPart}.${query}`); return this; } /** * Match only rows where each column in `query` keys is equal to its * associated value. Shorthand for multiple `.eq()`s. * * @param query - The object to filter with, with column names as keys mapped * to their filter values */ match(query) { Object.entries(query).forEach(([column, value]) => { this.url.searchParams.append(column, `eq.${value}`); }); return this; } /** * Match only rows which doesn't satisfy the filter. * * Unlike most filters, `opearator` and `value` are used as-is and need to * follow [PostgREST * syntax](https://postgrest.org/en/stable/api.html#operators). You also need * to make sure they are properly sanitized. * * @param column - The column to filter on * @param operator - The operator to be negated to filter with, following * PostgREST syntax * @param value - The value to filter with, following PostgREST syntax */ not(column, operator, value) { this.url.searchParams.append(column, `not.${operator}.${value}`); return this; } /** * Match only rows which satisfy at least one of the filters. * * Unlike most filters, `filters` is used as-is and needs to follow [PostgREST * syntax](https://postgrest.org/en/stable/api.html#operators). You also need * to make sure it's properly sanitized. * * It's currently not possible to do an `.or()` filter across multiple tables. * * @param filters - The filters to use, following PostgREST syntax * @param options - Named parameters * @param options.referencedTable - Set this to filter on referenced tables * instead of the parent table * @param options.foreignTable - Deprecated, use `referencedTable` instead */ or(filters, { foreignTable, referencedTable = foreignTable, } = {}) { const key = referencedTable ? `${referencedTable}.or` : 'or'; this.url.searchParams.append(key, `(${filters})`); return this; } /** * Match only rows which satisfy the filter. This is an escape hatch - you * should use the specific filter methods wherever possible. * * Unlike most filters, `opearator` and `value` are used as-is and need to * follow [PostgREST * syntax](https://postgrest.org/en/stable/api.html#operators). You also need * to make sure they are properly sanitized. * * @param column - The column to filter on * @param operator - The operator to filter with, following PostgREST syntax * @param value - The value to filter with, following PostgREST syntax */ filter(column, operator, value) { this.url.searchParams.append(column, `${operator}.${value}`); return this; } } PostgrestFilterBuilder$1.default = PostgrestFilterBuilder; var __importDefault$8 = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(PostgrestQueryBuilder$1, "__esModule", { value: true }); const PostgrestFilterBuilder_1$2 = __importDefault$8(PostgrestFilterBuilder$1); class PostgrestQueryBuilder { constructor(url, { headers = {}, schema, fetch, }) { this.url = url; this.headers = headers; this.schema = schema; this.fetch = fetch; } /** * Perform a SELECT query on the table or view. * * @param columns - The columns to retrieve, separated by commas. Columns can be renamed when returned with `customName:columnName` * * @param options - Named parameters * * @param options.head - When set to `true`, `data` will not be returned. * Useful if you only need the count. * * @param options.count - Count algorithm to use to count rows in the table or view. * * `"exact"`: Exact but slow count algorithm. Performs a `COUNT(*)` under the * hood. * * `"planned"`: Approximated but fast count algorithm. Uses the Postgres * statistics under the hood. * * `"estimated"`: Uses exact count for low numbers and planned count for high * numbers. */ select(columns, { head = false, count, } = {}) { const method = head ? 'HEAD' : 'GET'; // Remove whitespaces except when quoted let quoted = false; const cleanedColumns = (columns !== null && columns !== void 0 ? columns : '*') .split('') .map((c) => { if (/\s/.test(c) && !quoted) { return ''; } if (c === '"') { quoted = !quoted; } return c; }) .join(''); this.url.searchParams.set('select', cleanedColumns); if (count) { this.headers['Prefer'] = `count=${count}`; } return new PostgrestFilterBuilder_1$2.default({ method, url: this.url, headers: this.headers, schema: this.schema, fetch: this.fetch, allowEmpty: false, }); } /** * Perform an INSERT into the table or view. * * By default, inserted rows are not returned. To return it, chain the call * with `.select()`. * * @param values - The values to insert. Pass an object to insert a single row * or an array to insert multiple rows. * * @param options - Named parameters * * @param options.count - Count algorithm to use to count inserted rows. * * `"exact"`: Exact but slow count algorithm. Performs a `COUNT(*)` under the * hood. * * `"planned"`: Approximated but fast count algorithm. Uses the Postgres * statistics under the hood. * * `"estimated"`: Uses exact count for low numbers and planned count for high * numbers. * * @param options.defaultToNull - Make missing fields default to `null`. * Otherwise, use the default value for the column. Only applies for bulk * inserts. */ insert(values, { count, defaultToNull = true, } = {}) { const method = 'POST'; const prefersHeaders = []; if (this.headers['Prefer']) { prefersHeaders.push(this.headers['Prefer']); } if (count) { prefersHeaders.push(`count=${count}`); } if (!defaultToNull) { prefersHeaders.push('missing=default'); } this.headers['Prefer'] = prefersHeaders.join(','); if (Array.isArray(values)) { const columns = values.reduce((acc, x) => acc.concat(Object.keys(x)), []); if (columns.length > 0) { const uniqueColumns = [...new Set(columns)].map((column) => `"${column}"`); this.url.searchParams.set('columns', uniqueColumns.join(',')); } } return new PostgrestFilterBuilder_1$2.default({ method, url: this.url, headers: this.headers, schema: this.schema, body: values, fetch: this.fetch, allowEmpty: false, }); } /** * Perform an UPSERT on the table or view. Depending on the column(s) passed * to `onConflict`, `.upsert()` allows you to perform the equivalent of * `.insert()` if a row with the corresponding `onConflict` columns doesn't * exist, or if it does exist, perform an alternative action depending on * `ignoreDuplicates`. * * By default, upserted rows are not returned. To return it, chain the call * with `.select()`. * * @param values - The values to upsert with. Pass an object to upsert a * single row or an array to upsert multiple rows. * * @param options - Named parameters * * @param options.onConflict - Comma-separated UNIQUE column(s) to specify how * duplicate rows are determined. Two rows are duplicates if all the * `onConflict` columns are equal. * * @param options.ignoreDuplicates - If `true`, duplicate rows are ignored. If * `false`, duplicate rows are merged with existing rows. * * @param options.count - Count algorithm to use to count upserted rows. * * `"exact"`: Exact but slow count algorithm. Performs a `COUNT(*)` under the * hood. * * `"planned"`: Approximated but fast count algorithm. Uses the Postgres * statistics under the hood. * * `"estimated"`: Uses exact count for low numbers and planned count for high * numbers. * * @param options.defaultToNull - Make missing fields default to `null`. * Otherwise, use the default value for the column. This only applies when * inserting new rows, not when merging with existing rows under * `ignoreDuplicates: false`. This also only applies when doing bulk upserts. */ upsert(values, { onConflict, ignoreDuplicates = false, count, defaultToNull = true, } = {}) { const method = 'POST'; const prefersHeaders = [`resolution=${ignoreDuplicates ? 'ignore' : 'merge'}-duplicates`]; if (onConflict !== undefined) this.url.searchParams.set('on_conflict', onConflict); if (this.headers['Prefer']) { prefersHeaders.push(this.headers['Prefer']); } if (count) { prefersHeaders.push(`count=${count}`); } if (!defaultToNull) { prefersHeaders.push('missing=default'); } this.headers['Prefer'] = prefersHeaders.join(','); if (Array.isArray(values)) { const columns = values.reduce((acc, x) => acc.concat(Object.keys(x)), []); if (columns.length > 0) { const uniqueColumns = [...new Set(columns)].map((column) => `"${column}"`); this.url.searchParams.set('columns', uniqueColumns.join(',')); } } return new PostgrestFilterBuilder_1$2.default({ method, url: this.url, headers: this.headers, schema: this.schema, body: values, fetch: this.fetch, allowEmpty: false, }); } /** * Perform an UPDATE on the table or view. * * By default, updated rows are not returned. To return it, chain the call * with `.select()` after filters. * * @param values - The values to update with * * @param options - Named parameters * * @param options.count - Count algorithm to use to count updated rows. * * `"exact"`: Exact but slow count algorithm. Performs a `COUNT(*)` under the * hood. * * `"planned"`: Approximated but fast count algorithm. Uses the Postgres * statistics under the hood. * * `"estimated"`: Uses exact count for low numbers and planned count for high * numbers. */ update(values, { count, } = {}) { const method = 'PATCH'; const prefersHeaders = []; if (this.headers['Prefer']) { prefersHeaders.push(this.headers['Prefer']); } if (count) { prefersHeaders.push(`count=${count}`); } this.headers['Prefer'] = prefersHeaders.join(','); return new PostgrestFilterBuilder_1$2.default({ method, url: this.url, headers: this.headers, schema: this.schema, body: values, fetch: this.fetch, allowEmpty: false, }); } /** * Perform a DELETE on the table or view. * * By default, deleted rows are not returned. To return it, chain the call * with `.select()` after filters. * * @param options - Named parameters * * @param options.count - Count algorithm to use to count deleted rows. * * `"exact"`: Exact but slow count algorithm. Performs a `COUNT(*)` under the * hood. * * `"planned"`: Approximated but fast count algorithm. Uses the Postgres * statistics under the hood. * * `"estimated"`: Uses exact count for low numbers and planned count for high * numbers. */ delete({ count, } = {}) { const method = 'DELETE'; const prefersHeaders = []; if (count) { prefersHeaders.push(`count=${count}`); } if (this.headers['Prefer']) { prefersHeaders.unshift(this.headers['Prefer']); } this.headers['Prefer'] = prefersHeaders.join(','); return new PostgrestFilterBuilder_1$2.default({ method, url: this.url, headers: this.headers, schema: this.schema, fetch: this.fetch, allowEmpty: false, }); } } PostgrestQueryBuilder$1.default = PostgrestQueryBuilder; var constants$5 = {}; var version$4 = {}; Object.defineProperty(version$4, "__esModule", { value: true }); version$4.version = void 0; version$4.version = '0.0.0-automated'; Object.defineProperty(constants$5, "__esModule", { value: true }); constants$5.DEFAULT_HEADERS = void 0; const version_1$2 = version$4; constants$5.DEFAULT_HEADERS = { 'X-Client-Info': `postgrest-js/${version_1$2.version}` }; var __importDefault$7 = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(PostgrestClient$1, "__esModule", { value: true }); const PostgrestQueryBuilder_1$1 = __importDefault$7(PostgrestQueryBuilder$1); const PostgrestFilterBuilder_1$1 = __importDefault$7(PostgrestFilterBuilder$1); const constants_1$6 = constants$5; /** * PostgREST client. * * @typeParam Database - Types for the schema from the [type * generator](https://supabase.com/docs/reference/javascript/next/typescript-support) * * @typeParam SchemaName - Postgres schema to switch to. Must be a string * literal, the same one passed to the constructor. If the schema is not * `"public"`, this must be supplied manually. */ class PostgrestClient { // TODO: Add back shouldThrowOnError once we figure out the typings /** * Creates a PostgREST client. * * @param url - URL of the PostgREST endpoint * @param options - Named parameters * @param options.headers - Custom headers * @param options.schema - Postgres schema to switch to * @param options.fetch - Custom fetch */ constructor(url, { headers = {}, schema, fetch, } = {}) { this.url = url; this.headers = Object.assign(Object.assign({}, constants_1$6.DEFAULT_HEADERS), headers); this.schemaName = schema; this.fetch = fetch; } /** * Perform a query on a table or a view. * * @param relation - The table or view name to query */ from(relation) { const url = new URL(`${this.url}/${relation}`); return new PostgrestQueryBuilder_1$1.default(url, { headers: Object.assign({}, this.headers), schema: this.schemaName, fetch: this.fetch, }); } /** * Select a schema to query or perform an function (rpc) call. * * The schema needs to be on the list of exposed schemas inside Supabase. * * @param schema - The schema to query */ schema(schema) { return new PostgrestClient(this.url, { headers: this.headers, schema, fetch: this.fetch, }); } /** * Perform a function call. * * @param fn - The function name to call * @param args - The arguments to pass to the function call * @param options - Named parameters * @param options.head - When set to `true`, `data` will not be returned. * Useful if you only need the count. * @param options.get - When set to `true`, the function will be called with * read-only access mode. * @param options.count - Count algorithm to use to count rows returned by the * function. Only applicable for [set-returning * functions](https://www.postgresql.org/docs/current/functions-srf.html). * * `"exact"`: Exact but slow count algorithm. Performs a `COUNT(*)` under the * hood. * * `"planned"`: Approximated but fast count algorithm. Uses the Postgres * statistics under the hood. * * `"estimated"`: Uses exact count for low numbers and planned count for high * numbers. */ rpc(fn, args = {}, { head = false, get = false, count, } = {}) { let method; const url = new URL(`${this.url}/rpc/${fn}`); let body; if (head || get) { method = head ? 'HEAD' : 'GET'; Object.entries(args) // params with undefined value needs to be filtered out, otherwise it'll // show up as `?param=undefined` .filter(([_, value]) => value !== undefined) // array values need special syntax .map(([name, value]) => [name, Array.isArray(value) ? `{${value.join(',')}}` : `${value}`]) .forEach(([name, value]) => { url.searchParams.append(name, value); }); } else { method = 'POST'; body = args; } const headers = Object.assign({}, this.headers); if (count) { headers['Prefer'] = `count=${count}`; } return new PostgrestFilterBuilder_1$1.default({ method, url, headers, schema: this.schemaName, body, fetch: this.fetch, allowEmpty: false, }); } } PostgrestClient$1.default = PostgrestClient; var __importDefault$6 = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(cjs, "__esModule", { value: true }); cjs.PostgrestError = cjs.PostgrestBuilder = cjs.PostgrestTransformBuilder = cjs.PostgrestFilterBuilder = cjs.PostgrestQueryBuilder = cjs.PostgrestClient = void 0; // Always update wrapper.mjs when updating this file. const PostgrestClient_1 = __importDefault$6(PostgrestClient$1); cjs.PostgrestClient = PostgrestClient_1.default; const PostgrestQueryBuilder_1 = __importDefault$6(PostgrestQueryBuilder$1); cjs.PostgrestQueryBuilder = PostgrestQueryBuilder_1.default; const PostgrestFilterBuilder_1 = __importDefault$6(PostgrestFilterBuilder$1); cjs.PostgrestFilterBuilder = PostgrestFilterBuilder_1.default; const PostgrestTransformBuilder_1 = __importDefault$6(PostgrestTransformBuilder$1); cjs.PostgrestTransformBuilder = PostgrestTransformBuilder_1.default; const PostgrestBuilder_1 = __importDefault$6(PostgrestBuilder$1); cjs.PostgrestBuilder = PostgrestBuilder_1.default; const PostgrestError_1 = __importDefault$6(PostgrestError$1); cjs.PostgrestError = PostgrestError_1.default; cjs.default = { PostgrestClient: PostgrestClient_1.default, PostgrestQueryBuilder: PostgrestQueryBuilder_1.default, PostgrestFilterBuilder: PostgrestFilterBuilder_1.default, PostgrestTransformBuilder: PostgrestTransformBuilder_1.default, PostgrestBuilder: PostgrestBuilder_1.default, PostgrestError: PostgrestError_1.default, }; var main$2 = {}; var RealtimeClient$1 = {}; var constants$4 = {}; var version$3 = {}; Object.defineProperty(version$3, "__esModule", { value: true }); version$3.version = void 0; version$3.version = '2.11.2'; (function (exports) { Object.defineProperty(exports, "__esModule", { value: true }); exports.CONNECTION_STATE = exports.TRANSPORTS = exports.CHANNEL_EVENTS = exports.CHANNEL_STATES = exports.SOCKET_STATES = exports.WS_CLOSE_NORMAL = exports.DEFAULT_TIMEOUT = exports.VSN = exports.DEFAULT_HEADERS = void 0; const version_1 = version$3; exports.DEFAULT_HEADERS = { 'X-Client-Info': `realtime-js/${version_1.version}` }; exports.VSN = '1.0.0'; exports.DEFAULT_TIMEOUT = 10000; exports.WS_CLOSE_NORMAL = 1000; (function (SOCKET_STATES) { SOCKET_STATES[SOCKET_STATES["connecting"] = 0] = "connecting"; SOCKET_STATES[SOCKET_STATES["open"] = 1] = "open"; SOCKET_STATES[SOCKET_STATES["closing"] = 2] = "closing"; SOCKET_STATES[SOCKET_STATES["closed"] = 3] = "closed"; })(exports.SOCKET_STATES || (exports.SOCKET_STATES = {})); (function (CHANNEL_STATES) { CHANNEL_STATES["closed"] = "closed"; CHANNEL_STATES["errored"] = "errored"; CHANNEL_STATES["joined"] = "joined"; CHANNEL_STATES["joining"] = "joining"; CHANNEL_STATES["leaving"] = "leaving"; })(exports.CHANNEL_STATES || (exports.CHANNEL_STATES = {})); (function (CHANNEL_EVENTS) { CHANNEL_EVENTS["close"] = "phx_close"; CHANNEL_EVENTS["error"] = "phx_error"; CHANNEL_EVENTS["join"] = "phx_join"; CHANNEL_EVENTS["reply"] = "phx_reply"; CHANNEL_EVENTS["leave"] = "phx_leave"; CHANNEL_EVENTS["access_token"] = "access_token"; })(exports.CHANNEL_EVENTS || (exports.CHANNEL_EVENTS = {})); (function (TRANSPORTS) { TRANSPORTS["websocket"] = "websocket"; })(exports.TRANSPORTS || (exports.TRANSPORTS = {})); (function (CONNECTION_STATE) { CONNECTION_STATE["Connecting"] = "connecting"; CONNECTION_STATE["Open"] = "open"; CONNECTION_STATE["Closing"] = "closing"; CONNECTION_STATE["Closed"] = "closed"; })(exports.CONNECTION_STATE || (exports.CONNECTION_STATE = {})); } (constants$4)); var serializer = {}; // This file draws heavily from https://github.com/phoenixframework/phoenix/commit/cf098e9cf7a44ee6479d31d911a97d3c7430c6fe // License: https://github.com/phoenixframework/phoenix/blob/master/LICENSE.md Object.defineProperty(serializer, "__esModule", { value: true }); class Serializer { constructor() { this.HEADER_LENGTH = 1; } decode(rawPayload, callback) { if (rawPayload.constructor === ArrayBuffer) { return callback(this._binaryDecode(rawPayload)); } if (typeof rawPayload === 'string') { return callback(JSON.parse(rawPayload)); } return callback({}); } _binaryDecode(buffer) { const view = new DataView(buffer); const decoder = new TextDecoder(); return this._decodeBroadcast(buffer, view, decoder); } _decodeBroadcast(buffer, view, decoder) { const topicSize = view.getUint8(1); const eventSize = view.getUint8(2); let offset = this.HEADER_LENGTH + 2; const topic = decoder.decode(buffer.slice(offset, offset + topicSize)); offset = offset + topicSize; const event = decoder.decode(buffer.slice(offset, offset + eventSize)); offset = offset + eventSize; const data = JSON.parse(decoder.decode(buffer.slice(offset, buffer.byteLength))); return { ref: null, topic: topic, event: event, payload: data }; } } serializer.default = Serializer; var timer = {}; Object.defineProperty(timer, "__esModule", { value: true }); /** * Creates a timer that accepts a `timerCalc` function to perform calculated timeout retries, such as exponential backoff. * * @example * let reconnectTimer = new Timer(() => this.connect(), function(tries){ * return [1000, 5000, 10000][tries - 1] || 10000 * }) * reconnectTimer.scheduleTimeout() // fires after 1000 * reconnectTimer.scheduleTimeout() // fires after 5000 * reconnectTimer.reset() * reconnectTimer.scheduleTimeout() // fires after 1000 */ class Timer { constructor(callback, timerCalc) { this.callback = callback; this.timerCalc = timerCalc; this.timer = undefined; this.tries = 0; this.callback = callback; this.timerCalc = timerCalc; } reset() { this.tries = 0; clearTimeout(this.timer); } // Cancels any previous scheduleTimeout and schedules callback scheduleTimeout() { clearTimeout(this.timer); this.timer = setTimeout(() => { this.tries = this.tries + 1; this.callback(); }, this.timerCalc(this.tries + 1)); } } timer.default = Timer; var transformers = {}; (function (exports) { /** * Helpers to convert the change Payload into native JS types. */ Object.defineProperty(exports, "__esModule", { value: true }); exports.httpEndpointURL = exports.toTimestampString = exports.toArray = exports.toJson = exports.toNumber = exports.toBoolean = exports.convertCell = exports.convertColumn = exports.convertChangeData = exports.PostgresTypes = void 0; // Adapted from epgsql (src/epgsql_binary.erl), this module licensed under // 3-clause BSD found here: https://raw.githubusercontent.com/epgsql/epgsql/devel/LICENSE var PostgresTypes; (function (PostgresTypes) { PostgresTypes["abstime"] = "abstime"; PostgresTypes["bool"] = "bool"; PostgresTypes["date"] = "date"; PostgresTypes["daterange"] = "daterange"; PostgresTypes["float4"] = "float4"; PostgresTypes["float8"] = "float8"; PostgresTypes["int2"] = "int2"; PostgresTypes["int4"] = "int4"; PostgresTypes["int4range"] = "int4range"; PostgresTypes["int8"] = "int8"; PostgresTypes["int8range"] = "int8range"; PostgresTypes["json"] = "json"; PostgresTypes["jsonb"] = "jsonb"; PostgresTypes["money"] = "money"; PostgresTypes["numeric"] = "numeric"; PostgresTypes["oid"] = "oid"; PostgresTypes["reltime"] = "reltime"; PostgresTypes["text"] = "text"; PostgresTypes["time"] = "time"; PostgresTypes["timestamp"] = "timestamp"; PostgresTypes["timestamptz"] = "timestamptz"; PostgresTypes["timetz"] = "timetz"; PostgresTypes["tsrange"] = "tsrange"; PostgresTypes["tstzrange"] = "tstzrange"; })(PostgresTypes = exports.PostgresTypes || (exports.PostgresTypes = {})); /** * Takes an array of columns and an object of string values then converts each string value * to its mapped type. * * @param {{name: String, type: String}[]} columns * @param {Object} record * @param {Object} options The map of various options that can be applied to the mapper * @param {Array} options.skipTypes The array of types that should not be converted * * @example convertChangeData([{name: 'first_name', type: 'text'}, {name: 'age', type: 'int4'}], {first_name: 'Paul', age:'33'}, {}) * //=>{ first_name: 'Paul', age: 33 } */ const convertChangeData = (columns, record, options = {}) => { var _a; const skipTypes = (_a = options.skipTypes) !== null && _a !== void 0 ? _a : []; return Object.keys(record).reduce((acc, rec_key) => { acc[rec_key] = (0, exports.convertColumn)(rec_key, columns, record, skipTypes); return acc; }, {}); }; exports.convertChangeData = convertChangeData; /** * Converts the value of an individual column. * * @param {String} columnName The column that you want to convert * @param {{name: String, type: String}[]} columns All of the columns * @param {Object} record The map of string values * @param {Array} skipTypes An array of types that should not be converted * @return {object} Useless information * * @example convertColumn('age', [{name: 'first_name', type: 'text'}, {name: 'age', type: 'int4'}], {first_name: 'Paul', age: '33'}, []) * //=> 33 * @example convertColumn('age', [{name: 'first_name', type: 'text'}, {name: 'age', type: 'int4'}], {first_name: 'Paul', age: '33'}, ['int4']) * //=> "33" */ const convertColumn = (columnName, columns, record, skipTypes) => { const column = columns.find((x) => x.name === columnName); const colType = column === null || column === void 0 ? void 0 : column.type; const value = record[columnName]; if (colType && !skipTypes.includes(colType)) { return (0, exports.convertCell)(colType, value); } return noop(value); }; exports.convertColumn = convertColumn; /** * If the value of the cell is `null`, returns null. * Otherwise converts the string value to the correct type. * @param {String} type A postgres column type * @param {String} value The cell value * * @example convertCell('bool', 't') * //=> true * @example convertCell('int8', '10') * //=> 10 * @example convertCell('_int4', '{1,2,3,4}') * //=> [1,2,3,4] */ const convertCell = (type, value) => { // if data type is an array if (type.charAt(0) === '_') { const dataType = type.slice(1, type.length); return (0, exports.toArray)(value, dataType); } // If not null, convert to correct type. switch (type) { case PostgresTypes.bool: return (0, exports.toBoolean)(value); case PostgresTypes.float4: case PostgresTypes.float8: case PostgresTypes.int2: case PostgresTypes.int4: case PostgresTypes.int8: case PostgresTypes.numeric: case PostgresTypes.oid: return (0, exports.toNumber)(value); case PostgresTypes.json: case PostgresTypes.jsonb: return (0, exports.toJson)(value); case PostgresTypes.timestamp: return (0, exports.toTimestampString)(value); // Format to be consistent with PostgREST case PostgresTypes.abstime: // To allow users to cast it based on Timezone case PostgresTypes.date: // To allow users to cast it based on Timezone case PostgresTypes.daterange: case PostgresTypes.int4range: case PostgresTypes.int8range: case PostgresTypes.money: case PostgresTypes.reltime: // To allow users to cast it based on Timezone case PostgresTypes.text: case PostgresTypes.time: // To allow users to cast it based on Timezone case PostgresTypes.timestamptz: // To allow users to cast it based on Timezone case PostgresTypes.timetz: // To allow users to cast it based on Timezone case PostgresTypes.tsrange: case PostgresTypes.tstzrange: return noop(value); default: // Return the value for remaining types return noop(value); } }; exports.convertCell = convertCell; const noop = (value) => { return value; }; const toBoolean = (value) => { switch (value) { case 't': return true; case 'f': return false; default: return value; } }; exports.toBoolean = toBoolean; const toNumber = (value) => { if (typeof value === 'string') { const parsedValue = parseFloat(value); if (!Number.isNaN(parsedValue)) { return parsedValue; } } return value; }; exports.toNumber = toNumber; const toJson = (value) => { if (typeof value === 'string') { try { return JSON.parse(value); } catch (error) { console.log(`JSON parse error: ${error}`); return value; } } return value; }; exports.toJson = toJson; /** * Converts a Postgres Array into a native JS array * * @example toArray('{}', 'int4') * //=> [] * @example toArray('{"[2021-01-01,2021-12-31)","(2021-01-01,2021-12-32]"}', 'daterange') * //=> ['[2021-01-01,2021-12-31)', '(2021-01-01,2021-12-32]'] * @example toArray([1,2,3,4], 'int4') * //=> [1,2,3,4] */ const toArray = (value, type) => { if (typeof value !== 'string') { return value; } const lastIdx = value.length - 1; const closeBrace = value[lastIdx]; const openBrace = value[0]; // Confirm value is a Postgres array by checking curly brackets if (openBrace === '{' && closeBrace === '}') { let arr; const valTrim = value.slice(1, lastIdx); // TODO: find a better solution to separate Postgres array data try { arr = JSON.parse('[' + valTrim + ']'); } catch (_) { // WARNING: splitting on comma does not cover all edge cases arr = valTrim ? valTrim.split(',') : []; } return arr.map((val) => (0, exports.convertCell)(type, val)); } return value; }; exports.toArray = toArray; /** * Fixes timestamp to be ISO-8601. Swaps the space between the date and time for a 'T' * See https://github.com/supabase/supabase/issues/18 * * @example toTimestampString('2019-09-10 00:00:00') * //=> '2019-09-10T00:00:00' */ const toTimestampString = (value) => { if (typeof value === 'string') { return value.replace(' ', 'T'); } return value; }; exports.toTimestampString = toTimestampString; const httpEndpointURL = (socketUrl) => { let url = socketUrl; url = url.replace(/^ws/i, 'http'); url = url.replace(/(\/socket\/websocket|\/socket|\/websocket)\/?$/i, ''); return url.replace(/\/+$/, ''); }; exports.httpEndpointURL = httpEndpointURL; } (transformers)); var RealtimeChannel = {}; var push = {}; Object.defineProperty(push, "__esModule", { value: true }); const constants_1$5 = constants$4; class Push { /** * Initializes the Push * * @param channel The Channel * @param event The event, for example `"phx_join"` * @param payload The payload, for example `{user_id: 123}` * @param timeout The push timeout in milliseconds */ constructor(channel, event, payload = {}, timeout = constants_1$5.DEFAULT_TIMEOUT) { this.channel = channel; this.event = event; this.payload = payload; this.timeout = timeout; this.sent = false; this.timeoutTimer = undefined; this.ref = ''; this.receivedResp = null; this.recHooks = []; this.refEvent = null; } resend(timeout) { this.timeout = timeout; this._cancelRefEvent(); this.ref = ''; this.refEvent = null; this.receivedResp = null; this.sent = false; this.send(); } send() { if (this._hasReceived('timeout')) { return; } this.startTimeout(); this.sent = true; this.channel.socket.push({ topic: this.channel.topic, event: this.event, payload: this.payload, ref: this.ref, join_ref: this.channel._joinRef(), }); } updatePayload(payload) { this.payload = Object.assign(Object.assign({}, this.payload), payload); } receive(status, callback) { var _a; if (this._hasReceived(status)) { callback((_a = this.receivedResp) === null || _a === void 0 ? void 0 : _a.response); } this.recHooks.push({ status, callback }); return this; } startTimeout() { if (this.timeoutTimer) { return; } this.ref = this.channel.socket._makeRef(); this.refEvent = this.channel._replyEventName(this.ref); const callback = (payload) => { this._cancelRefEvent(); this._cancelTimeout(); this.receivedResp = payload; this._matchReceive(payload); }; this.channel._on(this.refEvent, {}, callback); this.timeoutTimer = setTimeout(() => { this.trigger('timeout', {}); }, this.timeout); } trigger(status, response) { if (this.refEvent) this.channel._trigger(this.refEvent, { status, response }); } destroy() { this._cancelRefEvent(); this._cancelTimeout(); } _cancelRefEvent() { if (!this.refEvent) { return; } this.channel._off(this.refEvent, {}); } _cancelTimeout() { clearTimeout(this.timeoutTimer); this.timeoutTimer = undefined; } _matchReceive({ status, response, }) { this.recHooks .filter((h) => h.status === status) .forEach((h) => h.callback(response)); } _hasReceived(status) { return this.receivedResp && this.receivedResp.status === status; } } push.default = Push; var RealtimePresence = {}; (function (exports) { /* This file draws heavily from https://github.com/phoenixframework/phoenix/blob/d344ec0a732ab4ee204215b31de69cf4be72e3bf/assets/js/phoenix/presence.js License: https://github.com/phoenixframework/phoenix/blob/d344ec0a732ab4ee204215b31de69cf4be72e3bf/LICENSE.md */ Object.defineProperty(exports, "__esModule", { value: true }); exports.REALTIME_PRESENCE_LISTEN_EVENTS = void 0; (function (REALTIME_PRESENCE_LISTEN_EVENTS) { REALTIME_PRESENCE_LISTEN_EVENTS["SYNC"] = "sync"; REALTIME_PRESENCE_LISTEN_EVENTS["JOIN"] = "join"; REALTIME_PRESENCE_LISTEN_EVENTS["LEAVE"] = "leave"; })(exports.REALTIME_PRESENCE_LISTEN_EVENTS || (exports.REALTIME_PRESENCE_LISTEN_EVENTS = {})); class RealtimePresence { /** * Initializes the Presence. * * @param channel - The RealtimeChannel * @param opts - The options, * for example `{events: {state: 'state', diff: 'diff'}}` */ constructor(channel, opts) { this.channel = channel; this.state = {}; this.pendingDiffs = []; this.joinRef = null; this.caller = { onJoin: () => { }, onLeave: () => { }, onSync: () => { }, }; const events = (opts === null || opts === void 0 ? void 0 : opts.events) || { state: 'presence_state', diff: 'presence_diff', }; this.channel._on(events.state, {}, (newState) => { const { onJoin, onLeave, onSync } = this.caller; this.joinRef = this.channel._joinRef(); this.state = RealtimePresence.syncState(this.state, newState, onJoin, onLeave); this.pendingDiffs.forEach((diff) => { this.state = RealtimePresence.syncDiff(this.state, diff, onJoin, onLeave); }); this.pendingDiffs = []; onSync(); }); this.channel._on(events.diff, {}, (diff) => { const { onJoin, onLeave, onSync } = this.caller; if (this.inPendingSyncState()) { this.pendingDiffs.push(diff); } else { this.state = RealtimePresence.syncDiff(this.state, diff, onJoin, onLeave); onSync(); } }); this.onJoin((key, currentPresences, newPresences) => { this.channel._trigger('presence', { event: 'join', key, currentPresences, newPresences, }); }); this.onLeave((key, currentPresences, leftPresences) => { this.channel._trigger('presence', { event: 'leave', key, currentPresences, leftPresences, }); }); this.onSync(() => { this.channel._trigger('presence', { event: 'sync' }); }); } /** * Used to sync the list of presences on the server with the * client's state. * * An optional `onJoin` and `onLeave` callback can be provided to * react to changes in the client's local presences across * disconnects and reconnects with the server. * * @internal */ static syncState(currentState, newState, onJoin, onLeave) { const state = this.cloneDeep(currentState); const transformedState = this.transformState(newState); const joins = {}; const leaves = {}; this.map(state, (key, presences) => { if (!transformedState[key]) { leaves[key] = presences; } }); this.map(transformedState, (key, newPresences) => { const currentPresences = state[key]; if (currentPresences) { const newPresenceRefs = newPresences.map((m) => m.presence_ref); const curPresenceRefs = currentPresences.map((m) => m.presence_ref); const joinedPresences = newPresences.filter((m) => curPresenceRefs.indexOf(m.presence_ref) < 0); const leftPresences = currentPresences.filter((m) => newPresenceRefs.indexOf(m.presence_ref) < 0); if (joinedPresences.length > 0) { joins[key] = joinedPresences; } if (leftPresences.length > 0) { leaves[key] = leftPresences; } } else { joins[key] = newPresences; } }); return this.syncDiff(state, { joins, leaves }, onJoin, onLeave); } /** * Used to sync a diff of presence join and leave events from the * server, as they happen. * * Like `syncState`, `syncDiff` accepts optional `onJoin` and * `onLeave` callbacks to react to a user joining or leaving from a * device. * * @internal */ static syncDiff(state, diff, onJoin, onLeave) { const { joins, leaves } = { joins: this.transformState(diff.joins), leaves: this.transformState(diff.leaves), }; if (!onJoin) { onJoin = () => { }; } if (!onLeave) { onLeave = () => { }; } this.map(joins, (key, newPresences) => { var _a; const currentPresences = (_a = state[key]) !== null && _a !== void 0 ? _a : []; state[key] = this.cloneDeep(newPresences); if (currentPresences.length > 0) { const joinedPresenceRefs = state[key].map((m) => m.presence_ref); const curPresences = currentPresences.filter((m) => joinedPresenceRefs.indexOf(m.presence_ref) < 0); state[key].unshift(...curPresences); } onJoin(key, currentPresences, newPresences); }); this.map(leaves, (key, leftPresences) => { let currentPresences = state[key]; if (!currentPresences) return; const presenceRefsToRemove = leftPresences.map((m) => m.presence_ref); currentPresences = currentPresences.filter((m) => presenceRefsToRemove.indexOf(m.presence_ref) < 0); state[key] = currentPresences; onLeave(key, currentPresences, leftPresences); if (currentPresences.length === 0) delete state[key]; }); return state; } /** @internal */ static map(obj, func) { return Object.getOwnPropertyNames(obj).map((key) => func(key, obj[key])); } /** * Remove 'metas' key * Change 'phx_ref' to 'presence_ref' * Remove 'phx_ref' and 'phx_ref_prev' * * @example * // returns { * abc123: [ * { presence_ref: '2', user_id: 1 }, * { presence_ref: '3', user_id: 2 } * ] * } * RealtimePresence.transformState({ * abc123: { * metas: [ * { phx_ref: '2', phx_ref_prev: '1' user_id: 1 }, * { phx_ref: '3', user_id: 2 } * ] * } * }) * * @internal */ static transformState(state) { state = this.cloneDeep(state); return Object.getOwnPropertyNames(state).reduce((newState, key) => { const presences = state[key]; if ('metas' in presences) { newState[key] = presences.metas.map((presence) => { presence['presence_ref'] = presence['phx_ref']; delete presence['phx_ref']; delete presence['phx_ref_prev']; return presence; }); } else { newState[key] = presences; } return newState; }, {}); } /** @internal */ static cloneDeep(obj) { return JSON.parse(JSON.stringify(obj)); } /** @internal */ onJoin(callback) { this.caller.onJoin = callback; } /** @internal */ onLeave(callback) { this.caller.onLeave = callback; } /** @internal */ onSync(callback) { this.caller.onSync = callback; } /** @internal */ inPendingSyncState() { return !this.joinRef || this.joinRef !== this.channel._joinRef(); } } exports.default = RealtimePresence; } (RealtimePresence)); (function (exports) { var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (commonjsGlobal && commonjsGlobal.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (commonjsGlobal && commonjsGlobal.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.REALTIME_CHANNEL_STATES = exports.REALTIME_SUBSCRIBE_STATES = exports.REALTIME_LISTEN_TYPES = exports.REALTIME_POSTGRES_CHANGES_LISTEN_EVENT = void 0; const constants_1 = constants$4; const push_1 = __importDefault(push); const timer_1 = __importDefault(timer); const RealtimePresence_1 = __importDefault(RealtimePresence); const Transformers = __importStar(transformers); const transformers_1 = transformers; (function (REALTIME_POSTGRES_CHANGES_LISTEN_EVENT) { REALTIME_POSTGRES_CHANGES_LISTEN_EVENT["ALL"] = "*"; REALTIME_POSTGRES_CHANGES_LISTEN_EVENT["INSERT"] = "INSERT"; REALTIME_POSTGRES_CHANGES_LISTEN_EVENT["UPDATE"] = "UPDATE"; REALTIME_POSTGRES_CHANGES_LISTEN_EVENT["DELETE"] = "DELETE"; })(exports.REALTIME_POSTGRES_CHANGES_LISTEN_EVENT || (exports.REALTIME_POSTGRES_CHANGES_LISTEN_EVENT = {})); (function (REALTIME_LISTEN_TYPES) { REALTIME_LISTEN_TYPES["BROADCAST"] = "broadcast"; REALTIME_LISTEN_TYPES["PRESENCE"] = "presence"; REALTIME_LISTEN_TYPES["POSTGRES_CHANGES"] = "postgres_changes"; REALTIME_LISTEN_TYPES["SYSTEM"] = "system"; })(exports.REALTIME_LISTEN_TYPES || (exports.REALTIME_LISTEN_TYPES = {})); var REALTIME_SUBSCRIBE_STATES; (function (REALTIME_SUBSCRIBE_STATES) { REALTIME_SUBSCRIBE_STATES["SUBSCRIBED"] = "SUBSCRIBED"; REALTIME_SUBSCRIBE_STATES["TIMED_OUT"] = "TIMED_OUT"; REALTIME_SUBSCRIBE_STATES["CLOSED"] = "CLOSED"; REALTIME_SUBSCRIBE_STATES["CHANNEL_ERROR"] = "CHANNEL_ERROR"; })(REALTIME_SUBSCRIBE_STATES = exports.REALTIME_SUBSCRIBE_STATES || (exports.REALTIME_SUBSCRIBE_STATES = {})); exports.REALTIME_CHANNEL_STATES = constants_1.CHANNEL_STATES; /** A channel is the basic building block of Realtime * and narrows the scope of data flow to subscribed clients. * You can think of a channel as a chatroom where participants are able to see who's online * and send and receive messages. */ class RealtimeChannel { constructor( /** Topic name can be any string. */ topic, params = { config: {} }, socket) { this.topic = topic; this.params = params; this.socket = socket; this.bindings = {}; this.state = constants_1.CHANNEL_STATES.closed; this.joinedOnce = false; this.pushBuffer = []; this.subTopic = topic.replace(/^realtime:/i, ''); this.params.config = Object.assign({ broadcast: { ack: false, self: false }, presence: { key: '' }, private: false, }, params.config); this.timeout = this.socket.timeout; this.joinPush = new push_1.default(this, constants_1.CHANNEL_EVENTS.join, this.params, this.timeout); this.rejoinTimer = new timer_1.default(() => this._rejoinUntilConnected(), this.socket.reconnectAfterMs); this.joinPush.receive('ok', () => { this.state = constants_1.CHANNEL_STATES.joined; this.rejoinTimer.reset(); this.pushBuffer.forEach((pushEvent) => pushEvent.send()); this.pushBuffer = []; }); this._onClose(() => { this.rejoinTimer.reset(); this.socket.log('channel', `close ${this.topic} ${this._joinRef()}`); this.state = constants_1.CHANNEL_STATES.closed; this.socket._remove(this); }); this._onError((reason) => { if (this._isLeaving() || this._isClosed()) { return; } this.socket.log('channel', `error ${this.topic}`, reason); this.state = constants_1.CHANNEL_STATES.errored; this.rejoinTimer.scheduleTimeout(); }); this.joinPush.receive('timeout', () => { if (!this._isJoining()) { return; } this.socket.log('channel', `timeout ${this.topic}`, this.joinPush.timeout); this.state = constants_1.CHANNEL_STATES.errored; this.rejoinTimer.scheduleTimeout(); }); this._on(constants_1.CHANNEL_EVENTS.reply, {}, (payload, ref) => { this._trigger(this._replyEventName(ref), payload); }); this.presence = new RealtimePresence_1.default(this); this.broadcastEndpointURL = (0, transformers_1.httpEndpointURL)(this.socket.endPoint) + '/api/broadcast'; this.private = this.params.config.private || false; } /** Subscribe registers your client with the server */ subscribe(callback, timeout = this.timeout) { var _a, _b; if (!this.socket.isConnected()) { this.socket.connect(); } if (this.joinedOnce) { throw `tried to subscribe multiple times. 'subscribe' can only be called a single time per channel instance`; } else { const { config: { broadcast, presence, private: isPrivate }, } = this.params; this._onError((e) => callback === null || callback === void 0 ? void 0 : callback(REALTIME_SUBSCRIBE_STATES.CHANNEL_ERROR, e)); this._onClose(() => callback === null || callback === void 0 ? void 0 : callback(REALTIME_SUBSCRIBE_STATES.CLOSED)); const accessTokenPayload = {}; const config = { broadcast, presence, postgres_changes: (_b = (_a = this.bindings.postgres_changes) === null || _a === void 0 ? void 0 : _a.map((r) => r.filter)) !== null && _b !== void 0 ? _b : [], private: isPrivate, }; if (this.socket.accessTokenValue) { accessTokenPayload.access_token = this.socket.accessTokenValue; } this.updateJoinPayload(Object.assign({ config }, accessTokenPayload)); this.joinedOnce = true; this._rejoin(timeout); this.joinPush .receive('ok', async ({ postgres_changes }) => { var _a; this.socket.setAuth(); if (postgres_changes === undefined) { callback === null || callback === void 0 ? void 0 : callback(REALTIME_SUBSCRIBE_STATES.SUBSCRIBED); return; } else { const clientPostgresBindings = this.bindings.postgres_changes; const bindingsLen = (_a = clientPostgresBindings === null || clientPostgresBindings === void 0 ? void 0 : clientPostgresBindings.length) !== null && _a !== void 0 ? _a : 0; const newPostgresBindings = []; for (let i = 0; i < bindingsLen; i++) { const clientPostgresBinding = clientPostgresBindings[i]; const { filter: { event, schema, table, filter }, } = clientPostgresBinding; const serverPostgresFilter = postgres_changes && postgres_changes[i]; if (serverPostgresFilter && serverPostgresFilter.event === event && serverPostgresFilter.schema === schema && serverPostgresFilter.table === table && serverPostgresFilter.filter === filter) { newPostgresBindings.push(Object.assign(Object.assign({}, clientPostgresBinding), { id: serverPostgresFilter.id })); } else { this.unsubscribe(); callback === null || callback === void 0 ? void 0 : callback(REALTIME_SUBSCRIBE_STATES.CHANNEL_ERROR, new Error('mismatch between server and client bindings for postgres changes')); return; } } this.bindings.postgres_changes = newPostgresBindings; callback && callback(REALTIME_SUBSCRIBE_STATES.SUBSCRIBED); return; } }) .receive('error', (error) => { callback === null || callback === void 0 ? void 0 : callback(REALTIME_SUBSCRIBE_STATES.CHANNEL_ERROR, new Error(JSON.stringify(Object.values(error).join(', ') || 'error'))); return; }) .receive('timeout', () => { callback === null || callback === void 0 ? void 0 : callback(REALTIME_SUBSCRIBE_STATES.TIMED_OUT); return; }); } return this; } presenceState() { return this.presence.state; } async track(payload, opts = {}) { return await this.send({ type: 'presence', event: 'track', payload, }, opts.timeout || this.timeout); } async untrack(opts = {}) { return await this.send({ type: 'presence', event: 'untrack', }, opts); } on(type, filter, callback) { return this._on(type, filter, callback); } /** * Sends a message into the channel. * * @param args Arguments to send to channel * @param args.type The type of event to send * @param args.event The name of the event being sent * @param args.payload Payload to be sent * @param opts Options to be used during the send process */ async send(args, opts = {}) { var _a, _b; if (!this._canPush() && args.type === 'broadcast') { const { event, payload: endpoint_payload } = args; const authorization = this.socket.accessTokenValue ? `Bearer ${this.socket.accessTokenValue}` : ''; const options = { method: 'POST', headers: { Authorization: authorization, apikey: this.socket.apiKey ? this.socket.apiKey : '', 'Content-Type': 'application/json', }, body: JSON.stringify({ messages: [ { topic: this.subTopic, event, payload: endpoint_payload, private: this.private, }, ], }), }; try { const response = await this._fetchWithTimeout(this.broadcastEndpointURL, options, (_a = opts.timeout) !== null && _a !== void 0 ? _a : this.timeout); await ((_b = response.body) === null || _b === void 0 ? void 0 : _b.cancel()); return response.ok ? 'ok' : 'error'; } catch (error) { if (error.name === 'AbortError') { return 'timed out'; } else { return 'error'; } } } else { return new Promise((resolve) => { var _a, _b, _c; const push = this._push(args.type, args, opts.timeout || this.timeout); if (args.type === 'broadcast' && !((_c = (_b = (_a = this.params) === null || _a === void 0 ? void 0 : _a.config) === null || _b === void 0 ? void 0 : _b.broadcast) === null || _c === void 0 ? void 0 : _c.ack)) { resolve('ok'); } push.receive('ok', () => resolve('ok')); push.receive('error', () => resolve('error')); push.receive('timeout', () => resolve('timed out')); }); } } updateJoinPayload(payload) { this.joinPush.updatePayload(payload); } /** * Leaves the channel. * * Unsubscribes from server events, and instructs channel to terminate on server. * Triggers onClose() hooks. * * To receive leave acknowledgements, use the a `receive` hook to bind to the server ack, ie: * channel.unsubscribe().receive("ok", () => alert("left!") ) */ unsubscribe(timeout = this.timeout) { this.state = constants_1.CHANNEL_STATES.leaving; const onClose = () => { this.socket.log('channel', `leave ${this.topic}`); this._trigger(constants_1.CHANNEL_EVENTS.close, 'leave', this._joinRef()); }; this.rejoinTimer.reset(); // Destroy joinPush to avoid connection timeouts during unscription phase this.joinPush.destroy(); return new Promise((resolve) => { const leavePush = new push_1.default(this, constants_1.CHANNEL_EVENTS.leave, {}, timeout); leavePush .receive('ok', () => { onClose(); resolve('ok'); }) .receive('timeout', () => { onClose(); resolve('timed out'); }) .receive('error', () => { resolve('error'); }); leavePush.send(); if (!this._canPush()) { leavePush.trigger('ok', {}); } }); } /** @internal */ async _fetchWithTimeout(url, options, timeout) { const controller = new AbortController(); const id = setTimeout(() => controller.abort(), timeout); const response = await this.socket.fetch(url, Object.assign(Object.assign({}, options), { signal: controller.signal })); clearTimeout(id); return response; } /** @internal */ _push(event, payload, timeout = this.timeout) { if (!this.joinedOnce) { throw `tried to push '${event}' to '${this.topic}' before joining. Use channel.subscribe() before pushing events`; } let pushEvent = new push_1.default(this, event, payload, timeout); if (this._canPush()) { pushEvent.send(); } else { pushEvent.startTimeout(); this.pushBuffer.push(pushEvent); } return pushEvent; } /** * Overridable message hook * * Receives all events for specialized message handling before dispatching to the channel callbacks. * Must return the payload, modified or unmodified. * * @internal */ _onMessage(_event, payload, _ref) { return payload; } /** @internal */ _isMember(topic) { return this.topic === topic; } /** @internal */ _joinRef() { return this.joinPush.ref; } /** @internal */ _trigger(type, payload, ref) { var _a, _b; const typeLower = type.toLocaleLowerCase(); const { close, error, leave, join } = constants_1.CHANNEL_EVENTS; const events = [close, error, leave, join]; if (ref && events.indexOf(typeLower) >= 0 && ref !== this._joinRef()) { return; } let handledPayload = this._onMessage(typeLower, payload, ref); if (payload && !handledPayload) { throw 'channel onMessage callbacks must return the payload, modified or unmodified'; } if (['insert', 'update', 'delete'].includes(typeLower)) { (_a = this.bindings.postgres_changes) === null || _a === void 0 ? void 0 : _a.filter((bind) => { var _a, _b, _c; return (((_a = bind.filter) === null || _a === void 0 ? void 0 : _a.event) === '*' || ((_c = (_b = bind.filter) === null || _b === void 0 ? void 0 : _b.event) === null || _c === void 0 ? void 0 : _c.toLocaleLowerCase()) === typeLower); }).map((bind) => bind.callback(handledPayload, ref)); } else { (_b = this.bindings[typeLower]) === null || _b === void 0 ? void 0 : _b.filter((bind) => { var _a, _b, _c, _d, _e, _f; if (['broadcast', 'presence', 'postgres_changes'].includes(typeLower)) { if ('id' in bind) { const bindId = bind.id; const bindEvent = (_a = bind.filter) === null || _a === void 0 ? void 0 : _a.event; return (bindId && ((_b = payload.ids) === null || _b === void 0 ? void 0 : _b.includes(bindId)) && (bindEvent === '*' || (bindEvent === null || bindEvent === void 0 ? void 0 : bindEvent.toLocaleLowerCase()) === ((_c = payload.data) === null || _c === void 0 ? void 0 : _c.type.toLocaleLowerCase()))); } else { const bindEvent = (_e = (_d = bind === null || bind === void 0 ? void 0 : bind.filter) === null || _d === void 0 ? void 0 : _d.event) === null || _e === void 0 ? void 0 : _e.toLocaleLowerCase(); return (bindEvent === '*' || bindEvent === ((_f = payload === null || payload === void 0 ? void 0 : payload.event) === null || _f === void 0 ? void 0 : _f.toLocaleLowerCase())); } } else { return bind.type.toLocaleLowerCase() === typeLower; } }).map((bind) => { if (typeof handledPayload === 'object' && 'ids' in handledPayload) { const postgresChanges = handledPayload.data; const { schema, table, commit_timestamp, type, errors } = postgresChanges; const enrichedPayload = { schema: schema, table: table, commit_timestamp: commit_timestamp, eventType: type, new: {}, old: {}, errors: errors, }; handledPayload = Object.assign(Object.assign({}, enrichedPayload), this._getPayloadRecords(postgresChanges)); } bind.callback(handledPayload, ref); }); } } /** @internal */ _isClosed() { return this.state === constants_1.CHANNEL_STATES.closed; } /** @internal */ _isJoined() { return this.state === constants_1.CHANNEL_STATES.joined; } /** @internal */ _isJoining() { return this.state === constants_1.CHANNEL_STATES.joining; } /** @internal */ _isLeaving() { return this.state === constants_1.CHANNEL_STATES.leaving; } /** @internal */ _replyEventName(ref) { return `chan_reply_${ref}`; } /** @internal */ _on(type, filter, callback) { const typeLower = type.toLocaleLowerCase(); const binding = { type: typeLower, filter: filter, callback: callback, }; if (this.bindings[typeLower]) { this.bindings[typeLower].push(binding); } else { this.bindings[typeLower] = [binding]; } return this; } /** @internal */ _off(type, filter) { const typeLower = type.toLocaleLowerCase(); this.bindings[typeLower] = this.bindings[typeLower].filter((bind) => { var _a; return !(((_a = bind.type) === null || _a === void 0 ? void 0 : _a.toLocaleLowerCase()) === typeLower && RealtimeChannel.isEqual(bind.filter, filter)); }); return this; } /** @internal */ static isEqual(obj1, obj2) { if (Object.keys(obj1).length !== Object.keys(obj2).length) { return false; } for (const k in obj1) { if (obj1[k] !== obj2[k]) { return false; } } return true; } /** @internal */ _rejoinUntilConnected() { this.rejoinTimer.scheduleTimeout(); if (this.socket.isConnected()) { this._rejoin(); } } /** * Registers a callback that will be executed when the channel closes. * * @internal */ _onClose(callback) { this._on(constants_1.CHANNEL_EVENTS.close, {}, callback); } /** * Registers a callback that will be executed when the channel encounteres an error. * * @internal */ _onError(callback) { this._on(constants_1.CHANNEL_EVENTS.error, {}, (reason) => callback(reason)); } /** * Returns `true` if the socket is connected and the channel has been joined. * * @internal */ _canPush() { return this.socket.isConnected() && this._isJoined(); } /** @internal */ _rejoin(timeout = this.timeout) { if (this._isLeaving()) { return; } this.socket._leaveOpenTopic(this.topic); this.state = constants_1.CHANNEL_STATES.joining; this.joinPush.resend(timeout); } /** @internal */ _getPayloadRecords(payload) { const records = { new: {}, old: {}, }; if (payload.type === 'INSERT' || payload.type === 'UPDATE') { records.new = Transformers.convertChangeData(payload.columns, payload.record); } if (payload.type === 'UPDATE' || payload.type === 'DELETE') { records.old = Transformers.convertChangeData(payload.columns, payload.old_record); } return records; } } exports.default = RealtimeChannel; } (RealtimeChannel)); var browser$1; var hasRequiredBrowser$1; function requireBrowser$1 () { if (hasRequiredBrowser$1) return browser$1; hasRequiredBrowser$1 = 1; browser$1 = function () { throw new Error( 'ws does not work in the browser. Browser clients must use the native ' + 'WebSocket object' ); }; return browser$1; } var __createBinding$1 = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault$1 = (commonjsGlobal && commonjsGlobal.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar$1 = (commonjsGlobal && commonjsGlobal.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding$1(result, mod, k); __setModuleDefault$1(result, mod); return result; }; var __importDefault$5 = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(RealtimeClient$1, "__esModule", { value: true }); const constants_1$4 = constants$4; const serializer_1 = __importDefault$5(serializer); const timer_1 = __importDefault$5(timer); const transformers_1 = transformers; const RealtimeChannel_1 = __importDefault$5(RealtimeChannel); const noop$3 = () => { }; const NATIVE_WEBSOCKET_AVAILABLE = typeof WebSocket !== 'undefined'; const WORKER_SCRIPT = ` addEventListener("message", (e) => { if (e.data.event === "start") { setInterval(() => postMessage({ event: "keepAlive" }), e.data.interval); } });`; class RealtimeClient { /** * Initializes the Socket. * * @param endPoint The string WebSocket endpoint, ie, "ws://example.com/socket", "wss://example.com", "/socket" (inherited host & protocol) * @param httpEndpoint The string HTTP endpoint, ie, "https://example.com", "/" (inherited host & protocol) * @param options.transport The Websocket Transport, for example WebSocket. * @param options.timeout The default timeout in milliseconds to trigger push timeouts. * @param options.params The optional params to pass when connecting. * @param options.headers The optional headers to pass when connecting. * @param options.heartbeatIntervalMs The millisec interval to send a heartbeat message. * @param options.logger The optional function for specialized logging, ie: logger: (kind, msg, data) => { console.log(`${kind}: ${msg}`, data) } * @param options.encode The function to encode outgoing messages. Defaults to JSON: (payload, callback) => callback(JSON.stringify(payload)) * @param options.decode The function to decode incoming messages. Defaults to Serializer's decode. * @param options.reconnectAfterMs he optional function that returns the millsec reconnect interval. Defaults to stepped backoff off. * @param options.worker Use Web Worker to set a side flow. Defaults to false. * @param options.workerUrl The URL of the worker script. Defaults to https://realtime.supabase.com/worker.js that includes a heartbeat event call to keep the connection alive. */ constructor(endPoint, options) { var _a; this.accessTokenValue = null; this.apiKey = null; this.channels = []; this.endPoint = ''; this.httpEndpoint = ''; this.headers = constants_1$4.DEFAULT_HEADERS; this.params = {}; this.timeout = constants_1$4.DEFAULT_TIMEOUT; this.heartbeatIntervalMs = 30000; this.heartbeatTimer = undefined; this.pendingHeartbeatRef = null; this.ref = 0; this.logger = noop$3; this.conn = null; this.sendBuffer = []; this.serializer = new serializer_1.default(); this.stateChangeCallbacks = { open: [], close: [], error: [], message: [], }; this.accessToken = null; /** * Use either custom fetch, if provided, or default fetch to make HTTP requests * * @internal */ this._resolveFetch = (customFetch) => { let _fetch; if (customFetch) { _fetch = customFetch; } else if (typeof fetch === 'undefined') { _fetch = (...args) => Promise.resolve().then(() => __importStar$1(require$$1)).then(({ default: fetch }) => fetch(...args)); } else { _fetch = fetch; } return (...args) => _fetch(...args); }; this.endPoint = `${endPoint}/${constants_1$4.TRANSPORTS.websocket}`; this.httpEndpoint = (0, transformers_1.httpEndpointURL)(endPoint); if (options === null || options === void 0 ? void 0 : options.transport) { this.transport = options.transport; } else { this.transport = null; } if (options === null || options === void 0 ? void 0 : options.params) this.params = options.params; if (options === null || options === void 0 ? void 0 : options.headers) this.headers = Object.assign(Object.assign({}, this.headers), options.headers); if (options === null || options === void 0 ? void 0 : options.timeout) this.timeout = options.timeout; if (options === null || options === void 0 ? void 0 : options.logger) this.logger = options.logger; if (options === null || options === void 0 ? void 0 : options.heartbeatIntervalMs) this.heartbeatIntervalMs = options.heartbeatIntervalMs; const accessTokenValue = (_a = options === null || options === void 0 ? void 0 : options.params) === null || _a === void 0 ? void 0 : _a.apikey; if (accessTokenValue) { this.accessTokenValue = accessTokenValue; this.apiKey = accessTokenValue; } this.reconnectAfterMs = (options === null || options === void 0 ? void 0 : options.reconnectAfterMs) ? options.reconnectAfterMs : (tries) => { return [1000, 2000, 5000, 10000][tries - 1] || 10000; }; this.encode = (options === null || options === void 0 ? void 0 : options.encode) ? options.encode : (payload, callback) => { return callback(JSON.stringify(payload)); }; this.decode = (options === null || options === void 0 ? void 0 : options.decode) ? options.decode : this.serializer.decode.bind(this.serializer); this.reconnectTimer = new timer_1.default(async () => { this.disconnect(); this.connect(); }, this.reconnectAfterMs); this.fetch = this._resolveFetch(options === null || options === void 0 ? void 0 : options.fetch); if (options === null || options === void 0 ? void 0 : options.worker) { if (typeof window !== 'undefined' && !window.Worker) { throw new Error('Web Worker is not supported'); } this.worker = (options === null || options === void 0 ? void 0 : options.worker) || false; this.workerUrl = options === null || options === void 0 ? void 0 : options.workerUrl; } this.accessToken = (options === null || options === void 0 ? void 0 : options.accessToken) || null; } /** * Connects the socket, unless already connected. */ connect() { if (this.conn) { return; } if (this.transport) { this.conn = new this.transport(this.endpointURL(), undefined, { headers: this.headers, }); return; } if (NATIVE_WEBSOCKET_AVAILABLE) { this.conn = new WebSocket(this.endpointURL()); this.setupConnection(); return; } this.conn = new WSWebSocketDummy(this.endpointURL(), undefined, { close: () => { this.conn = null; }, }); Promise.resolve().then(() => __importStar$1(requireBrowser$1())).then(({ default: WS }) => { this.conn = new WS(this.endpointURL(), undefined, { headers: this.headers, }); this.setupConnection(); }); } /** * Returns the URL of the websocket. * @returns string The URL of the websocket. */ endpointURL() { return this._appendParams(this.endPoint, Object.assign({}, this.params, { vsn: constants_1$4.VSN })); } /** * Disconnects the socket. * * @param code A numeric status code to send on disconnect. * @param reason A custom reason for the disconnect. */ disconnect(code, reason) { if (this.conn) { this.conn.onclose = function () { }; // noop if (code) { this.conn.close(code, reason !== null && reason !== void 0 ? reason : ''); } else { this.conn.close(); } this.conn = null; // remove open handles this.heartbeatTimer && clearInterval(this.heartbeatTimer); this.reconnectTimer.reset(); } } /** * Returns all created channels */ getChannels() { return this.channels; } /** * Unsubscribes and removes a single channel * @param channel A RealtimeChannel instance */ async removeChannel(channel) { const status = await channel.unsubscribe(); if (this.channels.length === 0) { this.disconnect(); } return status; } /** * Unsubscribes and removes all channels */ async removeAllChannels() { const values_1 = await Promise.all(this.channels.map((channel) => channel.unsubscribe())); this.disconnect(); return values_1; } /** * Logs the message. * * For customized logging, `this.logger` can be overridden. */ log(kind, msg, data) { this.logger(kind, msg, data); } /** * Returns the current state of the socket. */ connectionState() { switch (this.conn && this.conn.readyState) { case constants_1$4.SOCKET_STATES.connecting: return constants_1$4.CONNECTION_STATE.Connecting; case constants_1$4.SOCKET_STATES.open: return constants_1$4.CONNECTION_STATE.Open; case constants_1$4.SOCKET_STATES.closing: return constants_1$4.CONNECTION_STATE.Closing; default: return constants_1$4.CONNECTION_STATE.Closed; } } /** * Returns `true` is the connection is open. */ isConnected() { return this.connectionState() === constants_1$4.CONNECTION_STATE.Open; } channel(topic, params = { config: {} }) { const chan = new RealtimeChannel_1.default(`realtime:${topic}`, params, this); this.channels.push(chan); return chan; } /** * Push out a message if the socket is connected. * * If the socket is not connected, the message gets enqueued within a local buffer, and sent out when a connection is next established. */ push(data) { const { topic, event, payload, ref } = data; const callback = () => { this.encode(data, (result) => { var _a; (_a = this.conn) === null || _a === void 0 ? void 0 : _a.send(result); }); }; this.log('push', `${topic} ${event} (${ref})`, payload); if (this.isConnected()) { callback(); } else { this.sendBuffer.push(callback); } } /** * Sets the JWT access token used for channel subscription authorization and Realtime RLS. * * If param is null it will use the `accessToken` callback function or the token set on the client. * * On callback used, it will set the value of the token internal to the client. * * @param token A JWT string to override the token set on the client. */ async setAuth(token = null) { let tokenToSend = token || (this.accessToken && (await this.accessToken())) || this.accessTokenValue; if (tokenToSend) { let parsed = null; try { parsed = JSON.parse(atob(tokenToSend.split('.')[1])); } catch (_error) { } if (parsed && parsed.exp) { let now = Math.floor(Date.now() / 1000); let valid = now - parsed.exp < 0; if (!valid) { this.log('auth', `InvalidJWTToken: Invalid value for JWT claim "exp" with value ${parsed.exp}`); return Promise.reject(`InvalidJWTToken: Invalid value for JWT claim "exp" with value ${parsed.exp}`); } } this.accessTokenValue = tokenToSend; this.channels.forEach((channel) => { tokenToSend && channel.updateJoinPayload({ access_token: tokenToSend }); if (channel.joinedOnce && channel._isJoined()) { channel._push(constants_1$4.CHANNEL_EVENTS.access_token, { access_token: tokenToSend, }); } }); } } /** * Sends a heartbeat message if the socket is connected. */ async sendHeartbeat() { var _a; if (!this.isConnected()) { return; } if (this.pendingHeartbeatRef) { this.pendingHeartbeatRef = null; this.log('transport', 'heartbeat timeout. Attempting to re-establish connection'); (_a = this.conn) === null || _a === void 0 ? void 0 : _a.close(constants_1$4.WS_CLOSE_NORMAL, 'hearbeat timeout'); return; } this.pendingHeartbeatRef = this._makeRef(); this.push({ topic: 'phoenix', event: 'heartbeat', payload: {}, ref: this.pendingHeartbeatRef, }); this.setAuth(); } /** * Flushes send buffer */ flushSendBuffer() { if (this.isConnected() && this.sendBuffer.length > 0) { this.sendBuffer.forEach((callback) => callback()); this.sendBuffer = []; } } /** * Return the next message ref, accounting for overflows * * @internal */ _makeRef() { let newRef = this.ref + 1; if (newRef === this.ref) { this.ref = 0; } else { this.ref = newRef; } return this.ref.toString(); } /** * Unsubscribe from channels with the specified topic. * * @internal */ _leaveOpenTopic(topic) { let dupChannel = this.channels.find((c) => c.topic === topic && (c._isJoined() || c._isJoining())); if (dupChannel) { this.log('transport', `leaving duplicate topic "${topic}"`); dupChannel.unsubscribe(); } } /** * Removes a subscription from the socket. * * @param channel An open subscription. * * @internal */ _remove(channel) { this.channels = this.channels.filter((c) => c._joinRef() !== channel._joinRef()); } /** * Sets up connection handlers. * * @internal */ setupConnection() { if (this.conn) { this.conn.binaryType = 'arraybuffer'; this.conn.onopen = () => this._onConnOpen(); this.conn.onerror = (error) => this._onConnError(error); this.conn.onmessage = (event) => this._onConnMessage(event); this.conn.onclose = (event) => this._onConnClose(event); } } /** @internal */ _onConnMessage(rawMessage) { this.decode(rawMessage.data, (msg) => { let { topic, event, payload, ref } = msg; if (ref && ref === this.pendingHeartbeatRef) { this.pendingHeartbeatRef = null; } this.log('receive', `${payload.status || ''} ${topic} ${event} ${(ref && '(' + ref + ')') || ''}`, payload); this.channels .filter((channel) => channel._isMember(topic)) .forEach((channel) => channel._trigger(event, payload, ref)); this.stateChangeCallbacks.message.forEach((callback) => callback(msg)); }); } /** @internal */ async _onConnOpen() { this.log('transport', `connected to ${this.endpointURL()}`); this.flushSendBuffer(); this.reconnectTimer.reset(); if (!this.worker) { this.heartbeatTimer && clearInterval(this.heartbeatTimer); this.heartbeatTimer = setInterval(() => this.sendHeartbeat(), this.heartbeatIntervalMs); } else { if (this.workerUrl) { this.log('worker', `starting worker for from ${this.workerUrl}`); } else { this.log('worker', `starting default worker`); } const objectUrl = this._workerObjectUrl(this.workerUrl); this.workerRef = new Worker(objectUrl); this.workerRef.onerror = (error) => { this.log('worker', 'worker error', error.message); this.workerRef.terminate(); }; this.workerRef.onmessage = (event) => { if (event.data.event === 'keepAlive') { this.sendHeartbeat(); } }; this.workerRef.postMessage({ event: 'start', interval: this.heartbeatIntervalMs, }); } this.stateChangeCallbacks.open.forEach((callback) => callback()); } /** @internal */ _onConnClose(event) { this.log('transport', 'close', event); this._triggerChanError(); this.heartbeatTimer && clearInterval(this.heartbeatTimer); this.reconnectTimer.scheduleTimeout(); this.stateChangeCallbacks.close.forEach((callback) => callback(event)); } /** @internal */ _onConnError(error) { this.log('transport', error.message); this._triggerChanError(); this.stateChangeCallbacks.error.forEach((callback) => callback(error)); } /** @internal */ _triggerChanError() { this.channels.forEach((channel) => channel._trigger(constants_1$4.CHANNEL_EVENTS.error)); } /** @internal */ _appendParams(url, params) { if (Object.keys(params).length === 0) { return url; } const prefix = url.match(/\?/) ? '&' : '?'; const query = new URLSearchParams(params); return `${url}${prefix}${query}`; } _workerObjectUrl(url) { let result_url; if (url) { result_url = url; } else { const blob = new Blob([WORKER_SCRIPT], { type: 'application/javascript' }); result_url = URL.createObjectURL(blob); } return result_url; } } RealtimeClient$1.default = RealtimeClient; class WSWebSocketDummy { constructor(address, _protocols, options) { this.binaryType = 'arraybuffer'; this.onclose = () => { }; this.onerror = () => { }; this.onmessage = () => { }; this.onopen = () => { }; this.readyState = constants_1$4.SOCKET_STATES.connecting; this.send = () => { }; this.url = null; this.url = address; this.close = options.close; } } (function (exports) { var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (commonjsGlobal && commonjsGlobal.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (commonjsGlobal && commonjsGlobal.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.REALTIME_CHANNEL_STATES = exports.REALTIME_SUBSCRIBE_STATES = exports.REALTIME_PRESENCE_LISTEN_EVENTS = exports.REALTIME_POSTGRES_CHANGES_LISTEN_EVENT = exports.REALTIME_LISTEN_TYPES = exports.RealtimeClient = exports.RealtimeChannel = exports.RealtimePresence = void 0; const RealtimeClient_1 = __importDefault(RealtimeClient$1); exports.RealtimeClient = RealtimeClient_1.default; const RealtimeChannel_1 = __importStar(RealtimeChannel); exports.RealtimeChannel = RealtimeChannel_1.default; Object.defineProperty(exports, "REALTIME_LISTEN_TYPES", { enumerable: true, get: function () { return RealtimeChannel_1.REALTIME_LISTEN_TYPES; } }); Object.defineProperty(exports, "REALTIME_POSTGRES_CHANGES_LISTEN_EVENT", { enumerable: true, get: function () { return RealtimeChannel_1.REALTIME_POSTGRES_CHANGES_LISTEN_EVENT; } }); Object.defineProperty(exports, "REALTIME_SUBSCRIBE_STATES", { enumerable: true, get: function () { return RealtimeChannel_1.REALTIME_SUBSCRIBE_STATES; } }); Object.defineProperty(exports, "REALTIME_CHANNEL_STATES", { enumerable: true, get: function () { return RealtimeChannel_1.REALTIME_CHANNEL_STATES; } }); const RealtimePresence_1 = __importStar(RealtimePresence); exports.RealtimePresence = RealtimePresence_1.default; Object.defineProperty(exports, "REALTIME_PRESENCE_LISTEN_EVENTS", { enumerable: true, get: function () { return RealtimePresence_1.REALTIME_PRESENCE_LISTEN_EVENTS; } }); } (main$2)); var main$1 = {}; var StorageClient$1 = {}; var StorageFileApi$1 = {}; var errors$1 = {}; Object.defineProperty(errors$1, "__esModule", { value: true }); errors$1.StorageUnknownError = errors$1.StorageApiError = errors$1.isStorageError = errors$1.StorageError = void 0; class StorageError extends Error { constructor(message) { super(message); this.__isStorageError = true; this.name = 'StorageError'; } } errors$1.StorageError = StorageError; function isStorageError(error) { return typeof error === 'object' && error !== null && '__isStorageError' in error; } errors$1.isStorageError = isStorageError; class StorageApiError extends StorageError { constructor(message, status) { super(message); this.name = 'StorageApiError'; this.status = status; } toJSON() { return { name: this.name, message: this.message, status: this.status, }; } } errors$1.StorageApiError = StorageApiError; class StorageUnknownError extends StorageError { constructor(message, originalError) { super(message); this.name = 'StorageUnknownError'; this.originalError = originalError; } } errors$1.StorageUnknownError = StorageUnknownError; var fetch$3 = {}; var helpers$2 = {}; (function (exports) { var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (commonjsGlobal && commonjsGlobal.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (commonjsGlobal && commonjsGlobal.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __awaiter = (commonjsGlobal && commonjsGlobal.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.recursiveToCamel = exports.resolveResponse = exports.resolveFetch = void 0; const resolveFetch = (customFetch) => { let _fetch; if (customFetch) { _fetch = customFetch; } else if (typeof fetch === 'undefined') { _fetch = (...args) => Promise.resolve().then(() => __importStar(require$$1)).then(({ default: fetch }) => fetch(...args)); } else { _fetch = fetch; } return (...args) => _fetch(...args); }; exports.resolveFetch = resolveFetch; const resolveResponse = () => __awaiter(void 0, void 0, void 0, function* () { if (typeof Response === 'undefined') { // @ts-ignore return (yield Promise.resolve().then(() => __importStar(require$$1))).Response; } return Response; }); exports.resolveResponse = resolveResponse; const recursiveToCamel = (item) => { if (Array.isArray(item)) { return item.map((el) => (0, exports.recursiveToCamel)(el)); } else if (typeof item === 'function' || item !== Object(item)) { return item; } const result = {}; Object.entries(item).forEach(([key, value]) => { const newKey = key.replace(/([-_][a-z])/gi, (c) => c.toUpperCase().replace(/[-_]/g, '')); result[newKey] = (0, exports.recursiveToCamel)(value); }); return result; }; exports.recursiveToCamel = recursiveToCamel; } (helpers$2)); var __awaiter$6 = (commonjsGlobal && commonjsGlobal.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(fetch$3, "__esModule", { value: true }); fetch$3.remove = fetch$3.head = fetch$3.put = fetch$3.post = fetch$3.get = void 0; const errors_1$5 = errors$1; const helpers_1$7 = helpers$2; const _getErrorMessage$1 = (err) => err.msg || err.message || err.error_description || err.error || JSON.stringify(err); const handleError$1 = (error, reject, options) => __awaiter$6(void 0, void 0, void 0, function* () { const Res = yield (0, helpers_1$7.resolveResponse)(); if (error instanceof Res && !(options === null || options === void 0 ? void 0 : options.noResolveJson)) { error .json() .then((err) => { reject(new errors_1$5.StorageApiError(_getErrorMessage$1(err), error.status || 500)); }) .catch((err) => { reject(new errors_1$5.StorageUnknownError(_getErrorMessage$1(err), err)); }); } else { reject(new errors_1$5.StorageUnknownError(_getErrorMessage$1(error), error)); } }); const _getRequestParams$1 = (method, options, parameters, body) => { const params = { method, headers: (options === null || options === void 0 ? void 0 : options.headers) || {} }; if (method === 'GET') { return params; } params.headers = Object.assign({ 'Content-Type': 'application/json' }, options === null || options === void 0 ? void 0 : options.headers); if (body) { params.body = JSON.stringify(body); } return Object.assign(Object.assign({}, params), parameters); }; function _handleRequest$1(fetcher, method, url, options, parameters, body) { return __awaiter$6(this, void 0, void 0, function* () { return new Promise((resolve, reject) => { fetcher(url, _getRequestParams$1(method, options, parameters, body)) .then((result) => { if (!result.ok) throw result; if (options === null || options === void 0 ? void 0 : options.noResolveJson) return result; return result.json(); }) .then((data) => resolve(data)) .catch((error) => handleError$1(error, reject, options)); }); }); } function get$1(fetcher, url, options, parameters) { return __awaiter$6(this, void 0, void 0, function* () { return _handleRequest$1(fetcher, 'GET', url, options, parameters); }); } fetch$3.get = get$1; function post(fetcher, url, body, options, parameters) { return __awaiter$6(this, void 0, void 0, function* () { return _handleRequest$1(fetcher, 'POST', url, options, parameters, body); }); } fetch$3.post = post; function put(fetcher, url, body, options, parameters) { return __awaiter$6(this, void 0, void 0, function* () { return _handleRequest$1(fetcher, 'PUT', url, options, parameters, body); }); } fetch$3.put = put; function head(fetcher, url, options, parameters) { return __awaiter$6(this, void 0, void 0, function* () { return _handleRequest$1(fetcher, 'HEAD', url, Object.assign(Object.assign({}, options), { noResolveJson: true }), parameters); }); } fetch$3.head = head; function remove(fetcher, url, body, options, parameters) { return __awaiter$6(this, void 0, void 0, function* () { return _handleRequest$1(fetcher, 'DELETE', url, options, parameters, body); }); } fetch$3.remove = remove; var __awaiter$5 = (commonjsGlobal && commonjsGlobal.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(StorageFileApi$1, "__esModule", { value: true }); const errors_1$4 = errors$1; const fetch_1$4 = fetch$3; const helpers_1$6 = helpers$2; const DEFAULT_SEARCH_OPTIONS = { limit: 100, offset: 0, sortBy: { column: 'name', order: 'asc', }, }; const DEFAULT_FILE_OPTIONS = { cacheControl: '3600', contentType: 'text/plain;charset=UTF-8', upsert: false, }; class StorageFileApi { constructor(url, headers = {}, bucketId, fetch) { this.url = url; this.headers = headers; this.bucketId = bucketId; this.fetch = (0, helpers_1$6.resolveFetch)(fetch); } /** * Uploads a file to an existing bucket or replaces an existing file at the specified path with a new one. * * @param method HTTP method. * @param path The relative file path. Should be of the format `folder/subfolder/filename.png`. The bucket must already exist before attempting to upload. * @param fileBody The body of the file to be stored in the bucket. */ uploadOrUpdate(method, path, fileBody, fileOptions) { return __awaiter$5(this, void 0, void 0, function* () { try { let body; const options = Object.assign(Object.assign({}, DEFAULT_FILE_OPTIONS), fileOptions); let headers = Object.assign(Object.assign({}, this.headers), (method === 'POST' && { 'x-upsert': String(options.upsert) })); const metadata = options.metadata; if (typeof Blob !== 'undefined' && fileBody instanceof Blob) { body = new FormData(); body.append('cacheControl', options.cacheControl); if (metadata) { body.append('metadata', this.encodeMetadata(metadata)); } body.append('', fileBody); } else if (typeof FormData !== 'undefined' && fileBody instanceof FormData) { body = fileBody; body.append('cacheControl', options.cacheControl); if (metadata) { body.append('metadata', this.encodeMetadata(metadata)); } } else { body = fileBody; headers['cache-control'] = `max-age=${options.cacheControl}`; headers['content-type'] = options.contentType; if (metadata) { headers['x-metadata'] = this.toBase64(this.encodeMetadata(metadata)); } } if (fileOptions === null || fileOptions === void 0 ? void 0 : fileOptions.headers) { headers = Object.assign(Object.assign({}, headers), fileOptions.headers); } const cleanPath = this._removeEmptyFolders(path); const _path = this._getFinalPath(cleanPath); const res = yield this.fetch(`${this.url}/object/${_path}`, Object.assign({ method, body: body, headers }, ((options === null || options === void 0 ? void 0 : options.duplex) ? { duplex: options.duplex } : {}))); const data = yield res.json(); if (res.ok) { return { data: { path: cleanPath, id: data.Id, fullPath: data.Key }, error: null, }; } else { const error = data; return { data: null, error }; } } catch (error) { if ((0, errors_1$4.isStorageError)(error)) { return { data: null, error }; } throw error; } }); } /** * Uploads a file to an existing bucket. * * @param path The file path, including the file name. Should be of the format `folder/subfolder/filename.png`. The bucket must already exist before attempting to upload. * @param fileBody The body of the file to be stored in the bucket. */ upload(path, fileBody, fileOptions) { return __awaiter$5(this, void 0, void 0, function* () { return this.uploadOrUpdate('POST', path, fileBody, fileOptions); }); } /** * Upload a file with a token generated from `createSignedUploadUrl`. * @param path The file path, including the file name. Should be of the format `folder/subfolder/filename.png`. The bucket must already exist before attempting to upload. * @param token The token generated from `createSignedUploadUrl` * @param fileBody The body of the file to be stored in the bucket. */ uploadToSignedUrl(path, token, fileBody, fileOptions) { return __awaiter$5(this, void 0, void 0, function* () { const cleanPath = this._removeEmptyFolders(path); const _path = this._getFinalPath(cleanPath); const url = new URL(this.url + `/object/upload/sign/${_path}`); url.searchParams.set('token', token); try { let body; const options = Object.assign({ upsert: DEFAULT_FILE_OPTIONS.upsert }, fileOptions); const headers = Object.assign(Object.assign({}, this.headers), { 'x-upsert': String(options.upsert) }); if (typeof Blob !== 'undefined' && fileBody instanceof Blob) { body = new FormData(); body.append('cacheControl', options.cacheControl); body.append('', fileBody); } else if (typeof FormData !== 'undefined' && fileBody instanceof FormData) { body = fileBody; body.append('cacheControl', options.cacheControl); } else { body = fileBody; headers['cache-control'] = `max-age=${options.cacheControl}`; headers['content-type'] = options.contentType; } const res = yield this.fetch(url.toString(), { method: 'PUT', body: body, headers, }); const data = yield res.json(); if (res.ok) { return { data: { path: cleanPath, fullPath: data.Key }, error: null, }; } else { const error = data; return { data: null, error }; } } catch (error) { if ((0, errors_1$4.isStorageError)(error)) { return { data: null, error }; } throw error; } }); } /** * Creates a signed upload URL. * Signed upload URLs can be used to upload files to the bucket without further authentication. * They are valid for 2 hours. * @param path The file path, including the current file name. For example `folder/image.png`. * @param options.upsert If set to true, allows the file to be overwritten if it already exists. */ createSignedUploadUrl(path, options) { return __awaiter$5(this, void 0, void 0, function* () { try { let _path = this._getFinalPath(path); const headers = Object.assign({}, this.headers); if (options === null || options === void 0 ? void 0 : options.upsert) { headers['x-upsert'] = 'true'; } const data = yield (0, fetch_1$4.post)(this.fetch, `${this.url}/object/upload/sign/${_path}`, {}, { headers }); const url = new URL(this.url + data.url); const token = url.searchParams.get('token'); if (!token) { throw new errors_1$4.StorageError('No token returned by API'); } return { data: { signedUrl: url.toString(), path, token }, error: null }; } catch (error) { if ((0, errors_1$4.isStorageError)(error)) { return { data: null, error }; } throw error; } }); } /** * Replaces an existing file at the specified path with a new one. * * @param path The relative file path. Should be of the format `folder/subfolder/filename.png`. The bucket must already exist before attempting to update. * @param fileBody The body of the file to be stored in the bucket. */ update(path, fileBody, fileOptions) { return __awaiter$5(this, void 0, void 0, function* () { return this.uploadOrUpdate('PUT', path, fileBody, fileOptions); }); } /** * Moves an existing file to a new path in the same bucket. * * @param fromPath The original file path, including the current file name. For example `folder/image.png`. * @param toPath The new file path, including the new file name. For example `folder/image-new.png`. * @param options The destination options. */ move(fromPath, toPath, options) { return __awaiter$5(this, void 0, void 0, function* () { try { const data = yield (0, fetch_1$4.post)(this.fetch, `${this.url}/object/move`, { bucketId: this.bucketId, sourceKey: fromPath, destinationKey: toPath, destinationBucket: options === null || options === void 0 ? void 0 : options.destinationBucket, }, { headers: this.headers }); return { data, error: null }; } catch (error) { if ((0, errors_1$4.isStorageError)(error)) { return { data: null, error }; } throw error; } }); } /** * Copies an existing file to a new path in the same bucket. * * @param fromPath The original file path, including the current file name. For example `folder/image.png`. * @param toPath The new file path, including the new file name. For example `folder/image-copy.png`. * @param options The destination options. */ copy(fromPath, toPath, options) { return __awaiter$5(this, void 0, void 0, function* () { try { const data = yield (0, fetch_1$4.post)(this.fetch, `${this.url}/object/copy`, { bucketId: this.bucketId, sourceKey: fromPath, destinationKey: toPath, destinationBucket: options === null || options === void 0 ? void 0 : options.destinationBucket, }, { headers: this.headers }); return { data: { path: data.Key }, error: null }; } catch (error) { if ((0, errors_1$4.isStorageError)(error)) { return { data: null, error }; } throw error; } }); } /** * Creates a signed URL. Use a signed URL to share a file for a fixed amount of time. * * @param path The file path, including the current file name. For example `folder/image.png`. * @param expiresIn The number of seconds until the signed URL expires. For example, `60` for a URL which is valid for one minute. * @param options.download triggers the file as a download if set to true. Set this parameter as the name of the file if you want to trigger the download with a different filename. * @param options.transform Transform the asset before serving it to the client. */ createSignedUrl(path, expiresIn, options) { return __awaiter$5(this, void 0, void 0, function* () { try { let _path = this._getFinalPath(path); let data = yield (0, fetch_1$4.post)(this.fetch, `${this.url}/object/sign/${_path}`, Object.assign({ expiresIn }, ((options === null || options === void 0 ? void 0 : options.transform) ? { transform: options.transform } : {})), { headers: this.headers }); const downloadQueryParam = (options === null || options === void 0 ? void 0 : options.download) ? `&download=${options.download === true ? '' : options.download}` : ''; const signedUrl = encodeURI(`${this.url}${data.signedURL}${downloadQueryParam}`); data = { signedUrl }; return { data, error: null }; } catch (error) { if ((0, errors_1$4.isStorageError)(error)) { return { data: null, error }; } throw error; } }); } /** * Creates multiple signed URLs. Use a signed URL to share a file for a fixed amount of time. * * @param paths The file paths to be downloaded, including the current file names. For example `['folder/image.png', 'folder2/image2.png']`. * @param expiresIn The number of seconds until the signed URLs expire. For example, `60` for URLs which are valid for one minute. * @param options.download triggers the file as a download if set to true. Set this parameter as the name of the file if you want to trigger the download with a different filename. */ createSignedUrls(paths, expiresIn, options) { return __awaiter$5(this, void 0, void 0, function* () { try { const data = yield (0, fetch_1$4.post)(this.fetch, `${this.url}/object/sign/${this.bucketId}`, { expiresIn, paths }, { headers: this.headers }); const downloadQueryParam = (options === null || options === void 0 ? void 0 : options.download) ? `&download=${options.download === true ? '' : options.download}` : ''; return { data: data.map((datum) => (Object.assign(Object.assign({}, datum), { signedUrl: datum.signedURL ? encodeURI(`${this.url}${datum.signedURL}${downloadQueryParam}`) : null }))), error: null, }; } catch (error) { if ((0, errors_1$4.isStorageError)(error)) { return { data: null, error }; } throw error; } }); } /** * Downloads a file from a private bucket. For public buckets, make a request to the URL returned from `getPublicUrl` instead. * * @param path The full path and file name of the file to be downloaded. For example `folder/image.png`. * @param options.transform Transform the asset before serving it to the client. */ download(path, options) { return __awaiter$5(this, void 0, void 0, function* () { const wantsTransformation = typeof (options === null || options === void 0 ? void 0 : options.transform) !== 'undefined'; const renderPath = wantsTransformation ? 'render/image/authenticated' : 'object'; const transformationQuery = this.transformOptsToQueryString((options === null || options === void 0 ? void 0 : options.transform) || {}); const queryString = transformationQuery ? `?${transformationQuery}` : ''; try { const _path = this._getFinalPath(path); const res = yield (0, fetch_1$4.get)(this.fetch, `${this.url}/${renderPath}/${_path}${queryString}`, { headers: this.headers, noResolveJson: true, }); const data = yield res.blob(); return { data, error: null }; } catch (error) { if ((0, errors_1$4.isStorageError)(error)) { return { data: null, error }; } throw error; } }); } /** * Retrieves the details of an existing file. * @param path */ info(path) { return __awaiter$5(this, void 0, void 0, function* () { const _path = this._getFinalPath(path); try { const data = yield (0, fetch_1$4.get)(this.fetch, `${this.url}/object/info/${_path}`, { headers: this.headers, }); return { data: (0, helpers_1$6.recursiveToCamel)(data), error: null }; } catch (error) { if ((0, errors_1$4.isStorageError)(error)) { return { data: null, error }; } throw error; } }); } /** * Checks the existence of a file. * @param path */ exists(path) { return __awaiter$5(this, void 0, void 0, function* () { const _path = this._getFinalPath(path); try { yield (0, fetch_1$4.head)(this.fetch, `${this.url}/object/${_path}`, { headers: this.headers, }); return { data: true, error: null }; } catch (error) { if ((0, errors_1$4.isStorageError)(error) && error instanceof errors_1$4.StorageUnknownError) { const originalError = error.originalError; if ([400, 404].includes(originalError === null || originalError === void 0 ? void 0 : originalError.status)) { return { data: false, error }; } } throw error; } }); } /** * A simple convenience function to get the URL for an asset in a public bucket. If you do not want to use this function, you can construct the public URL by concatenating the bucket URL with the path to the asset. * This function does not verify if the bucket is public. If a public URL is created for a bucket which is not public, you will not be able to download the asset. * * @param path The path and name of the file to generate the public URL for. For example `folder/image.png`. * @param options.download Triggers the file as a download if set to true. Set this parameter as the name of the file if you want to trigger the download with a different filename. * @param options.transform Transform the asset before serving it to the client. */ getPublicUrl(path, options) { const _path = this._getFinalPath(path); const _queryString = []; const downloadQueryParam = (options === null || options === void 0 ? void 0 : options.download) ? `download=${options.download === true ? '' : options.download}` : ''; if (downloadQueryParam !== '') { _queryString.push(downloadQueryParam); } const wantsTransformation = typeof (options === null || options === void 0 ? void 0 : options.transform) !== 'undefined'; const renderPath = wantsTransformation ? 'render/image' : 'object'; const transformationQuery = this.transformOptsToQueryString((options === null || options === void 0 ? void 0 : options.transform) || {}); if (transformationQuery !== '') { _queryString.push(transformationQuery); } let queryString = _queryString.join('&'); if (queryString !== '') { queryString = `?${queryString}`; } return { data: { publicUrl: encodeURI(`${this.url}/${renderPath}/public/${_path}${queryString}`) }, }; } /** * Deletes files within the same bucket * * @param paths An array of files to delete, including the path and file name. For example [`'folder/image.png'`]. */ remove(paths) { return __awaiter$5(this, void 0, void 0, function* () { try { const data = yield (0, fetch_1$4.remove)(this.fetch, `${this.url}/object/${this.bucketId}`, { prefixes: paths }, { headers: this.headers }); return { data, error: null }; } catch (error) { if ((0, errors_1$4.isStorageError)(error)) { return { data: null, error }; } throw error; } }); } /** * Get file metadata * @param id the file id to retrieve metadata */ // async getMetadata( // id: string // ): Promise< // | { // data: Metadata // error: null // } // | { // data: null // error: StorageError // } // > { // try { // const data = await get(this.fetch, `${this.url}/metadata/${id}`, { headers: this.headers }) // return { data, error: null } // } catch (error) { // if (isStorageError(error)) { // return { data: null, error } // } // throw error // } // } /** * Update file metadata * @param id the file id to update metadata * @param meta the new file metadata */ // async updateMetadata( // id: string, // meta: Metadata // ): Promise< // | { // data: Metadata // error: null // } // | { // data: null // error: StorageError // } // > { // try { // const data = await post( // this.fetch, // `${this.url}/metadata/${id}`, // { ...meta }, // { headers: this.headers } // ) // return { data, error: null } // } catch (error) { // if (isStorageError(error)) { // return { data: null, error } // } // throw error // } // } /** * Lists all the files within a bucket. * @param path The folder path. */ list(path, options, parameters) { return __awaiter$5(this, void 0, void 0, function* () { try { const body = Object.assign(Object.assign(Object.assign({}, DEFAULT_SEARCH_OPTIONS), options), { prefix: path || '' }); const data = yield (0, fetch_1$4.post)(this.fetch, `${this.url}/object/list/${this.bucketId}`, body, { headers: this.headers }, parameters); return { data, error: null }; } catch (error) { if ((0, errors_1$4.isStorageError)(error)) { return { data: null, error }; } throw error; } }); } encodeMetadata(metadata) { return JSON.stringify(metadata); } toBase64(data) { if (typeof Buffer !== 'undefined') { return Buffer.from(data).toString('base64'); } return btoa(data); } _getFinalPath(path) { return `${this.bucketId}/${path}`; } _removeEmptyFolders(path) { return path.replace(/^\/|\/$/g, '').replace(/\/+/g, '/'); } transformOptsToQueryString(transform) { const params = []; if (transform.width) { params.push(`width=${transform.width}`); } if (transform.height) { params.push(`height=${transform.height}`); } if (transform.resize) { params.push(`resize=${transform.resize}`); } if (transform.format) { params.push(`format=${transform.format}`); } if (transform.quality) { params.push(`quality=${transform.quality}`); } return params.join('&'); } } StorageFileApi$1.default = StorageFileApi; var StorageBucketApi$1 = {}; var constants$3 = {}; var version$2 = {}; Object.defineProperty(version$2, "__esModule", { value: true }); version$2.version = void 0; // generated by genversion version$2.version = '2.7.1'; Object.defineProperty(constants$3, "__esModule", { value: true }); constants$3.DEFAULT_HEADERS = void 0; const version_1$1 = version$2; constants$3.DEFAULT_HEADERS = { 'X-Client-Info': `storage-js/${version_1$1.version}` }; var __awaiter$4 = (commonjsGlobal && commonjsGlobal.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(StorageBucketApi$1, "__esModule", { value: true }); const constants_1$3 = constants$3; const errors_1$3 = errors$1; const fetch_1$3 = fetch$3; const helpers_1$5 = helpers$2; class StorageBucketApi { constructor(url, headers = {}, fetch) { this.url = url; this.headers = Object.assign(Object.assign({}, constants_1$3.DEFAULT_HEADERS), headers); this.fetch = (0, helpers_1$5.resolveFetch)(fetch); } /** * Retrieves the details of all Storage buckets within an existing project. */ listBuckets() { return __awaiter$4(this, void 0, void 0, function* () { try { const data = yield (0, fetch_1$3.get)(this.fetch, `${this.url}/bucket`, { headers: this.headers }); return { data, error: null }; } catch (error) { if ((0, errors_1$3.isStorageError)(error)) { return { data: null, error }; } throw error; } }); } /** * Retrieves the details of an existing Storage bucket. * * @param id The unique identifier of the bucket you would like to retrieve. */ getBucket(id) { return __awaiter$4(this, void 0, void 0, function* () { try { const data = yield (0, fetch_1$3.get)(this.fetch, `${this.url}/bucket/${id}`, { headers: this.headers }); return { data, error: null }; } catch (error) { if ((0, errors_1$3.isStorageError)(error)) { return { data: null, error }; } throw error; } }); } /** * Creates a new Storage bucket * * @param id A unique identifier for the bucket you are creating. * @param options.public The visibility of the bucket. Public buckets don't require an authorization token to download objects, but still require a valid token for all other operations. By default, buckets are private. * @param options.fileSizeLimit specifies the max file size in bytes that can be uploaded to this bucket. * The global file size limit takes precedence over this value. * The default value is null, which doesn't set a per bucket file size limit. * @param options.allowedMimeTypes specifies the allowed mime types that this bucket can accept during upload. * The default value is null, which allows files with all mime types to be uploaded. * Each mime type specified can be a wildcard, e.g. image/*, or a specific mime type, e.g. image/png. * @returns newly created bucket id */ createBucket(id, options = { public: false, }) { return __awaiter$4(this, void 0, void 0, function* () { try { const data = yield (0, fetch_1$3.post)(this.fetch, `${this.url}/bucket`, { id, name: id, public: options.public, file_size_limit: options.fileSizeLimit, allowed_mime_types: options.allowedMimeTypes, }, { headers: this.headers }); return { data, error: null }; } catch (error) { if ((0, errors_1$3.isStorageError)(error)) { return { data: null, error }; } throw error; } }); } /** * Updates a Storage bucket * * @param id A unique identifier for the bucket you are updating. * @param options.public The visibility of the bucket. Public buckets don't require an authorization token to download objects, but still require a valid token for all other operations. * @param options.fileSizeLimit specifies the max file size in bytes that can be uploaded to this bucket. * The global file size limit takes precedence over this value. * The default value is null, which doesn't set a per bucket file size limit. * @param options.allowedMimeTypes specifies the allowed mime types that this bucket can accept during upload. * The default value is null, which allows files with all mime types to be uploaded. * Each mime type specified can be a wildcard, e.g. image/*, or a specific mime type, e.g. image/png. */ updateBucket(id, options) { return __awaiter$4(this, void 0, void 0, function* () { try { const data = yield (0, fetch_1$3.put)(this.fetch, `${this.url}/bucket/${id}`, { id, name: id, public: options.public, file_size_limit: options.fileSizeLimit, allowed_mime_types: options.allowedMimeTypes, }, { headers: this.headers }); return { data, error: null }; } catch (error) { if ((0, errors_1$3.isStorageError)(error)) { return { data: null, error }; } throw error; } }); } /** * Removes all objects inside a single bucket. * * @param id The unique identifier of the bucket you would like to empty. */ emptyBucket(id) { return __awaiter$4(this, void 0, void 0, function* () { try { const data = yield (0, fetch_1$3.post)(this.fetch, `${this.url}/bucket/${id}/empty`, {}, { headers: this.headers }); return { data, error: null }; } catch (error) { if ((0, errors_1$3.isStorageError)(error)) { return { data: null, error }; } throw error; } }); } /** * Deletes an existing bucket. A bucket can't be deleted with existing objects inside it. * You must first `empty()` the bucket. * * @param id The unique identifier of the bucket you would like to delete. */ deleteBucket(id) { return __awaiter$4(this, void 0, void 0, function* () { try { const data = yield (0, fetch_1$3.remove)(this.fetch, `${this.url}/bucket/${id}`, {}, { headers: this.headers }); return { data, error: null }; } catch (error) { if ((0, errors_1$3.isStorageError)(error)) { return { data: null, error }; } throw error; } }); } } StorageBucketApi$1.default = StorageBucketApi; var __importDefault$4 = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(StorageClient$1, "__esModule", { value: true }); StorageClient$1.StorageClient = void 0; const StorageFileApi_1 = __importDefault$4(StorageFileApi$1); const StorageBucketApi_1 = __importDefault$4(StorageBucketApi$1); class StorageClient extends StorageBucketApi_1.default { constructor(url, headers = {}, fetch) { super(url, headers, fetch); } /** * Perform file operation in a bucket. * * @param id The bucket id to operate on. */ from(id) { return new StorageFileApi_1.default(this.url, this.headers, id, this.fetch); } } StorageClient$1.StorageClient = StorageClient; var types$1 = {}; Object.defineProperty(types$1, "__esModule", { value: true }); (function (exports) { var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __exportStar = (commonjsGlobal && commonjsGlobal.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.StorageClient = void 0; var StorageClient_1 = StorageClient$1; Object.defineProperty(exports, "StorageClient", { enumerable: true, get: function () { return StorageClient_1.StorageClient; } }); __exportStar(types$1, exports); __exportStar(errors$1, exports); } (main$1)); var constants$2 = {}; var version$1 = {}; Object.defineProperty(version$1, "__esModule", { value: true }); version$1.version = void 0; version$1.version = '2.49.1'; (function (exports) { Object.defineProperty(exports, "__esModule", { value: true }); exports.DEFAULT_REALTIME_OPTIONS = exports.DEFAULT_AUTH_OPTIONS = exports.DEFAULT_DB_OPTIONS = exports.DEFAULT_GLOBAL_OPTIONS = exports.DEFAULT_HEADERS = void 0; const version_1 = version$1; let JS_ENV = ''; // @ts-ignore if (typeof Deno !== 'undefined') { JS_ENV = 'deno'; } else if (typeof document !== 'undefined') { JS_ENV = 'web'; } else if (typeof navigator !== 'undefined' && navigator.product === 'ReactNative') { JS_ENV = 'react-native'; } else { JS_ENV = 'node'; } exports.DEFAULT_HEADERS = { 'X-Client-Info': `supabase-js-${JS_ENV}/${version_1.version}` }; exports.DEFAULT_GLOBAL_OPTIONS = { headers: exports.DEFAULT_HEADERS, }; exports.DEFAULT_DB_OPTIONS = { schema: 'public', }; exports.DEFAULT_AUTH_OPTIONS = { autoRefreshToken: true, persistSession: true, detectSessionInUrl: true, flowType: 'implicit', }; exports.DEFAULT_REALTIME_OPTIONS = {}; } (constants$2)); var fetch$2 = {}; (function (exports) { var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (commonjsGlobal && commonjsGlobal.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (commonjsGlobal && commonjsGlobal.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __awaiter = (commonjsGlobal && commonjsGlobal.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.fetchWithAuth = exports.resolveHeadersConstructor = exports.resolveFetch = void 0; // @ts-ignore const node_fetch_1 = __importStar(require$$1); const resolveFetch = (customFetch) => { let _fetch; if (customFetch) { _fetch = customFetch; } else if (typeof fetch === 'undefined') { _fetch = node_fetch_1.default; } else { _fetch = fetch; } return (...args) => _fetch(...args); }; exports.resolveFetch = resolveFetch; const resolveHeadersConstructor = () => { if (typeof Headers === 'undefined') { return node_fetch_1.Headers; } return Headers; }; exports.resolveHeadersConstructor = resolveHeadersConstructor; const fetchWithAuth = (supabaseKey, getAccessToken, customFetch) => { const fetch = (0, exports.resolveFetch)(customFetch); const HeadersConstructor = (0, exports.resolveHeadersConstructor)(); return (input, init) => __awaiter(void 0, void 0, void 0, function* () { var _a; const accessToken = (_a = (yield getAccessToken())) !== null && _a !== void 0 ? _a : supabaseKey; let headers = new HeadersConstructor(init === null || init === void 0 ? void 0 : init.headers); if (!headers.has('apikey')) { headers.set('apikey', supabaseKey); } if (!headers.has('Authorization')) { headers.set('Authorization', `Bearer ${accessToken}`); } return fetch(input, Object.assign(Object.assign({}, init), { headers })); }); }; exports.fetchWithAuth = fetchWithAuth; } (fetch$2)); var helpers$1 = {}; var __awaiter$3 = (commonjsGlobal && commonjsGlobal.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(helpers$1, "__esModule", { value: true }); helpers$1.applySettingDefaults = helpers$1.isBrowser = helpers$1.stripTrailingSlash = helpers$1.uuid = void 0; function uuid() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { var r = (Math.random() * 16) | 0, v = c == 'x' ? r : (r & 0x3) | 0x8; return v.toString(16); }); } helpers$1.uuid = uuid; function stripTrailingSlash(url) { return url.replace(/\/$/, ''); } helpers$1.stripTrailingSlash = stripTrailingSlash; const isBrowser = () => typeof window !== 'undefined'; helpers$1.isBrowser = isBrowser; function applySettingDefaults(options, defaults) { const { db: dbOptions, auth: authOptions, realtime: realtimeOptions, global: globalOptions, } = options; const { db: DEFAULT_DB_OPTIONS, auth: DEFAULT_AUTH_OPTIONS, realtime: DEFAULT_REALTIME_OPTIONS, global: DEFAULT_GLOBAL_OPTIONS, } = defaults; const result = { db: Object.assign(Object.assign({}, DEFAULT_DB_OPTIONS), dbOptions), auth: Object.assign(Object.assign({}, DEFAULT_AUTH_OPTIONS), authOptions), realtime: Object.assign(Object.assign({}, DEFAULT_REALTIME_OPTIONS), realtimeOptions), global: Object.assign(Object.assign({}, DEFAULT_GLOBAL_OPTIONS), globalOptions), accessToken: () => __awaiter$3(this, void 0, void 0, function* () { return ''; }), }; if (options.accessToken) { result.accessToken = options.accessToken; } else { // hack around Required<> delete result.accessToken; } return result; } helpers$1.applySettingDefaults = applySettingDefaults; var SupabaseAuthClient$1 = {}; var main = {}; var GoTrueAdminApi$1 = {}; var fetch$1 = {}; var constants$1 = {}; var version = {}; Object.defineProperty(version, "__esModule", { value: true }); version.version = void 0; version.version = '2.68.0'; (function (exports) { Object.defineProperty(exports, "__esModule", { value: true }); exports.API_VERSIONS = exports.API_VERSION_HEADER_NAME = exports.NETWORK_FAILURE = exports.DEFAULT_HEADERS = exports.AUDIENCE = exports.STORAGE_KEY = exports.GOTRUE_URL = exports.EXPIRY_MARGIN_MS = exports.AUTO_REFRESH_TICK_THRESHOLD = exports.AUTO_REFRESH_TICK_DURATION_MS = void 0; const version_1 = version; /** Current session will be checked for refresh at this interval. */ exports.AUTO_REFRESH_TICK_DURATION_MS = 30 * 1000; /** * A token refresh will be attempted this many ticks before the current session expires. */ exports.AUTO_REFRESH_TICK_THRESHOLD = 3; /* * Earliest time before an access token expires that the session should be refreshed. */ exports.EXPIRY_MARGIN_MS = exports.AUTO_REFRESH_TICK_THRESHOLD * exports.AUTO_REFRESH_TICK_DURATION_MS; exports.GOTRUE_URL = 'http://localhost:9999'; exports.STORAGE_KEY = 'supabase.auth.token'; exports.AUDIENCE = ''; exports.DEFAULT_HEADERS = { 'X-Client-Info': `gotrue-js/${version_1.version}` }; exports.NETWORK_FAILURE = { MAX_RETRIES: 10, RETRY_INTERVAL: 2, // in deciseconds }; exports.API_VERSION_HEADER_NAME = 'X-Supabase-Api-Version'; exports.API_VERSIONS = { '2024-01-01': { timestamp: Date.parse('2024-01-01T00:00:00.0Z'), name: '2024-01-01', }, }; } (constants$1)); var helpers = {}; (function (exports) { var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (commonjsGlobal && commonjsGlobal.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (commonjsGlobal && commonjsGlobal.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.parseResponseAPIVersion = exports.getCodeChallengeAndMethod = exports.generatePKCEChallenge = exports.generatePKCEVerifier = exports.retryable = exports.sleep = exports.decodeJWTPayload = exports.Deferred = exports.decodeBase64URL = exports.removeItemAsync = exports.getItemAsync = exports.setItemAsync = exports.looksLikeFetchResponse = exports.resolveFetch = exports.parseParametersFromURL = exports.supportsLocalStorage = exports.isBrowser = exports.uuid = exports.expiresAt = void 0; const constants_1 = constants$1; function expiresAt(expiresIn) { const timeNow = Math.round(Date.now() / 1000); return timeNow + expiresIn; } exports.expiresAt = expiresAt; function uuid() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { const r = (Math.random() * 16) | 0, v = c == 'x' ? r : (r & 0x3) | 0x8; return v.toString(16); }); } exports.uuid = uuid; const isBrowser = () => typeof window !== 'undefined' && typeof document !== 'undefined'; exports.isBrowser = isBrowser; const localStorageWriteTests = { tested: false, writable: false, }; /** * Checks whether localStorage is supported on this browser. */ const supportsLocalStorage = () => { if (!(0, exports.isBrowser)()) { return false; } try { if (typeof globalThis.localStorage !== 'object') { return false; } } catch (e) { // DOM exception when accessing `localStorage` return false; } if (localStorageWriteTests.tested) { return localStorageWriteTests.writable; } const randomKey = `lswt-${Math.random()}${Math.random()}`; try { globalThis.localStorage.setItem(randomKey, randomKey); globalThis.localStorage.removeItem(randomKey); localStorageWriteTests.tested = true; localStorageWriteTests.writable = true; } catch (e) { // localStorage can't be written to // https://www.chromium.org/for-testers/bug-reporting-guidelines/uncaught-securityerror-failed-to-read-the-localstorage-property-from-window-access-is-denied-for-this-document localStorageWriteTests.tested = true; localStorageWriteTests.writable = false; } return localStorageWriteTests.writable; }; exports.supportsLocalStorage = supportsLocalStorage; /** * Extracts parameters encoded in the URL both in the query and fragment. */ function parseParametersFromURL(href) { const result = {}; const url = new URL(href); if (url.hash && url.hash[0] === '#') { try { const hashSearchParams = new URLSearchParams(url.hash.substring(1)); hashSearchParams.forEach((value, key) => { result[key] = value; }); } catch (e) { // hash is not a query string } } // search parameters take precedence over hash parameters url.searchParams.forEach((value, key) => { result[key] = value; }); return result; } exports.parseParametersFromURL = parseParametersFromURL; const resolveFetch = (customFetch) => { let _fetch; if (customFetch) { _fetch = customFetch; } else if (typeof fetch === 'undefined') { _fetch = (...args) => Promise.resolve().then(() => __importStar(require$$1)).then(({ default: fetch }) => fetch(...args)); } else { _fetch = fetch; } return (...args) => _fetch(...args); }; exports.resolveFetch = resolveFetch; const looksLikeFetchResponse = (maybeResponse) => { return (typeof maybeResponse === 'object' && maybeResponse !== null && 'status' in maybeResponse && 'ok' in maybeResponse && 'json' in maybeResponse && typeof maybeResponse.json === 'function'); }; exports.looksLikeFetchResponse = looksLikeFetchResponse; // Storage helpers const setItemAsync = async (storage, key, data) => { await storage.setItem(key, JSON.stringify(data)); }; exports.setItemAsync = setItemAsync; const getItemAsync = async (storage, key) => { const value = await storage.getItem(key); if (!value) { return null; } try { return JSON.parse(value); } catch (_a) { return value; } }; exports.getItemAsync = getItemAsync; const removeItemAsync = async (storage, key) => { await storage.removeItem(key); }; exports.removeItemAsync = removeItemAsync; function decodeBase64URL(value) { const key = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='; let base64 = ''; let chr1, chr2, chr3; let enc1, enc2, enc3, enc4; let i = 0; value = value.replace('-', '+').replace('_', '/'); while (i < value.length) { enc1 = key.indexOf(value.charAt(i++)); enc2 = key.indexOf(value.charAt(i++)); enc3 = key.indexOf(value.charAt(i++)); enc4 = key.indexOf(value.charAt(i++)); chr1 = (enc1 << 2) | (enc2 >> 4); chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); chr3 = ((enc3 & 3) << 6) | enc4; base64 = base64 + String.fromCharCode(chr1); if (enc3 != 64 && chr2 != 0) { base64 = base64 + String.fromCharCode(chr2); } if (enc4 != 64 && chr3 != 0) { base64 = base64 + String.fromCharCode(chr3); } } return base64; } exports.decodeBase64URL = decodeBase64URL; /** * A deferred represents some asynchronous work that is not yet finished, which * may or may not culminate in a value. * Taken from: https://github.com/mike-north/types/blob/master/src/async.ts */ class Deferred { constructor() { this.promise = new Deferred.promiseConstructor((res, rej) => { this.resolve = res; this.reject = rej; }); } } exports.Deferred = Deferred; Deferred.promiseConstructor = Promise; // Taken from: https://stackoverflow.com/questions/38552003/how-to-decode-jwt-token-in-javascript-without-using-a-library function decodeJWTPayload(token) { // Regex checks for base64url format const base64UrlRegex = /^([a-z0-9_-]{4})*($|[a-z0-9_-]{3}=?$|[a-z0-9_-]{2}(==)?$)$/i; const parts = token.split('.'); if (parts.length !== 3) { throw new Error('JWT is not valid: not a JWT structure'); } if (!base64UrlRegex.test(parts[1])) { throw new Error('JWT is not valid: payload is not in base64url format'); } const base64Url = parts[1]; return JSON.parse(decodeBase64URL(base64Url)); } exports.decodeJWTPayload = decodeJWTPayload; /** * Creates a promise that resolves to null after some time. */ async function sleep(time) { return await new Promise((accept) => { setTimeout(() => accept(null), time); }); } exports.sleep = sleep; /** * Converts the provided async function into a retryable function. Each result * or thrown error is sent to the isRetryable function which should return true * if the function should run again. */ function retryable(fn, isRetryable) { const promise = new Promise((accept, reject) => { (async () => { for (let attempt = 0; attempt < Infinity; attempt++) { try { const result = await fn(attempt); if (!isRetryable(attempt, null, result)) { accept(result); return; } } catch (e) { if (!isRetryable(attempt, e)) { reject(e); return; } } } })(); }); return promise; } exports.retryable = retryable; function dec2hex(dec) { return ('0' + dec.toString(16)).substr(-2); } // Functions below taken from: https://stackoverflow.com/questions/63309409/creating-a-code-verifier-and-challenge-for-pkce-auth-on-spotify-api-in-reactjs function generatePKCEVerifier() { const verifierLength = 56; const array = new Uint32Array(verifierLength); if (typeof crypto === 'undefined') { const charSet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~'; const charSetLen = charSet.length; let verifier = ''; for (let i = 0; i < verifierLength; i++) { verifier += charSet.charAt(Math.floor(Math.random() * charSetLen)); } return verifier; } crypto.getRandomValues(array); return Array.from(array, dec2hex).join(''); } exports.generatePKCEVerifier = generatePKCEVerifier; async function sha256(randomString) { const encoder = new TextEncoder(); const encodedData = encoder.encode(randomString); const hash = await crypto.subtle.digest('SHA-256', encodedData); const bytes = new Uint8Array(hash); return Array.from(bytes) .map((c) => String.fromCharCode(c)) .join(''); } function base64urlencode(str) { return btoa(str).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''); } async function generatePKCEChallenge(verifier) { const hasCryptoSupport = typeof crypto !== 'undefined' && typeof crypto.subtle !== 'undefined' && typeof TextEncoder !== 'undefined'; if (!hasCryptoSupport) { console.warn('WebCrypto API is not supported. Code challenge method will default to use plain instead of sha256.'); return verifier; } const hashed = await sha256(verifier); return base64urlencode(hashed); } exports.generatePKCEChallenge = generatePKCEChallenge; async function getCodeChallengeAndMethod(storage, storageKey, isPasswordRecovery = false) { const codeVerifier = generatePKCEVerifier(); let storedCodeVerifier = codeVerifier; if (isPasswordRecovery) { storedCodeVerifier += '/PASSWORD_RECOVERY'; } await (0, exports.setItemAsync)(storage, `${storageKey}-code-verifier`, storedCodeVerifier); const codeChallenge = await generatePKCEChallenge(codeVerifier); const codeChallengeMethod = codeVerifier === codeChallenge ? 'plain' : 's256'; return [codeChallenge, codeChallengeMethod]; } exports.getCodeChallengeAndMethod = getCodeChallengeAndMethod; /** Parses the API version which is 2YYY-MM-DD. */ const API_VERSION_REGEX = /^2[0-9]{3}-(0[1-9]|1[0-2])-(0[1-9]|1[0-9]|2[0-9]|3[0-1])$/i; function parseResponseAPIVersion(response) { const apiVersion = response.headers.get(constants_1.API_VERSION_HEADER_NAME); if (!apiVersion) { return null; } if (!apiVersion.match(API_VERSION_REGEX)) { return null; } try { const date = new Date(`${apiVersion}T00:00:00.0Z`); return date; } catch (e) { return null; } } exports.parseResponseAPIVersion = parseResponseAPIVersion; } (helpers)); var errors = {}; Object.defineProperty(errors, "__esModule", { value: true }); errors.isAuthWeakPasswordError = errors.AuthWeakPasswordError = errors.isAuthRetryableFetchError = errors.AuthRetryableFetchError = errors.AuthPKCEGrantCodeExchangeError = errors.isAuthImplicitGrantRedirectError = errors.AuthImplicitGrantRedirectError = errors.AuthInvalidCredentialsError = errors.AuthInvalidTokenResponseError = errors.isAuthSessionMissingError = errors.AuthSessionMissingError = errors.CustomAuthError = errors.AuthUnknownError = errors.isAuthApiError = errors.AuthApiError = errors.isAuthError = errors.AuthError = void 0; class AuthError extends Error { constructor(message, status, code) { super(message); this.__isAuthError = true; this.name = 'AuthError'; this.status = status; this.code = code; } } errors.AuthError = AuthError; function isAuthError(error) { return typeof error === 'object' && error !== null && '__isAuthError' in error; } errors.isAuthError = isAuthError; class AuthApiError extends AuthError { constructor(message, status, code) { super(message, status, code); this.name = 'AuthApiError'; this.status = status; this.code = code; } } errors.AuthApiError = AuthApiError; function isAuthApiError(error) { return isAuthError(error) && error.name === 'AuthApiError'; } errors.isAuthApiError = isAuthApiError; class AuthUnknownError extends AuthError { constructor(message, originalError) { super(message); this.name = 'AuthUnknownError'; this.originalError = originalError; } } errors.AuthUnknownError = AuthUnknownError; class CustomAuthError extends AuthError { constructor(message, name, status, code) { super(message, status, code); this.name = name; this.status = status; } } errors.CustomAuthError = CustomAuthError; class AuthSessionMissingError extends CustomAuthError { constructor() { super('Auth session missing!', 'AuthSessionMissingError', 400, undefined); } } errors.AuthSessionMissingError = AuthSessionMissingError; function isAuthSessionMissingError(error) { return isAuthError(error) && error.name === 'AuthSessionMissingError'; } errors.isAuthSessionMissingError = isAuthSessionMissingError; class AuthInvalidTokenResponseError extends CustomAuthError { constructor() { super('Auth session or user missing', 'AuthInvalidTokenResponseError', 500, undefined); } } errors.AuthInvalidTokenResponseError = AuthInvalidTokenResponseError; class AuthInvalidCredentialsError extends CustomAuthError { constructor(message) { super(message, 'AuthInvalidCredentialsError', 400, undefined); } } errors.AuthInvalidCredentialsError = AuthInvalidCredentialsError; class AuthImplicitGrantRedirectError extends CustomAuthError { constructor(message, details = null) { super(message, 'AuthImplicitGrantRedirectError', 500, undefined); this.details = null; this.details = details; } toJSON() { return { name: this.name, message: this.message, status: this.status, details: this.details, }; } } errors.AuthImplicitGrantRedirectError = AuthImplicitGrantRedirectError; function isAuthImplicitGrantRedirectError(error) { return isAuthError(error) && error.name === 'AuthImplicitGrantRedirectError'; } errors.isAuthImplicitGrantRedirectError = isAuthImplicitGrantRedirectError; class AuthPKCEGrantCodeExchangeError extends CustomAuthError { constructor(message, details = null) { super(message, 'AuthPKCEGrantCodeExchangeError', 500, undefined); this.details = null; this.details = details; } toJSON() { return { name: this.name, message: this.message, status: this.status, details: this.details, }; } } errors.AuthPKCEGrantCodeExchangeError = AuthPKCEGrantCodeExchangeError; class AuthRetryableFetchError extends CustomAuthError { constructor(message, status) { super(message, 'AuthRetryableFetchError', status, undefined); } } errors.AuthRetryableFetchError = AuthRetryableFetchError; function isAuthRetryableFetchError(error) { return isAuthError(error) && error.name === 'AuthRetryableFetchError'; } errors.isAuthRetryableFetchError = isAuthRetryableFetchError; /** * This error is thrown on certain methods when the password used is deemed * weak. Inspect the reasons to identify what password strength rules are * inadequate. */ class AuthWeakPasswordError extends CustomAuthError { constructor(message, status, reasons) { super(message, 'AuthWeakPasswordError', status, 'weak_password'); this.reasons = reasons; } } errors.AuthWeakPasswordError = AuthWeakPasswordError; function isAuthWeakPasswordError(error) { return isAuthError(error) && error.name === 'AuthWeakPasswordError'; } errors.isAuthWeakPasswordError = isAuthWeakPasswordError; var __rest$2 = (commonjsGlobal && commonjsGlobal.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; Object.defineProperty(fetch$1, "__esModule", { value: true }); fetch$1._noResolveJsonResponse = fetch$1._generateLinkResponse = fetch$1._ssoResponse = fetch$1._userResponse = fetch$1._sessionResponsePassword = fetch$1._sessionResponse = fetch$1._request = fetch$1.handleError = void 0; const constants_1$2 = constants$1; const helpers_1$4 = helpers; const errors_1$2 = errors; const _getErrorMessage = (err) => err.msg || err.message || err.error_description || err.error || JSON.stringify(err); const NETWORK_ERROR_CODES = [502, 503, 504]; async function handleError(error) { var _a; if (!(0, helpers_1$4.looksLikeFetchResponse)(error)) { throw new errors_1$2.AuthRetryableFetchError(_getErrorMessage(error), 0); } if (NETWORK_ERROR_CODES.includes(error.status)) { // status in 500...599 range - server had an error, request might be retryed. throw new errors_1$2.AuthRetryableFetchError(_getErrorMessage(error), error.status); } let data; try { data = await error.json(); } catch (e) { throw new errors_1$2.AuthUnknownError(_getErrorMessage(e), e); } let errorCode = undefined; const responseAPIVersion = (0, helpers_1$4.parseResponseAPIVersion)(error); if (responseAPIVersion && responseAPIVersion.getTime() >= constants_1$2.API_VERSIONS['2024-01-01'].timestamp && typeof data === 'object' && data && typeof data.code === 'string') { errorCode = data.code; } else if (typeof data === 'object' && data && typeof data.error_code === 'string') { errorCode = data.error_code; } if (!errorCode) { // Legacy support for weak password errors, when there were no error codes if (typeof data === 'object' && data && typeof data.weak_password === 'object' && data.weak_password && Array.isArray(data.weak_password.reasons) && data.weak_password.reasons.length && data.weak_password.reasons.reduce((a, i) => a && typeof i === 'string', true)) { throw new errors_1$2.AuthWeakPasswordError(_getErrorMessage(data), error.status, data.weak_password.reasons); } } else if (errorCode === 'weak_password') { throw new errors_1$2.AuthWeakPasswordError(_getErrorMessage(data), error.status, ((_a = data.weak_password) === null || _a === void 0 ? void 0 : _a.reasons) || []); } else if (errorCode === 'session_not_found') { // The `session_id` inside the JWT does not correspond to a row in the // `sessions` table. This usually means the user has signed out, has been // deleted, or their session has somehow been terminated. throw new errors_1$2.AuthSessionMissingError(); } throw new errors_1$2.AuthApiError(_getErrorMessage(data), error.status || 500, errorCode); } fetch$1.handleError = handleError; const _getRequestParams = (method, options, parameters, body) => { const params = { method, headers: (options === null || options === void 0 ? void 0 : options.headers) || {} }; if (method === 'GET') { return params; } params.headers = Object.assign({ 'Content-Type': 'application/json;charset=UTF-8' }, options === null || options === void 0 ? void 0 : options.headers); params.body = JSON.stringify(body); return Object.assign(Object.assign({}, params), parameters); }; async function _request(fetcher, method, url, options) { var _a; const headers = Object.assign({}, options === null || options === void 0 ? void 0 : options.headers); if (!headers[constants_1$2.API_VERSION_HEADER_NAME]) { headers[constants_1$2.API_VERSION_HEADER_NAME] = constants_1$2.API_VERSIONS['2024-01-01'].name; } if (options === null || options === void 0 ? void 0 : options.jwt) { headers['Authorization'] = `Bearer ${options.jwt}`; } const qs = (_a = options === null || options === void 0 ? void 0 : options.query) !== null && _a !== void 0 ? _a : {}; if (options === null || options === void 0 ? void 0 : options.redirectTo) { qs['redirect_to'] = options.redirectTo; } const queryString = Object.keys(qs).length ? '?' + new URLSearchParams(qs).toString() : ''; const data = await _handleRequest(fetcher, method, url + queryString, { headers, noResolveJson: options === null || options === void 0 ? void 0 : options.noResolveJson, }, {}, options === null || options === void 0 ? void 0 : options.body); return (options === null || options === void 0 ? void 0 : options.xform) ? options === null || options === void 0 ? void 0 : options.xform(data) : { data: Object.assign({}, data), error: null }; } fetch$1._request = _request; async function _handleRequest(fetcher, method, url, options, parameters, body) { const requestParams = _getRequestParams(method, options, parameters, body); let result; try { result = await fetcher(url, Object.assign({}, requestParams)); } catch (e) { console.error(e); // fetch failed, likely due to a network or CORS error throw new errors_1$2.AuthRetryableFetchError(_getErrorMessage(e), 0); } if (!result.ok) { await handleError(result); } if (options === null || options === void 0 ? void 0 : options.noResolveJson) { return result; } try { return await result.json(); } catch (e) { await handleError(e); } } function _sessionResponse(data) { var _a; let session = null; if (hasSession(data)) { session = Object.assign({}, data); if (!data.expires_at) { session.expires_at = (0, helpers_1$4.expiresAt)(data.expires_in); } } const user = (_a = data.user) !== null && _a !== void 0 ? _a : data; return { data: { session, user }, error: null }; } fetch$1._sessionResponse = _sessionResponse; function _sessionResponsePassword(data) { const response = _sessionResponse(data); if (!response.error && data.weak_password && typeof data.weak_password === 'object' && Array.isArray(data.weak_password.reasons) && data.weak_password.reasons.length && data.weak_password.message && typeof data.weak_password.message === 'string' && data.weak_password.reasons.reduce((a, i) => a && typeof i === 'string', true)) { response.data.weak_password = data.weak_password; } return response; } fetch$1._sessionResponsePassword = _sessionResponsePassword; function _userResponse(data) { var _a; const user = (_a = data.user) !== null && _a !== void 0 ? _a : data; return { data: { user }, error: null }; } fetch$1._userResponse = _userResponse; function _ssoResponse(data) { return { data, error: null }; } fetch$1._ssoResponse = _ssoResponse; function _generateLinkResponse(data) { const { action_link, email_otp, hashed_token, redirect_to, verification_type } = data, rest = __rest$2(data, ["action_link", "email_otp", "hashed_token", "redirect_to", "verification_type"]); const properties = { action_link, email_otp, hashed_token, redirect_to, verification_type, }; const user = Object.assign({}, rest); return { data: { properties, user, }, error: null, }; } fetch$1._generateLinkResponse = _generateLinkResponse; function _noResolveJsonResponse(data) { return data; } fetch$1._noResolveJsonResponse = _noResolveJsonResponse; /** * hasSession checks if the response object contains a valid session * @param data A response object * @returns true if a session is in the response */ function hasSession(data) { return data.access_token && data.refresh_token && data.expires_in; } var __rest$1 = (commonjsGlobal && commonjsGlobal.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; Object.defineProperty(GoTrueAdminApi$1, "__esModule", { value: true }); const fetch_1$2 = fetch$1; const helpers_1$3 = helpers; const errors_1$1 = errors; class GoTrueAdminApi { constructor({ url = '', headers = {}, fetch, }) { this.url = url; this.headers = headers; this.fetch = (0, helpers_1$3.resolveFetch)(fetch); this.mfa = { listFactors: this._listFactors.bind(this), deleteFactor: this._deleteFactor.bind(this), }; } /** * Removes a logged-in session. * @param jwt A valid, logged-in JWT. * @param scope The logout sope. */ async signOut(jwt, scope = 'global') { try { await (0, fetch_1$2._request)(this.fetch, 'POST', `${this.url}/logout?scope=${scope}`, { headers: this.headers, jwt, noResolveJson: true, }); return { data: null, error: null }; } catch (error) { if ((0, errors_1$1.isAuthError)(error)) { return { data: null, error }; } throw error; } } /** * Sends an invite link to an email address. * @param email The email address of the user. * @param options Additional options to be included when inviting. */ async inviteUserByEmail(email, options = {}) { try { return await (0, fetch_1$2._request)(this.fetch, 'POST', `${this.url}/invite`, { body: { email, data: options.data }, headers: this.headers, redirectTo: options.redirectTo, xform: fetch_1$2._userResponse, }); } catch (error) { if ((0, errors_1$1.isAuthError)(error)) { return { data: { user: null }, error }; } throw error; } } /** * Generates email links and OTPs to be sent via a custom email provider. * @param email The user's email. * @param options.password User password. For signup only. * @param options.data Optional user metadata. For signup only. * @param options.redirectTo The redirect url which should be appended to the generated link */ async generateLink(params) { try { const { options } = params, rest = __rest$1(params, ["options"]); const body = Object.assign(Object.assign({}, rest), options); if ('newEmail' in rest) { // replace newEmail with new_email in request body body.new_email = rest === null || rest === void 0 ? void 0 : rest.newEmail; delete body['newEmail']; } return await (0, fetch_1$2._request)(this.fetch, 'POST', `${this.url}/admin/generate_link`, { body: body, headers: this.headers, xform: fetch_1$2._generateLinkResponse, redirectTo: options === null || options === void 0 ? void 0 : options.redirectTo, }); } catch (error) { if ((0, errors_1$1.isAuthError)(error)) { return { data: { properties: null, user: null, }, error, }; } throw error; } } // User Admin API /** * Creates a new user. * This function should only be called on a server. Never expose your `service_role` key in the browser. */ async createUser(attributes) { try { return await (0, fetch_1$2._request)(this.fetch, 'POST', `${this.url}/admin/users`, { body: attributes, headers: this.headers, xform: fetch_1$2._userResponse, }); } catch (error) { if ((0, errors_1$1.isAuthError)(error)) { return { data: { user: null }, error }; } throw error; } } /** * Get a list of users. * * This function should only be called on a server. Never expose your `service_role` key in the browser. * @param params An object which supports `page` and `perPage` as numbers, to alter the paginated results. */ async listUsers(params) { var _a, _b, _c, _d, _e, _f, _g; try { const pagination = { nextPage: null, lastPage: 0, total: 0 }; const response = await (0, fetch_1$2._request)(this.fetch, 'GET', `${this.url}/admin/users`, { headers: this.headers, noResolveJson: true, query: { page: (_b = (_a = params === null || params === void 0 ? void 0 : params.page) === null || _a === void 0 ? void 0 : _a.toString()) !== null && _b !== void 0 ? _b : '', per_page: (_d = (_c = params === null || params === void 0 ? void 0 : params.perPage) === null || _c === void 0 ? void 0 : _c.toString()) !== null && _d !== void 0 ? _d : '', }, xform: fetch_1$2._noResolveJsonResponse, }); if (response.error) throw response.error; const users = await response.json(); const total = (_e = response.headers.get('x-total-count')) !== null && _e !== void 0 ? _e : 0; const links = (_g = (_f = response.headers.get('link')) === null || _f === void 0 ? void 0 : _f.split(',')) !== null && _g !== void 0 ? _g : []; if (links.length > 0) { links.forEach((link) => { const page = parseInt(link.split(';')[0].split('=')[1].substring(0, 1)); const rel = JSON.parse(link.split(';')[1].split('=')[1]); pagination[`${rel}Page`] = page; }); pagination.total = parseInt(total); } return { data: Object.assign(Object.assign({}, users), pagination), error: null }; } catch (error) { if ((0, errors_1$1.isAuthError)(error)) { return { data: { users: [] }, error }; } throw error; } } /** * Get user by id. * * @param uid The user's unique identifier * * This function should only be called on a server. Never expose your `service_role` key in the browser. */ async getUserById(uid) { try { return await (0, fetch_1$2._request)(this.fetch, 'GET', `${this.url}/admin/users/${uid}`, { headers: this.headers, xform: fetch_1$2._userResponse, }); } catch (error) { if ((0, errors_1$1.isAuthError)(error)) { return { data: { user: null }, error }; } throw error; } } /** * Updates the user data. * * @param attributes The data you want to update. * * This function should only be called on a server. Never expose your `service_role` key in the browser. */ async updateUserById(uid, attributes) { try { return await (0, fetch_1$2._request)(this.fetch, 'PUT', `${this.url}/admin/users/${uid}`, { body: attributes, headers: this.headers, xform: fetch_1$2._userResponse, }); } catch (error) { if ((0, errors_1$1.isAuthError)(error)) { return { data: { user: null }, error }; } throw error; } } /** * Delete a user. Requires a `service_role` key. * * @param id The user id you want to remove. * @param shouldSoftDelete If true, then the user will be soft-deleted from the auth schema. Soft deletion allows user identification from the hashed user ID but is not reversible. * Defaults to false for backward compatibility. * * This function should only be called on a server. Never expose your `service_role` key in the browser. */ async deleteUser(id, shouldSoftDelete = false) { try { return await (0, fetch_1$2._request)(this.fetch, 'DELETE', `${this.url}/admin/users/${id}`, { headers: this.headers, body: { should_soft_delete: shouldSoftDelete, }, xform: fetch_1$2._userResponse, }); } catch (error) { if ((0, errors_1$1.isAuthError)(error)) { return { data: { user: null }, error }; } throw error; } } async _listFactors(params) { try { const { data, error } = await (0, fetch_1$2._request)(this.fetch, 'GET', `${this.url}/admin/users/${params.userId}/factors`, { headers: this.headers, xform: (factors) => { return { data: { factors }, error: null }; }, }); return { data, error }; } catch (error) { if ((0, errors_1$1.isAuthError)(error)) { return { data: null, error }; } throw error; } } async _deleteFactor(params) { try { const data = await (0, fetch_1$2._request)(this.fetch, 'DELETE', `${this.url}/admin/users/${params.userId}/factors/${params.id}`, { headers: this.headers, }); return { data, error: null }; } catch (error) { if ((0, errors_1$1.isAuthError)(error)) { return { data: null, error }; } throw error; } } } GoTrueAdminApi$1.default = GoTrueAdminApi; var GoTrueClient$1 = {}; var localStorage = {}; Object.defineProperty(localStorage, "__esModule", { value: true }); localStorage.memoryLocalStorageAdapter = localStorage.localStorageAdapter = void 0; const helpers_1$2 = helpers; /** * Provides safe access to the globalThis.localStorage property. */ localStorage.localStorageAdapter = { getItem: (key) => { if (!(0, helpers_1$2.supportsLocalStorage)()) { return null; } return globalThis.localStorage.getItem(key); }, setItem: (key, value) => { if (!(0, helpers_1$2.supportsLocalStorage)()) { return; } globalThis.localStorage.setItem(key, value); }, removeItem: (key) => { if (!(0, helpers_1$2.supportsLocalStorage)()) { return; } globalThis.localStorage.removeItem(key); }, }; /** * Returns a localStorage-like object that stores the key-value pairs in * memory. */ function memoryLocalStorageAdapter(store = {}) { return { getItem: (key) => { return store[key] || null; }, setItem: (key, value) => { store[key] = value; }, removeItem: (key) => { delete store[key]; }, }; } localStorage.memoryLocalStorageAdapter = memoryLocalStorageAdapter; var polyfills = {}; Object.defineProperty(polyfills, "__esModule", { value: true }); polyfills.polyfillGlobalThis = void 0; /** * https://mathiasbynens.be/notes/globalthis */ function polyfillGlobalThis() { if (typeof globalThis === 'object') return; try { Object.defineProperty(Object.prototype, '__magic__', { get: function () { return this; }, configurable: true, }); // @ts-expect-error 'Allow access to magic' __magic__.globalThis = __magic__; // @ts-expect-error 'Allow access to magic' delete Object.prototype.__magic__; } catch (e) { if (typeof self !== 'undefined') { // @ts-expect-error 'Allow access to globals' self.globalThis = self; } } } polyfills.polyfillGlobalThis = polyfillGlobalThis; var locks = {}; (function (exports) { Object.defineProperty(exports, "__esModule", { value: true }); exports.processLock = exports.navigatorLock = exports.ProcessLockAcquireTimeoutError = exports.NavigatorLockAcquireTimeoutError = exports.LockAcquireTimeoutError = exports.internals = void 0; const helpers_1 = helpers; /** * @experimental */ exports.internals = { /** * @experimental */ debug: !!(globalThis && (0, helpers_1.supportsLocalStorage)() && globalThis.localStorage && globalThis.localStorage.getItem('supabase.gotrue-js.locks.debug') === 'true'), }; /** * An error thrown when a lock cannot be acquired after some amount of time. * * Use the {@link #isAcquireTimeout} property instead of checking with `instanceof`. */ class LockAcquireTimeoutError extends Error { constructor(message) { super(message); this.isAcquireTimeout = true; } } exports.LockAcquireTimeoutError = LockAcquireTimeoutError; class NavigatorLockAcquireTimeoutError extends LockAcquireTimeoutError { } exports.NavigatorLockAcquireTimeoutError = NavigatorLockAcquireTimeoutError; class ProcessLockAcquireTimeoutError extends LockAcquireTimeoutError { } exports.ProcessLockAcquireTimeoutError = ProcessLockAcquireTimeoutError; /** * Implements a global exclusive lock using the Navigator LockManager API. It * is available on all browsers released after 2022-03-15 with Safari being the * last one to release support. If the API is not available, this function will * throw. Make sure you check availablility before configuring {@link * GoTrueClient}. * * You can turn on debugging by setting the `supabase.gotrue-js.locks.debug` * local storage item to `true`. * * Internals: * * Since the LockManager API does not preserve stack traces for the async * function passed in the `request` method, a trick is used where acquiring the * lock releases a previously started promise to run the operation in the `fn` * function. The lock waits for that promise to finish (with or without error), * while the function will finally wait for the result anyway. * * @param name Name of the lock to be acquired. * @param acquireTimeout If negative, no timeout. If 0 an error is thrown if * the lock can't be acquired without waiting. If positive, the lock acquire * will time out after so many milliseconds. An error is * a timeout if it has `isAcquireTimeout` set to true. * @param fn The operation to run once the lock is acquired. */ async function navigatorLock(name, acquireTimeout, fn) { if (exports.internals.debug) { console.log('@supabase/gotrue-js: navigatorLock: acquire lock', name, acquireTimeout); } const abortController = new globalThis.AbortController(); if (acquireTimeout > 0) { setTimeout(() => { abortController.abort(); if (exports.internals.debug) { console.log('@supabase/gotrue-js: navigatorLock acquire timed out', name); } }, acquireTimeout); } // MDN article: https://developer.mozilla.org/en-US/docs/Web/API/LockManager/request // Wrapping navigator.locks.request() with a plain Promise is done as some // libraries like zone.js patch the Promise object to track the execution // context. However, it appears that most browsers use an internal promise // implementation when using the navigator.locks.request() API causing them // to lose context and emit confusing log messages or break certain features. // This wrapping is believed to help zone.js track the execution context // better. return await Promise.resolve().then(() => globalThis.navigator.locks.request(name, acquireTimeout === 0 ? { mode: 'exclusive', ifAvailable: true, } : { mode: 'exclusive', signal: abortController.signal, }, async (lock) => { if (lock) { if (exports.internals.debug) { console.log('@supabase/gotrue-js: navigatorLock: acquired', name, lock.name); } try { return await fn(); } finally { if (exports.internals.debug) { console.log('@supabase/gotrue-js: navigatorLock: released', name, lock.name); } } } else { if (acquireTimeout === 0) { if (exports.internals.debug) { console.log('@supabase/gotrue-js: navigatorLock: not immediately available', name); } throw new NavigatorLockAcquireTimeoutError(`Acquiring an exclusive Navigator LockManager lock "${name}" immediately failed`); } else { if (exports.internals.debug) { try { const result = await globalThis.navigator.locks.query(); console.log('@supabase/gotrue-js: Navigator LockManager state', JSON.stringify(result, null, ' ')); } catch (e) { console.warn('@supabase/gotrue-js: Error when querying Navigator LockManager state', e); } } // Browser is not following the Navigator LockManager spec, it // returned a null lock when we didn't use ifAvailable. So we can // pretend the lock is acquired in the name of backward compatibility // and user experience and just run the function. console.warn('@supabase/gotrue-js: Navigator LockManager returned a null lock when using #request without ifAvailable set to true, it appears this browser is not following the LockManager spec https://developer.mozilla.org/en-US/docs/Web/API/LockManager/request'); return await fn(); } } })); } exports.navigatorLock = navigatorLock; const PROCESS_LOCKS = {}; /** * Implements a global exclusive lock that works only in the current process. * Useful for environments like React Native or other non-browser * single-process (i.e. no concept of "tabs") environments. * * Use {@link #navigatorLock} in browser environments. * * @param name Name of the lock to be acquired. * @param acquireTimeout If negative, no timeout. If 0 an error is thrown if * the lock can't be acquired without waiting. If positive, the lock acquire * will time out after so many milliseconds. An error is * a timeout if it has `isAcquireTimeout` set to true. * @param fn The operation to run once the lock is acquired. */ async function processLock(name, acquireTimeout, fn) { var _a; const previousOperation = (_a = PROCESS_LOCKS[name]) !== null && _a !== void 0 ? _a : Promise.resolve(); const currentOperation = Promise.race([ previousOperation.catch(() => { // ignore error of previous operation that we're waiting to finish return null; }), acquireTimeout >= 0 ? new Promise((_, reject) => { setTimeout(() => { reject(new ProcessLockAcquireTimeoutError(`Acquring process lock with name "${name}" timed out`)); }, acquireTimeout); }) : null, ].filter((x) => x)) .catch((e) => { if (e && e.isAcquireTimeout) { throw e; } return null; }) .then(async () => { // previous operations finished and we didn't get a race on the acquire // timeout, so the current operation can finally start return await fn(); }); PROCESS_LOCKS[name] = currentOperation.catch(async (e) => { if (e && e.isAcquireTimeout) { // if the current operation timed out, it doesn't mean that the previous // operation finished, so we need contnue waiting for it to finish await previousOperation; return null; } throw e; }); // finally wait for the current operation to finish successfully, with an // error or with an acquire timeout error return await currentOperation; } exports.processLock = processLock; } (locks)); var __importDefault$3 = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(GoTrueClient$1, "__esModule", { value: true }); const GoTrueAdminApi_1$1 = __importDefault$3(GoTrueAdminApi$1); const constants_1$1 = constants$1; const errors_1 = errors; const fetch_1$1 = fetch$1; const helpers_1$1 = helpers; const local_storage_1 = localStorage; const polyfills_1 = polyfills; const version_1 = version; const locks_1 = locks; (0, polyfills_1.polyfillGlobalThis)(); // Make "globalThis" available const DEFAULT_OPTIONS = { url: constants_1$1.GOTRUE_URL, storageKey: constants_1$1.STORAGE_KEY, autoRefreshToken: true, persistSession: true, detectSessionInUrl: true, headers: constants_1$1.DEFAULT_HEADERS, flowType: 'implicit', debug: false, hasCustomAuthorizationHeader: false, }; async function lockNoOp(name, acquireTimeout, fn) { return await fn(); } class GoTrueClient { /** * Create a new client for use in the browser. */ constructor(options) { var _a, _b; this.memoryStorage = null; this.stateChangeEmitters = new Map(); this.autoRefreshTicker = null; this.visibilityChangedCallback = null; this.refreshingDeferred = null; /** * Keeps track of the async client initialization. * When null or not yet resolved the auth state is `unknown` * Once resolved the the auth state is known and it's save to call any further client methods. * Keep extra care to never reject or throw uncaught errors */ this.initializePromise = null; this.detectSessionInUrl = true; this.hasCustomAuthorizationHeader = false; this.suppressGetSessionWarning = false; this.lockAcquired = false; this.pendingInLock = []; /** * Used to broadcast state change events to other tabs listening. */ this.broadcastChannel = null; this.logger = console.log; this.instanceID = GoTrueClient.nextInstanceID; GoTrueClient.nextInstanceID += 1; if (this.instanceID > 0 && (0, helpers_1$1.isBrowser)()) { console.warn('Multiple GoTrueClient instances detected in the same browser context. It is not an error, but this should be avoided as it may produce undefined behavior when used concurrently under the same storage key.'); } const settings = Object.assign(Object.assign({}, DEFAULT_OPTIONS), options); this.logDebugMessages = !!settings.debug; if (typeof settings.debug === 'function') { this.logger = settings.debug; } this.persistSession = settings.persistSession; this.storageKey = settings.storageKey; this.autoRefreshToken = settings.autoRefreshToken; this.admin = new GoTrueAdminApi_1$1.default({ url: settings.url, headers: settings.headers, fetch: settings.fetch, }); this.url = settings.url; this.headers = settings.headers; this.fetch = (0, helpers_1$1.resolveFetch)(settings.fetch); this.lock = settings.lock || lockNoOp; this.detectSessionInUrl = settings.detectSessionInUrl; this.flowType = settings.flowType; this.hasCustomAuthorizationHeader = settings.hasCustomAuthorizationHeader; if (settings.lock) { this.lock = settings.lock; } else if ((0, helpers_1$1.isBrowser)() && ((_a = globalThis === null || globalThis === void 0 ? void 0 : globalThis.navigator) === null || _a === void 0 ? void 0 : _a.locks)) { this.lock = locks_1.navigatorLock; } else { this.lock = lockNoOp; } this.mfa = { verify: this._verify.bind(this), enroll: this._enroll.bind(this), unenroll: this._unenroll.bind(this), challenge: this._challenge.bind(this), listFactors: this._listFactors.bind(this), challengeAndVerify: this._challengeAndVerify.bind(this), getAuthenticatorAssuranceLevel: this._getAuthenticatorAssuranceLevel.bind(this), }; if (this.persistSession) { if (settings.storage) { this.storage = settings.storage; } else { if ((0, helpers_1$1.supportsLocalStorage)()) { this.storage = local_storage_1.localStorageAdapter; } else { this.memoryStorage = {}; this.storage = (0, local_storage_1.memoryLocalStorageAdapter)(this.memoryStorage); } } } else { this.memoryStorage = {}; this.storage = (0, local_storage_1.memoryLocalStorageAdapter)(this.memoryStorage); } if ((0, helpers_1$1.isBrowser)() && globalThis.BroadcastChannel && this.persistSession && this.storageKey) { try { this.broadcastChannel = new globalThis.BroadcastChannel(this.storageKey); } catch (e) { console.error('Failed to create a new BroadcastChannel, multi-tab state changes will not be available', e); } (_b = this.broadcastChannel) === null || _b === void 0 ? void 0 : _b.addEventListener('message', async (event) => { this._debug('received broadcast notification from other tab or client', event); await this._notifyAllSubscribers(event.data.event, event.data.session, false); // broadcast = false so we don't get an endless loop of messages }); } this.initialize(); } _debug(...args) { if (this.logDebugMessages) { this.logger(`GoTrueClient@${this.instanceID} (${version_1.version}) ${new Date().toISOString()}`, ...args); } return this; } /** * Initializes the client session either from the url or from storage. * This method is automatically called when instantiating the client, but should also be called * manually when checking for an error from an auth redirect (oauth, magiclink, password recovery, etc). */ async initialize() { if (this.initializePromise) { return await this.initializePromise; } this.initializePromise = (async () => { return await this._acquireLock(-1, async () => { return await this._initialize(); }); })(); return await this.initializePromise; } /** * IMPORTANT: * 1. Never throw in this method, as it is called from the constructor * 2. Never return a session from this method as it would be cached over * the whole lifetime of the client */ async _initialize() { var _a; try { const params = (0, helpers_1$1.parseParametersFromURL)(window.location.href); let callbackUrlType = 'none'; if (this._isImplicitGrantCallback(params)) { callbackUrlType = 'implicit'; } else if (await this._isPKCECallback(params)) { callbackUrlType = 'pkce'; } /** * Attempt to get the session from the URL only if these conditions are fulfilled * * Note: If the URL isn't one of the callback url types (implicit or pkce), * then there could be an existing session so we don't want to prematurely remove it */ if ((0, helpers_1$1.isBrowser)() && this.detectSessionInUrl && callbackUrlType !== 'none') { const { data, error } = await this._getSessionFromURL(params, callbackUrlType); if (error) { this._debug('#_initialize()', 'error detecting session from URL', error); if ((0, errors_1.isAuthImplicitGrantRedirectError)(error)) { const errorCode = (_a = error.details) === null || _a === void 0 ? void 0 : _a.code; if (errorCode === 'identity_already_exists' || errorCode === 'identity_not_found' || errorCode === 'single_identity_not_deletable') { return { error }; } } // failed login attempt via url, // remove old session as in verifyOtp, signUp and signInWith* await this._removeSession(); return { error }; } const { session, redirectType } = data; this._debug('#_initialize()', 'detected session in URL', session, 'redirect type', redirectType); await this._saveSession(session); setTimeout(async () => { if (redirectType === 'recovery') { await this._notifyAllSubscribers('PASSWORD_RECOVERY', session); } else { await this._notifyAllSubscribers('SIGNED_IN', session); } }, 0); return { error: null }; } // no login attempt via callback url try to recover session from storage await this._recoverAndRefresh(); return { error: null }; } catch (error) { if ((0, errors_1.isAuthError)(error)) { return { error }; } return { error: new errors_1.AuthUnknownError('Unexpected error during initialization', error), }; } finally { await this._handleVisibilityChange(); this._debug('#_initialize()', 'end'); } } /** * Creates a new anonymous user. * * @returns A session where the is_anonymous claim in the access token JWT set to true */ async signInAnonymously(credentials) { var _a, _b, _c; try { const res = await (0, fetch_1$1._request)(this.fetch, 'POST', `${this.url}/signup`, { headers: this.headers, body: { data: (_b = (_a = credentials === null || credentials === void 0 ? void 0 : credentials.options) === null || _a === void 0 ? void 0 : _a.data) !== null && _b !== void 0 ? _b : {}, gotrue_meta_security: { captcha_token: (_c = credentials === null || credentials === void 0 ? void 0 : credentials.options) === null || _c === void 0 ? void 0 : _c.captchaToken }, }, xform: fetch_1$1._sessionResponse, }); const { data, error } = res; if (error || !data) { return { data: { user: null, session: null }, error: error }; } const session = data.session; const user = data.user; if (data.session) { await this._saveSession(data.session); await this._notifyAllSubscribers('SIGNED_IN', session); } return { data: { user, session }, error: null }; } catch (error) { if ((0, errors_1.isAuthError)(error)) { return { data: { user: null, session: null }, error }; } throw error; } } /** * Creates a new user. * * Be aware that if a user account exists in the system you may get back an * error message that attempts to hide this information from the user. * This method has support for PKCE via email signups. The PKCE flow cannot be used when autoconfirm is enabled. * * @returns A logged-in session if the server has "autoconfirm" ON * @returns A user if the server has "autoconfirm" OFF */ async signUp(credentials) { var _a, _b, _c; try { let res; if ('email' in credentials) { const { email, password, options } = credentials; let codeChallenge = null; let codeChallengeMethod = null; if (this.flowType === 'pkce') { ; [codeChallenge, codeChallengeMethod] = await (0, helpers_1$1.getCodeChallengeAndMethod)(this.storage, this.storageKey); } res = await (0, fetch_1$1._request)(this.fetch, 'POST', `${this.url}/signup`, { headers: this.headers, redirectTo: options === null || options === void 0 ? void 0 : options.emailRedirectTo, body: { email, password, data: (_a = options === null || options === void 0 ? void 0 : options.data) !== null && _a !== void 0 ? _a : {}, gotrue_meta_security: { captcha_token: options === null || options === void 0 ? void 0 : options.captchaToken }, code_challenge: codeChallenge, code_challenge_method: codeChallengeMethod, }, xform: fetch_1$1._sessionResponse, }); } else if ('phone' in credentials) { const { phone, password, options } = credentials; res = await (0, fetch_1$1._request)(this.fetch, 'POST', `${this.url}/signup`, { headers: this.headers, body: { phone, password, data: (_b = options === null || options === void 0 ? void 0 : options.data) !== null && _b !== void 0 ? _b : {}, channel: (_c = options === null || options === void 0 ? void 0 : options.channel) !== null && _c !== void 0 ? _c : 'sms', gotrue_meta_security: { captcha_token: options === null || options === void 0 ? void 0 : options.captchaToken }, }, xform: fetch_1$1._sessionResponse, }); } else { throw new errors_1.AuthInvalidCredentialsError('You must provide either an email or phone number and a password'); } const { data, error } = res; if (error || !data) { return { data: { user: null, session: null }, error: error }; } const session = data.session; const user = data.user; if (data.session) { await this._saveSession(data.session); await this._notifyAllSubscribers('SIGNED_IN', session); } return { data: { user, session }, error: null }; } catch (error) { if ((0, errors_1.isAuthError)(error)) { return { data: { user: null, session: null }, error }; } throw error; } } /** * Log in an existing user with an email and password or phone and password. * * Be aware that you may get back an error message that will not distinguish * between the cases where the account does not exist or that the * email/phone and password combination is wrong or that the account can only * be accessed via social login. */ async signInWithPassword(credentials) { try { let res; if ('email' in credentials) { const { email, password, options } = credentials; res = await (0, fetch_1$1._request)(this.fetch, 'POST', `${this.url}/token?grant_type=password`, { headers: this.headers, body: { email, password, gotrue_meta_security: { captcha_token: options === null || options === void 0 ? void 0 : options.captchaToken }, }, xform: fetch_1$1._sessionResponsePassword, }); } else if ('phone' in credentials) { const { phone, password, options } = credentials; res = await (0, fetch_1$1._request)(this.fetch, 'POST', `${this.url}/token?grant_type=password`, { headers: this.headers, body: { phone, password, gotrue_meta_security: { captcha_token: options === null || options === void 0 ? void 0 : options.captchaToken }, }, xform: fetch_1$1._sessionResponsePassword, }); } else { throw new errors_1.AuthInvalidCredentialsError('You must provide either an email or phone number and a password'); } const { data, error } = res; if (error) { return { data: { user: null, session: null }, error }; } else if (!data || !data.session || !data.user) { return { data: { user: null, session: null }, error: new errors_1.AuthInvalidTokenResponseError() }; } if (data.session) { await this._saveSession(data.session); await this._notifyAllSubscribers('SIGNED_IN', data.session); } return { data: Object.assign({ user: data.user, session: data.session }, (data.weak_password ? { weakPassword: data.weak_password } : null)), error, }; } catch (error) { if ((0, errors_1.isAuthError)(error)) { return { data: { user: null, session: null }, error }; } throw error; } } /** * Log in an existing user via a third-party provider. * This method supports the PKCE flow. */ async signInWithOAuth(credentials) { var _a, _b, _c, _d; return await this._handleProviderSignIn(credentials.provider, { redirectTo: (_a = credentials.options) === null || _a === void 0 ? void 0 : _a.redirectTo, scopes: (_b = credentials.options) === null || _b === void 0 ? void 0 : _b.scopes, queryParams: (_c = credentials.options) === null || _c === void 0 ? void 0 : _c.queryParams, skipBrowserRedirect: (_d = credentials.options) === null || _d === void 0 ? void 0 : _d.skipBrowserRedirect, }); } /** * Log in an existing user by exchanging an Auth Code issued during the PKCE flow. */ async exchangeCodeForSession(authCode) { await this.initializePromise; return this._acquireLock(-1, async () => { return this._exchangeCodeForSession(authCode); }); } async _exchangeCodeForSession(authCode) { const storageItem = await (0, helpers_1$1.getItemAsync)(this.storage, `${this.storageKey}-code-verifier`); const [codeVerifier, redirectType] = (storageItem !== null && storageItem !== void 0 ? storageItem : '').split('/'); try { const { data, error } = await (0, fetch_1$1._request)(this.fetch, 'POST', `${this.url}/token?grant_type=pkce`, { headers: this.headers, body: { auth_code: authCode, code_verifier: codeVerifier, }, xform: fetch_1$1._sessionResponse, }); await (0, helpers_1$1.removeItemAsync)(this.storage, `${this.storageKey}-code-verifier`); if (error) { throw error; } if (!data || !data.session || !data.user) { return { data: { user: null, session: null, redirectType: null }, error: new errors_1.AuthInvalidTokenResponseError(), }; } if (data.session) { await this._saveSession(data.session); await this._notifyAllSubscribers('SIGNED_IN', data.session); } return { data: Object.assign(Object.assign({}, data), { redirectType: redirectType !== null && redirectType !== void 0 ? redirectType : null }), error }; } catch (error) { if ((0, errors_1.isAuthError)(error)) { return { data: { user: null, session: null, redirectType: null }, error }; } throw error; } } /** * Allows signing in with an OIDC ID token. The authentication provider used * should be enabled and configured. */ async signInWithIdToken(credentials) { try { const { options, provider, token, access_token, nonce } = credentials; const res = await (0, fetch_1$1._request)(this.fetch, 'POST', `${this.url}/token?grant_type=id_token`, { headers: this.headers, body: { provider, id_token: token, access_token, nonce, gotrue_meta_security: { captcha_token: options === null || options === void 0 ? void 0 : options.captchaToken }, }, xform: fetch_1$1._sessionResponse, }); const { data, error } = res; if (error) { return { data: { user: null, session: null }, error }; } else if (!data || !data.session || !data.user) { return { data: { user: null, session: null }, error: new errors_1.AuthInvalidTokenResponseError(), }; } if (data.session) { await this._saveSession(data.session); await this._notifyAllSubscribers('SIGNED_IN', data.session); } return { data, error }; } catch (error) { if ((0, errors_1.isAuthError)(error)) { return { data: { user: null, session: null }, error }; } throw error; } } /** * Log in a user using magiclink or a one-time password (OTP). * * If the `{{ .ConfirmationURL }}` variable is specified in the email template, a magiclink will be sent. * If the `{{ .Token }}` variable is specified in the email template, an OTP will be sent. * If you're using phone sign-ins, only an OTP will be sent. You won't be able to send a magiclink for phone sign-ins. * * Be aware that you may get back an error message that will not distinguish * between the cases where the account does not exist or, that the account * can only be accessed via social login. * * Do note that you will need to configure a Whatsapp sender on Twilio * if you are using phone sign in with the 'whatsapp' channel. The whatsapp * channel is not supported on other providers * at this time. * This method supports PKCE when an email is passed. */ async signInWithOtp(credentials) { var _a, _b, _c, _d, _e; try { if ('email' in credentials) { const { email, options } = credentials; let codeChallenge = null; let codeChallengeMethod = null; if (this.flowType === 'pkce') { ; [codeChallenge, codeChallengeMethod] = await (0, helpers_1$1.getCodeChallengeAndMethod)(this.storage, this.storageKey); } const { error } = await (0, fetch_1$1._request)(this.fetch, 'POST', `${this.url}/otp`, { headers: this.headers, body: { email, data: (_a = options === null || options === void 0 ? void 0 : options.data) !== null && _a !== void 0 ? _a : {}, create_user: (_b = options === null || options === void 0 ? void 0 : options.shouldCreateUser) !== null && _b !== void 0 ? _b : true, gotrue_meta_security: { captcha_token: options === null || options === void 0 ? void 0 : options.captchaToken }, code_challenge: codeChallenge, code_challenge_method: codeChallengeMethod, }, redirectTo: options === null || options === void 0 ? void 0 : options.emailRedirectTo, }); return { data: { user: null, session: null }, error }; } if ('phone' in credentials) { const { phone, options } = credentials; const { data, error } = await (0, fetch_1$1._request)(this.fetch, 'POST', `${this.url}/otp`, { headers: this.headers, body: { phone, data: (_c = options === null || options === void 0 ? void 0 : options.data) !== null && _c !== void 0 ? _c : {}, create_user: (_d = options === null || options === void 0 ? void 0 : options.shouldCreateUser) !== null && _d !== void 0 ? _d : true, gotrue_meta_security: { captcha_token: options === null || options === void 0 ? void 0 : options.captchaToken }, channel: (_e = options === null || options === void 0 ? void 0 : options.channel) !== null && _e !== void 0 ? _e : 'sms', }, }); return { data: { user: null, session: null, messageId: data === null || data === void 0 ? void 0 : data.message_id }, error }; } throw new errors_1.AuthInvalidCredentialsError('You must provide either an email or phone number.'); } catch (error) { if ((0, errors_1.isAuthError)(error)) { return { data: { user: null, session: null }, error }; } throw error; } } /** * Log in a user given a User supplied OTP or TokenHash received through mobile or email. */ async verifyOtp(params) { var _a, _b; try { let redirectTo = undefined; let captchaToken = undefined; if ('options' in params) { redirectTo = (_a = params.options) === null || _a === void 0 ? void 0 : _a.redirectTo; captchaToken = (_b = params.options) === null || _b === void 0 ? void 0 : _b.captchaToken; } const { data, error } = await (0, fetch_1$1._request)(this.fetch, 'POST', `${this.url}/verify`, { headers: this.headers, body: Object.assign(Object.assign({}, params), { gotrue_meta_security: { captcha_token: captchaToken } }), redirectTo, xform: fetch_1$1._sessionResponse, }); if (error) { throw error; } if (!data) { throw new Error('An error occurred on token verification.'); } const session = data.session; const user = data.user; if (session === null || session === void 0 ? void 0 : session.access_token) { await this._saveSession(session); await this._notifyAllSubscribers(params.type == 'recovery' ? 'PASSWORD_RECOVERY' : 'SIGNED_IN', session); } return { data: { user, session }, error: null }; } catch (error) { if ((0, errors_1.isAuthError)(error)) { return { data: { user: null, session: null }, error }; } throw error; } } /** * Attempts a single-sign on using an enterprise Identity Provider. A * successful SSO attempt will redirect the current page to the identity * provider authorization page. The redirect URL is implementation and SSO * protocol specific. * * You can use it by providing a SSO domain. Typically you can extract this * domain by asking users for their email address. If this domain is * registered on the Auth instance the redirect will use that organization's * currently active SSO Identity Provider for the login. * * If you have built an organization-specific login page, you can use the * organization's SSO Identity Provider UUID directly instead. */ async signInWithSSO(params) { var _a, _b, _c; try { let codeChallenge = null; let codeChallengeMethod = null; if (this.flowType === 'pkce') { ; [codeChallenge, codeChallengeMethod] = await (0, helpers_1$1.getCodeChallengeAndMethod)(this.storage, this.storageKey); } return await (0, fetch_1$1._request)(this.fetch, 'POST', `${this.url}/sso`, { body: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, ('providerId' in params ? { provider_id: params.providerId } : null)), ('domain' in params ? { domain: params.domain } : null)), { redirect_to: (_b = (_a = params.options) === null || _a === void 0 ? void 0 : _a.redirectTo) !== null && _b !== void 0 ? _b : undefined }), (((_c = params === null || params === void 0 ? void 0 : params.options) === null || _c === void 0 ? void 0 : _c.captchaToken) ? { gotrue_meta_security: { captcha_token: params.options.captchaToken } } : null)), { skip_http_redirect: true, code_challenge: codeChallenge, code_challenge_method: codeChallengeMethod }), headers: this.headers, xform: fetch_1$1._ssoResponse, }); } catch (error) { if ((0, errors_1.isAuthError)(error)) { return { data: null, error }; } throw error; } } /** * Sends a reauthentication OTP to the user's email or phone number. * Requires the user to be signed-in. */ async reauthenticate() { await this.initializePromise; return await this._acquireLock(-1, async () => { return await this._reauthenticate(); }); } async _reauthenticate() { try { return await this._useSession(async (result) => { const { data: { session }, error: sessionError, } = result; if (sessionError) throw sessionError; if (!session) throw new errors_1.AuthSessionMissingError(); const { error } = await (0, fetch_1$1._request)(this.fetch, 'GET', `${this.url}/reauthenticate`, { headers: this.headers, jwt: session.access_token, }); return { data: { user: null, session: null }, error }; }); } catch (error) { if ((0, errors_1.isAuthError)(error)) { return { data: { user: null, session: null }, error }; } throw error; } } /** * Resends an existing signup confirmation email, email change email, SMS OTP or phone change OTP. */ async resend(credentials) { try { const endpoint = `${this.url}/resend`; if ('email' in credentials) { const { email, type, options } = credentials; const { error } = await (0, fetch_1$1._request)(this.fetch, 'POST', endpoint, { headers: this.headers, body: { email, type, gotrue_meta_security: { captcha_token: options === null || options === void 0 ? void 0 : options.captchaToken }, }, redirectTo: options === null || options === void 0 ? void 0 : options.emailRedirectTo, }); return { data: { user: null, session: null }, error }; } else if ('phone' in credentials) { const { phone, type, options } = credentials; const { data, error } = await (0, fetch_1$1._request)(this.fetch, 'POST', endpoint, { headers: this.headers, body: { phone, type, gotrue_meta_security: { captcha_token: options === null || options === void 0 ? void 0 : options.captchaToken }, }, }); return { data: { user: null, session: null, messageId: data === null || data === void 0 ? void 0 : data.message_id }, error }; } throw new errors_1.AuthInvalidCredentialsError('You must provide either an email or phone number and a type'); } catch (error) { if ((0, errors_1.isAuthError)(error)) { return { data: { user: null, session: null }, error }; } throw error; } } /** * Returns the session, refreshing it if necessary. * * The session returned can be null if the session is not detected which can happen in the event a user is not signed-in or has logged out. * * **IMPORTANT:** This method loads values directly from the storage attached * to the client. If that storage is based on request cookies for example, * the values in it may not be authentic and therefore it's strongly advised * against using this method and its results in such circumstances. A warning * will be emitted if this is detected. Use {@link #getUser()} instead. */ async getSession() { await this.initializePromise; const result = await this._acquireLock(-1, async () => { return this._useSession(async (result) => { return result; }); }); return result; } /** * Acquires a global lock based on the storage key. */ async _acquireLock(acquireTimeout, fn) { this._debug('#_acquireLock', 'begin', acquireTimeout); try { if (this.lockAcquired) { const last = this.pendingInLock.length ? this.pendingInLock[this.pendingInLock.length - 1] : Promise.resolve(); const result = (async () => { await last; return await fn(); })(); this.pendingInLock.push((async () => { try { await result; } catch (e) { // we just care if it finished } })()); return result; } return await this.lock(`lock:${this.storageKey}`, acquireTimeout, async () => { this._debug('#_acquireLock', 'lock acquired for storage key', this.storageKey); try { this.lockAcquired = true; const result = fn(); this.pendingInLock.push((async () => { try { await result; } catch (e) { // we just care if it finished } })()); await result; // keep draining the queue until there's nothing to wait on while (this.pendingInLock.length) { const waitOn = [...this.pendingInLock]; await Promise.all(waitOn); this.pendingInLock.splice(0, waitOn.length); } return await result; } finally { this._debug('#_acquireLock', 'lock released for storage key', this.storageKey); this.lockAcquired = false; } }); } finally { this._debug('#_acquireLock', 'end'); } } /** * Use instead of {@link #getSession} inside the library. It is * semantically usually what you want, as getting a session involves some * processing afterwards that requires only one client operating on the * session at once across multiple tabs or processes. */ async _useSession(fn) { this._debug('#_useSession', 'begin'); try { // the use of __loadSession here is the only correct use of the function! const result = await this.__loadSession(); return await fn(result); } finally { this._debug('#_useSession', 'end'); } } /** * NEVER USE DIRECTLY! * * Always use {@link #_useSession}. */ async __loadSession() { this._debug('#__loadSession()', 'begin'); if (!this.lockAcquired) { this._debug('#__loadSession()', 'used outside of an acquired lock!', new Error().stack); } try { let currentSession = null; const maybeSession = await (0, helpers_1$1.getItemAsync)(this.storage, this.storageKey); this._debug('#getSession()', 'session from storage', maybeSession); if (maybeSession !== null) { if (this._isValidSession(maybeSession)) { currentSession = maybeSession; } else { this._debug('#getSession()', 'session from storage is not valid'); await this._removeSession(); } } if (!currentSession) { return { data: { session: null }, error: null }; } // A session is considered expired before the access token _actually_ // expires. When the autoRefreshToken option is off (or when the tab is // in the background), very eager users of getSession() -- like // realtime-js -- might send a valid JWT which will expire by the time it // reaches the server. const hasExpired = currentSession.expires_at ? currentSession.expires_at * 1000 - Date.now() < constants_1$1.EXPIRY_MARGIN_MS : false; this._debug('#__loadSession()', `session has${hasExpired ? '' : ' not'} expired`, 'expires_at', currentSession.expires_at); if (!hasExpired) { if (this.storage.isServer) { let suppressWarning = this.suppressGetSessionWarning; const proxySession = new Proxy(currentSession, { get: (target, prop, receiver) => { if (!suppressWarning && prop === 'user') { // only show warning when the user object is being accessed from the server console.warn('Using the user object as returned from supabase.auth.getSession() or from some supabase.auth.onAuthStateChange() events could be insecure! This value comes directly from the storage medium (usually cookies on the server) and may not be authentic. Use supabase.auth.getUser() instead which authenticates the data by contacting the Supabase Auth server.'); suppressWarning = true; // keeps this proxy instance from logging additional warnings this.suppressGetSessionWarning = true; // keeps this client's future proxy instances from warning } return Reflect.get(target, prop, receiver); }, }); currentSession = proxySession; } return { data: { session: currentSession }, error: null }; } const { session, error } = await this._callRefreshToken(currentSession.refresh_token); if (error) { return { data: { session: null }, error }; } return { data: { session }, error: null }; } finally { this._debug('#__loadSession()', 'end'); } } /** * Gets the current user details if there is an existing session. This method * performs a network request to the Supabase Auth server, so the returned * value is authentic and can be used to base authorization rules on. * * @param jwt Takes in an optional access token JWT. If no JWT is provided, the JWT from the current session is used. */ async getUser(jwt) { if (jwt) { return await this._getUser(jwt); } await this.initializePromise; const result = await this._acquireLock(-1, async () => { return await this._getUser(); }); return result; } async _getUser(jwt) { try { if (jwt) { return await (0, fetch_1$1._request)(this.fetch, 'GET', `${this.url}/user`, { headers: this.headers, jwt: jwt, xform: fetch_1$1._userResponse, }); } return await this._useSession(async (result) => { var _a, _b, _c; const { data, error } = result; if (error) { throw error; } // returns an error if there is no access_token or custom authorization header if (!((_a = data.session) === null || _a === void 0 ? void 0 : _a.access_token) && !this.hasCustomAuthorizationHeader) { return { data: { user: null }, error: new errors_1.AuthSessionMissingError() }; } return await (0, fetch_1$1._request)(this.fetch, 'GET', `${this.url}/user`, { headers: this.headers, jwt: (_c = (_b = data.session) === null || _b === void 0 ? void 0 : _b.access_token) !== null && _c !== void 0 ? _c : undefined, xform: fetch_1$1._userResponse, }); }); } catch (error) { if ((0, errors_1.isAuthError)(error)) { if ((0, errors_1.isAuthSessionMissingError)(error)) { // JWT contains a `session_id` which does not correspond to an active // session in the database, indicating the user is signed out. await this._removeSession(); await (0, helpers_1$1.removeItemAsync)(this.storage, `${this.storageKey}-code-verifier`); } return { data: { user: null }, error }; } throw error; } } /** * Updates user data for a logged in user. */ async updateUser(attributes, options = {}) { await this.initializePromise; return await this._acquireLock(-1, async () => { return await this._updateUser(attributes, options); }); } async _updateUser(attributes, options = {}) { try { return await this._useSession(async (result) => { const { data: sessionData, error: sessionError } = result; if (sessionError) { throw sessionError; } if (!sessionData.session) { throw new errors_1.AuthSessionMissingError(); } const session = sessionData.session; let codeChallenge = null; let codeChallengeMethod = null; if (this.flowType === 'pkce' && attributes.email != null) { ; [codeChallenge, codeChallengeMethod] = await (0, helpers_1$1.getCodeChallengeAndMethod)(this.storage, this.storageKey); } const { data, error: userError } = await (0, fetch_1$1._request)(this.fetch, 'PUT', `${this.url}/user`, { headers: this.headers, redirectTo: options === null || options === void 0 ? void 0 : options.emailRedirectTo, body: Object.assign(Object.assign({}, attributes), { code_challenge: codeChallenge, code_challenge_method: codeChallengeMethod }), jwt: session.access_token, xform: fetch_1$1._userResponse, }); if (userError) throw userError; session.user = data.user; await this._saveSession(session); await this._notifyAllSubscribers('USER_UPDATED', session); return { data: { user: session.user }, error: null }; }); } catch (error) { if ((0, errors_1.isAuthError)(error)) { return { data: { user: null }, error }; } throw error; } } /** * Decodes a JWT (without performing any validation). */ _decodeJWT(jwt) { return (0, helpers_1$1.decodeJWTPayload)(jwt); } /** * Sets the session data from the current session. If the current session is expired, setSession will take care of refreshing it to obtain a new session. * If the refresh token or access token in the current session is invalid, an error will be thrown. * @param currentSession The current session that minimally contains an access token and refresh token. */ async setSession(currentSession) { await this.initializePromise; return await this._acquireLock(-1, async () => { return await this._setSession(currentSession); }); } async _setSession(currentSession) { try { if (!currentSession.access_token || !currentSession.refresh_token) { throw new errors_1.AuthSessionMissingError(); } const timeNow = Date.now() / 1000; let expiresAt = timeNow; let hasExpired = true; let session = null; const payload = (0, helpers_1$1.decodeJWTPayload)(currentSession.access_token); if (payload.exp) { expiresAt = payload.exp; hasExpired = expiresAt <= timeNow; } if (hasExpired) { const { session: refreshedSession, error } = await this._callRefreshToken(currentSession.refresh_token); if (error) { return { data: { user: null, session: null }, error: error }; } if (!refreshedSession) { return { data: { user: null, session: null }, error: null }; } session = refreshedSession; } else { const { data, error } = await this._getUser(currentSession.access_token); if (error) { throw error; } session = { access_token: currentSession.access_token, refresh_token: currentSession.refresh_token, user: data.user, token_type: 'bearer', expires_in: expiresAt - timeNow, expires_at: expiresAt, }; await this._saveSession(session); await this._notifyAllSubscribers('SIGNED_IN', session); } return { data: { user: session.user, session }, error: null }; } catch (error) { if ((0, errors_1.isAuthError)(error)) { return { data: { session: null, user: null }, error }; } throw error; } } /** * Returns a new session, regardless of expiry status. * Takes in an optional current session. If not passed in, then refreshSession() will attempt to retrieve it from getSession(). * If the current session's refresh token is invalid, an error will be thrown. * @param currentSession The current session. If passed in, it must contain a refresh token. */ async refreshSession(currentSession) { await this.initializePromise; return await this._acquireLock(-1, async () => { return await this._refreshSession(currentSession); }); } async _refreshSession(currentSession) { try { return await this._useSession(async (result) => { var _a; if (!currentSession) { const { data, error } = result; if (error) { throw error; } currentSession = (_a = data.session) !== null && _a !== void 0 ? _a : undefined; } if (!(currentSession === null || currentSession === void 0 ? void 0 : currentSession.refresh_token)) { throw new errors_1.AuthSessionMissingError(); } const { session, error } = await this._callRefreshToken(currentSession.refresh_token); if (error) { return { data: { user: null, session: null }, error: error }; } if (!session) { return { data: { user: null, session: null }, error: null }; } return { data: { user: session.user, session }, error: null }; }); } catch (error) { if ((0, errors_1.isAuthError)(error)) { return { data: { user: null, session: null }, error }; } throw error; } } /** * Gets the session data from a URL string */ async _getSessionFromURL(params, callbackUrlType) { try { if (!(0, helpers_1$1.isBrowser)()) throw new errors_1.AuthImplicitGrantRedirectError('No browser detected.'); // If there's an error in the URL, it doesn't matter what flow it is, we just return the error. if (params.error || params.error_description || params.error_code) { // The error class returned implies that the redirect is from an implicit grant flow // but it could also be from a redirect error from a PKCE flow. throw new errors_1.AuthImplicitGrantRedirectError(params.error_description || 'Error in URL with unspecified error_description', { error: params.error || 'unspecified_error', code: params.error_code || 'unspecified_code', }); } // Checks for mismatches between the flowType initialised in the client and the URL parameters switch (callbackUrlType) { case 'implicit': if (this.flowType === 'pkce') { throw new errors_1.AuthPKCEGrantCodeExchangeError('Not a valid PKCE flow url.'); } break; case 'pkce': if (this.flowType === 'implicit') { throw new errors_1.AuthImplicitGrantRedirectError('Not a valid implicit grant flow url.'); } break; default: // there's no mismatch so we continue } // Since this is a redirect for PKCE, we attempt to retrieve the code from the URL for the code exchange if (callbackUrlType === 'pkce') { this._debug('#_initialize()', 'begin', 'is PKCE flow', true); if (!params.code) throw new errors_1.AuthPKCEGrantCodeExchangeError('No code detected.'); const { data, error } = await this._exchangeCodeForSession(params.code); if (error) throw error; const url = new URL(window.location.href); url.searchParams.delete('code'); window.history.replaceState(window.history.state, '', url.toString()); return { data: { session: data.session, redirectType: null }, error: null }; } const { provider_token, provider_refresh_token, access_token, refresh_token, expires_in, expires_at, token_type, } = params; if (!access_token || !expires_in || !refresh_token || !token_type) { throw new errors_1.AuthImplicitGrantRedirectError('No session defined in URL'); } const timeNow = Math.round(Date.now() / 1000); const expiresIn = parseInt(expires_in); let expiresAt = timeNow + expiresIn; if (expires_at) { expiresAt = parseInt(expires_at); } const actuallyExpiresIn = expiresAt - timeNow; if (actuallyExpiresIn * 1000 <= constants_1$1.AUTO_REFRESH_TICK_DURATION_MS) { console.warn(`@supabase/gotrue-js: Session as retrieved from URL expires in ${actuallyExpiresIn}s, should have been closer to ${expiresIn}s`); } const issuedAt = expiresAt - expiresIn; if (timeNow - issuedAt >= 120) { console.warn('@supabase/gotrue-js: Session as retrieved from URL was issued over 120s ago, URL could be stale', issuedAt, expiresAt, timeNow); } else if (timeNow - issuedAt < 0) { console.warn('@supabase/gotrue-js: Session as retrieved from URL was issued in the future? Check the device clock for skew', issuedAt, expiresAt, timeNow); } const { data, error } = await this._getUser(access_token); if (error) throw error; const session = { provider_token, provider_refresh_token, access_token, expires_in: expiresIn, expires_at: expiresAt, refresh_token, token_type, user: data.user, }; // Remove tokens from URL window.location.hash = ''; this._debug('#_getSessionFromURL()', 'clearing window.location.hash'); return { data: { session, redirectType: params.type }, error: null }; } catch (error) { if ((0, errors_1.isAuthError)(error)) { return { data: { session: null, redirectType: null }, error }; } throw error; } } /** * Checks if the current URL contains parameters given by an implicit oauth grant flow (https://www.rfc-editor.org/rfc/rfc6749.html#section-4.2) */ _isImplicitGrantCallback(params) { return Boolean(params.access_token || params.error_description); } /** * Checks if the current URL and backing storage contain parameters given by a PKCE flow */ async _isPKCECallback(params) { const currentStorageContent = await (0, helpers_1$1.getItemAsync)(this.storage, `${this.storageKey}-code-verifier`); return !!(params.code && currentStorageContent); } /** * Inside a browser context, `signOut()` will remove the logged in user from the browser session and log them out - removing all items from localstorage and then trigger a `"SIGNED_OUT"` event. * * For server-side management, you can revoke all refresh tokens for a user by passing a user's JWT through to `auth.api.signOut(JWT: string)`. * There is no way to revoke a user's access token jwt until it expires. It is recommended to set a shorter expiry on the jwt for this reason. * * If using `others` scope, no `SIGNED_OUT` event is fired! */ async signOut(options = { scope: 'global' }) { await this.initializePromise; return await this._acquireLock(-1, async () => { return await this._signOut(options); }); } async _signOut({ scope } = { scope: 'global' }) { return await this._useSession(async (result) => { var _a; const { data, error: sessionError } = result; if (sessionError) { return { error: sessionError }; } const accessToken = (_a = data.session) === null || _a === void 0 ? void 0 : _a.access_token; if (accessToken) { const { error } = await this.admin.signOut(accessToken, scope); if (error) { // ignore 404s since user might not exist anymore // ignore 401s since an invalid or expired JWT should sign out the current session if (!((0, errors_1.isAuthApiError)(error) && (error.status === 404 || error.status === 401 || error.status === 403))) { return { error }; } } } if (scope !== 'others') { await this._removeSession(); await (0, helpers_1$1.removeItemAsync)(this.storage, `${this.storageKey}-code-verifier`); } return { error: null }; }); } /** * Receive a notification every time an auth event happens. * @param callback A callback function to be invoked when an auth event happens. */ onAuthStateChange(callback) { const id = (0, helpers_1$1.uuid)(); const subscription = { id, callback, unsubscribe: () => { this._debug('#unsubscribe()', 'state change callback with id removed', id); this.stateChangeEmitters.delete(id); }, }; this._debug('#onAuthStateChange()', 'registered callback with id', id); this.stateChangeEmitters.set(id, subscription); (async () => { await this.initializePromise; await this._acquireLock(-1, async () => { this._emitInitialSession(id); }); })(); return { data: { subscription } }; } async _emitInitialSession(id) { return await this._useSession(async (result) => { var _a, _b; try { const { data: { session }, error, } = result; if (error) throw error; await ((_a = this.stateChangeEmitters.get(id)) === null || _a === void 0 ? void 0 : _a.callback('INITIAL_SESSION', session)); this._debug('INITIAL_SESSION', 'callback id', id, 'session', session); } catch (err) { await ((_b = this.stateChangeEmitters.get(id)) === null || _b === void 0 ? void 0 : _b.callback('INITIAL_SESSION', null)); this._debug('INITIAL_SESSION', 'callback id', id, 'error', err); console.error(err); } }); } /** * Sends a password reset request to an email address. This method supports the PKCE flow. * * @param email The email address of the user. * @param options.redirectTo The URL to send the user to after they click the password reset link. * @param options.captchaToken Verification token received when the user completes the captcha on the site. */ async resetPasswordForEmail(email, options = {}) { let codeChallenge = null; let codeChallengeMethod = null; if (this.flowType === 'pkce') { [codeChallenge, codeChallengeMethod] = await (0, helpers_1$1.getCodeChallengeAndMethod)(this.storage, this.storageKey, true // isPasswordRecovery ); } try { return await (0, fetch_1$1._request)(this.fetch, 'POST', `${this.url}/recover`, { body: { email, code_challenge: codeChallenge, code_challenge_method: codeChallengeMethod, gotrue_meta_security: { captcha_token: options.captchaToken }, }, headers: this.headers, redirectTo: options.redirectTo, }); } catch (error) { if ((0, errors_1.isAuthError)(error)) { return { data: null, error }; } throw error; } } /** * Gets all the identities linked to a user. */ async getUserIdentities() { var _a; try { const { data, error } = await this.getUser(); if (error) throw error; return { data: { identities: (_a = data.user.identities) !== null && _a !== void 0 ? _a : [] }, error: null }; } catch (error) { if ((0, errors_1.isAuthError)(error)) { return { data: null, error }; } throw error; } } /** * Links an oauth identity to an existing user. * This method supports the PKCE flow. */ async linkIdentity(credentials) { var _a; try { const { data, error } = await this._useSession(async (result) => { var _a, _b, _c, _d, _e; const { data, error } = result; if (error) throw error; const url = await this._getUrlForProvider(`${this.url}/user/identities/authorize`, credentials.provider, { redirectTo: (_a = credentials.options) === null || _a === void 0 ? void 0 : _a.redirectTo, scopes: (_b = credentials.options) === null || _b === void 0 ? void 0 : _b.scopes, queryParams: (_c = credentials.options) === null || _c === void 0 ? void 0 : _c.queryParams, skipBrowserRedirect: true, }); return await (0, fetch_1$1._request)(this.fetch, 'GET', url, { headers: this.headers, jwt: (_e = (_d = data.session) === null || _d === void 0 ? void 0 : _d.access_token) !== null && _e !== void 0 ? _e : undefined, }); }); if (error) throw error; if ((0, helpers_1$1.isBrowser)() && !((_a = credentials.options) === null || _a === void 0 ? void 0 : _a.skipBrowserRedirect)) { window.location.assign(data === null || data === void 0 ? void 0 : data.url); } return { data: { provider: credentials.provider, url: data === null || data === void 0 ? void 0 : data.url }, error: null }; } catch (error) { if ((0, errors_1.isAuthError)(error)) { return { data: { provider: credentials.provider, url: null }, error }; } throw error; } } /** * Unlinks an identity from a user by deleting it. The user will no longer be able to sign in with that identity once it's unlinked. */ async unlinkIdentity(identity) { try { return await this._useSession(async (result) => { var _a, _b; const { data, error } = result; if (error) { throw error; } return await (0, fetch_1$1._request)(this.fetch, 'DELETE', `${this.url}/user/identities/${identity.identity_id}`, { headers: this.headers, jwt: (_b = (_a = data.session) === null || _a === void 0 ? void 0 : _a.access_token) !== null && _b !== void 0 ? _b : undefined, }); }); } catch (error) { if ((0, errors_1.isAuthError)(error)) { return { data: null, error }; } throw error; } } /** * Generates a new JWT. * @param refreshToken A valid refresh token that was returned on login. */ async _refreshAccessToken(refreshToken) { const debugName = `#_refreshAccessToken(${refreshToken.substring(0, 5)}...)`; this._debug(debugName, 'begin'); try { const startedAt = Date.now(); // will attempt to refresh the token with exponential backoff return await (0, helpers_1$1.retryable)(async (attempt) => { if (attempt > 0) { await (0, helpers_1$1.sleep)(200 * Math.pow(2, attempt - 1)); // 200, 400, 800, ... } this._debug(debugName, 'refreshing attempt', attempt); return await (0, fetch_1$1._request)(this.fetch, 'POST', `${this.url}/token?grant_type=refresh_token`, { body: { refresh_token: refreshToken }, headers: this.headers, xform: fetch_1$1._sessionResponse, }); }, (attempt, error) => { const nextBackOffInterval = 200 * Math.pow(2, attempt); return (error && (0, errors_1.isAuthRetryableFetchError)(error) && // retryable only if the request can be sent before the backoff overflows the tick duration Date.now() + nextBackOffInterval - startedAt < constants_1$1.AUTO_REFRESH_TICK_DURATION_MS); }); } catch (error) { this._debug(debugName, 'error', error); if ((0, errors_1.isAuthError)(error)) { return { data: { session: null, user: null }, error }; } throw error; } finally { this._debug(debugName, 'end'); } } _isValidSession(maybeSession) { const isValidSession = typeof maybeSession === 'object' && maybeSession !== null && 'access_token' in maybeSession && 'refresh_token' in maybeSession && 'expires_at' in maybeSession; return isValidSession; } async _handleProviderSignIn(provider, options) { const url = await this._getUrlForProvider(`${this.url}/authorize`, provider, { redirectTo: options.redirectTo, scopes: options.scopes, queryParams: options.queryParams, }); this._debug('#_handleProviderSignIn()', 'provider', provider, 'options', options, 'url', url); // try to open on the browser if ((0, helpers_1$1.isBrowser)() && !options.skipBrowserRedirect) { window.location.assign(url); } return { data: { provider, url }, error: null }; } /** * Recovers the session from LocalStorage and refreshes the token * Note: this method is async to accommodate for AsyncStorage e.g. in React native. */ async _recoverAndRefresh() { var _a; const debugName = '#_recoverAndRefresh()'; this._debug(debugName, 'begin'); try { const currentSession = await (0, helpers_1$1.getItemAsync)(this.storage, this.storageKey); this._debug(debugName, 'session from storage', currentSession); if (!this._isValidSession(currentSession)) { this._debug(debugName, 'session is not valid'); if (currentSession !== null) { await this._removeSession(); } return; } const expiresWithMargin = ((_a = currentSession.expires_at) !== null && _a !== void 0 ? _a : Infinity) * 1000 - Date.now() < constants_1$1.EXPIRY_MARGIN_MS; this._debug(debugName, `session has${expiresWithMargin ? '' : ' not'} expired with margin of ${constants_1$1.EXPIRY_MARGIN_MS}s`); if (expiresWithMargin) { if (this.autoRefreshToken && currentSession.refresh_token) { const { error } = await this._callRefreshToken(currentSession.refresh_token); if (error) { console.error(error); if (!(0, errors_1.isAuthRetryableFetchError)(error)) { this._debug(debugName, 'refresh failed with a non-retryable error, removing the session', error); await this._removeSession(); } } } } else { // no need to persist currentSession again, as we just loaded it from // local storage; persisting it again may overwrite a value saved by // another client with access to the same local storage await this._notifyAllSubscribers('SIGNED_IN', currentSession); } } catch (err) { this._debug(debugName, 'error', err); console.error(err); return; } finally { this._debug(debugName, 'end'); } } async _callRefreshToken(refreshToken) { var _a, _b; if (!refreshToken) { throw new errors_1.AuthSessionMissingError(); } // refreshing is already in progress if (this.refreshingDeferred) { return this.refreshingDeferred.promise; } const debugName = `#_callRefreshToken(${refreshToken.substring(0, 5)}...)`; this._debug(debugName, 'begin'); try { this.refreshingDeferred = new helpers_1$1.Deferred(); const { data, error } = await this._refreshAccessToken(refreshToken); if (error) throw error; if (!data.session) throw new errors_1.AuthSessionMissingError(); await this._saveSession(data.session); await this._notifyAllSubscribers('TOKEN_REFRESHED', data.session); const result = { session: data.session, error: null }; this.refreshingDeferred.resolve(result); return result; } catch (error) { this._debug(debugName, 'error', error); if ((0, errors_1.isAuthError)(error)) { const result = { session: null, error }; if (!(0, errors_1.isAuthRetryableFetchError)(error)) { await this._removeSession(); } (_a = this.refreshingDeferred) === null || _a === void 0 ? void 0 : _a.resolve(result); return result; } (_b = this.refreshingDeferred) === null || _b === void 0 ? void 0 : _b.reject(error); throw error; } finally { this.refreshingDeferred = null; this._debug(debugName, 'end'); } } async _notifyAllSubscribers(event, session, broadcast = true) { const debugName = `#_notifyAllSubscribers(${event})`; this._debug(debugName, 'begin', session, `broadcast = ${broadcast}`); try { if (this.broadcastChannel && broadcast) { this.broadcastChannel.postMessage({ event, session }); } const errors = []; const promises = Array.from(this.stateChangeEmitters.values()).map(async (x) => { try { await x.callback(event, session); } catch (e) { errors.push(e); } }); await Promise.all(promises); if (errors.length > 0) { for (let i = 0; i < errors.length; i += 1) { console.error(errors[i]); } throw errors[0]; } } finally { this._debug(debugName, 'end'); } } /** * set currentSession and currentUser * process to _startAutoRefreshToken if possible */ async _saveSession(session) { this._debug('#_saveSession()', session); // _saveSession is always called whenever a new session has been acquired // so we can safely suppress the warning returned by future getSession calls this.suppressGetSessionWarning = true; await (0, helpers_1$1.setItemAsync)(this.storage, this.storageKey, session); } async _removeSession() { this._debug('#_removeSession()'); await (0, helpers_1$1.removeItemAsync)(this.storage, this.storageKey); await this._notifyAllSubscribers('SIGNED_OUT', null); } /** * Removes any registered visibilitychange callback. * * {@see #startAutoRefresh} * {@see #stopAutoRefresh} */ _removeVisibilityChangedCallback() { this._debug('#_removeVisibilityChangedCallback()'); const callback = this.visibilityChangedCallback; this.visibilityChangedCallback = null; try { if (callback && (0, helpers_1$1.isBrowser)() && (window === null || window === void 0 ? void 0 : window.removeEventListener)) { window.removeEventListener('visibilitychange', callback); } } catch (e) { console.error('removing visibilitychange callback failed', e); } } /** * This is the private implementation of {@link #startAutoRefresh}. Use this * within the library. */ async _startAutoRefresh() { await this._stopAutoRefresh(); this._debug('#_startAutoRefresh()'); const ticker = setInterval(() => this._autoRefreshTokenTick(), constants_1$1.AUTO_REFRESH_TICK_DURATION_MS); this.autoRefreshTicker = ticker; if (ticker && typeof ticker === 'object' && typeof ticker.unref === 'function') { // ticker is a NodeJS Timeout object that has an `unref` method // https://nodejs.org/api/timers.html#timeoutunref // When auto refresh is used in NodeJS (like for testing) the // `setInterval` is preventing the process from being marked as // finished and tests run endlessly. This can be prevented by calling // `unref()` on the returned object. ticker.unref(); // @ts-expect-error TS has no context of Deno } else if (typeof Deno !== 'undefined' && typeof Deno.unrefTimer === 'function') { // similar like for NodeJS, but with the Deno API // https://deno.land/api@latest?unstable&s=Deno.unrefTimer // @ts-expect-error TS has no context of Deno Deno.unrefTimer(ticker); } // run the tick immediately, but in the next pass of the event loop so that // #_initialize can be allowed to complete without recursively waiting on // itself setTimeout(async () => { await this.initializePromise; await this._autoRefreshTokenTick(); }, 0); } /** * This is the private implementation of {@link #stopAutoRefresh}. Use this * within the library. */ async _stopAutoRefresh() { this._debug('#_stopAutoRefresh()'); const ticker = this.autoRefreshTicker; this.autoRefreshTicker = null; if (ticker) { clearInterval(ticker); } } /** * Starts an auto-refresh process in the background. The session is checked * every few seconds. Close to the time of expiration a process is started to * refresh the session. If refreshing fails it will be retried for as long as * necessary. * * If you set the {@link GoTrueClientOptions#autoRefreshToken} you don't need * to call this function, it will be called for you. * * On browsers the refresh process works only when the tab/window is in the * foreground to conserve resources as well as prevent race conditions and * flooding auth with requests. If you call this method any managed * visibility change callback will be removed and you must manage visibility * changes on your own. * * On non-browser platforms the refresh process works *continuously* in the * background, which may not be desirable. You should hook into your * platform's foreground indication mechanism and call these methods * appropriately to conserve resources. * * {@see #stopAutoRefresh} */ async startAutoRefresh() { this._removeVisibilityChangedCallback(); await this._startAutoRefresh(); } /** * Stops an active auto refresh process running in the background (if any). * * If you call this method any managed visibility change callback will be * removed and you must manage visibility changes on your own. * * See {@link #startAutoRefresh} for more details. */ async stopAutoRefresh() { this._removeVisibilityChangedCallback(); await this._stopAutoRefresh(); } /** * Runs the auto refresh token tick. */ async _autoRefreshTokenTick() { this._debug('#_autoRefreshTokenTick()', 'begin'); try { await this._acquireLock(0, async () => { try { const now = Date.now(); try { return await this._useSession(async (result) => { const { data: { session }, } = result; if (!session || !session.refresh_token || !session.expires_at) { this._debug('#_autoRefreshTokenTick()', 'no session'); return; } // session will expire in this many ticks (or has already expired if <= 0) const expiresInTicks = Math.floor((session.expires_at * 1000 - now) / constants_1$1.AUTO_REFRESH_TICK_DURATION_MS); this._debug('#_autoRefreshTokenTick()', `access token expires in ${expiresInTicks} ticks, a tick lasts ${constants_1$1.AUTO_REFRESH_TICK_DURATION_MS}ms, refresh threshold is ${constants_1$1.AUTO_REFRESH_TICK_THRESHOLD} ticks`); if (expiresInTicks <= constants_1$1.AUTO_REFRESH_TICK_THRESHOLD) { await this._callRefreshToken(session.refresh_token); } }); } catch (e) { console.error('Auto refresh tick failed with error. This is likely a transient error.', e); } } finally { this._debug('#_autoRefreshTokenTick()', 'end'); } }); } catch (e) { if (e.isAcquireTimeout || e instanceof locks_1.LockAcquireTimeoutError) { this._debug('auto refresh token tick lock not available'); } else { throw e; } } } /** * Registers callbacks on the browser / platform, which in-turn run * algorithms when the browser window/tab are in foreground. On non-browser * platforms it assumes always foreground. */ async _handleVisibilityChange() { this._debug('#_handleVisibilityChange()'); if (!(0, helpers_1$1.isBrowser)() || !(window === null || window === void 0 ? void 0 : window.addEventListener)) { if (this.autoRefreshToken) { // in non-browser environments the refresh token ticker runs always this.startAutoRefresh(); } return false; } try { this.visibilityChangedCallback = async () => await this._onVisibilityChanged(false); window === null || window === void 0 ? void 0 : window.addEventListener('visibilitychange', this.visibilityChangedCallback); // now immediately call the visbility changed callback to setup with the // current visbility state await this._onVisibilityChanged(true); // initial call } catch (error) { console.error('_handleVisibilityChange', error); } } /** * Callback registered with `window.addEventListener('visibilitychange')`. */ async _onVisibilityChanged(calledFromInitialize) { const methodName = `#_onVisibilityChanged(${calledFromInitialize})`; this._debug(methodName, 'visibilityState', document.visibilityState); if (document.visibilityState === 'visible') { if (this.autoRefreshToken) { // in browser environments the refresh token ticker runs only on focused tabs // which prevents race conditions this._startAutoRefresh(); } if (!calledFromInitialize) { // called when the visibility has changed, i.e. the browser // transitioned from hidden -> visible so we need to see if the session // should be recovered immediately... but to do that we need to acquire // the lock first asynchronously await this.initializePromise; await this._acquireLock(-1, async () => { if (document.visibilityState !== 'visible') { this._debug(methodName, 'acquired the lock to recover the session, but the browser visibilityState is no longer visible, aborting'); // visibility has changed while waiting for the lock, abort return; } // recover the session await this._recoverAndRefresh(); }); } } else if (document.visibilityState === 'hidden') { if (this.autoRefreshToken) { this._stopAutoRefresh(); } } } /** * Generates the relevant login URL for a third-party provider. * @param options.redirectTo A URL or mobile address to send the user to after they are confirmed. * @param options.scopes A space-separated list of scopes granted to the OAuth application. * @param options.queryParams An object of key-value pairs containing query parameters granted to the OAuth application. */ async _getUrlForProvider(url, provider, options) { const urlParams = [`provider=${encodeURIComponent(provider)}`]; if (options === null || options === void 0 ? void 0 : options.redirectTo) { urlParams.push(`redirect_to=${encodeURIComponent(options.redirectTo)}`); } if (options === null || options === void 0 ? void 0 : options.scopes) { urlParams.push(`scopes=${encodeURIComponent(options.scopes)}`); } if (this.flowType === 'pkce') { const [codeChallenge, codeChallengeMethod] = await (0, helpers_1$1.getCodeChallengeAndMethod)(this.storage, this.storageKey); const flowParams = new URLSearchParams({ code_challenge: `${encodeURIComponent(codeChallenge)}`, code_challenge_method: `${encodeURIComponent(codeChallengeMethod)}`, }); urlParams.push(flowParams.toString()); } if (options === null || options === void 0 ? void 0 : options.queryParams) { const query = new URLSearchParams(options.queryParams); urlParams.push(query.toString()); } if (options === null || options === void 0 ? void 0 : options.skipBrowserRedirect) { urlParams.push(`skip_http_redirect=${options.skipBrowserRedirect}`); } return `${url}?${urlParams.join('&')}`; } async _unenroll(params) { try { return await this._useSession(async (result) => { var _a; const { data: sessionData, error: sessionError } = result; if (sessionError) { return { data: null, error: sessionError }; } return await (0, fetch_1$1._request)(this.fetch, 'DELETE', `${this.url}/factors/${params.factorId}`, { headers: this.headers, jwt: (_a = sessionData === null || sessionData === void 0 ? void 0 : sessionData.session) === null || _a === void 0 ? void 0 : _a.access_token, }); }); } catch (error) { if ((0, errors_1.isAuthError)(error)) { return { data: null, error }; } throw error; } } async _enroll(params) { try { return await this._useSession(async (result) => { var _a, _b; const { data: sessionData, error: sessionError } = result; if (sessionError) { return { data: null, error: sessionError }; } const body = Object.assign({ friendly_name: params.friendlyName, factor_type: params.factorType }, (params.factorType === 'phone' ? { phone: params.phone } : { issuer: params.issuer })); const { data, error } = await (0, fetch_1$1._request)(this.fetch, 'POST', `${this.url}/factors`, { body, headers: this.headers, jwt: (_a = sessionData === null || sessionData === void 0 ? void 0 : sessionData.session) === null || _a === void 0 ? void 0 : _a.access_token, }); if (error) { return { data: null, error }; } if (params.factorType === 'totp' && ((_b = data === null || data === void 0 ? void 0 : data.totp) === null || _b === void 0 ? void 0 : _b.qr_code)) { data.totp.qr_code = `data:image/svg+xml;utf-8,${data.totp.qr_code}`; } return { data, error: null }; }); } catch (error) { if ((0, errors_1.isAuthError)(error)) { return { data: null, error }; } throw error; } } /** * {@see GoTrueMFAApi#verify} */ async _verify(params) { return this._acquireLock(-1, async () => { try { return await this._useSession(async (result) => { var _a; const { data: sessionData, error: sessionError } = result; if (sessionError) { return { data: null, error: sessionError }; } const { data, error } = await (0, fetch_1$1._request)(this.fetch, 'POST', `${this.url}/factors/${params.factorId}/verify`, { body: { code: params.code, challenge_id: params.challengeId }, headers: this.headers, jwt: (_a = sessionData === null || sessionData === void 0 ? void 0 : sessionData.session) === null || _a === void 0 ? void 0 : _a.access_token, }); if (error) { return { data: null, error }; } await this._saveSession(Object.assign({ expires_at: Math.round(Date.now() / 1000) + data.expires_in }, data)); await this._notifyAllSubscribers('MFA_CHALLENGE_VERIFIED', data); return { data, error }; }); } catch (error) { if ((0, errors_1.isAuthError)(error)) { return { data: null, error }; } throw error; } }); } /** * {@see GoTrueMFAApi#challenge} */ async _challenge(params) { return this._acquireLock(-1, async () => { try { return await this._useSession(async (result) => { var _a; const { data: sessionData, error: sessionError } = result; if (sessionError) { return { data: null, error: sessionError }; } return await (0, fetch_1$1._request)(this.fetch, 'POST', `${this.url}/factors/${params.factorId}/challenge`, { body: { channel: params.channel }, headers: this.headers, jwt: (_a = sessionData === null || sessionData === void 0 ? void 0 : sessionData.session) === null || _a === void 0 ? void 0 : _a.access_token, }); }); } catch (error) { if ((0, errors_1.isAuthError)(error)) { return { data: null, error }; } throw error; } }); } /** * {@see GoTrueMFAApi#challengeAndVerify} */ async _challengeAndVerify(params) { // both _challenge and _verify independently acquire the lock, so no need // to acquire it here const { data: challengeData, error: challengeError } = await this._challenge({ factorId: params.factorId, }); if (challengeError) { return { data: null, error: challengeError }; } return await this._verify({ factorId: params.factorId, challengeId: challengeData.id, code: params.code, }); } /** * {@see GoTrueMFAApi#listFactors} */ async _listFactors() { // use #getUser instead of #_getUser as the former acquires a lock const { data: { user }, error: userError, } = await this.getUser(); if (userError) { return { data: null, error: userError }; } const factors = (user === null || user === void 0 ? void 0 : user.factors) || []; const totp = factors.filter((factor) => factor.factor_type === 'totp' && factor.status === 'verified'); const phone = factors.filter((factor) => factor.factor_type === 'phone' && factor.status === 'verified'); return { data: { all: factors, totp, phone, }, error: null, }; } /** * {@see GoTrueMFAApi#getAuthenticatorAssuranceLevel} */ async _getAuthenticatorAssuranceLevel() { return this._acquireLock(-1, async () => { return await this._useSession(async (result) => { var _a, _b; const { data: { session }, error: sessionError, } = result; if (sessionError) { return { data: null, error: sessionError }; } if (!session) { return { data: { currentLevel: null, nextLevel: null, currentAuthenticationMethods: [] }, error: null, }; } const payload = this._decodeJWT(session.access_token); let currentLevel = null; if (payload.aal) { currentLevel = payload.aal; } let nextLevel = currentLevel; const verifiedFactors = (_b = (_a = session.user.factors) === null || _a === void 0 ? void 0 : _a.filter((factor) => factor.status === 'verified')) !== null && _b !== void 0 ? _b : []; if (verifiedFactors.length > 0) { nextLevel = 'aal2'; } const currentAuthenticationMethods = payload.amr || []; return { data: { currentLevel, nextLevel, currentAuthenticationMethods }, error: null }; }); }); } } GoTrueClient$1.default = GoTrueClient; GoTrueClient.nextInstanceID = 0; var AuthAdminApi$1 = {}; var __importDefault$2 = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(AuthAdminApi$1, "__esModule", { value: true }); const GoTrueAdminApi_1 = __importDefault$2(GoTrueAdminApi$1); const AuthAdminApi = GoTrueAdminApi_1.default; AuthAdminApi$1.default = AuthAdminApi; var AuthClient$1 = {}; var __importDefault$1 = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(AuthClient$1, "__esModule", { value: true }); const GoTrueClient_1 = __importDefault$1(GoTrueClient$1); const AuthClient = GoTrueClient_1.default; AuthClient$1.default = AuthClient; var types = {}; Object.defineProperty(types, "__esModule", { value: true }); (function (exports) { var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __exportStar = (commonjsGlobal && commonjsGlobal.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; var __importDefault = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.lockInternals = exports.NavigatorLockAcquireTimeoutError = exports.navigatorLock = exports.AuthClient = exports.AuthAdminApi = exports.GoTrueClient = exports.GoTrueAdminApi = void 0; const GoTrueAdminApi_1 = __importDefault(GoTrueAdminApi$1); exports.GoTrueAdminApi = GoTrueAdminApi_1.default; const GoTrueClient_1 = __importDefault(GoTrueClient$1); exports.GoTrueClient = GoTrueClient_1.default; const AuthAdminApi_1 = __importDefault(AuthAdminApi$1); exports.AuthAdminApi = AuthAdminApi_1.default; const AuthClient_1 = __importDefault(AuthClient$1); exports.AuthClient = AuthClient_1.default; __exportStar(types, exports); __exportStar(errors, exports); var locks_1 = locks; Object.defineProperty(exports, "navigatorLock", { enumerable: true, get: function () { return locks_1.navigatorLock; } }); Object.defineProperty(exports, "NavigatorLockAcquireTimeoutError", { enumerable: true, get: function () { return locks_1.NavigatorLockAcquireTimeoutError; } }); Object.defineProperty(exports, "lockInternals", { enumerable: true, get: function () { return locks_1.internals; } }); } (main)); Object.defineProperty(SupabaseAuthClient$1, "__esModule", { value: true }); SupabaseAuthClient$1.SupabaseAuthClient = void 0; const auth_js_1 = main; class SupabaseAuthClient extends auth_js_1.AuthClient { constructor(options) { super(options); } } SupabaseAuthClient$1.SupabaseAuthClient = SupabaseAuthClient; var __awaiter$2 = (commonjsGlobal && commonjsGlobal.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(SupabaseClient$1, "__esModule", { value: true }); const functions_js_1 = main$3; const postgrest_js_1 = cjs; const realtime_js_1 = main$2; const storage_js_1 = main$1; const constants_1 = constants$2; const fetch_1 = fetch$2; const helpers_1 = helpers$1; const SupabaseAuthClient_1 = SupabaseAuthClient$1; /** * Supabase Client. * * An isomorphic Javascript client for interacting with Postgres. */ class SupabaseClient { /** * Create a new client for use in the browser. * @param supabaseUrl The unique Supabase URL which is supplied when you create a new project in your project dashboard. * @param supabaseKey The unique Supabase Key which is supplied when you create a new project in your project dashboard. * @param options.db.schema You can switch in between schemas. The schema needs to be on the list of exposed schemas inside Supabase. * @param options.auth.autoRefreshToken Set to "true" if you want to automatically refresh the token before expiring. * @param options.auth.persistSession Set to "true" if you want to automatically save the user session into local storage. * @param options.auth.detectSessionInUrl Set to "true" if you want to automatically detects OAuth grants in the URL and signs in the user. * @param options.realtime Options passed along to realtime-js constructor. * @param options.global.fetch A custom fetch implementation. * @param options.global.headers Any additional headers to send with each network request. */ constructor(supabaseUrl, supabaseKey, options) { var _a, _b, _c; this.supabaseUrl = supabaseUrl; this.supabaseKey = supabaseKey; if (!supabaseUrl) throw new Error('supabaseUrl is required.'); if (!supabaseKey) throw new Error('supabaseKey is required.'); const _supabaseUrl = (0, helpers_1.stripTrailingSlash)(supabaseUrl); this.realtimeUrl = `${_supabaseUrl}/realtime/v1`.replace(/^http/i, 'ws'); this.authUrl = `${_supabaseUrl}/auth/v1`; this.storageUrl = `${_supabaseUrl}/storage/v1`; this.functionsUrl = `${_supabaseUrl}/functions/v1`; // default storage key uses the supabase project ref as a namespace const defaultStorageKey = `sb-${new URL(this.authUrl).hostname.split('.')[0]}-auth-token`; const DEFAULTS = { db: constants_1.DEFAULT_DB_OPTIONS, realtime: constants_1.DEFAULT_REALTIME_OPTIONS, auth: Object.assign(Object.assign({}, constants_1.DEFAULT_AUTH_OPTIONS), { storageKey: defaultStorageKey }), global: constants_1.DEFAULT_GLOBAL_OPTIONS, }; const settings = (0, helpers_1.applySettingDefaults)(options !== null && options !== void 0 ? options : {}, DEFAULTS); this.storageKey = (_a = settings.auth.storageKey) !== null && _a !== void 0 ? _a : ''; this.headers = (_b = settings.global.headers) !== null && _b !== void 0 ? _b : {}; if (!settings.accessToken) { this.auth = this._initSupabaseAuthClient((_c = settings.auth) !== null && _c !== void 0 ? _c : {}, this.headers, settings.global.fetch); } else { this.accessToken = settings.accessToken; this.auth = new Proxy({}, { get: (_, prop) => { throw new Error(`@supabase/supabase-js: Supabase Client is configured with the accessToken option, accessing supabase.auth.${String(prop)} is not possible`); }, }); } this.fetch = (0, fetch_1.fetchWithAuth)(supabaseKey, this._getAccessToken.bind(this), settings.global.fetch); this.realtime = this._initRealtimeClient(Object.assign({ headers: this.headers, accessToken: this._getAccessToken.bind(this) }, settings.realtime)); this.rest = new postgrest_js_1.PostgrestClient(`${_supabaseUrl}/rest/v1`, { headers: this.headers, schema: settings.db.schema, fetch: this.fetch, }); if (!settings.accessToken) { this._listenForAuthEvents(); } } /** * Supabase Functions allows you to deploy and invoke edge functions. */ get functions() { return new functions_js_1.FunctionsClient(this.functionsUrl, { headers: this.headers, customFetch: this.fetch, }); } /** * Supabase Storage allows you to manage user-generated content, such as photos or videos. */ get storage() { return new storage_js_1.StorageClient(this.storageUrl, this.headers, this.fetch); } /** * Perform a query on a table or a view. * * @param relation - The table or view name to query */ from(relation) { return this.rest.from(relation); } // NOTE: signatures must be kept in sync with PostgrestClient.schema /** * Select a schema to query or perform an function (rpc) call. * * The schema needs to be on the list of exposed schemas inside Supabase. * * @param schema - The schema to query */ schema(schema) { return this.rest.schema(schema); } // NOTE: signatures must be kept in sync with PostgrestClient.rpc /** * Perform a function call. * * @param fn - The function name to call * @param args - The arguments to pass to the function call * @param options - Named parameters * @param options.head - When set to `true`, `data` will not be returned. * Useful if you only need the count. * @param options.get - When set to `true`, the function will be called with * read-only access mode. * @param options.count - Count algorithm to use to count rows returned by the * function. Only applicable for [set-returning * functions](https://www.postgresql.org/docs/current/functions-srf.html). * * `"exact"`: Exact but slow count algorithm. Performs a `COUNT(*)` under the * hood. * * `"planned"`: Approximated but fast count algorithm. Uses the Postgres * statistics under the hood. * * `"estimated"`: Uses exact count for low numbers and planned count for high * numbers. */ rpc(fn, args = {}, options = {}) { return this.rest.rpc(fn, args, options); } /** * Creates a Realtime channel with Broadcast, Presence, and Postgres Changes. * * @param {string} name - The name of the Realtime channel. * @param {Object} opts - The options to pass to the Realtime channel. * */ channel(name, opts = { config: {} }) { return this.realtime.channel(name, opts); } /** * Returns all Realtime channels. */ getChannels() { return this.realtime.getChannels(); } /** * Unsubscribes and removes Realtime channel from Realtime client. * * @param {RealtimeChannel} channel - The name of the Realtime channel. * */ removeChannel(channel) { return this.realtime.removeChannel(channel); } /** * Unsubscribes and removes all Realtime channels from Realtime client. */ removeAllChannels() { return this.realtime.removeAllChannels(); } _getAccessToken() { var _a, _b; return __awaiter$2(this, void 0, void 0, function* () { if (this.accessToken) { return yield this.accessToken(); } const { data } = yield this.auth.getSession(); return (_b = (_a = data.session) === null || _a === void 0 ? void 0 : _a.access_token) !== null && _b !== void 0 ? _b : null; }); } _initSupabaseAuthClient({ autoRefreshToken, persistSession, detectSessionInUrl, storage, storageKey, flowType, lock, debug, }, headers, fetch) { const authHeaders = { Authorization: `Bearer ${this.supabaseKey}`, apikey: `${this.supabaseKey}`, }; return new SupabaseAuthClient_1.SupabaseAuthClient({ url: this.authUrl, headers: Object.assign(Object.assign({}, authHeaders), headers), storageKey: storageKey, autoRefreshToken, persistSession, detectSessionInUrl, storage, flowType, lock, debug, fetch, // auth checks if there is a custom authorizaiton header using this flag // so it knows whether to return an error when getUser is called with no session hasCustomAuthorizationHeader: 'Authorization' in this.headers, }); } _initRealtimeClient(options) { return new realtime_js_1.RealtimeClient(this.realtimeUrl, Object.assign(Object.assign({}, options), { params: Object.assign({ apikey: this.supabaseKey }, options === null || options === void 0 ? void 0 : options.params) })); } _listenForAuthEvents() { let data = this.auth.onAuthStateChange((event, session) => { this._handleTokenChanged(event, 'CLIENT', session === null || session === void 0 ? void 0 : session.access_token); }); return data; } _handleTokenChanged(event, source, token) { if ((event === 'TOKEN_REFRESHED' || event === 'SIGNED_IN') && this.changedAccessToken !== token) { this.changedAccessToken = token; } else if (event === 'SIGNED_OUT') { this.realtime.setAuth(); if (source == 'STORAGE') this.auth.signOut(); this.changedAccessToken = undefined; } } } SupabaseClient$1.default = SupabaseClient; (function (exports) { var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __exportStar = (commonjsGlobal && commonjsGlobal.__exportStar) || function(m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; var __importDefault = (commonjsGlobal && commonjsGlobal.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createClient = exports.SupabaseClient = exports.FunctionRegion = exports.FunctionsError = exports.FunctionsRelayError = exports.FunctionsFetchError = exports.FunctionsHttpError = exports.PostgrestError = void 0; const SupabaseClient_1 = __importDefault(SupabaseClient$1); __exportStar(main, exports); var postgrest_js_1 = cjs; Object.defineProperty(exports, "PostgrestError", { enumerable: true, get: function () { return postgrest_js_1.PostgrestError; } }); var functions_js_1 = main$3; Object.defineProperty(exports, "FunctionsHttpError", { enumerable: true, get: function () { return functions_js_1.FunctionsHttpError; } }); Object.defineProperty(exports, "FunctionsFetchError", { enumerable: true, get: function () { return functions_js_1.FunctionsFetchError; } }); Object.defineProperty(exports, "FunctionsRelayError", { enumerable: true, get: function () { return functions_js_1.FunctionsRelayError; } }); Object.defineProperty(exports, "FunctionsError", { enumerable: true, get: function () { return functions_js_1.FunctionsError; } }); Object.defineProperty(exports, "FunctionRegion", { enumerable: true, get: function () { return functions_js_1.FunctionRegion; } }); __exportStar(main$2, exports); var SupabaseClient_2 = SupabaseClient$1; Object.defineProperty(exports, "SupabaseClient", { enumerable: true, get: function () { return __importDefault(SupabaseClient_2).default; } }); /** * Creates a new Supabase Client. */ const createClient = (supabaseUrl, supabaseKey, options) => { return new SupabaseClient_1.default(supabaseUrl, supabaseKey, options); }; exports.createClient = createClient; } (main$4)); let client; function supabaseClient() { if (!client) client = main$4.createClient(AdminJS.env.FRONTEND_SUPABASE_PROJECT_URL, AdminJS.env.FRONTEND_SUPABASE_ANON_KEY); return client; } function assertPath(path) { if (typeof path !== 'string') { throw new TypeError('Path must be a string. Received ' + JSON.stringify(path)); } } // Resolves . and .. elements in a path with directory names function normalizeStringPosix(path, allowAboveRoot) { var res = ''; var lastSegmentLength = 0; var lastSlash = -1; var dots = 0; var code; for (var i = 0; i <= path.length; ++i) { if (i < path.length) code = path.charCodeAt(i); else if (code === 47 /*/*/) break; else code = 47 /*/*/; if (code === 47 /*/*/) { if (lastSlash === i - 1 || dots === 1) ; else if (lastSlash !== i - 1 && dots === 2) { if (res.length < 2 || lastSegmentLength !== 2 || res.charCodeAt(res.length - 1) !== 46 /*.*/ || res.charCodeAt(res.length - 2) !== 46 /*.*/) { if (res.length > 2) { var lastSlashIndex = res.lastIndexOf('/'); if (lastSlashIndex !== res.length - 1) { if (lastSlashIndex === -1) { res = ''; lastSegmentLength = 0; } else { res = res.slice(0, lastSlashIndex); lastSegmentLength = res.length - 1 - res.lastIndexOf('/'); } lastSlash = i; dots = 0; continue; } } else if (res.length === 2 || res.length === 1) { res = ''; lastSegmentLength = 0; lastSlash = i; dots = 0; continue; } } if (allowAboveRoot) { if (res.length > 0) res += '/..'; else res = '..'; lastSegmentLength = 2; } } else { if (res.length > 0) res += '/' + path.slice(lastSlash + 1, i); else res = path.slice(lastSlash + 1, i); lastSegmentLength = i - lastSlash - 1; } lastSlash = i; dots = 0; } else if (code === 46 /*.*/ && dots !== -1) { ++dots; } else { dots = -1; } } return res; } function _format(sep, pathObject) { var dir = pathObject.dir || pathObject.root; var base = pathObject.base || (pathObject.name || '') + (pathObject.ext || ''); if (!dir) { return base; } if (dir === pathObject.root) { return dir + base; } return dir + sep + base; } var posix = { // path.resolve([from ...], to) resolve: function resolve() { var resolvedPath = ''; var resolvedAbsolute = false; var cwd; for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { var path; if (i >= 0) path = arguments[i]; else { if (cwd === undefined) cwd = process.cwd(); path = cwd; } assertPath(path); // Skip empty entries if (path.length === 0) { continue; } resolvedPath = path + '/' + resolvedPath; resolvedAbsolute = path.charCodeAt(0) === 47 /*/*/; } // At this point the path should be resolved to a full absolute path, but // handle relative paths to be safe (might happen when process.cwd() fails) // Normalize the path resolvedPath = normalizeStringPosix(resolvedPath, !resolvedAbsolute); if (resolvedAbsolute) { if (resolvedPath.length > 0) return '/' + resolvedPath; else return '/'; } else if (resolvedPath.length > 0) { return resolvedPath; } else { return '.'; } }, normalize: function normalize(path) { assertPath(path); if (path.length === 0) return '.'; var isAbsolute = path.charCodeAt(0) === 47 /*/*/; var trailingSeparator = path.charCodeAt(path.length - 1) === 47 /*/*/; // Normalize the path path = normalizeStringPosix(path, !isAbsolute); if (path.length === 0 && !isAbsolute) path = '.'; if (path.length > 0 && trailingSeparator) path += '/'; if (isAbsolute) return '/' + path; return path; }, isAbsolute: function isAbsolute(path) { assertPath(path); return path.length > 0 && path.charCodeAt(0) === 47 /*/*/; }, join: function join() { if (arguments.length === 0) return '.'; var joined; for (var i = 0; i < arguments.length; ++i) { var arg = arguments[i]; assertPath(arg); if (arg.length > 0) { if (joined === undefined) joined = arg; else joined += '/' + arg; } } if (joined === undefined) return '.'; return posix.normalize(joined); }, relative: function relative(from, to) { assertPath(from); assertPath(to); if (from === to) return ''; from = posix.resolve(from); to = posix.resolve(to); if (from === to) return ''; // Trim any leading backslashes var fromStart = 1; for (; fromStart < from.length; ++fromStart) { if (from.charCodeAt(fromStart) !== 47 /*/*/) break; } var fromEnd = from.length; var fromLen = fromEnd - fromStart; // Trim any leading backslashes var toStart = 1; for (; toStart < to.length; ++toStart) { if (to.charCodeAt(toStart) !== 47 /*/*/) break; } var toEnd = to.length; var toLen = toEnd - toStart; // Compare paths to find the longest common path from root var length = fromLen < toLen ? fromLen : toLen; var lastCommonSep = -1; var i = 0; for (; i <= length; ++i) { if (i === length) { if (toLen > length) { if (to.charCodeAt(toStart + i) === 47 /*/*/) { // We get here if `from` is the exact base path for `to`. // For example: from='/foo/bar'; to='/foo/bar/baz' return to.slice(toStart + i + 1); } else if (i === 0) { // We get here if `from` is the root // For example: from='/'; to='/foo' return to.slice(toStart + i); } } else if (fromLen > length) { if (from.charCodeAt(fromStart + i) === 47 /*/*/) { // We get here if `to` is the exact base path for `from`. // For example: from='/foo/bar/baz'; to='/foo/bar' lastCommonSep = i; } else if (i === 0) { // We get here if `to` is the root. // For example: from='/foo'; to='/' lastCommonSep = 0; } } break; } var fromCode = from.charCodeAt(fromStart + i); var toCode = to.charCodeAt(toStart + i); if (fromCode !== toCode) break; else if (fromCode === 47 /*/*/) lastCommonSep = i; } var out = ''; // Generate the relative path based on the path difference between `to` // and `from` for (i = fromStart + lastCommonSep + 1; i <= fromEnd; ++i) { if (i === fromEnd || from.charCodeAt(i) === 47 /*/*/) { if (out.length === 0) out += '..'; else out += '/..'; } } // Lastly, append the rest of the destination (`to`) path that comes after // the common path parts if (out.length > 0) return out + to.slice(toStart + lastCommonSep); else { toStart += lastCommonSep; if (to.charCodeAt(toStart) === 47 /*/*/) ++toStart; return to.slice(toStart); } }, _makeLong: function _makeLong(path) { return path; }, dirname: function dirname(path) { assertPath(path); if (path.length === 0) return '.'; var code = path.charCodeAt(0); var hasRoot = code === 47 /*/*/; var end = -1; var matchedSlash = true; for (var i = path.length - 1; i >= 1; --i) { code = path.charCodeAt(i); if (code === 47 /*/*/) { if (!matchedSlash) { end = i; break; } } else { // We saw the first non-path separator matchedSlash = false; } } if (end === -1) return hasRoot ? '/' : '.'; if (hasRoot && end === 1) return '//'; return path.slice(0, end); }, basename: function basename(path, ext) { if (ext !== undefined && typeof ext !== 'string') throw new TypeError('"ext" argument must be a string'); assertPath(path); var start = 0; var end = -1; var matchedSlash = true; var i; if (ext !== undefined && ext.length > 0 && ext.length <= path.length) { if (ext.length === path.length && ext === path) return ''; var extIdx = ext.length - 1; var firstNonSlashEnd = -1; for (i = path.length - 1; i >= 0; --i) { var code = path.charCodeAt(i); if (code === 47 /*/*/) { // If we reached a path separator that was not part of a set of path // separators at the end of the string, stop now if (!matchedSlash) { start = i + 1; break; } } else { if (firstNonSlashEnd === -1) { // We saw the first non-path separator, remember this index in case // we need it if the extension ends up not matching matchedSlash = false; firstNonSlashEnd = i + 1; } if (extIdx >= 0) { // Try to match the explicit extension if (code === ext.charCodeAt(extIdx)) { if (--extIdx === -1) { // We matched the extension, so mark this as the end of our path // component end = i; } } else { // Extension does not match, so our result is the entire path // component extIdx = -1; end = firstNonSlashEnd; } } } } if (start === end) end = firstNonSlashEnd;else if (end === -1) end = path.length; return path.slice(start, end); } else { for (i = path.length - 1; i >= 0; --i) { if (path.charCodeAt(i) === 47 /*/*/) { // If we reached a path separator that was not part of a set of path // separators at the end of the string, stop now if (!matchedSlash) { start = i + 1; break; } } else if (end === -1) { // We saw the first non-path separator, mark this as the end of our // path component matchedSlash = false; end = i + 1; } } if (end === -1) return ''; return path.slice(start, end); } }, extname: function extname(path) { assertPath(path); var startDot = -1; var startPart = 0; var end = -1; var matchedSlash = true; // Track the state of characters (if any) we see before our first dot and // after any path separator we find var preDotState = 0; for (var i = path.length - 1; i >= 0; --i) { var code = path.charCodeAt(i); if (code === 47 /*/*/) { // If we reached a path separator that was not part of a set of path // separators at the end of the string, stop now if (!matchedSlash) { startPart = i + 1; break; } continue; } if (end === -1) { // We saw the first non-path separator, mark this as the end of our // extension matchedSlash = false; end = i + 1; } if (code === 46 /*.*/) { // If this is our first dot, mark it as the start of our extension if (startDot === -1) startDot = i; else if (preDotState !== 1) preDotState = 1; } else if (startDot !== -1) { // We saw a non-dot and non-path separator before our dot, so we should // have a good chance at having a non-empty extension preDotState = -1; } } if (startDot === -1 || end === -1 || // We saw a non-dot character immediately before the dot preDotState === 0 || // The (right-most) trimmed path component is exactly '..' preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) { return ''; } return path.slice(startDot, end); }, format: function format(pathObject) { if (pathObject === null || typeof pathObject !== 'object') { throw new TypeError('The "pathObject" argument must be of type Object. Received type ' + typeof pathObject); } return _format('/', pathObject); }, parse: function parse(path) { assertPath(path); var ret = { root: '', dir: '', base: '', ext: '', name: '' }; if (path.length === 0) return ret; var code = path.charCodeAt(0); var isAbsolute = code === 47 /*/*/; var start; if (isAbsolute) { ret.root = '/'; start = 1; } else { start = 0; } var startDot = -1; var startPart = 0; var end = -1; var matchedSlash = true; var i = path.length - 1; // Track the state of characters (if any) we see before our first dot and // after any path separator we find var preDotState = 0; // Get non-dir info for (; i >= start; --i) { code = path.charCodeAt(i); if (code === 47 /*/*/) { // If we reached a path separator that was not part of a set of path // separators at the end of the string, stop now if (!matchedSlash) { startPart = i + 1; break; } continue; } if (end === -1) { // We saw the first non-path separator, mark this as the end of our // extension matchedSlash = false; end = i + 1; } if (code === 46 /*.*/) { // If this is our first dot, mark it as the start of our extension if (startDot === -1) startDot = i;else if (preDotState !== 1) preDotState = 1; } else if (startDot !== -1) { // We saw a non-dot and non-path separator before our dot, so we should // have a good chance at having a non-empty extension preDotState = -1; } } if (startDot === -1 || end === -1 || // We saw a non-dot character immediately before the dot preDotState === 0 || // The (right-most) trimmed path component is exactly '..' preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) { if (end !== -1) { if (startPart === 0 && isAbsolute) ret.base = ret.name = path.slice(1, end);else ret.base = ret.name = path.slice(startPart, end); } } else { if (startPart === 0 && isAbsolute) { ret.name = path.slice(1, startDot); ret.base = path.slice(1, end); } else { ret.name = path.slice(startPart, startDot); ret.base = path.slice(startPart, end); } ret.ext = path.slice(startDot, end); } if (startPart > 0) ret.dir = path.slice(0, startPart - 1);else if (isAbsolute) ret.dir = '/'; return ret; }, sep: '/', delimiter: ':', win32: null, posix: null }; posix.posix = posix; var pathBrowserify = posix; var path = /*@__PURE__*/getDefaultExportFromCjs(pathBrowserify); const byteToHex = []; for (let i = 0; i < 256; ++i) { byteToHex.push((i + 0x100).toString(16).slice(1)); } function unsafeStringify(arr, offset = 0) { return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + '-' + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + '-' + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + '-' + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + '-' + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase(); } let getRandomValues; const rnds8 = new Uint8Array(16); function rng() { if (!getRandomValues) { if (typeof crypto === 'undefined' || !crypto.getRandomValues) { throw new Error('crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported'); } getRandomValues = crypto.getRandomValues.bind(crypto); } return getRandomValues(rnds8); } const randomUUID = typeof crypto !== 'undefined' && crypto.randomUUID && crypto.randomUUID.bind(crypto); var native = { randomUUID }; function v4(options, buf, offset) { if (native.randomUUID && true && !options) { return native.randomUUID(); } options = options || {}; const rnds = options.random ?? options.rng?.() ?? rng(); if (rnds.length < 16) { throw new Error('Random bytes length must be >= 16'); } rnds[6] = (rnds[6] & 0x0f) | 0x40; rnds[8] = (rnds[8] & 0x3f) | 0x80; return unsafeStringify(rnds); } var DefaultContext = { color: undefined, size: undefined, className: undefined, style: undefined, attr: undefined }; var IconContext = React__namespace.default.createContext && /*#__PURE__*/React__namespace.default.createContext(DefaultContext); var _excluded$1 = ["attr", "size", "title"]; function _objectWithoutProperties$2(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose$2(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; } function _objectWithoutPropertiesLoose$2(source, excluded) { if (source == null) return {}; var target = {}; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } } return target; } function _extends$2() { _extends$2 = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends$2.apply(this, arguments); } function ownKeys$3(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread$7(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$3(Object(t), true).forEach(function (r) { _defineProperty$7(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$3(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } function _defineProperty$7(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } function Tree2Element(tree) { return tree && tree.map((node, i) => /*#__PURE__*/React__namespace.default.createElement(node.tag, _objectSpread$7({ key: i }, node.attr), Tree2Element(node.child))); } function GenIcon(data) { return props => /*#__PURE__*/React__namespace.default.createElement(IconBase, _extends$2({ attr: _objectSpread$7({}, data.attr) }, props), Tree2Element(data.child)); } function IconBase(props) { var elem = conf => { var { attr, size, title } = props, svgProps = _objectWithoutProperties$2(props, _excluded$1); var computedSize = size || conf.size || "1em"; var className; if (conf.className) className = conf.className; if (props.className) className = (className ? className + " " : "") + props.className; return /*#__PURE__*/React__namespace.default.createElement("svg", _extends$2({ stroke: "currentColor", fill: "currentColor", strokeWidth: "0" }, conf.attr, attr, svgProps, { className: className, style: _objectSpread$7(_objectSpread$7({ color: props.color || conf.color }, conf.style), props.style), height: computedSize, width: computedSize, xmlns: "http://www.w3.org/2000/svg" }), title && /*#__PURE__*/React__namespace.default.createElement("title", null, title), props.children); }; return IconContext !== undefined ? /*#__PURE__*/React__namespace.default.createElement(IconContext.Consumer, null, conf => elem(conf)) : elem(DefaultContext); } // THIS FILE IS AUTO GENERATED function FaImage(props){return GenIcon({"attr":{"viewBox":"0 0 512 512"},"child":[{"tag":"path","attr":{"d":"M464 448H48c-26.51 0-48-21.49-48-48V112c0-26.51 21.49-48 48-48h416c26.51 0 48 21.49 48 48v288c0 26.51-21.49 48-48 48zM112 120c-30.928 0-56 25.072-56 56s25.072 56 56 56 56-25.072 56-56-25.072-56-56-56zM64 384h384V272l-87.515-87.515c-4.686-4.686-12.284-4.686-16.971 0L208 320l-55.515-55.515c-4.686-4.686-12.284-4.686-16.971 0L64 336v48z"},"child":[]}]})(props);} // THIS FILE IS AUTO GENERATED function FaPen(props){return GenIcon({"attr":{"viewBox":"0 0 512 512"},"child":[{"tag":"path","attr":{"d":"M362.7 19.3L314.3 67.7 444.3 197.7l48.4-48.4c25-25 25-65.5 0-90.5L453.3 19.3c-25-25-65.5-25-90.5 0zm-71 71L58.6 323.5c-10.4 10.4-18 23.3-22.2 37.4L1 481.2C-1.5 489.7 .8 498.8 7 505s15.3 8.5 23.7 6.1l120.3-35.4c14.1-4.2 27-11.8 37.4-22.2L421.7 220.3 291.7 90.3z"},"child":[]}]})(props);} const PhotoWithEdit = ({ variant = 'medium', imageUrl, onImageChange, onImageDelete, loading, editable = false, showLabel }) => { const handleImageChange = e => { try { if (!e.target.files || e.target.files.length === 0) { throw new Error('You must select an image to upload.'); } const file = e.target.files[0]; if (!file) return; onImageChange?.(file); } catch (error) { console.log(error); } }; const handleDeleteClicked = () => { onImageDelete?.(); }; const content = /*#__PURE__*/React__namespace.default.createElement("div", { style: { position: 'relative', display: 'inline-block' } }, editable && (/*#__PURE__*/React__namespace.default.createElement("input", { type: "file", accept: "image/*", style: { display: 'none' }, onChange: editable ? handleImageChange : undefined, id: "image-input" })), /*#__PURE__*/React__namespace.default.createElement("label", { htmlFor: "image-input" }, /*#__PURE__*/React__namespace.default.createElement("div", { style: { width: variant == 'medium' ? '335px' : '166px', height: variant == 'medium' ? '210px' : '105px', backgroundImage: imageUrl ? `url(${imageUrl})` : 'none', backgroundSize: 'cover', backgroundPosition: 'center', borderRadius: '8px', position: 'relative', cursor: 'pointer' } }, (editable || loading) && (/*#__PURE__*/React__namespace.default.createElement("div", null, /*#__PURE__*/React__namespace.default.createElement("div", { style: { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, backgroundColor: 'rgba(0, 0, 0, 0.4)', borderRadius: '8px' } }), /*#__PURE__*/React__namespace.default.createElement("div", { style: { position: 'absolute', top: '50%', left: '50%', transform: 'translate(-50%, -50%)', fontSize: '24px', color: 'white', borderRadius: '50%', padding: '10px', display: 'flex', justifyContent: 'center', alignItems: 'center' } }, loading ? /*#__PURE__*/React__namespace.default.createElement("div", { className: "spinner" }) : /*#__PURE__*/React__namespace.default.createElement(FaPen, null)))), !imageUrl && !editable && (/*#__PURE__*/React__namespace.default.createElement("div", { style: { position: 'absolute', top: '50%', left: '50%', transform: 'translate(-50%, -50%)', fontSize: '24px', color: 'rgba(0, 0, 0, 0.5)', borderRadius: '50%', padding: '10px', display: 'flex', justifyContent: 'center', alignItems: 'center' } }, /*#__PURE__*/React__namespace.default.createElement(FaImage, null)))))); return showLabel || editable ? (/*#__PURE__*/React__namespace.default.createElement(designSystem.FormGroup, null, showLabel && /*#__PURE__*/React__namespace.default.createElement(designSystem.Label, null, "\u041F\u0440\u0435\u0432\u044C\u044E"), content, editable && (/*#__PURE__*/React__namespace.default.createElement("div", null, /*#__PURE__*/React__namespace.default.createElement("br", null), /*#__PURE__*/React__namespace.default.createElement(designSystem.Button, { type: "button", variant: "danger", onClick: handleDeleteClicked }, "Delete image"), /*#__PURE__*/React__namespace.default.createElement("br", null))))) : content; }; const MediaView = props => { const { record, property, onChange } = props; const imagePath = property.resourceId == 'media' ? record?.params['path'] : record?.populated[property.path]?.params['path']; const [imageUrl, setImageUrl] = React$1.useState(imagePath ? supabaseClient().storage.from('media').getPublicUrl(imagePath, { transform: { width: 335 * 4, height: 210 * 4, resize: 'cover', quality: 80 } }).data.publicUrl.replace('supabase.vrum.rent', 'cdn.vrum.rent') : null); const [loading, setLoading] = React$1.useState(false); const handleImageChange = async file => { const oldImage = imageUrl; const fileUrl = URL.createObjectURL(file); console.log('File name: ' + path.extname(file.name)); setImageUrl(fileUrl); setLoading(true); const { data, error } = await supabaseClient().storage.from('media').upload(`photo/${v4()}${path.extname(file.name)}`, file, { contentType: file.type }); setLoading(false); if (error || !data) { setImageUrl(oldImage); return; } console.log('Media path: ' + data.path); if (property.resourceId != 'media') { const dbRes = await supabaseClient().from('media').insert({ path: data.path }).select(); if (!dbRes.data || !dbRes.data[0]?.id) { setImageUrl(oldImage); return; } console.log('DB Media: ' + JSON.stringify(dbRes)); const mediaId = dbRes.data[0].id; console.log('DB Media id: ' + mediaId); onChange?.(property.path, mediaId); } else { onChange?.(property.path, data.path); } }; const handleImageDelete = () => { setImageUrl(null); onChange?.(property.path, null); }; return /*#__PURE__*/React__namespace.default.createElement(PhotoWithEdit, { imageUrl: imageUrl, onImageChange: handleImageChange, onImageDelete: handleImageDelete, loading: loading, variant: property.props['variant'], editable: property.props['editable'], showLabel: props.where == 'show' || props.where == 'edit' }); }; const MediaViewSmall = props => { const variant = 'small'; const newPropertyProps = { ...props.property.props, variant }; const newProps = { ...props, property: { ...props.property, props: newPropertyProps } }; return /*#__PURE__*/React__namespace.default.createElement(MediaView, { ...newProps }); }; const MediaViewEditable = props => { const editable = true; const newPropertyProps = { ...props.property.props, editable }; const newProps = { ...props, property: { ...props.property, props: newPropertyProps } }; return /*#__PURE__*/React__namespace.default.createElement(MediaView, { ...newProps }); }; const CarComponent = props => { const { record } = props; const imagePath = record; return /*#__PURE__*/React__namespace.default.createElement("div", null, JSON.stringify(imagePath, null, 2)); }; // packages/react/compose-refs/src/composeRefs.tsx function setRef$1(ref, value) { if (typeof ref === "function") { return ref(value); } else if (ref !== null && ref !== void 0) { ref.current = value; } } function composeRefs(...refs) { return node => { let hasCleanup = false; const cleanups = refs.map(ref => { const cleanup = setRef$1(ref, node); if (!hasCleanup && typeof cleanup == "function") { hasCleanup = true; } return cleanup; }); if (hasCleanup) { return () => { for (let i = 0; i < cleanups.length; i++) { const cleanup = cleanups[i]; if (typeof cleanup == "function") { cleanup(); } else { setRef$1(refs[i], null); } } }; } }; } function useComposedRefs(...refs) { return React__namespace.useCallback(composeRefs(...refs), refs); } var jsxRuntime = {exports: {}}; var reactJsxRuntime_development = {}; /** * @license React * react-jsx-runtime.development.js * * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ { (function() { var React = React__namespace.default; // ATTENTION // When adding new symbols to this file, // Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols' // The Symbol used to tag the ReactElement-like types. var REACT_ELEMENT_TYPE = Symbol.for('react.element'); var REACT_PORTAL_TYPE = Symbol.for('react.portal'); var REACT_FRAGMENT_TYPE = Symbol.for('react.fragment'); var REACT_STRICT_MODE_TYPE = Symbol.for('react.strict_mode'); var REACT_PROFILER_TYPE = Symbol.for('react.profiler'); var REACT_PROVIDER_TYPE = Symbol.for('react.provider'); var REACT_CONTEXT_TYPE = Symbol.for('react.context'); var REACT_FORWARD_REF_TYPE = Symbol.for('react.forward_ref'); var REACT_SUSPENSE_TYPE = Symbol.for('react.suspense'); var REACT_SUSPENSE_LIST_TYPE = Symbol.for('react.suspense_list'); var REACT_MEMO_TYPE = Symbol.for('react.memo'); var REACT_LAZY_TYPE = Symbol.for('react.lazy'); var REACT_OFFSCREEN_TYPE = Symbol.for('react.offscreen'); var MAYBE_ITERATOR_SYMBOL = Symbol.iterator; var FAUX_ITERATOR_SYMBOL = '@@iterator'; function getIteratorFn(maybeIterable) { if (maybeIterable === null || typeof maybeIterable !== 'object') { return null; } var maybeIterator = MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL] || maybeIterable[FAUX_ITERATOR_SYMBOL]; if (typeof maybeIterator === 'function') { return maybeIterator; } return null; } var ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; function error(format) { { { for (var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) { args[_key2 - 1] = arguments[_key2]; } printWarning('error', format, args); } } } function printWarning(level, format, args) { // When changing this logic, you might want to also // update consoleWithStackDev.www.js as well. { var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; var stack = ReactDebugCurrentFrame.getStackAddendum(); if (stack !== '') { format += '%s'; args = args.concat([stack]); } // eslint-disable-next-line react-internal/safe-string-coercion var argsWithFormat = args.map(function (item) { return String(item); }); // Careful: RN currently depends on this prefix argsWithFormat.unshift('Warning: ' + format); // We intentionally don't use spread (or .apply) directly because it // breaks IE9: https://github.com/facebook/react/issues/13610 // eslint-disable-next-line react-internal/no-production-logging Function.prototype.apply.call(console[level], console, argsWithFormat); } } // ----------------------------------------------------------------------------- var enableScopeAPI = false; // Experimental Create Event Handle API. var enableCacheElement = false; var enableTransitionTracing = false; // No known bugs, but needs performance testing var enableLegacyHidden = false; // Enables unstable_avoidThisFallback feature in Fiber // stuff. Intended to enable React core members to more easily debug scheduling // issues in DEV builds. var enableDebugTracing = false; // Track which Fiber(s) schedule render work. var REACT_MODULE_REFERENCE; { REACT_MODULE_REFERENCE = Symbol.for('react.module.reference'); } function isValidElementType(type) { if (typeof type === 'string' || typeof type === 'function') { return true; } // Note: typeof might be other than 'symbol' or 'number' (e.g. if it's a polyfill). if (type === REACT_FRAGMENT_TYPE || type === REACT_PROFILER_TYPE || enableDebugTracing || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || enableLegacyHidden || type === REACT_OFFSCREEN_TYPE || enableScopeAPI || enableCacheElement || enableTransitionTracing ) { return true; } if (typeof type === 'object' && type !== null) { if (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || // This needs to include all possible module reference object // types supported by any Flight configuration anywhere since // we don't know which Flight build this will end up being used // with. type.$$typeof === REACT_MODULE_REFERENCE || type.getModuleId !== undefined) { return true; } } return false; } function getWrappedName(outerType, innerType, wrapperName) { var displayName = outerType.displayName; if (displayName) { return displayName; } var functionName = innerType.displayName || innerType.name || ''; return functionName !== '' ? wrapperName + "(" + functionName + ")" : wrapperName; } // Keep in sync with react-reconciler/getComponentNameFromFiber function getContextName(type) { return type.displayName || 'Context'; } // Note that the reconciler package should generally prefer to use getComponentNameFromFiber() instead. function getComponentNameFromType(type) { if (type == null) { // Host root, text node or just invalid type. return null; } { if (typeof type.tag === 'number') { error('Received an unexpected object in getComponentNameFromType(). ' + 'This is likely a bug in React. Please file an issue.'); } } if (typeof type === 'function') { return type.displayName || type.name || null; } if (typeof type === 'string') { return type; } switch (type) { case REACT_FRAGMENT_TYPE: return 'Fragment'; case REACT_PORTAL_TYPE: return 'Portal'; case REACT_PROFILER_TYPE: return 'Profiler'; case REACT_STRICT_MODE_TYPE: return 'StrictMode'; case REACT_SUSPENSE_TYPE: return 'Suspense'; case REACT_SUSPENSE_LIST_TYPE: return 'SuspenseList'; } if (typeof type === 'object') { switch (type.$$typeof) { case REACT_CONTEXT_TYPE: var context = type; return getContextName(context) + '.Consumer'; case REACT_PROVIDER_TYPE: var provider = type; return getContextName(provider._context) + '.Provider'; case REACT_FORWARD_REF_TYPE: return getWrappedName(type, type.render, 'ForwardRef'); case REACT_MEMO_TYPE: var outerName = type.displayName || null; if (outerName !== null) { return outerName; } return getComponentNameFromType(type.type) || 'Memo'; case REACT_LAZY_TYPE: { var lazyComponent = type; var payload = lazyComponent._payload; var init = lazyComponent._init; try { return getComponentNameFromType(init(payload)); } catch (x) { return null; } } // eslint-disable-next-line no-fallthrough } } return null; } var assign = Object.assign; // Helpers to patch console.logs to avoid logging during side-effect free // replaying on render function. This currently only patches the object // lazily which won't cover if the log function was extracted eagerly. // We could also eagerly patch the method. var disabledDepth = 0; var prevLog; var prevInfo; var prevWarn; var prevError; var prevGroup; var prevGroupCollapsed; var prevGroupEnd; function disabledLog() {} disabledLog.__reactDisabledLog = true; function disableLogs() { { if (disabledDepth === 0) { /* eslint-disable react-internal/no-production-logging */ prevLog = console.log; prevInfo = console.info; prevWarn = console.warn; prevError = console.error; prevGroup = console.group; prevGroupCollapsed = console.groupCollapsed; prevGroupEnd = console.groupEnd; // https://github.com/facebook/react/issues/19099 var props = { configurable: true, enumerable: true, value: disabledLog, writable: true }; // $FlowFixMe Flow thinks console is immutable. Object.defineProperties(console, { info: props, log: props, warn: props, error: props, group: props, groupCollapsed: props, groupEnd: props }); /* eslint-enable react-internal/no-production-logging */ } disabledDepth++; } } function reenableLogs() { { disabledDepth--; if (disabledDepth === 0) { /* eslint-disable react-internal/no-production-logging */ var props = { configurable: true, enumerable: true, writable: true }; // $FlowFixMe Flow thinks console is immutable. Object.defineProperties(console, { log: assign({}, props, { value: prevLog }), info: assign({}, props, { value: prevInfo }), warn: assign({}, props, { value: prevWarn }), error: assign({}, props, { value: prevError }), group: assign({}, props, { value: prevGroup }), groupCollapsed: assign({}, props, { value: prevGroupCollapsed }), groupEnd: assign({}, props, { value: prevGroupEnd }) }); /* eslint-enable react-internal/no-production-logging */ } if (disabledDepth < 0) { error('disabledDepth fell below zero. ' + 'This is a bug in React. Please file an issue.'); } } } var ReactCurrentDispatcher = ReactSharedInternals.ReactCurrentDispatcher; var prefix; function describeBuiltInComponentFrame(name, source, ownerFn) { { if (prefix === undefined) { // Extract the VM specific prefix used by each line. try { throw Error(); } catch (x) { var match = x.stack.trim().match(/\n( *(at )?)/); prefix = match && match[1] || ''; } } // We use the prefix to ensure our stacks line up with native stack frames. return '\n' + prefix + name; } } var reentry = false; var componentFrameCache; { var PossiblyWeakMap = typeof WeakMap === 'function' ? WeakMap : Map; componentFrameCache = new PossiblyWeakMap(); } function describeNativeComponentFrame(fn, construct) { // If something asked for a stack inside a fake render, it should get ignored. if ( !fn || reentry) { return ''; } { var frame = componentFrameCache.get(fn); if (frame !== undefined) { return frame; } } var control; reentry = true; var previousPrepareStackTrace = Error.prepareStackTrace; // $FlowFixMe It does accept undefined. Error.prepareStackTrace = undefined; var previousDispatcher; { previousDispatcher = ReactCurrentDispatcher.current; // Set the dispatcher in DEV because this might be call in the render function // for warnings. ReactCurrentDispatcher.current = null; disableLogs(); } try { // This should throw. if (construct) { // Something should be setting the props in the constructor. var Fake = function () { throw Error(); }; // $FlowFixMe Object.defineProperty(Fake.prototype, 'props', { set: function () { // We use a throwing setter instead of frozen or non-writable props // because that won't throw in a non-strict mode function. throw Error(); } }); if (typeof Reflect === 'object' && Reflect.construct) { // We construct a different control for this case to include any extra // frames added by the construct call. try { Reflect.construct(Fake, []); } catch (x) { control = x; } Reflect.construct(fn, [], Fake); } else { try { Fake.call(); } catch (x) { control = x; } fn.call(Fake.prototype); } } else { try { throw Error(); } catch (x) { control = x; } fn(); } } catch (sample) { // This is inlined manually because closure doesn't do it for us. if (sample && control && typeof sample.stack === 'string') { // This extracts the first frame from the sample that isn't also in the control. // Skipping one frame that we assume is the frame that calls the two. var sampleLines = sample.stack.split('\n'); var controlLines = control.stack.split('\n'); var s = sampleLines.length - 1; var c = controlLines.length - 1; while (s >= 1 && c >= 0 && sampleLines[s] !== controlLines[c]) { // We expect at least one stack frame to be shared. // Typically this will be the root most one. However, stack frames may be // cut off due to maximum stack limits. In this case, one maybe cut off // earlier than the other. We assume that the sample is longer or the same // and there for cut off earlier. So we should find the root most frame in // the sample somewhere in the control. c--; } for (; s >= 1 && c >= 0; s--, c--) { // Next we find the first one that isn't the same which should be the // frame that called our sample function and the control. if (sampleLines[s] !== controlLines[c]) { // In V8, the first line is describing the message but other VMs don't. // If we're about to return the first line, and the control is also on the same // line, that's a pretty good indicator that our sample threw at same line as // the control. I.e. before we entered the sample frame. So we ignore this result. // This can happen if you passed a class to function component, or non-function. if (s !== 1 || c !== 1) { do { s--; c--; // We may still have similar intermediate frames from the construct call. // The next one that isn't the same should be our match though. if (c < 0 || sampleLines[s] !== controlLines[c]) { // V8 adds a "new" prefix for native classes. Let's remove it to make it prettier. var _frame = '\n' + sampleLines[s].replace(' at new ', ' at '); // If our component frame is labeled "" // but we have a user-provided "displayName" // splice it in to make the stack more readable. if (fn.displayName && _frame.includes('')) { _frame = _frame.replace('', fn.displayName); } { if (typeof fn === 'function') { componentFrameCache.set(fn, _frame); } } // Return the line we found. return _frame; } } while (s >= 1 && c >= 0); } break; } } } } finally { reentry = false; { ReactCurrentDispatcher.current = previousDispatcher; reenableLogs(); } Error.prepareStackTrace = previousPrepareStackTrace; } // Fallback to just using the name if we couldn't make it throw. var name = fn ? fn.displayName || fn.name : ''; var syntheticFrame = name ? describeBuiltInComponentFrame(name) : ''; { if (typeof fn === 'function') { componentFrameCache.set(fn, syntheticFrame); } } return syntheticFrame; } function describeFunctionComponentFrame(fn, source, ownerFn) { { return describeNativeComponentFrame(fn, false); } } function shouldConstruct(Component) { var prototype = Component.prototype; return !!(prototype && prototype.isReactComponent); } function describeUnknownElementTypeFrameInDEV(type, source, ownerFn) { if (type == null) { return ''; } if (typeof type === 'function') { { return describeNativeComponentFrame(type, shouldConstruct(type)); } } if (typeof type === 'string') { return describeBuiltInComponentFrame(type); } switch (type) { case REACT_SUSPENSE_TYPE: return describeBuiltInComponentFrame('Suspense'); case REACT_SUSPENSE_LIST_TYPE: return describeBuiltInComponentFrame('SuspenseList'); } if (typeof type === 'object') { switch (type.$$typeof) { case REACT_FORWARD_REF_TYPE: return describeFunctionComponentFrame(type.render); case REACT_MEMO_TYPE: // Memo may contain any component type so we recursively resolve it. return describeUnknownElementTypeFrameInDEV(type.type, source, ownerFn); case REACT_LAZY_TYPE: { var lazyComponent = type; var payload = lazyComponent._payload; var init = lazyComponent._init; try { // Lazy may contain any component type so we recursively resolve it. return describeUnknownElementTypeFrameInDEV(init(payload), source, ownerFn); } catch (x) {} } } } return ''; } var hasOwnProperty = Object.prototype.hasOwnProperty; var loggedTypeFailures = {}; var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; function setCurrentlyValidatingElement(element) { { if (element) { var owner = element._owner; var stack = describeUnknownElementTypeFrameInDEV(element.type, element._source, owner ? owner.type : null); ReactDebugCurrentFrame.setExtraStackFrame(stack); } else { ReactDebugCurrentFrame.setExtraStackFrame(null); } } } function checkPropTypes(typeSpecs, values, location, componentName, element) { { // $FlowFixMe This is okay but Flow doesn't know it. var has = Function.call.bind(hasOwnProperty); for (var typeSpecName in typeSpecs) { if (has(typeSpecs, typeSpecName)) { var error$1 = void 0; // Prop type validation may throw. In case they do, we don't want to // fail the render phase where it didn't fail before. So we log it. // After these have been cleaned up, we'll let them throw. try { // This is intentionally an invariant that gets caught. It's the same // behavior as without this statement except with a better message. if (typeof typeSpecs[typeSpecName] !== 'function') { // eslint-disable-next-line react-internal/prod-error-codes var err = Error((componentName || 'React class') + ': ' + location + ' type `' + typeSpecName + '` is invalid; ' + 'it must be a function, usually from the `prop-types` package, but received `' + typeof typeSpecs[typeSpecName] + '`.' + 'This often happens because of typos such as `PropTypes.function` instead of `PropTypes.func`.'); err.name = 'Invariant Violation'; throw err; } error$1 = typeSpecs[typeSpecName](values, typeSpecName, componentName, location, null, 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED'); } catch (ex) { error$1 = ex; } if (error$1 && !(error$1 instanceof Error)) { setCurrentlyValidatingElement(element); error('%s: type specification of %s' + ' `%s` is invalid; the type checker ' + 'function must return `null` or an `Error` but returned a %s. ' + 'You may have forgotten to pass an argument to the type checker ' + 'creator (arrayOf, instanceOf, objectOf, oneOf, oneOfType, and ' + 'shape all require an argument).', componentName || 'React class', location, typeSpecName, typeof error$1); setCurrentlyValidatingElement(null); } if (error$1 instanceof Error && !(error$1.message in loggedTypeFailures)) { // Only monitor this failure once because there tends to be a lot of the // same error. loggedTypeFailures[error$1.message] = true; setCurrentlyValidatingElement(element); error('Failed %s type: %s', location, error$1.message); setCurrentlyValidatingElement(null); } } } } } var isArrayImpl = Array.isArray; // eslint-disable-next-line no-redeclare function isArray(a) { return isArrayImpl(a); } /* * The `'' + value` pattern (used in in perf-sensitive code) throws for Symbol * and Temporal.* types. See https://github.com/facebook/react/pull/22064. * * The functions in this module will throw an easier-to-understand, * easier-to-debug exception with a clear errors message message explaining the * problem. (Instead of a confusing exception thrown inside the implementation * of the `value` object). */ // $FlowFixMe only called in DEV, so void return is not possible. function typeName(value) { { // toStringTag is needed for namespaced types like Temporal.Instant var hasToStringTag = typeof Symbol === 'function' && Symbol.toStringTag; var type = hasToStringTag && value[Symbol.toStringTag] || value.constructor.name || 'Object'; return type; } } // $FlowFixMe only called in DEV, so void return is not possible. function willCoercionThrow(value) { { try { testStringCoercion(value); return false; } catch (e) { return true; } } } function testStringCoercion(value) { // If you ended up here by following an exception call stack, here's what's // happened: you supplied an object or symbol value to React (as a prop, key, // DOM attribute, CSS property, string ref, etc.) and when React tried to // coerce it to a string using `'' + value`, an exception was thrown. // // The most common types that will cause this exception are `Symbol` instances // and Temporal objects like `Temporal.Instant`. But any object that has a // `valueOf` or `[Symbol.toPrimitive]` method that throws will also cause this // exception. (Library authors do this to prevent users from using built-in // numeric operators like `+` or comparison operators like `>=` because custom // methods are needed to perform accurate arithmetic or comparison.) // // To fix the problem, coerce this object or symbol value to a string before // passing it to React. The most reliable way is usually `String(value)`. // // To find which value is throwing, check the browser or debugger console. // Before this exception was thrown, there should be `console.error` output // that shows the type (Symbol, Temporal.PlainDate, etc.) that caused the // problem and how that type was used: key, atrribute, input value prop, etc. // In most cases, this console output also shows the component and its // ancestor components where the exception happened. // // eslint-disable-next-line react-internal/safe-string-coercion return '' + value; } function checkKeyStringCoercion(value) { { if (willCoercionThrow(value)) { error('The provided key is an unsupported type %s.' + ' This value must be coerced to a string before before using it here.', typeName(value)); return testStringCoercion(value); // throw (to help callers find troubleshooting comments) } } } var ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; var RESERVED_PROPS = { key: true, ref: true, __self: true, __source: true }; var specialPropKeyWarningShown; var specialPropRefWarningShown; function hasValidRef(config) { { if (hasOwnProperty.call(config, 'ref')) { var getter = Object.getOwnPropertyDescriptor(config, 'ref').get; if (getter && getter.isReactWarning) { return false; } } } return config.ref !== undefined; } function hasValidKey(config) { { if (hasOwnProperty.call(config, 'key')) { var getter = Object.getOwnPropertyDescriptor(config, 'key').get; if (getter && getter.isReactWarning) { return false; } } } return config.key !== undefined; } function warnIfStringRefCannotBeAutoConverted(config, self) { { if (typeof config.ref === 'string' && ReactCurrentOwner.current && self) ; } } function defineKeyPropWarningGetter(props, displayName) { { var warnAboutAccessingKey = function () { if (!specialPropKeyWarningShown) { specialPropKeyWarningShown = true; error('%s: `key` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://reactjs.org/link/special-props)', displayName); } }; warnAboutAccessingKey.isReactWarning = true; Object.defineProperty(props, 'key', { get: warnAboutAccessingKey, configurable: true }); } } function defineRefPropWarningGetter(props, displayName) { { var warnAboutAccessingRef = function () { if (!specialPropRefWarningShown) { specialPropRefWarningShown = true; error('%s: `ref` is not a prop. Trying to access it will result ' + 'in `undefined` being returned. If you need to access the same ' + 'value within the child component, you should pass it as a different ' + 'prop. (https://reactjs.org/link/special-props)', displayName); } }; warnAboutAccessingRef.isReactWarning = true; Object.defineProperty(props, 'ref', { get: warnAboutAccessingRef, configurable: true }); } } /** * Factory method to create a new React element. This no longer adheres to * the class pattern, so do not use new to call it. Also, instanceof check * will not work. Instead test $$typeof field against Symbol.for('react.element') to check * if something is a React Element. * * @param {*} type * @param {*} props * @param {*} key * @param {string|object} ref * @param {*} owner * @param {*} self A *temporary* helper to detect places where `this` is * different from the `owner` when React.createElement is called, so that we * can warn. We want to get rid of owner and replace string `ref`s with arrow * functions, and as long as `this` and owner are the same, there will be no * change in behavior. * @param {*} source An annotation object (added by a transpiler or otherwise) * indicating filename, line number, and/or other information. * @internal */ var ReactElement = function (type, key, ref, self, source, owner, props) { var element = { // This tag allows us to uniquely identify this as a React Element $$typeof: REACT_ELEMENT_TYPE, // Built-in properties that belong on the element type: type, key: key, ref: ref, props: props, // Record the component responsible for creating this element. _owner: owner }; { // The validation flag is currently mutative. We put it on // an external backing store so that we can freeze the whole object. // This can be replaced with a WeakMap once they are implemented in // commonly used development environments. element._store = {}; // To make comparing ReactElements easier for testing purposes, we make // the validation flag non-enumerable (where possible, which should // include every environment we run tests in), so the test framework // ignores it. Object.defineProperty(element._store, 'validated', { configurable: false, enumerable: false, writable: true, value: false }); // self and source are DEV only properties. Object.defineProperty(element, '_self', { configurable: false, enumerable: false, writable: false, value: self }); // Two elements created in two different places should be considered // equal for testing purposes and therefore we hide it from enumeration. Object.defineProperty(element, '_source', { configurable: false, enumerable: false, writable: false, value: source }); if (Object.freeze) { Object.freeze(element.props); Object.freeze(element); } } return element; }; /** * https://github.com/reactjs/rfcs/pull/107 * @param {*} type * @param {object} props * @param {string} key */ function jsxDEV(type, config, maybeKey, source, self) { { var propName; // Reserved names are extracted var props = {}; var key = null; var ref = null; // Currently, key can be spread in as a prop. This causes a potential // issue if key is also explicitly declared (ie.
// or
). We want to deprecate key spread, // but as an intermediary step, we will use jsxDEV for everything except //
, because we aren't currently able to tell if // key is explicitly declared to be undefined or not. if (maybeKey !== undefined) { { checkKeyStringCoercion(maybeKey); } key = '' + maybeKey; } if (hasValidKey(config)) { { checkKeyStringCoercion(config.key); } key = '' + config.key; } if (hasValidRef(config)) { ref = config.ref; warnIfStringRefCannotBeAutoConverted(config, self); } // Remaining properties are added to a new props object for (propName in config) { if (hasOwnProperty.call(config, propName) && !RESERVED_PROPS.hasOwnProperty(propName)) { props[propName] = config[propName]; } } // Resolve default props if (type && type.defaultProps) { var defaultProps = type.defaultProps; for (propName in defaultProps) { if (props[propName] === undefined) { props[propName] = defaultProps[propName]; } } } if (key || ref) { var displayName = typeof type === 'function' ? type.displayName || type.name || 'Unknown' : type; if (key) { defineKeyPropWarningGetter(props, displayName); } if (ref) { defineRefPropWarningGetter(props, displayName); } } return ReactElement(type, key, ref, self, source, ReactCurrentOwner.current, props); } } var ReactCurrentOwner$1 = ReactSharedInternals.ReactCurrentOwner; var ReactDebugCurrentFrame$1 = ReactSharedInternals.ReactDebugCurrentFrame; function setCurrentlyValidatingElement$1(element) { { if (element) { var owner = element._owner; var stack = describeUnknownElementTypeFrameInDEV(element.type, element._source, owner ? owner.type : null); ReactDebugCurrentFrame$1.setExtraStackFrame(stack); } else { ReactDebugCurrentFrame$1.setExtraStackFrame(null); } } } var propTypesMisspellWarningShown; { propTypesMisspellWarningShown = false; } /** * Verifies the object is a ReactElement. * See https://reactjs.org/docs/react-api.html#isvalidelement * @param {?object} object * @return {boolean} True if `object` is a ReactElement. * @final */ function isValidElement(object) { { return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE; } } function getDeclarationErrorAddendum() { { if (ReactCurrentOwner$1.current) { var name = getComponentNameFromType(ReactCurrentOwner$1.current.type); if (name) { return '\n\nCheck the render method of `' + name + '`.'; } } return ''; } } function getSourceInfoErrorAddendum(source) { { return ''; } } /** * Warn if there's no key explicitly set on dynamic arrays of children or * object keys are not valid. This allows us to keep track of children between * updates. */ var ownerHasKeyUseWarning = {}; function getCurrentComponentErrorInfo(parentType) { { var info = getDeclarationErrorAddendum(); if (!info) { var parentName = typeof parentType === 'string' ? parentType : parentType.displayName || parentType.name; if (parentName) { info = "\n\nCheck the top-level render call using <" + parentName + ">."; } } return info; } } /** * Warn if the element doesn't have an explicit key assigned to it. * This element is in an array. The array could grow and shrink or be * reordered. All children that haven't already been validated are required to * have a "key" property assigned to it. Error statuses are cached so a warning * will only be shown once. * * @internal * @param {ReactElement} element Element that requires a key. * @param {*} parentType element's parent's type. */ function validateExplicitKey(element, parentType) { { if (!element._store || element._store.validated || element.key != null) { return; } element._store.validated = true; var currentComponentErrorInfo = getCurrentComponentErrorInfo(parentType); if (ownerHasKeyUseWarning[currentComponentErrorInfo]) { return; } ownerHasKeyUseWarning[currentComponentErrorInfo] = true; // Usually the current owner is the offender, but if it accepts children as a // property, it may be the creator of the child that's responsible for // assigning it a key. var childOwner = ''; if (element && element._owner && element._owner !== ReactCurrentOwner$1.current) { // Give the component that originally created this child. childOwner = " It was passed a child from " + getComponentNameFromType(element._owner.type) + "."; } setCurrentlyValidatingElement$1(element); error('Each child in a list should have a unique "key" prop.' + '%s%s See https://reactjs.org/link/warning-keys for more information.', currentComponentErrorInfo, childOwner); setCurrentlyValidatingElement$1(null); } } /** * Ensure that every element either is passed in a static location, in an * array with an explicit keys property defined, or in an object literal * with valid key property. * * @internal * @param {ReactNode} node Statically passed child of any type. * @param {*} parentType node's parent's type. */ function validateChildKeys(node, parentType) { { if (typeof node !== 'object') { return; } if (isArray(node)) { for (var i = 0; i < node.length; i++) { var child = node[i]; if (isValidElement(child)) { validateExplicitKey(child, parentType); } } } else if (isValidElement(node)) { // This element was passed in a valid location. if (node._store) { node._store.validated = true; } } else if (node) { var iteratorFn = getIteratorFn(node); if (typeof iteratorFn === 'function') { // Entry iterators used to provide implicit keys, // but now we print a separate warning for them later. if (iteratorFn !== node.entries) { var iterator = iteratorFn.call(node); var step; while (!(step = iterator.next()).done) { if (isValidElement(step.value)) { validateExplicitKey(step.value, parentType); } } } } } } } /** * Given an element, validate that its props follow the propTypes definition, * provided by the type. * * @param {ReactElement} element */ function validatePropTypes(element) { { var type = element.type; if (type === null || type === undefined || typeof type === 'string') { return; } var propTypes; if (typeof type === 'function') { propTypes = type.propTypes; } else if (typeof type === 'object' && (type.$$typeof === REACT_FORWARD_REF_TYPE || // Note: Memo only checks outer props here. // Inner props are checked in the reconciler. type.$$typeof === REACT_MEMO_TYPE)) { propTypes = type.propTypes; } else { return; } if (propTypes) { // Intentionally inside to avoid triggering lazy initializers: var name = getComponentNameFromType(type); checkPropTypes(propTypes, element.props, 'prop', name, element); } else if (type.PropTypes !== undefined && !propTypesMisspellWarningShown) { propTypesMisspellWarningShown = true; // Intentionally inside to avoid triggering lazy initializers: var _name = getComponentNameFromType(type); error('Component %s declared `PropTypes` instead of `propTypes`. Did you misspell the property assignment?', _name || 'Unknown'); } if (typeof type.getDefaultProps === 'function' && !type.getDefaultProps.isReactClassApproved) { error('getDefaultProps is only used on classic React.createClass ' + 'definitions. Use a static property named `defaultProps` instead.'); } } } /** * Given a fragment, validate that it can only be provided with fragment props * @param {ReactElement} fragment */ function validateFragmentProps(fragment) { { var keys = Object.keys(fragment.props); for (var i = 0; i < keys.length; i++) { var key = keys[i]; if (key !== 'children' && key !== 'key') { setCurrentlyValidatingElement$1(fragment); error('Invalid prop `%s` supplied to `React.Fragment`. ' + 'React.Fragment can only have `key` and `children` props.', key); setCurrentlyValidatingElement$1(null); break; } } if (fragment.ref !== null) { setCurrentlyValidatingElement$1(fragment); error('Invalid attribute `ref` supplied to `React.Fragment`.'); setCurrentlyValidatingElement$1(null); } } } var didWarnAboutKeySpread = {}; function jsxWithValidation(type, props, key, isStaticChildren, source, self) { { var validType = isValidElementType(type); // We warn in this case but don't throw. We expect the element creation to // succeed and there will likely be errors in render. if (!validType) { var info = ''; if (type === undefined || typeof type === 'object' && type !== null && Object.keys(type).length === 0) { info += ' You likely forgot to export your component from the file ' + "it's defined in, or you might have mixed up default and named imports."; } var sourceInfo = getSourceInfoErrorAddendum(); if (sourceInfo) { info += sourceInfo; } else { info += getDeclarationErrorAddendum(); } var typeString; if (type === null) { typeString = 'null'; } else if (isArray(type)) { typeString = 'array'; } else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) { typeString = "<" + (getComponentNameFromType(type.type) || 'Unknown') + " />"; info = ' Did you accidentally export a JSX literal instead of a component?'; } else { typeString = typeof type; } error('React.jsx: type is invalid -- expected a string (for ' + 'built-in components) or a class/function (for composite ' + 'components) but got: %s.%s', typeString, info); } var element = jsxDEV(type, props, key, source, self); // The result can be nullish if a mock or a custom function is used. // TODO: Drop this when these are no longer allowed as the type argument. if (element == null) { return element; } // Skip key warning if the type isn't valid since our key validation logic // doesn't expect a non-string/function type and can throw confusing errors. // We don't want exception behavior to differ between dev and prod. // (Rendering will throw with a helpful message and as soon as the type is // fixed, the key warnings will appear.) if (validType) { var children = props.children; if (children !== undefined) { if (isStaticChildren) { if (isArray(children)) { for (var i = 0; i < children.length; i++) { validateChildKeys(children[i], type); } if (Object.freeze) { Object.freeze(children); } } else { error('React.jsx: Static children should always be an array. ' + 'You are likely explicitly calling React.jsxs or React.jsxDEV. ' + 'Use the Babel transform instead.'); } } else { validateChildKeys(children, type); } } } { if (hasOwnProperty.call(props, 'key')) { var componentName = getComponentNameFromType(type); var keys = Object.keys(props).filter(function (k) { return k !== 'key'; }); var beforeExample = keys.length > 0 ? '{key: someKey, ' + keys.join(': ..., ') + ': ...}' : '{key: someKey}'; if (!didWarnAboutKeySpread[componentName + beforeExample]) { var afterExample = keys.length > 0 ? '{' + keys.join(': ..., ') + ': ...}' : '{}'; error('A props object containing a "key" prop is being spread into JSX:\n' + ' let props = %s;\n' + ' <%s {...props} />\n' + 'React keys must be passed directly to JSX without using spread:\n' + ' let props = %s;\n' + ' <%s key={someKey} {...props} />', beforeExample, componentName, afterExample, componentName); didWarnAboutKeySpread[componentName + beforeExample] = true; } } } if (type === REACT_FRAGMENT_TYPE) { validateFragmentProps(element); } else { validatePropTypes(element); } return element; } } // These two functions exist to still get child warnings in dev // even with the prod transform. This means that jsxDEV is purely // opt-in behavior for better messages but that we won't stop // giving you warnings if you use production apis. function jsxWithValidationStatic(type, props, key) { { return jsxWithValidation(type, props, key, true); } } function jsxWithValidationDynamic(type, props, key) { { return jsxWithValidation(type, props, key, false); } } var jsx = jsxWithValidationDynamic ; // we may want to special case jsxs internally to take advantage of static children. // for now we can ship identical prod functions var jsxs = jsxWithValidationStatic ; reactJsxRuntime_development.Fragment = REACT_FRAGMENT_TYPE; reactJsxRuntime_development.jsx = jsx; reactJsxRuntime_development.jsxs = jsxs; })(); } { jsxRuntime.exports = reactJsxRuntime_development; } var jsxRuntimeExports = jsxRuntime.exports; // packages/react/slot/src/slot.tsx var Slot = /*#__PURE__*/React__namespace.forwardRef((props, forwardedRef) => { const { children, ...slotProps } = props; const childrenArray = React__namespace.Children.toArray(children); const slottable = childrenArray.find(isSlottable); if (slottable) { const newElement = slottable.props.children; const newChildren = childrenArray.map(child => { if (child === slottable) { if (React__namespace.Children.count(newElement) > 1) return React__namespace.Children.only(null); return /*#__PURE__*/React__namespace.isValidElement(newElement) ? newElement.props.children : null; } else { return child; } }); return /* @__PURE__ */jsxRuntimeExports.jsx(SlotClone, { ...slotProps, ref: forwardedRef, children: /*#__PURE__*/React__namespace.isValidElement(newElement) ? /*#__PURE__*/React__namespace.cloneElement(newElement, void 0, newChildren) : null }); } return /* @__PURE__ */jsxRuntimeExports.jsx(SlotClone, { ...slotProps, ref: forwardedRef, children }); }); Slot.displayName = "Slot"; var SlotClone = /*#__PURE__*/React__namespace.forwardRef((props, forwardedRef) => { const { children, ...slotProps } = props; if (/*#__PURE__*/React__namespace.isValidElement(children)) { const childrenRef = getElementRef$1(children); const props2 = mergeProps(slotProps, children.props); if (children.type !== React__namespace.Fragment) { props2.ref = forwardedRef ? composeRefs(forwardedRef, childrenRef) : childrenRef; } return /*#__PURE__*/React__namespace.cloneElement(children, props2); } return React__namespace.Children.count(children) > 1 ? React__namespace.Children.only(null) : null; }); SlotClone.displayName = "SlotClone"; var Slottable = ({ children }) => { return /* @__PURE__ */jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children }); }; function isSlottable(child) { return /*#__PURE__*/React__namespace.isValidElement(child) && child.type === Slottable; } function mergeProps(slotProps, childProps) { const overrideProps = { ...childProps }; for (const propName in childProps) { const slotPropValue = slotProps[propName]; const childPropValue = childProps[propName]; const isHandler = /^on[A-Z]/.test(propName); if (isHandler) { if (slotPropValue && childPropValue) { overrideProps[propName] = (...args) => { childPropValue(...args); slotPropValue(...args); }; } else if (slotPropValue) { overrideProps[propName] = slotPropValue; } } else if (propName === "style") { overrideProps[propName] = { ...slotPropValue, ...childPropValue }; } else if (propName === "className") { overrideProps[propName] = [slotPropValue, childPropValue].filter(Boolean).join(" "); } } return { ...slotProps, ...overrideProps }; } function getElementRef$1(element) { let getter = Object.getOwnPropertyDescriptor(element.props, "ref")?.get; let mayWarn = getter && "isReactWarning" in getter && getter.isReactWarning; if (mayWarn) { return element.ref; } getter = Object.getOwnPropertyDescriptor(element, "ref")?.get; mayWarn = getter && "isReactWarning" in getter && getter.isReactWarning; if (mayWarn) { return element.props.ref; } return element.props.ref || element.ref; } function r(e) { var t, f, n = ""; if ("string" == typeof e || "number" == typeof e) n += e;else if ("object" == typeof e) if (Array.isArray(e)) { var o = e.length; for (t = 0; t < o; t++) e[t] && (f = r(e[t])) && (n && (n += " "), n += f); } else for (f in e) e[f] && (n && (n += " "), n += f); return n; } function clsx() { for (var e, t, f = 0, n = "", o = arguments.length; f < o; f++) (e = arguments[f]) && (t = r(e)) && (n && (n += " "), n += t); return n; } const falsyToString = value => typeof value === "boolean" ? `${value}` : value === 0 ? "0" : value; const cx = clsx; const cva = (base, config) => props => { var _config_compoundVariants; if ((config === null || config === void 0 ? void 0 : config.variants) == null) return cx(base, props === null || props === void 0 ? void 0 : props.class, props === null || props === void 0 ? void 0 : props.className); const { variants, defaultVariants } = config; const getVariantClassNames = Object.keys(variants).map(variant => { const variantProp = props === null || props === void 0 ? void 0 : props[variant]; const defaultVariantProp = defaultVariants === null || defaultVariants === void 0 ? void 0 : defaultVariants[variant]; if (variantProp === null) return null; const variantKey = falsyToString(variantProp) || falsyToString(defaultVariantProp); return variants[variant][variantKey]; }); const propsWithoutUndefined = props && Object.entries(props).reduce((acc, param) => { let [key, value] = param; if (value === undefined) { return acc; } acc[key] = value; return acc; }, {}); const getCompoundVariantClassNames = config === null || config === void 0 ? void 0 : (_config_compoundVariants = config.compoundVariants) === null || _config_compoundVariants === void 0 ? void 0 : _config_compoundVariants.reduce((acc, param) => { let { class: cvClass, className: cvClassName, ...compoundVariantOptions } = param; return Object.entries(compoundVariantOptions).every(param => { let [key, value] = param; return Array.isArray(value) ? value.includes({ ...defaultVariants, ...propsWithoutUndefined }[key]) : { ...defaultVariants, ...propsWithoutUndefined }[key] === value; }) ? [...acc, cvClass, cvClassName] : acc; }, []); return cx(base, getVariantClassNames, getCompoundVariantClassNames, props === null || props === void 0 ? void 0 : props.class, props === null || props === void 0 ? void 0 : props.className); }; const CLASS_PART_SEPARATOR = '-'; const createClassGroupUtils = config => { const classMap = createClassMap(config); const { conflictingClassGroups, conflictingClassGroupModifiers } = config; const getClassGroupId = className => { const classParts = className.split(CLASS_PART_SEPARATOR); // Classes like `-inset-1` produce an empty string as first classPart. We assume that classes for negative values are used correctly and remove it from classParts. if (classParts[0] === '' && classParts.length !== 1) { classParts.shift(); } return getGroupRecursive(classParts, classMap) || getGroupIdForArbitraryProperty(className); }; const getConflictingClassGroupIds = (classGroupId, hasPostfixModifier) => { const conflicts = conflictingClassGroups[classGroupId] || []; if (hasPostfixModifier && conflictingClassGroupModifiers[classGroupId]) { return [...conflicts, ...conflictingClassGroupModifiers[classGroupId]]; } return conflicts; }; return { getClassGroupId, getConflictingClassGroupIds }; }; const getGroupRecursive = (classParts, classPartObject) => { if (classParts.length === 0) { return classPartObject.classGroupId; } const currentClassPart = classParts[0]; const nextClassPartObject = classPartObject.nextPart.get(currentClassPart); const classGroupFromNextClassPart = nextClassPartObject ? getGroupRecursive(classParts.slice(1), nextClassPartObject) : undefined; if (classGroupFromNextClassPart) { return classGroupFromNextClassPart; } if (classPartObject.validators.length === 0) { return undefined; } const classRest = classParts.join(CLASS_PART_SEPARATOR); return classPartObject.validators.find(({ validator }) => validator(classRest))?.classGroupId; }; const arbitraryPropertyRegex = /^\[(.+)\]$/; const getGroupIdForArbitraryProperty = className => { if (arbitraryPropertyRegex.test(className)) { const arbitraryPropertyClassName = arbitraryPropertyRegex.exec(className)[1]; const property = arbitraryPropertyClassName?.substring(0, arbitraryPropertyClassName.indexOf(':')); if (property) { // I use two dots here because one dot is used as prefix for class groups in plugins return 'arbitrary..' + property; } } }; /** * Exported for testing only */ const createClassMap = config => { const { theme, classGroups } = config; const classMap = { nextPart: new Map(), validators: [] }; for (const classGroupId in classGroups) { processClassesRecursively(classGroups[classGroupId], classMap, classGroupId, theme); } return classMap; }; const processClassesRecursively = (classGroup, classPartObject, classGroupId, theme) => { classGroup.forEach(classDefinition => { if (typeof classDefinition === 'string') { const classPartObjectToEdit = classDefinition === '' ? classPartObject : getPart(classPartObject, classDefinition); classPartObjectToEdit.classGroupId = classGroupId; return; } if (typeof classDefinition === 'function') { if (isThemeGetter(classDefinition)) { processClassesRecursively(classDefinition(theme), classPartObject, classGroupId, theme); return; } classPartObject.validators.push({ validator: classDefinition, classGroupId }); return; } Object.entries(classDefinition).forEach(([key, classGroup]) => { processClassesRecursively(classGroup, getPart(classPartObject, key), classGroupId, theme); }); }); }; const getPart = (classPartObject, path) => { let currentClassPartObject = classPartObject; path.split(CLASS_PART_SEPARATOR).forEach(pathPart => { if (!currentClassPartObject.nextPart.has(pathPart)) { currentClassPartObject.nextPart.set(pathPart, { nextPart: new Map(), validators: [] }); } currentClassPartObject = currentClassPartObject.nextPart.get(pathPart); }); return currentClassPartObject; }; const isThemeGetter = func => func.isThemeGetter; // LRU cache inspired from hashlru (https://github.com/dominictarr/hashlru/blob/v1.0.4/index.js) but object replaced with Map to improve performance const createLruCache = maxCacheSize => { if (maxCacheSize < 1) { return { get: () => undefined, set: () => {} }; } let cacheSize = 0; let cache = new Map(); let previousCache = new Map(); const update = (key, value) => { cache.set(key, value); cacheSize++; if (cacheSize > maxCacheSize) { cacheSize = 0; previousCache = cache; cache = new Map(); } }; return { get(key) { let value = cache.get(key); if (value !== undefined) { return value; } if ((value = previousCache.get(key)) !== undefined) { update(key, value); return value; } }, set(key, value) { if (cache.has(key)) { cache.set(key, value); } else { update(key, value); } } }; }; const IMPORTANT_MODIFIER = '!'; const MODIFIER_SEPARATOR = ':'; const MODIFIER_SEPARATOR_LENGTH = MODIFIER_SEPARATOR.length; const createParseClassName = config => { const { prefix, experimentalParseClassName } = config; /** * Parse class name into parts. * * Inspired by `splitAtTopLevelOnly` used in Tailwind CSS * @see https://github.com/tailwindlabs/tailwindcss/blob/v3.2.2/src/util/splitAtTopLevelOnly.js */ let parseClassName = className => { const modifiers = []; let bracketDepth = 0; let parenDepth = 0; let modifierStart = 0; let postfixModifierPosition; for (let index = 0; index < className.length; index++) { let currentCharacter = className[index]; if (bracketDepth === 0 && parenDepth === 0) { if (currentCharacter === MODIFIER_SEPARATOR) { modifiers.push(className.slice(modifierStart, index)); modifierStart = index + MODIFIER_SEPARATOR_LENGTH; continue; } if (currentCharacter === '/') { postfixModifierPosition = index; continue; } } if (currentCharacter === '[') { bracketDepth++; } else if (currentCharacter === ']') { bracketDepth--; } else if (currentCharacter === '(') { parenDepth++; } else if (currentCharacter === ')') { parenDepth--; } } const baseClassNameWithImportantModifier = modifiers.length === 0 ? className : className.substring(modifierStart); const baseClassName = stripImportantModifier(baseClassNameWithImportantModifier); const hasImportantModifier = baseClassName !== baseClassNameWithImportantModifier; const maybePostfixModifierPosition = postfixModifierPosition && postfixModifierPosition > modifierStart ? postfixModifierPosition - modifierStart : undefined; return { modifiers, hasImportantModifier, baseClassName, maybePostfixModifierPosition }; }; if (prefix) { const fullPrefix = prefix + MODIFIER_SEPARATOR; const parseClassNameOriginal = parseClassName; parseClassName = className => className.startsWith(fullPrefix) ? parseClassNameOriginal(className.substring(fullPrefix.length)) : { isExternal: true, modifiers: [], hasImportantModifier: false, baseClassName: className, maybePostfixModifierPosition: undefined }; } if (experimentalParseClassName) { const parseClassNameOriginal = parseClassName; parseClassName = className => experimentalParseClassName({ className, parseClassName: parseClassNameOriginal }); } return parseClassName; }; const stripImportantModifier = baseClassName => { if (baseClassName.endsWith(IMPORTANT_MODIFIER)) { return baseClassName.substring(0, baseClassName.length - 1); } /** * In Tailwind CSS v3 the important modifier was at the start of the base class name. This is still supported for legacy reasons. * @see https://github.com/dcastil/tailwind-merge/issues/513#issuecomment-2614029864 */ if (baseClassName.startsWith(IMPORTANT_MODIFIER)) { return baseClassName.substring(1); } return baseClassName; }; /** * Sorts modifiers according to following schema: * - Predefined modifiers are sorted alphabetically * - When an arbitrary variant appears, it must be preserved which modifiers are before and after it */ const createSortModifiers = config => { const orderSensitiveModifiers = Object.fromEntries(config.orderSensitiveModifiers.map(modifier => [modifier, true])); const sortModifiers = modifiers => { if (modifiers.length <= 1) { return modifiers; } const sortedModifiers = []; let unsortedModifiers = []; modifiers.forEach(modifier => { const isPositionSensitive = modifier[0] === '[' || orderSensitiveModifiers[modifier]; if (isPositionSensitive) { sortedModifiers.push(...unsortedModifiers.sort(), modifier); unsortedModifiers = []; } else { unsortedModifiers.push(modifier); } }); sortedModifiers.push(...unsortedModifiers.sort()); return sortedModifiers; }; return sortModifiers; }; const createConfigUtils = config => ({ cache: createLruCache(config.cacheSize), parseClassName: createParseClassName(config), sortModifiers: createSortModifiers(config), ...createClassGroupUtils(config) }); const SPLIT_CLASSES_REGEX = /\s+/; const mergeClassList = (classList, configUtils) => { const { parseClassName, getClassGroupId, getConflictingClassGroupIds, sortModifiers } = configUtils; /** * Set of classGroupIds in following format: * `{importantModifier}{variantModifiers}{classGroupId}` * @example 'float' * @example 'hover:focus:bg-color' * @example 'md:!pr' */ const classGroupsInConflict = []; const classNames = classList.trim().split(SPLIT_CLASSES_REGEX); let result = ''; for (let index = classNames.length - 1; index >= 0; index -= 1) { const originalClassName = classNames[index]; const { isExternal, modifiers, hasImportantModifier, baseClassName, maybePostfixModifierPosition } = parseClassName(originalClassName); if (isExternal) { result = originalClassName + (result.length > 0 ? ' ' + result : result); continue; } let hasPostfixModifier = !!maybePostfixModifierPosition; let classGroupId = getClassGroupId(hasPostfixModifier ? baseClassName.substring(0, maybePostfixModifierPosition) : baseClassName); if (!classGroupId) { if (!hasPostfixModifier) { // Not a Tailwind class result = originalClassName + (result.length > 0 ? ' ' + result : result); continue; } classGroupId = getClassGroupId(baseClassName); if (!classGroupId) { // Not a Tailwind class result = originalClassName + (result.length > 0 ? ' ' + result : result); continue; } hasPostfixModifier = false; } const variantModifier = sortModifiers(modifiers).join(':'); const modifierId = hasImportantModifier ? variantModifier + IMPORTANT_MODIFIER : variantModifier; const classId = modifierId + classGroupId; if (classGroupsInConflict.includes(classId)) { // Tailwind class omitted due to conflict continue; } classGroupsInConflict.push(classId); const conflictGroups = getConflictingClassGroupIds(classGroupId, hasPostfixModifier); for (let i = 0; i < conflictGroups.length; ++i) { const group = conflictGroups[i]; classGroupsInConflict.push(modifierId + group); } // Tailwind class not in conflict result = originalClassName + (result.length > 0 ? ' ' + result : result); } return result; }; /** * The code in this file is copied from https://github.com/lukeed/clsx and modified to suit the needs of tailwind-merge better. * * Specifically: * - Runtime code from https://github.com/lukeed/clsx/blob/v1.2.1/src/index.js * - TypeScript types from https://github.com/lukeed/clsx/blob/v1.2.1/clsx.d.ts * * Original code has MIT license: Copyright (c) Luke Edwards (lukeed.com) */ function twJoin() { let index = 0; let argument; let resolvedValue; let string = ''; while (index < arguments.length) { if (argument = arguments[index++]) { if (resolvedValue = toValue(argument)) { string && (string += ' '); string += resolvedValue; } } } return string; } const toValue = mix => { if (typeof mix === 'string') { return mix; } let resolvedValue; let string = ''; for (let k = 0; k < mix.length; k++) { if (mix[k]) { if (resolvedValue = toValue(mix[k])) { string && (string += ' '); string += resolvedValue; } } } return string; }; function createTailwindMerge(createConfigFirst, ...createConfigRest) { let configUtils; let cacheGet; let cacheSet; let functionToCall = initTailwindMerge; function initTailwindMerge(classList) { const config = createConfigRest.reduce((previousConfig, createConfigCurrent) => createConfigCurrent(previousConfig), createConfigFirst()); configUtils = createConfigUtils(config); cacheGet = configUtils.cache.get; cacheSet = configUtils.cache.set; functionToCall = tailwindMerge; return tailwindMerge(classList); } function tailwindMerge(classList) { const cachedResult = cacheGet(classList); if (cachedResult) { return cachedResult; } const result = mergeClassList(classList, configUtils); cacheSet(classList, result); return result; } return function callTailwindMerge() { return functionToCall(twJoin.apply(null, arguments)); }; } const fromTheme = key => { const themeGetter = theme => theme[key] || []; themeGetter.isThemeGetter = true; return themeGetter; }; const arbitraryValueRegex = /^\[(?:(\w[\w-]*):)?(.+)\]$/i; const arbitraryVariableRegex = /^\((?:(\w[\w-]*):)?(.+)\)$/i; const fractionRegex = /^\d+\/\d+$/; const tshirtUnitRegex = /^(\d+(\.\d+)?)?(xs|sm|md|lg|xl)$/; const lengthUnitRegex = /\d+(%|px|r?em|[sdl]?v([hwib]|min|max)|pt|pc|in|cm|mm|cap|ch|ex|r?lh|cq(w|h|i|b|min|max))|\b(calc|min|max|clamp)\(.+\)|^0$/; const colorFunctionRegex = /^(rgba?|hsla?|hwb|(ok)?(lab|lch))\(.+\)$/; // Shadow always begins with x and y offset separated by underscore optionally prepended by inset const shadowRegex = /^(inset_)?-?((\d+)?\.?(\d+)[a-z]+|0)_-?((\d+)?\.?(\d+)[a-z]+|0)/; const imageRegex = /^(url|image|image-set|cross-fade|element|(repeating-)?(linear|radial|conic)-gradient)\(.+\)$/; const isFraction = value => fractionRegex.test(value); const isNumber = value => Boolean(value) && !Number.isNaN(Number(value)); const isInteger$1 = value => Boolean(value) && Number.isInteger(Number(value)); const isPercent = value => value.endsWith('%') && isNumber(value.slice(0, -1)); const isTshirtSize = value => tshirtUnitRegex.test(value); const isAny = () => true; const isLengthOnly = value => // `colorFunctionRegex` check is necessary because color functions can have percentages in them which which would be incorrectly classified as lengths. // For example, `hsl(0 0% 0%)` would be classified as a length without this check. // I could also use lookbehind assertion in `lengthUnitRegex` but that isn't supported widely enough. lengthUnitRegex.test(value) && !colorFunctionRegex.test(value); const isNever = () => false; const isShadow = value => shadowRegex.test(value); const isImage = value => imageRegex.test(value); const isAnyNonArbitrary = value => !isArbitraryValue(value) && !isArbitraryVariable(value); const isArbitrarySize = value => getIsArbitraryValue(value, isLabelSize, isNever); const isArbitraryValue = value => arbitraryValueRegex.test(value); const isArbitraryLength = value => getIsArbitraryValue(value, isLabelLength, isLengthOnly); const isArbitraryNumber = value => getIsArbitraryValue(value, isLabelNumber, isNumber); const isArbitraryPosition = value => getIsArbitraryValue(value, isLabelPosition, isNever); const isArbitraryImage = value => getIsArbitraryValue(value, isLabelImage, isImage); const isArbitraryShadow = value => getIsArbitraryValue(value, isNever, isShadow); const isArbitraryVariable = value => arbitraryVariableRegex.test(value); const isArbitraryVariableLength = value => getIsArbitraryVariable(value, isLabelLength); const isArbitraryVariableFamilyName = value => getIsArbitraryVariable(value, isLabelFamilyName); const isArbitraryVariablePosition = value => getIsArbitraryVariable(value, isLabelPosition); const isArbitraryVariableSize = value => getIsArbitraryVariable(value, isLabelSize); const isArbitraryVariableImage = value => getIsArbitraryVariable(value, isLabelImage); const isArbitraryVariableShadow = value => getIsArbitraryVariable(value, isLabelShadow, true); // Helpers const getIsArbitraryValue = (value, testLabel, testValue) => { const result = arbitraryValueRegex.exec(value); if (result) { if (result[1]) { return testLabel(result[1]); } return testValue(result[2]); } return false; }; const getIsArbitraryVariable = (value, testLabel, shouldMatchNoLabel = false) => { const result = arbitraryVariableRegex.exec(value); if (result) { if (result[1]) { return testLabel(result[1]); } return shouldMatchNoLabel; } return false; }; // Labels const isLabelPosition = label => label === 'position'; const imageLabels = /*#__PURE__*/new Set(['image', 'url']); const isLabelImage = label => imageLabels.has(label); const sizeLabels = /*#__PURE__*/new Set(['length', 'size', 'percentage']); const isLabelSize = label => sizeLabels.has(label); const isLabelLength = label => label === 'length'; const isLabelNumber = label => label === 'number'; const isLabelFamilyName = label => label === 'family-name'; const isLabelShadow = label => label === 'shadow'; const getDefaultConfig = () => { /** * Theme getters for theme variable namespaces * @see https://tailwindcss.com/docs/theme#theme-variable-namespaces */ /***/ const themeColor = fromTheme('color'); const themeFont = fromTheme('font'); const themeText = fromTheme('text'); const themeFontWeight = fromTheme('font-weight'); const themeTracking = fromTheme('tracking'); const themeLeading = fromTheme('leading'); const themeBreakpoint = fromTheme('breakpoint'); const themeContainer = fromTheme('container'); const themeSpacing = fromTheme('spacing'); const themeRadius = fromTheme('radius'); const themeShadow = fromTheme('shadow'); const themeInsetShadow = fromTheme('inset-shadow'); const themeDropShadow = fromTheme('drop-shadow'); const themeBlur = fromTheme('blur'); const themePerspective = fromTheme('perspective'); const themeAspect = fromTheme('aspect'); const themeEase = fromTheme('ease'); const themeAnimate = fromTheme('animate'); /** * Helpers to avoid repeating the same scales * * We use functions that create a new array every time they're called instead of static arrays. * This ensures that users who modify any scale by mutating the array (e.g. with `array.push(element)`) don't accidentally mutate arrays in other parts of the config. */ /***/ const scaleBreak = () => ['auto', 'avoid', 'all', 'avoid-page', 'page', 'left', 'right', 'column']; const scalePosition = () => ['bottom', 'center', 'left', 'left-bottom', 'left-top', 'right', 'right-bottom', 'right-top', 'top']; const scaleOverflow = () => ['auto', 'hidden', 'clip', 'visible', 'scroll']; const scaleOverscroll = () => ['auto', 'contain', 'none']; const scaleUnambiguousSpacing = () => [isArbitraryVariable, isArbitraryValue, themeSpacing]; const scaleInset = () => [isFraction, 'full', 'auto', ...scaleUnambiguousSpacing()]; const scaleGridTemplateColsRows = () => [isInteger$1, 'none', 'subgrid', isArbitraryVariable, isArbitraryValue]; const scaleGridColRowStartAndEnd = () => ['auto', { span: ['full', isInteger$1, isArbitraryVariable, isArbitraryValue] }, isArbitraryVariable, isArbitraryValue]; const scaleGridColRowStartOrEnd = () => [isInteger$1, 'auto', isArbitraryVariable, isArbitraryValue]; const scaleGridAutoColsRows = () => ['auto', 'min', 'max', 'fr', isArbitraryVariable, isArbitraryValue]; const scaleAlignPrimaryAxis = () => ['start', 'end', 'center', 'between', 'around', 'evenly', 'stretch', 'baseline']; const scaleAlignSecondaryAxis = () => ['start', 'end', 'center', 'stretch']; const scaleMargin = () => ['auto', ...scaleUnambiguousSpacing()]; const scaleSizing = () => [isFraction, 'auto', 'full', 'dvw', 'dvh', 'lvw', 'lvh', 'svw', 'svh', 'min', 'max', 'fit', ...scaleUnambiguousSpacing()]; const scaleColor = () => [themeColor, isArbitraryVariable, isArbitraryValue]; const scaleGradientStopPosition = () => [isPercent, isArbitraryLength]; const scaleRadius = () => [ // Deprecated since Tailwind CSS v4.0.0 '', 'none', 'full', themeRadius, isArbitraryVariable, isArbitraryValue]; const scaleBorderWidth = () => ['', isNumber, isArbitraryVariableLength, isArbitraryLength]; const scaleLineStyle = () => ['solid', 'dashed', 'dotted', 'double']; const scaleBlendMode = () => ['normal', 'multiply', 'screen', 'overlay', 'darken', 'lighten', 'color-dodge', 'color-burn', 'hard-light', 'soft-light', 'difference', 'exclusion', 'hue', 'saturation', 'color', 'luminosity']; const scaleBlur = () => [ // Deprecated since Tailwind CSS v4.0.0 '', 'none', themeBlur, isArbitraryVariable, isArbitraryValue]; const scaleOrigin = () => ['center', 'top', 'top-right', 'right', 'bottom-right', 'bottom', 'bottom-left', 'left', 'top-left', isArbitraryVariable, isArbitraryValue]; const scaleRotate = () => ['none', isNumber, isArbitraryVariable, isArbitraryValue]; const scaleScale = () => ['none', isNumber, isArbitraryVariable, isArbitraryValue]; const scaleSkew = () => [isNumber, isArbitraryVariable, isArbitraryValue]; const scaleTranslate = () => [isFraction, 'full', ...scaleUnambiguousSpacing()]; return { cacheSize: 500, theme: { animate: ['spin', 'ping', 'pulse', 'bounce'], aspect: ['video'], blur: [isTshirtSize], breakpoint: [isTshirtSize], color: [isAny], container: [isTshirtSize], 'drop-shadow': [isTshirtSize], ease: ['in', 'out', 'in-out'], font: [isAnyNonArbitrary], 'font-weight': ['thin', 'extralight', 'light', 'normal', 'medium', 'semibold', 'bold', 'extrabold', 'black'], 'inset-shadow': [isTshirtSize], leading: ['none', 'tight', 'snug', 'normal', 'relaxed', 'loose'], perspective: ['dramatic', 'near', 'normal', 'midrange', 'distant', 'none'], radius: [isTshirtSize], shadow: [isTshirtSize], spacing: ['px', isNumber], text: [isTshirtSize], tracking: ['tighter', 'tight', 'normal', 'wide', 'wider', 'widest'] }, classGroups: { // -------------- // --- Layout --- // -------------- /** * Aspect Ratio * @see https://tailwindcss.com/docs/aspect-ratio */ aspect: [{ aspect: ['auto', 'square', isFraction, isArbitraryValue, isArbitraryVariable, themeAspect] }], /** * Container * @see https://tailwindcss.com/docs/container * @deprecated since Tailwind CSS v4.0.0 */ container: ['container'], /** * Columns * @see https://tailwindcss.com/docs/columns */ columns: [{ columns: [isNumber, isArbitraryValue, isArbitraryVariable, themeContainer] }], /** * Break After * @see https://tailwindcss.com/docs/break-after */ 'break-after': [{ 'break-after': scaleBreak() }], /** * Break Before * @see https://tailwindcss.com/docs/break-before */ 'break-before': [{ 'break-before': scaleBreak() }], /** * Break Inside * @see https://tailwindcss.com/docs/break-inside */ 'break-inside': [{ 'break-inside': ['auto', 'avoid', 'avoid-page', 'avoid-column'] }], /** * Box Decoration Break * @see https://tailwindcss.com/docs/box-decoration-break */ 'box-decoration': [{ 'box-decoration': ['slice', 'clone'] }], /** * Box Sizing * @see https://tailwindcss.com/docs/box-sizing */ box: [{ box: ['border', 'content'] }], /** * Display * @see https://tailwindcss.com/docs/display */ display: ['block', 'inline-block', 'inline', 'flex', 'inline-flex', 'table', 'inline-table', 'table-caption', 'table-cell', 'table-column', 'table-column-group', 'table-footer-group', 'table-header-group', 'table-row-group', 'table-row', 'flow-root', 'grid', 'inline-grid', 'contents', 'list-item', 'hidden'], /** * Screen Reader Only * @see https://tailwindcss.com/docs/display#screen-reader-only */ sr: ['sr-only', 'not-sr-only'], /** * Floats * @see https://tailwindcss.com/docs/float */ float: [{ float: ['right', 'left', 'none', 'start', 'end'] }], /** * Clear * @see https://tailwindcss.com/docs/clear */ clear: [{ clear: ['left', 'right', 'both', 'none', 'start', 'end'] }], /** * Isolation * @see https://tailwindcss.com/docs/isolation */ isolation: ['isolate', 'isolation-auto'], /** * Object Fit * @see https://tailwindcss.com/docs/object-fit */ 'object-fit': [{ object: ['contain', 'cover', 'fill', 'none', 'scale-down'] }], /** * Object Position * @see https://tailwindcss.com/docs/object-position */ 'object-position': [{ object: [...scalePosition(), isArbitraryValue, isArbitraryVariable] }], /** * Overflow * @see https://tailwindcss.com/docs/overflow */ overflow: [{ overflow: scaleOverflow() }], /** * Overflow X * @see https://tailwindcss.com/docs/overflow */ 'overflow-x': [{ 'overflow-x': scaleOverflow() }], /** * Overflow Y * @see https://tailwindcss.com/docs/overflow */ 'overflow-y': [{ 'overflow-y': scaleOverflow() }], /** * Overscroll Behavior * @see https://tailwindcss.com/docs/overscroll-behavior */ overscroll: [{ overscroll: scaleOverscroll() }], /** * Overscroll Behavior X * @see https://tailwindcss.com/docs/overscroll-behavior */ 'overscroll-x': [{ 'overscroll-x': scaleOverscroll() }], /** * Overscroll Behavior Y * @see https://tailwindcss.com/docs/overscroll-behavior */ 'overscroll-y': [{ 'overscroll-y': scaleOverscroll() }], /** * Position * @see https://tailwindcss.com/docs/position */ position: ['static', 'fixed', 'absolute', 'relative', 'sticky'], /** * Top / Right / Bottom / Left * @see https://tailwindcss.com/docs/top-right-bottom-left */ inset: [{ inset: scaleInset() }], /** * Right / Left * @see https://tailwindcss.com/docs/top-right-bottom-left */ 'inset-x': [{ 'inset-x': scaleInset() }], /** * Top / Bottom * @see https://tailwindcss.com/docs/top-right-bottom-left */ 'inset-y': [{ 'inset-y': scaleInset() }], /** * Start * @see https://tailwindcss.com/docs/top-right-bottom-left */ start: [{ start: scaleInset() }], /** * End * @see https://tailwindcss.com/docs/top-right-bottom-left */ end: [{ end: scaleInset() }], /** * Top * @see https://tailwindcss.com/docs/top-right-bottom-left */ top: [{ top: scaleInset() }], /** * Right * @see https://tailwindcss.com/docs/top-right-bottom-left */ right: [{ right: scaleInset() }], /** * Bottom * @see https://tailwindcss.com/docs/top-right-bottom-left */ bottom: [{ bottom: scaleInset() }], /** * Left * @see https://tailwindcss.com/docs/top-right-bottom-left */ left: [{ left: scaleInset() }], /** * Visibility * @see https://tailwindcss.com/docs/visibility */ visibility: ['visible', 'invisible', 'collapse'], /** * Z-Index * @see https://tailwindcss.com/docs/z-index */ z: [{ z: [isInteger$1, 'auto', isArbitraryVariable, isArbitraryValue] }], // ------------------------ // --- Flexbox and Grid --- // ------------------------ /** * Flex Basis * @see https://tailwindcss.com/docs/flex-basis */ basis: [{ basis: [isFraction, 'full', 'auto', themeContainer, ...scaleUnambiguousSpacing()] }], /** * Flex Direction * @see https://tailwindcss.com/docs/flex-direction */ 'flex-direction': [{ flex: ['row', 'row-reverse', 'col', 'col-reverse'] }], /** * Flex Wrap * @see https://tailwindcss.com/docs/flex-wrap */ 'flex-wrap': [{ flex: ['nowrap', 'wrap', 'wrap-reverse'] }], /** * Flex * @see https://tailwindcss.com/docs/flex */ flex: [{ flex: [isNumber, isFraction, 'auto', 'initial', 'none', isArbitraryValue] }], /** * Flex Grow * @see https://tailwindcss.com/docs/flex-grow */ grow: [{ grow: ['', isNumber, isArbitraryVariable, isArbitraryValue] }], /** * Flex Shrink * @see https://tailwindcss.com/docs/flex-shrink */ shrink: [{ shrink: ['', isNumber, isArbitraryVariable, isArbitraryValue] }], /** * Order * @see https://tailwindcss.com/docs/order */ order: [{ order: [isInteger$1, 'first', 'last', 'none', isArbitraryVariable, isArbitraryValue] }], /** * Grid Template Columns * @see https://tailwindcss.com/docs/grid-template-columns */ 'grid-cols': [{ 'grid-cols': scaleGridTemplateColsRows() }], /** * Grid Column Start / End * @see https://tailwindcss.com/docs/grid-column */ 'col-start-end': [{ col: scaleGridColRowStartAndEnd() }], /** * Grid Column Start * @see https://tailwindcss.com/docs/grid-column */ 'col-start': [{ 'col-start': scaleGridColRowStartOrEnd() }], /** * Grid Column End * @see https://tailwindcss.com/docs/grid-column */ 'col-end': [{ 'col-end': scaleGridColRowStartOrEnd() }], /** * Grid Template Rows * @see https://tailwindcss.com/docs/grid-template-rows */ 'grid-rows': [{ 'grid-rows': scaleGridTemplateColsRows() }], /** * Grid Row Start / End * @see https://tailwindcss.com/docs/grid-row */ 'row-start-end': [{ row: scaleGridColRowStartAndEnd() }], /** * Grid Row Start * @see https://tailwindcss.com/docs/grid-row */ 'row-start': [{ 'row-start': scaleGridColRowStartOrEnd() }], /** * Grid Row End * @see https://tailwindcss.com/docs/grid-row */ 'row-end': [{ 'row-end': scaleGridColRowStartOrEnd() }], /** * Grid Auto Flow * @see https://tailwindcss.com/docs/grid-auto-flow */ 'grid-flow': [{ 'grid-flow': ['row', 'col', 'dense', 'row-dense', 'col-dense'] }], /** * Grid Auto Columns * @see https://tailwindcss.com/docs/grid-auto-columns */ 'auto-cols': [{ 'auto-cols': scaleGridAutoColsRows() }], /** * Grid Auto Rows * @see https://tailwindcss.com/docs/grid-auto-rows */ 'auto-rows': [{ 'auto-rows': scaleGridAutoColsRows() }], /** * Gap * @see https://tailwindcss.com/docs/gap */ gap: [{ gap: scaleUnambiguousSpacing() }], /** * Gap X * @see https://tailwindcss.com/docs/gap */ 'gap-x': [{ 'gap-x': scaleUnambiguousSpacing() }], /** * Gap Y * @see https://tailwindcss.com/docs/gap */ 'gap-y': [{ 'gap-y': scaleUnambiguousSpacing() }], /** * Justify Content * @see https://tailwindcss.com/docs/justify-content */ 'justify-content': [{ justify: [...scaleAlignPrimaryAxis(), 'normal'] }], /** * Justify Items * @see https://tailwindcss.com/docs/justify-items */ 'justify-items': [{ 'justify-items': [...scaleAlignSecondaryAxis(), 'normal'] }], /** * Justify Self * @see https://tailwindcss.com/docs/justify-self */ 'justify-self': [{ 'justify-self': ['auto', ...scaleAlignSecondaryAxis()] }], /** * Align Content * @see https://tailwindcss.com/docs/align-content */ 'align-content': [{ content: ['normal', ...scaleAlignPrimaryAxis()] }], /** * Align Items * @see https://tailwindcss.com/docs/align-items */ 'align-items': [{ items: [...scaleAlignSecondaryAxis(), 'baseline'] }], /** * Align Self * @see https://tailwindcss.com/docs/align-self */ 'align-self': [{ self: ['auto', ...scaleAlignSecondaryAxis(), 'baseline'] }], /** * Place Content * @see https://tailwindcss.com/docs/place-content */ 'place-content': [{ 'place-content': scaleAlignPrimaryAxis() }], /** * Place Items * @see https://tailwindcss.com/docs/place-items */ 'place-items': [{ 'place-items': [...scaleAlignSecondaryAxis(), 'baseline'] }], /** * Place Self * @see https://tailwindcss.com/docs/place-self */ 'place-self': [{ 'place-self': ['auto', ...scaleAlignSecondaryAxis()] }], // Spacing /** * Padding * @see https://tailwindcss.com/docs/padding */ p: [{ p: scaleUnambiguousSpacing() }], /** * Padding X * @see https://tailwindcss.com/docs/padding */ px: [{ px: scaleUnambiguousSpacing() }], /** * Padding Y * @see https://tailwindcss.com/docs/padding */ py: [{ py: scaleUnambiguousSpacing() }], /** * Padding Start * @see https://tailwindcss.com/docs/padding */ ps: [{ ps: scaleUnambiguousSpacing() }], /** * Padding End * @see https://tailwindcss.com/docs/padding */ pe: [{ pe: scaleUnambiguousSpacing() }], /** * Padding Top * @see https://tailwindcss.com/docs/padding */ pt: [{ pt: scaleUnambiguousSpacing() }], /** * Padding Right * @see https://tailwindcss.com/docs/padding */ pr: [{ pr: scaleUnambiguousSpacing() }], /** * Padding Bottom * @see https://tailwindcss.com/docs/padding */ pb: [{ pb: scaleUnambiguousSpacing() }], /** * Padding Left * @see https://tailwindcss.com/docs/padding */ pl: [{ pl: scaleUnambiguousSpacing() }], /** * Margin * @see https://tailwindcss.com/docs/margin */ m: [{ m: scaleMargin() }], /** * Margin X * @see https://tailwindcss.com/docs/margin */ mx: [{ mx: scaleMargin() }], /** * Margin Y * @see https://tailwindcss.com/docs/margin */ my: [{ my: scaleMargin() }], /** * Margin Start * @see https://tailwindcss.com/docs/margin */ ms: [{ ms: scaleMargin() }], /** * Margin End * @see https://tailwindcss.com/docs/margin */ me: [{ me: scaleMargin() }], /** * Margin Top * @see https://tailwindcss.com/docs/margin */ mt: [{ mt: scaleMargin() }], /** * Margin Right * @see https://tailwindcss.com/docs/margin */ mr: [{ mr: scaleMargin() }], /** * Margin Bottom * @see https://tailwindcss.com/docs/margin */ mb: [{ mb: scaleMargin() }], /** * Margin Left * @see https://tailwindcss.com/docs/margin */ ml: [{ ml: scaleMargin() }], /** * Space Between X * @see https://tailwindcss.com/docs/margin#adding-space-between-children */ 'space-x': [{ 'space-x': scaleUnambiguousSpacing() }], /** * Space Between X Reverse * @see https://tailwindcss.com/docs/margin#adding-space-between-children */ 'space-x-reverse': ['space-x-reverse'], /** * Space Between Y * @see https://tailwindcss.com/docs/margin#adding-space-between-children */ 'space-y': [{ 'space-y': scaleUnambiguousSpacing() }], /** * Space Between Y Reverse * @see https://tailwindcss.com/docs/margin#adding-space-between-children */ 'space-y-reverse': ['space-y-reverse'], // -------------- // --- Sizing --- // -------------- /** * Size * @see https://tailwindcss.com/docs/width#setting-both-width-and-height */ size: [{ size: scaleSizing() }], /** * Width * @see https://tailwindcss.com/docs/width */ w: [{ w: [themeContainer, 'screen', ...scaleSizing()] }], /** * Min-Width * @see https://tailwindcss.com/docs/min-width */ 'min-w': [{ 'min-w': [themeContainer, 'screen', /** Deprecated. @see https://github.com/tailwindlabs/tailwindcss.com/issues/2027#issuecomment-2620152757 */ 'none', ...scaleSizing()] }], /** * Max-Width * @see https://tailwindcss.com/docs/max-width */ 'max-w': [{ 'max-w': [themeContainer, 'screen', 'none', /** Deprecated since Tailwind CSS v4.0.0. @see https://github.com/tailwindlabs/tailwindcss.com/issues/2027#issuecomment-2620152757 */ 'prose', /** Deprecated since Tailwind CSS v4.0.0. @see https://github.com/tailwindlabs/tailwindcss.com/issues/2027#issuecomment-2620152757 */ { screen: [themeBreakpoint] }, ...scaleSizing()] }], /** * Height * @see https://tailwindcss.com/docs/height */ h: [{ h: ['screen', ...scaleSizing()] }], /** * Min-Height * @see https://tailwindcss.com/docs/min-height */ 'min-h': [{ 'min-h': ['screen', 'none', ...scaleSizing()] }], /** * Max-Height * @see https://tailwindcss.com/docs/max-height */ 'max-h': [{ 'max-h': ['screen', ...scaleSizing()] }], // ------------------ // --- Typography --- // ------------------ /** * Font Size * @see https://tailwindcss.com/docs/font-size */ 'font-size': [{ text: ['base', themeText, isArbitraryVariableLength, isArbitraryLength] }], /** * Font Smoothing * @see https://tailwindcss.com/docs/font-smoothing */ 'font-smoothing': ['antialiased', 'subpixel-antialiased'], /** * Font Style * @see https://tailwindcss.com/docs/font-style */ 'font-style': ['italic', 'not-italic'], /** * Font Weight * @see https://tailwindcss.com/docs/font-weight */ 'font-weight': [{ font: [themeFontWeight, isArbitraryVariable, isArbitraryNumber] }], /** * Font Stretch * @see https://tailwindcss.com/docs/font-stretch */ 'font-stretch': [{ 'font-stretch': ['ultra-condensed', 'extra-condensed', 'condensed', 'semi-condensed', 'normal', 'semi-expanded', 'expanded', 'extra-expanded', 'ultra-expanded', isPercent, isArbitraryValue] }], /** * Font Family * @see https://tailwindcss.com/docs/font-family */ 'font-family': [{ font: [isArbitraryVariableFamilyName, isArbitraryValue, themeFont] }], /** * Font Variant Numeric * @see https://tailwindcss.com/docs/font-variant-numeric */ 'fvn-normal': ['normal-nums'], /** * Font Variant Numeric * @see https://tailwindcss.com/docs/font-variant-numeric */ 'fvn-ordinal': ['ordinal'], /** * Font Variant Numeric * @see https://tailwindcss.com/docs/font-variant-numeric */ 'fvn-slashed-zero': ['slashed-zero'], /** * Font Variant Numeric * @see https://tailwindcss.com/docs/font-variant-numeric */ 'fvn-figure': ['lining-nums', 'oldstyle-nums'], /** * Font Variant Numeric * @see https://tailwindcss.com/docs/font-variant-numeric */ 'fvn-spacing': ['proportional-nums', 'tabular-nums'], /** * Font Variant Numeric * @see https://tailwindcss.com/docs/font-variant-numeric */ 'fvn-fraction': ['diagonal-fractions', 'stacked-fractions'], /** * Letter Spacing * @see https://tailwindcss.com/docs/letter-spacing */ tracking: [{ tracking: [themeTracking, isArbitraryVariable, isArbitraryValue] }], /** * Line Clamp * @see https://tailwindcss.com/docs/line-clamp */ 'line-clamp': [{ 'line-clamp': [isNumber, 'none', isArbitraryVariable, isArbitraryNumber] }], /** * Line Height * @see https://tailwindcss.com/docs/line-height */ leading: [{ leading: [/** Deprecated since Tailwind CSS v4.0.0. @see https://github.com/tailwindlabs/tailwindcss.com/issues/2027#issuecomment-2620152757 */ themeLeading, ...scaleUnambiguousSpacing()] }], /** * List Style Image * @see https://tailwindcss.com/docs/list-style-image */ 'list-image': [{ 'list-image': ['none', isArbitraryVariable, isArbitraryValue] }], /** * List Style Position * @see https://tailwindcss.com/docs/list-style-position */ 'list-style-position': [{ list: ['inside', 'outside'] }], /** * List Style Type * @see https://tailwindcss.com/docs/list-style-type */ 'list-style-type': [{ list: ['disc', 'decimal', 'none', isArbitraryVariable, isArbitraryValue] }], /** * Text Alignment * @see https://tailwindcss.com/docs/text-align */ 'text-alignment': [{ text: ['left', 'center', 'right', 'justify', 'start', 'end'] }], /** * Placeholder Color * @deprecated since Tailwind CSS v3.0.0 * @see https://v3.tailwindcss.com/docs/placeholder-color */ 'placeholder-color': [{ placeholder: scaleColor() }], /** * Text Color * @see https://tailwindcss.com/docs/text-color */ 'text-color': [{ text: scaleColor() }], /** * Text Decoration * @see https://tailwindcss.com/docs/text-decoration */ 'text-decoration': ['underline', 'overline', 'line-through', 'no-underline'], /** * Text Decoration Style * @see https://tailwindcss.com/docs/text-decoration-style */ 'text-decoration-style': [{ decoration: [...scaleLineStyle(), 'wavy'] }], /** * Text Decoration Thickness * @see https://tailwindcss.com/docs/text-decoration-thickness */ 'text-decoration-thickness': [{ decoration: [isNumber, 'from-font', 'auto', isArbitraryVariable, isArbitraryLength] }], /** * Text Decoration Color * @see https://tailwindcss.com/docs/text-decoration-color */ 'text-decoration-color': [{ decoration: scaleColor() }], /** * Text Underline Offset * @see https://tailwindcss.com/docs/text-underline-offset */ 'underline-offset': [{ 'underline-offset': [isNumber, 'auto', isArbitraryVariable, isArbitraryValue] }], /** * Text Transform * @see https://tailwindcss.com/docs/text-transform */ 'text-transform': ['uppercase', 'lowercase', 'capitalize', 'normal-case'], /** * Text Overflow * @see https://tailwindcss.com/docs/text-overflow */ 'text-overflow': ['truncate', 'text-ellipsis', 'text-clip'], /** * Text Wrap * @see https://tailwindcss.com/docs/text-wrap */ 'text-wrap': [{ text: ['wrap', 'nowrap', 'balance', 'pretty'] }], /** * Text Indent * @see https://tailwindcss.com/docs/text-indent */ indent: [{ indent: scaleUnambiguousSpacing() }], /** * Vertical Alignment * @see https://tailwindcss.com/docs/vertical-align */ 'vertical-align': [{ align: ['baseline', 'top', 'middle', 'bottom', 'text-top', 'text-bottom', 'sub', 'super', isArbitraryVariable, isArbitraryValue] }], /** * Whitespace * @see https://tailwindcss.com/docs/whitespace */ whitespace: [{ whitespace: ['normal', 'nowrap', 'pre', 'pre-line', 'pre-wrap', 'break-spaces'] }], /** * Word Break * @see https://tailwindcss.com/docs/word-break */ break: [{ break: ['normal', 'words', 'all', 'keep'] }], /** * Hyphens * @see https://tailwindcss.com/docs/hyphens */ hyphens: [{ hyphens: ['none', 'manual', 'auto'] }], /** * Content * @see https://tailwindcss.com/docs/content */ content: [{ content: ['none', isArbitraryVariable, isArbitraryValue] }], // ------------------- // --- Backgrounds --- // ------------------- /** * Background Attachment * @see https://tailwindcss.com/docs/background-attachment */ 'bg-attachment': [{ bg: ['fixed', 'local', 'scroll'] }], /** * Background Clip * @see https://tailwindcss.com/docs/background-clip */ 'bg-clip': [{ 'bg-clip': ['border', 'padding', 'content', 'text'] }], /** * Background Origin * @see https://tailwindcss.com/docs/background-origin */ 'bg-origin': [{ 'bg-origin': ['border', 'padding', 'content'] }], /** * Background Position * @see https://tailwindcss.com/docs/background-position */ 'bg-position': [{ bg: [...scalePosition(), isArbitraryVariablePosition, isArbitraryPosition] }], /** * Background Repeat * @see https://tailwindcss.com/docs/background-repeat */ 'bg-repeat': [{ bg: ['no-repeat', { repeat: ['', 'x', 'y', 'space', 'round'] }] }], /** * Background Size * @see https://tailwindcss.com/docs/background-size */ 'bg-size': [{ bg: ['auto', 'cover', 'contain', isArbitraryVariableSize, isArbitrarySize] }], /** * Background Image * @see https://tailwindcss.com/docs/background-image */ 'bg-image': [{ bg: ['none', { linear: [{ to: ['t', 'tr', 'r', 'br', 'b', 'bl', 'l', 'tl'] }, isInteger$1, isArbitraryVariable, isArbitraryValue], radial: ['', isArbitraryVariable, isArbitraryValue], conic: [isInteger$1, isArbitraryVariable, isArbitraryValue] }, isArbitraryVariableImage, isArbitraryImage] }], /** * Background Color * @see https://tailwindcss.com/docs/background-color */ 'bg-color': [{ bg: scaleColor() }], /** * Gradient Color Stops From Position * @see https://tailwindcss.com/docs/gradient-color-stops */ 'gradient-from-pos': [{ from: scaleGradientStopPosition() }], /** * Gradient Color Stops Via Position * @see https://tailwindcss.com/docs/gradient-color-stops */ 'gradient-via-pos': [{ via: scaleGradientStopPosition() }], /** * Gradient Color Stops To Position * @see https://tailwindcss.com/docs/gradient-color-stops */ 'gradient-to-pos': [{ to: scaleGradientStopPosition() }], /** * Gradient Color Stops From * @see https://tailwindcss.com/docs/gradient-color-stops */ 'gradient-from': [{ from: scaleColor() }], /** * Gradient Color Stops Via * @see https://tailwindcss.com/docs/gradient-color-stops */ 'gradient-via': [{ via: scaleColor() }], /** * Gradient Color Stops To * @see https://tailwindcss.com/docs/gradient-color-stops */ 'gradient-to': [{ to: scaleColor() }], // --------------- // --- Borders --- // --------------- /** * Border Radius * @see https://tailwindcss.com/docs/border-radius */ rounded: [{ rounded: scaleRadius() }], /** * Border Radius Start * @see https://tailwindcss.com/docs/border-radius */ 'rounded-s': [{ 'rounded-s': scaleRadius() }], /** * Border Radius End * @see https://tailwindcss.com/docs/border-radius */ 'rounded-e': [{ 'rounded-e': scaleRadius() }], /** * Border Radius Top * @see https://tailwindcss.com/docs/border-radius */ 'rounded-t': [{ 'rounded-t': scaleRadius() }], /** * Border Radius Right * @see https://tailwindcss.com/docs/border-radius */ 'rounded-r': [{ 'rounded-r': scaleRadius() }], /** * Border Radius Bottom * @see https://tailwindcss.com/docs/border-radius */ 'rounded-b': [{ 'rounded-b': scaleRadius() }], /** * Border Radius Left * @see https://tailwindcss.com/docs/border-radius */ 'rounded-l': [{ 'rounded-l': scaleRadius() }], /** * Border Radius Start Start * @see https://tailwindcss.com/docs/border-radius */ 'rounded-ss': [{ 'rounded-ss': scaleRadius() }], /** * Border Radius Start End * @see https://tailwindcss.com/docs/border-radius */ 'rounded-se': [{ 'rounded-se': scaleRadius() }], /** * Border Radius End End * @see https://tailwindcss.com/docs/border-radius */ 'rounded-ee': [{ 'rounded-ee': scaleRadius() }], /** * Border Radius End Start * @see https://tailwindcss.com/docs/border-radius */ 'rounded-es': [{ 'rounded-es': scaleRadius() }], /** * Border Radius Top Left * @see https://tailwindcss.com/docs/border-radius */ 'rounded-tl': [{ 'rounded-tl': scaleRadius() }], /** * Border Radius Top Right * @see https://tailwindcss.com/docs/border-radius */ 'rounded-tr': [{ 'rounded-tr': scaleRadius() }], /** * Border Radius Bottom Right * @see https://tailwindcss.com/docs/border-radius */ 'rounded-br': [{ 'rounded-br': scaleRadius() }], /** * Border Radius Bottom Left * @see https://tailwindcss.com/docs/border-radius */ 'rounded-bl': [{ 'rounded-bl': scaleRadius() }], /** * Border Width * @see https://tailwindcss.com/docs/border-width */ 'border-w': [{ border: scaleBorderWidth() }], /** * Border Width X * @see https://tailwindcss.com/docs/border-width */ 'border-w-x': [{ 'border-x': scaleBorderWidth() }], /** * Border Width Y * @see https://tailwindcss.com/docs/border-width */ 'border-w-y': [{ 'border-y': scaleBorderWidth() }], /** * Border Width Start * @see https://tailwindcss.com/docs/border-width */ 'border-w-s': [{ 'border-s': scaleBorderWidth() }], /** * Border Width End * @see https://tailwindcss.com/docs/border-width */ 'border-w-e': [{ 'border-e': scaleBorderWidth() }], /** * Border Width Top * @see https://tailwindcss.com/docs/border-width */ 'border-w-t': [{ 'border-t': scaleBorderWidth() }], /** * Border Width Right * @see https://tailwindcss.com/docs/border-width */ 'border-w-r': [{ 'border-r': scaleBorderWidth() }], /** * Border Width Bottom * @see https://tailwindcss.com/docs/border-width */ 'border-w-b': [{ 'border-b': scaleBorderWidth() }], /** * Border Width Left * @see https://tailwindcss.com/docs/border-width */ 'border-w-l': [{ 'border-l': scaleBorderWidth() }], /** * Divide Width X * @see https://tailwindcss.com/docs/border-width#between-children */ 'divide-x': [{ 'divide-x': scaleBorderWidth() }], /** * Divide Width X Reverse * @see https://tailwindcss.com/docs/border-width#between-children */ 'divide-x-reverse': ['divide-x-reverse'], /** * Divide Width Y * @see https://tailwindcss.com/docs/border-width#between-children */ 'divide-y': [{ 'divide-y': scaleBorderWidth() }], /** * Divide Width Y Reverse * @see https://tailwindcss.com/docs/border-width#between-children */ 'divide-y-reverse': ['divide-y-reverse'], /** * Border Style * @see https://tailwindcss.com/docs/border-style */ 'border-style': [{ border: [...scaleLineStyle(), 'hidden', 'none'] }], /** * Divide Style * @see https://tailwindcss.com/docs/border-style#setting-the-divider-style */ 'divide-style': [{ divide: [...scaleLineStyle(), 'hidden', 'none'] }], /** * Border Color * @see https://tailwindcss.com/docs/border-color */ 'border-color': [{ border: scaleColor() }], /** * Border Color X * @see https://tailwindcss.com/docs/border-color */ 'border-color-x': [{ 'border-x': scaleColor() }], /** * Border Color Y * @see https://tailwindcss.com/docs/border-color */ 'border-color-y': [{ 'border-y': scaleColor() }], /** * Border Color S * @see https://tailwindcss.com/docs/border-color */ 'border-color-s': [{ 'border-s': scaleColor() }], /** * Border Color E * @see https://tailwindcss.com/docs/border-color */ 'border-color-e': [{ 'border-e': scaleColor() }], /** * Border Color Top * @see https://tailwindcss.com/docs/border-color */ 'border-color-t': [{ 'border-t': scaleColor() }], /** * Border Color Right * @see https://tailwindcss.com/docs/border-color */ 'border-color-r': [{ 'border-r': scaleColor() }], /** * Border Color Bottom * @see https://tailwindcss.com/docs/border-color */ 'border-color-b': [{ 'border-b': scaleColor() }], /** * Border Color Left * @see https://tailwindcss.com/docs/border-color */ 'border-color-l': [{ 'border-l': scaleColor() }], /** * Divide Color * @see https://tailwindcss.com/docs/divide-color */ 'divide-color': [{ divide: scaleColor() }], /** * Outline Style * @see https://tailwindcss.com/docs/outline-style */ 'outline-style': [{ outline: [...scaleLineStyle(), 'none', 'hidden'] }], /** * Outline Offset * @see https://tailwindcss.com/docs/outline-offset */ 'outline-offset': [{ 'outline-offset': [isNumber, isArbitraryVariable, isArbitraryValue] }], /** * Outline Width * @see https://tailwindcss.com/docs/outline-width */ 'outline-w': [{ outline: ['', isNumber, isArbitraryVariableLength, isArbitraryLength] }], /** * Outline Color * @see https://tailwindcss.com/docs/outline-color */ 'outline-color': [{ outline: [themeColor] }], // --------------- // --- Effects --- // --------------- /** * Box Shadow * @see https://tailwindcss.com/docs/box-shadow */ shadow: [{ shadow: [ // Deprecated since Tailwind CSS v4.0.0 '', 'none', themeShadow, isArbitraryVariableShadow, isArbitraryShadow] }], /** * Box Shadow Color * @see https://tailwindcss.com/docs/box-shadow#setting-the-shadow-color */ 'shadow-color': [{ shadow: scaleColor() }], /** * Inset Box Shadow * @see https://tailwindcss.com/docs/box-shadow#adding-an-inset-shadow */ 'inset-shadow': [{ 'inset-shadow': ['none', isArbitraryVariable, isArbitraryValue, themeInsetShadow] }], /** * Inset Box Shadow Color * @see https://tailwindcss.com/docs/box-shadow#setting-the-inset-shadow-color */ 'inset-shadow-color': [{ 'inset-shadow': scaleColor() }], /** * Ring Width * @see https://tailwindcss.com/docs/box-shadow#adding-a-ring */ 'ring-w': [{ ring: scaleBorderWidth() }], /** * Ring Width Inset * @see https://v3.tailwindcss.com/docs/ring-width#inset-rings * @deprecated since Tailwind CSS v4.0.0 * @see https://github.com/tailwindlabs/tailwindcss/blob/v4.0.0/packages/tailwindcss/src/utilities.ts#L4158 */ 'ring-w-inset': ['ring-inset'], /** * Ring Color * @see https://tailwindcss.com/docs/box-shadow#setting-the-ring-color */ 'ring-color': [{ ring: scaleColor() }], /** * Ring Offset Width * @see https://v3.tailwindcss.com/docs/ring-offset-width * @deprecated since Tailwind CSS v4.0.0 * @see https://github.com/tailwindlabs/tailwindcss/blob/v4.0.0/packages/tailwindcss/src/utilities.ts#L4158 */ 'ring-offset-w': [{ 'ring-offset': [isNumber, isArbitraryLength] }], /** * Ring Offset Color * @see https://v3.tailwindcss.com/docs/ring-offset-color * @deprecated since Tailwind CSS v4.0.0 * @see https://github.com/tailwindlabs/tailwindcss/blob/v4.0.0/packages/tailwindcss/src/utilities.ts#L4158 */ 'ring-offset-color': [{ 'ring-offset': scaleColor() }], /** * Inset Ring Width * @see https://tailwindcss.com/docs/box-shadow#adding-an-inset-ring */ 'inset-ring-w': [{ 'inset-ring': scaleBorderWidth() }], /** * Inset Ring Color * @see https://tailwindcss.com/docs/box-shadow#setting-the-inset-ring-color */ 'inset-ring-color': [{ 'inset-ring': scaleColor() }], /** * Opacity * @see https://tailwindcss.com/docs/opacity */ opacity: [{ opacity: [isNumber, isArbitraryVariable, isArbitraryValue] }], /** * Mix Blend Mode * @see https://tailwindcss.com/docs/mix-blend-mode */ 'mix-blend': [{ 'mix-blend': [...scaleBlendMode(), 'plus-darker', 'plus-lighter'] }], /** * Background Blend Mode * @see https://tailwindcss.com/docs/background-blend-mode */ 'bg-blend': [{ 'bg-blend': scaleBlendMode() }], // --------------- // --- Filters --- // --------------- /** * Filter * @see https://tailwindcss.com/docs/filter */ filter: [{ filter: [ // Deprecated since Tailwind CSS v3.0.0 '', 'none', isArbitraryVariable, isArbitraryValue] }], /** * Blur * @see https://tailwindcss.com/docs/blur */ blur: [{ blur: scaleBlur() }], /** * Brightness * @see https://tailwindcss.com/docs/brightness */ brightness: [{ brightness: [isNumber, isArbitraryVariable, isArbitraryValue] }], /** * Contrast * @see https://tailwindcss.com/docs/contrast */ contrast: [{ contrast: [isNumber, isArbitraryVariable, isArbitraryValue] }], /** * Drop Shadow * @see https://tailwindcss.com/docs/drop-shadow */ 'drop-shadow': [{ 'drop-shadow': [ // Deprecated since Tailwind CSS v4.0.0 '', 'none', themeDropShadow, isArbitraryVariable, isArbitraryValue] }], /** * Grayscale * @see https://tailwindcss.com/docs/grayscale */ grayscale: [{ grayscale: ['', isNumber, isArbitraryVariable, isArbitraryValue] }], /** * Hue Rotate * @see https://tailwindcss.com/docs/hue-rotate */ 'hue-rotate': [{ 'hue-rotate': [isNumber, isArbitraryVariable, isArbitraryValue] }], /** * Invert * @see https://tailwindcss.com/docs/invert */ invert: [{ invert: ['', isNumber, isArbitraryVariable, isArbitraryValue] }], /** * Saturate * @see https://tailwindcss.com/docs/saturate */ saturate: [{ saturate: [isNumber, isArbitraryVariable, isArbitraryValue] }], /** * Sepia * @see https://tailwindcss.com/docs/sepia */ sepia: [{ sepia: ['', isNumber, isArbitraryVariable, isArbitraryValue] }], /** * Backdrop Filter * @see https://tailwindcss.com/docs/backdrop-filter */ 'backdrop-filter': [{ 'backdrop-filter': [ // Deprecated since Tailwind CSS v3.0.0 '', 'none', isArbitraryVariable, isArbitraryValue] }], /** * Backdrop Blur * @see https://tailwindcss.com/docs/backdrop-blur */ 'backdrop-blur': [{ 'backdrop-blur': scaleBlur() }], /** * Backdrop Brightness * @see https://tailwindcss.com/docs/backdrop-brightness */ 'backdrop-brightness': [{ 'backdrop-brightness': [isNumber, isArbitraryVariable, isArbitraryValue] }], /** * Backdrop Contrast * @see https://tailwindcss.com/docs/backdrop-contrast */ 'backdrop-contrast': [{ 'backdrop-contrast': [isNumber, isArbitraryVariable, isArbitraryValue] }], /** * Backdrop Grayscale * @see https://tailwindcss.com/docs/backdrop-grayscale */ 'backdrop-grayscale': [{ 'backdrop-grayscale': ['', isNumber, isArbitraryVariable, isArbitraryValue] }], /** * Backdrop Hue Rotate * @see https://tailwindcss.com/docs/backdrop-hue-rotate */ 'backdrop-hue-rotate': [{ 'backdrop-hue-rotate': [isNumber, isArbitraryVariable, isArbitraryValue] }], /** * Backdrop Invert * @see https://tailwindcss.com/docs/backdrop-invert */ 'backdrop-invert': [{ 'backdrop-invert': ['', isNumber, isArbitraryVariable, isArbitraryValue] }], /** * Backdrop Opacity * @see https://tailwindcss.com/docs/backdrop-opacity */ 'backdrop-opacity': [{ 'backdrop-opacity': [isNumber, isArbitraryVariable, isArbitraryValue] }], /** * Backdrop Saturate * @see https://tailwindcss.com/docs/backdrop-saturate */ 'backdrop-saturate': [{ 'backdrop-saturate': [isNumber, isArbitraryVariable, isArbitraryValue] }], /** * Backdrop Sepia * @see https://tailwindcss.com/docs/backdrop-sepia */ 'backdrop-sepia': [{ 'backdrop-sepia': ['', isNumber, isArbitraryVariable, isArbitraryValue] }], // -------------- // --- Tables --- // -------------- /** * Border Collapse * @see https://tailwindcss.com/docs/border-collapse */ 'border-collapse': [{ border: ['collapse', 'separate'] }], /** * Border Spacing * @see https://tailwindcss.com/docs/border-spacing */ 'border-spacing': [{ 'border-spacing': scaleUnambiguousSpacing() }], /** * Border Spacing X * @see https://tailwindcss.com/docs/border-spacing */ 'border-spacing-x': [{ 'border-spacing-x': scaleUnambiguousSpacing() }], /** * Border Spacing Y * @see https://tailwindcss.com/docs/border-spacing */ 'border-spacing-y': [{ 'border-spacing-y': scaleUnambiguousSpacing() }], /** * Table Layout * @see https://tailwindcss.com/docs/table-layout */ 'table-layout': [{ table: ['auto', 'fixed'] }], /** * Caption Side * @see https://tailwindcss.com/docs/caption-side */ caption: [{ caption: ['top', 'bottom'] }], // --------------------------------- // --- Transitions and Animation --- // --------------------------------- /** * Transition Property * @see https://tailwindcss.com/docs/transition-property */ transition: [{ transition: ['', 'all', 'colors', 'opacity', 'shadow', 'transform', 'none', isArbitraryVariable, isArbitraryValue] }], /** * Transition Behavior * @see https://tailwindcss.com/docs/transition-behavior */ 'transition-behavior': [{ transition: ['normal', 'discrete'] }], /** * Transition Duration * @see https://tailwindcss.com/docs/transition-duration */ duration: [{ duration: [isNumber, 'initial', isArbitraryVariable, isArbitraryValue] }], /** * Transition Timing Function * @see https://tailwindcss.com/docs/transition-timing-function */ ease: [{ ease: ['linear', 'initial', themeEase, isArbitraryVariable, isArbitraryValue] }], /** * Transition Delay * @see https://tailwindcss.com/docs/transition-delay */ delay: [{ delay: [isNumber, isArbitraryVariable, isArbitraryValue] }], /** * Animation * @see https://tailwindcss.com/docs/animation */ animate: [{ animate: ['none', themeAnimate, isArbitraryVariable, isArbitraryValue] }], // ------------------ // --- Transforms --- // ------------------ /** * Backface Visibility * @see https://tailwindcss.com/docs/backface-visibility */ backface: [{ backface: ['hidden', 'visible'] }], /** * Perspective * @see https://tailwindcss.com/docs/perspective */ perspective: [{ perspective: [themePerspective, isArbitraryVariable, isArbitraryValue] }], /** * Perspective Origin * @see https://tailwindcss.com/docs/perspective-origin */ 'perspective-origin': [{ 'perspective-origin': scaleOrigin() }], /** * Rotate * @see https://tailwindcss.com/docs/rotate */ rotate: [{ rotate: scaleRotate() }], /** * Rotate X * @see https://tailwindcss.com/docs/rotate */ 'rotate-x': [{ 'rotate-x': scaleRotate() }], /** * Rotate Y * @see https://tailwindcss.com/docs/rotate */ 'rotate-y': [{ 'rotate-y': scaleRotate() }], /** * Rotate Z * @see https://tailwindcss.com/docs/rotate */ 'rotate-z': [{ 'rotate-z': scaleRotate() }], /** * Scale * @see https://tailwindcss.com/docs/scale */ scale: [{ scale: scaleScale() }], /** * Scale X * @see https://tailwindcss.com/docs/scale */ 'scale-x': [{ 'scale-x': scaleScale() }], /** * Scale Y * @see https://tailwindcss.com/docs/scale */ 'scale-y': [{ 'scale-y': scaleScale() }], /** * Scale Z * @see https://tailwindcss.com/docs/scale */ 'scale-z': [{ 'scale-z': scaleScale() }], /** * Scale 3D * @see https://tailwindcss.com/docs/scale */ 'scale-3d': ['scale-3d'], /** * Skew * @see https://tailwindcss.com/docs/skew */ skew: [{ skew: scaleSkew() }], /** * Skew X * @see https://tailwindcss.com/docs/skew */ 'skew-x': [{ 'skew-x': scaleSkew() }], /** * Skew Y * @see https://tailwindcss.com/docs/skew */ 'skew-y': [{ 'skew-y': scaleSkew() }], /** * Transform * @see https://tailwindcss.com/docs/transform */ transform: [{ transform: [isArbitraryVariable, isArbitraryValue, '', 'none', 'gpu', 'cpu'] }], /** * Transform Origin * @see https://tailwindcss.com/docs/transform-origin */ 'transform-origin': [{ origin: scaleOrigin() }], /** * Transform Style * @see https://tailwindcss.com/docs/transform-style */ 'transform-style': [{ transform: ['3d', 'flat'] }], /** * Translate * @see https://tailwindcss.com/docs/translate */ translate: [{ translate: scaleTranslate() }], /** * Translate X * @see https://tailwindcss.com/docs/translate */ 'translate-x': [{ 'translate-x': scaleTranslate() }], /** * Translate Y * @see https://tailwindcss.com/docs/translate */ 'translate-y': [{ 'translate-y': scaleTranslate() }], /** * Translate Z * @see https://tailwindcss.com/docs/translate */ 'translate-z': [{ 'translate-z': scaleTranslate() }], /** * Translate None * @see https://tailwindcss.com/docs/translate */ 'translate-none': ['translate-none'], // --------------------- // --- Interactivity --- // --------------------- /** * Accent Color * @see https://tailwindcss.com/docs/accent-color */ accent: [{ accent: scaleColor() }], /** * Appearance * @see https://tailwindcss.com/docs/appearance */ appearance: [{ appearance: ['none', 'auto'] }], /** * Caret Color * @see https://tailwindcss.com/docs/just-in-time-mode#caret-color-utilities */ 'caret-color': [{ caret: scaleColor() }], /** * Color Scheme * @see https://tailwindcss.com/docs/color-scheme */ 'color-scheme': [{ scheme: ['normal', 'dark', 'light', 'light-dark', 'only-dark', 'only-light'] }], /** * Cursor * @see https://tailwindcss.com/docs/cursor */ cursor: [{ cursor: ['auto', 'default', 'pointer', 'wait', 'text', 'move', 'help', 'not-allowed', 'none', 'context-menu', 'progress', 'cell', 'crosshair', 'vertical-text', 'alias', 'copy', 'no-drop', 'grab', 'grabbing', 'all-scroll', 'col-resize', 'row-resize', 'n-resize', 'e-resize', 's-resize', 'w-resize', 'ne-resize', 'nw-resize', 'se-resize', 'sw-resize', 'ew-resize', 'ns-resize', 'nesw-resize', 'nwse-resize', 'zoom-in', 'zoom-out', isArbitraryVariable, isArbitraryValue] }], /** * Field Sizing * @see https://tailwindcss.com/docs/field-sizing */ 'field-sizing': [{ 'field-sizing': ['fixed', 'content'] }], /** * Pointer Events * @see https://tailwindcss.com/docs/pointer-events */ 'pointer-events': [{ 'pointer-events': ['auto', 'none'] }], /** * Resize * @see https://tailwindcss.com/docs/resize */ resize: [{ resize: ['none', '', 'y', 'x'] }], /** * Scroll Behavior * @see https://tailwindcss.com/docs/scroll-behavior */ 'scroll-behavior': [{ scroll: ['auto', 'smooth'] }], /** * Scroll Margin * @see https://tailwindcss.com/docs/scroll-margin */ 'scroll-m': [{ 'scroll-m': scaleUnambiguousSpacing() }], /** * Scroll Margin X * @see https://tailwindcss.com/docs/scroll-margin */ 'scroll-mx': [{ 'scroll-mx': scaleUnambiguousSpacing() }], /** * Scroll Margin Y * @see https://tailwindcss.com/docs/scroll-margin */ 'scroll-my': [{ 'scroll-my': scaleUnambiguousSpacing() }], /** * Scroll Margin Start * @see https://tailwindcss.com/docs/scroll-margin */ 'scroll-ms': [{ 'scroll-ms': scaleUnambiguousSpacing() }], /** * Scroll Margin End * @see https://tailwindcss.com/docs/scroll-margin */ 'scroll-me': [{ 'scroll-me': scaleUnambiguousSpacing() }], /** * Scroll Margin Top * @see https://tailwindcss.com/docs/scroll-margin */ 'scroll-mt': [{ 'scroll-mt': scaleUnambiguousSpacing() }], /** * Scroll Margin Right * @see https://tailwindcss.com/docs/scroll-margin */ 'scroll-mr': [{ 'scroll-mr': scaleUnambiguousSpacing() }], /** * Scroll Margin Bottom * @see https://tailwindcss.com/docs/scroll-margin */ 'scroll-mb': [{ 'scroll-mb': scaleUnambiguousSpacing() }], /** * Scroll Margin Left * @see https://tailwindcss.com/docs/scroll-margin */ 'scroll-ml': [{ 'scroll-ml': scaleUnambiguousSpacing() }], /** * Scroll Padding * @see https://tailwindcss.com/docs/scroll-padding */ 'scroll-p': [{ 'scroll-p': scaleUnambiguousSpacing() }], /** * Scroll Padding X * @see https://tailwindcss.com/docs/scroll-padding */ 'scroll-px': [{ 'scroll-px': scaleUnambiguousSpacing() }], /** * Scroll Padding Y * @see https://tailwindcss.com/docs/scroll-padding */ 'scroll-py': [{ 'scroll-py': scaleUnambiguousSpacing() }], /** * Scroll Padding Start * @see https://tailwindcss.com/docs/scroll-padding */ 'scroll-ps': [{ 'scroll-ps': scaleUnambiguousSpacing() }], /** * Scroll Padding End * @see https://tailwindcss.com/docs/scroll-padding */ 'scroll-pe': [{ 'scroll-pe': scaleUnambiguousSpacing() }], /** * Scroll Padding Top * @see https://tailwindcss.com/docs/scroll-padding */ 'scroll-pt': [{ 'scroll-pt': scaleUnambiguousSpacing() }], /** * Scroll Padding Right * @see https://tailwindcss.com/docs/scroll-padding */ 'scroll-pr': [{ 'scroll-pr': scaleUnambiguousSpacing() }], /** * Scroll Padding Bottom * @see https://tailwindcss.com/docs/scroll-padding */ 'scroll-pb': [{ 'scroll-pb': scaleUnambiguousSpacing() }], /** * Scroll Padding Left * @see https://tailwindcss.com/docs/scroll-padding */ 'scroll-pl': [{ 'scroll-pl': scaleUnambiguousSpacing() }], /** * Scroll Snap Align * @see https://tailwindcss.com/docs/scroll-snap-align */ 'snap-align': [{ snap: ['start', 'end', 'center', 'align-none'] }], /** * Scroll Snap Stop * @see https://tailwindcss.com/docs/scroll-snap-stop */ 'snap-stop': [{ snap: ['normal', 'always'] }], /** * Scroll Snap Type * @see https://tailwindcss.com/docs/scroll-snap-type */ 'snap-type': [{ snap: ['none', 'x', 'y', 'both'] }], /** * Scroll Snap Type Strictness * @see https://tailwindcss.com/docs/scroll-snap-type */ 'snap-strictness': [{ snap: ['mandatory', 'proximity'] }], /** * Touch Action * @see https://tailwindcss.com/docs/touch-action */ touch: [{ touch: ['auto', 'none', 'manipulation'] }], /** * Touch Action X * @see https://tailwindcss.com/docs/touch-action */ 'touch-x': [{ 'touch-pan': ['x', 'left', 'right'] }], /** * Touch Action Y * @see https://tailwindcss.com/docs/touch-action */ 'touch-y': [{ 'touch-pan': ['y', 'up', 'down'] }], /** * Touch Action Pinch Zoom * @see https://tailwindcss.com/docs/touch-action */ 'touch-pz': ['touch-pinch-zoom'], /** * User Select * @see https://tailwindcss.com/docs/user-select */ select: [{ select: ['none', 'text', 'all', 'auto'] }], /** * Will Change * @see https://tailwindcss.com/docs/will-change */ 'will-change': [{ 'will-change': ['auto', 'scroll', 'contents', 'transform', isArbitraryVariable, isArbitraryValue] }], // ----------- // --- SVG --- // ----------- /** * Fill * @see https://tailwindcss.com/docs/fill */ fill: [{ fill: ['none', ...scaleColor()] }], /** * Stroke Width * @see https://tailwindcss.com/docs/stroke-width */ 'stroke-w': [{ stroke: [isNumber, isArbitraryVariableLength, isArbitraryLength, isArbitraryNumber] }], /** * Stroke * @see https://tailwindcss.com/docs/stroke */ stroke: [{ stroke: ['none', ...scaleColor()] }], // --------------------- // --- Accessibility --- // --------------------- /** * Forced Color Adjust * @see https://tailwindcss.com/docs/forced-color-adjust */ 'forced-color-adjust': [{ 'forced-color-adjust': ['auto', 'none'] }] }, conflictingClassGroups: { overflow: ['overflow-x', 'overflow-y'], overscroll: ['overscroll-x', 'overscroll-y'], inset: ['inset-x', 'inset-y', 'start', 'end', 'top', 'right', 'bottom', 'left'], 'inset-x': ['right', 'left'], 'inset-y': ['top', 'bottom'], flex: ['basis', 'grow', 'shrink'], gap: ['gap-x', 'gap-y'], p: ['px', 'py', 'ps', 'pe', 'pt', 'pr', 'pb', 'pl'], px: ['pr', 'pl'], py: ['pt', 'pb'], m: ['mx', 'my', 'ms', 'me', 'mt', 'mr', 'mb', 'ml'], mx: ['mr', 'ml'], my: ['mt', 'mb'], size: ['w', 'h'], 'font-size': ['leading'], 'fvn-normal': ['fvn-ordinal', 'fvn-slashed-zero', 'fvn-figure', 'fvn-spacing', 'fvn-fraction'], 'fvn-ordinal': ['fvn-normal'], 'fvn-slashed-zero': ['fvn-normal'], 'fvn-figure': ['fvn-normal'], 'fvn-spacing': ['fvn-normal'], 'fvn-fraction': ['fvn-normal'], 'line-clamp': ['display', 'overflow'], rounded: ['rounded-s', 'rounded-e', 'rounded-t', 'rounded-r', 'rounded-b', 'rounded-l', 'rounded-ss', 'rounded-se', 'rounded-ee', 'rounded-es', 'rounded-tl', 'rounded-tr', 'rounded-br', 'rounded-bl'], 'rounded-s': ['rounded-ss', 'rounded-es'], 'rounded-e': ['rounded-se', 'rounded-ee'], 'rounded-t': ['rounded-tl', 'rounded-tr'], 'rounded-r': ['rounded-tr', 'rounded-br'], 'rounded-b': ['rounded-br', 'rounded-bl'], 'rounded-l': ['rounded-tl', 'rounded-bl'], 'border-spacing': ['border-spacing-x', 'border-spacing-y'], 'border-w': ['border-w-s', 'border-w-e', 'border-w-t', 'border-w-r', 'border-w-b', 'border-w-l'], 'border-w-x': ['border-w-r', 'border-w-l'], 'border-w-y': ['border-w-t', 'border-w-b'], 'border-color': ['border-color-s', 'border-color-e', 'border-color-t', 'border-color-r', 'border-color-b', 'border-color-l'], 'border-color-x': ['border-color-r', 'border-color-l'], 'border-color-y': ['border-color-t', 'border-color-b'], translate: ['translate-x', 'translate-y', 'translate-none'], 'translate-none': ['translate', 'translate-x', 'translate-y', 'translate-z'], 'scroll-m': ['scroll-mx', 'scroll-my', 'scroll-ms', 'scroll-me', 'scroll-mt', 'scroll-mr', 'scroll-mb', 'scroll-ml'], 'scroll-mx': ['scroll-mr', 'scroll-ml'], 'scroll-my': ['scroll-mt', 'scroll-mb'], 'scroll-p': ['scroll-px', 'scroll-py', 'scroll-ps', 'scroll-pe', 'scroll-pt', 'scroll-pr', 'scroll-pb', 'scroll-pl'], 'scroll-px': ['scroll-pr', 'scroll-pl'], 'scroll-py': ['scroll-pt', 'scroll-pb'], touch: ['touch-x', 'touch-y', 'touch-pz'], 'touch-x': ['touch'], 'touch-y': ['touch'], 'touch-pz': ['touch'] }, conflictingClassGroupModifiers: { 'font-size': ['leading'] }, orderSensitiveModifiers: ['before', 'after', 'placeholder', 'file', 'marker', 'selection', 'first-line', 'first-letter', 'backdrop', '*', '**'] }; }; const twMerge = /*#__PURE__*/createTailwindMerge(getDefaultConfig); function cn(...inputs) { return twMerge(clsx(inputs)); } const buttonVariants = cva("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-[color,box-shadow] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", { variants: { variant: { default: "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90", destructive: "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40", outline: "border border-input bg-background shadow-xs hover:bg-accent hover:text-accent-foreground", secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80", ghost: "hover:bg-accent hover:text-accent-foreground", link: "text-primary underline-offset-4 hover:underline" }, size: { default: "h-9 px-4 py-2 has-[>svg]:px-3", sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5", lg: "h-10 rounded-md px-6 has-[>svg]:px-4", icon: "size-9" } }, defaultVariants: { variant: "default", size: "default" } }); function Button({ className, variant, size, innerRef, asChild = false, ...props }) { return /*#__PURE__*/React__namespace.createElement("button", { "data-slot": "button", ref: innerRef, className: cn(buttonVariants({ variant, size, className })), ...props }); } const Input = /*#__PURE__*/React__namespace.forwardRef(({ className, type, ...props }, ref) => { return /*#__PURE__*/React__namespace.createElement("input", { type: type, className: cn("flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", className), ref: ref, ...props }); }); Input.displayName = "Input"; // packages/core/number/src/number.ts function clamp$1(value, [min, max]) { return Math.min(max, Math.max(min, value)); } // packages/core/primitive/src/primitive.tsx function composeEventHandlers$1(originalEventHandler, ourEventHandler, { checkForDefaultPrevented = true } = {}) { return function handleEvent(event) { originalEventHandler?.(event); if (checkForDefaultPrevented === false || !event.defaultPrevented) { return ourEventHandler?.(event); } }; } // packages/react/context/src/createContext.tsx function createContextScope(scopeName, createContextScopeDeps = []) { let defaultContexts = []; function createContext3(rootComponentName, defaultContext) { const BaseContext = /*#__PURE__*/React__namespace.createContext(defaultContext); const index = defaultContexts.length; defaultContexts = [...defaultContexts, defaultContext]; const Provider = props => { const { scope, children, ...context } = props; const Context = scope?.[scopeName]?.[index] || BaseContext; const value = React__namespace.useMemo(() => context, Object.values(context)); return /* @__PURE__ */jsxRuntimeExports.jsx(Context.Provider, { value, children }); }; Provider.displayName = rootComponentName + "Provider"; function useContext2(consumerName, scope) { const Context = scope?.[scopeName]?.[index] || BaseContext; const context = React__namespace.useContext(Context); if (context) return context; if (defaultContext !== void 0) return defaultContext; throw new Error(`\`${consumerName}\` must be used within \`${rootComponentName}\``); } return [Provider, useContext2]; } const createScope = () => { const scopeContexts = defaultContexts.map(defaultContext => { return /*#__PURE__*/React__namespace.createContext(defaultContext); }); return function useScope(scope) { const contexts = scope?.[scopeName] || scopeContexts; return React__namespace.useMemo(() => ({ [`__scope${scopeName}`]: { ...scope, [scopeName]: contexts } }), [scope, contexts]); }; }; createScope.scopeName = scopeName; return [createContext3, composeContextScopes(createScope, ...createContextScopeDeps)]; } function composeContextScopes(...scopes) { const baseScope = scopes[0]; if (scopes.length === 1) return baseScope; const createScope = () => { const scopeHooks = scopes.map(createScope2 => ({ useScope: createScope2(), scopeName: createScope2.scopeName })); return function useComposedScopes(overrideScopes) { const nextScopes = scopeHooks.reduce((nextScopes2, { useScope, scopeName }) => { const scopeProps = useScope(overrideScopes); const currentScope = scopeProps[`__scope${scopeName}`]; return { ...nextScopes2, ...currentScope }; }, {}); return React__namespace.useMemo(() => ({ [`__scope${baseScope.scopeName}`]: nextScopes }), [nextScopes]); }; }; createScope.scopeName = baseScope.scopeName; return createScope; } function createCollection(name) { const PROVIDER_NAME = name + "CollectionProvider"; const [createCollectionContext, createCollectionScope] = createContextScope(PROVIDER_NAME); const [CollectionProviderImpl, useCollectionContext] = createCollectionContext(PROVIDER_NAME, { collectionRef: { current: null }, itemMap: /* @__PURE__ */new Map() }); const CollectionProvider = props => { const { scope, children } = props; const ref = React__namespace.default.useRef(null); const itemMap = React__namespace.default.useRef(/* @__PURE__ */new Map()).current; return /* @__PURE__ */jsxRuntimeExports.jsx(CollectionProviderImpl, { scope, itemMap, collectionRef: ref, children }); }; CollectionProvider.displayName = PROVIDER_NAME; const COLLECTION_SLOT_NAME = name + "CollectionSlot"; const CollectionSlot = /*#__PURE__*/React__namespace.default.forwardRef((props, forwardedRef) => { const { scope, children } = props; const context = useCollectionContext(COLLECTION_SLOT_NAME, scope); const composedRefs = useComposedRefs(forwardedRef, context.collectionRef); return /* @__PURE__ */jsxRuntimeExports.jsx(Slot, { ref: composedRefs, children }); }); CollectionSlot.displayName = COLLECTION_SLOT_NAME; const ITEM_SLOT_NAME = name + "CollectionItemSlot"; const ITEM_DATA_ATTR = "data-radix-collection-item"; const CollectionItemSlot = /*#__PURE__*/React__namespace.default.forwardRef((props, forwardedRef) => { const { scope, children, ...itemData } = props; const ref = React__namespace.default.useRef(null); const composedRefs = useComposedRefs(forwardedRef, ref); const context = useCollectionContext(ITEM_SLOT_NAME, scope); React__namespace.default.useEffect(() => { context.itemMap.set(ref, { ref, ...itemData }); return () => void context.itemMap.delete(ref); }); return /* @__PURE__ */jsxRuntimeExports.jsx(Slot, { ...{ [ITEM_DATA_ATTR]: "" }, ref: composedRefs, children }); }); CollectionItemSlot.displayName = ITEM_SLOT_NAME; function useCollection(scope) { const context = useCollectionContext(name + "CollectionConsumer", scope); const getItems = React__namespace.default.useCallback(() => { const collectionNode = context.collectionRef.current; if (!collectionNode) return []; const orderedNodes = Array.from(collectionNode.querySelectorAll(`[${ITEM_DATA_ATTR}]`)); const items = Array.from(context.itemMap.values()); const orderedItems = items.sort((a, b) => orderedNodes.indexOf(a.ref.current) - orderedNodes.indexOf(b.ref.current)); return orderedItems; }, [context.collectionRef, context.itemMap]); return getItems; } return [{ Provider: CollectionProvider, Slot: CollectionSlot, ItemSlot: CollectionItemSlot }, useCollection, createCollectionScope]; } // packages/react/direction/src/Direction.tsx var DirectionContext = /*#__PURE__*/React__namespace.createContext(void 0); function useDirection(localDir) { const globalDir = React__namespace.useContext(DirectionContext); return localDir || globalDir || "ltr"; } // packages/react/primitive/src/primitive.tsx var NODES$2 = ["a", "button", "div", "form", "h2", "h3", "img", "input", "label", "li", "nav", "ol", "p", "span", "svg", "ul"]; var Primitive$2 = NODES$2.reduce((primitive, node) => { const Node = /*#__PURE__*/React__namespace.forwardRef((props, forwardedRef) => { const { asChild, ...primitiveProps } = props; const Comp = asChild ? Slot : node; if (typeof window !== "undefined") { window[Symbol.for("radix-ui")] = true; } return /* @__PURE__ */jsxRuntimeExports.jsx(Comp, { ...primitiveProps, ref: forwardedRef }); }); Node.displayName = `Primitive.${node}`; return { ...primitive, [node]: Node }; }, {}); function dispatchDiscreteCustomEvent(target, event) { if (target) ReactDOM__namespace.flushSync(() => target.dispatchEvent(event)); } // packages/react/use-callback-ref/src/useCallbackRef.tsx function useCallbackRef(callback) { const callbackRef = React__namespace.useRef(callback); React__namespace.useEffect(() => { callbackRef.current = callback; }); return React__namespace.useMemo(() => (...args) => callbackRef.current?.(...args), []); } // packages/react/use-escape-keydown/src/useEscapeKeydown.tsx function useEscapeKeydown(onEscapeKeyDownProp, ownerDocument = globalThis?.document) { const onEscapeKeyDown = useCallbackRef(onEscapeKeyDownProp); React__namespace.useEffect(() => { const handleKeyDown = event => { if (event.key === "Escape") { onEscapeKeyDown(event); } }; ownerDocument.addEventListener("keydown", handleKeyDown, { capture: true }); return () => ownerDocument.removeEventListener("keydown", handleKeyDown, { capture: true }); }, [onEscapeKeyDown, ownerDocument]); } var DISMISSABLE_LAYER_NAME = "DismissableLayer"; var CONTEXT_UPDATE = "dismissableLayer.update"; var POINTER_DOWN_OUTSIDE = "dismissableLayer.pointerDownOutside"; var FOCUS_OUTSIDE = "dismissableLayer.focusOutside"; var originalBodyPointerEvents; var DismissableLayerContext = /*#__PURE__*/React__namespace.createContext({ layers: /* @__PURE__ */new Set(), layersWithOutsidePointerEventsDisabled: /* @__PURE__ */new Set(), branches: /* @__PURE__ */new Set() }); var DismissableLayer = /*#__PURE__*/React__namespace.forwardRef((props, forwardedRef) => { const { disableOutsidePointerEvents = false, onEscapeKeyDown, onPointerDownOutside, onFocusOutside, onInteractOutside, onDismiss, ...layerProps } = props; const context = React__namespace.useContext(DismissableLayerContext); const [node, setNode] = React__namespace.useState(null); const ownerDocument = node?.ownerDocument ?? globalThis?.document; const [, force] = React__namespace.useState({}); const composedRefs = useComposedRefs(forwardedRef, node2 => setNode(node2)); const layers = Array.from(context.layers); const [highestLayerWithOutsidePointerEventsDisabled] = [...context.layersWithOutsidePointerEventsDisabled].slice(-1); const highestLayerWithOutsidePointerEventsDisabledIndex = layers.indexOf(highestLayerWithOutsidePointerEventsDisabled); const index = node ? layers.indexOf(node) : -1; const isBodyPointerEventsDisabled = context.layersWithOutsidePointerEventsDisabled.size > 0; const isPointerEventsEnabled = index >= highestLayerWithOutsidePointerEventsDisabledIndex; const pointerDownOutside = usePointerDownOutside(event => { const target = event.target; const isPointerDownOnBranch = [...context.branches].some(branch => branch.contains(target)); if (!isPointerEventsEnabled || isPointerDownOnBranch) return; onPointerDownOutside?.(event); onInteractOutside?.(event); if (!event.defaultPrevented) onDismiss?.(); }, ownerDocument); const focusOutside = useFocusOutside(event => { const target = event.target; const isFocusInBranch = [...context.branches].some(branch => branch.contains(target)); if (isFocusInBranch) return; onFocusOutside?.(event); onInteractOutside?.(event); if (!event.defaultPrevented) onDismiss?.(); }, ownerDocument); useEscapeKeydown(event => { const isHighestLayer = index === context.layers.size - 1; if (!isHighestLayer) return; onEscapeKeyDown?.(event); if (!event.defaultPrevented && onDismiss) { event.preventDefault(); onDismiss(); } }, ownerDocument); React__namespace.useEffect(() => { if (!node) return; if (disableOutsidePointerEvents) { if (context.layersWithOutsidePointerEventsDisabled.size === 0) { originalBodyPointerEvents = ownerDocument.body.style.pointerEvents; ownerDocument.body.style.pointerEvents = "none"; } context.layersWithOutsidePointerEventsDisabled.add(node); } context.layers.add(node); dispatchUpdate(); return () => { if (disableOutsidePointerEvents && context.layersWithOutsidePointerEventsDisabled.size === 1) { ownerDocument.body.style.pointerEvents = originalBodyPointerEvents; } }; }, [node, ownerDocument, disableOutsidePointerEvents, context]); React__namespace.useEffect(() => { return () => { if (!node) return; context.layers.delete(node); context.layersWithOutsidePointerEventsDisabled.delete(node); dispatchUpdate(); }; }, [node, context]); React__namespace.useEffect(() => { const handleUpdate = () => force({}); document.addEventListener(CONTEXT_UPDATE, handleUpdate); return () => document.removeEventListener(CONTEXT_UPDATE, handleUpdate); }, []); return /* @__PURE__ */jsxRuntimeExports.jsx(Primitive$2.div, { ...layerProps, ref: composedRefs, style: { pointerEvents: isBodyPointerEventsDisabled ? isPointerEventsEnabled ? "auto" : "none" : void 0, ...props.style }, onFocusCapture: composeEventHandlers$1(props.onFocusCapture, focusOutside.onFocusCapture), onBlurCapture: composeEventHandlers$1(props.onBlurCapture, focusOutside.onBlurCapture), onPointerDownCapture: composeEventHandlers$1(props.onPointerDownCapture, pointerDownOutside.onPointerDownCapture) }); }); DismissableLayer.displayName = DISMISSABLE_LAYER_NAME; var BRANCH_NAME = "DismissableLayerBranch"; var DismissableLayerBranch = /*#__PURE__*/React__namespace.forwardRef((props, forwardedRef) => { const context = React__namespace.useContext(DismissableLayerContext); const ref = React__namespace.useRef(null); const composedRefs = useComposedRefs(forwardedRef, ref); React__namespace.useEffect(() => { const node = ref.current; if (node) { context.branches.add(node); return () => { context.branches.delete(node); }; } }, [context.branches]); return /* @__PURE__ */jsxRuntimeExports.jsx(Primitive$2.div, { ...props, ref: composedRefs }); }); DismissableLayerBranch.displayName = BRANCH_NAME; function usePointerDownOutside(onPointerDownOutside, ownerDocument = globalThis?.document) { const handlePointerDownOutside = useCallbackRef(onPointerDownOutside); const isPointerInsideReactTreeRef = React__namespace.useRef(false); const handleClickRef = React__namespace.useRef(() => {}); React__namespace.useEffect(() => { const handlePointerDown = event => { if (event.target && !isPointerInsideReactTreeRef.current) { let handleAndDispatchPointerDownOutsideEvent2 = function () { handleAndDispatchCustomEvent(POINTER_DOWN_OUTSIDE, handlePointerDownOutside, eventDetail, { discrete: true }); }; const eventDetail = { originalEvent: event }; if (event.pointerType === "touch") { ownerDocument.removeEventListener("click", handleClickRef.current); handleClickRef.current = handleAndDispatchPointerDownOutsideEvent2; ownerDocument.addEventListener("click", handleClickRef.current, { once: true }); } else { handleAndDispatchPointerDownOutsideEvent2(); } } else { ownerDocument.removeEventListener("click", handleClickRef.current); } isPointerInsideReactTreeRef.current = false; }; const timerId = window.setTimeout(() => { ownerDocument.addEventListener("pointerdown", handlePointerDown); }, 0); return () => { window.clearTimeout(timerId); ownerDocument.removeEventListener("pointerdown", handlePointerDown); ownerDocument.removeEventListener("click", handleClickRef.current); }; }, [ownerDocument, handlePointerDownOutside]); return { // ensures we check React component tree (not just DOM tree) onPointerDownCapture: () => isPointerInsideReactTreeRef.current = true }; } function useFocusOutside(onFocusOutside, ownerDocument = globalThis?.document) { const handleFocusOutside = useCallbackRef(onFocusOutside); const isFocusInsideReactTreeRef = React__namespace.useRef(false); React__namespace.useEffect(() => { const handleFocus = event => { if (event.target && !isFocusInsideReactTreeRef.current) { const eventDetail = { originalEvent: event }; handleAndDispatchCustomEvent(FOCUS_OUTSIDE, handleFocusOutside, eventDetail, { discrete: false }); } }; ownerDocument.addEventListener("focusin", handleFocus); return () => ownerDocument.removeEventListener("focusin", handleFocus); }, [ownerDocument, handleFocusOutside]); return { onFocusCapture: () => isFocusInsideReactTreeRef.current = true, onBlurCapture: () => isFocusInsideReactTreeRef.current = false }; } function dispatchUpdate() { const event = new CustomEvent(CONTEXT_UPDATE); document.dispatchEvent(event); } function handleAndDispatchCustomEvent(name, handler, detail, { discrete }) { const target = detail.originalEvent.target; const event = new CustomEvent(name, { bubbles: false, cancelable: true, detail }); if (handler) target.addEventListener(name, handler, { once: true }); if (discrete) { dispatchDiscreteCustomEvent(target, event); } else { target.dispatchEvent(event); } } var count$3 = 0; function useFocusGuards() { React__namespace.useEffect(() => { const edgeGuards = document.querySelectorAll("[data-radix-focus-guard]"); document.body.insertAdjacentElement("afterbegin", edgeGuards[0] ?? createFocusGuard()); document.body.insertAdjacentElement("beforeend", edgeGuards[1] ?? createFocusGuard()); count$3++; return () => { if (count$3 === 1) { document.querySelectorAll("[data-radix-focus-guard]").forEach(node => node.remove()); } count$3--; }; }, []); } function createFocusGuard() { const element = document.createElement("span"); element.setAttribute("data-radix-focus-guard", ""); element.tabIndex = 0; element.style.outline = "none"; element.style.opacity = "0"; element.style.position = "fixed"; element.style.pointerEvents = "none"; return element; } var AUTOFOCUS_ON_MOUNT = "focusScope.autoFocusOnMount"; var AUTOFOCUS_ON_UNMOUNT = "focusScope.autoFocusOnUnmount"; var EVENT_OPTIONS = { bubbles: false, cancelable: true }; var FOCUS_SCOPE_NAME = "FocusScope"; var FocusScope = /*#__PURE__*/React__namespace.forwardRef((props, forwardedRef) => { const { loop = false, trapped = false, onMountAutoFocus: onMountAutoFocusProp, onUnmountAutoFocus: onUnmountAutoFocusProp, ...scopeProps } = props; const [container, setContainer] = React__namespace.useState(null); const onMountAutoFocus = useCallbackRef(onMountAutoFocusProp); const onUnmountAutoFocus = useCallbackRef(onUnmountAutoFocusProp); const lastFocusedElementRef = React__namespace.useRef(null); const composedRefs = useComposedRefs(forwardedRef, node => setContainer(node)); const focusScope = React__namespace.useRef({ paused: false, pause() { this.paused = true; }, resume() { this.paused = false; } }).current; React__namespace.useEffect(() => { if (trapped) { let handleFocusIn2 = function (event) { if (focusScope.paused || !container) return; const target = event.target; if (container.contains(target)) { lastFocusedElementRef.current = target; } else { focus$1(lastFocusedElementRef.current, { select: true }); } }, handleFocusOut2 = function (event) { if (focusScope.paused || !container) return; const relatedTarget = event.relatedTarget; if (relatedTarget === null) return; if (!container.contains(relatedTarget)) { focus$1(lastFocusedElementRef.current, { select: true }); } }, handleMutations2 = function (mutations) { const focusedElement = document.activeElement; if (focusedElement !== document.body) return; for (const mutation of mutations) { if (mutation.removedNodes.length > 0) focus$1(container); } }; document.addEventListener("focusin", handleFocusIn2); document.addEventListener("focusout", handleFocusOut2); const mutationObserver = new MutationObserver(handleMutations2); if (container) mutationObserver.observe(container, { childList: true, subtree: true }); return () => { document.removeEventListener("focusin", handleFocusIn2); document.removeEventListener("focusout", handleFocusOut2); mutationObserver.disconnect(); }; } }, [trapped, container, focusScope.paused]); React__namespace.useEffect(() => { if (container) { focusScopesStack.add(focusScope); const previouslyFocusedElement = document.activeElement; const hasFocusedCandidate = container.contains(previouslyFocusedElement); if (!hasFocusedCandidate) { const mountEvent = new CustomEvent(AUTOFOCUS_ON_MOUNT, EVENT_OPTIONS); container.addEventListener(AUTOFOCUS_ON_MOUNT, onMountAutoFocus); container.dispatchEvent(mountEvent); if (!mountEvent.defaultPrevented) { focusFirst(removeLinks(getTabbableCandidates(container)), { select: true }); if (document.activeElement === previouslyFocusedElement) { focus$1(container); } } } return () => { container.removeEventListener(AUTOFOCUS_ON_MOUNT, onMountAutoFocus); setTimeout(() => { const unmountEvent = new CustomEvent(AUTOFOCUS_ON_UNMOUNT, EVENT_OPTIONS); container.addEventListener(AUTOFOCUS_ON_UNMOUNT, onUnmountAutoFocus); container.dispatchEvent(unmountEvent); if (!unmountEvent.defaultPrevented) { focus$1(previouslyFocusedElement ?? document.body, { select: true }); } container.removeEventListener(AUTOFOCUS_ON_UNMOUNT, onUnmountAutoFocus); focusScopesStack.remove(focusScope); }, 0); }; } }, [container, onMountAutoFocus, onUnmountAutoFocus, focusScope]); const handleKeyDown = React__namespace.useCallback(event => { if (!loop && !trapped) return; if (focusScope.paused) return; const isTabKey = event.key === "Tab" && !event.altKey && !event.ctrlKey && !event.metaKey; const focusedElement = document.activeElement; if (isTabKey && focusedElement) { const container2 = event.currentTarget; const [first, last] = getTabbableEdges(container2); const hasTabbableElementsInside = first && last; if (!hasTabbableElementsInside) { if (focusedElement === container2) event.preventDefault(); } else { if (!event.shiftKey && focusedElement === last) { event.preventDefault(); if (loop) focus$1(first, { select: true }); } else if (event.shiftKey && focusedElement === first) { event.preventDefault(); if (loop) focus$1(last, { select: true }); } } } }, [loop, trapped, focusScope.paused]); return /* @__PURE__ */jsxRuntimeExports.jsx(Primitive$2.div, { tabIndex: -1, ...scopeProps, ref: composedRefs, onKeyDown: handleKeyDown }); }); FocusScope.displayName = FOCUS_SCOPE_NAME; function focusFirst(candidates, { select = false } = {}) { const previouslyFocusedElement = document.activeElement; for (const candidate of candidates) { focus$1(candidate, { select }); if (document.activeElement !== previouslyFocusedElement) return; } } function getTabbableEdges(container) { const candidates = getTabbableCandidates(container); const first = findVisible(candidates, container); const last = findVisible(candidates.reverse(), container); return [first, last]; } function getTabbableCandidates(container) { const nodes = []; const walker = document.createTreeWalker(container, NodeFilter.SHOW_ELEMENT, { acceptNode: node => { const isHiddenInput = node.tagName === "INPUT" && node.type === "hidden"; if (node.disabled || node.hidden || isHiddenInput) return NodeFilter.FILTER_SKIP; return node.tabIndex >= 0 ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP; } }); while (walker.nextNode()) nodes.push(walker.currentNode); return nodes; } function findVisible(elements, container) { for (const element of elements) { if (!isHidden(element, { upTo: container })) return element; } } function isHidden(node, { upTo }) { if (getComputedStyle(node).visibility === "hidden") return true; while (node) { if (upTo !== void 0 && node === upTo) return false; if (getComputedStyle(node).display === "none") return true; node = node.parentElement; } return false; } function isSelectableInput(element) { return element instanceof HTMLInputElement && "select" in element; } function focus$1(element, { select = false } = {}) { if (element && element.focus) { const previouslyFocusedElement = document.activeElement; element.focus({ preventScroll: true }); if (element !== previouslyFocusedElement && isSelectableInput(element) && select) element.select(); } } var focusScopesStack = createFocusScopesStack(); function createFocusScopesStack() { let stack = []; return { add(focusScope) { const activeFocusScope = stack[0]; if (focusScope !== activeFocusScope) { activeFocusScope?.pause(); } stack = arrayRemove(stack, focusScope); stack.unshift(focusScope); }, remove(focusScope) { stack = arrayRemove(stack, focusScope); stack[0]?.resume(); } }; } function arrayRemove(array, item) { const updatedArray = [...array]; const index = updatedArray.indexOf(item); if (index !== -1) { updatedArray.splice(index, 1); } return updatedArray; } function removeLinks(items) { return items.filter(item => item.tagName !== "A"); } // packages/react/use-layout-effect/src/useLayoutEffect.tsx var useLayoutEffect2 = Boolean(globalThis?.document) ? React__namespace.useLayoutEffect : () => {}; // packages/react/id/src/id.tsx var useReactId = React__namespace["useId".toString()] || (() => void 0); var count$2 = 0; function useId(deterministicId) { const [id, setId] = React__namespace.useState(useReactId()); useLayoutEffect2(() => { setId(reactId => reactId ?? String(count$2++)); }, [deterministicId]); return deterministicId || (id ? `radix-${id}` : ""); } /** * Custom positioning reference element. * @see https://floating-ui.com/docs/virtual-elements */ const sides = ['top', 'right', 'bottom', 'left']; const min$1 = Math.min; const max$1 = Math.max; const round = Math.round; const floor = Math.floor; const createCoords = v => ({ x: v, y: v }); const oppositeSideMap = { left: 'right', right: 'left', bottom: 'top', top: 'bottom' }; const oppositeAlignmentMap = { start: 'end', end: 'start' }; function clamp(start, value, end) { return max$1(start, min$1(value, end)); } function evaluate(value, param) { return typeof value === 'function' ? value(param) : value; } function getSide(placement) { return placement.split('-')[0]; } function getAlignment(placement) { return placement.split('-')[1]; } function getOppositeAxis(axis) { return axis === 'x' ? 'y' : 'x'; } function getAxisLength(axis) { return axis === 'y' ? 'height' : 'width'; } function getSideAxis(placement) { return ['top', 'bottom'].includes(getSide(placement)) ? 'y' : 'x'; } function getAlignmentAxis(placement) { return getOppositeAxis(getSideAxis(placement)); } function getAlignmentSides(placement, rects, rtl) { if (rtl === void 0) { rtl = false; } const alignment = getAlignment(placement); const alignmentAxis = getAlignmentAxis(placement); const length = getAxisLength(alignmentAxis); let mainAlignmentSide = alignmentAxis === 'x' ? alignment === (rtl ? 'end' : 'start') ? 'right' : 'left' : alignment === 'start' ? 'bottom' : 'top'; if (rects.reference[length] > rects.floating[length]) { mainAlignmentSide = getOppositePlacement(mainAlignmentSide); } return [mainAlignmentSide, getOppositePlacement(mainAlignmentSide)]; } function getExpandedPlacements(placement) { const oppositePlacement = getOppositePlacement(placement); return [getOppositeAlignmentPlacement(placement), oppositePlacement, getOppositeAlignmentPlacement(oppositePlacement)]; } function getOppositeAlignmentPlacement(placement) { return placement.replace(/start|end/g, alignment => oppositeAlignmentMap[alignment]); } function getSideList(side, isStart, rtl) { const lr = ['left', 'right']; const rl = ['right', 'left']; const tb = ['top', 'bottom']; const bt = ['bottom', 'top']; switch (side) { case 'top': case 'bottom': if (rtl) return isStart ? rl : lr; return isStart ? lr : rl; case 'left': case 'right': return isStart ? tb : bt; default: return []; } } function getOppositeAxisPlacements(placement, flipAlignment, direction, rtl) { const alignment = getAlignment(placement); let list = getSideList(getSide(placement), direction === 'start', rtl); if (alignment) { list = list.map(side => side + "-" + alignment); if (flipAlignment) { list = list.concat(list.map(getOppositeAlignmentPlacement)); } } return list; } function getOppositePlacement(placement) { return placement.replace(/left|right|bottom|top/g, side => oppositeSideMap[side]); } function expandPaddingObject(padding) { return { top: 0, right: 0, bottom: 0, left: 0, ...padding }; } function getPaddingObject(padding) { return typeof padding !== 'number' ? expandPaddingObject(padding) : { top: padding, right: padding, bottom: padding, left: padding }; } function rectToClientRect(rect) { const { x, y, width, height } = rect; return { width, height, top: y, left: x, right: x + width, bottom: y + height, x, y }; } function computeCoordsFromPlacement(_ref, placement, rtl) { let { reference, floating } = _ref; const sideAxis = getSideAxis(placement); const alignmentAxis = getAlignmentAxis(placement); const alignLength = getAxisLength(alignmentAxis); const side = getSide(placement); const isVertical = sideAxis === 'y'; const commonX = reference.x + reference.width / 2 - floating.width / 2; const commonY = reference.y + reference.height / 2 - floating.height / 2; const commonAlign = reference[alignLength] / 2 - floating[alignLength] / 2; let coords; switch (side) { case 'top': coords = { x: commonX, y: reference.y - floating.height }; break; case 'bottom': coords = { x: commonX, y: reference.y + reference.height }; break; case 'right': coords = { x: reference.x + reference.width, y: commonY }; break; case 'left': coords = { x: reference.x - floating.width, y: commonY }; break; default: coords = { x: reference.x, y: reference.y }; } switch (getAlignment(placement)) { case 'start': coords[alignmentAxis] -= commonAlign * (rtl && isVertical ? -1 : 1); break; case 'end': coords[alignmentAxis] += commonAlign * (rtl && isVertical ? -1 : 1); break; } return coords; } /** * Computes the `x` and `y` coordinates that will place the floating element * next to a given reference element. * * This export does not have any `platform` interface logic. You will need to * write one for the platform you are using Floating UI with. */ const computePosition$1 = async (reference, floating, config) => { const { placement = 'bottom', strategy = 'absolute', middleware = [], platform } = config; const validMiddleware = middleware.filter(Boolean); const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(floating)); let rects = await platform.getElementRects({ reference, floating, strategy }); let { x, y } = computeCoordsFromPlacement(rects, placement, rtl); let statefulPlacement = placement; let middlewareData = {}; let resetCount = 0; for (let i = 0; i < validMiddleware.length; i++) { const { name, fn } = validMiddleware[i]; const { x: nextX, y: nextY, data, reset } = await fn({ x, y, initialPlacement: placement, placement: statefulPlacement, strategy, middlewareData, rects, platform, elements: { reference, floating } }); x = nextX != null ? nextX : x; y = nextY != null ? nextY : y; middlewareData = { ...middlewareData, [name]: { ...middlewareData[name], ...data } }; if (reset && resetCount <= 50) { resetCount++; if (typeof reset === 'object') { if (reset.placement) { statefulPlacement = reset.placement; } if (reset.rects) { rects = reset.rects === true ? await platform.getElementRects({ reference, floating, strategy }) : reset.rects; } ({ x, y } = computeCoordsFromPlacement(rects, statefulPlacement, rtl)); } i = -1; } } return { x, y, placement: statefulPlacement, strategy, middlewareData }; }; /** * Resolves with an object of overflow side offsets that determine how much the * element is overflowing a given clipping boundary on each side. * - positive = overflowing the boundary by that number of pixels * - negative = how many pixels left before it will overflow * - 0 = lies flush with the boundary * @see https://floating-ui.com/docs/detectOverflow */ async function detectOverflow(state, options) { var _await$platform$isEle; if (options === void 0) { options = {}; } const { x, y, platform, rects, elements, strategy } = state; const { boundary = 'clippingAncestors', rootBoundary = 'viewport', elementContext = 'floating', altBoundary = false, padding = 0 } = evaluate(options, state); const paddingObject = getPaddingObject(padding); const altContext = elementContext === 'floating' ? 'reference' : 'floating'; const element = elements[altBoundary ? altContext : elementContext]; const clippingClientRect = rectToClientRect(await platform.getClippingRect({ element: ((_await$platform$isEle = await (platform.isElement == null ? void 0 : platform.isElement(element))) != null ? _await$platform$isEle : true) ? element : element.contextElement || (await (platform.getDocumentElement == null ? void 0 : platform.getDocumentElement(elements.floating))), boundary, rootBoundary, strategy })); const rect = elementContext === 'floating' ? { x, y, width: rects.floating.width, height: rects.floating.height } : rects.reference; const offsetParent = await (platform.getOffsetParent == null ? void 0 : platform.getOffsetParent(elements.floating)); const offsetScale = (await (platform.isElement == null ? void 0 : platform.isElement(offsetParent))) ? (await (platform.getScale == null ? void 0 : platform.getScale(offsetParent))) || { x: 1, y: 1 } : { x: 1, y: 1 }; const elementClientRect = rectToClientRect(platform.convertOffsetParentRelativeRectToViewportRelativeRect ? await platform.convertOffsetParentRelativeRectToViewportRelativeRect({ elements, rect, offsetParent, strategy }) : rect); return { top: (clippingClientRect.top - elementClientRect.top + paddingObject.top) / offsetScale.y, bottom: (elementClientRect.bottom - clippingClientRect.bottom + paddingObject.bottom) / offsetScale.y, left: (clippingClientRect.left - elementClientRect.left + paddingObject.left) / offsetScale.x, right: (elementClientRect.right - clippingClientRect.right + paddingObject.right) / offsetScale.x }; } /** * Provides data to position an inner element of the floating element so that it * appears centered to the reference element. * @see https://floating-ui.com/docs/arrow */ const arrow$3 = options => ({ name: 'arrow', options, async fn(state) { const { x, y, placement, rects, platform, elements, middlewareData } = state; // Since `element` is required, we don't Partial<> the type. const { element, padding = 0 } = evaluate(options, state) || {}; if (element == null) { return {}; } const paddingObject = getPaddingObject(padding); const coords = { x, y }; const axis = getAlignmentAxis(placement); const length = getAxisLength(axis); const arrowDimensions = await platform.getDimensions(element); const isYAxis = axis === 'y'; const minProp = isYAxis ? 'top' : 'left'; const maxProp = isYAxis ? 'bottom' : 'right'; const clientProp = isYAxis ? 'clientHeight' : 'clientWidth'; const endDiff = rects.reference[length] + rects.reference[axis] - coords[axis] - rects.floating[length]; const startDiff = coords[axis] - rects.reference[axis]; const arrowOffsetParent = await (platform.getOffsetParent == null ? void 0 : platform.getOffsetParent(element)); let clientSize = arrowOffsetParent ? arrowOffsetParent[clientProp] : 0; // DOM platform can return `window` as the `offsetParent`. if (!clientSize || !(await (platform.isElement == null ? void 0 : platform.isElement(arrowOffsetParent)))) { clientSize = elements.floating[clientProp] || rects.floating[length]; } const centerToReference = endDiff / 2 - startDiff / 2; // If the padding is large enough that it causes the arrow to no longer be // centered, modify the padding so that it is centered. const largestPossiblePadding = clientSize / 2 - arrowDimensions[length] / 2 - 1; const minPadding = min$1(paddingObject[minProp], largestPossiblePadding); const maxPadding = min$1(paddingObject[maxProp], largestPossiblePadding); // Make sure the arrow doesn't overflow the floating element if the center // point is outside the floating element's bounds. const min$1$1 = minPadding; const max = clientSize - arrowDimensions[length] - maxPadding; const center = clientSize / 2 - arrowDimensions[length] / 2 + centerToReference; const offset = clamp(min$1$1, center, max); // If the reference is small enough that the arrow's padding causes it to // to point to nothing for an aligned placement, adjust the offset of the // floating element itself. To ensure `shift()` continues to take action, // a single reset is performed when this is true. const shouldAddOffset = !middlewareData.arrow && getAlignment(placement) != null && center !== offset && rects.reference[length] / 2 - (center < min$1$1 ? minPadding : maxPadding) - arrowDimensions[length] / 2 < 0; const alignmentOffset = shouldAddOffset ? center < min$1$1 ? center - min$1$1 : center - max : 0; return { [axis]: coords[axis] + alignmentOffset, data: { [axis]: offset, centerOffset: center - offset - alignmentOffset, ...(shouldAddOffset && { alignmentOffset }) }, reset: shouldAddOffset }; } }); /** * Optimizes the visibility of the floating element by flipping the `placement` * in order to keep it in view when the preferred placement(s) will overflow the * clipping boundary. Alternative to `autoPlacement`. * @see https://floating-ui.com/docs/flip */ const flip$2 = function (options) { if (options === void 0) { options = {}; } return { name: 'flip', options, async fn(state) { var _middlewareData$arrow, _middlewareData$flip; const { placement, middlewareData, rects, initialPlacement, platform, elements } = state; const { mainAxis: checkMainAxis = true, crossAxis: checkCrossAxis = true, fallbackPlacements: specifiedFallbackPlacements, fallbackStrategy = 'bestFit', fallbackAxisSideDirection = 'none', flipAlignment = true, ...detectOverflowOptions } = evaluate(options, state); // If a reset by the arrow was caused due to an alignment offset being // added, we should skip any logic now since `flip()` has already done its // work. // https://github.com/floating-ui/floating-ui/issues/2549#issuecomment-1719601643 if ((_middlewareData$arrow = middlewareData.arrow) != null && _middlewareData$arrow.alignmentOffset) { return {}; } const side = getSide(placement); const initialSideAxis = getSideAxis(initialPlacement); const isBasePlacement = getSide(initialPlacement) === initialPlacement; const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating)); const fallbackPlacements = specifiedFallbackPlacements || (isBasePlacement || !flipAlignment ? [getOppositePlacement(initialPlacement)] : getExpandedPlacements(initialPlacement)); const hasFallbackAxisSideDirection = fallbackAxisSideDirection !== 'none'; if (!specifiedFallbackPlacements && hasFallbackAxisSideDirection) { fallbackPlacements.push(...getOppositeAxisPlacements(initialPlacement, flipAlignment, fallbackAxisSideDirection, rtl)); } const placements = [initialPlacement, ...fallbackPlacements]; const overflow = await detectOverflow(state, detectOverflowOptions); const overflows = []; let overflowsData = ((_middlewareData$flip = middlewareData.flip) == null ? void 0 : _middlewareData$flip.overflows) || []; if (checkMainAxis) { overflows.push(overflow[side]); } if (checkCrossAxis) { const sides = getAlignmentSides(placement, rects, rtl); overflows.push(overflow[sides[0]], overflow[sides[1]]); } overflowsData = [...overflowsData, { placement, overflows }]; // One or more sides is overflowing. if (!overflows.every(side => side <= 0)) { var _middlewareData$flip2, _overflowsData$filter; const nextIndex = (((_middlewareData$flip2 = middlewareData.flip) == null ? void 0 : _middlewareData$flip2.index) || 0) + 1; const nextPlacement = placements[nextIndex]; if (nextPlacement) { // Try next placement and re-run the lifecycle. return { data: { index: nextIndex, overflows: overflowsData }, reset: { placement: nextPlacement } }; } // First, find the candidates that fit on the mainAxis side of overflow, // then find the placement that fits the best on the main crossAxis side. let resetPlacement = (_overflowsData$filter = overflowsData.filter(d => d.overflows[0] <= 0).sort((a, b) => a.overflows[1] - b.overflows[1])[0]) == null ? void 0 : _overflowsData$filter.placement; // Otherwise fallback. if (!resetPlacement) { switch (fallbackStrategy) { case 'bestFit': { var _overflowsData$filter2; const placement = (_overflowsData$filter2 = overflowsData.filter(d => { if (hasFallbackAxisSideDirection) { const currentSideAxis = getSideAxis(d.placement); return currentSideAxis === initialSideAxis || // Create a bias to the `y` side axis due to horizontal // reading directions favoring greater width. currentSideAxis === 'y'; } return true; }).map(d => [d.placement, d.overflows.filter(overflow => overflow > 0).reduce((acc, overflow) => acc + overflow, 0)]).sort((a, b) => a[1] - b[1])[0]) == null ? void 0 : _overflowsData$filter2[0]; if (placement) { resetPlacement = placement; } break; } case 'initialPlacement': resetPlacement = initialPlacement; break; } } if (placement !== resetPlacement) { return { reset: { placement: resetPlacement } }; } } return {}; } }; }; function getSideOffsets(overflow, rect) { return { top: overflow.top - rect.height, right: overflow.right - rect.width, bottom: overflow.bottom - rect.height, left: overflow.left - rect.width }; } function isAnySideFullyClipped(overflow) { return sides.some(side => overflow[side] >= 0); } /** * Provides data to hide the floating element in applicable situations, such as * when it is not in the same clipping context as the reference element. * @see https://floating-ui.com/docs/hide */ const hide$2 = function (options) { if (options === void 0) { options = {}; } return { name: 'hide', options, async fn(state) { const { rects } = state; const { strategy = 'referenceHidden', ...detectOverflowOptions } = evaluate(options, state); switch (strategy) { case 'referenceHidden': { const overflow = await detectOverflow(state, { ...detectOverflowOptions, elementContext: 'reference' }); const offsets = getSideOffsets(overflow, rects.reference); return { data: { referenceHiddenOffsets: offsets, referenceHidden: isAnySideFullyClipped(offsets) } }; } case 'escaped': { const overflow = await detectOverflow(state, { ...detectOverflowOptions, altBoundary: true }); const offsets = getSideOffsets(overflow, rects.floating); return { data: { escapedOffsets: offsets, escaped: isAnySideFullyClipped(offsets) } }; } default: { return {}; } } } }; }; // For type backwards-compatibility, the `OffsetOptions` type was also // Derivable. async function convertValueToCoords(state, options) { const { placement, platform, elements } = state; const rtl = await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating)); const side = getSide(placement); const alignment = getAlignment(placement); const isVertical = getSideAxis(placement) === 'y'; const mainAxisMulti = ['left', 'top'].includes(side) ? -1 : 1; const crossAxisMulti = rtl && isVertical ? -1 : 1; const rawValue = evaluate(options, state); // eslint-disable-next-line prefer-const let { mainAxis, crossAxis, alignmentAxis } = typeof rawValue === 'number' ? { mainAxis: rawValue, crossAxis: 0, alignmentAxis: null } : { mainAxis: rawValue.mainAxis || 0, crossAxis: rawValue.crossAxis || 0, alignmentAxis: rawValue.alignmentAxis }; if (alignment && typeof alignmentAxis === 'number') { crossAxis = alignment === 'end' ? alignmentAxis * -1 : alignmentAxis; } return isVertical ? { x: crossAxis * crossAxisMulti, y: mainAxis * mainAxisMulti } : { x: mainAxis * mainAxisMulti, y: crossAxis * crossAxisMulti }; } /** * Modifies the placement by translating the floating element along the * specified axes. * A number (shorthand for `mainAxis` or distance), or an axes configuration * object may be passed. * @see https://floating-ui.com/docs/offset */ const offset$3 = function (options) { if (options === void 0) { options = 0; } return { name: 'offset', options, async fn(state) { var _middlewareData$offse, _middlewareData$arrow; const { x, y, placement, middlewareData } = state; const diffCoords = await convertValueToCoords(state, options); // If the placement is the same and the arrow caused an alignment offset // then we don't need to change the positioning coordinates. if (placement === ((_middlewareData$offse = middlewareData.offset) == null ? void 0 : _middlewareData$offse.placement) && (_middlewareData$arrow = middlewareData.arrow) != null && _middlewareData$arrow.alignmentOffset) { return {}; } return { x: x + diffCoords.x, y: y + diffCoords.y, data: { ...diffCoords, placement } }; } }; }; /** * Optimizes the visibility of the floating element by shifting it in order to * keep it in view when it will overflow the clipping boundary. * @see https://floating-ui.com/docs/shift */ const shift$3 = function (options) { if (options === void 0) { options = {}; } return { name: 'shift', options, async fn(state) { const { x, y, placement } = state; const { mainAxis: checkMainAxis = true, crossAxis: checkCrossAxis = false, limiter = { fn: _ref => { let { x, y } = _ref; return { x, y }; } }, ...detectOverflowOptions } = evaluate(options, state); const coords = { x, y }; const overflow = await detectOverflow(state, detectOverflowOptions); const crossAxis = getSideAxis(getSide(placement)); const mainAxis = getOppositeAxis(crossAxis); let mainAxisCoord = coords[mainAxis]; let crossAxisCoord = coords[crossAxis]; if (checkMainAxis) { const minSide = mainAxis === 'y' ? 'top' : 'left'; const maxSide = mainAxis === 'y' ? 'bottom' : 'right'; const min = mainAxisCoord + overflow[minSide]; const max = mainAxisCoord - overflow[maxSide]; mainAxisCoord = clamp(min, mainAxisCoord, max); } if (checkCrossAxis) { const minSide = crossAxis === 'y' ? 'top' : 'left'; const maxSide = crossAxis === 'y' ? 'bottom' : 'right'; const min = crossAxisCoord + overflow[minSide]; const max = crossAxisCoord - overflow[maxSide]; crossAxisCoord = clamp(min, crossAxisCoord, max); } const limitedCoords = limiter.fn({ ...state, [mainAxis]: mainAxisCoord, [crossAxis]: crossAxisCoord }); return { ...limitedCoords, data: { x: limitedCoords.x - x, y: limitedCoords.y - y, enabled: { [mainAxis]: checkMainAxis, [crossAxis]: checkCrossAxis } } }; } }; }; /** * Built-in `limiter` that will stop `shift()` at a certain point. */ const limitShift$2 = function (options) { if (options === void 0) { options = {}; } return { options, fn(state) { const { x, y, placement, rects, middlewareData } = state; const { offset = 0, mainAxis: checkMainAxis = true, crossAxis: checkCrossAxis = true } = evaluate(options, state); const coords = { x, y }; const crossAxis = getSideAxis(placement); const mainAxis = getOppositeAxis(crossAxis); let mainAxisCoord = coords[mainAxis]; let crossAxisCoord = coords[crossAxis]; const rawOffset = evaluate(offset, state); const computedOffset = typeof rawOffset === 'number' ? { mainAxis: rawOffset, crossAxis: 0 } : { mainAxis: 0, crossAxis: 0, ...rawOffset }; if (checkMainAxis) { const len = mainAxis === 'y' ? 'height' : 'width'; const limitMin = rects.reference[mainAxis] - rects.floating[len] + computedOffset.mainAxis; const limitMax = rects.reference[mainAxis] + rects.reference[len] - computedOffset.mainAxis; if (mainAxisCoord < limitMin) { mainAxisCoord = limitMin; } else if (mainAxisCoord > limitMax) { mainAxisCoord = limitMax; } } if (checkCrossAxis) { var _middlewareData$offse, _middlewareData$offse2; const len = mainAxis === 'y' ? 'width' : 'height'; const isOriginSide = ['top', 'left'].includes(getSide(placement)); const limitMin = rects.reference[crossAxis] - rects.floating[len] + (isOriginSide ? ((_middlewareData$offse = middlewareData.offset) == null ? void 0 : _middlewareData$offse[crossAxis]) || 0 : 0) + (isOriginSide ? 0 : computedOffset.crossAxis); const limitMax = rects.reference[crossAxis] + rects.reference[len] + (isOriginSide ? 0 : ((_middlewareData$offse2 = middlewareData.offset) == null ? void 0 : _middlewareData$offse2[crossAxis]) || 0) - (isOriginSide ? computedOffset.crossAxis : 0); if (crossAxisCoord < limitMin) { crossAxisCoord = limitMin; } else if (crossAxisCoord > limitMax) { crossAxisCoord = limitMax; } } return { [mainAxis]: mainAxisCoord, [crossAxis]: crossAxisCoord }; } }; }; /** * Provides data that allows you to change the size of the floating element — * for instance, prevent it from overflowing the clipping boundary or match the * width of the reference element. * @see https://floating-ui.com/docs/size */ const size$2 = function (options) { if (options === void 0) { options = {}; } return { name: 'size', options, async fn(state) { var _state$middlewareData, _state$middlewareData2; const { placement, rects, platform, elements } = state; const { apply = () => {}, ...detectOverflowOptions } = evaluate(options, state); const overflow = await detectOverflow(state, detectOverflowOptions); const side = getSide(placement); const alignment = getAlignment(placement); const isYAxis = getSideAxis(placement) === 'y'; const { width, height } = rects.floating; let heightSide; let widthSide; if (side === 'top' || side === 'bottom') { heightSide = side; widthSide = alignment === ((await (platform.isRTL == null ? void 0 : platform.isRTL(elements.floating))) ? 'start' : 'end') ? 'left' : 'right'; } else { widthSide = side; heightSide = alignment === 'end' ? 'top' : 'bottom'; } const maximumClippingHeight = height - overflow.top - overflow.bottom; const maximumClippingWidth = width - overflow.left - overflow.right; const overflowAvailableHeight = min$1(height - overflow[heightSide], maximumClippingHeight); const overflowAvailableWidth = min$1(width - overflow[widthSide], maximumClippingWidth); const noShift = !state.middlewareData.shift; let availableHeight = overflowAvailableHeight; let availableWidth = overflowAvailableWidth; if ((_state$middlewareData = state.middlewareData.shift) != null && _state$middlewareData.enabled.x) { availableWidth = maximumClippingWidth; } if ((_state$middlewareData2 = state.middlewareData.shift) != null && _state$middlewareData2.enabled.y) { availableHeight = maximumClippingHeight; } if (noShift && !alignment) { const xMin = max$1(overflow.left, 0); const xMax = max$1(overflow.right, 0); const yMin = max$1(overflow.top, 0); const yMax = max$1(overflow.bottom, 0); if (isYAxis) { availableWidth = width - 2 * (xMin !== 0 || xMax !== 0 ? xMin + xMax : max$1(overflow.left, overflow.right)); } else { availableHeight = height - 2 * (yMin !== 0 || yMax !== 0 ? yMin + yMax : max$1(overflow.top, overflow.bottom)); } } await apply({ ...state, availableWidth, availableHeight }); const nextDimensions = await platform.getDimensions(elements.floating); if (width !== nextDimensions.width || height !== nextDimensions.height) { return { reset: { rects: true } }; } return {}; } }; }; function hasWindow() { return typeof window !== 'undefined'; } function getNodeName(node) { if (isNode(node)) { return (node.nodeName || '').toLowerCase(); } // Mocked nodes in testing environments may not be instances of Node. By // returning `#document` an infinite loop won't occur. // https://github.com/floating-ui/floating-ui/issues/2317 return '#document'; } function getWindow(node) { var _node$ownerDocument; return (node == null || (_node$ownerDocument = node.ownerDocument) == null ? void 0 : _node$ownerDocument.defaultView) || window; } function getDocumentElement$1(node) { var _ref; return (_ref = (isNode(node) ? node.ownerDocument : node.document) || window.document) == null ? void 0 : _ref.documentElement; } function isNode(value) { if (!hasWindow()) { return false; } return value instanceof Node || value instanceof getWindow(value).Node; } function isElement$1(value) { if (!hasWindow()) { return false; } return value instanceof Element || value instanceof getWindow(value).Element; } function isHTMLElement(value) { if (!hasWindow()) { return false; } return value instanceof HTMLElement || value instanceof getWindow(value).HTMLElement; } function isShadowRoot(value) { if (!hasWindow() || typeof ShadowRoot === 'undefined') { return false; } return value instanceof ShadowRoot || value instanceof getWindow(value).ShadowRoot; } function isOverflowElement(element) { const { overflow, overflowX, overflowY, display } = getComputedStyle$1(element); return /auto|scroll|overlay|hidden|clip/.test(overflow + overflowY + overflowX) && !['inline', 'contents'].includes(display); } function isTableElement(element) { return ['table', 'td', 'th'].includes(getNodeName(element)); } function isTopLayer(element) { return [':popover-open', ':modal'].some(selector => { try { return element.matches(selector); } catch (e) { return false; } }); } function isContainingBlock(elementOrCss) { const webkit = isWebKit(); const css = isElement$1(elementOrCss) ? getComputedStyle$1(elementOrCss) : elementOrCss; // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block // https://drafts.csswg.org/css-transforms-2/#individual-transforms return ['transform', 'translate', 'scale', 'rotate', 'perspective'].some(value => css[value] ? css[value] !== 'none' : false) || (css.containerType ? css.containerType !== 'normal' : false) || !webkit && (css.backdropFilter ? css.backdropFilter !== 'none' : false) || !webkit && (css.filter ? css.filter !== 'none' : false) || ['transform', 'translate', 'scale', 'rotate', 'perspective', 'filter'].some(value => (css.willChange || '').includes(value)) || ['paint', 'layout', 'strict', 'content'].some(value => (css.contain || '').includes(value)); } function getContainingBlock(element) { let currentNode = getParentNode(element); while (isHTMLElement(currentNode) && !isLastTraversableNode(currentNode)) { if (isContainingBlock(currentNode)) { return currentNode; } else if (isTopLayer(currentNode)) { return null; } currentNode = getParentNode(currentNode); } return null; } function isWebKit() { if (typeof CSS === 'undefined' || !CSS.supports) return false; return CSS.supports('-webkit-backdrop-filter', 'none'); } function isLastTraversableNode(node) { return ['html', 'body', '#document'].includes(getNodeName(node)); } function getComputedStyle$1(element) { return getWindow(element).getComputedStyle(element); } function getNodeScroll(element) { if (isElement$1(element)) { return { scrollLeft: element.scrollLeft, scrollTop: element.scrollTop }; } return { scrollLeft: element.scrollX, scrollTop: element.scrollY }; } function getParentNode(node) { if (getNodeName(node) === 'html') { return node; } const result = // Step into the shadow DOM of the parent of a slotted node. node.assignedSlot || // DOM Element detected. node.parentNode || // ShadowRoot detected. isShadowRoot(node) && node.host || // Fallback. getDocumentElement$1(node); return isShadowRoot(result) ? result.host : result; } function getNearestOverflowAncestor(node) { const parentNode = getParentNode(node); if (isLastTraversableNode(parentNode)) { return node.ownerDocument ? node.ownerDocument.body : node.body; } if (isHTMLElement(parentNode) && isOverflowElement(parentNode)) { return parentNode; } return getNearestOverflowAncestor(parentNode); } function getOverflowAncestors(node, list, traverseIframes) { var _node$ownerDocument2; if (list === void 0) { list = []; } if (traverseIframes === void 0) { traverseIframes = true; } const scrollableAncestor = getNearestOverflowAncestor(node); const isBody = scrollableAncestor === ((_node$ownerDocument2 = node.ownerDocument) == null ? void 0 : _node$ownerDocument2.body); const win = getWindow(scrollableAncestor); if (isBody) { const frameElement = getFrameElement(win); return list.concat(win, win.visualViewport || [], isOverflowElement(scrollableAncestor) ? scrollableAncestor : [], frameElement && traverseIframes ? getOverflowAncestors(frameElement) : []); } return list.concat(scrollableAncestor, getOverflowAncestors(scrollableAncestor, [], traverseIframes)); } function getFrameElement(win) { return win.parent && Object.getPrototypeOf(win.parent) ? win.frameElement : null; } function getCssDimensions(element) { const css = getComputedStyle$1(element); // In testing environments, the `width` and `height` properties are empty // strings for SVG elements, returning NaN. Fallback to `0` in this case. let width = parseFloat(css.width) || 0; let height = parseFloat(css.height) || 0; const hasOffset = isHTMLElement(element); const offsetWidth = hasOffset ? element.offsetWidth : width; const offsetHeight = hasOffset ? element.offsetHeight : height; const shouldFallback = round(width) !== offsetWidth || round(height) !== offsetHeight; if (shouldFallback) { width = offsetWidth; height = offsetHeight; } return { width, height, $: shouldFallback }; } function unwrapElement(element) { return !isElement$1(element) ? element.contextElement : element; } function getScale(element) { const domElement = unwrapElement(element); if (!isHTMLElement(domElement)) { return createCoords(1); } const rect = domElement.getBoundingClientRect(); const { width, height, $ } = getCssDimensions(domElement); let x = ($ ? round(rect.width) : rect.width) / width; let y = ($ ? round(rect.height) : rect.height) / height; // 0, NaN, or Infinity should always fallback to 1. if (!x || !Number.isFinite(x)) { x = 1; } if (!y || !Number.isFinite(y)) { y = 1; } return { x, y }; } const noOffsets = /*#__PURE__*/createCoords(0); function getVisualOffsets(element) { const win = getWindow(element); if (!isWebKit() || !win.visualViewport) { return noOffsets; } return { x: win.visualViewport.offsetLeft, y: win.visualViewport.offsetTop }; } function shouldAddVisualOffsets(element, isFixed, floatingOffsetParent) { if (isFixed === void 0) { isFixed = false; } if (!floatingOffsetParent || isFixed && floatingOffsetParent !== getWindow(element)) { return false; } return isFixed; } function getBoundingClientRect(element, includeScale, isFixedStrategy, offsetParent) { if (includeScale === void 0) { includeScale = false; } if (isFixedStrategy === void 0) { isFixedStrategy = false; } const clientRect = element.getBoundingClientRect(); const domElement = unwrapElement(element); let scale = createCoords(1); if (includeScale) { if (offsetParent) { if (isElement$1(offsetParent)) { scale = getScale(offsetParent); } } else { scale = getScale(element); } } const visualOffsets = shouldAddVisualOffsets(domElement, isFixedStrategy, offsetParent) ? getVisualOffsets(domElement) : createCoords(0); let x = (clientRect.left + visualOffsets.x) / scale.x; let y = (clientRect.top + visualOffsets.y) / scale.y; let width = clientRect.width / scale.x; let height = clientRect.height / scale.y; if (domElement) { const win = getWindow(domElement); const offsetWin = offsetParent && isElement$1(offsetParent) ? getWindow(offsetParent) : offsetParent; let currentWin = win; let currentIFrame = getFrameElement(currentWin); while (currentIFrame && offsetParent && offsetWin !== currentWin) { const iframeScale = getScale(currentIFrame); const iframeRect = currentIFrame.getBoundingClientRect(); const css = getComputedStyle$1(currentIFrame); const left = iframeRect.left + (currentIFrame.clientLeft + parseFloat(css.paddingLeft)) * iframeScale.x; const top = iframeRect.top + (currentIFrame.clientTop + parseFloat(css.paddingTop)) * iframeScale.y; x *= iframeScale.x; y *= iframeScale.y; width *= iframeScale.x; height *= iframeScale.y; x += left; y += top; currentWin = getWindow(currentIFrame); currentIFrame = getFrameElement(currentWin); } } return rectToClientRect({ width, height, x, y }); } // If has a CSS width greater than the viewport, then this will be // incorrect for RTL. function getWindowScrollBarX(element, rect) { const leftScroll = getNodeScroll(element).scrollLeft; if (!rect) { return getBoundingClientRect(getDocumentElement$1(element)).left + leftScroll; } return rect.left + leftScroll; } function getHTMLOffset(documentElement, scroll, ignoreScrollbarX) { if (ignoreScrollbarX === void 0) { ignoreScrollbarX = false; } const htmlRect = documentElement.getBoundingClientRect(); const x = htmlRect.left + scroll.scrollLeft - (ignoreScrollbarX ? 0 : // RTL scrollbar. getWindowScrollBarX(documentElement, htmlRect)); const y = htmlRect.top + scroll.scrollTop; return { x, y }; } function convertOffsetParentRelativeRectToViewportRelativeRect(_ref) { let { elements, rect, offsetParent, strategy } = _ref; const isFixed = strategy === 'fixed'; const documentElement = getDocumentElement$1(offsetParent); const topLayer = elements ? isTopLayer(elements.floating) : false; if (offsetParent === documentElement || topLayer && isFixed) { return rect; } let scroll = { scrollLeft: 0, scrollTop: 0 }; let scale = createCoords(1); const offsets = createCoords(0); const isOffsetParentAnElement = isHTMLElement(offsetParent); if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) { if (getNodeName(offsetParent) !== 'body' || isOverflowElement(documentElement)) { scroll = getNodeScroll(offsetParent); } if (isHTMLElement(offsetParent)) { const offsetRect = getBoundingClientRect(offsetParent); scale = getScale(offsetParent); offsets.x = offsetRect.x + offsetParent.clientLeft; offsets.y = offsetRect.y + offsetParent.clientTop; } } const htmlOffset = documentElement && !isOffsetParentAnElement && !isFixed ? getHTMLOffset(documentElement, scroll, true) : createCoords(0); return { width: rect.width * scale.x, height: rect.height * scale.y, x: rect.x * scale.x - scroll.scrollLeft * scale.x + offsets.x + htmlOffset.x, y: rect.y * scale.y - scroll.scrollTop * scale.y + offsets.y + htmlOffset.y }; } function getClientRects(element) { return Array.from(element.getClientRects()); } // Gets the entire size of the scrollable document area, even extending outside // of the `` and `` rect bounds if horizontally scrollable. function getDocumentRect(element) { const html = getDocumentElement$1(element); const scroll = getNodeScroll(element); const body = element.ownerDocument.body; const width = max$1(html.scrollWidth, html.clientWidth, body.scrollWidth, body.clientWidth); const height = max$1(html.scrollHeight, html.clientHeight, body.scrollHeight, body.clientHeight); let x = -scroll.scrollLeft + getWindowScrollBarX(element); const y = -scroll.scrollTop; if (getComputedStyle$1(body).direction === 'rtl') { x += max$1(html.clientWidth, body.clientWidth) - width; } return { width, height, x, y }; } function getViewportRect(element, strategy) { const win = getWindow(element); const html = getDocumentElement$1(element); const visualViewport = win.visualViewport; let width = html.clientWidth; let height = html.clientHeight; let x = 0; let y = 0; if (visualViewport) { width = visualViewport.width; height = visualViewport.height; const visualViewportBased = isWebKit(); if (!visualViewportBased || visualViewportBased && strategy === 'fixed') { x = visualViewport.offsetLeft; y = visualViewport.offsetTop; } } return { width, height, x, y }; } // Returns the inner client rect, subtracting scrollbars if present. function getInnerBoundingClientRect(element, strategy) { const clientRect = getBoundingClientRect(element, true, strategy === 'fixed'); const top = clientRect.top + element.clientTop; const left = clientRect.left + element.clientLeft; const scale = isHTMLElement(element) ? getScale(element) : createCoords(1); const width = element.clientWidth * scale.x; const height = element.clientHeight * scale.y; const x = left * scale.x; const y = top * scale.y; return { width, height, x, y }; } function getClientRectFromClippingAncestor(element, clippingAncestor, strategy) { let rect; if (clippingAncestor === 'viewport') { rect = getViewportRect(element, strategy); } else if (clippingAncestor === 'document') { rect = getDocumentRect(getDocumentElement$1(element)); } else if (isElement$1(clippingAncestor)) { rect = getInnerBoundingClientRect(clippingAncestor, strategy); } else { const visualOffsets = getVisualOffsets(element); rect = { x: clippingAncestor.x - visualOffsets.x, y: clippingAncestor.y - visualOffsets.y, width: clippingAncestor.width, height: clippingAncestor.height }; } return rectToClientRect(rect); } function hasFixedPositionAncestor(element, stopNode) { const parentNode = getParentNode(element); if (parentNode === stopNode || !isElement$1(parentNode) || isLastTraversableNode(parentNode)) { return false; } return getComputedStyle$1(parentNode).position === 'fixed' || hasFixedPositionAncestor(parentNode, stopNode); } // A "clipping ancestor" is an `overflow` element with the characteristic of // clipping (or hiding) child elements. This returns all clipping ancestors // of the given element up the tree. function getClippingElementAncestors(element, cache) { const cachedResult = cache.get(element); if (cachedResult) { return cachedResult; } let result = getOverflowAncestors(element, [], false).filter(el => isElement$1(el) && getNodeName(el) !== 'body'); let currentContainingBlockComputedStyle = null; const elementIsFixed = getComputedStyle$1(element).position === 'fixed'; let currentNode = elementIsFixed ? getParentNode(element) : element; // https://developer.mozilla.org/en-US/docs/Web/CSS/Containing_block#identifying_the_containing_block while (isElement$1(currentNode) && !isLastTraversableNode(currentNode)) { const computedStyle = getComputedStyle$1(currentNode); const currentNodeIsContaining = isContainingBlock(currentNode); if (!currentNodeIsContaining && computedStyle.position === 'fixed') { currentContainingBlockComputedStyle = null; } const shouldDropCurrentNode = elementIsFixed ? !currentNodeIsContaining && !currentContainingBlockComputedStyle : !currentNodeIsContaining && computedStyle.position === 'static' && !!currentContainingBlockComputedStyle && ['absolute', 'fixed'].includes(currentContainingBlockComputedStyle.position) || isOverflowElement(currentNode) && !currentNodeIsContaining && hasFixedPositionAncestor(element, currentNode); if (shouldDropCurrentNode) { // Drop non-containing blocks. result = result.filter(ancestor => ancestor !== currentNode); } else { // Record last containing block for next iteration. currentContainingBlockComputedStyle = computedStyle; } currentNode = getParentNode(currentNode); } cache.set(element, result); return result; } // Gets the maximum area that the element is visible in due to any number of // clipping ancestors. function getClippingRect(_ref) { let { element, boundary, rootBoundary, strategy } = _ref; const elementClippingAncestors = boundary === 'clippingAncestors' ? isTopLayer(element) ? [] : getClippingElementAncestors(element, this._c) : [].concat(boundary); const clippingAncestors = [...elementClippingAncestors, rootBoundary]; const firstClippingAncestor = clippingAncestors[0]; const clippingRect = clippingAncestors.reduce((accRect, clippingAncestor) => { const rect = getClientRectFromClippingAncestor(element, clippingAncestor, strategy); accRect.top = max$1(rect.top, accRect.top); accRect.right = min$1(rect.right, accRect.right); accRect.bottom = min$1(rect.bottom, accRect.bottom); accRect.left = max$1(rect.left, accRect.left); return accRect; }, getClientRectFromClippingAncestor(element, firstClippingAncestor, strategy)); return { width: clippingRect.right - clippingRect.left, height: clippingRect.bottom - clippingRect.top, x: clippingRect.left, y: clippingRect.top }; } function getDimensions(element) { const { width, height } = getCssDimensions(element); return { width, height }; } function getRectRelativeToOffsetParent(element, offsetParent, strategy) { const isOffsetParentAnElement = isHTMLElement(offsetParent); const documentElement = getDocumentElement$1(offsetParent); const isFixed = strategy === 'fixed'; const rect = getBoundingClientRect(element, true, isFixed, offsetParent); let scroll = { scrollLeft: 0, scrollTop: 0 }; const offsets = createCoords(0); if (isOffsetParentAnElement || !isOffsetParentAnElement && !isFixed) { if (getNodeName(offsetParent) !== 'body' || isOverflowElement(documentElement)) { scroll = getNodeScroll(offsetParent); } if (isOffsetParentAnElement) { const offsetRect = getBoundingClientRect(offsetParent, true, isFixed, offsetParent); offsets.x = offsetRect.x + offsetParent.clientLeft; offsets.y = offsetRect.y + offsetParent.clientTop; } else if (documentElement) { // If the scrollbar appears on the left (e.g. RTL systems). Use // Firefox with layout.scrollbar.side = 3 in about:config to test this. offsets.x = getWindowScrollBarX(documentElement); } } const htmlOffset = documentElement && !isOffsetParentAnElement && !isFixed ? getHTMLOffset(documentElement, scroll) : createCoords(0); const x = rect.left + scroll.scrollLeft - offsets.x - htmlOffset.x; const y = rect.top + scroll.scrollTop - offsets.y - htmlOffset.y; return { x, y, width: rect.width, height: rect.height }; } function isStaticPositioned(element) { return getComputedStyle$1(element).position === 'static'; } function getTrueOffsetParent(element, polyfill) { if (!isHTMLElement(element) || getComputedStyle$1(element).position === 'fixed') { return null; } if (polyfill) { return polyfill(element); } let rawOffsetParent = element.offsetParent; // Firefox returns the element as the offsetParent if it's non-static, // while Chrome and Safari return the element. The element must // be used to perform the correct calculations even if the element is // non-static. if (getDocumentElement$1(element) === rawOffsetParent) { rawOffsetParent = rawOffsetParent.ownerDocument.body; } return rawOffsetParent; } // Gets the closest ancestor positioned element. Handles some edge cases, // such as table ancestors and cross browser bugs. function getOffsetParent(element, polyfill) { const win = getWindow(element); if (isTopLayer(element)) { return win; } if (!isHTMLElement(element)) { let svgOffsetParent = getParentNode(element); while (svgOffsetParent && !isLastTraversableNode(svgOffsetParent)) { if (isElement$1(svgOffsetParent) && !isStaticPositioned(svgOffsetParent)) { return svgOffsetParent; } svgOffsetParent = getParentNode(svgOffsetParent); } return win; } let offsetParent = getTrueOffsetParent(element, polyfill); while (offsetParent && isTableElement(offsetParent) && isStaticPositioned(offsetParent)) { offsetParent = getTrueOffsetParent(offsetParent, polyfill); } if (offsetParent && isLastTraversableNode(offsetParent) && isStaticPositioned(offsetParent) && !isContainingBlock(offsetParent)) { return win; } return offsetParent || getContainingBlock(element) || win; } const getElementRects = async function (data) { const getOffsetParentFn = this.getOffsetParent || getOffsetParent; const getDimensionsFn = this.getDimensions; const floatingDimensions = await getDimensionsFn(data.floating); return { reference: getRectRelativeToOffsetParent(data.reference, await getOffsetParentFn(data.floating), data.strategy), floating: { x: 0, y: 0, width: floatingDimensions.width, height: floatingDimensions.height } }; }; function isRTL(element) { return getComputedStyle$1(element).direction === 'rtl'; } const platform = { convertOffsetParentRelativeRectToViewportRelativeRect, getDocumentElement: getDocumentElement$1, getClippingRect, getOffsetParent, getElementRects, getClientRects, getDimensions, getScale, isElement: isElement$1, isRTL }; function rectsAreEqual(a, b) { return a.x === b.x && a.y === b.y && a.width === b.width && a.height === b.height; } // https://samthor.au/2021/observing-dom/ function observeMove(element, onMove) { let io = null; let timeoutId; const root = getDocumentElement$1(element); function cleanup() { var _io; clearTimeout(timeoutId); (_io = io) == null || _io.disconnect(); io = null; } function refresh(skip, threshold) { if (skip === void 0) { skip = false; } if (threshold === void 0) { threshold = 1; } cleanup(); const elementRectForRootMargin = element.getBoundingClientRect(); const { left, top, width, height } = elementRectForRootMargin; if (!skip) { onMove(); } if (!width || !height) { return; } const insetTop = floor(top); const insetRight = floor(root.clientWidth - (left + width)); const insetBottom = floor(root.clientHeight - (top + height)); const insetLeft = floor(left); const rootMargin = -insetTop + "px " + -insetRight + "px " + -insetBottom + "px " + -insetLeft + "px"; const options = { rootMargin, threshold: max$1(0, min$1(1, threshold)) || 1 }; let isFirstUpdate = true; function handleObserve(entries) { const ratio = entries[0].intersectionRatio; if (ratio !== threshold) { if (!isFirstUpdate) { return refresh(); } if (!ratio) { // If the reference is clipped, the ratio is 0. Throttle the refresh // to prevent an infinite loop of updates. timeoutId = setTimeout(() => { refresh(false, 1e-7); }, 1000); } else { refresh(false, ratio); } } if (ratio === 1 && !rectsAreEqual(elementRectForRootMargin, element.getBoundingClientRect())) { // It's possible that even though the ratio is reported as 1, the // element is not actually fully within the IntersectionObserver's root // area anymore. This can happen under performance constraints. This may // be a bug in the browser's IntersectionObserver implementation. To // work around this, we compare the element's bounding rect now with // what it was at the time we created the IntersectionObserver. If they // are not equal then the element moved, so we refresh. refresh(); } isFirstUpdate = false; } // Older browsers don't support a `document` as the root and will throw an // error. try { io = new IntersectionObserver(handleObserve, { ...options, // Handle