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

# القوالب المخصصة

> تجاوز طريقة عرض أي بلوك في Aftersell Cart بكود JSX الخاص بك: ما الذي يستبدله القالب، وما المتاح في النطاق، وكيف تنسّقه، وأين تجد خصائص كل بلوك.

يتيح لك **القالب المخصص** تجاوز طريقة عرض بلوك بعينه. فبدلًا من واجهة البلوك المدمجة، تعرض السلة كود JSX الخاص بك، باستخدام البيانات نفسها التي كان البلوك سيستخدمها عادة. وهو قدرة شاملة وليس بلوكًا بذاته: معظم البلوكات تتيحه من علامة تبويب **Code** الخاصة بها.

تغطي هذه الصفحة ما ينطبق على **كل** البلوكات. للخصائص التي يمررها لك بلوك محدد، انتقل إلى [مرجع البلوك نفسه](#props-for-each-block).

<div id="custom-template-vs-custom-code-block">
  ## القالب المخصص مقابل بلوك الكود المخصص
</div>

يبدوان متشابهين لكنهما يفعلان أمرين مختلفين:

* **القالب المخصص** *يستبدل عرض بلوك موجود* بترميزك الخاص، ويمرر لك بيانات ذلك البلوك نفسها (عنوان Header وعدد العناصر، وإجماليات Summary، وهكذا). لا يضيف شيئًا جديدًا؛ بل يعيد تنسيق بلوك واحد.
* بلوك **[Custom code](/ar/aftersell/cart/custom-code-blocks)** *يضيف بلوكًا جديدًا* من HTML أو React عشوائي في أي مكان في السلة.

الجأ إلى القالب المخصص عندما يكون البلوك المدمج قريبًا مما تريد لكنك تحتاج تخطيطًا أو ترميزًا مختلفًا. والجأ إلى بلوك Custom code عندما تريد إضافة شيء لا تغطيه البلوكات المدمجة.

<div id="using-a-custom-template">
  ## استخدام قالب مخصص
</div>

1. حدد بلوكًا في المحرر وافتح علامة تبويب **Code** الخاصة به.
2. حرر القالب الافتراضي. القوالب المخصصة **JSX فقط** (خيار HTML أو JSX حصري لبلوك Custom code).
3. انقر **Compile**. يزيل التجميع الأنواع ويحوّل JSX، فيلتقط أخطاء **الصياغة**. أخطاء الأنواع لا توقف التجميع — يشير المحرر إليها ضمنيًا أثناء الكتابة، بنفس IntelliSense الذي يكمل خصائص البلوك تلقائيًا.
4. فعّل القالب لتستخدمه السلة بدلًا من العرض المدمج.
5. يعيد **Reset to default** قالب البلوك الأصلي في أي وقت.

<div id="writing-a-template-with-ai">
  ## كتابة قالب بالذكاء الاصطناعي
</div>

تتضمن علامة تبويب Code زر **Copy AI prompt** (أيقونة العصا ✦). النقر عليه ينسخ إلى حافظتك موجزًا مكتفيًا بذاته يمكنك لصقه مباشرة في جلسة محادثة ذكاء اصطناعي (Claude أو ChatGPT أو ما شابه).

يتضمن الموجه كل ما يحتاجه الذكاء الاصطناعي لكتابة قالب صالح لذلك البلوك تحديدًا:

* قواعد التجميع (تعبير واحد، لا `export default`، لا استيرادات)
* الخصائص الدقيقة التي يستقبلها البلوك، مطابقة لما يعرضه IntelliSense في المحرر
* توقيع الدالة المقفل الذي يفرضه المحرر
* قواعد خاصة بالبلوك (تنسيقات الأموال، والمعالجات الواجب ربطها، ومتطلبات إمكانية الوصول)
* قسم للملء تلصق فيه قالبك الحالي وتصف التغيير الذي تريده

بعد النسخ، افتح جلسة ذكاء اصطناعي، والصق الموجه، واملأ الفراغين في الأسفل (قالبك الحالي والتغيير الذي تريده)، وأرسل. يعيد الذكاء الاصطناعي قالبًا كاملًا يمكنك لصقه في المحرر وتجميعه.

<Tip>
  الصق قالبك الحالي في قسم الملء بدلًا من تركه فارغًا. يستخدمه الذكاء الاصطناعي كنقطة انطلاق، فتنتقل أي تخصيصات أجريتها بالفعل بدلًا من استبدالها بالافتراضي.
</Tip>

<Note>
  الموجه خاص بكل بلوك. لا يظهر زر **Copy AI prompt** إلا على البلوكات التي تدعم القوالب المخصصة.
</Note>

<Tip>
  القالب الافتراضي الذي تبدأ منه هو **نسخة عاملة من ترميز البلوك المدمج**، فلديك دائمًا مرجع صحيح قابل للعرض تعدّله بدلًا من صفحة فارغة. الجأ إلى **Reset to default** كلما أردت استعادة ذلك المرجع.

  ليس دائمًا تطابقًا حرفيًا. القالب الافتراضي لـ Header يعرض أيضًا `logoUrl`، الذي لا موضع له في الترميز المدمج، فتفعيل ذلك القالب هو الطريقة التي تظهر بها صورة الترويسة المرفوعة لأول مرة.
</Tip>

<div id="what-your-template-replaces">
  ## ما الذي يستبدله قالبك
</div>

يستبدل القالب عرض البلوك **بالكامل**. لا يبقى أي غلاف حول JSX الخاص بك، ولهذا عواقب تستحق المعرفة قبل أن تبدأ في الحذف:

| ما تفقده                              | ما يعنيه ذلك                                                                                                                                                                       |
| ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| عنصر غلاف البلوك                      | لا شيء يغلّف ترميزك. أي حشو أو محاذاة أو تخطيط كان البلوك يوفره أصبح عليك توفيره.                                                                                                  |
| **إعدادات علامة تبويب Design للبلوك** | تُطبَّق إعدادات التصميم كأنماط مضمّنة على الغلاف المدمج، وقد اختفى ذلك الغلاف. الألوان والتباعد وأنصاف الأقطار المضبوطة في علامة تبويب Design **تتوقف عن التطبيق** على هذا البلوك. |
| ميزات إمكانية الوصول المدمجة          | `aria-label` ومعالجة التركيز والعناصر الدلالية لا توجد إلا إذا تضمنها JSX الخاص بك.                                                                                                |

<Warning>
  **علامة تبويب Design هي ما يفاجئ الناس.** أثناء تفعيل قالب مخصص، تُعطَّل حقول علامة تبويب Design وتظهر أيقونة تحذير بجوار عنوان "Design". مرر فوق الأيقونة لمعرفة السبب. نسّق البلوك من قالبك بدلًا من ذلك، إما [مضمّنًا أو بـ CSS الخاص بك](#styling-a-custom-template). تعود الحقول للعمل فور إيقاف القالب المخصص.
</Warning>

ما تحتفظ به: موضع البلوك في السلة، ومفتاح رؤيته، وإعداداته (التي لا تزال تغذي الخصائص التي تستقبلها)، ولوحة [Custom CSS](/ar/aftersell/cart/custom-css) الخاصة بالسلة، و**هيكل التحميل المدمج**.

هذا الأخير يفاجئ الناس. يتحقق البلوك مما إذا كانت السلة لا تزال تُحمَّل *قبل* الوصول إلى قالبك، لذا يُعرض الهيكل المدمج أثناء التحميل ولا يعمل قالبك إلا بعد جاهزية السلة. لا تحتاج إلى بناء حالة تحميل.

<div id="whats-available-inside-a-template">
  ## ما المتاح داخل القالب
</div>

قالبك هو مكوّن دالة واحد. يُجمَّع من **TSX**، فتُسمح تعليقات الأنواع وتُزال وقت التجميع. لهذا كُتبت القوالب الافتراضية بها:

```jsx theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
function Header(props: HeaderProps) {
  return <div>{/* … */}</div>;
}
```

**سطر التوقيع والقوس الختامي مقفلان** — لن يسمح لك المحرر بتحرير أي منهما، والتمرير فوقهما يعرض "Locked — this line can't be edited." تكتب الجسم بينهما. **Reset to default** هو الشيء الوحيد الذي يمكنه استبدالهما.

ما يهم أيضًا:

* **لديك خمسة خطافات:** `useState` و`useEffect` و`useMemo` و`useRef` و`useCallback`. إضافة إلى `Fragment`، لأجل `<>…</>`.
* **لا توجد استيرادات.** لا يمكنك عمل `import` لأي شيء، ولا يوجد كائن `React` في النطاق، فلا `React.useReducer` ولا `React.Children`. إذا لم يكن الخطاف في القائمة أعلاه، فهو غير متاح.
* **الخصائص للقراءة فقط.** تعديل خاصية لن يفيد شيئًا. لتغيير السلة، استخدم خصائص المعالجات التي يمنحك إياها البلوك (`onClose` و`increment` و`selectPlan` وغيرها) بدلًا من الكتابة في الخصائص مباشرة.
* **`window` قابل للوصول**، فيمكن للقالب استدعاء [Cart SDK](/ar/aftersell/cart/sdk-overview) عبر `window.aftersell.cart` عندما يحتاج شيئًا لا تغطيه خصائص البلوك.

<div id="conventions-across-every-block">
  ## أعراف تسري على كل بلوك
</div>

ثلاث قواعد تنطبق في كل مكان، ومعرفتها تزيل معظم التخمين:

* **خصائص `*Html` هي نص منسّق منقّى مسبقًا.** اعرضها بـ `dangerouslySetInnerHTML`. فقد مرت بالفعل عبر منقّي السلة، ورموز التاجر مثل `{{total_price}}` مستبدلة مسبقًا.
* **الأسعار التي تصل كـ `string` منسّقة مسبقًا** بتنسيق عملة المتجر. الأسعار كـ `number` تكون بالسنتات. يمنحك البلوك أحدهما، وجدول كل بلوك يحدد أيهما.
* **`isLoading` دائمًا `false` داخل القالب.** يعرض البلوك هيكله المدمج ولا يستدعي قالبك إلا بعد تحميل السلة، لذا تُمرَّر الخاصية للاكتمال وليس لتتفرع عليها.

<Note>
  بعض البلوكات لا تعرض شيئًا إطلاقًا في حالات معينة، لذا لا يُستدعى قالبك أبدًا ببيانات فارغة. قالب Rewards لا يرى أبدًا `milestones` فارغة، وقالب Subscription upgrade لا يرى أبدًا `view` بقيمة null. يذكر مرجع كل بلوك أين ينطبق ذلك، لتتمكن من تخطي فرع الحالة الفارغة.
</Note>

<div id="styling-a-custom-template">
  ## تنسيق قالب مخصص
</div>

يحمل القالب الافتراضي الذي تبدأ منه أسماء أصناف البلوك. وتعتمد طريقة تنسيق تعديلاتك على مدى ابتعادك عن نقطة الانطلاق تلك.

<div id="the-two-class-families">
  ### عائلتا الأصناف
</div>

كل عنصر في القالب الافتراضي يحمل اسم صنف مزدوجًا، ولكل منهما وظيفة مختلفة تمامًا:

| العائلة           | ما الذي تفعله                                                                                    | هل تكتب CSS ضدها؟                                                                       |
| ----------------- | ------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------- |
| `cart-internal-*` | **تحمل التنسيق المدمج للبلوك.** كل قاعدة في ورقة أنماط السلة تستهدف هذه العائلة.                 | لا. إنها البنية الداخلية للسلة، ويضع محرر Custom CSS علامات على المحددات الموجهة إليها. |
| `cart-external-*` | **خطاف بلا تنسيق خاص به.** لا شيء في ورقة أنماط السلة يستهدفه؛ إنه موجود ليتعلق به CSS الخاص بك. | نعم. هذه هي الطريقة المدعومة لإعادة تنسيق بلوك.                                         |

فـ `cart-internal-header__title` هو ما يجعل العنوان *يبدو* كالعنوان المدمج، و`cart-external-header__title` هو المقبض الذي يُفترض أن تمسك به عندما تريد تغيير مظهره.

<div id="small-changes-keep-both-classnames">
  ### التغييرات الصغيرة: احتفظ باسمي الصنف معًا
</div>

إذا كنت تعيد ترتيب العناصر أو تعيد التسمية أو تضيف شيئًا داخل البنية الحالية، فاترك أسماء الأصناف كما هي. تحتفظ بالمظهر المدمج مجانًا، وتعيد التنسيق عبر [Custom CSS](/ar/aftersell/cart/custom-css) مستهدفًا خطافات `cart-external-*`.

<div id="restructuring-drop-both-classnames">
  ### إعادة الهيكلة: احذف اسمي الصنف معًا
</div>

بمجرد أن تغيّر بنية DOM بدلًا من تعديلها الطفيف، أزل **كلتا** العائلتين من ترميزك واستخدم [أسماء أصناف خاصة بك](#option-1-your-own-classnames-plus-custom-css) بدلًا منهما. ولكل منهما سبب منفصل.

**احذف `cart-internal-*` لأن CSS المدمج كُتب لبنية DOM المدمجة.** إذا أبقيت تلك الأصناف على ترميز أُعيدت هيكلته، فسترث قواعد تخطيط تفترض عناصر لم تعد لديك: حاويات flex تتوقع أبناءً مختلفين، وتباعدًا بين عناصر انتقلت، وتموضعًا نسبةً إلى شيء أزلته. يظهر هذا عادة على شكل CSS الخاص بك "لا يعمل" بينما القواعد المدمجة هي الفائزة.

<Warning>
  **احذف `cart-external-*` لأنه اسم مشترك، وليس ملكك.** تلك الأسماء تعني شيئًا محددًا في الترميز المدمج، وCSS المخصص الخاص بك يُكتب مرة واحدة للسلة بأكملها. إذا أعاد قالب مُعاد الهيكلة استخدامها، فإن أي قاعدة تكتبها تستهدف بنيتك والبنية المدمجة معًا.

  يسوء ذلك لحظة إيقاف القالب المخصص: يعود البلوك إلى ترميزه المدمج، وCSS الخاص بك لا يزال يشير إليه، فينسّق الآن بنية DOM لم يُكتب لها أبدًا. بادئتك الخاصة تُبقي الاثنين منفصلين بوضوح، فيكون إيقاف القالب عودة نظيفة.
</Warning>

طريقتان لتنسيق ما بنيته:

<div id="option-1-your-own-classnames-plus-custom-css">
  #### الخيار 1: أسماء أصناف خاصة بك مع Custom CSS
</div>

الأفضل لأي شيء ستصونه أو تعيد استخدامه. امنح أصنافك بادئة لن يتصادم بها أحد، عادةً اسم متجرك أو علامتك التجارية:

```jsx theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
function Header(props) {
  return (
    <div className="northwind-custom-header">
      <div className="northwind-custom-header__title" dangerouslySetInnerHTML={{ __html: props.title }} />
      <button type="button" className="northwind-custom-header__close" onClick={props.onClose}>
        &times;
      </button>
    </div>
  );
}
```

ثم في محرر السلة، حدد **Cart settings** في اللوحة اليسرى وافتح علامة تبويب **Custom CSS** على اليمين:

```css theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
.northwind-custom-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px;
}

.northwind-custom-header__title {
  font-size: 18px;
  font-weight: 600;
}

.northwind-custom-header__close:hover {
  opacity: 0.6;
}
```

البادئة أهم مما تبدو. بدونها، صنف مثل `.header` أو `.title` معرّض للتصادم مع أصناف السلة نفسها، أو قالب تطبيق آخر، أو بلوك مستقبلي.

<div id="option-2-inline-styles">
  #### الخيار 2: الأنماط المضمّنة
</div>

بلا ذهاب وإياب مع لوحة CSS، وكل شيء في مكان واحد:

```jsx theme={"theme":{"light":"snazzy-light","dark":"github-dark"}}
<div style={{ display: 'flex', alignItems: 'center', gap: '12px' }}>
```

جيد لهيكلة التخطيط والحالات الفردية. حدوده هي المعتادة: لا `:hover` أو أشباه أصناف أخرى، ولا استعلامات وسائط، ولا إعادة استخدام عبر البلوكات. الجأ إلى الخيار 1 عندما تريد أيًا من ذلك.

<div id="picking-an-approach">
  ### اختيار المنهج
</div>

| الموقف                             | افعل هذا                                                             |
| ---------------------------------- | -------------------------------------------------------------------- |
| البنية نفسها، صياغة أو ترتيب مختلف | احتفظ باسمي الصنف، وأعد التنسيق عبر Custom CSS على `cart-external-*` |
| بنية جديدة، وتنسيق ستصونه          | أصنافك الخاصة ذات البادئة، مع حذف عائلتي السلة معًا                  |
| بنية جديدة، وبضع قواعد تخطيط سريعة | أنماط مضمّنة، مع حذف عائلتي السلة معًا                               |
| كود مخصص كثير عبر عدة بلوكات       | أصنافك الخاصة ذات البادئة في كل مكان، ليمكن إيقاف أي قالب بشكل نظيف  |

<Note>
  تُعرض السلة في shadow root، لذا لا يمكن لورقة أنماط قالبك الوصول إلى داخلها. يجب أن تأتي أنماط القالب المخصص من لوحة **Custom CSS** الخاصة بالسلة أو من أنماط مضمّنة، وليس من قالبك. راجع [CSS المخصص](/ar/aftersell/cart/custom-css).
</Note>

<div id="when-a-template-fails">
  ## عندما يفشل قالب
</div>

القالب المعطوب لا يعطّل السلة أبدًا. يعرض البلوك **لا شيء** ويستمر كل ما حوله في العمل، وهو أمر آمن لكن يسهل تفويته: العَرَض هو مساحة فارغة حيث ينبغي أن يكون بلوكك.

| الفشل              | متى تراه                      | أين يُبلَّغ                                                                     |
| ------------------ | ----------------------------- | ------------------------------------------------------------------------------- |
| خطأ نوع            | أثناء الكتابة                 | تمويج ضمني في المحرر. **لا** يمنع التجميع — المجمّع يزيل الأنواع بدلًا من فحصها |
| خطأ صياغة          | عند النقر على **Compile**     | المحرر، قبل أن يصل إلى واجهة متجرك                                              |
| انهيار أثناء العرض | على واجهة المتجر، بعد الإطلاق | `console.error('[aftersell-cart] module crashed: …')`                           |

ولأن البلوك يختفي بصمت بدلًا من إظهار خطأ مرئي، افحص القالب دائمًا في [المعاينة](/ar/aftersell/cart/previewing-carts) قبل النشر. إذا اختفى بلوك، فافتح وحدة تحكم المتصفح أولًا.

أمران يستحقان الحذر، لأن كليهما يُسقط قالبًا يفترض خلاف ذلك:

* **الخصائص القابلة للقيمة الفارغة.** كثير من الخصائص تكون `null` في الظروف العادية (`logoUrl` بلا شعار، و`imageUrl` بلا صورة، و`variantTitle` على منتج أحادي النسخة). تحقق قبل استخدامها.
* **المصفوفات التي قد تكون فارغة.** `discountTags` و`discountCodes` تكونان `[]` في أغلب الأحيان.

<div id="limitations">
  ## القيود
</div>

* **القوالب المخصصة تجاوزات عرض.** لتشغيل منطق على السلة (الاشتراك في الأحداث، إضافة عناصر، التفاعل مع التغييرات)، استخدم [السكربتات المخصصة](/ar/aftersell/cart/custom-scripts) و[Cart SDK](/ar/aftersell/cart/sdk-overview).
* **كل بلوك تقريبًا يدعم قالبًا.** الاستثناءات هي بلوك **[Express payments](/ar/aftersell/cart/express-payments-block)** الذي يستضيف أزرار دفع Shopify نفسها، وحاوية **[Cart items](/ar/aftersell/cart/cart-items-block)** نفسها، وإن كان صف **Product** داخلها يدعم قالبًا مخصصًا.
* **لا يمكن للقالب تغيير ما يفعله البلوك جوهريًا.** فهو يغيّر طريقة عرض بيانات البلوك، وليس البيانات أو السلوك خلفها.

<div id="props-for-each-block">
  ## خصائص كل بلوك
</div>

يمرر كل بلوك بياناته الخاصة. جدول الخصائص الكامل، مع الأنواع ومثال عملي، موجود في صفحة ذلك البلوك:

| البلوك                                                                                | الخصائص التي يستقبلها                                                                                                              |
| ------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| [Header](/ar/aftersell/cart/header-block#custom-template)                             | `title`, `logoUrl`, `leftSection`, `rightSection`, `itemCount`, `onClose`, `isLoading`                                             |
| [Banner](/ar/aftersell/cart/banner-block#custom-template)                             | `text`, `shouldUseTimer`, `isTimerExpiredAndShouldHide`, `isLoading`                                                               |
| [Rewards](/ar/aftersell/cart/rewards-block#custom-template)                           | `milestones`, `rewardsMessageHtml`, `showIcons`, `isLoading`                                                                       |
| [Cart items · Product](/ar/aftersell/cart/cart-items-block#custom-template)           | 25 خاصية: محتوى كل سطر، والمعرّفات، وعناصر تحكم الكمية                                                                             |
| [Subscription upgrade](/ar/aftersell/cart/subscription-upgrade-block#custom-template) | `view`, `selectPlan`, `onChange`, `oneTimeValue`, والمزيد                                                                          |
| [Summary](/ar/aftersell/cart/summary-block#custom-template)                           | `leftHtml`, `rightHtml`, `discountCodes`, `totalPrice`, `savings`, والمزيد                                                         |
| [Checkout button](/ar/aftersell/cart/checkout-button-block#custom-template)           | `label`, `href`, `isLoading`                                                                                                       |
| [Discount code](/ar/aftersell/cart/discount-code-block#custom-template)               | `discountCodeInput`, `placeholder`, `buttonText`, `isValidating`, `isInvalid`, `setDiscountCodeInput`, `handleSubmit`, `isLoading` |
| [Empty cart](/ar/aftersell/cart/empty-cart-block#custom-template)                     | `text`, `cta`, `href`                                                                                                              |
| [Image](/ar/aftersell/cart/image-block#custom-template)                               | `imageUrl`, `altText`, `maxHeight`, `fullWidth`                                                                                    |
| [Notes](/ar/aftersell/cart/notes-block#custom-template)                               | `titleHtml`, `placeholder`, `noteInput`, `status`, `isExpanded`, `onNoteChange`, `onNoteBlur`, `onToggle`, والمزيد                 |
| [Product add-on](/ar/aftersell/cart/product-add-on-block#custom-template)             | `addonTitleHtml`, `descriptionHtml`, `priceHtml`, `imageUrl`, `format`, `isEnabled`, `handleAdd`, `handleToggle`, والمزيد          |
| [Shipping protection](/ar/aftersell/cart/shipping-protection-block#custom-template)   | `titleHtml`, `descriptionHtml`, `priceHtml`, `imageUrl`, `format`, `isEnabled`, `handleAdd`, `handleToggle`, والمزيد               |
| [Upsells](/ar/aftersell/cart/upsells-block#custom-template)                           | `title`, `addButtonText`, `layout`, `upsells`, `selectVariant`, `handleAdd`, وعناصر تحكم العرض الدوّار                             |

بلوك [Custom code](/ar/aftersell/cart/custom-code-blocks) هو الواجهة الوحيدة التي **تضيف** ترميزًا بدلًا من استبدال عرض بلوك، لذا فإن خصائصه مختلفة: السلة بأكملها، إضافة إلى إجراء إضافة إلى السلة. راجع [بلوكات الكود المخصص ← الخصائص](/ar/aftersell/cart/custom-code-blocks#props).
