> ## Documentation Index
> Fetch the complete documentation index at: https://www.ayrshare.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# أداة Ayrshare Connect

> اسمح لمستخدميك بربط الحسابات الاجتماعية من داخل لوحة التحكم الخاصة بك، بوسم سكربت واحد وأزرارنا مضمّنة في صفحتك.

export const PlansAvailable = ({plans = [], maxPackRequired}) => {
  let displayPlans = plans;
  if (plans && plans.length === 1) {
    const lowerCasePlan = plans[0].toLowerCase();
    if (lowerCasePlan === "business") {
      displayPlans = ["Launch", "Business", "Enterprise"];
    } else if (lowerCasePlan === "premium") {
      displayPlans = ["Premium", "Launch", "Business", "Enterprise"];
    }
  }
  return <Note>
Available on {displayPlans.length === 1 ? "the " : ""}
{displayPlans.join(", ").replace(/\b\w/g, l => l.toUpperCase())}{" "}
{displayPlans.length > 1 ? "plans" : "plan"}.

{maxPackRequired && <span onClick={() => window.open('https://www.ayrshare.com/docs/additional/maxpack', '_self')} className="flex items-center mt-2 cursor-pointer">
 <span className="px-1.5 py-0.5 rounded text-sm" style={{
    backgroundColor: '#C264B6',
    color: 'white',
    fontSize: '12px'
  }}>
   Max Pack required
 </span>
</span>}
</Note>;
};

<PlansAvailable plans={["business"]} maxPackRequired={true} />

تضع أداة Ayrshare Connect أزرار الربط الخاصة بنا **داخل لوحة التحكم الخاصة بك**. تحمّل سكربتًا
واحدًا، وتضع فتحة (slot) حيثما يليق موضع شبكة في تخطيطك، فنعرض هناك زرًا يُظهر مسبقًا ما إذا
كان الحساب متصلًا. ينقر مستخدمك عليه ويربط الحساب دون مغادرة صفحتك — على الأكثر نافذة منبثقة
واحدة، هي نافذة الشبكة نفسها.

أنت لا تكتب أي معالجة للنوافذ المنبثقة، ولا استدعاءات OAuth راجعة، ولا تحديثًا للجلسة، ولا
منطقًا خاصًا بكل شبكة. وعندما تغيّر شبكة شيئًا من جانبها، يصل الإصلاح داخل إطاراتنا لحظة نشرنا
له؛ وأنت لا تعيد نشر أي شيء.

## أي سطح تريد

