{
  "version": 3,
  "sources": ["../../../shared/src/ProjectLicense.ts", "../../../shared/src/lib/getToolFallbackToast.ts", "../../../shared/src/Space.ts", "../../../shared/src/web-and-worker-env/ApiError.ts", "../../../shared/src/ACLAvatar.tsx", "../../../shared/src/ACLAvatar.styles.ts", "../../src/web/pages/project/lib/formatDistanceToNowShort.ts", "../../../shared/src/ACLEntry.ts", "../../../shared/src/lib/getMultiplayerColor.ts", "../../../shared/src/ACLAvatarList.tsx", "../../../shared/src/ACLAvatarList.styles.ts", "../../../shared/src/Deployments.ts", "../../../shared/src/LazyModal.tsx", "../../../shared/src/ProjectBarMenu.styles.ts", "../../../shared/src/ProjectState.ts", "../../../shared/src/AddOnPlan.ts", "../../../shared/src/dashboardPaths.ts", "../../../shared/src/getCollectionName.ts", "../../../shared/src/getProjectLocationLabel.ts", "../../../shared/src/lib/openNewTab.ts", "../../../shared/src/lib/downloads.ts", "../../../shared/src/lib/preventDefaultAndStopPropagation.ts", "../../../shared/src/TeamLicense.ts", "../../../shared/src/useSortedACL.ts", "../../../shared/src/utils/files.ts", "../../../shared/src/utils/fonts.ts", "../../../shared/src/utils/protocolValidation.ts", "../../../shared/src/utils/parseURL.ts", "../../../../../node_modules/safari-14-idb-fix/dist/index.js", "../../../../../node_modules/@iamakulov/idb-keyval/dist/index.js", "../../../shared/src/utils/accessTokenScopes.ts", "../../../shared/src/web-and-worker-env/AccessTokenRefresher.ts", "../../../shared/src/web-and-worker-env/dataLoadingURLGenerators.ts", "../../../shared/src/WindowWithAppStartTime.ts"],
  "sourcesContent": ["export enum ProjectLicenseType {\n\tFreeSite = \"freeSite\",\n\n\t// personal plans\n\tMiniSite = \"miniSite\",\n\tBasicSite = \"basicSite\",\n\tProSite = \"proSite\",\n\n\t// business plans\n\t/** LaunchSite was rebranded from startupSite, value kept across the codebase to avoid migrating DB data */\n\tLaunchSite = \"startupSite\",\n\t/** ScaleSite was rebranded from scaleupSite, value kept across the codebase to avoid migrating DB data */\n\tScaleSite = \"scaleupSite\",\n\n\t// 2025 Plans\n\tBasicSite2025 = \"basicSite2025\",\n\tProSite2025 = \"proSite2025\",\n\tScaleSite2025 = \"scaleSite2025\",\n\n\t// enterprise plan\n\tEnterpriseSite = \"enterpriseSite\",\n}\n\nconst personalLicenseTypes = [ProjectLicenseType.MiniSite, ProjectLicenseType.BasicSite, ProjectLicenseType.ProSite]\nconst businessLicenseTypes = [ProjectLicenseType.LaunchSite, ProjectLicenseType.ScaleSite]\nconst licenseTypes2025 = [\n\tProjectLicenseType.BasicSite2025,\n\tProjectLicenseType.ProSite2025,\n\tProjectLicenseType.ScaleSite2025,\n]\n\n/** @deprecated cleanup after introduction of 2025 plans */\nexport function isPersonalLicenseType(\n\tlicenseType: ProjectLicenseType,\n): licenseType is ProjectLicenseType.MiniSite | ProjectLicenseType.BasicSite | ProjectLicenseType.ProSite {\n\treturn personalLicenseTypes.includes(licenseType)\n}\n\n/** @deprecated cleanup after introduction of 2025 plans */\nexport function isBusinessLicenseType(\n\tlicenseType: ProjectLicenseType,\n): licenseType is ProjectLicenseType.LaunchSite | ProjectLicenseType.ScaleSite {\n\treturn businessLicenseTypes.includes(licenseType)\n}\n\nexport function isLicenseType2025(\n\tlicenseType: ProjectLicenseType,\n): licenseType is ProjectLicenseType.BasicSite2025 | ProjectLicenseType.ProSite2025 | ProjectLicenseType.ScaleSite2025 {\n\treturn licenseTypes2025.includes(licenseType)\n}\n\nexport type PaidProjectLicenseType = Exclude<\n\tProjectLicenseType,\n\tProjectLicenseType.EnterpriseSite | ProjectLicenseType.FreeSite\n>\n\n/** Includes license types the user can buy in the app, all but free and enterprise */\nexport function isPaidLicenseType(licenseType: ProjectLicenseType): licenseType is PaidProjectLicenseType {\n\treturn licenseType !== ProjectLicenseType.FreeSite && licenseType !== ProjectLicenseType.EnterpriseSite\n}\n\nexport enum ProjectLicensePeriod {\n\tYear = \"year\",\n\tMonth = \"month\",\n}\n\n// Order of the license types, from the lowest to the highest tier\n// in terms of features and limits.\nconst order = [\n\tProjectLicenseType.FreeSite,\n\tProjectLicenseType.MiniSite,\n\tProjectLicenseType.BasicSite2025,\n\tProjectLicenseType.BasicSite,\n\tProjectLicenseType.ProSite,\n\tProjectLicenseType.ProSite2025,\n\tProjectLicenseType.LaunchSite,\n\tProjectLicenseType.ScaleSite,\n\tProjectLicenseType.ScaleSite2025,\n\tProjectLicenseType.EnterpriseSite,\n] as const\n\nconst PROJECT_NAME_MAP: Record<ProjectLicenseType, string> = {\n\t[ProjectLicenseType.FreeSite]: \"Free\",\n\t[ProjectLicenseType.MiniSite]: \"Mini \u201924\",\n\t[ProjectLicenseType.BasicSite]: \"Basic \u201924\",\n\t[ProjectLicenseType.ProSite]: \"Pro \u201924\",\n\t[ProjectLicenseType.LaunchSite]: \"Launch \u201924\",\n\t[ProjectLicenseType.ScaleSite]: \"Scale \u201924\",\n\t[ProjectLicenseType.BasicSite2025]: \"Basic\",\n\t[ProjectLicenseType.ProSite2025]: \"Pro\",\n\t[ProjectLicenseType.ScaleSite2025]: \"Scale\",\n\t[ProjectLicenseType.EnterpriseSite]: \"Enterprise\",\n}\n\n/**\n * The highest tier plan after which we upsell to the Enterprise plan\n * @deprecated compare against the highest resource limit of paid self serve plans instead\n */\nexport function getHighestTierSiteUpsell(): ProjectLicenseType {\n\treturn ProjectLicenseType.ScaleSite2025\n}\n\n/**\n * Compare two sites licenses based on their hierarchical importance. E.g. a pro site license is \"greater\" than a basic site license.\n * Never use this function for feature access.\n * @param a\n * @param b\n * @returns true if a is higher in the hierarchy than b\n */\nexport function isSiteLicenseGreater(a: ProjectLicenseType, b: ProjectLicenseType): boolean {\n\treturn order.indexOf(a) > order.indexOf(b)\n}\n\nexport interface ProjectLicense {\n\tid: string\n\tprojectId: string\n\ttype: ProjectLicenseType\n\texpirationDate: null | Date\n\tsubscriptionIsActive: boolean\n\tperiod: ProjectLicensePeriod | null\n\tdomainVoucher?: {\n\t\tid: string\n\t\tredeemed: boolean\n\t}\n}\n\nexport const isValidProjectLicense = (value: string | null | undefined): value is ProjectLicenseType =>\n\t!value ? false : value in PROJECT_NAME_MAP\n\nexport const getProjectLicenseName = (licenseType: ProjectLicenseType) => PROJECT_NAME_MAP[licenseType]\n", "import type { ToasterAction } from \"@framerjs/fresco\"\n\ntype FallbackToastKey = \"toolCreateScreen\" | \"toolCreateRectangleShape\"\n\nconst toolFallbackToasts: Record<FallbackToastKey, ToasterAction> = {\n\ttoolCreateScreen: {\n\t\ttype: \"add\",\n\t\tvariant: \"info\",\n\t\ttext: \"Artboards in Framer are Screens. Press S to draw a Screen\",\n\t\tkey: \"use-screen-tool-artboards\",\n\t\ticon: \"screen\",\n\t\tduration: 5000,\n\t\tshowCloseButton: \"always\",\n\t\tstyleOverride: \"fallback-tool\",\n\t},\n\ttoolCreateRectangleShape: {\n\t\ttype: \"add\",\n\t\tvariant: \"info\",\n\t\ttext: \"Use the Frame Tool (F) to draw Rectangles\",\n\t\tkey: \"use-frame-tool-rectangles\",\n\t\ticon: \"frame\",\n\t\ticonOverride: \"frame\",\n\t\tduration: 5000,\n\t\tshowCloseButton: \"always\",\n\t\tstyleOverride: \"fallback-tool\",\n\t},\n}\n\nexport function isValidFallbackKey(key: string): key is FallbackToastKey {\n\treturn toolFallbackToasts[key as FallbackToastKey] !== undefined\n}\n\nexport function setToolFallbackToast(key: FallbackToastKey, toast: React.Dispatch<ToasterAction>) {\n\tdismissToolFallbackToasts(toast)\n\tconst toastData = toolFallbackToasts[key]\n\ttoastData && toast(toastData)\n}\n\nexport function dismissToolFallbackToast(key: FallbackToastKey, toast: React.Dispatch<ToasterAction>) {\n\tconst toastKey = toolFallbackToasts[key].key\n\ttoastKey && toast({ type: \"remove\", key: toastKey })\n}\n\nexport function dismissToolFallbackToasts(toast: React.Dispatch<ToasterAction>) {\n\tfor (const key in toolFallbackToasts) {\n\t\tdismissToolFallbackToast(key as FallbackToastKey, toast)\n\t}\n}\n", "import type { ProjectSpace, TeamExperiments } from \"./ProjectState.ts\"\nimport type { TeamLicense } from \"./TeamLicense.ts\"\n\ninterface SpaceBase {\n\tid: string\n\tavatar: string | null\n\townerId: string\n\tpermissions: { read: boolean; write: boolean }\n\t// Not used, and should be avoided. Use user.defaultSpaceId instead.\n\tisDefault: boolean\n}\n\nexport interface PersonalSpace extends SpaceBase {\n\tscope: \"user\"\n}\n\nexport interface TeamConfiguration {\n\trestrictEmailDomain: boolean\n\tdisablePublicStore: boolean\n\tdisablePrivateStore: boolean\n\tprojectsAccessLevel: string\n\tprototypesAccessLevel: string\n\tautoJoinTeam: boolean\n\tautoJoinDefaultRole: TeamMemberRole\n\tjoinLinkEnabled: boolean\n\tdisableMoveProjects: boolean\n\thidePackages: boolean\n\tallowSitesAccess: boolean\n\tdisableAi: boolean\n\texperiments: TeamExperiments | null\n\tscim: boolean\n}\n\nexport interface OrganizationSpace extends SpaceBase {\n\tdisplayName: string\n\tlicense: TeamLicense\n\tscope: \"organization\"\n\torganization: Organization | null\n\trole: Extract<TeamMemberRole, TeamMemberRole.Admin | TeamMemberRole.Editor | TeamMemberRole.Viewer>\n\tjoinedAt: string\n\tconfiguration: TeamConfiguration\n}\n\nexport enum TeamMemberRole {\n\tViewer = \"viewer\",\n\tEditor = \"editor\",\n\tContentEditor = \"contentEditor\",\n\tAdmin = \"admin\",\n\tExternalEditor = \"external\",\n\tExternalContentEditor = \"externalContent\",\n}\n\nexport interface Organization {\n\tid: string\n\tdisplayName: string\n\tavatar: string | null\n}\n\nexport type Space = PersonalSpace | OrganizationSpace\n\nexport function isPersonalSpace(space: Space | ProjectSpace | undefined): space is PersonalSpace {\n\treturn space?.scope === \"user\"\n}\n\n// NOTE: Don't include ProjectSpace as an allowed space type. The returned type `OrganizationSpace`\n// is broader than a ProjectSpace of scope \"organization\". See the [ProjectSpace](https://github.com/framer/FramerStudio/blob/77b2172ec12999c7e3fa6e88605b380f7fff3a32/src/app/shared/src/ProjectState.ts#L29)\n// type for more details.\n// FIXME: should probably be renamed to isTeamSpace\nexport function isOrganizationSpace(space: Space | undefined): space is OrganizationSpace {\n\treturn space?.scope === \"organization\"\n}\n", "interface ApiErrorConfig {\n\tmessage: string\n\tdata?: Record<string, unknown>\n\tisTemporary?: boolean\n\tref?: string\n\tstatus?: number\n\tskipSentry?: boolean\n\tcode?: number\n\tcause?: unknown\n}\n\nexport class ApiError extends Error {\n\t/** The error message to print out via the console. */\n\toverride readonly message: string\n\n\t/** Error code from the backend */\n\treadonly code?: number\n\n\t/** Generic metadata from the backend. */\n\treadonly data: Readonly<Record<string, unknown>>\n\n\t/** Whether this error can be considered temporary - can be used to decide whether to offer a retry. */\n\treadonly isTemporary: boolean\n\n\t/** An error reference code from the backend. */\n\treadonly ref?: string\n\n\t/** HTTP error code. */\n\treadonly status?: number\n\n\t/** Skip tracking in Sentry */\n\treadonly skipSentry: boolean\n\n\tconstructor({ message, code, data = {}, isTemporary, ref, status, skipSentry, cause }: ApiErrorConfig) {\n\t\tsuper()\n\n\t\t// Strip the stack trace of this custom error.\n\t\tif (Error.captureStackTrace) {\n\t\t\tError.captureStackTrace(this, ApiError)\n\t\t}\n\t\tthis.message = message\n\t\tthis.code = code\n\t\tthis.data = data\n\t\tthis.isTemporary = true\n\t\tthis.ref = ref\n\t\tthis.status = status\n\t\tthis.skipSentry = Boolean(skipSentry)\n\t\tthis.cause = cause\n\n\t\tif (isTemporary !== undefined) {\n\t\t\tthis.isTemporary = isTemporary\n\t\t} else if (status) {\n\t\t\tthis.isTemporary = status !== HTTP_ERROR_CODES.BadRequest\n\t\t}\n\t}\n\n\toverride toString() {\n\t\treturn this.message\n\t}\n\n\tisUnauthorized() {\n\t\treturn this.status === HTTP_ERROR_CODES.Unauthorized\n\t}\n\n\tisNotFound() {\n\t\treturn this.status === HTTP_ERROR_CODES.NotFound\n\t}\n\n\tisForbidden() {\n\t\treturn this.status === HTTP_ERROR_CODES.Forbidden\n\t}\n\n\tisClientError() {\n\t\treturn this.status && this.status >= 400 && this.status < 500\n\t}\n\n\tisServerError() {\n\t\treturn this.status && this.status >= 500\n\t}\n}\n\nexport const HTTP_ERROR_CODES = {\n\tOk: 200,\n\tBadRequest: 400,\n\tUnauthorized: 401,\n\tPaymentDeclined: 402,\n\tForbidden: 403,\n\tNotFound: 404,\n\tConflict: 409,\n}\n", "import { Avatar, FixedPositionTooltip, Stack, Text, useTooltip } from \"@framerjs/fresco\"\nimport { colors } from \"@framerjs/fresco/tokens\"\nimport { cx } from \"@linaria/core\"\nimport React from \"react\"\nimport * as styles from \"./ACLAvatar.styles.ts\"\nimport type { ACLEntry } from \"./ACLEntry.ts\"\nimport { aclEntryStatus } from \"./ACLEntry.ts\"\nimport { getMultiplayerColor } from \"./lib/getMultiplayerColor.ts\"\n\ninterface Props {\n\tentry: ACLEntry\n\tinactive?: boolean\n\tgreyScale?: boolean\n\t/* Show a UI that's irrelevant to the user status: active avatar with inactive tooltip, and the tooltip only shows the name */\n\tignoreStatus?: boolean\n\twithTooltip?: boolean\n\ttooltipText?: string\n\tbadge?: (hover: boolean) => JSX.Element\n\tcontainerClassName?: string\n\tavatarClassName?: string\n\tisDarkMode: boolean\n\tsize?: \"small\" | \"regular\"\n\tshadow?: string\n\tonClick?: React.MouseEventHandler<HTMLDivElement>\n\tonClickHoverIcon?: JSX.Element\n}\n\nexport function ACLAvatar({\n\tentry,\n\tinactive = false,\n\tgreyScale = false,\n\tignoreStatus = false,\n\twithTooltip = false,\n\ttooltipText,\n\tbadge,\n\tcontainerClassName,\n\tavatarClassName,\n\tisDarkMode,\n\tsize,\n\tshadow,\n\tonClick,\n\tonClickHoverIcon,\n}: Props) {\n\tconst ref = React.useRef<HTMLDivElement>(null)\n\tconst { triggerProps, tooltipProps } = useTooltip({\n\t\ttriggerRef: ref,\n\t\tdisabled: !withTooltip,\n\t\ttint: ignoreStatus || inactive ? colors.tooltipBackground : undefined,\n\t})\n\n\tconst color = !inactive ? getMultiplayerColor(entry.color || 0, isDarkMode) : undefined\n\tconst { initials, avatar, name } = entry.user\n\tconst status = aclEntryStatus(entry, !inactive)\n\n\treturn (\n\t\t<>\n\t\t\t<TooltipTrigger ref={ref} {...triggerProps} className={containerClassName}>\n\t\t\t\t<Avatar\n\t\t\t\t\tsrc={avatar}\n\t\t\t\t\tcolor={color}\n\t\t\t\t\ttext={initials}\n\t\t\t\t\tbadge={badge}\n\t\t\t\t\tinactive={inactive}\n\t\t\t\t\tgreyScale={greyScale}\n\t\t\t\t\tonClick={onClick}\n\t\t\t\t\tonClickHoverIcon={onClickHoverIcon}\n\t\t\t\t\tavatarCustomStyles={avatarClassName}\n\t\t\t\t\tshadow={shadow}\n\t\t\t\t\tsize={size}\n\t\t\t\t/>\n\t\t\t</TooltipTrigger>\n\t\t\t<FixedPositionTooltip {...tooltipProps}>\n\t\t\t\t<Stack gap={8} padding=\"5px 0\">\n\t\t\t\t\t{tooltipText ? (\n\t\t\t\t\t\t<Text className={styles.tooltipName} size={12}>\n\t\t\t\t\t\t\t{tooltipText}\n\t\t\t\t\t\t</Text>\n\t\t\t\t\t) : (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<Text className={styles.tooltipName} size={12}>\n\t\t\t\t\t\t\t\t{name}\n\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t{!ignoreStatus && (\n\t\t\t\t\t\t\t\t<Text className={styles.tooltipLabel} size={11}>\n\t\t\t\t\t\t\t\t\t{status}\n\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</>\n\t\t\t\t\t)}\n\t\t\t\t</Stack>\n\t\t\t</FixedPositionTooltip>\n\t\t</>\n\t)\n}\n\nexport const TooltipTrigger = React.forwardRef<HTMLDivElement, React.HtmlHTMLAttributes<HTMLDivElement>>(\n\tfunction TooltipTrigger({ children, className, ...props }, forwardedRef) {\n\t\treturn (\n\t\t\t<div ref={forwardedRef} {...props} className={cx(className)}>\n\t\t\t\t{React.Children.only(children)}\n\t\t\t</div>\n\t\t)\n\t},\n)\n", "import \"ACLAvatar.styles_9wfw7q.wyw.css\"; export const tooltipName = \"tooltipName_ts7fbvw\";\nexport const tooltipLabel = \"tooltipLabel_t18v0z1l\";", "import { assert } from \"@framerjs/shared\"\nimport type { Locale } from \"date-fns\"\nimport { formatDistanceToNow } from \"date-fns\"\n\n// Custom version of formatDistance, inspired by\n// https://github.com/date-fns/date-fns/blob/master/src/locale/en-US/_lib/formatDistance/index.ts\n\nconst formatDistanceLocale = {\n\tlessThanXSeconds: \"{{count}}s\",\n\txSeconds: \"{{count}}s\",\n\thalfAMinute: \"30s\",\n\tlessThanXMinutes: \"{{count}}m\",\n\txMinutes: \"{{count}}m\",\n\taboutXHours: \"{{count}}h\",\n\txHours: \"{{count}}h\",\n\txDays: \"{{count}}d\",\n\taboutXWeeks: \"{{count}}w\",\n\txWeeks: \"{{count}}w\",\n\taboutXMonths: \"{{count}}mo\",\n\txMonths: \"{{count}}mo\",\n\taboutXYears: \"{{count}}y\",\n\txYears: \"{{count}}y\",\n\toverXYears: \"{{count}}y\",\n\talmostXYears: \"{{count}}y\",\n}\n\nconst isDistanceLocalToken = (token: string): token is keyof typeof formatDistanceLocale => {\n\treturn token in formatDistanceLocale\n}\n\nconst isJustNowDistance = (token: keyof typeof formatDistanceLocale): boolean => {\n\treturn token === \"lessThanXSeconds\" || token === \"xSeconds\" || token === \"halfAMinute\" || token === \"lessThanXMinutes\"\n}\n\nfunction createFormatDistance(justNow?: boolean): Locale[\"formatDistance\"] {\n\treturn (token, count, options) => {\n\t\toptions = options || {}\n\t\tassert(isDistanceLocalToken(token), \"Token should have correct value\")\n\t\tif (justNow && isJustNowDistance(token)) {\n\t\t\treturn \"Just now\"\n\t\t}\n\n\t\tconst result = formatDistanceLocale[token].replace(\"{{count}}\", String(count))\n\n\t\tif (options.addSuffix) {\n\t\t\tif (options.comparison && options.comparison > 0) {\n\t\t\t\treturn \"in \" + result\n\t\t\t}\n\n\t\t\treturn result + \" ago\"\n\t\t}\n\n\t\treturn result\n\t}\n}\n\nexport function formatDistanceToNowShort(\n\tdate: number | Date,\n\toptions?: {\n\t\tincludeSeconds?: boolean\n\t\taddSuffix?: boolean\n\t\tlocale?: Locale\n\t\tjustNow?: boolean\n\t},\n) {\n\toptions = options || {}\n\treturn formatDistanceToNow(date, {\n\t\t...options,\n\t\tlocale: { ...options.locale, formatDistance: createFormatDistance(options.justNow) },\n\t})\n}\n", "import { assertNever } from \"@framerjs/shared\"\nimport { formatDistanceToNow, parseISO } from \"date-fns\"\nimport { experiments } from \"../../../app/vekter/src/app/experiments.ts\"\nimport { formatDistanceToNowShort } from \"../../../app/vekter/src/web/pages/project/lib/formatDistanceToNowShort.ts\"\nimport type { User } from \"./User.ts\"\n\n/**\n * The access control list entry in a project.\n */\nexport type ACLEntry = UserACLEntry | InviteACLEntry | AccessRequestACLEntry\n\n/**\n * The kind of the access control list entry,\n * which is populated on the client side.\n */\nexport enum ACLEntryKind {\n\tUser = \"user\",\n\tInvite = \"invite\",\n\tAccessRequest = \"accessRequest\",\n}\n\n/**\n * ACLEntry to map a user to a project\n */\nexport interface UserACLEntry {\n\tkind: ACLEntryKind.User\n\tcolor: number | null\n\tlastOpenedAt: string | null\n\tpending: false\n\tpermissions: ACLPermissions | null\n\trole: Role\n\tuser: User\n}\n\n/**\n * ACLEntry to map an invite to a project.\n * We overload the `user` object:\n * `user.id` holds the inviteId,\n * `user.name` holds the invite's email address.\n */\nexport interface InviteACLEntry {\n\tkind: ACLEntryKind.Invite\n\tcolor: null\n\tlastOpenedAt: null\n\t/**\n\t * Use with caution, `pending === true` for both\n\t * `InviteACLEntry` and `AccessRequestACLEntry`\n\t */\n\tpending: true\n\tpermissions?: ACLPermissions\n\trole: Role\n\tuser: User\n}\n\n/**\n * A pending invite request without an associated user or invite,\n * created on the client side.\n */\nexport interface ACLEntryRequest extends InviteACLEntry {\n\tsuccess: null | boolean\n\temail: string\n}\n\n/**\n * ACLEntry to map an access request to a project.\n */\nexport interface AccessRequestACLEntry {\n\tkind: ACLEntryKind.AccessRequest\n\tid: string // access request id\n\tuser: User\n\temail: string\n\t// these fields are missing,\n\t// but we declare them here to make the\n\t// type compatible with UserACLEntry\n\tcolor: undefined\n\tlastOpenedAt: undefined\n\tpending: undefined\n}\n\ninterface StatusOptions {\n\tshortDate?: boolean\n}\n\nexport function aclEntryStatus(entry: ACLEntry, isActive: boolean, options?: StatusOptions) {\n\tif (isActive) {\n\t\treturn \"Viewing now\"\n\t}\n\tif (entry.lastOpenedAt) {\n\t\tconst formatToNow = options?.shortDate ? formatDistanceToNowShort : formatDistanceToNow\n\t\tconst [first, ...rest] = formatToNow(parseISO(entry.lastOpenedAt), { addSuffix: true })\n\t\treturn [first?.toLocaleUpperCase() ?? \"\", ...rest].join(\"\")\n\t}\n\treturn \"Never viewed\"\n}\n\nexport const enum Role {\n\t// User can make additional changes to the project.\n\tOwner = \"owner\",\n\t// User can view and edit the project.\n\tCollaborator = \"collaborator\",\n\t// User can view and edit the project content.\n\tContentCollaborator = \"contentCollaborator\",\n\t// User can only view the project.\n\tViewer = \"viewer\",\n\t// User can only view the prototype\n\tPrototypeViewer = \"prototypeViewer\",\n}\n\nexport function labelForRole(role: Role) {\n\tswitch (role) {\n\t\tcase Role.Owner:\n\t\t\treturn \"Project owner\"\n\t\tcase Role.Collaborator:\n\t\t\treturn \"Can edit\"\n\t\tcase Role.Viewer:\n\t\t\treturn \"Can view\"\n\t\tcase Role.PrototypeViewer:\n\t\t\treturn \"Can view prototype\"\n\t\tcase Role.ContentCollaborator:\n\t\t\treturn \"Can edit content\"\n\t\tdefault:\n\t\t\tassertNever(role)\n\t}\n}\n\nexport const enum ACLPermission {\n\tOn = \"on\",\n\tOff = \"off\",\n}\n\nexport function togglePermission(permission: ACLPermission) {\n\tswitch (permission) {\n\t\tcase ACLPermission.On:\n\t\t\treturn ACLPermission.Off\n\t\tcase ACLPermission.Off:\n\t\t\treturn ACLPermission.On\n\t\tdefault:\n\t\t\tassertNever(permission)\n\t}\n}\n\nexport interface ACLPermissions {\n\tcanDesign: ACLPermission\n\tcanEditContent: ACLPermission\n\tcanPublish: ACLPermission\n}\n\n/**\n * Checks if all ACL permissions are turned off.\n */\nexport function isViewerPermissions(permissions: ACLPermissions): boolean {\n\treturn Object.values(permissions).every(permission => permission === ACLPermission.Off)\n}\n\n/**\n * Checks if permissions match content collaborator pattern (only content editing enabled).\n */\nexport function isContentCollaboratorPermissions(permissions: ACLPermissions): boolean {\n\treturn (\n\t\tpermissions.canDesign === ACLPermission.Off &&\n\t\tpermissions.canEditContent === ACLPermission.On &&\n\t\tpermissions.canPublish === ACLPermission.Off\n\t)\n}\n\n/**\n * Checks if the role is a content-editing role.\n */\nexport function isContentRole(role: Role): boolean {\n\treturn role === Role.ContentCollaborator\n}\n\n/**\n * Checks if the role can edit content.\n */\n// TODO: this should also take into account the permissions set as the user can have noPermissions\n// and still have \"Collaborator\" role\nexport function canEditContent(role: Role): boolean {\n\treturn role === Role.Owner || role === Role.Collaborator || role === Role.ContentCollaborator\n}\n\nexport type ACLPermissionKey = keyof ACLPermissions\n\nexport const assignablePermissions: ACLPermissionKey[] = [\"canDesign\", \"canEditContent\", \"canPublish\"]\n\nexport const fullPermissions: ACLPermissions = {\n\tcanDesign: ACLPermission.On,\n\tcanEditContent: ACLPermission.On,\n\tcanPublish: ACLPermission.On,\n}\n\nexport const contentCollaboratorPermissions: ACLPermissions = {\n\tcanDesign: ACLPermission.Off,\n\tcanEditContent: ACLPermission.On,\n\tcanPublish: ACLPermission.Off,\n}\n\nexport const noPermissions: ACLPermissions = {\n\tcanDesign: ACLPermission.Off,\n\tcanEditContent: ACLPermission.Off,\n\tcanPublish: ACLPermission.Off,\n}\n\nexport function detailsForPermission(permission: ACLPermissionKey) {\n\tswitch (permission) {\n\t\tcase \"canDesign\":\n\t\t\treturn {\n\t\t\t\tlabel: \"Design\",\n\t\t\t\tdescription: \"Canvas\",\n\t\t\t}\n\t\tcase \"canEditContent\":\n\t\t\treturn {\n\t\t\t\tlabel: \"Content\",\n\t\t\t\tdescription: \"CMS, On-Page\",\n\t\t\t}\n\t\tcase \"canPublish\":\n\t\t\treturn {\n\t\t\t\tlabel: \"Deploy\",\n\t\t\t\tdescription: \"Publish\",\n\t\t\t}\n\t\tdefault:\n\t\t\tassertNever(permission)\n\t}\n}\n\nexport function labelForPermissions(permissions: ACLPermissions | null, role: Role): string {\n\tif (role === Role.Owner) return \"Owner\"\n\tif (role === Role.Viewer) return \"View Only\"\n\n\tconst entries = Object.entries(permissions ?? {}) as [ACLPermissionKey, ACLPermission][]\n\tconst enabledPermissions = entries.filter(([_, value]) => value === ACLPermission.On).map(([key, _]) => key)\n\n\tif (enabledPermissions.length === 0) return \"View Only\"\n\tif (assignablePermissions.every(a => enabledPermissions.includes(a))) return \"Full Access\"\n\tif (enabledPermissions.length === 1) {\n\t\tconst singlePermission = enabledPermissions[0]\n\t\tif (singlePermission === \"canEditContent\" && experiments.isOn(\"contentEditor\")) return \"Content Editor\"\n\t\tif (singlePermission) return detailsForPermission(singlePermission).label\n\t}\n\n\tconst permissionLabels = enabledPermissions.map(permission => detailsForPermission(permission).label)\n\treturn permissionLabels.join(\", \")\n}\n\nexport function roleForACLPermissions(permissions: ACLPermissions, contentEditorExperimentEnabled: boolean): Role {\n\tif (isViewerPermissions(permissions)) return Role.Viewer\n\tif (contentEditorExperimentEnabled && isContentCollaboratorPermissions(permissions)) {\n\t\treturn Role.ContentCollaborator\n\t}\n\treturn Role.Collaborator\n}\n", "// Colors used in multiplayer.\n// Colors should be defined in pairs of light mode, dark mode.\n// Note that adding a color will affect all existing projects.\nconst colors = [\n\t// Light   // Dark\n\t[\"#0099FF\", \"#0099FF\"],\n\t[\"#0066FF\", \"#0066FF\"],\n\t[\"#0000FF\", \"#3838FF\"],\n\t[\"#3300FF\", \"#5024FF\"],\n\t[\"#6600FF\", \"#7B24FF\"],\n\t[\"#9900FF\", \"#9F0FFF\"],\n\t[\"#EE00FF\", \"#EF0FFF\"],\n\t[\"#FF0088\", \"#FF1A94\"],\n\t[\"#FF0022\", \"#FF1434\"],\n\t[\"#FF4400\", \"#FF571A\"],\n\t[\"#FF7700\", \"#FF851A\"],\n\t[\"#FFBB00\", \"#FFBB00\"],\n\t[\"#FFD500\", \"#FFD500\"],\n\t[\"#00DD66\", \"#12ED6A\"],\n\t[\"#22DDDD\", \"#22DDDD\"],\n\t[\"#00CCFF\", \"#00CCFF\"],\n] as const\n\nexport function getMultiplayerColor(color: number, isDarkMode: boolean): string {\n\tconst pair = colors[color % colors.length] ?? colors[0]\n\treturn pair[isDarkMode ? 1 : 0]\n}\n", "import { Avatar, FixedPositionTooltip, Stack, Text, useTooltip } from \"@framerjs/fresco\"\nimport { colors } from \"@framerjs/fresco/tokens\"\nimport { cx } from \"@linaria/core\"\nimport React, { useMemo } from \"react\"\nimport { ACLAvatar, TooltipTrigger } from \"./ACLAvatar.tsx\"\nimport * as classes from \"./ACLAvatarList.styles.ts\"\nimport type { ACLEntry } from \"./ACLEntry.ts\"\n\ninterface Props {\n\tentries: (ACLEntry & { inactive?: boolean })[]\n\tuserEntry?: ACLEntry | null\n\t/* Show a UI that's irrelevant to the user status: visible avatars are active, the more-user avatar is inactive (grey), tooltips are inactive and only show the name */\n\tignoreStatus?: boolean\n\tisDarkMode: boolean\n\tmaxAvatars?: number\n\tmaxOtherNames?: number\n\tavatarClassName?: string\n\ttooltipClassName?: string\n\tlistClassName?: string\n\tshadow?: string\n\t/** Override background color for the overflow count avatar */\n\tcountColor?: string\n\tsize?: \"small\" | \"regular\"\n\t/** When false, individual avatar tooltips are suppressed (e.g. when an external popover handles hover display) */\n\twithTooltips?: boolean\n}\n\nexport const ACLAvatarList = React.memo(function AvatarList({\n\tentries,\n\tuserEntry,\n\tignoreStatus = false,\n\tisDarkMode,\n\tmaxAvatars = 5,\n\tmaxOtherNames = 5,\n\tavatarClassName,\n\tlistClassName,\n\tshadow,\n\tcountColor,\n\tsize,\n\twithTooltips = true,\n}: Props) {\n\tconst ref = React.useRef<HTMLDivElement>(null)\n\n\tconst [displayedEntries, hiddenEntries] = useMemo(() => {\n\t\t// We never want to show only 1 hidden user, so we ensure we truncate at least 2 users.\n\t\tconst _displayedEntries = entries.length > maxAvatars ? entries.slice(0, maxAvatars - 1) : entries\n\t\tconst _hiddenEntries = entries.length > maxAvatars ? entries.slice(maxAvatars - 1) : []\n\t\treturn [_displayedEntries, _hiddenEntries]\n\t}, [entries, maxAvatars])\n\n\tconst displayedAvatars = useMemo(() => displayedEntries.reverse(), [displayedEntries])\n\n\tconst numberOfHiddenUsers = hiddenEntries.length\n\tconst showMoreUsers = numberOfHiddenUsers > 0\n\tconst moreUserNames = useMemo(\n\t\t() =>\n\t\t\thiddenEntries\n\t\t\t\t.reverse()\n\t\t\t\t.slice(0, maxOtherNames)\n\t\t\t\t.map(entry => entry.user.name),\n\t\t[hiddenEntries, maxOtherNames],\n\t)\n\tconst moreUserCount = numberOfHiddenUsers - moreUserNames.length\n\n\tconst isFirstHiddenUserInactive = hiddenEntries[0]?.inactive\n\tconst { triggerProps, tooltipProps } = useTooltip({\n\t\ttriggerRef: ref,\n\t\tdisabled: !withTooltips,\n\t\ttint: isFirstHiddenUserInactive || ignoreStatus ? colors.tooltipBackground : undefined,\n\t})\n\n\t// Masking handled in CSS via &:not(:last-child)\n\n\treturn (\n\t\t<div className={cx(classes.list, size === \"small\" && classes.small, listClassName)}>\n\t\t\t{showMoreUsers && (\n\t\t\t\t<>\n\t\t\t\t\t<TooltipTrigger ref={ref} {...triggerProps} className={classes.avatar}>\n\t\t\t\t\t\t<Avatar\n\t\t\t\t\t\t\tinactive={!countColor && (ignoreStatus || isFirstHiddenUserInactive)}\n\t\t\t\t\t\t\tcolor={countColor}\n\t\t\t\t\t\t\ttext={numberOfHiddenUsers}\n\t\t\t\t\t\t\ttextCustomStyles={countColor ? classes.countText : undefined}\n\t\t\t\t\t\t\tavatarCustomStyles={cx(size === \"small\" && classes.smallAvatar, avatarClassName)}\n\t\t\t\t\t\t\tshadow={shadow}\n\t\t\t\t\t\t\tsize={size}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</TooltipTrigger>\n\t\t\t\t\t<FixedPositionTooltip {...tooltipProps}>\n\t\t\t\t\t\t<Stack gap={10} padding=\"5px 0\">\n\t\t\t\t\t\t\t{moreUserNames.map((name, i) => (\n\t\t\t\t\t\t\t\t<Text key={i} className={classes.tooltipName} size={12}>\n\t\t\t\t\t\t\t\t\t{name}\n\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t\t{moreUserCount > 0 && (\n\t\t\t\t\t\t\t\t<Text className={classes.tooltipLabel} size={11}>\n\t\t\t\t\t\t\t\t\tand {moreUserCount} {moreUserCount === 1 ? \"other\" : \"others\"}\n\t\t\t\t\t\t\t\t</Text>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</Stack>\n\t\t\t\t\t</FixedPositionTooltip>\n\t\t\t\t</>\n\t\t\t)}\n\t\t\t{displayedAvatars.map(entry => (\n\t\t\t\t<ACLAvatar\n\t\t\t\t\tkey={entry.user.id}\n\t\t\t\t\tentry={entry}\n\t\t\t\t\tinactive={!ignoreStatus && entry.inactive}\n\t\t\t\t\twithTooltip={withTooltips}\n\t\t\t\t\tcontainerClassName={classes.avatar}\n\t\t\t\t\tavatarClassName={cx(size === \"small\" && classes.smallAvatar, avatarClassName)}\n\t\t\t\t\tisDarkMode={isDarkMode}\n\t\t\t\t\tshadow={shadow}\n\t\t\t\t\tsize={size}\n\t\t\t\t\tignoreStatus={ignoreStatus}\n\t\t\t\t/>\n\t\t\t))}\n\t\t\t{userEntry && (\n\t\t\t\t<ACLAvatar\n\t\t\t\t\tentry={userEntry}\n\t\t\t\t\twithTooltip={withTooltips}\n\t\t\t\t\tcontainerClassName={classes.avatar}\n\t\t\t\t\tavatarClassName={cx(size === \"small\" && classes.smallAvatar, avatarClassName)}\n\t\t\t\t\tisDarkMode={isDarkMode}\n\t\t\t\t\tshadow={shadow}\n\t\t\t\t\tsize={size}\n\t\t\t\t\tignoreStatus={ignoreStatus}\n\t\t\t\t/>\n\t\t\t)}\n\t\t</div>\n\t)\n})\n", "import \"ACLAvatarList.styles_1qhh5fi.wyw.css\"; export const list = \"list_l1l8om57\";\nexport const small = \"small_sv36qp8\";\nexport const tooltipName = \"tooltipName_t1aewutb\";\nexport const tooltipLabel = \"tooltipLabel_tfydinf\";\nexport const avatar = \"avatar_a16903hn\";\nexport const countText = \"countText_c1m9oj4r\";\nexport const smallAvatar = \"smallAvatar_s18jzmm1\";", "import type { User } from \"./User.ts\"\n\nexport enum HostnameType {\n\t/** A \"stable\" hostname we generate when a project is published the first time, like `happy-llama-1234.framer.app`. */\n\tDefault = \"default\",\n\n\t/** For specific deployments, like `happy-llama-1234-be347d8a.framer.app` */\n\tVersion = \"version\",\n\n\t/** Configured by users, like `amazon.framer.app` or `mycustomdomain.com` */\n\tCustom = \"custom\",\n\n\t/** For branch deployments, like `happy-llama-1234--be347d8ab.framer.app` or `happy-llama-1234--new-pricing-be347d8ab.framer.app` */\n\tBranch = \"branch\",\n}\n\nexport enum HostnameStatus {\n\t/** Hostname is active and in use, cannot be re-used for another deployment */\n\tActive = \"active\",\n\n\t/**\n\t * Hostname DNS settings haven't been validated yet.\n\t * Only applicable for custom hostnames.\n\t */\n\tInvalidDNS = \"invalid_dns\",\n}\n\n/**\n * Used to identify hostname \"sub types\", i.e. variations of a hostname within their \"main type\" (`hostnameType`).\n * For example, some custom hostnames can be \"free\" (but not all custom hostnames are \"free\").\n */\nexport enum HostnameVariant {\n\t/** Regular custom hostname */\n\tDefault = \"default\",\n\n\t/**\n\t * Redirect hostnames are a special type of custom hostname\n\t * that don't point to a deployment, but to another hostname.\n\t */\n\tRedirect = \"redirect\",\n\n\t/**\n\t * Free hostnames are a special type of custom hostname offered\n\t * by Framer, so users can use a custom domain without buying/configuring one.\n\t */\n\tFree = \"free\",\n}\n\ninterface BaseHostname {\n\tprojectId: string\n\tdeploymentId: string\n\ttype: HostnameType\n\thostname: string\n\tisPublished: boolean\n\tcreatedAt: string\n\tupdatedAt: string\n\tisPrimary?: boolean\n\tstatus?: HostnameStatus\n\tredirect?: string\n\tbranchId?: string\n}\n\nexport interface DefaultHostname extends BaseHostname {\n\ttype: HostnameType.Default\n\tisPrimary: boolean\n\tstatus: HostnameStatus\n}\n\nexport interface CustomHostname extends BaseHostname {\n\ttype: HostnameType.Custom\n\tisPrimary: boolean\n\tstatus: HostnameStatus\n}\n\nexport interface VersionHostname extends Omit<BaseHostname, \"status\" | \"isPrimary\" | \"redirect\"> {\n\ttype: HostnameType.Version\n}\n\nexport interface BranchHostname extends Omit<BaseHostname, \"isPrimary\" | \"redirect\"> {\n\ttype: HostnameType.Branch\n\tbranchId: string\n}\n\nexport type Hostname = DefaultHostname | CustomHostname | VersionHostname | BranchHostname\n\nexport enum DeploymentStatus {\n\t/** Publishing is in progress, and the SPA is not available yet. */\n\tPending = \"pending\",\n\n\t/** Publishing the SPA failed due to an infrastructure error (e.g. upload failure). */\n\tSpaFailed = \"spa-failed\",\n\n\t/** Publish the SPA succeeded, SSG is in progress. */\n\tSpaReady = \"spa-ready\",\n\n\t/** SSG failed due to an infrastructure error (e.g. DB failure). */\n\tSsgPipelineFailed = \"ssg-pipeline-failed\",\n\n\t/**\n\t * SSG succeeded, but some pages have errors.\n\t *\n\t * The value of the enum member is different for backwards compatibility.\n\t */\n\tSsgReadyWithErrors = \"ssg-user-code-failed\",\n\n\t/**\n\t * SSG succeeded, but some pages have warnings.\n\t *\n\t * Introduced in deployments with routes version 8.\n\t */\n\tSsgReadyWithWarnings = \"ssg-ready-with-warnings\",\n\n\t/**\n\t * SSG succeeded.\n\t *\n\t * Before routes version 8, there may or may not have been warnings, check the Deployment `messages`.\n\t */\n\tSsgReady = \"ssg-ready\",\n}\n\nexport enum SearchIndexStatus {\n\t/** Search index hasn't been generated yet. */\n\tUnavailable = \"unavailable\",\n\n\t/** Search index is available. */\n\tReady = \"ready\",\n\n\t/** Search index generation failed. */\n\tFailed = \"failed\",\n}\n\nexport type DeploymentCrdtFrontier = [client: number, seq: number][]\n\n/** Must be serializable to JSON. */\nexport type DeploymentTreeState = RegularDeploymentTreeState | PatchedDeploymentTreeState\n\nexport interface RegularDeploymentTreeState {\n\ttreeVersion: number\n\t/** Only present when publishing CRDT deployments. */\n\tfrontier?: DeploymentCrdtFrontier\n\tbaseDeploymentId?: never\n\tpatchedSnapshotId?: never\n}\n\nexport interface PatchedDeploymentTreeState {\n\ttreeVersion?: never\n\tfrontier: DeploymentCrdtFrontier\n\tbaseDeploymentId: string\n\tpatchedSnapshotId: string\n}\n\ninterface CommonDeployment {\n\tid: string\n\tstatus: DeploymentStatus\n\tdeployedBy: User\n\tchangeSummary?: string\n\tcreatedAt: string\n\tupdatedAt: string\n\tversionHostname?: string\n\ttreeVersion?: number\n\ttreeState?: DeploymentTreeState\n\tsearchIndexUrl?: string\n\tsearchIndexStatus?: SearchIndexStatus\n\tabTestIds?: string[]\n}\n\ninterface WithAggregatedData {\n\t/** If a deployment has a successful SSG build but had messages in the process (warnings or errors) */\n\thasWarnings: boolean\n}\n\ninterface WithServerErrorsAndMessages {\n\t/**\n\t * @deprecated Messages are now being fetched using a dedicated endpoint, see `getDeploymentIssues`. This field is\n\t * now only being used to see if a pre-v8 deployment in the \"ssg-ready\" state has any warnings.\n\t */\n\tmessages?: unknown[]\n}\n\nexport type BaseDeployment = CommonDeployment & WithAggregatedData\n/**\n * Data representation for the deployment that is received from the server.\n */\ntype ServerBaseDeployment = CommonDeployment & WithServerErrorsAndMessages\n\ninterface WithProjectId {\n\tprojectId: string\n}\n\ninterface WithVersionHostname {\n\tversionHostname: string\n}\n\nexport type Deployment = BaseDeployment & WithProjectId\nexport type ServerDeployment = ServerBaseDeployment & WithProjectId\n\nexport type VersionDeployment = Deployment & WithVersionHostname\nexport type ServerVersionDeployment = ServerDeployment & WithVersionHostname\n\nexport enum DeploymentStrategy {\n\tAlwaysLatest = \"always-latest\",\n\tManual = \"manual\",\n}\n\nexport enum ProtectedStagingValue {\n\tOn = \"on\",\n\tOff = \"off\",\n}\n\nexport type EnrichedHostnameWithDeployment = Omit<Hostname, \"deploymentId\"> & {\n\tprojectId: string\n\tdeployment: BaseDeployment\n}\n\nexport type BranchHostnameWithDeployment = BranchHostname & {\n\tdeployment: BaseDeployment\n}\n\nexport function hasOptimizationIssue(deploymentStatus: DeploymentStatus): boolean {\n\treturn [DeploymentStatus.SsgPipelineFailed, DeploymentStatus.SsgReadyWithErrors].includes(deploymentStatus)\n}\n\n// A helper type that allows us to know which client deployment type corresponds to a server deployment type\n// It does a check with the subtypes that are more specific than the base one, and then the base type is the last in the check\ntype CorrespondingClientDeployment<T extends ServerBaseDeployment> = T extends ServerVersionDeployment\n\t? VersionDeployment\n\t: T extends ServerDeployment\n\t\t? Deployment\n\t\t: T extends ServerBaseDeployment // The base type\n\t\t\t? BaseDeployment\n\t\t\t: never\n\n/**\n * Maps a ServerDeployment to a ClientDeployment.\n *\n * This is used to map the data received from the server to the data that is\n * used in the client.\n */\nexport function mapDeployment<T extends ServerBaseDeployment>(deployment: T): CorrespondingClientDeployment<T> {\n\tconst hasWarnings =\n\t\t// New deployments have a dedicated status for this case.\n\t\tdeployment.status === DeploymentStatus.SsgReadyWithWarnings ||\n\t\t// Search index failing to generate is also a warning.\n\t\tdeployment.searchIndexStatus === SearchIndexStatus.Failed ||\n\t\t// Old deployments didn't, so we need to check if there are any messages.\n\t\tBoolean(deployment.status === DeploymentStatus.SsgReady && deployment.messages?.length)\n\n\treturn {\n\t\t...deployment,\n\t\thasWarnings,\n\t} as unknown as CorrespondingClientDeployment<T>\n}\n", "import React, { Suspense } from \"react\"\n\ninterface Props {\n\tchildren: React.ReactNode\n}\n\nfunction ModalLoader() {\n\tconst [isVisible, setIsVisible] = React.useState(false)\n\n\tReact.useEffect(() => {\n\t\tconst timer = setTimeout(() => setIsVisible(true), 200)\n\n\t\treturn () => {\n\t\t\tclearTimeout(timer)\n\t\t}\n\t}, [])\n\n\tif (!isVisible) return null\n\n\treturn (\n\t\t<div\n\t\t\tstyle={{\n\t\t\t\tposition: \"fixed\",\n\t\t\t\twidth: \"100vw\",\n\t\t\t\theight: \"100vh\",\n\t\t\t\tleft: 0,\n\t\t\t\ttop: 0,\n\t\t\t\tcursor: \"wait\",\n\t\t\t\tzIndex: 5000,\n\t\t\t}}\n\t\t/>\n\t)\n}\n\nexport function LazyModal({ children }: Props) {\n\tif (!children) return null\n\treturn <Suspense fallback={<ModalLoader />}>{children}</Suspense>\n}\n", "import \"ProjectBarMenu.styles_8gsa7a.wyw.css\"; export const projectBarMenu = \"projectBarMenu_pvu3uy5\";", "import type { ExperimentName, ProjectSettingsFeatureFlags, ProjectSettingsResourceLimits } from \"@framerjs/app-config\"\nimport type { ACLPermissions, AccessRequestACLEntry, InviteACLEntry, Role, UserACLEntry } from \"./ACLEntry.ts\"\nimport type { Collection } from \"./Collection.ts\"\nimport type { ProjectLicense } from \"./ProjectLicense.ts\"\nimport type { TeamMemberRole } from \"./Space.ts\"\nimport type { TeamLicenseType } from \"./TeamLicense.ts\"\nimport type { User } from \"./User.ts\"\n\nexport const enum ProjectPublicAccess {\n\t// Link sharing is not enabled\n\tNone = \"none\",\n\t// Anyone with the link can view the project\n\tView = \"view\",\n}\n\nexport type ProjectSpace =\n\t| {\n\t\t\tid: string\n\t\t\ticon: string | null\n\t\t\tavatar: string | null\n\t\t\townerId: string\n\t\t\tscope: \"user\"\n\t\t\t// Avoid referencing this field in case it's removed.\n\t\t\tdisplayName: null\n\t  }\n\t| {\n\t\t\tid: string\n\t\t\tdisplayName: string\n\t\t\ticon: string | null\n\t\t\tavatar: string | null\n\t\t\townerId: string\n\t\t\tscope: \"organization\"\n\t  }\n\nexport interface ProjectSettings {\n\tcannotInviteEditorsReason: CannotInviteEditorsReason | null\n\tallowedDomains: string[]\n\tautoJoinDefaultRole: TeamMemberRole\n\n\tfeatureFlags: ProjectSettingsFeatureFlags\n\tresourceLimits: ProjectSettingsResourceLimits\n}\n\nexport enum CannotInviteEditorsReason {\n\tCancelled = \"cancelled\",\n\tLimitReached = \"limit-reached\",\n\tSitesPersonalPlan = \"sites-personal-plan\",\n}\n\nexport enum ProjectType {\n\tDefault = \"default\",\n\t/** @deprecated Templates can no longer be created */\n\tTemplate = \"template\",\n}\n\nexport enum TeamSubscriptionSyncAction {\n\t// Billing v2 actions\n\tReactivate = \"reactivate\",\n\tSync = \"sync\",\n\tChargeableSync = \"chargeableSync\",\n\t// Billing v3 actions\n\tCreateTeamSubscription = \"createTeamSubscription\",\n\tSyncQuantity = \"syncQuantity\",\n\tSyncTeamLicense = \"syncTeamLicense\",\n}\n\nexport type TeamExperiments = {\n\t[name in ExperimentName]?: string\n}\n\ninterface AdvancedAnalyticsUsage {\n\tcurrentMonth: number\n\tpreviousMonth: number\n}\n\ninterface BandwidthUsage {\n\tcurrentMonth: number\n\tpreviousMonth: number\n\ttwoMonthsAgo: number\n}\n\nexport interface AiUsage {\n\tcurrentMonth: number\n\tcurrentDay: number\n}\n\nexport interface Usage {\n\tadvancedAnalytics: AdvancedAnalyticsUsage | null\n\tbandwidth: BandwidthUsage | null\n\taiCredits: AiUsage | null\n}\n\nexport interface Team {\n\tid: string\n\tdisplayName: string\n\tavatar: string | null\n}\n\nexport interface Project extends ProjectBase {\n\turl: string\n\taccessToken?: string\n\tteamExperiments: TeamExperiments | null\n\t// Team license type is expected to be set when creating or fetching a\n\t// single project, and is expected NOT to be set when listing projects,\n\t// e.g., on the dashboard. The dashboard currently uses ProjectBase, so we\n\t// have this covered.\n\tteamLicenseType: TeamLicenseType\n\treleaseChannel: string | null\n\t// XXX: settings is actually null on the dashboard\n\tsettings: ProjectSettings\n\t// NOTE: usage is only available when fetching individual projects, not when listing projects on the dashboard\n\tusage: Usage\n\t// NOTE: team is only available when fetching individual projects, not when listing projects on the dashboard\n\tteam: Team | null\n\n\tuserPermissions: ACLPermissions | null\n}\n\n/**\n * Per-project feature flags.\n *\n * The source of truth and validation for these flags lives in the Projects Service.\n * We've intentionally removed legacy project flags from here, as they are not supported anymore.\n */\nexport enum ProjectCanvasFeature {\n\tKit = \"kit\",\n\tSites = \"sites\",\n\tSkipInterstitial = \"skipInterstitial\",\n\tCanvasPages = \"canvasPages\",\n}\n\nexport enum TeamLicenseVersion {\n\tV2 = 2,\n\tV3 = 3,\n}\n\nexport interface ProjectBase {\n\tid: string\n\tarchived: boolean\n\tarchivedAt: string | null\n\tarchivedBy: User | null\n\tcollection: Collection | null\n\tcreatedAt: string\n\tduplicatedFromId: string | null\n\tlastOpenedAt: string | null\n\towner: User\n\tpublicAccess: ProjectPublicAccess\n\tspace: ProjectSpace\n\ttitle: string | null\n\tupdatedAt: string\n\tuserRole: Role | null\n\tcanvasFeatures: Partial<Record<ProjectCanvasFeature, boolean>>\n\ttype: ProjectType\n\tteamCurrentEditors: number\n\tlicense: ProjectLicense\n\tteamLicenseVersion: TeamLicenseVersion | null\n\t// If this is not null, it means that the subscription is not in order. In that case project edition will be locked and the user has to reactivate it\n\tteamSyncAction: TeamSubscriptionSyncAction | null\n\tpartnerLink: string | null\n\tremixId?: string\n}\n\nexport function isTeamTemplate(project: ProjectBase) {\n\treturn project.type === ProjectType.Template\n}\n\n// NOTE: This type is copied from `vekter/src/socket/types.ts` because we can't import it here.\ninterface UserStateData {\n\t// Cursor position.\n\tx?: number\n\ty?: number\n\t// Scope node that the user is viewing.\n\tpageId?: string\n\t// Node that is being previewed (for cross-device sync).\n\tpreviewNode?: { type: \"node\" | \"component\"; id: string }\n\t// Any chat text to show for the user.\n\tchat?: string\n\t// Canvas scroll and zoom.\n\tscroll?: { x: number; y: number }\n\tzoom?: number\n}\n\nexport interface LoadingProjectState {\n\t// The ACL entries of all users that have access to the project.\n\tacl: (InviteACLEntry | UserACLEntry)[]\n\t// Lookup table for ACL entries.\n\taclById: { [id: string]: InviteACLEntry | UserACLEntry | undefined }\n\t// The ACL entries of all users that have requested access to the project. This information is\n\t// only available to the project collaborators who can grant access.\n\taccessRequests: AccessRequestACLEntry[]\n\t// The ids of all users currently viewing the project. Only changes\n\t// when someone joins/leaves and can be used as a hook dependency.\n\tactiveIds: Set<string>\n\t// The project id\n\tprojectId: string\n\t// The latest project metadata.\n\tproject?: Project\n\t// State of the users that are currently viewing the project.\n\tuserStates: {\n\t\t[id: string]: UserStateData\n\t}\n}\n\nexport interface ProjectState extends LoadingProjectState {\n\t// The latest project metadata, guaranteed to be loaded\n\tproject: Project\n}\n", "import { ProjectLicensePeriod } from \"./ProjectLicense.ts\"\n\nexport enum AddOnLicenseType {\n\tLocale = \"locale\",\n\tAdvancedAnalytics = \"advancedAnalytics\",\n\tCustomProxySetup = \"customProxySetup\",\n\tBandwidth = \"bandwidth\",\n\tPages = \"pages\",\n\tCmsCollections = \"cmsCollections\",\n\tCmsItems = \"cmsItems\",\n}\n\nconst ADD_ON_NAME_MAP: Record<AddOnLicenseType, string> = {\n\t[AddOnLicenseType.Locale]: \"Locale\",\n\t[AddOnLicenseType.AdvancedAnalytics]: \"Convert\",\n\t[AddOnLicenseType.CustomProxySetup]: \"Advanced Hosting\",\n\t[AddOnLicenseType.Bandwidth]: \"Bandwidth\",\n\t[AddOnLicenseType.Pages]: \"Pages\",\n\t[AddOnLicenseType.CmsCollections]: \"CMS Collections\",\n\t[AddOnLicenseType.CmsItems]: \"CMS Items\",\n}\n\nexport type UpsellableAddonLicenseType = Extract<\n\tAddOnLicenseType,\n\tAddOnLicenseType.AdvancedAnalytics | AddOnLicenseType.CustomProxySetup\n>\n\nexport function isUpsellableAddonLicenseType(type: AddOnLicenseType): type is UpsellableAddonLicenseType {\n\treturn type === AddOnLicenseType.AdvancedAnalytics || type === AddOnLicenseType.CustomProxySetup\n}\n\nexport const getAddOnLicenseTypeName = (addOnLicenseType: AddOnLicenseType) => {\n\treturn ADD_ON_NAME_MAP[addOnLicenseType]\n}\n\nexport function isValidAddOnLicense(value: string | null | undefined): value is AddOnLicenseType {\n\treturn !value ? false : value in ADD_ON_NAME_MAP\n}\n\nexport enum TeamAddOnPlan {\n\tAiCreditsMonthly = \"ai_credits_monthly\",\n\tAiCreditsYearly = \"ai_credits_yearly\",\n\tContentEditorsMonthly = \"content_editors_monthly\",\n\tContentEditorsYearly = \"content_editors_yearly\",\n}\n\nexport enum TeamAddOnLicenseType {\n\tAiCredits = \"aiCredits\",\n\tContentEditors = \"contentEditors\",\n}\n\nconst TEAM_ADD_ON_NAME_MAP: Record<TeamAddOnLicenseType, string> = {\n\t[TeamAddOnLicenseType.AiCredits]: \"Credits Add-On\",\n\t[TeamAddOnLicenseType.ContentEditors]: \"Content Editors\",\n}\n\nexport function getTeamAddOnLicenseTypeName(licenseType: TeamAddOnLicenseType): string {\n\treturn TEAM_ADD_ON_NAME_MAP[licenseType]\n}\n\nexport function isValidTeamAddOnLicense(value: string | null | undefined): value is TeamAddOnLicenseType {\n\treturn !value ? false : value in TEAM_ADD_ON_NAME_MAP\n}\n\nexport function getContentEditorAddOnPlan(period: ProjectLicensePeriod): TeamAddOnPlan {\n\treturn period === ProjectLicensePeriod.Month\n\t\t? TeamAddOnPlan.ContentEditorsMonthly\n\t\t: TeamAddOnPlan.ContentEditorsYearly\n}\n", "export const dashboardPath = \"/projects/\"\nexport const dashboardRecentPath = `${dashboardPath}folder/recent`\nexport const dashboardDraftsPath = `${dashboardPath}folder/drafts`\nexport const dashboardArchivedPath = `${dashboardPath}folder/archived`\nexport const domainsDashboardPath = \"/domains\"\n", "import { assertNever } from \"@framerjs/shared\"\nimport type { Collection } from \"./Collection.ts\"\n\nexport function getCollectionName(collection: Collection): string {\n\tif (collection.isCustom) {\n\t\treturn collection.displayName\n\t}\n\n\t// With the new the dashboard-redesign, we removed the templates menu item\n\t// and we now show it in the dropdown menu. However, we still need to keep\n\t// the collection.id for the templates page to work, so we can't remove it from\n\t// collections.\n\tconst { id } = collection\n\tswitch (id) {\n\t\tcase \"recent\":\n\t\tcase \"drafts\":\n\t\t\treturn \"All\"\n\t\tcase \"templates\":\n\t\t\treturn \"\"\n\t\tcase \"archived\":\n\t\t\treturn \"Archive\"\n\t\tcase \"personal\":\n\t\t\treturn \"Drafts\"\n\t\tdefault:\n\t\t\tassertNever(id)\n\t}\n}\n", "import { emoji } from \"@framerjs/fresco\"\nimport { assertNever } from \"@framerjs/shared\"\nimport type { ProjectBase } from \"./ProjectState.ts\"\nimport { isTeamTemplate } from \"./ProjectState.ts\"\nimport { getCollectionName } from \"./getCollectionName.ts\"\n\n/**\n * Determines the label for a project's location.\n * @param project The project to get the location information for.\n * @param currentUserId The current user's id.\n */\nexport function getProjectLocationLabel(project: ProjectBase, currentUserId: string): string {\n\tconst { owner, space, collection } = project\n\n\tswitch (space.scope) {\n\t\tcase \"organization\": {\n\t\t\tconst collectionName = isTeamTemplate(project)\n\t\t\t\t? \"Templates\"\n\t\t\t\t: (collection && getCollectionName(collection)) || \"All\"\n\t\t\tconst collectionNameWithoutEmoji = emoji.extract(collectionName)[1] || collectionName\n\t\t\treturn `${space.displayName} / ${collectionNameWithoutEmoji}`\n\t\t}\n\t\tcase \"user\":\n\t\t\tif (space.ownerId === currentUserId) {\n\t\t\t\treturn \"Drafts\"\n\t\t\t} else {\n\t\t\t\t// Other users' spaces are referred to by the user's name, and can only be found in \"Recent\".\n\t\t\t\treturn owner.name\n\t\t\t}\n\t\tdefault:\n\t\t\tassertNever(space)\n\t}\n}\n", "// Work around a \"feature\" in Safari under the Preferences > Tabs setting\n// where a new window with target=\"_blank\" created by window.open() will\n// open in a new window but when opened from a link it will use a new tab.\nexport function openNewTab(href: string, options: { referrer: boolean } = { referrer: true }) {\n\tconst link = document.createElement(\"a\")\n\tlink.href = href\n\tlink.rel = `${options.referrer ? \"\" : \" noreferrer\"}`\n\tlink.target = \"_blank\"\n\tdocument.body.appendChild(link)\n\tlink.click()\n\tlink.remove()\n}\n", "import { openNewTab } from \"./openNewTab.ts\"\n\nexport function downloadDesktopApp() {\n\topenNewTab(\"https://www.framer.com/downloads/\")\n}\n", "export const preventDefaultAndStopPropagation = (event: React.MouseEvent) => {\n\tevent.preventDefault()\n\tevent.stopPropagation()\n}\n", "import type { TeamLicenseFeatureFlags } from \"@framerjs/app-config\"\n\nexport enum TeamLicenseType {\n\tFreePlan = \"free\",\n\tTeamBasicPlan = \"teamAccount\", // This was originally called the TeamAccountPlan, as there was only one team plan. Now there are more, so we renamed it to TeamBasicPlan, however its value will stay \"teamAccount\" for backwards compatibility.\n\tTeamProPlan = \"teamPro\", // deprecated, we will encourage users to upgrade to TeamBasicPlan\n\tTeamBusinessPlan = \"teamBusiness\", // matched to the launch and scale site plans\n\tTeamEditorPlan = \"teamEditor\", // all v3 plans now have a team editor plan\n\tEnterprisePlan = \"enterprise\",\n}\n\nexport interface TeamEditors {\n\tcurrent: number\n\tlimit: number | null\n\tfullEditors?: number\n\tcontentEditors?: number\n}\n\nexport interface TeamLicense {\n\tid: string\n\texpirationDate: string | null\n\tfeatureFlags: TeamLicenseFeatureFlags\n\townerId: string\n\townerType: string\n\t/**\n\t * Not available when the space was fetched via the /users/me request.\n\t */\n\tteamEditors: TeamEditors | null\n\ttype: TeamLicenseType\n\tunlimitedEditors: boolean\n\tisTrial: boolean\n\ttrialExpirationDate: string | null\n\tsubscriptionIsActive: boolean\n\tversion: number\n\tresourceLimits: {\n\t\taiCredits: number\n\t\taiCreditsDaily: number | null\n\t}\n}\n\nconst TEAM_NAME_MAP: Record<TeamLicenseType, string> = {\n\t[TeamLicenseType.FreePlan]: \"Free\",\n\t[TeamLicenseType.TeamBasicPlan]: \"Personal\",\n\t[TeamLicenseType.TeamProPlan]: \"Pro\",\n\t[TeamLicenseType.TeamBusinessPlan]: \"Business\",\n\t[TeamLicenseType.TeamEditorPlan]: \"Paid\",\n\t[TeamLicenseType.EnterprisePlan]: \"Enterprise\",\n}\n\nexport function getTeamLicenseName(licenseType: TeamLicenseType): string {\n\treturn TEAM_NAME_MAP[licenseType]\n}\n\nexport function isValidTeamLicense(value: string | null | undefined): value is TeamLicenseType {\n\treturn !value ? false : value in TEAM_NAME_MAP\n}\n", "import { useMemo } from \"react\"\nimport type { InviteACLEntry, UserACLEntry } from \"./ACLEntry.ts\"\nimport { ACLEntryKind } from \"./ACLEntry.ts\"\n\nfunction chronologically(a: InviteACLEntry | UserACLEntry, b: InviteACLEntry | UserACLEntry): 0 | 1 | -1 {\n\tif (a.lastOpenedAt === b.lastOpenedAt) return 0\n\tif (a.lastOpenedAt === null) return 1\n\tif (b.lastOpenedAt === null) return -1\n\treturn a.lastOpenedAt < b.lastOpenedAt ? 1 : -1\n}\n\nexport function useSortedACL({\n\tacl,\n\tactiveIds,\n\tuserId,\n}: {\n\tacl: (InviteACLEntry | UserACLEntry)[]\n\tactiveIds: Set<string>\n\tuserId: string\n}): [UserACLEntry | null, UserACLEntry[], UserACLEntry[], InviteACLEntry[]] {\n\treturn useMemo(() => {\n\t\tconst activeUsers: UserACLEntry[] = []\n\t\tconst inactiveUsers: UserACLEntry[] = []\n\t\tconst invites: InviteACLEntry[] = []\n\t\tlet currentUser: UserACLEntry | null = null\n\n\t\tconst sortedAcl = Array.from(acl)\n\t\tsortedAcl.sort(chronologically)\n\n\t\tfor (const entry of acl) {\n\t\t\tif (entry.kind === ACLEntryKind.Invite) {\n\t\t\t\tinvites.push(entry)\n\t\t\t} else if (entry.user.id === userId) {\n\t\t\t\tcurrentUser = entry\n\t\t\t} else if (activeIds.has(entry.user.id)) {\n\t\t\t\tactiveUsers.push(entry)\n\t\t\t} else {\n\t\t\t\tinactiveUsers.push(entry)\n\t\t\t}\n\t\t}\n\n\t\treturn [currentUser, activeUsers, inactiveUsers, invites]\n\t}, [acl, activeIds, userId])\n}\n", "export interface FileData {\n\tcontent: string\n\toriginalFilename: string\n}\n\nexport function readFilePromise(file: File): Promise<FileData> {\n\treturn new Promise((resolve, reject) => {\n\t\tconst reader = new FileReader()\n\n\t\treader.onloadend = () => {\n\t\t\tif (reader.result) {\n\t\t\t\tresolve({\n\t\t\t\t\tcontent: reader.result as string,\n\t\t\t\t\toriginalFilename: file.name,\n\t\t\t\t})\n\t\t\t} else {\n\t\t\t\treject(reader.error)\n\t\t\t}\n\t\t}\n\t\treader.readAsDataURL(file)\n\t})\n}\n\nexport function readFiles(files: File[]) {\n\tconst promises = files.map(file => readFilePromise(file))\n\treturn Promise.all(promises)\n}\n", "import type { Asset, AssetFontProperties } from \"@framerjs/assets\"\n\nexport const ACCEPTED_FONT_EXTENSIONS = \".ttf,.otf,.woff,.woff2\"\n\nexport const REGULAR_FONT_WEIGHT = 400\n\n/**\n * Our custom font assets may clash with custom fonts uploaded via public packages by users.\n * With a strict check, we can ensure that the asset is trusted and native to Framer.\n * */\nexport function isTrustedFontAsset(asset: Asset): asset is Asset & { properties: AssetFontProperties } {\n\tif (!asset.mimeType.startsWith(\"font/\")) return false\n\tif (asset.properties?.kind !== \"font\") return false\n\tif (!asset.properties.font) return false\n\treturn \"fontFamily\" in asset.properties.font\n}\n", "/**\n * Matches any protocol, e.g. \"http://\", \"https://\", \"ftp://\", \"sftp://\", \"ftps://\", \"ws://\", \"wss://\", \"mailto://\"\n */\nconst protocolPrefixRegex = /^[a-z0-9-]+:\\/\\//i\n// Matches any protocol like file:, ftp:, mailto:, etc. (i.e., protocol:...), but NOT protocol://...\nconst blockedProtocolRegex = /^[a-z0-9-]+:(?!\\/\\/)/i\nconst allowedProtocols = new Set([\"http://\", \"https://\"])\n\n// Makes it more explicit that the protocol prefix is always a string with a \"://\" suffix\ntype ProtocolPrefix = `${string}://` | \"\"\nexport function extractProtocolPrefix(urlString: string): ProtocolPrefix {\n\tconst match = protocolPrefixRegex.exec(urlString)\n\t// No protocol prefix, return empty string\n\tif (!match) return \"\"\n\treturn match[0] as ProtocolPrefix\n}\n\nexport function hasInvalidProtocolPrefix(urlString: string): boolean {\n\t// Block protocols like \"javascript:danger\"\n\tif (blockedProtocolRegex.test(urlString)) return true\n\n\tconst protocolPrefix = extractProtocolPrefix(urlString)\n\t// No protocol prefix, it's valid\n\tif (!protocolPrefix) return false\n\treturn !allowedProtocols.has(protocolPrefix)\n}\n", "import { getLogger } from \"@framerjs/shared\"\nimport { extractProtocolPrefix } from \"./protocolValidation.ts\"\n\nconst logger = getLogger(\"extractDomainAndPathnameFromUrl\")\n\ninterface ParsedURL {\n\tprotocol: string\n\thostname: string\n\tport: string\n\tpathname: string\n}\n\nexport function parseURL(url: string): ParsedURL {\n\ttry {\n\t\t// urlObject requires a protocol, so we add \"https://\" if missing\n\t\tconst extractedProtocol = extractProtocolPrefix(url)\n\n\t\tconst urlObject = extractedProtocol ? new URL(url) : new URL(`https://${url}`)\n\t\treturn {\n\t\t\tprotocol: extractedProtocol,\n\t\t\thostname: urlObject.hostname,\n\t\t\tport: urlObject.port,\n\t\t\tpathname: urlObject.pathname,\n\t\t}\n\t} catch (error) {\n\t\tlogger.reportError(error, { url })\n\t\treturn {\n\t\t\tprotocol: \"\",\n\t\t\thostname: \"\",\n\t\t\tport: \"\",\n\t\t\tpathname: \"\",\n\t\t}\n\t}\n}\n", "/**\n * Work around Safari 14 IndexedDB open bug.\n *\n * Safari has a horrible bug where IDB requests can hang while the browser is starting up. https://bugs.webkit.org/show_bug.cgi?id=226547\n * The only solution is to keep nudging it until it's awake.\n */\nfunction idbReady() {\n    var isSafari = !navigator.userAgentData &&\n        /Safari\\//.test(navigator.userAgent) &&\n        !/Chrom(e|ium)\\//.test(navigator.userAgent);\n    // No point putting other browsers or older versions of Safari through this mess.\n    if (!isSafari || !indexedDB.databases)\n        return Promise.resolve();\n    var intervalId;\n    return new Promise(function (resolve) {\n        var tryIdb = function () { return indexedDB.databases().finally(resolve); };\n        intervalId = setInterval(tryIdb, 100);\n        tryIdb();\n    }).finally(function () { return clearInterval(intervalId); });\n}\n\nexport default idbReady;\n", "import safariFix from 'safari-14-idb-fix';\n\nfunction promisifyRequest(request) {\n    return new Promise((resolve, reject) => {\n        // @ts-ignore - file size hacks\n        request.oncomplete = request.onsuccess = () => resolve(request.result);\n        // @ts-ignore - file size hacks\n        request.onabort = request.onerror = () => reject(request.error);\n    });\n}\nfunction createDbWithStore(dbName, storeName, version) {\n    const request = indexedDB.open(dbName, version);\n    request.onupgradeneeded = () => request.result.createObjectStore(storeName);\n    return promisifyRequest(request);\n}\nfunction createStore(dbName, storeName) {\n    const dbp = safariFix()\n        .then(() => createDbWithStore(dbName, storeName))\n        .then((db) => {\n        if (db.objectStoreNames.contains(storeName)) {\n            return db;\n        }\n        // Sometimes, the DB gets into a weird state when the DB exists but the object store doesn\u2019t.\n        // (See eg https://github.com/jakearchibald/idb-keyval/issues/134.)\n        // We\u2019re handling this by upgrading the DB and creating the store.\n        db.close();\n        return createDbWithStore(dbName, storeName, db.version + 1);\n    });\n    return (txMode, callback) => dbp.then((db) => callback(db.transaction(storeName, txMode).objectStore(storeName)));\n}\nlet defaultGetStoreFunc;\nfunction defaultGetStore() {\n    if (!defaultGetStoreFunc) {\n        defaultGetStoreFunc = createStore('keyval-store', 'keyval');\n    }\n    return defaultGetStoreFunc;\n}\n/**\n * Get a value by its key.\n *\n * @param key\n * @param customStore Method to get a custom store. Use with caution (see the docs).\n */\nfunction get(key, customStore = defaultGetStore()) {\n    return customStore('readonly', (store) => promisifyRequest(store.get(key)));\n}\n/**\n * Set a value with a key.\n *\n * @param key\n * @param value\n * @param customStore Method to get a custom store. Use with caution (see the docs).\n */\nfunction set(key, value, customStore = defaultGetStore()) {\n    return customStore('readwrite', (store) => {\n        store.put(value, key);\n        return promisifyRequest(store.transaction);\n    });\n}\n/**\n * Set multiple values at once. This is faster than calling set() multiple times.\n * It's also atomic \u2013 if one of the pairs can't be added, none will be added.\n *\n * @param entries Array of entries, where each entry is an array of `[key, value]`.\n * @param customStore Method to get a custom store. Use with caution (see the docs).\n */\nfunction setMany(entries, customStore = defaultGetStore()) {\n    return customStore('readwrite', (store) => {\n        entries.forEach((entry) => store.put(entry[1], entry[0]));\n        return promisifyRequest(store.transaction);\n    });\n}\n/**\n * Get multiple values by their keys\n *\n * @param keys\n * @param customStore Method to get a custom store. Use with caution (see the docs).\n */\nfunction getMany(keys, customStore = defaultGetStore()) {\n    return customStore('readonly', (store) => Promise.all(keys.map((key) => promisifyRequest(store.get(key)))));\n}\n/**\n * Update a value. This lets you see the old value and update it as an atomic operation.\n *\n * @param key\n * @param updater A callback that takes the old value and returns a new value.\n * @param customStore Method to get a custom store. Use with caution (see the docs).\n */\nfunction update(key, updater, customStore = defaultGetStore()) {\n    return customStore('readwrite', (store) => \n    // Need to create the promise manually.\n    // If I try to chain promises, the transaction closes in browsers\n    // that use a promise polyfill (IE10/11).\n    new Promise((resolve, reject) => {\n        store.get(key).onsuccess = function () {\n            try {\n                store.put(updater(this.result), key);\n                resolve(promisifyRequest(store.transaction));\n            }\n            catch (err) {\n                reject(err);\n            }\n        };\n    }));\n}\n/**\n * Delete a particular key from the store.\n *\n * @param key\n * @param customStore Method to get a custom store. Use with caution (see the docs).\n */\nfunction del(key, customStore = defaultGetStore()) {\n    return customStore('readwrite', (store) => {\n        store.delete(key);\n        return promisifyRequest(store.transaction);\n    });\n}\n/**\n * Delete multiple keys at once.\n *\n * @param keys List of keys to delete.\n * @param customStore Method to get a custom store. Use with caution (see the docs).\n */\nfunction delMany(keys, customStore = defaultGetStore()) {\n    return customStore('readwrite', (store) => {\n        keys.forEach((key) => store.delete(key));\n        return promisifyRequest(store.transaction);\n    });\n}\n/**\n * Clear all values in the store.\n *\n * @param customStore Method to get a custom store. Use with caution (see the docs).\n */\nfunction clear(customStore = defaultGetStore()) {\n    return customStore('readwrite', (store) => {\n        store.clear();\n        return promisifyRequest(store.transaction);\n    });\n}\nfunction eachCursor(customStore, callback) {\n    return customStore('readonly', (store) => {\n        // This would be store.getAllKeys(), but it isn't supported by Edge or Safari.\n        // And openKeyCursor isn't supported by Safari.\n        store.openCursor().onsuccess = function () {\n            if (!this.result)\n                return;\n            callback(this.result);\n            this.result.continue();\n        };\n        return promisifyRequest(store.transaction);\n    });\n}\n/**\n * Get all keys in the store.\n *\n * @param customStore Method to get a custom store. Use with caution (see the docs).\n */\nfunction keys(customStore = defaultGetStore()) {\n    const items = [];\n    return eachCursor(customStore, (cursor) => items.push(cursor.key)).then(() => items);\n}\n/**\n * Get all values in the store.\n *\n * @param customStore Method to get a custom store. Use with caution (see the docs).\n */\nfunction values(customStore = defaultGetStore()) {\n    const items = [];\n    return eachCursor(customStore, (cursor) => items.push(cursor.value)).then(() => items);\n}\n/**\n * Get all entries in the store. Each entry is an array of `[key, value]`.\n *\n * @param customStore Method to get a custom store. Use with caution (see the docs).\n */\nfunction entries(customStore = defaultGetStore()) {\n    const items = [];\n    return eachCursor(customStore, (cursor) => items.push([cursor.key, cursor.value])).then(() => items);\n}\n\nexport { clear, createStore, del, delMany, entries, get, getMany, keys, promisifyRequest, set, setMany, update, values };\n", "/*\n * This file is duplicated from\n * https://github.com/framer/FramerAuthMiddleware/blob/9ab88feea31caab8bc0076eb7e6833238ac2e2e2/src/scopes.ts\n * Because installing the NPM dependency would bring a lot of useless backend dependencies.\n */\n\nexport class AccessTokenScopes {\n\tprivate scopes: bigint\n\n\tconstructor(s: string | bigint | AccessTokenScope | AccessTokenScope[]) {\n\t\tthis.scopes = BigInt(0)\n\n\t\tif (typeof s === \"string\") {\n\t\t\tthis.scopes = BigInt(s).valueOf()\n\t\t\treturn\n\t\t}\n\t\tif (typeof s === \"bigint\") {\n\t\t\tthis.scopes = s\n\t\t\treturn\n\t\t}\n\t\tif (typeof s === \"number\") {\n\t\t\tthis.addScope(s)\n\t\t\treturn\n\t\t}\n\t\tif (Array.isArray(s)) {\n\t\t\tthis.addScope(...s)\n\t\t\treturn\n\t\t}\n\t}\n\n\taddScope(...scopes: AccessTokenScope[]) {\n\t\tfor (const scope of scopes) {\n\t\t\tif (scope < 0) {\n\t\t\t\tthrow new Error(\"Scope must be 0 or bigger.\")\n\t\t\t}\n\t\t\tthis.scopes = this.scopes | BigInt(1 << scope).valueOf()\n\t\t}\n\t}\n\n\thasScope(scope: AccessTokenScope): boolean {\n\t\tif (scope < 0) {\n\t\t\tthrow new Error(\"Scope must be 0 or bigger.\")\n\t\t}\n\t\treturn Boolean((this.scopes >> BigInt(scope)) & BigInt(1))\n\t}\n\n\t/**\n\t * @returns new Scopes containing only the original scopes that are present in the given `scopes` parameter.\n\t */\n\tintersection(scopes: AccessTokenScopes): AccessTokenScopes {\n\t\treturn new AccessTokenScopes(this.scopes & scopes.valueOf())\n\t}\n\n\tmatches(scopes: AccessTokenScopes): boolean {\n\t\t// Returns true if the `scopes` argument has *at least* the bits of `this.scopes`.\n\t\treturn this.intersection(scopes).valueOf() === this.scopes\n\t}\n\n\tvalueOf(): bigint {\n\t\treturn this.scopes\n\t}\n\n\ttoString(): string {\n\t\treturn this.scopes.toString()\n\t}\n}\n\nexport enum AccessTokenScope {\n\tViewProfile = 0,\n\tEditProfile = 1,\n\tViewTeam = 2,\n\tEditTeam = 3,\n\tViewProject = 4,\n\tEditProject = 5,\n\tViewModule = 6,\n\tEditModule = 7,\n\tViewPackage = 8,\n\tEditPackage = 9,\n\tViewAsset = 10,\n\tEditAsset = 11,\n\tViewAIChat = 12,\n\tEditAIChat = 13,\n}\n\nexport const vekterExpectedScopes = new AccessTokenScopes([\n\tAccessTokenScope.ViewProfile,\n\tAccessTokenScope.EditProfile,\n\tAccessTokenScope.ViewTeam,\n\tAccessTokenScope.EditTeam,\n\tAccessTokenScope.ViewProject,\n\tAccessTokenScope.EditProject,\n\tAccessTokenScope.ViewModule,\n\tAccessTokenScope.EditModule,\n\tAccessTokenScope.ViewPackage,\n\tAccessTokenScope.EditPackage,\n\tAccessTokenScope.ViewAsset,\n\tAccessTokenScope.EditAsset,\n\tAccessTokenScope.ViewAIChat,\n\tAccessTokenScope.EditAIChat,\n])\n\nexport const publicApiExpectedScopes = new AccessTokenScopes([\n\tAccessTokenScope.ViewProject,\n\tAccessTokenScope.EditProject,\n\tAccessTokenScope.ViewModule,\n\tAccessTokenScope.EditModule,\n\tAccessTokenScope.ViewAsset,\n\tAccessTokenScope.EditAsset,\n])\n", "import { assert, getLogger } from \"@framerjs/shared\"\nimport * as idb from \"@iamakulov/idb-keyval\"\nimport { type JwtPayload, jwtDecode } from \"jwt-decode\"\nimport { AccessTokenScopes, publicApiExpectedScopes, vekterExpectedScopes } from \"../utils/accessTokenScopes.ts\"\nimport { ApiError } from \"./ApiError.ts\"\n\nconst log = getLogger(\"accessTokenRefresher\")\n\ntype WaitListCallback = (token: string | undefined) => void\nconst StatusCodeUnauthorized = 401\n\ninterface AccessToken {\n\taccessToken: string\n\texpiresAt: string\n}\n\n/**\n * Stores the access token with full privileges.\n */\nconst STORAGE_KEY = \"access_token\"\n\n/**\n * Stores the access token with limited privileges, used in On-Page Editing.\n *\n * The string chosen here is to mimic \"session\" and \"session.edit\" cookies.\n */\nconst EDIT_STORAGE_KEY = \"access_token.edit\"\n\nconst PROACTIVE_REFRESH_WINDOW = 90 * 1000 // Refresh 1.5 minutes before expiry. The browser may lag in triggering timeouts by up to a minute when saving power, so this is a precaution.\nconst REFRESH_DEADLINE = 30 * 1000 // Consider expired tokens that have a remaining lifespan of less than 30 seconds to avoid race conditions. We should've refreshed those well before then, but if we didn't, just discard it and make requests wait for a new one.\n\nexport class AccessTokenRefresher {\n\tprivate _accessToken?: string\n\tprivate _accessTokenExpiry?: Date\n\t/**\n\t * We need to remember in which storage the current access token got stored,\n\t * so that if we need to discard it, we'll discard the right one.\n\t */\n\tprivate _accessTokenStorageKey?: string\n\tprivate timer: number | null = null\n\tprivate url: string\n\tprivate accessTokenWaitList: WaitListCallback[] = []\n\tprivate retryAttempt: number = 0\n\tprivate MaxRetryDelay: number = 60 * 1000 // 1 Minute Max retry wait\n\tprivate BaseRetryDelay: number = 1000 // 1 Second Max retry wait\n\tprivate isUnauthorized: boolean = false\n\tprivate hasStarted: boolean = false\n\t/**\n\t * On On-Page Editing, we only have access to the \"session.edit\" cookie,\n\t * which in turn gets exchanged for a limited-scope access token.\n\t *\n\t * We must be careful not to store that limited-scope token under the main\n\t * STORAGE_KEY, because it won't work in the main Framer app.\n\t */\n\tprivate isEmbeddedCrossOrigin: boolean = false\n\n\tconstructor(\n\t\tapiBaseURL: string,\n\t\tprivate readonly options?: {\n\t\t\tonInsufficientScopes?: (self: AccessTokenRefresher) => void\n\t\t},\n\t) {\n\t\tthis.url = `${apiBaseURL}/auth/web/access-token`\n\n\t\ttry {\n\t\t\t// If we're embedded cross-origin, accessing\n\t\t\t// window.top.location.href will throw a cross-origin error.\n\t\t\t//\n\t\t\t// Note that window.top can be null:\n\t\t\t// https://html.spec.whatwg.org/multipage/browsers.html#dom-top\n\t\t\t//\n\t\t\t// If this happens, we can't do our cross-origin litmus test, so\n\t\t\t// let's err on the side of caution and assume we're NOT embedded\n\t\t\t// cross-origin. Otherwise, if this were to happen on framer.com,\n\t\t\t// we'd break our app.\n\t\t\t//\n\t\t\t// We also skip this check if there's no window, because that means\n\t\t\t// we're running in our service worker, and thus should have access\n\t\t\t// to the \"session\" cookie.\n\t\t\t// eslint-disable-next-line no-unused-expressions\n\t\t\ttypeof window !== \"undefined\" && window.top?.location.href\n\t\t} catch {\n\t\t\tthis.isEmbeddedCrossOrigin = true\n\t\t}\n\t}\n\n\tasync start(): Promise<void> {\n\t\tassert(!this.hasStarted, \"Attempt to start AccessTokenRefresher more than once.\")\n\t\tthis.hasStarted = true\n\n\t\tconst tokenFromStorage = await this.loadAccessTokenFromStorage()\n\n\t\tif (tokenFromStorage) {\n\t\t\tconst { accessToken, expiry, storageKey } = tokenFromStorage\n\t\t\tthis.setToken(accessToken, expiry, storageKey)\n\t\t\tthis.scheduleRefreshAt(getProactiveRefreshTimeForExpiry(expiry))\n\t\t} else {\n\t\t\tawait this.refreshAccessTokenAndScheduleNextRefresh()\n\t\t}\n\t}\n\n\tprivate registerForNewToken(callback: WaitListCallback) {\n\t\tlog.debug(\"Adding waiter for new token\")\n\t\tthis.accessTokenWaitList.push(callback)\n\t}\n\n\tprivate flushWaitList() {\n\t\tconst waitList = this.accessTokenWaitList\n\t\tthis.accessTokenWaitList = []\n\t\tlog.debug(\"Flushing waitlist, contains\", waitList.length, \"waiters\")\n\n\t\tfor (const callback of waitList) {\n\t\t\tcallback(this._accessToken)\n\t\t}\n\t}\n\n\tprivate isUnauthorizedResponse(response: Response) {\n\t\treturn response.status === StatusCodeUnauthorized\n\t}\n\n\tprivate handleServerError = (response: Response) => {\n\t\tif (!this.isUnauthorizedResponse(response)) {\n\t\t\tlog.debug(\"Error response status:\", response.status, \"with text:\", response.statusText)\n\t\t\tthis.retryWithBackoff()\n\t\t\tthrow new ApiError({\n\t\t\t\tstatus: response.status,\n\t\t\t\tmessage: response.statusText,\n\t\t\t})\n\t\t}\n\t}\n\n\t// TODO: We should leverage whether a tab's focused\n\tprivate async refreshAccessTokenAndScheduleNextRefresh(): Promise<void> {\n\t\tlog.debug(\"Renewing access token\")\n\t\t// This counts as a start, as it will kickstart a token renew loop\n\t\tif (!this.hasStarted) {\n\t\t\tthis.hasStarted = true\n\t\t}\n\n\t\tlet response\n\t\ttry {\n\t\t\tresponse = await fetch(this.url, {\n\t\t\t\tcredentials: \"include\",\n\t\t\t})\n\t\t} catch (error) {\n\t\t\tlog.error(\"Connection error, retrying\u2026\")\n\t\t\tthis.retryWithBackoff()\n\t\t\treturn\n\t\t}\n\n\t\tif (!response.ok) {\n\t\t\tthis.handleServerError(response)\n\t\t\tif (this.isUnauthorizedResponse(response)) {\n\t\t\t\t// Don't retry, and prevent any more\n\t\t\t\t// requests to trigger getting the token\n\t\t\t\tlog.debug(\"Turning on unauthorized mode\")\n\t\t\t\tthis.isUnauthorized = true\n\t\t\t\tthis.flushWaitList()\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\tlog.debug(\"Received access token\")\n\t\t// Reset retries in case we succeeded\n\t\tthis.retryAttempt = 0\n\n\t\tconst rawAccessToken = await response.json()\n\t\tconst { accessToken } = rawAccessToken\n\n\t\tconst decodedAccessToken: JwtPayload & { scopes: string; scope: string } = jwtDecode(accessToken)\n\t\tconst accessTokenScopes = new AccessTokenScopes(decodedAccessToken.scopes)\n\n\t\t// If we are not embedded cross-origin (i.e., in on-page editing), then we expect that our\n\t\t// access token contains all scopes. If this doesn't happen, we are in a bad, unrecoverable state.\n\t\t//\n\t\t// This would happen if we have no `session` cookie, but we do have a `session.edit` cookie. In\n\t\t// that case, we'd get an access token with on-page editing permission on Vekter. This state is\n\t\t// unrecoverable, so the only solution is to log out. We don't know why it happens, but we've\n\t\t// seen reports of customers being stuck there.\n\t\tif (!this.isEmbeddedCrossOrigin && !this.isValidAccessToken(decodedAccessToken.scope, accessTokenScopes)) {\n\t\t\tawait this.discardAccessToken()\n\n\t\t\tlog.reportError(\n\t\t\t\t`Received access token has insufficient scopes. Wanted: ${vekterExpectedScopes.valueOf()}, got: ${accessTokenScopes.valueOf()}`,\n\t\t\t\tundefined,\n\t\t\t\tundefined,\n\t\t\t\ttrue,\n\t\t\t)\n\t\t\tthis.options?.onInsufficientScopes?.(this)\n\t\t\tthis.retryWithBackoff()\n\t\t\treturn\n\t\t}\n\n\t\tlet expiresAt\n\t\tif (rawAccessToken.expiresInSeconds) {\n\t\t\texpiresAt = Date.now() + rawAccessToken.expiresInSeconds * 1000\n\t\t\tlog.debug(\"Received expiry seconds:\", rawAccessToken.expiresInSeconds)\n\t\t} else {\n\t\t\texpiresAt = rawAccessToken.expiresAt\n\t\t}\n\n\t\tif (!accessToken) {\n\t\t\t// This should not happen unless something's really off\n\t\t\tlog.error(\"Unable to authenticate client\")\n\t\t\tthis.retryWithBackoff()\n\t\t\treturn\n\t\t}\n\n\t\tconst expiry = new Date(expiresAt)\n\t\tif (Number.isNaN(expiry.getTime())) {\n\t\t\tlog.error(\"Access Token expiry date is invalid\")\n\t\t\tthis.retryWithBackoff()\n\t\t\treturn\n\t\t}\n\n\t\tthis.setToken(accessToken, expiry, this.isEmbeddedCrossOrigin ? EDIT_STORAGE_KEY : STORAGE_KEY)\n\t\tthis.scheduleRefreshAt(getProactiveRefreshTimeForExpiry(expiry))\n\t}\n\n\tprivate setToken(accessToken: string, expiry: Date, storageKey: string) {\n\t\tlog.debug(\"Setting acccess token\")\n\t\tthis._accessToken = accessToken\n\t\tthis._accessTokenExpiry = expiry\n\t\tthis._accessTokenStorageKey = storageKey\n\t\tthis.flushWaitList()\n\t\t// We don\u2019t want to block execution by waiting until the access token is saved into IndexedDB,\n\t\t// so we\u2019re not `await`ing this\n\t\tvoid this.saveAccessTokenInStorage(storageKey, { accessToken, expiresAt: expiry.toISOString() })\n\t}\n\n\tprivate clearRefreshTimer() {\n\t\tif (this.timer) {\n\t\t\tlog.debug(\"Clearing refresh timer\")\n\t\t\tclearTimeout(this.timer)\n\t\t\tthis.timer = null\n\t\t}\n\t}\n\n\t/**\n\t * Implements an exponential backoff with jitter approach to retrying\n\t * If customers are having trouble connection issues, we continue to\n\t * retry, but slower and slower. The jitter is added to prevent many\n\t * clients synchronizing causing multiple calls to come in at the same time\n\t */\n\tprivate retryWithBackoff() {\n\t\tthis.clearRefreshTimer()\n\n\t\tthis.retryAttempt += 1\n\t\tconst retryDelay = Math.floor(\n\t\t\tMath.random() * Math.min(this.MaxRetryDelay, this.BaseRetryDelay * 2 ** this.retryAttempt),\n\t\t)\n\t\tlog.debug(\"Retrying after\", retryDelay)\n\t\tthis.scheduleRefreshAfter(retryDelay)\n\t}\n\n\tprivate scheduleRefreshAfter(milliseconds: number) {\n\t\tthis.clearRefreshTimer()\n\n\t\t// Casting the return type since, by default, setTimeout picks up Node.js\u2019 type definitions\n\t\t// which mismatch browser\u2019s ones\n\t\t// IMPORTANT: to not use `window.setTimeout` here, as this code runs in a worker context too.\n\t\tthis.timer = setTimeout(() => this.refreshAccessTokenAndScheduleNextRefresh(), milliseconds) as unknown as number\n\t}\n\n\tprivate scheduleRefreshAt(date: Date) {\n\t\tconst delay = date.getTime() - new Date().getTime()\n\t\tif (delay <= 0) {\n\t\t\tthrow new Error(\"Refresh time is not valid\")\n\t\t\t// TODO: Invalidate session, something's up\n\t\t}\n\n\t\tthis.scheduleRefreshAfter(delay)\n\t}\n\n\tprivate async saveAccessTokenInStorage(storageKey: string, data: AccessToken) {\n\t\ttry {\n\t\t\tawait idb.set(storageKey, data)\n\t\t} catch (e) {\n\t\t\t// ignore\n\t\t\tlog.debug(\"Error in storing access token\", e)\n\t\t}\n\t}\n\n\tprivate async loadAccessTokenFromStorage(): Promise<{\n\t\taccessToken: string\n\t\texpiry: Date\n\t\tstorageKey: string\n\t} | null> {\n\t\tconst storageKey = this.isEmbeddedCrossOrigin ? EDIT_STORAGE_KEY : STORAGE_KEY\n\n\t\ttry {\n\t\t\tconst item = await idb.get(storageKey)\n\t\t\tif (!item) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t\tconst { accessToken, expiresAt }: AccessToken = item\n\t\t\tconst expiry = new Date(expiresAt)\n\n\t\t\t// Do not use the token if already expired or close to expiring.\n\t\t\tif (new Date() >= getProactiveRefreshTimeForExpiry(expiry)) {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\treturn { accessToken, expiry, storageKey }\n\t\t} catch (error) {\n\t\t\tlog.warn(\"Warning: failed to read the access token from IndexedDB (via idb-keyval):\", error)\n\t\t\treturn null\n\t\t}\n\t}\n\n\tprivate hasAccessTokenExpired() {\n\t\tif (this._accessTokenExpiry) {\n\t\t\treturn new Date().getTime() >= this._accessTokenExpiry.getTime() - REFRESH_DEADLINE\n\t\t}\n\t\t// Returning false here because we're probably requesting a token still,\n\t\t// and don't want multiple calls\n\t\treturn false\n\t}\n\n\tprivate isAccessTokenValid() {\n\t\tconst isValid = this._accessToken && !this.isUnauthorized\n\n\t\treturn isValid && !this.hasAccessTokenExpired()\n\t}\n\n\tasync getAccessToken(): Promise<string | undefined> {\n\t\t// Exit early if we're unauthorized\n\t\tif (this.isUnauthorized) return Promise.resolve(undefined)\n\n\t\t// If we have a valid token, return that token\n\t\tif (this.isAccessTokenValid()) {\n\t\t\treturn Promise.resolve(this._accessToken)\n\t\t}\n\n\t\t// If we don't have a valid token, register to wait list\n\t\tconst resolvePromise = new Promise(resolve => this.registerForNewToken(resolve))\n\n\t\t// In case we had a token that's expired, we need to throw it away, and start over\n\t\tif (this.hasAccessTokenExpired()) {\n\t\t\tawait this.discardAccessToken(true)\n\t\t}\n\n\t\t// If this is the first time we're calling this method, and the refresher\n\t\t// hasn't started yet, lets start the loop\n\t\tif (!this.hasStarted) {\n\t\t\tawait this.start()\n\t\t}\n\n\t\treturn resolvePromise as Promise<string>\n\t}\n\n\tasync getAuthorizationHeaderValue() {\n\t\tconst accessToken = await this.getAccessToken()\n\t\tif (!accessToken) {\n\t\t\treturn\n\t\t}\n\t\treturn `Bearer ${accessToken}`\n\t}\n\n\t/**\n\t * Stops the accessTokenRefresher from requesting further\n\t * tokens, and clears session storage\n\t * Should only be used when signing out a user\n\t */\n\tasync stopAuthentication(): Promise<void> {\n\t\ttry {\n\t\t\tawait this.discardAccessToken(false)\n\t\t\tthis.hasStarted = false\n\t\t\tawait idb.del(STORAGE_KEY)\n\t\t\tawait idb.del(EDIT_STORAGE_KEY)\n\t\t} catch {\n\t\t\t// ignore\n\t\t}\n\t}\n\n\tasync discardAccessToken(shouldRenew = false): Promise<void> {\n\t\ttry {\n\t\t\tlog.debug(\"Discarding access token with renewal\", shouldRenew)\n\t\t\tthis.clearRefreshTimer()\n\t\t\tthis._accessToken = undefined\n\t\t\tthis._accessTokenExpiry = undefined\n\t\t\tif (this._accessTokenStorageKey) await idb.del(this._accessTokenStorageKey)\n\t\t\tthis._accessTokenStorageKey = undefined\n\t\t\tif (shouldRenew && !this.isUnauthorized) {\n\t\t\t\tthis.scheduleRefreshAfter(0)\n\t\t\t}\n\t\t} catch (e) {\n\t\t\t// ignore\n\t\t}\n\t}\n\n\t/**\n\t * Adds an access-token obtained from the Authentication API to the fetch call as\n\t * an `authorization` header.\n\t *\n\t * @param init RequestInit object containing all the request params for a fetch call\n\t * @returns a RequestInit object that has it's `headers` field updated. The resulting `headers`\n\t * field will always be of type `Header`\n\t */\n\tasync withAuthorizationHeader(init: RequestInit): Promise<RequestInit> {\n\t\tconst authHeaderValue = await this.getAuthorizationHeaderValue()\n\t\tif (authHeaderValue) {\n\t\t\tinit.headers = new Headers(init.headers)\n\t\t\tinit.headers.set(\"authorization\", authHeaderValue)\n\t\t}\n\n\t\treturn init\n\t}\n\n\tprivate isValidAccessToken(scope: string, accessTokenScopes: AccessTokenScopes): boolean {\n\t\tif (scope === \"public-api\") {\n\t\t\treturn publicApiExpectedScopes.matches(accessTokenScopes)\n\t\t}\n\n\t\treturn vekterExpectedScopes.matches(accessTokenScopes)\n\t}\n}\n\nfunction getProactiveRefreshTimeForExpiry(expiry: Date) {\n\treturn new Date(expiry.getTime() - PROACTIVE_REFRESH_WINDOW)\n}\n", "// This file includes the logic that generates URLs for dataLoadingHelpers.ts.\n// It's split into a separate file to allow using it in both the window and the worker environment.\n\ntype PathAndQuery = [path: string, query?: Record<string, string>]\n\nexport function currentUserURL(): PathAndQuery {\n\treturn [\"/web/users/me\"]\n}\n\nexport function projectURL(projectId: string, accessToken?: string): PathAndQuery {\n\tconst queryParams = accessToken ? { accessToken } : undefined\n\treturn [`/web/projects/${projectId}`, queryParams]\n}\n\nexport function defaultProjectLocationURL(): PathAndQuery {\n\treturn [`/web/users/default-project-location`]\n}\n\nexport function dashboardTeamsURL(): PathAndQuery {\n\treturn [\"/web/v2/dashboard/metadata\"]\n}\n", "// We currently expect `window.__app-start-time` to be set with the first script in the html.\nexport type WindowWithAppStartTime = typeof window & { \"__app-start-time\": number }\n\n/** Returns the `Date.now()` number when the app started. Or zero if not set. */\nexport function getAppStartTime(): number {\n\treturn (window as WindowWithAppStartTime)[\"__app-start-time\"] || 0\n}\n"],
  "mappings": "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",
  "names": ["colors", "React", "avatar", "TooltipTrigger", "import_react", "tooltipName", "tooltipLabel", "import_jsx_runtime", "React", "tooltipName", "tooltipLabel", "import_react", "import_jsx_runtime", "React", "import_react", "keys", "keys"]
}
