diff --git a/.github/scripts/fix_i18n.py b/.github/scripts/fix_i18n.py index bddb25e567..8e9ffc35b4 100644 --- a/.github/scripts/fix_i18n.py +++ b/.github/scripts/fix_i18n.py @@ -4,17 +4,12 @@ # Define MDX tags and locales MDX_TAGS = [ - "Abbr", "Accordion", - "ApiVersion", - "SdkVersion", "Callout", "CodeBlock", "MinorVersion", - "Table", "Tabs", "Tab", - "Tile", "ListColumns", ] locales = ["ja", "ko", "zh"] diff --git a/.lycheeignore b/.lycheeignore index cd3230b9b3..a1143598f3 100644 --- a/.lycheeignore +++ b/.lycheeignore @@ -1,9 +1,10 @@ -^https?://api\.adjust\.com(?:/.*)?$ -^https?://example\.go\.link(?:/.*)?$ -^https?://dash\.adjust\.com/control-center(?:/.*)?$ -^https?://segment\.com(?:/.*)?$ -^https?://admin\.shopify\.com(?:/.*)?$ -^https?://launch\.adobe\.com(?:/.*)?$ -^https?://app\.adjust.com(?:/.*)?$ -^https?://mydomain\.com(?:/.*)?$ +^https?:\/\/(www.)?api\.adjust\.com(?:\/.*)?$ +^https?:\/\/(www.)?example\.go\.link(?:\/.*)?$ +^https?:\/\/(www.)?dash\.adjust\.com\/control-center(?:\/.*)?$ +^https?:\/\/(www.)?segment\.com(?:\/.*)?$ +^https?:\/\/(www.)?admin\.shopify\.com(?:\/.*)?$ +^https?:\/\/(www.)?launch\.adobe\.com(?:\/.*)?$ +^https?:\/\/(www.)?app\.adjust.com(?:\/.*)?$ +^https?:\/\/(www.)?mydomain\.com(?:\/.*)?$ @images* +^file:\/\/\/.*?$ diff --git a/package-lock.json b/package-lock.json index 5100ab6986..e108c6d2a4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -39,7 +39,8 @@ "tailwindcss": "^3.4.15", "typesense-instantsearch-adapter": "^2.8.0", "unified": "^11.0.5", - "unist-util-visit": "^5.0.0" + "unist-util-visit": "^5.0.0", + "uuid": "^11.0.3" }, "devDependencies": { "@stylistic/eslint-plugin": "^2.10.1", @@ -11762,6 +11763,19 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "license": "MIT" }, + "node_modules/uuid": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.0.3.tgz", + "integrity": "sha512-d0z310fCWv5dJwnX1Y/MncBAqGMKEzlBb1AOf7z9K8ALnd0utBX/msg/fA0+sbyN1ihbMsLhrBlnl1ak7Wa0rg==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", diff --git a/package.json b/package.json index 34eb47e056..94aee7d96b 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,8 @@ "tailwindcss": "^3.4.15", "typesense-instantsearch-adapter": "^2.8.0", "unified": "^11.0.5", - "unist-util-visit": "^5.0.0" + "unist-util-visit": "^5.0.0", + "uuid": "^11.0.3" }, "devDependencies": { "@stylistic/eslint-plugin": "^2.10.1", diff --git a/src/components/Accordion.astro b/src/components/Accordion.astro index 1f96d16437..b36547f300 100644 --- a/src/components/Accordion.astro +++ b/src/components/Accordion.astro @@ -39,19 +39,35 @@ const { title, badge } = Astro.props; diff --git a/src/components/AudienceDropdown.astro b/src/components/AudienceDropdown.astro index 89263c1d80..9b66046b2c 100644 --- a/src/components/AudienceDropdown.astro +++ b/src/components/AudienceDropdown.astro @@ -75,24 +75,38 @@ const audiences = [ diff --git a/src/components/Cards/CategoryCard.astro b/src/components/Cards/CategoryCard.astro index acdbd6b195..999096b8b9 100644 --- a/src/components/Cards/CategoryCard.astro +++ b/src/components/Cards/CategoryCard.astro @@ -1,6 +1,5 @@ --- import type { SidebarItem } from "@utils/helpers/navigation/types"; -import classNames from "classnames"; interface Props { child: SidebarItem; @@ -13,13 +12,7 @@ const categoryClass = `category-${childCategory}-${childVersion}`; ---
import { $versions as $sdkVersions } from "@store/sdkVersionsStore"; - document.addEventListener("DOMContentLoaded", () => { - const currentSdkVersion = $sdkVersions.get().currentVersion.value || "v5"; - // Helper function to hide all versioned items initially - const hideAllVersionedItems = () => { + class CategoryController { + private sdkVersionsStore: typeof $sdkVersions; + + constructor(sdkVersionsStore: typeof $sdkVersions) { + this.sdkVersionsStore = sdkVersionsStore; + } + + // Hide all versioned items + private hideAllVersionedItems(): void { const versionedItems = document.querySelectorAll( "[class*='category-sdk']", ); versionedItems.forEach((item) => { if (!item.classList.contains("hidden")) item.classList.add("hidden"); }); - }; + } - // Helper function to show items for the current versions - const showCurrentVersionItems = (sdkVersion: string) => { - hideAllVersionedItems(); - // Select and show items for the current SDK versions + // Show items for the current SDK version + private showCurrentVersionItems(sdkVersion: string): void { + this.hideAllVersionedItems(); const versionedItems = document.querySelectorAll( `.category-sdk-${sdkVersion}, .category-sdk-0`, ); @@ -61,14 +58,26 @@ const categoryClass = `category-${childCategory}-${childVersion}`; item.classList.remove("hidden"); item.classList.add("block"); }); - }; + } + + // Initialize and subscribe to version changes + public initialize(): void { + const currentSdkVersion = + this.sdkVersionsStore.get()?.currentVersion?.value || "v5"; + this.showCurrentVersionItems(currentSdkVersion); + + this.sdkVersionsStore.subscribe((store) => { + const sdkVersion = store.currentVersion?.value; + if (sdkVersion) { + this.showCurrentVersionItems(sdkVersion); + } + }); + } + } + + document.addEventListener("DOMContentLoaded", () => { + const controller = new CategoryController($sdkVersions); - // Subscribe to version changes in the Nanostores - $sdkVersions.subscribe((store) => { - const sdkVersion = store.currentVersion?.value; - if (sdkVersion) { - showCurrentVersionItems(sdkVersion); - } - }); + controller.initialize(); }); diff --git a/src/components/FigmaEmbed/Caption.astro b/src/components/FigmaEmbed/Caption.astro deleted file mode 100644 index 67e1495ab3..0000000000 --- a/src/components/FigmaEmbed/Caption.astro +++ /dev/null @@ -1,22 +0,0 @@ ---- -interface Props { - bottom?: number; - left?: number; - right?: number; - top?: number; -} - -const { bottom = "24", left = "0", right = "0", top = "-16" } = Astro.props; ---- - -
- -
diff --git a/src/components/FigmaEmbed/FigmaEmbed.astro b/src/components/FigmaEmbed/FigmaEmbed.astro deleted file mode 100644 index aeec06fc13..0000000000 --- a/src/components/FigmaEmbed/FigmaEmbed.astro +++ /dev/null @@ -1,35 +0,0 @@ ---- -import Caption from "@components/FigmaEmbed/Caption.astro"; - -interface Props { - embedUrl: string; - caption?: string; -} - -const { embedUrl } = Astro.props; - -const width = 800; -const height = 360; - -const figmaIframePadding = 96; - -const aspectRatio = ((+height + figmaIframePadding) / width) * 100 + "%"; - -const src = `https://www.figma.com/embed?embed_host=share&url=${embedUrl}`; ---- - -<> -
- -
- { - Astro.slots.has("default") && ( - - - - ) - } - diff --git a/src/components/LanguageSwitch.astro b/src/components/LanguageSwitch.astro index ef6c31ac7f..443535588a 100644 --- a/src/components/LanguageSwitch.astro +++ b/src/components/LanguageSwitch.astro @@ -56,30 +56,38 @@ const getLanguageUrl = (newLang: string) => {
diff --git a/src/components/Layout/Footer/ContactSupportButton/index.astro b/src/components/Layout/Footer/ContactSupportButton.astro similarity index 100% rename from src/components/Layout/Footer/ContactSupportButton/index.astro rename to src/components/Layout/Footer/ContactSupportButton.astro diff --git a/src/components/Layout/Footer/FooterContent.astro b/src/components/Layout/Footer/FooterContent.astro index acf8c65070..ba8b5e444d 100644 --- a/src/components/Layout/Footer/FooterContent.astro +++ b/src/components/Layout/Footer/FooterContent.astro @@ -1,5 +1,5 @@ --- -import ContactSupportButton from "./ContactSupportButton/index.astro"; +import ContactSupportButton from "./ContactSupportButton.astro"; import { footerIcons, footerLinks } from "./static"; import type { IWithLanguage } from "src/types/WithLanguage"; import type { Locales } from "@i18n/locales"; diff --git a/src/components/Layout/Footer/FooterMain.astro b/src/components/Layout/Footer/FooterMain.astro index a24d56017c..363b832c23 100644 --- a/src/components/Layout/Footer/FooterMain.astro +++ b/src/components/Layout/Footer/FooterMain.astro @@ -1,5 +1,5 @@ --- -import ContactSupportButton from "./ContactSupportButton/index.astro"; +import ContactSupportButton from "./ContactSupportButton.astro"; import FooterLanguageSwitch from "./FooterLanguageSwitch.astro"; import { footerIcons, footerLinks } from "./static"; import type { IWithLanguage } from "src/types/WithLanguage"; diff --git a/src/components/Layout/Footer/types.ts b/src/components/Layout/Footer/types.ts index d1ce9211fb..b31c4ebf65 100644 --- a/src/components/Layout/Footer/types.ts +++ b/src/components/Layout/Footer/types.ts @@ -1,5 +1,4 @@ import type { Locales } from "@i18n/locales"; -import type { IWithLanguage } from "src/types/WithLanguage"; export interface LanguageSwitchProps { lang: string; diff --git a/src/components/Layout/LeftSidebar/ChevronToggle.astro b/src/components/Layout/LeftSidebar/ChevronToggle.astro index d903e18732..3866f92725 100644 --- a/src/components/Layout/LeftSidebar/ChevronToggle.astro +++ b/src/components/Layout/LeftSidebar/ChevronToggle.astro @@ -1,7 +1,4 @@ --- -import ChevronRight from "@components/Layout/LeftSidebar/Icons/ChevronRight.astro"; -import ChevronDown from "@components/Layout/LeftSidebar/Icons/ChevronDown.astro"; - interface Props { slug: string; initialOpen: boolean; @@ -13,14 +10,44 @@ const { slug, initialOpen } = Astro.props;
- +
+ +
- +
+ +
diff --git a/src/components/Layout/LeftSidebar/Icons/ChevronDown.astro b/src/components/Layout/LeftSidebar/Icons/ChevronDown.astro deleted file mode 100644 index 49bdd86b02..0000000000 --- a/src/components/Layout/LeftSidebar/Icons/ChevronDown.astro +++ /dev/null @@ -1,16 +0,0 @@ -
- -
diff --git a/src/components/Layout/LeftSidebar/Icons/ChevronRight.astro b/src/components/Layout/LeftSidebar/Icons/ChevronRight.astro deleted file mode 100644 index c05655bcf2..0000000000 --- a/src/components/Layout/LeftSidebar/Icons/ChevronRight.astro +++ /dev/null @@ -1,16 +0,0 @@ -
- -
diff --git a/src/components/Layout/LeftSidebar/LeftSidebarItem.astro b/src/components/Layout/LeftSidebar/LeftSidebarItem.astro index 342dd02d75..0bc820d2e9 100644 --- a/src/components/Layout/LeftSidebar/LeftSidebarItem.astro +++ b/src/components/Layout/LeftSidebar/LeftSidebarItem.astro @@ -1,5 +1,4 @@ --- -import classNames from "classnames"; import ChevronToggle from "./ChevronToggle.astro"; import type { SidebarItem } from "@utils/helpers/navigation/types"; @@ -16,41 +15,24 @@ const initialOpen = currentSlug.startsWith(sidebarData.slug); const itemVersion = version; const itemCategory = slug?.includes("/sdk") ? "sdk" : "api"; const itemName = label ? label : categoryTitle ? categoryTitle : title; +const categoryClass = itemVersion + ? `item-version-${itemCategory}-${itemVersion}` + : "item-version-0"; ---
- - diff --git a/src/components/SdkVersionSwitch.astro b/src/components/SdkVersionSwitch.astro new file mode 100644 index 0000000000..db0480a0fe --- /dev/null +++ b/src/components/SdkVersionSwitch.astro @@ -0,0 +1,180 @@ +--- +import type { Locales } from "@i18n/locales"; +import { useTranslations } from "@i18n/utils"; +import { findEntryBySlug } from "@utils/helpers/navigation/findEntryBySlug"; +import { uniqueSdkVersions } from "@utils/helpers/navigation/getUniqueVersions"; + +interface Props { + lang: string; + currentPage: string; +} + +const { lang, currentPage } = Astro.props; +const t = useTranslations(lang as keyof Locales); + +// Get current page data and redirects from frontmatter +const pageData = findEntryBySlug(currentPage); +const redirects = pageData?.redirects || {}; +const defaultVersion = + (uniqueSdkVersions && uniqueSdkVersions.find((v) => v.default)?.value) || ""; +--- + +
+ +
+ + +
+
+ + diff --git a/src/components/Tab.astro b/src/components/Tab.astro index 22337640e2..24d062049c 100644 --- a/src/components/Tab.astro +++ b/src/components/Tab.astro @@ -1,5 +1,5 @@ --- -import { randomUUID } from "crypto"; +import { v4 as uuidv4 } from "uuid"; interface Props { title: string; @@ -9,7 +9,7 @@ interface Props { const { title, sync, icon } = Astro.props; -const uniqueId = randomUUID(); +const uniqueId = uuidv4(); ---
{ - const toc = document.getElementById("toc"); - if (!toc) return; - - const tocButton = document.getElementById("toc-toggle-button"); - const tocList = document.getElementById("toc-list"); - const tocHeader = document.getElementById("toc-header"); - const leftChevron = document.getElementById("chevron-left"); - const rightChevron = document.getElementById("chevron-right"); - const article = document.getElementById("article"); - - const storeValue = $tocOpen.get(); - let didUpdateStore = storeValue !== undefined; - let isTocOpen = storeValue === "true" || window.innerWidth >= 1440; - - const openTocClasses = [ - "xxl:ml-open-toc", - "z-25", - "px-4", - "bg-white", - "max-h-screen", - "w-[19rem]", - "opacity-1", - "items-start", - "z-10", - ]; - const closedTocClasses = ["w-8", "ml-closed-toc"]; - - const toggleMenu = (open: boolean, updateStore: boolean) => { - isTocOpen = open; + class TocController { + private toc: HTMLElement | null; + private tocButton: HTMLElement | null; + private tocList: HTMLElement | null; + private tocHeader: HTMLElement | null; + private leftChevron: HTMLElement | null; + private rightChevron: HTMLElement | null; + private article: HTMLElement | null; + private isTocOpen: boolean; + private didUpdateStore: boolean; + private openTocClasses: string[]; + private closedTocClasses: string[]; + + /** + * Selects DOM elements and sets class properties + */ + constructor() { + this.toc = document.getElementById("toc"); + this.tocButton = document.getElementById("toc-toggle-button"); + this.tocList = document.getElementById("toc-list"); + this.tocHeader = document.getElementById("toc-header"); + this.leftChevron = document.getElementById("chevron-left"); + this.rightChevron = document.getElementById("chevron-right"); + this.article = document.getElementById("article"); + + const storeValue = $tocOpen.get(); + this.didUpdateStore = storeValue !== undefined; + this.isTocOpen = storeValue === "true" || window.innerWidth >= 1440; + + this.openTocClasses = [ + "xxl:ml-open-toc", + "z-25", + "px-4", + "bg-white", + "max-h-screen", + "w-[19rem]", + "opacity-1", + "items-start", + "z-10", + ]; + this.closedTocClasses = ["w-8", "ml-closed-toc"]; + } + + /** + * Toggles menus open and closed by altering classes + * @param open Whether the sidebar is currently open + * @param updateStore Whether to update the store value to persist the user's choice + */ + private toggleMenu(open: boolean, updateStore: boolean): void { + this.isTocOpen = open; if (updateStore) { setTocOpen(open); - didUpdateStore = true; + this.didUpdateStore = true; } - tocList!.classList.toggle("hidden", !open); - tocHeader!.classList.toggle("hidden", !open); - leftChevron!.classList.toggle("hidden", open); - rightChevron!.classList.toggle("hidden", !open); - toc.classList[open ? "add" : "remove"](...openTocClasses); - toc.classList[open ? "remove" : "add"](...closedTocClasses); - tocButton!.classList.toggle("-ml-8", open); - tocButton!.classList.toggle("-ml-4", !open); - article!.classList.toggle("lg:w-toc-open-article", open); - article!.classList.toggle("lg:w-toc-closed-article", !open); - }; - - toggleMenu(storeValue !== "false" && isTocOpen, false); - - tocButton!.addEventListener("click", () => { - toggleMenu(!isTocOpen, true); - }); - - const debounce = (func: Function, wait: number, immediate: boolean) => { - let timeout: any; - return (...args: any) => { + this.tocList?.classList.toggle("hidden", !open); + this.tocHeader?.classList.toggle("hidden", !open); + this.leftChevron?.classList.toggle("hidden", open); + this.rightChevron?.classList.toggle("hidden", !open); + this.toc?.classList[open ? "add" : "remove"](...this.openTocClasses); + this.toc?.classList[open ? "remove" : "add"](...this.closedTocClasses); + this.tocButton?.classList.toggle("-ml-8", open); + this.tocButton?.classList.toggle("-ml-4", !open); + this.article?.classList.toggle("lg:w-toc-open-article", open); + this.article?.classList.toggle("lg:w-toc-closed-article", !open); + } + + /** + * Debounces functions to reduce performance impact + * @param func The function to be debounced + * @param wait The amount of time to wait before timeout + * @param immediate Whether the function needs to be called immediately + * @returns The debounced function + */ + private debounce(func: Function, wait: number, immediate: boolean) { + let timeout: number | null = null; + return (...args: any[]) => { const later = () => { timeout = null; if (!immediate) func(...args); }; const callNow = immediate && !timeout; - clearTimeout(timeout); - timeout = setTimeout(later, wait); + if (timeout) clearTimeout(timeout); + timeout = window.setTimeout(later, wait); if (callNow) func(...args); }; - }; + } - const handleResize = debounce( + private handleResize = this.debounce( () => { - if (!didUpdateStore) { + if (!this.didUpdateStore) { const smallScreen = window.innerWidth < 1440; const verySmallScreen = window.innerWidth < 768; const bigScreen = window.innerWidth > 1600; if (smallScreen && !verySmallScreen) { - setTimeout(() => toggleMenu(false, false), 100); + setTimeout(() => this.toggleMenu(false, false), 100); } else if (!smallScreen && !verySmallScreen && !bigScreen) { - setTimeout(() => toggleMenu(true, false), 100); + setTimeout(() => this.toggleMenu(true, false), 100); } } }, @@ -165,10 +186,34 @@ const t = useTranslations(lang as keyof Locales); true, ); - window.addEventListener("resize", handleResize); + private handleScroll = this.debounce(handleScrollSpy, 100, true); - const handleScroll = debounce(handleScrollSpy, 100, true); + /** + * Initializes the ToC controller by setting initial values and assigning handlers + */ + public initialize(): void { + // Don't execute if there's no ToC on the page + if (!this.toc) return; + // Initial setup based on store value and viewport width + const storeValue = $tocOpen.get(); + this.toggleMenu(storeValue !== "false" && this.isTocOpen, false); + + // Event listener for the toggle button + this.tocButton?.addEventListener("click", () => { + this.toggleMenu(!this.isTocOpen, true); + }); + + // Handle window resize + window.addEventListener("resize", this.handleResize); + + // Handle scroll spy + requestAnimationFrame(this.handleScroll); + } + } + + document.addEventListener("DOMContentLoaded", () => { + const controller = new TocController(); - requestAnimationFrame(handleScroll); + controller.initialize(); }); diff --git a/src/components/Tabs.astro b/src/components/Tabs.astro index 7d3cf982d7..4730103fc6 100644 --- a/src/components/Tabs.astro +++ b/src/components/Tabs.astro @@ -1,6 +1,6 @@ --- import { extractTabProps } from "./utils/extractTabProps"; -import { randomUUID } from "crypto"; +import { v4 as uuidv4 } from "uuid"; let content = ""; @@ -9,7 +9,7 @@ if (Astro.slots.has("default")) { } const { tabs, updatedContent } = await extractTabProps(content); -const uniqueId = randomUUID(); +const uniqueId = uuidv4(); ---
@@ -131,11 +131,189 @@ const uniqueId = randomUUID(); diff --git a/src/components/Version/ApiVersionSwitch.tsx b/src/components/Version/ApiVersionSwitch.tsx deleted file mode 100644 index a99010a334..0000000000 --- a/src/components/Version/ApiVersionSwitch.tsx +++ /dev/null @@ -1,116 +0,0 @@ -import { type FC, useEffect, useCallback } from "react"; -import { ComboBox } from "@adjust/components"; -import { useStore } from "@nanostores/react"; - -import type { Locales } from "@i18n/locales"; -import { useTranslations } from "@i18n/utils"; -import { getCurrentPage } from "@utils/helpers/navigation/getCurrentPage"; -import type { Option } from "@adjust/components/build/ComboBox/ComboBox"; -import { - $versions, - changeVersionValue, - updateVersionsItems, - type VersionStore, -} from "@store/apiVersionsStore"; -import type { CollectionEntry } from "astro:content"; -import type { NavigationData } from "@utils/helpers/navigation/types"; - -interface VersionSwitchProps { - lang: string; - redirects: CollectionEntry<"docs">["data"]["redirects"]; - apiVersions: NavigationData["versions"]["api"]; -} - -const VersionSwitch: FC = ({ - lang, - apiVersions, - redirects, -}) => { - const t = useTranslations(lang as keyof Locales); - const versions = useStore($versions); - - const handleVersionChange = useCallback( - (newVersion: VersionStore["currentVersion"]) => { - changeVersionValue(newVersion); - - const redirectValue = (redirects as { [key: string]: string })?.[ - newVersion.value - ]; - - const href = location.href; - if (newVersion.value !== versions.currentVersion.value) { - if (redirectValue) { - return (location.href = redirectValue); - } - - const defaultVersionReg = /\/(\w*)v\d/gi; - const versionReg = /\/api\/(\w*)(\/|$)/gi; - - if (newVersion.default) { - return (location.href = href.replace(defaultVersionReg, "$1")); - } - - return (location.href = href.replace( - versionReg, - `/api/$1/${newVersion.value}/`, - )); - } - }, - [], - ); - - const handleUrlVersion = () => { - const url = location.href; - const urlVersion = url.match(/(\w*)v\d/gi); - if ( - !getCurrentPage(url).endsWith("/api") && - !versions.currentVersion.value - ) { - // if we have a version in the URL and it`s not the current version we change current selected to this version - if ( - urlVersion?.length && - versions.currentVersion.value !== urlVersion[0] - ) { - const version = apiVersions!.find( - (item) => item.value === urlVersion[0], - ); - if (version) { - return changeVersionValue(version); - } - } - // we change the version to the default if we can`t update the version by the current URL - if ( - !urlVersion?.length || - !apiVersions!.find((item) => item.value === urlVersion[0]) - ) { - return changeVersionValue(apiVersions!.find((item) => item.default)!); - } - } - }; - - useEffect(() => { - handleUrlVersion(); - }, []); - - // need to add versions from the page data to the SDK versions store - useEffect(() => { - updateVersionsItems(apiVersions as Option[]); - }, []); - - const label = t("apiversionswitch.label"); - - return ( -
- - -
- ); -}; - -export default VersionSwitch; diff --git a/src/components/Version/SdkVersionSwitch.astro b/src/components/Version/SdkVersionSwitch.astro deleted file mode 100644 index 745818bd18..0000000000 --- a/src/components/Version/SdkVersionSwitch.astro +++ /dev/null @@ -1,137 +0,0 @@ ---- -import type { Locales } from "@i18n/locales"; -import { useTranslations } from "@i18n/utils"; -import { findEntryBySlug } from "@utils/helpers/navigation/findEntryBySlug"; -import { uniqueSdkVersions } from "@utils/helpers/navigation/getUniqueVersions"; - -interface Props { - lang: string; - currentPage: string; -} - -const { lang, currentPage } = Astro.props; -const t = useTranslations(lang as keyof Locales); - -// Get current page data and redirects from frontmatter -const pageData = findEntryBySlug(currentPage); -const redirects = pageData?.redirects || {}; -const defaultVersion = - (uniqueSdkVersions && uniqueSdkVersions.find((v) => v.default)?.value) || ""; ---- - -
- -
- - -
-
- - diff --git a/src/components/utils/TabGroup.ts b/src/components/utils/TabGroup.ts deleted file mode 100644 index bbf3da5d10..0000000000 --- a/src/components/utils/TabGroup.ts +++ /dev/null @@ -1,189 +0,0 @@ -interface TabHeader { - syncKey?: string; - tabId: string; - element: HTMLElement; -} - -interface TabContent { - id: string; - syncKey?: string; - element: HTMLElement; -} - -/** - * Contains tab groups for synchronized and non-synchronized content - */ -export class TabGroup { - // To make syncing easier, store all TabGroup instances in an array - static tabGroups: TabGroup[] = []; - - id: string; - element: HTMLElement; - headers: TabHeader[]; - tabs: TabContent[]; - - /** - * Create a TabGroup by passing a .tab-group element - * @param element The tab group parent element - */ - constructor(element: HTMLElement) { - this.id = element.id; - this.element = element; - - // Initialize headers and tabs - this.headers = Array.from( - element.querySelectorAll(":scope > .tab-row > .tab-header"), - ).map( - (tab) => ({ - element: tab as HTMLElement, - tabId: tab.getAttribute("data-id")!, - syncKey: tab.getAttribute("data-sync") || "", - }), - ); - - this.tabs = Array.from( - element.querySelectorAll(":scope > .tab-content-block > .tab-content"), - ).map((content) => ({ - element: content as HTMLElement, - id: content.id, - syncKey: content.getAttribute("data-sync") || "", - })); - - // Add an event listener to each header to facilitate switching - this.headers.forEach((header, index) => { - header.element.addEventListener("click", () => { - TabGroup.syncTabs(this, header.tabId, header.syncKey); - }); - - header.element.addEventListener("keydown", (event) => { - this.handleKeydown(event, index); - }); - }); - - // Automatically activate the first tab - this.activateFirstTab(); - - // Add this instance to the static list of TabGroups - TabGroup.tabGroups.push(this); - } - - /** - * Sets the first tab in each tab group to active by default - */ - activateFirstTab(): void { - if (this.headers.length > 0) { - this.headers[0].element.classList.add("active"); - this.headers[0].element.setAttribute("aria-selected", "true"); - } - if (this.tabs.length > 0) { - this.tabs[0].element.classList.remove("hidden"); - } - } - - /** - * Synchronizes tabs with a matching syncKey - * @param activeGroup The current TabGroup - * @param tabId The ID of the selected tab - * @param syncKey The syncKey of the selected tab - */ - static syncTabs( - activeGroup: TabGroup, - tabId: string, - syncKey?: string, - ): void { - if (syncKey) { - // Track if any matching syncKey was found in other groups - let syncFound = false; - - // Loop through all TabGroups to apply syncing based on syncKey - for (const group of TabGroup.tabGroups) { - const matchedHeader = group.headers.find((header) => - header.syncKey === syncKey - ); - const matchedTab = group.tabs.find((tab) => - tab.syncKey === syncKey - ); - - if (matchedHeader && matchedTab) { - syncFound = true; - - // Update headers in this group - group.headers.forEach((header) => { - const isActive = header === matchedHeader; - header.element.classList.toggle( - "active", - isActive, - ); - header.element.setAttribute( - "aria-selected", - String(isActive), - ); - }); - - // Update tabs in this group - group.tabs.forEach((tab) => { - tab.element.classList.toggle("hidden", tab !== matchedTab); - }); - } - } - - // If no matching syncKey was found in any other group, fall back to updating only the active group - if (!syncFound) { - activeGroup.updateTabsByTabId(tabId); - } - } else { - // No syncKey provided, so update only the clicked group based on tabId - activeGroup.updateTabsByTabId(tabId); - } - } - - /** - * Update tab appearance by tab ID - * @param tabId The ID of the selected tab - */ - private updateTabsByTabId(tabId: string): void { - // Update headers in this group - this.headers.forEach((header) => { - const isActive = header.tabId === tabId; - header.element.classList.toggle("active", isActive); - header.element.setAttribute("aria-selected", String(isActive)); - }); - - // Update tabs in this group - this.tabs.forEach((tab) => { - tab.element.classList.toggle("hidden", tab.id !== tabId); - }); - } - - /** - * Enables using arrow keys to select tabs - * @param event The keyboard event (key) - * @param currentIndex The currently selected tab - */ - private handleKeydown(event: KeyboardEvent, currentIndex: number): void { - const { headers } = this; - let newIndex = currentIndex; - - switch (event.key) { - case "ArrowRight": - newIndex = (currentIndex + 1) % headers.length; - headers[newIndex].element.focus(); - break; - - case "ArrowLeft": - newIndex = (currentIndex - 1 + headers.length) % headers.length; - headers[newIndex].element.focus(); - break; - - case "Enter": - case " ": - event.preventDefault(); - TabGroup.syncTabs( - this, - headers[currentIndex].tabId, - headers[currentIndex].syncKey, - ); - break; - } - } -} diff --git a/src/components/utils/convertCase.ts b/src/components/utils/convertCase.ts deleted file mode 100644 index 4aba18f3e9..0000000000 --- a/src/components/utils/convertCase.ts +++ /dev/null @@ -1,4 +0,0 @@ -export function toSnakeCase(string: string): string { - if (!string) return string; // Handle empty strings - return string.toLowerCase().replace(/\s+/g, "_"); -} diff --git a/src/components/utils/queryParamHelpers.ts b/src/components/utils/queryParamHelpers.ts deleted file mode 100644 index 0f81484fb7..0000000000 --- a/src/components/utils/queryParamHelpers.ts +++ /dev/null @@ -1,17 +0,0 @@ -export const getQueryParameter = (name: string): string | null => { - if (!name) return null; // Handle empty string or null/undefined parameter name - - const urlParams = new URLSearchParams(window.location.search); - return urlParams.get(name); -}; - -export const updateQueryParameter = (name: string, value: string): void => { - if (!name || value == null) return; // Handle null/undefined parameter name or value - - const url = new URL(window.location.href); - url.searchParams.set(name, value); - window.history.replaceState(null, "", url.toString()); - - // Notify the browser when the URL value has changed - window.dispatchEvent(new CustomEvent("urlChange", { detail: { name, value } })); -}; diff --git a/src/i18n/translations/en.json b/src/i18n/translations/en.json index 41f06937c6..7cf26581e1 100644 --- a/src/i18n/translations/en.json +++ b/src/i18n/translations/en.json @@ -43,7 +43,6 @@ "minorversion.removed": "Removed in ${version}", "minorversion.release-notes": "Check the release notes for this version", "sdkversionswitch.label": "Select your SDK version:", - "apiversionswitch.label": "Select your API version:", "table.search-label": "Search", "toc.header": "Table of contents", "toc.toggle-label": "Toggle table of contents", diff --git a/src/i18n/translations/ja.json b/src/i18n/translations/ja.json index 1bdd3a851e..262c8665f1 100644 --- a/src/i18n/translations/ja.json +++ b/src/i18n/translations/ja.json @@ -43,7 +43,6 @@ "minorversion.removed": "${version}で削除", "minorversion.release-notes": "このバージョンのリリースノートを確認", "sdkversionswitch.label": "SDKバージョンを選択:", - "apiversionswitch.label": "APIバージョンを選択:", "table.search-label": "検索", "toc.header": "目次", "toc.toggle-label": "目次を見る", diff --git a/src/i18n/translations/ko.json b/src/i18n/translations/ko.json index 52b1f7c3bb..4809f108c8 100644 --- a/src/i18n/translations/ko.json +++ b/src/i18n/translations/ko.json @@ -43,7 +43,6 @@ "minorversion.removed": "${version}에서 삭제됨", "minorversion.release-notes": "이 버전의 릴리스 노트를 확인하세요", "sdkversionswitch.label": "SDK 버전을 선택합니다.", - "apiversionswitch.label": "API 버전을 선택합니다.", "table.search-label": "검색", "toc.header": "목차", "toc.toggle-label": "토글 목차", diff --git a/src/i18n/translations/zh.json b/src/i18n/translations/zh.json index 46364d8e91..1277f42776 100644 --- a/src/i18n/translations/zh.json +++ b/src/i18n/translations/zh.json @@ -43,7 +43,6 @@ "minorversion.removed": "于 ${version} 中删除", "minorversion.release-notes": "请查看本版本的发布说明", "sdkversionswitch.label": "选择您的 SDK 版本:", - "apiversionswitch.label": "选择您的 API 版本:", "table.search-label": "搜索", "toc.header": "目录", "toc.toggle-label": "Toggle table of contents", diff --git a/src/layouts/MainLayout.astro b/src/layouts/MainLayout.astro index 840feb78d4..62167e5f5b 100644 --- a/src/layouts/MainLayout.astro +++ b/src/layouts/MainLayout.astro @@ -6,7 +6,7 @@ import { languageTree } from "@utils/helpers/navigation/buildLanguageTree"; import HeadCommon from "../components/HeadCommon.astro"; import HeadSEO from "../components/HeadSEO.astro"; import PageContent from "../components/Layout/PageContent/PageContent.astro"; -import PageBreadcrumbs from "@components/Layout/PageBreadcrumbs/PageBreadcrumbs.astro"; +import PageBreadcrumbs from "@components/PageBreadcrumbs.astro"; import { type Locales } from "@i18n/locales"; import { useTranslations } from "@i18n/utils"; import MobileHeader from "@components/Layout/Header/MobileHeader.astro"; diff --git a/src/store/apiVersionsStore.ts b/src/store/apiVersionsStore.ts deleted file mode 100644 index 0e884d7e9b..0000000000 --- a/src/store/apiVersionsStore.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { map } from "nanostores"; -import { uniqBy } from "lodash-es"; -import type { Option } from "@adjust/components/build/ComboBox/ComboBox"; - -export interface VersionStore { - items: Option[] & { - default?: boolean; - }; - currentVersion: Option & { - default?: boolean; - }; -} - -export const $versions = map({ - items: [], - currentVersion: { label: "v1", value: "v1" }, -}); - -export const changeVersionValue = (version: Option) => { - const currentStore = $versions.get(); - $versions.set({ ...currentStore, currentVersion: version }); -}; - -export const updateVersionsItems = (newItems: Option[]) => { - const currentStore = $versions.get(); - const uniqueItems = uniqBy([...currentStore.items, ...newItems], "value"); - $versions.set({ ...currentStore, items: uniqueItems }); -};