| السطح                                                                                                                         | ما يراه مستخدمك                                                      | العلامة البيضاء                                             | اختره عندما                                                                                              |
| ----------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- | ----------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| **الأداة — إطارات مضمّنة** ([`mount()`](#mount-a-slot))                                                                       | أزرارنا مدمجة في تخطيط صفحتك؛ لا نافذة منبثقة حتى نافذة الشبكة نفسها | **الأقوى.** صفحتك وخطوطك وألوانك، ومستخدمك لا يغادرها أبدًا | لديك لوحة تحكم فيها صف لكل شبكة وتريد أن يجري الربط في مكانه. يتطلب Max Pack.                            |
| **الأداة — زرك الخاص** ([`popup()`](#your-own-button))                                                                        | زرك، ثم نافذة منبثقة واحدة للشبكة                                    | **قوي.** النافذة المنبثقة نافذتنا، لكنها وجيزة وترث مظهرك   | تريد زرك وتنسيقك الخاصين، ولا إطارات في تخطيطك. يتطلب Max Pack.                                          |
| **صفحة الربط المستضافة** ([كيفية الاستخدام](/docs/multiple-users/api-integration-business#single-sign-on-with-jwt-authentication)) | صفحة نستضيفها نحن، تحمل شعارك وألوانك وCSS المخصص الخاص بك           | **الأضعف.** إنها صفحتنا، ويغادر مستخدمك صفحتك لاستخدامها    | تريد رابطًا واحدًا لتوزيعه، أو تجري التأهيل عبر البريد الإلكتروني. لا شيء لبنائه، ولا حاجة إلى Max Pack. |

<div className="my-8">
  <Frame caption="الإطارات المضمّنة: بطاقاتنا معروضة داخل تخطيطك، فتحة لكل شبكة أو فتحة واحدة لعدة شبكات.">
    <img src="https://mintcdn.com/ayrshare-docs/-2tpx3mFy9vWIObd/images/multiple-users/connect-widget-frames.webp?fit=max&auto=format&n=-2tpx3mFy9vWIObd&q=85&s=d6c26228a418421772f753f31b0dfc59" alt="A customer dashboard with Ayrshare Connect tiles for Instagram, TikTok and LinkedIn embedded in a card" width="2400" height="1120" data-path="images/multiple-users/connect-widget-frames.webp" />
  </Frame>
</div>

<div className="my-8">
  <Frame caption="زرك الخاص: أنت تعرض الزر، ونافذة منبثقة وجيزة من عندنا تتولى الشبكة.">
    <img src="https://mintcdn.com/ayrshare-docs/-2tpx3mFy9vWIObd/images/multiple-users/connect-widget-popup.webp?fit=max&auto=format&n=-2tpx3mFy9vWIObd&q=85&s=b68021d477703d97a5994ee85d299be6" alt="A customer dashboard with its own Connect buttons and an Ayrshare popup showing the Facebook hand-off screen" width="2880" height="1317" data-path="images/multiple-users/connect-widget-popup.webp" />
  </Frame>
</div>

<div className="my-8">
  <Frame caption="صفحة الربط المستضافة: صفحة نستضيفها نحن، تحمل شعارك وألوانك، يغادر مستخدمك تطبيقك لاستخدامها.">
    <img src="https://mintcdn.com/ayrshare-docs/-2tpx3mFy9vWIObd/images/multiple-users/connect-widget-hosted.webp?fit=max&auto=format&n=-2tpx3mFy9vWIObd&q=85&s=4d22a992f6e70808fd9ad9f065ed3879" alt="The hosted social linking page showing every available network" width="2336" height="1906" data-path="images/multiple-users/connect-widget-hosted.webp" />
  </Frame>
</div>

<Note>
  صفّا الأداة هما **تكامل واحد** لا اثنان. استدعاء `init` واحد يمنحك الاثنين معًا: ركّب الإطارات
  حيث تريد أزرارنا، واستدعِ `popup()` من زرك الخاص في أي مكان آخر. يتشاركان جلسة واحدة ويبلّغان
  على المعالجات نفسها.

  [الوضع المباشر (Direct mode)](/docs/multiple-users/connect-direct-mode) هو النافذة المنبثقة نفسها
  **دون** السكربت الخاص بنا — لصفحة ذات Content-Security-Policy صارمة، أو صفحة تُعرض من الخادم،
  أو تطبيق أصلي. هناك تفتح النافذة المنبثقة وتراقبها بنفسك.
</Note>

## إضافة السكربت

ثبّت إصدارًا مع الـ hash الخاص به، أو تتبّع قناة دون hash. لا تجمع بينهما أبدًا — فسمة
`integrity` على عنوان URL متحرك تتوقف عن العمل عند إصدارنا التالي، لأن الملف الذي تُسمّيه قد
تغيّر تغيّرًا مشروعًا.

```html Pinned version theme={"system"}
<script
  src="https://app.ayrshare.com/ayrshare-connect/1.2.0/widget.js"
  integrity="sha384-qQ/of8CnYj26nF9RkQ6qk3D1vvzWesu7mpBK6MFK2D0EmmgRJHfbDmRowFBfltmz"
  crossorigin="anonymous"
></script>
```

```html Tracking v1 theme={"system"}
<script src="https://app.ayrshare.com/ayrshare-connect/v1/widget.js" crossorigin="anonymous"></script>
```

| المسار                                  | التخزين المؤقت              | `integrity`     |
| --------------------------------------- | --------------------------- | --------------- |
| `/ayrshare-connect/<version>/widget.js` | ثابت (immutable)، سنة واحدة | **نعم** — ثبّته |
| `/ayrshare-connect/v1/widget.js`        | خمس دقائق                   | لا              |
| `/ayrshare-connect/latest/widget.js`    | خمس دقائق                   | لا              |

**`v1` هي القناة التي نوصي بها.** تلتقط الإصلاحات لكنها لا تعبر أبدًا تغييرًا كاسرًا. أما
`latest` فتعبر الإصدارات الرئيسية بحكم تعريفها، لذا ستسلّم صفحتك في نهاية المطاف إصدارًا لم
تراجع سلوكه.

يُنشر hash كل إصدار في
[`manifest.json`](https://app.ayrshare.com/ayrshare-connect/manifest.json)، الذي يُسمّي أيضًا ما
تقدّمه كل قناة حاليًا:

```json manifest.json theme={"system"}
{
  "versions": {
    "1.2.0": { "integrity": "sha384-qQ/of8CnYj26nF9RkQ6qk3D1vvzWesu7mpBK6MFK2D0EmmgRJHfbDmRowFBfltmz" }
  },
  "latest": "1.2.0",
  "channels": { "v1": "1.2.0", "latest": "1.2.0" }
}
```

تبدأ كل حزمة أيضًا بتعليق يُسمّي إصدارها، وهو أسرع وسيلة لإخبارنا بما تشغّله صفحة فعليًا:

```js theme={"system"}
/*! ayrshare-connect 1.2.0 */
```

### Content-Security-Policy

إذا كانت صفحتك ترسل Content-Security-Policy، فهي تحتاج إلى **إدخالين**، كلاهما يُسمّي المضيف
الذي تحمّل السكربت منه:

```
script-src https://app.ayrshare.com;
frame-src  https://app.ayrshare.com;
```

هذه هي القائمة بأكملها. لا تحتاج إلى **أي إدخال `connect-src`** لأجلنا — تصل إطاراتنا إلى API
الخاصة بنا من داخلها هي، لا من صفحتك — و**لا إدخال للنوافذ المنبثقة**، فهي نوافذ من المستوى
الأعلى لا تحكمها سياستك. كلا الإدخالين مُقاس أثرهما: إزالة `script-src` تحجب السكربت، وإزالة
`frame-src` تحجب الإطار.

## بدء نسخة (Instance)

‏`session` هو الخيار الوحيد المطلوب. يُستدعى **مرة واحدة لكل نسخة**، لا مرة لكل تركيب (mount)،
ويجب أن يعيد استجابة خادمك الخلفي لـ
[إنشاء Link Session](/docs/apis/profiles/create-link-session) مع `mode: "connect"` —
‏`{ sessionId, token, expiresAt }` — تمامًا كما أُعيدت.

```javascript Your page theme={"system"}
const connect = AyrshareConnect.init({
  session: () => fetch("/my-api/ayrshare-session").then(r => r.json()),
  appearance: { "--ayr-connect-accent": "#0B7A6C" },
  maxHeight: 800,
});
```

```javascript Your backend theme={"system"}
app.get("/my-api/ayrshare-session", async (req, res) => {
  const response = await fetch("https://api.ayrshare.com/api/profiles/link-sessions", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${process.env.AYRSHARE_API_KEY}`,
      "Profile-Key": profileKeyFor(req.user),
    },
    body: JSON.stringify({ mode: "connect", origin: "https://app.example.com" }),
  });

  res.json(await response.json());
});
```

جلسة الأداة لا تُسمّي **أي** `network` — فهي تفوّض كل شبكة يسمح بها حسابك، ويُقرَّر ما يظهر
منها عند كل تركيب، في صفحتك أنت. لكنها تحمل `origin`، وهو الشيء الوحيد الذي يجعل الإطارات
تُعرض أصلًا: يتحقق الإطار من الصفحة التي تضمّنه مقابل تلك القيمة ويرفض العرض في أي مكان آخر.

<Warning>
  أنشئ الجلسة على خادمك. الاستدعاء يحتاج إلى مفتاح API الخاص بك، والتوكن الذي يعيده يُسجّل
  دخول مستخدمك إلى User Profile الخاص به — تعامل معه كما تتعامل مع كلمة المرور.
</Warning>

نستدعي `session` مجددًا قبل انتهاء صلاحية التوكن، فتظل الأداة تعمل في صفحة مفتوحة طوال اليوم.
الاستدعاء الذي يُرفض، أو لا يعيد توكنًا، تُعاد محاولته مرتين أخريين — بعد 0.5 ثانية ثم ثانية
واحدة — قبل أن نستسلم ونُطلق `error`. أي أن التحديث الواحد يكلّف على الأكثر ثلاثة استدعاءات
لنقطة النهاية الخاصة بك.

| الخيار       | الافتراضي   | الوظيفة                                                               |
| ------------ | ----------- | --------------------------------------------------------------------- |
| `session`    | —           | **مطلوب.** يعيد جلسة ربط بوضع connect.                                |
| `appearance` | افتراضياتنا | رموز التصميم، تُطبَّق داخل كل إطار. راجع [المظهر](#appearance).       |
| `css`        | لا شيء      | سلسلة CSS تُطبَّق داخل كل إطار. راجع [CSS مخصص](#custom-css).         |
| `maxHeight`  | `600`       | إلى أي ارتفاع يمكن أن ينمو الإطار قبل أن يتمرّر داخليًا بدلًا من ذلك. |

<h2 id="mount-a-slot">
  تركيب فتحة
</h2>

استدعاء `mount` واحد لكل فتحة. اطلب شبكة واحدة أو عدة شبكات أو كل ما تسمح به الجلسة —
فمستوى التفصيل بيدك، ويمكن أن تكون الفتحة صفًا واحدًا في جدول موجود أو لوحة واحدة تحوي كل شيء.

```javascript theme={"system"}
connect.mount("#instagram-slot", { network: "instagram" });
connect.mount("#some-slot", { networks: ["facebook", "tiktok", "x"] });
connect.mount("#everything");

const row = connect.mount(document.querySelector("#tall"), { maxHeight: 1200 });
row.unmount();
```

يقبل `mount` مُحدِّد CSS أو عنصرًا، ويعيد `{ unmount, element }`. ويرمي خطأً إذا لم يطابق
الهدف أي شيء — وهذا في الغالب فتحة لم توجد بعد، لذا ركّب بعد أن تكون علاماتك (markup) في
المستند.

كل تركيب هو iframe واحد. يُبلغنا عن ارتفاعه فنعيد تحجيمه ليطابقه، فيُعاد تدفق تخطيطك مع
تغيّر محتوانا؛ وبعد `maxHeight` يتمرّر الإطار داخليًا بدلًا من أن يفيض خارج صفحتك. **أضيق فتحة
ندعمها هي 300px.**

مفاتيح الشبكات هي مفاتيح Ayrshare نفسها، وتعمل التهجئات البديلة أيضًا: `instagram`
و`instagramapi` كلاهما يعني `instagramApi`، و`x` يعني `twitter`. المفتاح الذي ليس شبكة لا
يعرض أي بطاقة.

<h2 id="your-own-button">
  زرك الخاص
</h2>

العميل الذي يفضّل استخدام زره الخاص بدلًا من أحد إطاراتنا يستدعي `popup` بدلًا من ذلك. فهو
يشغّل التدفق نفسه، على الجلسة نفسها، ويبلّغ على المعالجات نفسها.

<Warning>
  **استدعه مباشرةً داخل معالج النقر، دون أي `await` قبله.** لا يسمح المتصفح بنافذة منبثقة إلا
  وهو لا يزال يعالج نقرة مستخدمك، وهذا الإذن لا ينجو من `await`. ولا شيء يحتاج إلى انتظار على
  أي حال — فالجلسة أُنشئت عند `init`.
</Warning>

```javascript theme={"system"}
linkedInButton.addEventListener("click", () => {
  connect.popup({ network: "linkedin" });
});
```

يعيد `popup` القيمة `{ close(), network }`، ويعيد **دائمًا** مقبضًا — حتى بعد نافذة منبثقة
محجوبة، حيث لا يفعل `close()` شيئًا — بحيث لا تضطر شيفرتك أبدًا إلى فحص القيمة الفارغة قبل
استدعاء `close()`.

كل شبكة تعمل هنا، بما فيها الشبكات التي يُنهي الإطار عمله فيها داخل لوحته: يعرض Facebook شاشة
شرح التسليم في النافذة المنبثقة، ويعرض Bluesky وX نموذج بيانات الاعتماد، بينما تخرج LinkedIn
وPinterest وYouTube وGoogle Business إلى الشبكة وتعود.

يرمي بشكل متزامن للأمور الثلاثة التي تُعدّ أخطاء برمجية — لا `network`، أو نسخة مدمّرة، أو
جلسة لم تُحلّ بعد. أما النافذة المنبثقة المحجوبة فهي **ليست** منها: تلك تُطلق `error` مع
`reason: "popupBlocked"`، لأن مستخدمك لم يرتكب أي خطأ.

نافذة منبثقة واحدة على الأكثر تكون مفتوحة في أي لحظة. الاستدعاء الثاني يُغلق الأولى ويبلّغ
عنها بـ `cancelled` مع `reason: "superseded"`. أما النافذة المنبثقة التي فتحها أحد **إطاراتنا**
فهي شيء مختلف ولا تُمسّ أبدًا، فلا يمكن لزرك أن يُلغي تدفقًا يجري داخل فتحة مركّبة.

<Note>
  ما إذا كان يجوز للجلسة ربط شبكة ما هو جواب **الخادم**، لا السكربت. الجلسة المحصورة في
  Bluesky التي يُطلب منها LinkedIn تحصل على رفض يُعرض في النافذة المنبثقة ويُبلَّغ عنه كـ
  `error`. السكربت لا يتحقق إلا من أن شبكة قد سُمّيت أصلًا.
</Note>

## React

السكربت مستقل عن أطر العمل، لذا لا يحتاج React إلى أي شيء خاص منا — لكن أربعة أمور في دورة
حياته تستحق ضبطها صحيحًا من المرة الأولى.

حمّل السكربت **مرة واحدة**، خارج شجرة مكوّناتك. في Next.js يعني ذلك `next/script` في التخطيط
الجذري؛ وفي Vite أو Create React App وسم في `index.html`. تحميله لكل مكوّن يعيد تشغيله عند كل
تركيب.

```jsx ConnectAccounts.jsx theme={"system"}
import { useEffect, useRef, useState } from "react";

export function ConnectAccounts() {
  const slot = useRef(null);
  const [linked, setLinked] = useState([]);

  useEffect(() => {
    // Inside the effect, so the ref is attached: mount() throws if its target
    // does not exist yet, which is exactly what happens if you call it during render.
    const connect = window.AyrshareConnect.init({
      session: () => fetch("/my-api/ayrshare-session").then(r => r.json()),
      appearance: { "--ayr-connect-accent": "#0B7A6C" },
    });

    connect.mount(slot.current, { networks: ["instagram", "tiktok", "x"] });

    const stop = connect.on("success", ({ network }) => {
      setLinked(current => [...current, network]);
    });
    // `success` is one of ten events the widget reports. See Events below for
    // the full list, including `state`, which replaces polling.

    // destroy() takes the frames, the message listener and the timers with it.
    // Without this, a route change leaves all three behind.
    return () => {
      stop();
      connect.destroy();
    };
  }, []);

  return <div ref={slot} />;
}
```

<Warning>
  **لا تُعِد استخدام نسخة بعد `destroy()` أبدًا.** النسخة المدمّرة تبقى مدمّرة — يرمي `popup()`
  عليها خطأً، ولن يُعيدها `mount()` إلى الحياة. أنشئ نسخة جديدة في تشغيل الـ effect التالي، وهو
  ما تفعله الشيفرة أعلاه.
</Warning>

نتيجتان لهذا النمط، ولا واحدة منهما خلل:

* **في بيئة التطوير سترى استدعاء الجلسة يُطلق مرتين.** يشغّل Strict Mode في React التأثيرات
  بترتيب تركيب ← تفكيك ← تركيب، فتُنشأ النسخة وتُدمّر وتُنشأ مجددًا. التنظيف أعلاه يجعل ذلك
  آمنًا؛ ويكلّف استدعاءً إضافيًا واحدًا لخادمك الخلفي في التطوير ولا شيء في الإنتاج.
* **أبقِ اعتماديات الـ effect ثابتة.** المصفوفة الحرفية المُمرَّرة مباشرةً إلى `mount` من عرض
  (render) للمكوّن الأب هي قيمة جديدة في كل مرة، فالـ effect الذي يعتمد عليها يفكّك الأداة
  ويعيد بناءها عند كل عرض. خزّنها بـ memoization، أو أبقِها ثابتة كما في المثال أعلاه.

## الأحداث

اشترك بـ `on`، الذي يعيد دالة لإلغاء الاشتراك. تتلقى المعالجات حمولة الحدث والتركيب الذي جاء
منه؛ ويؤدي `off(name, handler)` المهمة نفسها عندما تفضّل تسمية المعالج.

```javascript theme={"system"}
const stop = connect.on("success", ({ network, displayName }, mount) => {
  refreshRow(network, displayName, mount.element);
});
stop();

connect.on("error", ({ network, code, message }) => report(code, message));
connect.destroy(); // every frame, listener and timer
```

عشرة أحداث. كل واحد منها يحمل `network` باستثناء `ready`، وباستثناء النوع الوحيد من `error`
الذي لا يتعلق بشبكة إطلاقًا — راجع [`error` له مصدران](#error-has-two-sources) أدناه.

| الحدث       | متى يُطلق                                           | يحمل أيضًا                                   |
| ----------- | --------------------------------------------------- | -------------------------------------------- |
| `ready`     | إطار مُركّب وجاهز                                   | —                                            |
| `click`     | نقر مستخدمك على شبكة، **في أي من الاتجاهين**        | `action`: ‏`"connect"` أو `"unlink"`         |
| `started`   | محاولة ربط جارية                                    | —                                            |
| `selection` | وصل مستخدمك إلى مُنتقٍ أو نموذج                     | `step`                                       |
| `success`   | الحساب متصل **ومحفوظ**                              | `displayName` (يُحذف عند عدم توفره)، `refId` |
| `unlinked`  | أُزيل حساب متصل، وحُفظت الإزالة                     | —                                            |
| `error`     | فشلت المحاولة                                       | `code`، `message`، `reason`                  |
| `cancelled` | تراجع مستخدمك                                       | `reason`                                     |
| `closed`    | النافذة المنبثقة التي استخدمتها هذه المحاولة أُغلقت | —                                            |
| `state`     | حالة حساب شبكة، عند التركيب وعند كل تغيّر           | `state`، `since`                             |

**أربعة منها نهايات** — `success` و`unlinked` و`error` و`cancelled` — ويصل واحد منها بالضبط
لكل محاولة. أما `closed` فهو إشعار دورة حياة يتبع النهاية ولا يُعدّ نهاية بذاته.

يُطلق `click` **قبل** بدء أي عمل ربط، فهو يبلّغ عن نقرة قد ترفضها لاحقًا نافذة منبثقة محجوبة
أو جلسة ميتة. إنه الحدث المناسب لتحليلاتك الخاصة؛ أما `started` فهو الذي يعني أن محاولة تجري
فعلًا.

### الأسباب

| الحدث       | `reason`        | المعنى                                           |
| ----------- | --------------- | ------------------------------------------------ |
| `error`     | `popupBlocked`  | رفض المتصفح فتح النافذة المنبثقة                 |
| `cancelled` | `popupClosed`   | أغلق مستخدمك النافذة يدويًا                      |
| `cancelled` | `scopesDenied`  | رفض مستخدمك إذنًا طلبته الشبكة                   |
| `cancelled` | `userCancelled` | تراجع مستخدمك، أو استدعت شيفرتك `handle.close()` |
| `cancelled` | `superseded`    | استدعاء `popup()` ثانٍ حلّ محل هذه المحاولة      |

<h3 id="error-has-two-sources">
  لـ `error` مصدران
</h3>

واحد منهما فقط هو فشل ربط، ويحملان حقولًا مختلفة.

* **خطأ الربط** يحمل `network` و`code` والتركيب الذي جاء منه.
* **خطأ الجلسة** — تعذّر علينا إنشاء جلستك أو تحديثها — يحمل `message` فقط، لأنه لم يكن هناك
  شيء يُربط في ذلك الوقت.

فكّك (destructure) بحذر: `code` و`network` قيمتهما `undefined` في النوع الثاني.

### ‏`state` يُغنيك عن الاستطلاع

‏`state` هو قناة البيانات لا تقريرًا عن محاولة. يُطلق كل إطار حدثًا واحدًا لكل شبكة عند تركيبه،
يحمل الحالة الراهنة لتلك الشبكة وطابع `since` الزمني الذي تحملها منه، وحدثًا آخر كلما تغيّرت
حالة — **بما في ذلك التغييرات التي تنشأ من جانبنا**، مثل موت توكن إلى حالة تتطلب إعادة الربط.
فبإمكانك إذًا تشغيل واجهتك كلها من الأداة دون استطلاع أي شيء.

القيم هي التعداد (enum) نفسه الذي تعيده
[`GET /profiles` مع `include=state`](/docs/apis/profiles/get-profiles): ‏`linked` و`unlinked`
و`identityVerificationRequired` و`restricted` و`rateLimited` و`suspended`.

## فك الربط

بطاقاتنا تفكّ الربط كما تربط. ينقر مستخدمك على شبكة متصلة، ويؤكد، فيُزال الحساب:

1. يُطلق `click` مع `action: "unlink"`.
2. يُطلق `unlinked` بمجرد حفظ الإزالة.

فك الربط الذي **يفشل** يبلّغ عنه `error`، والذي يتراجع عنه مستخدمك عند خطوة التأكيد يبلّغ عنه
`cancelled`. لا يوجد حدث منفصل لفشل فك الربط.

<h2 id="appearance">
  المظهر
</h2>

لا تستطيع ورقة أنماط العميل الوصول إلى داخل إطار عابر الأصول (cross-origin)، لذا ينتقل
التنسيق كبيانات نطبّقها نحن داخله. مرّر `appearance` إلى `init` كخصائص CSS مخصصة؛ وكل خاصية
لا نتلقاها تحتفظ بقيمتنا الافتراضية.

```javascript theme={"system"}
const connect = AyrshareConnect.init({
  session: getSession,
  appearance: {
    "--ayr-connect-font-family": "Inter, system-ui, sans-serif",
    "--ayr-connect-surface-bg": "#111318",
    "--ayr-connect-surface-fg": "#F2F3F7",
    "--ayr-connect-accent": "#0B7A6C",
    "--ayr-connect-accent-fg": "#FFFFFF",
    "--ayr-connect-radius": "12px",
  },
});
```

<Warning>
  **اضبط الألوان أزواجًا.** رمز خلفية دون رمز مقدّمة إلى جانبه هو الطريقة الوحيدة لجعل هذا
  ينتج شيئًا غير مقروء: اضبط `--ayr-connect-surface-bg` على قيمة داكنة وحده وسيبقى
  `--ayr-connect-surface-fg` الافتراضي لدينا كحليًا داكنًا. لا شيء يستطيع استنتاج النصف الآخر
  نيابةً عنك.
</Warning>

من دون أي `appearance` إطلاقًا، يحتفظ كل رمز بقيمته الافتراضية ويبدو الإطار هكذا:

<div className="my-8">
  <Frame caption="الرموز الافتراضية: أسطح بيضاء، ونص كحلي داكن، ولون مميز نيلي، ونصف قطر 8px.">
    <img src="https://mintcdn.com/ayrshare-docs/-2tpx3mFy9vWIObd/images/multiple-users/connect-widget-appearance-default.webp?fit=max&auto=format&n=-2tpx3mFy9vWIObd&q=85&s=62f9ce7e061c8bb58132960b9e270f4a" alt="Three Ayrshare Connect tiles with the default appearance" width="920" height="528" data-path="images/multiple-users/connect-widget-appearance-default.webp" />
  </Frame>
</div>

مرّر حفنة من الرموز فيتخذ الإطار نفسه لوحة ألوانك. هذا المثال يجعل الأسطح زرقاء باهتة،
ويعمّق النص واللون المميز ليطابقاها، ويزيد استدارة الزوايا قليلًا:

```javascript theme={"system"}
const connect = AyrshareConnect.init({
  session: getSession,
  appearance: {
    "--ayr-connect-surface-bg": "#EFF6FF",
    "--ayr-connect-border-color": "#BFDBFE",
    "--ayr-connect-surface-fg": "#0F2A5F",
    "--ayr-connect-surface-fg-muted": "#4A6A9A",
    "--ayr-connect-accent": "#1D4ED8",
    "--ayr-connect-radius": "14px",
    "--ayr-connect-spacing": "10px",
  },
});
```

<div className="my-8">
  <Frame caption="البطاقات الثلاث نفسها بعد تطبيق الرموز أعلاه.">
    <img src="https://mintcdn.com/ayrshare-docs/-2tpx3mFy9vWIObd/images/multiple-users/connect-widget-appearance-themed.webp?fit=max&auto=format&n=-2tpx3mFy9vWIObd&q=85&s=686d1ad900628a6d4c75dc242f1ab38c" alt="Three Ayrshare Connect tiles restyled with pale blue surfaces and a deeper blue accent" width="920" height="574" data-path="images/multiple-users/connect-widget-appearance-themed.webp" />
  </Frame>
</div>

**هناك لوحة ألوان واحدة ولا إعداد مسبق فاتح/داكن.** لا شيء يعتمد على `prefers-color-scheme`،
عن قصد — فقد لا يطابق ثيم صفحتك نظام تشغيل مستخدمك، وكان استعلام وسائط سيتفوق بصمت على
الألوان التي اخترتها. لوحة التحكم الداكنة تُظلَّل بتزويد قيم داكنة.

قائمة الرموز هذه عقد مدعوم نحافظ عليه عبر الإصدارات.

### الرموز

| الرمز                              | الافتراضي                                                 |
| ---------------------------------- | --------------------------------------------------------- |
| `--ayr-connect-font-family`        | `Inter, "Segoe UI", system-ui, -apple-system, sans-serif` |
| `--ayr-connect-font-size`          | `16px`                                                    |
| `--ayr-connect-font-size-sm`       | `12px`                                                    |
| `--ayr-connect-label-font-weight`  | `600`                                                     |
| `--ayr-connect-status-font-size`   | `12px`                                                    |
| `--ayr-connect-status-font-weight` | `600`                                                     |
| `--ayr-connect-surface-bg`         | `#FFFFFF`                                                 |
| `--ayr-connect-surface-bg-hover`   | `#F7F7F7`                                                 |
| `--ayr-connect-surface-fg`         | `#010629`                                                 |
| `--ayr-connect-surface-fg-muted`   | `#56596F`                                                 |
| `--ayr-connect-border-color`       | `#DDDEE2`                                                 |
| `--ayr-connect-border-width`       | `1px`                                                     |
| `--ayr-connect-radius`             | `8px`                                                     |
| `--ayr-connect-spacing`            | `8px`                                                     |
| `--ayr-connect-accent`             | `#4553EE`                                                 |
| `--ayr-connect-accent-fg`          | `#FFFFFF`                                                 |
| `--ayr-connect-focus-ring-color`   | `#4553EE`                                                 |
| `--ayr-connect-focus-ring-width`   | `2px`                                                     |
| `--ayr-connect-disabled-fg`        | `#6E7185`                                                 |
| `--ayr-connect-status-radius`      | `4px`                                                     |
| `--ayr-connect-status-success-bg`  | `#EBFFF8`                                                 |
| `--ayr-connect-status-success-fg`  | `#237C5C`                                                 |
| `--ayr-connect-status-warning-bg`  | `#FFF7EF`                                                 |
| `--ayr-connect-status-warning-fg`  | `#702E00`                                                 |
| `--ayr-connect-status-critical-bg` | `#FFE5E1`                                                 |
| `--ayr-connect-status-critical-fg` | `#AD1902`                                                 |
| `--ayr-connect-status-info-bg`     | `#ECF9FF`                                                 |
| `--ayr-connect-status-info-fg`     | `#1F6686`                                                 |
| `--ayr-connect-callout-bg`         | `#FFF7EF`                                                 |
| `--ayr-connect-callout-fg`         | `#702E00`                                                 |
| `--ayr-connect-partner-name`       | `""`                                                      |
| `--ayr-connect-icon-size`          | `32px`                                                    |
| `--ayr-connect-avatar-size`        | `40px`                                                    |

القيمة التي ليست CSS صالحًا لرمزها **تُتجاهل، مع تحذير في الـ console لديك**، بدلًا من أن
تُطبَّق. وهذا أهم مما يبدو: القيمة `8` بلا وحدة لـ `--ayr-connect-spacing` سلسلة بريئة تمامًا
كانت ستُبطل كل حساب يقرؤها وتُقوّض التخطيط، دون خطأ في أي مكان. أعطِ الأطوال وحدة.

### اسمك الخاص على شاشة التسليم

قبل أن نسلّم مستخدمك إلى شبكة، نعرض شاشة قصيرة تُسمّي الجهة التي يتصل من خلالها. خطّافان
يتيحان لك جعلها خاصتك، وكلاهما مستقر عبر الإصدارات.

يضبط `--ayr-connect-partner-name` التسمية. وهو الرمز الوحيد الذي قيمته **نص**، لذا يجب
اقتباسها كسلسلة CSS — القيمة غير المقتبسة غير صالحة ولا تعرض شيئًا إطلاقًا:

```javascript theme={"system"}
AyrshareConnect.init({
  session: getSession,
  appearance: { "--ayr-connect-partner-name": "'Acme Social'" },
  css: "[data-ayr-connect-partner-mark]::after { background-image: url('https://cdn.example.com/mark.svg') }",
});
```

الشعار ليس رمزًا. نشحن العلامة كعنصر موضوع ومحدد الحجم وأنت تملؤه بـ `background-image` عبر
`css`، كما في المثال أعلاه — فالرمز الذي يستطيع جلب صورة من داخل مستندنا ليس شيئًا نقبله،
لذا يأتي الطلب من قاعدة كتبتها أنت لا من قيمة مرّرتها إلينا.

<Note>
  ‏`[data-ayr-connect-partner-mark]` و`[data-ayr-connect-partner-name]` هما **الاستثناء** من
  تنبيه CSS المخصص أدناه: هذان المُحدِّدان جزء من العقد ونحافظ عليهما عبر الإصدارات.
</Note>

<h3 id="custom-css">
  CSS مخصص
</h3>

يقبل `css` سلسلة تُطبَّق داخل كل إطار، للحالات التي لا تغطيها الرموز.

```javascript theme={"system"}
AyrshareConnect.init({ session: getSession, css: "button { letter-spacing: 0.01em }" });
```

<Warning>
  **CSS المخصص غير مدعوم عبر الإصدارات.** تستهدف مُحدِّداته علاماتنا الداخلية، التي تتغير بين
  الإصدارات — فالقاعدة التي تعمل اليوم قد تتوقف بصمت عن المطابقة بعد أي تحديث. عقد الرموز
  أعلاه هو الجزء الذي نحافظ عليه. ثبّت إصدارًا إن كنت تعتمد على CSS المخصص.
</Warning>

ترث النوافذ المنبثقة `appearance` و`css` الخاصين بالنسخة تمامًا كما ترثهما الإطارات، فلا يشاهد
مستخدمك افتراضياتنا المحايدة تظهر في منتصف تدفق.

## يستحق المعرفة قبل الإطلاق

<AccordionGroup>
  <Accordion title="النافذة المنبثقة التي انتهت صلاحية جلستها تبلّغ عن cancelled لا error">
    لا يمكن إخبار نافذة منبثقة فتحتها بـ `popup()` بسبب رفض توكن — فلكي تفعل ذلك سيكون عليها
    الوثوق بأصل لم تتحقق منه بعد، وهو ما لا يسمح به نموذجنا الأمني. لذا فإن النافذة المنبثقة
    التي تحمل توكنًا ميتًا تُغلق وتظهر كـ `cancelled` مع `reason: "popupClosed"` بدلًا من
    `error`.

    عمليًا هذا نادر: النافذة المنبثقة المفتوحة قبل تحديث صامت تستمر في العمل، لأنها تحققت من
    توكنها عند فتحها. إذا رأيت نتائج `popupClosed` غير مفسّرة، فتحقق من أن نقطة نهاية
    `session` لديك تعيد جلسة حديثة.
  </Accordion>

  <Accordion title="جلسة واحدة لكل نسخة، لا واحدة لكل تركيب">
    أربعة عشر تركيبًا تتشارك توكنًا واحدًا وتكلّف استدعاءً واحدًا لخادمك الخلفي، لا أربعة عشر.
    إذا أردت فتحات ذات نطاقات مختلفة — قيمة `allowedSocial` مختلفة على بعضها — فشغّل استدعاء
    `init` ثانيًا بجلسته الخاصة بدلًا من توقّع أن يضيّق التركيب النطاق.
  </Accordion>

  <Accordion title="الإطارات لا تُعرض إلا على الأصل الذي صرّحت به">
    تحمل كل جلسة `origin` الذي تعمل عليه صفحتك، ويقارن الإطار الصفحة التي تضمّنه بتلك القيمة
    قبل عرض أي شيء. الإطار المضمّن في مكان آخر يبقى فارغًا ولا يرسل أي أحداث. لا توجد قائمة
    سماح للتسجيل ولا شيء للإعداد — أرسل `origin` الصحيح عند إنشاء الجلسة.
  </Accordion>

  <Accordion title="الارتفاع نتولّاه نحن، وليس حدثًا">
    تبلّغ الإطارات السكربت عن ارتفاعها، والسكربت يعيد تحجيمها. وتخطيطك يُعاد تدفقه فحسب. لا
    يوجد حدث لإعادة التحجيم تشترك فيه، ولا شيء تقيسه من جانبك.
  </Accordion>
</AccordionGroup>

## المتطلبات

<ul className="custom-bullets">
  <li>
    **[Max Pack](/docs/additional/maxpack)**. جلسة الأداة هي جلسة بوضع connect، وإنشاء واحدة دون
    Max Pack يعيد `code: 504`. تواصل مع الدعم إذا كنت بحاجة إلى تفعيل وضع connect على حساب
    من دونه.
  </li>

  <li>
    **`origin`** على كل جلسة — الأصل الفعلي الذي تعمل عليه صفحتك. حذفه يعيد `code: 505`؛
    والقيمة التي ليست أصل `https` أو مخططًا مخصصًا أو `http://localhost` تعيد `code: 506`.
  </li>

  <li>
    **لا `network`** على الجلسة. هذا المعامل هو ما يجعل الجلسة
    [وضعًا مباشرًا](/docs/multiple-users/connect-direct-mode) بدلًا من ذلك، وعنوان URL لجلسة الوضع
    المباشر ليس ما يتوقعه السكربت.
  </li>
</ul>

كل رمز أعلاه موجود في مرجع
[أخطاء Link Session](/docs/errors/errors-ayrshare#link-session-errors)، مع الرسالة الفعلية التي
تعيدها API وما ينبغي فعله حيالها.
