mirror of
https://github.com/twentyhq/twenty.git
synced 2026-08-01 18:19:37 -04:00
i18n - docs translations (#23559)
Created by Github action Co-authored-by: github-actions <github-actions@twenty.com>
This commit is contained in:
committed by
GitHub
parent
c862a2a43d
commit
cdeebb1a18
@@ -7,7 +7,7 @@ icon: window-maximize
|
||||
المكوّنات الأمامية هي مكوّنات React تُعرَض مباشرة داخل واجهة مستخدم Twenty. تعمل ضمن **Web Worker معزول** باستخدام Remote DOM — تُنفَّذ شيفرتك داخل iframe معزول ذو منشأ غير شفاف، ومع ذلك لا تزال واجهتها تُعرَض محليًا داخل الصفحة بدلًا من أن تظل محصورة داخل ذلك الـ iframe.
|
||||
|
||||
<Warning>
|
||||
Front components are still under active development. Your code runs against a partial DOM, not a real browser page, so advanced usages can fail, often silently. See [Current limitations](#current-limitations).
|
||||
لا تزال مكوّنات Front قيد التطوير النشط. يعمل الكود الخاص بك على DOM جزئي، وليس على صفحة متصفح حقيقية، لذلك يمكن أن تفشل الاستخدامات المتقدمة، وغالبًا من دون أي إشعار. راجع [القيود الحالية](#current-limitations).
|
||||
</Warning>
|
||||
|
||||
## أين يمكن استخدام مكوّنات الواجهة الأمامية
|
||||
@@ -73,10 +73,10 @@ export default defineCommandMenuItem({
|
||||
|
||||
| الحقل | مطلوب | الوصف |
|
||||
| --------------------- | ----- | ------------------------------------------------------------- |
|
||||
| `universalIdentifier` | Yes | معرّف فريد ثابت لهذا المكوّن |
|
||||
| `universalIdentifier` | نعم | معرّف فريد ثابت لهذا المكوّن |
|
||||
| `component` | نعم | دالة مكوّن React |
|
||||
| `name` | No | الاسم المعروض |
|
||||
| `description` | No | وصف لما يفعله المكوّن |
|
||||
| `name` | لا | الاسم المعروض |
|
||||
| `description` | لا | وصف لما يفعله المكوّن |
|
||||
| `isHeadless` | لا | عيّنه على `true` إذا كان المكوّن بلا واجهة مرئية (انظر أدناه) |
|
||||
|
||||
## وضع مكوّن أمامي على صفحة
|
||||
@@ -701,71 +701,71 @@ const Card = () => {
|
||||
|
||||
للتفرّع بناءً على النظام النشِط (active scheme) صراحةً، اقرأه باستخدام `useColorScheme()` من `twenty-sdk/front-component`، والذي يعيد `'light'` أو `'dark'`.
|
||||
|
||||
## Current limitations
|
||||
## القيود الحالية
|
||||
|
||||
Front components are under active development. Rendering, styling and handling events works well. Anything that reaches *past* rendering (measuring an element, calling a DOM method on a ref, portaling outside your tree, touching browser storage) is missing or incomplete today, and most of it fails silently: no exception, and no TypeScript error either, since the scaffold is typed against the full browser DOM.
|
||||
مكوّنات Front قيد التطوير النشط. الترسيم والتنسيق والتعامل مع الأحداث تعمل بشكل جيد. أي شيء يتجاوز *مرحلة* الترسيم (قياس عنصر، استدعاء دالة DOM على ref، إنشاء portal خارج الشجرة الخاصة بك، أو لمس تخزين المتصفح) مفقود أو غير مكتمل حاليًا، ومعظم هذه الحالات تفشل بصمت: لا يتم رمي استثناء، ولا يظهر خطأ TypeScript أيضًا، لأن القالب مكتوب استنادًا إلى DOM الكامل للمتصفح.
|
||||
|
||||
If one of these blocks you, [open an issue](https://github.com/twentyhq/twenty/issues/new/choose) so it gets prioritized.
|
||||
إذا كان أحد هذه الأمور يعيقك، [افتح تذكرة](https://github.com/twentyhq/twenty/issues/new/choose) ليتم إعطاؤه أولوية.
|
||||
|
||||
### Layout and measurement
|
||||
### التخطيط والقياس
|
||||
|
||||
Nothing can measure itself yet.
|
||||
لا يوجد أي شيء يمكنه قياس نفسه بعد.
|
||||
|
||||
| API | What happens |
|
||||
| ------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
|
||||
| `getBoundingClientRect()`, `getClientRects()` | Throws |
|
||||
| `offsetWidth`, `clientWidth`, `scrollWidth`, `offsetTop`, ... | Silently `undefined`, so `width ?? 0` yields `0` and `width > 600` is always false |
|
||||
| `ResizeObserver`, `IntersectionObserver` | `ReferenceError` (`typeof` guards do work) |
|
||||
| `window.matchMedia()`, `window.getComputedStyle()` | Throws |
|
||||
| `window.innerWidth`, `innerHeight`, `devicePixelRatio` | Silently `undefined` |
|
||||
| `new MutationObserver(fn)` | Constructs, then `.observe()` throws |
|
||||
| واجهة برمجة التطبيقات | ما الذي يحدث |
|
||||
| ------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
|
||||
| `getBoundingClientRect()`, `getClientRects()` | يرمي استثناء |
|
||||
| `offsetWidth`, `clientWidth`, `scrollWidth`, `offsetTop`, ... | قيمة `undefined` بصمت، لذا فإن `width ?? 0` تعطي `0` و `width > 600` تكون دائمًا خاطئة |
|
||||
| `ResizeObserver`, `IntersectionObserver` | `ReferenceError` (`typeof` guards تعمل) |
|
||||
| `window.matchMedia()`, `window.getComputedStyle()` | يرمي استثناء |
|
||||
| `window.innerWidth`, `innerHeight`, `devicePixelRatio` | قيمة `undefined` بصمت |
|
||||
| `new MutationObserver(fn)` | يتم الإنشاء، ثم ترمي `.observe()` استثناء |
|
||||
|
||||
So recharts `ResponsiveContainer`, Floating UI / Popper, list virtualization and drag-to-resize do not work yet. Do layout in CSS instead: your stylesheet reaches the real page, so flexbox, grid, `aspect-ratio`, `clamp()` and `@container` all behave normally.
|
||||
لذلك فإن recharts `ResponsiveContainer`، و Floating UI / Popper، وvirtualization للقوائم، والسحب لتغيير الحجم لا تعمل بعد. قم بتنفيذ التخطيط في CSS بدلًا من ذلك: ورقة الأنماط الخاصة بك تصل إلى الصفحة الحقيقية، لذا فإن flexbox و grid و `aspect-ratio` و `clamp()` و `@container` كلها تتصرف بشكل طبيعي.
|
||||
|
||||
<Note>
|
||||
`requestAnimationFrame`, `fetch`, `setTimeout` and `queueMicrotask` work without the `window.` prefix. Only `window.requestAnimationFrame(...)` and friends throw.
|
||||
`requestAnimationFrame`, `fetch`, `setTimeout` و `queueMicrotask` تعمل بدون بادئة `window.`. فقط `window.requestAnimationFrame(...)` وما شابهها ترمي استثناء.
|
||||
</Note>
|
||||
|
||||
### DOM access
|
||||
### الوصول إلى DOM
|
||||
|
||||
A `ref` gives you a sandbox element, not an `HTMLElement`.
|
||||
يعطيك `ref` عنصرًا في sandbox، وليس `HTMLElement`.
|
||||
|
||||
| What you write | What happens | Use instead |
|
||||
| ----------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- | ----------------------------------------------------------------------------------------- |
|
||||
| `ref.current.focus()`, `.click()`, `.select()`, `.setSelectionRange()`, `.scrollIntoView()`, `video.play()` | Throws | Controlled components; read values from `event.target` |
|
||||
| `element.classList.add(...)` | Throws (`classList` is `undefined`) | Build the `className` string yourself |
|
||||
| `document.getElementById()`, `getElementsByClassName()`, `createTreeWalker()` | Throws | `querySelector()` / `querySelectorAll()`, which work |
|
||||
| `document.activeElement` | Always `undefined` | Track focus with `onFocus` / `onBlur` |
|
||||
| `\<canvas>` | Renders nothing, no error | SVG, or draw offscreen and show an `<img src={dataUrl}>` |
|
||||
| `createPortal(node, document.body)` | Renders nothing, while `isConnected` reports success | Overlays inline with `position: absolute`, or pass the library your own container element |
|
||||
| ما الذي تكتبه | ما الذي يحدث | استخدم بدلًا من ذلك |
|
||||
| ----------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
|
||||
| `ref.current.focus()`, `.click()`, `.select()`, `.setSelectionRange()`, `.scrollIntoView()`, `video.play()` | يرمي استثناء | مكوّنات مضبوطة (Controlled components)؛ اقرأ القيم من `event.target` |
|
||||
| `element.classList.add(...)` | يرمي استثناء (`classList` هو `undefined`) | قم ببناء سلسلة `className` بنفسك |
|
||||
| `document.getElementById()`, `getElementsByClassName()`, `createTreeWalker()` | يرمي استثناء | `querySelector()` / `querySelectorAll()`, والتي تعمل |
|
||||
| `document.activeElement` | دائمًا `undefined` | تتبّع التركيز باستخدام `onFocus` / `onBlur` |
|
||||
| `\<canvas>` | لا يَرسُم أي شيء، بدون خطأ | استخدم SVG، أو ارسم خارج الشاشة ثم اعرض `<img src={dataUrl}>` |
|
||||
| `createPortal(node, document.body)` | لا يَرسُم أي شيء، بينما `isConnected` يُبلغ عن النجاح | استخدم الطبقات العائمة (overlays) داخل التخطيط نفسه مع `position: absolute`، أو مرّر إلى المكتبة عنصر الحاوية الخاص بك |
|
||||
|
||||
The portal gap is why Radix, Headless UI, MUI and react-select popovers render nothing by default. Most accept a container prop; point it at an element you rendered.
|
||||
فجوة الـ portal هي السبب في أن عناصر popover في Radix و Headless UI و MUI و react-select لا ترسُم أي شيء بشكل افتراضي. معظمها يقبل خاصية container؛ وجّهها إلى عنصر قمت بترسيمه.
|
||||
|
||||
### Events
|
||||
### الأحداث
|
||||
|
||||
Mouse, pointer, touch, drag, keyboard, focus, `input`/`change`/`submit`, `scroll`/`wheel`/`contextmenu` and `animationend`/`transitionend` cross to the host, plus a few per element: `load`/`error` on `<img>`, clipboard and composition on `<input>`/`\<textarea>`, media on `\<video>`/`\<audio>`, `toggle` on `\<details>`/`\<dialog>`. Anything else (`onAuxClick`, `onSelect`, `onInvalid`, `onReset`, `onAnimationStart`, pointer capture, `onLoad` off `<img>`) is dropped without warning.
|
||||
أحداث الماوس، والمؤشر، واللمس، والسحب، ولوحة المفاتيح، والتركيز، و`input`/`change`/`submit`، و`scroll`/`wheel`/`contextmenu` و`animationend`/`transitionend` تمر إلى المضيف، بالإضافة إلى عدد قليل لكل عنصر: `load`/`error` على `<img>`، والحافظة والتكوين على `<input>`/`\<textarea>`، والوسائط على `\<video>`/`\<audio>`، و`toggle` على `\<details>`/`\<dialog>`. أي شيء آخر (`onAuxClick`, `onSelect`, `onInvalid`, `onReset`, `onAnimationStart`, التقاط المؤشر، `onLoad` خارج `<img>`) يتم إسقاطه دون تحذير.
|
||||
|
||||
`document.addEventListener()` and `window.addEventListener()` register without error and never fire, which is why a drag stops as soon as the pointer leaves the element it started on. `event.preventDefault()` does not cross either; form submission, `dragover`/`drop` and link clicks are already guarded for you.
|
||||
`document.addEventListener()` و `window.addEventListener()` تُسجِّلان بدون خطأ لكن لا تُطلقان أبدًا، وهذا هو السبب في أن السحب يتوقف بمجرد أن يغادر المؤشر العنصر الذي بدأ عليه. `event.preventDefault()` لا يعبر أيضًا؛ إرسال النماذج، و`dragover`/`drop` ونقرات الروابط محمية مسبقًا من أجلك.
|
||||
|
||||
### Attributes and styling
|
||||
### السمات والأنماط
|
||||
|
||||
Each element forwards its own properties to the host DOM (`href` on `\<a>`, `src`/`alt` on `<img>`, `value`/`placeholder`/`disabled` on `<input>`, and so on), plus a common set on every element: `id`, `className`, `style`, `title`, `tabIndex`, `role`, `draggable` and any `aria-*` / `data-*` attribute (hyphenated, so `ariaLabel` is dropped). Anything outside that is silently discarded, so express custom state as `data-*`.
|
||||
كل عنصر يمرّر خصائصه الخاصة إلى DOM المضيف (`href` على `\<a>`, و `src`/`alt` على `<img>`, و `value`/`placeholder`/`disabled` على `<input>`, وهكذا)، بالإضافة إلى مجموعة مشتركة على كل عنصر: `id`, `className`, `style`, `title`, `tabIndex`, `role`, `draggable` وأي سمة `aria-*` / `data-*` (مفصولة بشرطات، لذا يتم إسقاط `ariaLabel`). أي شيء خارج ذلك يتم تجاهله بصمت، لذا عبّر عن الحالة المخصّصة كـ `data-*`.
|
||||
|
||||
Component CSS, whether from `import './styles.css'`, CSS-in-JS or a `\<style>` element, is injected into the host page's `\<head>` **unscoped**. So class names collide with Twenty's own (prefix them, and never write bare `div { ... }` selectors), and `@media` matches the browser window rather than your widget (use `@container` with your own `container-type`). Inline `style` props are unaffected.
|
||||
يتم حقن CSS الخاص بالمكوّن، سواءً من `import './styles.css'` أو CSS-in-JS أو عنصر `\<style>`، في وسم `\<head>` لصفحة المضيف **بدون نطاق**. لذا تتصادم أسماء الأصناف مع أسماء Twenty نفسها (قم بإضافة بادئة لها، ولا تكتب أبدًا محددًا مثل `div { ... }`)، و `@media` تطابِق نافذة المتصفح بدلاً من الودجت الخاص بك (استخدم `@container` مع `container-type` الخاص بك). خصائص `style` المضمنة لا تتأثر.
|
||||
|
||||
### Storage and network
|
||||
### التخزين والشبكة
|
||||
|
||||
`localStorage`, `sessionStorage`, IndexedDB, cookies, the Cache API and `BroadcastChannel` are all unavailable, since the component runs in a worker at an opaque origin. To persist state, call a [logic function](/l/ar/developers/extend/apps/logic/logic-functions) and use its [key-value store](/l/ar/developers/extend/apps/logic/key-value-store).
|
||||
`localStorage` و`sessionStorage` وIndexedDB وملفات تعريف الارتباط وواجهة برمجة تطبيقات Cache و`BroadcastChannel` كلها غير متاحة، لأن المكوّن يعمل في عامل (worker) بأصل غير شفاف. للاحتفاظ بالحالة، استدعِ [دالة منطقية](/l/ar/developers/extend/apps/logic/logic-functions) واستخدم [مخزن القيم المفتاحية](/l/ar/developers/extend/apps/logic/key-value-store) الخاص بها.
|
||||
|
||||
`fetch` works, with caveats:
|
||||
`fetch` يعمل، مع بعض التحفّظات:
|
||||
|
||||
* Calls to the Twenty API and your app's routes are proxied by the host, so prefer [`RestApiClient`](#calling-the-twenty-rest-api). On proxied calls, `AbortSignal` and the other `RequestInit` options are dropped, and only `string` and `URLSearchParams` bodies are supported.
|
||||
* Other origins leave the sandbox with `Origin: null`, so a third-party API answers only if it sends `Access-Control-Allow-Origin: *`. Call it from a logic function instead.
|
||||
* `fetch('/rest/people')` is never matched to the Twenty API, because the sandbox has no page URL to resolve a relative path against.
|
||||
* يتم تمرير الاستدعاءات إلى Twenty API ومسارات تطبيقك عبر المضيف، لذا يُفضَّل استخدام [`RestApiClient`](#calling-the-twenty-rest-api). في الاستدعاءات الممرَّرة عبر الوكيل، يتم إسقاط `AbortSignal` وخيارات `RequestInit` الأخرى، ولا يتم دعم سوى الأجسام من نوع `string` و`URLSearchParams`.
|
||||
* تغادر النطاقات (origins) الأخرى صندوق العزل مع `Origin: null`، لذلك يجيب طرف ثالث لواجهة برمجة التطبيقات فقط إذا أرسل `Access-Control-Allow-Origin: *`. استدعِها من دالة منطقية بدلًا من ذلك.
|
||||
* `fetch('/rest/people')` لا يتطابق أبدًا مع Twenty API، لأن صندوق العزل ليس لديه عنوان URL للصفحة لحساب مسار نسبي بناءً عليه.
|
||||
|
||||
### Other gaps
|
||||
### فجوات أخرى
|
||||
|
||||
* **File contents.** `<input type="file">` gives your handler file metadata only, not the bytes, so `FileReader` and uploads are not possible yet.
|
||||
* **Drag-and-drop payloads.** Drag events fire, but `event.dataTransfer` is `undefined`.
|
||||
* **Node built-ins.** `fs`, `path` and `node:crypto` fail the build, so move that work into a [logic function](/l/ar/developers/extend/apps/logic/logic-functions). Web Crypto, `fetch`, `TextEncoder` and `URL` are available.
|
||||
* **`\<iframe>`** is always re-sandboxed without `allow-same-origin`, so an embed relying on its own session renders logged out. It has no `onLoad` either.
|
||||
* **محتويات الملفات.** يُرجِع `<input type="file">` إلى معالجك بيانات تعريف الملف فقط، وليس البايتات، لذلك فإن `FileReader` وعمليات الرفع غير ممكنة بعد.
|
||||
* **حمولات السحب والإفلات.** أحداث السحب تُطلق، لكن `event.dataTransfer` هي `undefined`.
|
||||
* **الوحدات المدمجة في Node.** `fs` و`path` و`node:crypto` تفشل في عملية البناء، لذا انقل ذلك العمل إلى [دالة منطقية](/l/ar/developers/extend/apps/logic/logic-functions). Web Crypto و `fetch` و `TextEncoder` و `URL` متوفرة.
|
||||
* يتم دائمًا إعادة عزل **`\<iframe>`** دون `allow-same-origin`، لذلك يعمل التضمين الذي يعتمد على جلسته الخاصة في وضع "تسجيل الخروج". ليس لديه `onLoad` أيضًا.
|
||||
|
||||
@@ -7,7 +7,7 @@ icon: window-maximize
|
||||
Frontendové komponenty jsou React komponenty, které se vykreslují přímo v uživatelském rozhraní Twenty. Běží v **izolovaném Web Workeru** s využitím Remote DOM — váš kód se spouští uvnitř sandboxovaného iframe s nejasným původem (opaque-origin), ale jeho UI se stále vykresluje nativně na stránce, místo aby bylo omezené na tento iframe.
|
||||
|
||||
<Warning>
|
||||
Komponenty Front jsou stále aktivně vyvíjeny. Váš kód běží nad částečným DOMem, nikoli nad skutečnou stránkou prohlížeče, takže pokročilé způsoby použití mohou selhávat, často bez zjevných chyb. Viz [Současná omezení](#current-limitations).
|
||||
Komponenty Front jsou stále aktivně vyvíjeny. Váš kód běží nad částečným DOMem, nikoli nad skutečnou stránkou prohlížeče, takže pokročilé způsoby použití mohou selhávat, často bez zjevných chyb. Viz [Aktuální omezení](#current-limitations).
|
||||
</Warning>
|
||||
|
||||
## Kde lze použít frontendové komponenty
|
||||
@@ -703,69 +703,69 @@ Chcete-li se explicitně větvit podle aktivního schématu, načtěte jej pomoc
|
||||
|
||||
## Aktuální omezení
|
||||
|
||||
Front components are under active development. Rendering, styling and handling events works well. Anything that reaches *past* rendering (measuring an element, calling a DOM method on a ref, portaling outside your tree, touching browser storage) is missing or incomplete today, and most of it fails silently: no exception, and no TypeScript error either, since the scaffold is typed against the full browser DOM.
|
||||
Komponenty Front jsou aktivně vyvíjeny. Renderování, stylování a obsluha událostí fungují dobře. Cokoli, co sahá *mimo* samotné renderování (měření prvku, volání metody DOM na refu, vytváření portálu mimo váš strom, práce s úložištěm prohlížeče), dnes chybí nebo je nekompletní a většinou to selhává tiše: bez výjimky a bez chyby TypeScriptu, protože kostra je typovaná proti plnému DOMu prohlížeče.
|
||||
|
||||
If one of these blocks you, [open an issue](https://github.com/twentyhq/twenty/issues/new/choose) so it gets prioritized.
|
||||
Pokud vás něco z toho blokuje, [vytvořte issue](https://github.com/twentyhq/twenty/issues/new/choose), aby to bylo upřednostněno.
|
||||
|
||||
### Layout and measurement
|
||||
### Rozvržení a měření
|
||||
|
||||
Nothing can measure itself yet.
|
||||
Zatím se nic nemůže samo změřit.
|
||||
|
||||
| API | What happens |
|
||||
| ------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
|
||||
| `getBoundingClientRect()`, `getClientRects()` | Throws |
|
||||
| `offsetWidth`, `clientWidth`, `scrollWidth`, `offsetTop`, ... | Silently `undefined`, so `width ?? 0` yields `0` and `width > 600` is always false |
|
||||
| `ResizeObserver`, `IntersectionObserver` | `ReferenceError` (`typeof` guards do work) |
|
||||
| `window.matchMedia()`, `window.getComputedStyle()` | Throws |
|
||||
| `window.innerWidth`, `innerHeight`, `devicePixelRatio` | Silently `undefined` |
|
||||
| `new MutationObserver(fn)` | Constructs, then `.observe()` throws |
|
||||
| API | Co se stane |
|
||||
| ------------------------------------------------------------- | ------------------------------------------------------------------------------- |
|
||||
| `getBoundingClientRect()`, `getClientRects()` | Vyvolá výjimku |
|
||||
| `offsetWidth`, `clientWidth`, `scrollWidth`, `offsetTop`, ... | Tiše `undefined`, takže `width ?? 0` vrátí `0` a `width > 600` je vždycky false |
|
||||
| `ResizeObserver`, `IntersectionObserver` | `ReferenceError` (ochrany pomocí `typeof` fungují) |
|
||||
| `window.matchMedia()`, `window.getComputedStyle()` | Vyvolá výjimku |
|
||||
| `window.innerWidth`, `innerHeight`, `devicePixelRatio` | Tiše `undefined` |
|
||||
| `new MutationObserver(fn)` | Zkonstruuje se, pak `.observe()` vyvolá výjimku |
|
||||
|
||||
So recharts `ResponsiveContainer`, Floating UI / Popper, list virtualization and drag-to-resize do not work yet. Do layout in CSS instead: your stylesheet reaches the real page, so flexbox, grid, `aspect-ratio`, `clamp()` and `@container` all behave normally.
|
||||
Takže recharts `ResponsiveContainer`, Floating UI / Popper, virtualizace seznamů a táhnutí pro změnu velikosti zatím nefungují. Místo toho dělejte rozvržení v CSS: váš stylesheet se dostane ke skutečné stránce, takže flexbox, grid, `aspect-ratio`, `clamp()` i `@container` se chovají normálně.
|
||||
|
||||
<Note>
|
||||
`requestAnimationFrame`, `fetch`, `setTimeout` and `queueMicrotask` work without the `window.` prefix. Only `window.requestAnimationFrame(...)` and friends throw.
|
||||
`requestAnimationFrame`, `fetch`, `setTimeout` a `queueMicrotask` fungují bez prefixu `window.`. Pouze `window.requestAnimationFrame(...)` a podobné volání vyvolají výjimku.
|
||||
</Note>
|
||||
|
||||
### DOM access
|
||||
### Přístup k DOMu
|
||||
|
||||
A `ref` gives you a sandbox element, not an `HTMLElement`.
|
||||
`ref` vám dává sandboxový prvek, ne `HTMLElement`.
|
||||
|
||||
| What you write | What happens | Use instead |
|
||||
| ----------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- | ----------------------------------------------------------------------------------------- |
|
||||
| `ref.current.focus()`, `.click()`, `.select()`, `.setSelectionRange()`, `.scrollIntoView()`, `video.play()` | Throws | Controlled components; read values from `event.target` |
|
||||
| `element.classList.add(...)` | Throws (`classList` is `undefined`) | Build the `className` string yourself |
|
||||
| `document.getElementById()`, `getElementsByClassName()`, `createTreeWalker()` | Throws | `querySelector()` / `querySelectorAll()`, which work |
|
||||
| `document.activeElement` | Always `undefined` | Track focus with `onFocus` / `onBlur` |
|
||||
| `\<canvas>` | Renders nothing, no error | SVG, or draw offscreen and show an `<img src={dataUrl}>` |
|
||||
| `createPortal(node, document.body)` | Renders nothing, while `isConnected` reports success | Overlays inline with `position: absolute`, or pass the library your own container element |
|
||||
| Co napíšete | Co se stane | Co použít místo toho |
|
||||
| ----------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
|
||||
| `ref.current.focus()`, `.click()`, `.select()`, `.setSelectionRange()`, `.scrollIntoView()`, `video.play()` | Vyvolá výjimku | Řízené komponenty; čtěte hodnoty z `event.target` |
|
||||
| `element.classList.add(...)` | Vyvolá výjimku (`classList` je `undefined`) | Sestavte si řetězec `className` sami |
|
||||
| `document.getElementById()`, `getElementsByClassName()`, `createTreeWalker()` | Vyvolá výjimku | `querySelector()` / `querySelectorAll()`, které fungují |
|
||||
| `document.activeElement` | Vždy `undefined` | Sledujte fokus pomocí `onFocus` / `onBlur` |
|
||||
| `\<canvas>` | Nerenderuje nic, žádná chyba | SVG, nebo kreslete offscreen a zobrazte `<img src={dataUrl}>` |
|
||||
| `createPortal(node, document.body)` | Nerenderuje nic, zatímco `isConnected` hlásí úspěch | Překryvné prvky inline pomocí `position: absolute`, nebo knihovně předávejte vlastní kontejnerový prvek |
|
||||
|
||||
The portal gap is why Radix, Headless UI, MUI and react-select popovers render nothing by default. Most accept a container prop; point it at an element you rendered.
|
||||
Kvůli této mezeře v portálu popovery Radix, Headless UI, MUI a react-select ve výchozím stavu nic nevyrenderují. Většina z nich přijímá prop pro kontejner; nasměrujte ho na prvek, který jste vyrenderovali.
|
||||
|
||||
### Události
|
||||
|
||||
Mouse, pointer, touch, drag, keyboard, focus, `input`/`change`/`submit`, `scroll`/`wheel`/`contextmenu` and `animationend`/`transitionend` cross to the host, plus a few per element: `load`/`error` on `<img>`, clipboard and composition on `<input>`/`\<textarea>`, media on `\<video>`/`\<audio>`, `toggle` on `\<details>`/`\<dialog>`. Anything else (`onAuxClick`, `onSelect`, `onInvalid`, `onReset`, `onAnimationStart`, pointer capture, `onLoad` off `<img>`) is dropped without warning.
|
||||
Události myši, ukazatele, dotyku, tažení, klávesnice, fokusu, `input`/`change`/`submit`, `scroll`/`wheel`/`contextmenu` a `animationend`/`transitionend` přecházejí do hostitele, plus několik specifických pro prvek: `load`/`error` na `<img>`, schránka a kompozice na `<input>`/`\<textarea>`, média na `\<video>`/`\<audio>`, `toggle` na `\<details>`/`\<dialog>`. Cokoli dalšího (`onAuxClick`, `onSelect`, `onInvalid`, `onReset`, `onAnimationStart`, zachycení ukazatele (pointer capture), `onLoad` na `<img>`) je bez varování zahazováno.
|
||||
|
||||
`document.addEventListener()` and `window.addEventListener()` register without error and never fire, which is why a drag stops as soon as the pointer leaves the element it started on. `event.preventDefault()` does not cross either; form submission, `dragover`/`drop` and link clicks are already guarded for you.
|
||||
`document.addEventListener()` a `window.addEventListener()` se zaregistrují bez chyby, ale nikdy se nespustí, což je důvod, proč se přetažení zastaví, jakmile ukazatel opustí prvek, na kterém začalo. Ani `event.preventDefault()` se nepřenáší; odeslání formuláře, `dragover`/`drop` a kliknutí na odkazy jsou už za vás ošetřené.
|
||||
|
||||
### Attributes and styling
|
||||
### Atributy a stylování
|
||||
|
||||
Each element forwards its own properties to the host DOM (`href` on `\<a>`, `src`/`alt` on `<img>`, `value`/`placeholder`/`disabled` on `<input>`, and so on), plus a common set on every element: `id`, `className`, `style`, `title`, `tabIndex`, `role`, `draggable` and any `aria-*` / `data-*` attribute (hyphenated, so `ariaLabel` is dropped). Anything outside that is silently discarded, so express custom state as `data-*`.
|
||||
Každý prvek předává své vlastní vlastnosti do hostitelského DOMu (`href` na `\<a>`, `src`/`alt` na `<img>`, `value`/`placeholder`/`disabled` na `<input>` atd.) plus společnou sadu na každém prvku: `id`, `className`, `style`, `title`, `tabIndex`, `role`, `draggable` a jakýkoli atribut `aria-*` / `data-*` (s pomlčkou, takže `ariaLabel` je zahozena). Cokoli mimo tento rozsah je tiše zahazováno, takže vlastní stav vyjádřete jako `data-*`.
|
||||
|
||||
Component CSS, whether from `import './styles.css'`, CSS-in-JS or a `\<style>` element, is injected into the host page's `\<head>` **unscoped**. So class names collide with Twenty's own (prefix them, and never write bare `div { ... }` selectors), and `@media` matches the browser window rather than your widget (use `@container` with your own `container-type`). Inline `style` props are unaffected.
|
||||
Komponentové CSS, ať už z `import './styles.css'`, CSS-in-JS nebo z prvku `\<style>`, je do `\<head>` hostitelské stránky vkládáno **bez ohraničení (unscoped)**. Třídy se tak střetávají s vlastními třídami Twenty (přidávejte jim předpony a nikdy nepište holé `div { ... }` selektory) a `@media` se vztahuje k oknu prohlížeče, nikoli k vašemu widgetu (použijte `@container` s vlastním `container-type`). Inline propy `style` nejsou ovlivněny.
|
||||
|
||||
### Storage and network
|
||||
### Úložiště a síť
|
||||
|
||||
`localStorage`, `sessionStorage`, IndexedDB, cookies, the Cache API and `BroadcastChannel` are all unavailable, since the component runs in a worker at an opaque origin. To persist state, call a [logic function](/l/cs/developers/extend/apps/logic/logic-functions) and use its [key-value store](/l/cs/developers/extend/apps/logic/key-value-store).
|
||||
`localStorage`, `sessionStorage`, IndexedDB, cookies, Cache API a `BroadcastChannel` nejsou vůbec k dispozici, protože komponenta běží ve workeru na neprůhledném (opaque) původu. Pro uchování stavu zavolejte [logickou funkci](/l/cs/developers/extend/apps/logic/logic-functions) a použijte její [úložiště klíč–hodnota](/l/cs/developers/extend/apps/logic/key-value-store).
|
||||
|
||||
`fetch` works, with caveats:
|
||||
`fetch` funguje, s výhradami:
|
||||
|
||||
* Calls to the Twenty API and your app's routes are proxied by the host, so prefer [`RestApiClient`](#calling-the-twenty-rest-api). On proxied calls, `AbortSignal` and the other `RequestInit` options are dropped, and only `string` and `URLSearchParams` bodies are supported.
|
||||
* Other origins leave the sandbox with `Origin: null`, so a third-party API answers only if it sends `Access-Control-Allow-Origin: *`. Call it from a logic function instead.
|
||||
* `fetch('/rest/people')` is never matched to the Twenty API, because the sandbox has no page URL to resolve a relative path against.
|
||||
* Volání na Twenty API a trasy (routes) vaší aplikace jsou proxyována hostitelem, proto upřednostněte [`RestApiClient`](#calling-the-twenty-rest-api). U proxyovaných volání jsou `AbortSignal` a ostatní volby `RequestInit` zahazovány a jsou podporována pouze těla typu `string` a `URLSearchParams`.
|
||||
* Jiné původy opouštějí sandbox s `Origin: null`, takže API třetí strany odpoví jen tehdy, pokud posílá `Access-Control-Allow-Origin: *`. Místo toho jej volejte z logické funkce.
|
||||
* `fetch('/rest/people')` se nikdy nespáruje s Twenty API, protože sandbox nemá URL stránky, podle které by vyhodnotil relativní cestu.
|
||||
|
||||
### Other gaps
|
||||
### Další omezení
|
||||
|
||||
* **File contents.** `<input type="file">` gives your handler file metadata only, not the bytes, so `FileReader` and uploads are not possible yet.
|
||||
* **Drag-and-drop payloads.** Drag events fire, but `event.dataTransfer` is `undefined`.
|
||||
* **Node built-ins.** `fs`, `path` and `node:crypto` fail the build, so move that work into a [logic function](/l/cs/developers/extend/apps/logic/logic-functions). Web Crypto, `fetch`, `TextEncoder` and `URL` are available.
|
||||
* **`\<iframe>`** is always re-sandboxed without `allow-same-origin`, so an embed relying on its own session renders logged out. It has no `onLoad` either.
|
||||
* **Obsah souborů.** `<input type="file">` poskytuje vašemu handleru pouze metadata souboru, nikoli samotné bajty, takže `FileReader` a nahrávání zatím nejsou možná.
|
||||
* **Payloady drag-and-drop.** Události tažení se spouštějí, ale `event.dataTransfer` je `undefined`.
|
||||
* **Vestavěné moduly Node.** `fs`, `path` a `node:crypto` způsobí chybu při sestavení, takže tuto práci přesuňte do [logické funkce](/l/cs/developers/extend/apps/logic/logic-functions). Web Crypto, `fetch`, `TextEncoder` a `URL` jsou k dispozici.
|
||||
* **`\<iframe>`** je vždy znovu zasandboxováno bez `allow-same-origin`, takže vložený obsah spoléhající se na vlastní relaci se vykreslí jako odhlášený. Nemá ani `onLoad`.
|
||||
|
||||
@@ -56,4 +56,4 @@ icon: table-columns
|
||||
|
||||
Frontendové komponenty běží uvnitř izolovaného Web Workeru pomocí Remote DOM — vykreslují se na stránce nativně (ne uvnitř iframe), ale nemají přímý přístup k hostitelské stránce ani DOM. Komunikace s Twenty probíhá prostřednictvím hostitelského API pro předávání zpráv.
|
||||
|
||||
Stále jsou ve vývoji: sandbox implementuje částečné DOM, takže pokročilá použití mohou selhat. Viz [Aktuální omezení](/l/cs/developers/extend/apps/layout/front-components#current-limitations).
|
||||
Stále jsou v aktivním vývoji: sandbox implementuje částečný DOM, takže pokročilá použití mohou selhat. Viz [Aktuální omezení](/l/cs/developers/extend/apps/layout/front-components#current-limitations).
|
||||
|
||||
@@ -703,69 +703,69 @@ Um explizit nach dem aktiven Schema zu verzweigen, lesen Sie es mit `useColorSch
|
||||
|
||||
## Aktuelle Einschränkungen
|
||||
|
||||
Front components are under active development. Rendering, styling and handling events works well. Anything that reaches *past* rendering (measuring an element, calling a DOM method on a ref, portaling outside your tree, touching browser storage) is missing or incomplete today, and most of it fails silently: no exception, and no TypeScript error either, since the scaffold is typed against the full browser DOM.
|
||||
Front-Komponenten befinden sich in aktiver Entwicklung. Rendern, Styling und das Behandeln von Ereignissen funktionieren gut. Alles, was *über* das Rendern hinausgeht (Messen eines Elements, Aufrufen einer DOM-Methode auf einem Ref, Portaling außerhalb deines Baums, Zugriff auf den Browser-Speicher), fehlt heute noch oder ist unvollständig, und das meiste davon schlägt stillschweigend fehl: keine Exception und auch kein TypeScript-Fehler, da das Gerüst gegen das vollständige Browser-DOM typisiert ist.
|
||||
|
||||
If one of these blocks you, [open an issue](https://github.com/twentyhq/twenty/issues/new/choose) so it gets prioritized.
|
||||
Wenn dich eines dieser Probleme blockiert, [eröffne ein Issue](https://github.com/twentyhq/twenty/issues/new/choose), damit es priorisiert wird.
|
||||
|
||||
### Layout and measurement
|
||||
### Layout und Messung
|
||||
|
||||
Nothing can measure itself yet.
|
||||
Noch kann sich nichts selbst messen.
|
||||
|
||||
| API | What happens |
|
||||
| ------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
|
||||
| `getBoundingClientRect()`, `getClientRects()` | Throws |
|
||||
| `offsetWidth`, `clientWidth`, `scrollWidth`, `offsetTop`, ... | Silently `undefined`, so `width ?? 0` yields `0` and `width > 600` is always false |
|
||||
| `ResizeObserver`, `IntersectionObserver` | `ReferenceError` (`typeof` guards do work) |
|
||||
| `window.matchMedia()`, `window.getComputedStyle()` | Throws |
|
||||
| `window.innerWidth`, `innerHeight`, `devicePixelRatio` | Silently `undefined` |
|
||||
| `new MutationObserver(fn)` | Constructs, then `.observe()` throws |
|
||||
| API | Was passiert |
|
||||
| ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
|
||||
| `getBoundingClientRect()`, `getClientRects()` | Löst eine Exception aus |
|
||||
| `offsetWidth`, `clientWidth`, `scrollWidth`, `offsetTop`, ... | Stillschweigend `undefined`, daher ergibt `width ?? 0` den Wert `0` und `width > 600` ist immer falsch |
|
||||
| `ResizeObserver`, `IntersectionObserver` | `ReferenceError` (`typeof`-Guards funktionieren) |
|
||||
| `window.matchMedia()`, `window.getComputedStyle()` | Löst eine Exception aus |
|
||||
| `window.innerWidth`, `innerHeight`, `devicePixelRatio` | Stillschweigend `undefined` |
|
||||
| `new MutationObserver(fn)` | Wird konstruiert, dann löst `.observe()` eine Exception aus |
|
||||
|
||||
So recharts `ResponsiveContainer`, Floating UI / Popper, list virtualization and drag-to-resize do not work yet. Do layout in CSS instead: your stylesheet reaches the real page, so flexbox, grid, `aspect-ratio`, `clamp()` and `@container` all behave normally.
|
||||
Daher funktionieren recharts `ResponsiveContainer`, Floating UI / Popper, Listen-Virtualisierung und Drag-to-Resize noch nicht. Führe das Layout stattdessen in CSS aus: Dein Stylesheet erreicht die echte Seite, daher verhalten sich Flexbox, Grid, `aspect-ratio`, `clamp()` und `@container` alle normal.
|
||||
|
||||
<Note>
|
||||
`requestAnimationFrame`, `fetch`, `setTimeout` and `queueMicrotask` work without the `window.` prefix. Only `window.requestAnimationFrame(...)` and friends throw.
|
||||
`requestAnimationFrame`, `fetch`, `setTimeout` und `queueMicrotask` funktionieren ohne das Präfix `window.`. Nur `window.requestAnimationFrame(...)` und ähnliche Aufrufe lösen eine Exception aus.
|
||||
</Note>
|
||||
|
||||
### DOM access
|
||||
### DOM-Zugriff
|
||||
|
||||
A `ref` gives you a sandbox element, not an `HTMLElement`.
|
||||
Ein `ref` gibt dir ein Sandbox-Element, kein `HTMLElement`.
|
||||
|
||||
| What you write | What happens | Use instead |
|
||||
| ----------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- | ----------------------------------------------------------------------------------------- |
|
||||
| `ref.current.focus()`, `.click()`, `.select()`, `.setSelectionRange()`, `.scrollIntoView()`, `video.play()` | Throws | Controlled components; read values from `event.target` |
|
||||
| `element.classList.add(...)` | Throws (`classList` is `undefined`) | Build the `className` string yourself |
|
||||
| `document.getElementById()`, `getElementsByClassName()`, `createTreeWalker()` | Throws | `querySelector()` / `querySelectorAll()`, which work |
|
||||
| `document.activeElement` | Always `undefined` | Track focus with `onFocus` / `onBlur` |
|
||||
| `\<canvas>` | Renders nothing, no error | SVG, or draw offscreen and show an `<img src={dataUrl}>` |
|
||||
| `createPortal(node, document.body)` | Renders nothing, while `isConnected` reports success | Overlays inline with `position: absolute`, or pass the library your own container element |
|
||||
| Was du schreibst | Was passiert | Stattdessen verwenden |
|
||||
| ----------------------------------------------------------------------------------------------------------- | ----------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
|
||||
| `ref.current.focus()`, `.click()`, `.select()`, `.setSelectionRange()`, `.scrollIntoView()`, `video.play()` | Löst eine Exception aus | Gesteuerte Komponenten; Werte aus `event.target` auslesen |
|
||||
| `element.classList.add(...)` | Löst eine Exception aus (`classList` ist `undefined`) | Erstelle den `className`-String selbst |
|
||||
| `document.getElementById()`, `getElementsByClassName()`, `createTreeWalker()` | Löst eine Exception aus | `querySelector()` / `querySelectorAll()`, die funktionieren |
|
||||
| `document.activeElement` | Immer `undefined` | Fokus mit `onFocus` / `onBlur` verfolgen |
|
||||
| `\<canvas>` | Rendert nichts, keine Fehlermeldung | SVG verwenden oder Offscreen zeichnen und ein `<img src={dataUrl}>` anzeigen |
|
||||
| `createPortal(node, document.body)` | Rendert nichts, während `isConnected` Erfolg meldet | Overlays inline mit `position: absolute` oder der Bibliothek dein eigenes Container-Element übergeben |
|
||||
|
||||
The portal gap is why Radix, Headless UI, MUI and react-select popovers render nothing by default. Most accept a container prop; point it at an element you rendered.
|
||||
Diese Portal-Lücke ist der Grund, warum Radix-, Headless-UI-, MUI- und react-select-Popover standardmäßig nichts rendern. Die meisten akzeptieren eine Container-Prop; verweise sie auf ein Element, das du gerendert hast.
|
||||
|
||||
### Ereignisse
|
||||
|
||||
Mouse, pointer, touch, drag, keyboard, focus, `input`/`change`/`submit`, `scroll`/`wheel`/`contextmenu` and `animationend`/`transitionend` cross to the host, plus a few per element: `load`/`error` on `<img>`, clipboard and composition on `<input>`/`\<textarea>`, media on `\<video>`/`\<audio>`, `toggle` on `\<details>`/`\<dialog>`. Anything else (`onAuxClick`, `onSelect`, `onInvalid`, `onReset`, `onAnimationStart`, pointer capture, `onLoad` off `<img>`) is dropped without warning.
|
||||
Maus, Zeiger, Touch, Drag, Tastatur, Fokus, `input`/`change`/`submit`, `scroll`/`wheel`/`contextmenu` und `animationend`/`transitionend` werden an den Host durchgereicht, plus ein paar pro Element: `load`/`error` auf `<img>`, Zwischenablage und Composition auf `<input>`/`\<textarea>`, Medien auf `\<video>`/`\<audio>`, `toggle` auf `\<details>`/`\<dialog>`. Alles andere (`onAuxClick`, `onSelect`, `onInvalid`, `onReset`, `onAnimationStart`, Pointer-Capture, `onLoad` von `<img>`) wird ohne Warnung verworfen.
|
||||
|
||||
`document.addEventListener()` and `window.addEventListener()` register without error and never fire, which is why a drag stops as soon as the pointer leaves the element it started on. `event.preventDefault()` does not cross either; form submission, `dragover`/`drop` and link clicks are already guarded for you.
|
||||
`document.addEventListener()` und `window.addEventListener()` werden ohne Fehler registriert und feuern nie, weshalb ein Drag aufhört, sobald der Zeiger das Element verlässt, auf dem er begonnen hat. `event.preventDefault()` wird ebenfalls nicht durchgereicht; Formularübermittlung, `dragover`/`drop` und Link-Klicks sind bereits für dich abgesichert.
|
||||
|
||||
### Attributes and styling
|
||||
### Attribute und Styling
|
||||
|
||||
Each element forwards its own properties to the host DOM (`href` on `\<a>`, `src`/`alt` on `<img>`, `value`/`placeholder`/`disabled` on `<input>`, and so on), plus a common set on every element: `id`, `className`, `style`, `title`, `tabIndex`, `role`, `draggable` and any `aria-*` / `data-*` attribute (hyphenated, so `ariaLabel` is dropped). Anything outside that is silently discarded, so express custom state as `data-*`.
|
||||
Jedes Element leitet seine eigenen Eigenschaften an den Host-DOM weiter (`href` auf `\<a>`, `src`/`alt` auf `<img>`, `value`/`placeholder`/`disabled` auf `<input>` usw.), plus einen gemeinsamen Satz auf jedem Element: `id`, `className`, `style`, `title`, `tabIndex`, `role`, `draggable` und jedes `aria-*`-/`data-*`-Attribut (mit Bindestrich, daher wird `ariaLabel` verworfen). Alles außerhalb davon wird stillschweigend verworfen, daher solltest du benutzerdefinierte Zustände als `data-*` ausdrücken.
|
||||
|
||||
Component CSS, whether from `import './styles.css'`, CSS-in-JS or a `\<style>` element, is injected into the host page's `\<head>` **unscoped**. So class names collide with Twenty's own (prefix them, and never write bare `div { ... }` selectors), and `@media` matches the browser window rather than your widget (use `@container` with your own `container-type`). Inline `style` props are unaffected.
|
||||
Component-CSS, egal ob aus `import './styles.css'`, CSS-in-JS oder einem `\<style>`-Element, wird **unscoped** in den `\<head>` der Host-Seite injiziert. Dadurch kollidieren Klassennamen mit denen von Twenty (präfixe sie und schreibe niemals nacktes `div { ... }`-Selektoren), und `@media` bezieht sich auf das Browserfenster statt auf dein Widget (verwende `@container` mit deinem eigenen `container-type`). Inline-`style`-Props sind nicht betroffen.
|
||||
|
||||
### Storage and network
|
||||
### Speicher und Netzwerk
|
||||
|
||||
`localStorage`, `sessionStorage`, IndexedDB, cookies, the Cache API and `BroadcastChannel` are all unavailable, since the component runs in a worker at an opaque origin. To persist state, call a [logic function](/l/de/developers/extend/apps/logic/logic-functions) and use its [key-value store](/l/de/developers/extend/apps/logic/key-value-store).
|
||||
`localStorage`, `sessionStorage`, IndexedDB, Cookies, die Cache-API und `BroadcastChannel` sind alle nicht verfügbar, da die Komponente in einem Worker unter einem undurchsichtigen Origin läuft. Um Zustand zu persistieren, rufe eine [Logic Function](/l/de/developers/extend/apps/logic/logic-functions) auf und verwende deren [Key-Value Store](/l/de/developers/extend/apps/logic/key-value-store).
|
||||
|
||||
`fetch` works, with caveats:
|
||||
`fetch` funktioniert, mit Einschränkungen:
|
||||
|
||||
* Calls to the Twenty API and your app's routes are proxied by the host, so prefer [`RestApiClient`](#calling-the-twenty-rest-api). On proxied calls, `AbortSignal` and the other `RequestInit` options are dropped, and only `string` and `URLSearchParams` bodies are supported.
|
||||
* Other origins leave the sandbox with `Origin: null`, so a third-party API answers only if it sends `Access-Control-Allow-Origin: *`. Call it from a logic function instead.
|
||||
* `fetch('/rest/people')` is never matched to the Twenty API, because the sandbox has no page URL to resolve a relative path against.
|
||||
* Aufrufe an die Twenty-API und die Routen deiner App werden vom Host als Proxy weitergeleitet, daher solltest du [`RestApiClient`](#calling-the-twenty-rest-api) bevorzugen. Bei proxied Aufrufen werden `AbortSignal` und die anderen `RequestInit`-Optionen verworfen, und es werden nur `string`- und `URLSearchParams`-Bodies unterstützt.
|
||||
* Andere Origins verlassen die Sandbox mit `Origin: null`, sodass eine Drittanbieter-API nur antwortet, wenn sie `Access-Control-Allow-Origin: *` sendet. Rufe sie stattdessen aus einer Logic Function auf.
|
||||
* `fetch('/rest/people')` wird niemals der Twenty-API zugeordnet, weil die Sandbox keine Seiten-URL hat, gegen die ein relativer Pfad aufgelöst werden könnte.
|
||||
|
||||
### Other gaps
|
||||
### Weitere Lücken
|
||||
|
||||
* **File contents.** `<input type="file">` gives your handler file metadata only, not the bytes, so `FileReader` and uploads are not possible yet.
|
||||
* **Drag-and-drop payloads.** Drag events fire, but `event.dataTransfer` is `undefined`.
|
||||
* **Node built-ins.** `fs`, `path` and `node:crypto` fail the build, so move that work into a [logic function](/l/de/developers/extend/apps/logic/logic-functions). Web Crypto, `fetch`, `TextEncoder` and `URL` are available.
|
||||
* **`\<iframe>`** is always re-sandboxed without `allow-same-origin`, so an embed relying on its own session renders logged out. It has no `onLoad` either.
|
||||
* **Dateiinhalt.** `<input type="file">` gibt deinem Handler nur Dateimetadaten, nicht die Bytes, daher sind `FileReader` und Uploads noch nicht möglich.
|
||||
* **Drag-and-drop-Nutzlasten.** Drag-Events werden ausgelöst, aber `event.dataTransfer` ist `undefined`.
|
||||
* **Node-Built-ins.** `fs`, `path` und `node:crypto` führen zu einem Build-Fehler, daher solltest du diese Arbeit in eine [Logic Function](/l/de/developers/extend/apps/logic/logic-functions) auslagern. Web Crypto, `fetch`, `TextEncoder` und `URL` sind verfügbar.
|
||||
* **`\<iframe>`** wird immer erneut ohne `allow-same-origin` sandboxed, sodass ein Embed, das von seiner eigenen Session abhängt, als ausgeloggt gerendert wird. Es hat auch kein `onLoad`.
|
||||
|
||||
@@ -703,69 +703,69 @@ Para hacer bifurcaciones explícitamente según el esquema activo, léelo con `u
|
||||
|
||||
## Limitaciones actuales
|
||||
|
||||
Front components are under active development. Rendering, styling and handling events works well. Anything that reaches *past* rendering (measuring an element, calling a DOM method on a ref, portaling outside your tree, touching browser storage) is missing or incomplete today, and most of it fails silently: no exception, and no TypeScript error either, since the scaffold is typed against the full browser DOM.
|
||||
Los componentes de Front están en desarrollo activo. El renderizado, el estilo y el manejo de eventos funcionan bien. Cualquier cosa que vaya *más allá* del renderizado (medir un elemento, llamar a un método del DOM en un ref, hacer portal fuera de tu árbol, acceder al almacenamiento del navegador) falta o está incompleta hoy, y la mayoría falla silenciosamente: no hay excepción ni error de TypeScript tampoco, ya que el andamiaje está tipado contra el DOM completo del navegador.
|
||||
|
||||
If one of these blocks you, [open an issue](https://github.com/twentyhq/twenty/issues/new/choose) so it gets prioritized.
|
||||
Si una de estas cosas te bloquea, [abre una incidencia](https://github.com/twentyhq/twenty/issues/new/choose) para que se priorice.
|
||||
|
||||
### Layout and measurement
|
||||
### Diseño y medición
|
||||
|
||||
Nothing can measure itself yet.
|
||||
Nada puede medirse a sí mismo todavía.
|
||||
|
||||
| API | What happens |
|
||||
| ------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
|
||||
| `getBoundingClientRect()`, `getClientRects()` | Throws |
|
||||
| `offsetWidth`, `clientWidth`, `scrollWidth`, `offsetTop`, ... | Silently `undefined`, so `width ?? 0` yields `0` and `width > 600` is always false |
|
||||
| `ResizeObserver`, `IntersectionObserver` | `ReferenceError` (`typeof` guards do work) |
|
||||
| `window.matchMedia()`, `window.getComputedStyle()` | Throws |
|
||||
| `window.innerWidth`, `innerHeight`, `devicePixelRatio` | Silently `undefined` |
|
||||
| `new MutationObserver(fn)` | Constructs, then `.observe()` throws |
|
||||
| API | Qué ocurre |
|
||||
| ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
|
||||
| `getBoundingClientRect()`, `getClientRects()` | Lanza una excepción |
|
||||
| `offsetWidth`, `clientWidth`, `scrollWidth`, `offsetTop`, ... | Silenciosamente `undefined`, por lo que `width ?? 0` produce `0` y `width > 600` siempre es falso |
|
||||
| `ResizeObserver`, `IntersectionObserver` | `ReferenceError` (las comprobaciones con `typeof` sí funcionan) |
|
||||
| `window.matchMedia()`, `window.getComputedStyle()` | Lanza una excepción |
|
||||
| `window.innerWidth`, `innerHeight`, `devicePixelRatio` | Silenciosamente `undefined` |
|
||||
| `new MutationObserver(fn)` | Se construye, luego `.observe()` lanza una excepción |
|
||||
|
||||
So recharts `ResponsiveContainer`, Floating UI / Popper, list virtualization and drag-to-resize do not work yet. Do layout in CSS instead: your stylesheet reaches the real page, so flexbox, grid, `aspect-ratio`, `clamp()` and `@container` all behave normally.
|
||||
Así que `ResponsiveContainer` de recharts, Floating UI / Popper, la virtualización de listas y arrastrar-para-redimensionar todavía no funcionan. Haz el diseño en CSS en su lugar: tu hoja de estilos llega a la página real, por lo que flexbox, grid, `aspect-ratio`, `clamp()` y `@container` se comportan con normalidad.
|
||||
|
||||
<Note>
|
||||
`requestAnimationFrame`, `fetch`, `setTimeout` and `queueMicrotask` work without the `window.` prefix. Only `window.requestAnimationFrame(...)` and friends throw.
|
||||
`requestAnimationFrame`, `fetch`, `setTimeout` y `queueMicrotask` funcionan sin el prefijo `window.`. Solo `window.requestAnimationFrame(...)` y similares lanzan una excepción.
|
||||
</Note>
|
||||
|
||||
### DOM access
|
||||
### Acceso al DOM
|
||||
|
||||
A `ref` gives you a sandbox element, not an `HTMLElement`.
|
||||
Un `ref` te da un elemento sandbox, no un `HTMLElement`.
|
||||
|
||||
| What you write | What happens | Use instead |
|
||||
| ----------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- | ----------------------------------------------------------------------------------------- |
|
||||
| `ref.current.focus()`, `.click()`, `.select()`, `.setSelectionRange()`, `.scrollIntoView()`, `video.play()` | Throws | Controlled components; read values from `event.target` |
|
||||
| `element.classList.add(...)` | Throws (`classList` is `undefined`) | Build the `className` string yourself |
|
||||
| `document.getElementById()`, `getElementsByClassName()`, `createTreeWalker()` | Throws | `querySelector()` / `querySelectorAll()`, which work |
|
||||
| `document.activeElement` | Always `undefined` | Track focus with `onFocus` / `onBlur` |
|
||||
| `\<canvas>` | Renders nothing, no error | SVG, or draw offscreen and show an `<img src={dataUrl}>` |
|
||||
| `createPortal(node, document.body)` | Renders nothing, while `isConnected` reports success | Overlays inline with `position: absolute`, or pass the library your own container element |
|
||||
| Lo que escribes | Qué ocurre | Usa en su lugar |
|
||||
| ----------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
|
||||
| `ref.current.focus()`, `.click()`, `.select()`, `.setSelectionRange()`, `.scrollIntoView()`, `video.play()` | Lanza una excepción | Componentes controlados; lee los valores de `event.target` |
|
||||
| `element.classList.add(...)` | Lanza una excepción (`classList` es `undefined`) | Construye tú mismo la cadena `className` |
|
||||
| `document.getElementById()`, `getElementsByClassName()`, `createTreeWalker()` | Lanza una excepción | `querySelector()` / `querySelectorAll()`, que sí funcionan |
|
||||
| `document.activeElement` | Siempre `undefined` | Controla el foco con `onFocus` / `onBlur` |
|
||||
| `\<canvas>` | No renderiza nada, sin error | SVG, o dibuja fuera de pantalla y muestra un `<img src={dataUrl}>` |
|
||||
| `createPortal(node, document.body)` | No renderiza nada, mientras que `isConnected` informa de éxito | Superposiciones en línea con `position: absolute`, o pasa a la biblioteca tu propio elemento contenedor |
|
||||
|
||||
The portal gap is why Radix, Headless UI, MUI and react-select popovers render nothing by default. Most accept a container prop; point it at an element you rendered.
|
||||
La brecha del portal es la razón por la que los popovers de Radix, Headless UI, MUI y react-select no renderizan nada de forma predeterminada. La mayoría acepta una prop de contenedor; apúntala a un elemento que hayas renderizado.
|
||||
|
||||
### Eventos
|
||||
|
||||
Mouse, pointer, touch, drag, keyboard, focus, `input`/`change`/`submit`, `scroll`/`wheel`/`contextmenu` and `animationend`/`transitionend` cross to the host, plus a few per element: `load`/`error` on `<img>`, clipboard and composition on `<input>`/`\<textarea>`, media on `\<video>`/`\<audio>`, `toggle` on `\<details>`/`\<dialog>`. Anything else (`onAuxClick`, `onSelect`, `onInvalid`, `onReset`, `onAnimationStart`, pointer capture, `onLoad` off `<img>`) is dropped without warning.
|
||||
Eventos de ratón, puntero, tacto, arrastre, teclado, foco, `input`/`change`/`submit`, `scroll`/`wheel`/`contextmenu` y `animationend`/`transitionend` pasan al host, además de algunos específicos por elemento: `load`/`error` en `<img>`, portapapeles y composición en `<input>`/`\<textarea>`, medios en `\<video>`/`\<audio>`, `toggle` en `\<details>`/`\<dialog>`. Cualquier otra cosa (`onAuxClick`, `onSelect`, `onInvalid`, `onReset`, `onAnimationStart`, captura de puntero, `onLoad` fuera de `<img>`) se descarta sin aviso.
|
||||
|
||||
`document.addEventListener()` and `window.addEventListener()` register without error and never fire, which is why a drag stops as soon as the pointer leaves the element it started on. `event.preventDefault()` does not cross either; form submission, `dragover`/`drop` and link clicks are already guarded for you.
|
||||
`document.addEventListener()` y `window.addEventListener()` se registran sin error y nunca se disparan, lo que explica por qué un arrastre se detiene tan pronto como el puntero sale del elemento en el que comenzó. `event.preventDefault()` tampoco cruza; el envío de formularios, `dragover`/`drop` y los clics en enlaces ya están protegidos por ti.
|
||||
|
||||
### Attributes and styling
|
||||
### Atributos y estilos
|
||||
|
||||
Each element forwards its own properties to the host DOM (`href` on `\<a>`, `src`/`alt` on `<img>`, `value`/`placeholder`/`disabled` on `<input>`, and so on), plus a common set on every element: `id`, `className`, `style`, `title`, `tabIndex`, `role`, `draggable` and any `aria-*` / `data-*` attribute (hyphenated, so `ariaLabel` is dropped). Anything outside that is silently discarded, so express custom state as `data-*`.
|
||||
Cada elemento reenvía sus propias propiedades al DOM del host (`href` en `\<a>`, `src`/`alt` en `<img>`, `value`/`placeholder`/`disabled` en `<input>`, etc.), además de un conjunto común en cada elemento: `id`, `className`, `style`, `title`, `tabIndex`, `role`, `draggable` y cualquier atributo `aria-*` / `data-*` (con guiones, por lo que `ariaLabel` se descarta). Cualquier cosa fuera de eso se descarta silenciosamente, así que expresa el estado personalizado como `data-*`.
|
||||
|
||||
Component CSS, whether from `import './styles.css'`, CSS-in-JS or a `\<style>` element, is injected into the host page's `\<head>` **unscoped**. So class names collide with Twenty's own (prefix them, and never write bare `div { ... }` selectors), and `@media` matches the browser window rather than your widget (use `@container` with your own `container-type`). Inline `style` props are unaffected.
|
||||
El CSS del componente, ya sea desde `import './styles.css'`, CSS-in-JS o un elemento `\<style>`, se inyecta en el `\<head>` de la página del host **sin ámbito**. Así que los nombres de clase colisionan con los de Twenty (ponles un prefijo y nunca escribas `div { ... }` como selectores), y `@media` coincide con la ventana del navegador en lugar de con tu widget (usa `@container` con tu propio `container-type`). Las props de `style` en línea no se ven afectadas.
|
||||
|
||||
### Storage and network
|
||||
### Almacenamiento y red
|
||||
|
||||
`localStorage`, `sessionStorage`, IndexedDB, cookies, the Cache API and `BroadcastChannel` are all unavailable, since the component runs in a worker at an opaque origin. To persist state, call a [logic function](/l/es/developers/extend/apps/logic/logic-functions) and use its [key-value store](/l/es/developers/extend/apps/logic/key-value-store).
|
||||
`localStorage`, `sessionStorage`, IndexedDB, las cookies, la Cache API y `BroadcastChannel` no están disponibles, ya que el componente se ejecuta en un worker en un origen opaco. Para persistir el estado, llama a una [función de lógica](/l/es/developers/extend/apps/logic/logic-functions) y usa su [almacenamiento de clave-valor](/l/es/developers/extend/apps/logic/key-value-store).
|
||||
|
||||
`fetch` works, with caveats:
|
||||
`fetch` funciona, con matices:
|
||||
|
||||
* Calls to the Twenty API and your app's routes are proxied by the host, so prefer [`RestApiClient`](#calling-the-twenty-rest-api). On proxied calls, `AbortSignal` and the other `RequestInit` options are dropped, and only `string` and `URLSearchParams` bodies are supported.
|
||||
* Other origins leave the sandbox with `Origin: null`, so a third-party API answers only if it sends `Access-Control-Allow-Origin: *`. Call it from a logic function instead.
|
||||
* `fetch('/rest/people')` is never matched to the Twenty API, because the sandbox has no page URL to resolve a relative path against.
|
||||
* Las llamadas a la API de Twenty y a las rutas de tu aplicación se hacen por proxy a través del host, así que da prioridad a [`RestApiClient`](#calling-the-twenty-rest-api). En las llamadas con proxy, `AbortSignal` y las demás opciones de `RequestInit` se descartan, y solo se admiten cuerpos de tipo `string` y `URLSearchParams`.
|
||||
* Otros orígenes salen del sandbox con `Origin: null`, por lo que una API de terceros responde solo si envía `Access-Control-Allow-Origin: *`. Llámala desde una función de lógica en su lugar.
|
||||
* `fetch('/rest/people')` nunca se hace coincidir con la API de Twenty, porque el sandbox no tiene URL de página contra la que resolver una ruta relativa.
|
||||
|
||||
### Other gaps
|
||||
### Otras carencias
|
||||
|
||||
* **File contents.** `<input type="file">` gives your handler file metadata only, not the bytes, so `FileReader` and uploads are not possible yet.
|
||||
* **Drag-and-drop payloads.** Drag events fire, but `event.dataTransfer` is `undefined`.
|
||||
* **Node built-ins.** `fs`, `path` and `node:crypto` fail the build, so move that work into a [logic function](/l/es/developers/extend/apps/logic/logic-functions). Web Crypto, `fetch`, `TextEncoder` and `URL` are available.
|
||||
* **`\<iframe>`** is always re-sandboxed without `allow-same-origin`, so an embed relying on its own session renders logged out. It has no `onLoad` either.
|
||||
* **Contenido de archivos.** `<input type="file">` solo proporciona a tu manejador los metadatos del archivo, no los bytes, por lo que `FileReader` y las subidas no son posibles todavía.
|
||||
* **Cargas útiles de arrastrar y soltar.** Los eventos de arrastre se disparan, pero `event.dataTransfer` es `undefined`.
|
||||
* **Integraciones nativas de Node.** `fs`, `path` y `node:crypto` hacen que la compilación falle, así que mueve ese trabajo a una [función de lógica](/l/es/developers/extend/apps/logic/logic-functions). Web Crypto, `fetch`, `TextEncoder` y `URL` están disponibles.
|
||||
* **`\<iframe>`** siempre se vuelve a aislar sin `allow-same-origin`, por lo que un embed que depende de su propia sesión se renderiza como desconectado. Tampoco tiene `onLoad`.
|
||||
|
||||
@@ -7,7 +7,7 @@ icon: window-maximize
|
||||
Les composants frontaux sont des composants React qui s'affichent directement dans l'interface utilisateur de Twenty. Ils s'exécutent dans un **Web Worker isolé** en utilisant Remote DOM — votre code s'exécute dans un iframe à origine opaque et sandboxé, mais son interface utilisateur continue de s'afficher nativement dans la page plutôt que d'être confinée à cet iframe.
|
||||
|
||||
<Warning>
|
||||
Front components are still under active development. Your code runs against a partial DOM, not a real browser page, so advanced usages can fail, often silently. See [Current limitations](#current-limitations).
|
||||
Les composants Front sont encore en cours de développement actif. Votre code s’exécute sur un DOM partiel, et non sur une véritable page de navigateur, de sorte que les utilisations avancées peuvent échouer, souvent sans message d’erreur. Voir [Limitations actuelles](#current-limitations).
|
||||
</Warning>
|
||||
|
||||
## Où les composants frontaux peuvent être utilisés
|
||||
@@ -73,10 +73,10 @@ Cliquez dessus pour afficher le composant en ligne.
|
||||
|
||||
| Champ | Obligatoire | Description |
|
||||
| --------------------- | ----------- | -------------------------------------------------------------------------------- |
|
||||
| `universalIdentifier` | Yes | ID unique et stable pour ce composant |
|
||||
| `universalIdentifier` | Oui | ID unique et stable pour ce composant |
|
||||
| `component` | Oui | Une fonction de composant React |
|
||||
| `name` | No | Nom d'affichage |
|
||||
| `description` | No | Description de ce que fait le composant |
|
||||
| `name` | Non | Nom d'affichage |
|
||||
| `description` | Non | Description de ce que fait le composant |
|
||||
| `isHeadless` | Non | Définir sur `true` si le composant n'a pas d'interface visible (voir ci-dessous) |
|
||||
|
||||
## Placer un composant frontal sur une page
|
||||
@@ -701,71 +701,71 @@ Comme `useTheme()` est un hook, vous lisez les jetons à l’intérieur du corps
|
||||
|
||||
Pour bifurquer explicitement selon le jeu de couleurs actif, lisez-le avec `useColorScheme()` depuis `twenty-sdk/front-component`, qui renvoie `'light'` ou `'dark'`.
|
||||
|
||||
## Current limitations
|
||||
## Limitations actuelles
|
||||
|
||||
Front components are under active development. Rendering, styling and handling events works well. Anything that reaches *past* rendering (measuring an element, calling a DOM method on a ref, portaling outside your tree, touching browser storage) is missing or incomplete today, and most of it fails silently: no exception, and no TypeScript error either, since the scaffold is typed against the full browser DOM.
|
||||
Les composants Front sont en cours de développement actif. Le rendu, le style et la gestion des événements fonctionnent bien. Tout ce qui va *au-delà* du rendu (mesurer un élément, appeler une méthode du DOM sur une ref, créer un portail en dehors de votre arbre, accéder au stockage du navigateur) est manquant ou incomplet aujourd’hui, et la plupart de ces opérations échouent silencieusement : aucune exception et aucune erreur TypeScript non plus, puisque l’échafaudage est typé par rapport au DOM complet du navigateur.
|
||||
|
||||
If one of these blocks you, [open an issue](https://github.com/twentyhq/twenty/issues/new/choose) so it gets prioritized.
|
||||
Si l’un de ces points vous bloque, [ouvrez un ticket](https://github.com/twentyhq/twenty/issues/new/choose) afin qu’il soit priorisé.
|
||||
|
||||
### Layout and measurement
|
||||
### Disposition et mesure
|
||||
|
||||
Nothing can measure itself yet.
|
||||
Rien ne peut encore se mesurer soi-même.
|
||||
|
||||
| API | What happens |
|
||||
| ------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
|
||||
| `getBoundingClientRect()`, `getClientRects()` | Throws |
|
||||
| `offsetWidth`, `clientWidth`, `scrollWidth`, `offsetTop`, ... | Silently `undefined`, so `width ?? 0` yields `0` and `width > 600` is always false |
|
||||
| `ResizeObserver`, `IntersectionObserver` | `ReferenceError` (`typeof` guards do work) |
|
||||
| `window.matchMedia()`, `window.getComputedStyle()` | Throws |
|
||||
| `window.innerWidth`, `innerHeight`, `devicePixelRatio` | Silently `undefined` |
|
||||
| `new MutationObserver(fn)` | Constructs, then `.observe()` throws |
|
||||
| API | Ce qui se passe |
|
||||
| ------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
|
||||
| `getBoundingClientRect()`, `getClientRects()` | Lève une exception |
|
||||
| `offsetWidth`, `clientWidth`, `scrollWidth`, `offsetTop`, ... | Silencieusement `undefined`, donc `width ?? 0` donne `0` et `width > 600` est toujours faux |
|
||||
| `ResizeObserver`, `IntersectionObserver` | `ReferenceError` (les gardes `typeof` fonctionnent) |
|
||||
| `window.matchMedia()`, `window.getComputedStyle()` | Lève une exception |
|
||||
| `window.innerWidth`, `innerHeight`, `devicePixelRatio` | Silencieusement `undefined` |
|
||||
| `new MutationObserver(fn)` | Se construit, puis `.observe()` lève une exception |
|
||||
|
||||
So recharts `ResponsiveContainer`, Floating UI / Popper, list virtualization and drag-to-resize do not work yet. Do layout in CSS instead: your stylesheet reaches the real page, so flexbox, grid, `aspect-ratio`, `clamp()` and `@container` all behave normally.
|
||||
Ainsi, recharts `ResponsiveContainer`, Floating UI / Popper, la virtualisation de liste et le redimensionnement par glisser-déposer ne fonctionnent pas encore. Réalisez plutôt la mise en page en CSS : votre feuille de style atteint la vraie page, donc flexbox, grid, `aspect-ratio`, `clamp()` et `@container` se comportent tous normalement.
|
||||
|
||||
<Note>
|
||||
`requestAnimationFrame`, `fetch`, `setTimeout` and `queueMicrotask` work without the `window.` prefix. Only `window.requestAnimationFrame(...)` and friends throw.
|
||||
`requestAnimationFrame`, `fetch`, `setTimeout` et `queueMicrotask` fonctionnent sans le préfixe `window.`. Seuls `window.requestAnimationFrame(...)` et les fonctions similaires lèvent une exception.
|
||||
</Note>
|
||||
|
||||
### DOM access
|
||||
### Accès au DOM
|
||||
|
||||
A `ref` gives you a sandbox element, not an `HTMLElement`.
|
||||
Une `ref` vous donne un élément du bac à sable, pas un `HTMLElement`.
|
||||
|
||||
| What you write | What happens | Use instead |
|
||||
| ----------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- | ----------------------------------------------------------------------------------------- |
|
||||
| `ref.current.focus()`, `.click()`, `.select()`, `.setSelectionRange()`, `.scrollIntoView()`, `video.play()` | Throws | Controlled components; read values from `event.target` |
|
||||
| `element.classList.add(...)` | Throws (`classList` is `undefined`) | Build the `className` string yourself |
|
||||
| `document.getElementById()`, `getElementsByClassName()`, `createTreeWalker()` | Throws | `querySelector()` / `querySelectorAll()`, which work |
|
||||
| `document.activeElement` | Always `undefined` | Track focus with `onFocus` / `onBlur` |
|
||||
| `\<canvas>` | Renders nothing, no error | SVG, or draw offscreen and show an `<img src={dataUrl}>` |
|
||||
| `createPortal(node, document.body)` | Renders nothing, while `isConnected` reports success | Overlays inline with `position: absolute`, or pass the library your own container element |
|
||||
| Ce que vous écrivez | Ce qui se passe | À utiliser à la place |
|
||||
| ----------------------------------------------------------------------------------------------------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
|
||||
| `ref.current.focus()`, `.click()`, `.select()`, `.setSelectionRange()`, `.scrollIntoView()`, `video.play()` | Lève une exception | Composants contrôlés ; lisez les valeurs à partir de `event.target` |
|
||||
| `element.classList.add(...)` | Lève une exception (`classList` est `undefined`) | Construisez vous-même la chaîne `className` |
|
||||
| `document.getElementById()`, `getElementsByClassName()`, `createTreeWalker()` | Lève une exception | `querySelector()` / `querySelectorAll()`, qui fonctionnent |
|
||||
| `document.activeElement` | Toujours `undefined` | Suivez le focus avec `onFocus` / `onBlur` |
|
||||
| `\<canvas>` | Ne rend rien, pas d’erreur | SVG, ou dessinez hors écran et affichez une `<img src={dataUrl}>` |
|
||||
| `createPortal(node, document.body)` | Ne rend rien, tandis que `isConnected` signale un succès | Superpositions en ligne avec `position: absolute`, ou passez à la bibliothèque votre propre élément conteneur |
|
||||
|
||||
The portal gap is why Radix, Headless UI, MUI and react-select popovers render nothing by default. Most accept a container prop; point it at an element you rendered.
|
||||
Cet écart lié au portail est la raison pour laquelle les popovers de Radix, Headless UI, MUI et react-select ne rendent rien par défaut. La plupart acceptent une prop de conteneur ; faites-la pointer vers un élément que vous avez rendu.
|
||||
|
||||
### Events
|
||||
### Événements
|
||||
|
||||
Mouse, pointer, touch, drag, keyboard, focus, `input`/`change`/`submit`, `scroll`/`wheel`/`contextmenu` and `animationend`/`transitionend` cross to the host, plus a few per element: `load`/`error` on `<img>`, clipboard and composition on `<input>`/`\<textarea>`, media on `\<video>`/`\<audio>`, `toggle` on `\<details>`/`\<dialog>`. Anything else (`onAuxClick`, `onSelect`, `onInvalid`, `onReset`, `onAnimationStart`, pointer capture, `onLoad` off `<img>`) is dropped without warning.
|
||||
La souris, le pointeur, le toucher, le glisser-déposer, le clavier, le focus, `input`/`change`/`submit`, `scroll`/`wheel`/`contextmenu` et `animationend`/`transitionend` sont transmis à l’hôte, plus quelques événements spécifiques à chaque élément : `load`/`error` sur `<img>`, le presse-papiers et la composition sur `<input>`/`\<textarea>`, les médias sur `\<video>`/`\<audio>`, `toggle` sur `\<details>`/`\<dialog>`. Tout le reste (`onAuxClick`, `onSelect`, `onInvalid`, `onReset`, `onAnimationStart`, la capture de pointeur, `onLoad` sur `<img>`) est ignoré sans avertissement.
|
||||
|
||||
`document.addEventListener()` and `window.addEventListener()` register without error and never fire, which is why a drag stops as soon as the pointer leaves the element it started on. `event.preventDefault()` does not cross either; form submission, `dragover`/`drop` and link clicks are already guarded for you.
|
||||
`document.addEventListener()` et `window.addEventListener()` s’enregistrent sans erreur mais ne se déclenchent jamais, c’est pourquoi un glisser-déposer s’arrête dès que le pointeur quitte l’élément sur lequel il a commencé. `event.preventDefault()` ne traverse pas non plus ; l’envoi de formulaire, `dragover`/`drop` et les clics sur les liens sont déjà protégés pour vous.
|
||||
|
||||
### Attributes and styling
|
||||
### Attributs et styles
|
||||
|
||||
Each element forwards its own properties to the host DOM (`href` on `\<a>`, `src`/`alt` on `<img>`, `value`/`placeholder`/`disabled` on `<input>`, and so on), plus a common set on every element: `id`, `className`, `style`, `title`, `tabIndex`, `role`, `draggable` and any `aria-*` / `data-*` attribute (hyphenated, so `ariaLabel` is dropped). Anything outside that is silently discarded, so express custom state as `data-*`.
|
||||
Chaque élément transfère ses propres propriétés au DOM hôte (`href` sur `\<a>`, `src`/`alt` sur `<img>`, `value`/`placeholder`/`disabled` sur `<input>`, etc.), plus un ensemble commun sur chaque élément : `id`, `className`, `style`, `title`, `tabIndex`, `role`, `draggable` et tout attribut `aria-*` / `data-*` (avec tiret, donc `ariaLabel` est ignoré). Tout ce qui sort de ce cadre est silencieusement supprimé, donc exprimez l’état personnalisé sous forme de `data-*`.
|
||||
|
||||
Component CSS, whether from `import './styles.css'`, CSS-in-JS or a `\<style>` element, is injected into the host page's `\<head>` **unscoped**. So class names collide with Twenty's own (prefix them, and never write bare `div { ... }` selectors), and `@media` matches the browser window rather than your widget (use `@container` with your own `container-type`). Inline `style` props are unaffected.
|
||||
Le CSS du composant, qu’il provienne de `import './styles.css'`, de CSS-in-JS ou d’un élément `\<style>`, est injecté dans le `\<head>` de la page hôte **sans portée**. Ainsi, les noms de classes entrent en collision avec ceux de Twenty (préfixez-les, et n’écrivez jamais de `div { ... }` sélecteurs), et `@media` correspond à la fenêtre du navigateur plutôt qu’à votre widget (utilisez `@container` avec votre propre `container-type`). Les props `style` en ligne ne sont pas affectées.
|
||||
|
||||
### Storage and network
|
||||
### Stockage et réseau
|
||||
|
||||
`localStorage`, `sessionStorage`, IndexedDB, cookies, the Cache API and `BroadcastChannel` are all unavailable, since the component runs in a worker at an opaque origin. To persist state, call a [logic function](/l/fr/developers/extend/apps/logic/logic-functions) and use its [key-value store](/l/fr/developers/extend/apps/logic/key-value-store).
|
||||
`localStorage`, `sessionStorage`, IndexedDB, les cookies, l’API Cache et `BroadcastChannel` ne sont pas disponibles, puisque le composant s’exécute dans un worker avec une origine opaque. Pour conserver l’état, appelez une [fonction logique](/l/fr/developers/extend/apps/logic/logic-functions) et utilisez son [magasin clé-valeur](/l/fr/developers/extend/apps/logic/key-value-store).
|
||||
|
||||
`fetch` works, with caveats:
|
||||
`fetch` fonctionne, avec quelques réserves :
|
||||
|
||||
* Calls to the Twenty API and your app's routes are proxied by the host, so prefer [`RestApiClient`](#calling-the-twenty-rest-api). On proxied calls, `AbortSignal` and the other `RequestInit` options are dropped, and only `string` and `URLSearchParams` bodies are supported.
|
||||
* Other origins leave the sandbox with `Origin: null`, so a third-party API answers only if it sends `Access-Control-Allow-Origin: *`. Call it from a logic function instead.
|
||||
* `fetch('/rest/people')` is never matched to the Twenty API, because the sandbox has no page URL to resolve a relative path against.
|
||||
* Les appels à l’API Twenty et aux routes de votre application sont proxifiés par l’hôte, donc privilégiez [`RestApiClient`](#calling-the-twenty-rest-api). Sur les appels proxifiés, `AbortSignal` et les autres options `RequestInit` sont ignorées, et seuls les corps `string` et `URLSearchParams` sont pris en charge.
|
||||
* Les autres origines quittent le bac à sable avec `Origin: null`, donc une API tierce répond uniquement si elle envoie `Access-Control-Allow-Origin: *`. Appelez-la plutôt depuis une fonction logique.
|
||||
* `fetch('/rest/people')` n’est jamais associé à l’API Twenty, car le bac à sable n’a pas d’URL de page pour résoudre un chemin relatif.
|
||||
|
||||
### Other gaps
|
||||
### Autres lacunes
|
||||
|
||||
* **File contents.** `<input type="file">` gives your handler file metadata only, not the bytes, so `FileReader` and uploads are not possible yet.
|
||||
* **Drag-and-drop payloads.** Drag events fire, but `event.dataTransfer` is `undefined`.
|
||||
* **Node built-ins.** `fs`, `path` and `node:crypto` fail the build, so move that work into a [logic function](/l/fr/developers/extend/apps/logic/logic-functions). Web Crypto, `fetch`, `TextEncoder` and `URL` are available.
|
||||
* **`\<iframe>`** is always re-sandboxed without `allow-same-origin`, so an embed relying on its own session renders logged out. It has no `onLoad` either.
|
||||
* **Contenu de fichier.** `<input type="file">` fournit uniquement à votre gestionnaire les métadonnées du fichier, pas les octets, donc `FileReader` et les téléversements ne sont pas encore possibles.
|
||||
* **Charges utiles de glisser-déposer.** Les événements de glisser-déposer se déclenchent, mais `event.dataTransfer` est `undefined`.
|
||||
* **Modules natifs Node.** `fs`, `path` et `node:crypto` font échouer la construction, donc déplacez ce travail dans une [fonction logique](/l/fr/developers/extend/apps/logic/logic-functions). Web Crypto, `fetch`, `TextEncoder` et `URL` sont disponibles.
|
||||
* **`\<iframe>`** est toujours à nouveau placé dans un bac à sable sans `allow-same-origin`, donc une intégration qui repose sur sa propre session s’affiche comme déconnectée. Il n’a pas non plus de `onLoad`.
|
||||
|
||||
@@ -56,4 +56,4 @@ La **couche de mise en page** d’une application Twenty est tout ce que l’uti
|
||||
|
||||
Les composants frontaux s’exécutent à l’intérieur d’un Web Worker isolé en utilisant Remote DOM — ils sont rendus *nativement* dans la page (et non dans une iframe), mais ne peuvent pas accéder directement à la page hôte ou au DOM. La communication avec Twenty se fait via une API hôte de passage de messages.
|
||||
|
||||
Elles sont encore en cours de développement actif : le bac à sable implémente un DOM partiel, donc les usages avancés peuvent échouer. Voir [limitations actuelles](/l/fr/developers/extend/apps/layout/front-components#current-limitations).
|
||||
Elles sont encore en cours de développement actif : le bac à sable implémente un DOM partiel, donc les usages avancés peuvent échouer. Voir [Limitations actuelles](/l/fr/developers/extend/apps/layout/front-components#current-limitations).
|
||||
|
||||
@@ -703,69 +703,69 @@ Per diramare esplicitamente in base allo schema attivo, leggilo con `useColorSch
|
||||
|
||||
## Limitazioni attuali
|
||||
|
||||
Front components are under active development. Rendering, styling and handling events works well. Anything that reaches *past* rendering (measuring an element, calling a DOM method on a ref, portaling outside your tree, touching browser storage) is missing or incomplete today, and most of it fails silently: no exception, and no TypeScript error either, since the scaffold is typed against the full browser DOM.
|
||||
I componenti Front sono in fase di sviluppo attivo. Il rendering, lo styling e la gestione degli eventi funzionano bene. Qualsiasi cosa vada *oltre* il rendering (misurare un elemento, chiamare un metodo del DOM su una ref, creare un portale fuori dal tuo tree, accedere allo storage del browser) oggi è assente o incompleta, e per lo più fallisce in modo silenzioso: nessuna eccezione e nessun errore TypeScript, dato che l’impalcatura è tipizzata rispetto al DOM completo del browser.
|
||||
|
||||
If one of these blocks you, [open an issue](https://github.com/twentyhq/twenty/issues/new/choose) so it gets prioritized.
|
||||
Se una di queste limitazioni ti blocca, [apri una issue](https://github.com/twentyhq/twenty/issues/new/choose) così la sua priorità aumenta.
|
||||
|
||||
### Layout and measurement
|
||||
### Layout e misurazione
|
||||
|
||||
Nothing can measure itself yet.
|
||||
Per ora nulla può ancora misurare se stesso.
|
||||
|
||||
| API | What happens |
|
||||
| ------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
|
||||
| `getBoundingClientRect()`, `getClientRects()` | Throws |
|
||||
| `offsetWidth`, `clientWidth`, `scrollWidth`, `offsetTop`, ... | Silently `undefined`, so `width ?? 0` yields `0` and `width > 600` is always false |
|
||||
| `ResizeObserver`, `IntersectionObserver` | `ReferenceError` (`typeof` guards do work) |
|
||||
| `window.matchMedia()`, `window.getComputedStyle()` | Throws |
|
||||
| `window.innerWidth`, `innerHeight`, `devicePixelRatio` | Silently `undefined` |
|
||||
| `new MutationObserver(fn)` | Constructs, then `.observe()` throws |
|
||||
| API | Cosa succede |
|
||||
| ------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
|
||||
| `getBoundingClientRect()`, `getClientRects()` | Genera un’eccezione |
|
||||
| `offsetWidth`, `clientWidth`, `scrollWidth`, `offsetTop`, ... | Silenziosamente `undefined`, quindi `width ?? 0` restituisce `0` e `width > 600` è sempre falso |
|
||||
| `ResizeObserver`, `IntersectionObserver` | `ReferenceError` (le verifiche con `typeof` funzionano) |
|
||||
| `window.matchMedia()`, `window.getComputedStyle()` | Genera un’eccezione |
|
||||
| `window.innerWidth`, `innerHeight`, `devicePixelRatio` | Silenziosamente `undefined` |
|
||||
| `new MutationObserver(fn)` | Viene costruito, poi `.observe()` genera un’eccezione |
|
||||
|
||||
So recharts `ResponsiveContainer`, Floating UI / Popper, list virtualization and drag-to-resize do not work yet. Do layout in CSS instead: your stylesheet reaches the real page, so flexbox, grid, `aspect-ratio`, `clamp()` and `@container` all behave normally.
|
||||
Quindi recharts `ResponsiveContainer`, Floating UI / Popper, la virtualizzazione delle liste e il ridimensionamento tramite trascinamento non funzionano ancora. Esegui invece il layout in CSS: il tuo stylesheet raggiunge la pagina reale, quindi flexbox, grid, `aspect-ratio`, `clamp()` e `@container` si comportano tutti normalmente.
|
||||
|
||||
<Note>
|
||||
`requestAnimationFrame`, `fetch`, `setTimeout` and `queueMicrotask` work without the `window.` prefix. Only `window.requestAnimationFrame(...)` and friends throw.
|
||||
`requestAnimationFrame`, `fetch`, `setTimeout` e `queueMicrotask` funzionano senza il prefisso `window.`. Solo `window.requestAnimationFrame(...)` e simili generano un’eccezione.
|
||||
</Note>
|
||||
|
||||
### DOM access
|
||||
### Accesso al DOM
|
||||
|
||||
A `ref` gives you a sandbox element, not an `HTMLElement`.
|
||||
Un `ref` ti restituisce un elemento sandbox, non un `HTMLElement`.
|
||||
|
||||
| What you write | What happens | Use instead |
|
||||
| ----------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- | ----------------------------------------------------------------------------------------- |
|
||||
| `ref.current.focus()`, `.click()`, `.select()`, `.setSelectionRange()`, `.scrollIntoView()`, `video.play()` | Throws | Controlled components; read values from `event.target` |
|
||||
| `element.classList.add(...)` | Throws (`classList` is `undefined`) | Build the `className` string yourself |
|
||||
| `document.getElementById()`, `getElementsByClassName()`, `createTreeWalker()` | Throws | `querySelector()` / `querySelectorAll()`, which work |
|
||||
| `document.activeElement` | Always `undefined` | Track focus with `onFocus` / `onBlur` |
|
||||
| `\<canvas>` | Renders nothing, no error | SVG, or draw offscreen and show an `<img src={dataUrl}>` |
|
||||
| `createPortal(node, document.body)` | Renders nothing, while `isConnected` reports success | Overlays inline with `position: absolute`, or pass the library your own container element |
|
||||
| Cosa scrivi | Cosa succede | Usa invece |
|
||||
| ----------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
|
||||
| `ref.current.focus()`, `.click()`, `.select()`, `.setSelectionRange()`, `.scrollIntoView()`, `video.play()` | Genera un’eccezione | Componenti controllati; leggi i valori da `event.target` |
|
||||
| `element.classList.add(...)` | Genera un’eccezione (`classList` è `undefined`) | Costruisci tu stesso la stringa `className` |
|
||||
| `document.getElementById()`, `getElementsByClassName()`, `createTreeWalker()` | Genera un’eccezione | `querySelector()` / `querySelectorAll()`, che funzionano |
|
||||
| `document.activeElement` | Sempre `undefined` | Tieni traccia del focus con `onFocus` / `onBlur` |
|
||||
| `\<canvas>` | Non renderizza nulla, nessun errore | SVG, oppure disegna offscreen e mostra un `<img src={dataUrl}>` |
|
||||
| `createPortal(node, document.body)` | Non renderizza nulla, mentre `isConnected` segnala successo | Overlay inline con `position: absolute`, oppure passa alla libreria un tuo elemento container |
|
||||
|
||||
The portal gap is why Radix, Headless UI, MUI and react-select popovers render nothing by default. Most accept a container prop; point it at an element you rendered.
|
||||
Il gap del portale è il motivo per cui i popover di Radix, Headless UI, MUI e react-select non renderizzano nulla per impostazione predefinita. La maggior parte accetta una prop container; indirizzala a un elemento che hai renderizzato.
|
||||
|
||||
### Eventi
|
||||
|
||||
Mouse, pointer, touch, drag, keyboard, focus, `input`/`change`/`submit`, `scroll`/`wheel`/`contextmenu` and `animationend`/`transitionend` cross to the host, plus a few per element: `load`/`error` on `<img>`, clipboard and composition on `<input>`/`\<textarea>`, media on `\<video>`/`\<audio>`, `toggle` on `\<details>`/`\<dialog>`. Anything else (`onAuxClick`, `onSelect`, `onInvalid`, `onReset`, `onAnimationStart`, pointer capture, `onLoad` off `<img>`) is dropped without warning.
|
||||
Mouse, puntatore, touch, drag, tastiera, focus, `input`/`change`/`submit`, `scroll`/`wheel`/`contextmenu` e `animationend`/`transitionend` passano all'host, più alcuni per elemento: `load`/`error` su `<img>`, appunti e composizione su `<input>`/`\<textarea>`, media su `\<video>`/`\<audio>`, `toggle` su `\<details>`/`\<dialog>`. Tutto il resto (`onAuxClick`, `onSelect`, `onInvalid`, `onReset`, `onAnimationStart`, capture del pointer, `onLoad` fuori da `<img>`) viene ignorato senza avviso.
|
||||
|
||||
`document.addEventListener()` and `window.addEventListener()` register without error and never fire, which is why a drag stops as soon as the pointer leaves the element it started on. `event.preventDefault()` does not cross either; form submission, `dragover`/`drop` and link clicks are already guarded for you.
|
||||
`document.addEventListener()` e `window.addEventListener()` si registrano senza errori e non vengono mai attivati, motivo per cui un drag si interrompe non appena il puntatore lascia l'elemento da cui è partito. `event.preventDefault()` non viene propagato nemmeno; l'invio dei form, `dragover`/`drop` e i clic sui link sono già protetti per te.
|
||||
|
||||
### Attributes and styling
|
||||
### Attributi e stile
|
||||
|
||||
Each element forwards its own properties to the host DOM (`href` on `\<a>`, `src`/`alt` on `<img>`, `value`/`placeholder`/`disabled` on `<input>`, and so on), plus a common set on every element: `id`, `className`, `style`, `title`, `tabIndex`, `role`, `draggable` and any `aria-*` / `data-*` attribute (hyphenated, so `ariaLabel` is dropped). Anything outside that is silently discarded, so express custom state as `data-*`.
|
||||
Ogni elemento inoltra le proprie proprietà al DOM host (`href` su `\<a>`, `src`/`alt` su `<img>`, `value`/`placeholder`/`disabled` su `<input>`, e così via), più un insieme comune su ogni elemento: `id`, `className`, `style`, `title`, `tabIndex`, `role`, `draggable` e qualsiasi attributo `aria-*` / `data-*` (con trattino, quindi `ariaLabel` viene scartato). Qualsiasi cosa al di fuori di ciò viene silenziosamente scartata, quindi esprimi lo stato personalizzato come `data-*`.
|
||||
|
||||
Component CSS, whether from `import './styles.css'`, CSS-in-JS or a `\<style>` element, is injected into the host page's `\<head>` **unscoped**. So class names collide with Twenty's own (prefix them, and never write bare `div { ... }` selectors), and `@media` matches the browser window rather than your widget (use `@container` with your own `container-type`). Inline `style` props are unaffected.
|
||||
Il CSS del componente, che provenga da `import './styles.css'`, da CSS-in-JS o da un elemento `\<style>`, viene iniettato nel `\<head>` della pagina host **senza ambito**. Quindi i nomi delle classi entrano in conflitto con quelli di Twenty (aggiungi un prefisso e non scrivere mai `div { ... }` come selettori), e `@media` corrisponde alla finestra del browser piuttosto che al tuo widget (usa `@container` con il tuo `container-type`). Le prop `style` inline non sono interessate.
|
||||
|
||||
### Storage and network
|
||||
### Storage e rete
|
||||
|
||||
`localStorage`, `sessionStorage`, IndexedDB, cookies, the Cache API and `BroadcastChannel` are all unavailable, since the component runs in a worker at an opaque origin. To persist state, call a [logic function](/l/it/developers/extend/apps/logic/logic-functions) and use its [key-value store](/l/it/developers/extend/apps/logic/key-value-store).
|
||||
`localStorage`, `sessionStorage`, IndexedDB, cookie, Cache API e `BroadcastChannel` non sono disponibili, poiché il componente viene eseguito in un worker con origine opaca. Per rendere persistente lo stato, chiama una [logic function](/l/it/developers/extend/apps/logic/logic-functions) e utilizza il suo [key-value store](/l/it/developers/extend/apps/logic/key-value-store).
|
||||
|
||||
`fetch` works, with caveats:
|
||||
`fetch` funziona, con alcune avvertenze:
|
||||
|
||||
* Calls to the Twenty API and your app's routes are proxied by the host, so prefer [`RestApiClient`](#calling-the-twenty-rest-api). On proxied calls, `AbortSignal` and the other `RequestInit` options are dropped, and only `string` and `URLSearchParams` bodies are supported.
|
||||
* Other origins leave the sandbox with `Origin: null`, so a third-party API answers only if it sends `Access-Control-Allow-Origin: *`. Call it from a logic function instead.
|
||||
* `fetch('/rest/people')` is never matched to the Twenty API, because the sandbox has no page URL to resolve a relative path against.
|
||||
* Le chiamate alla Twenty API e alle route della tua app sono proxyate dall'host, quindi preferisci [`RestApiClient`](#calling-the-twenty-rest-api). Nelle chiamate proxyate, `AbortSignal` e le altre opzioni di `RequestInit` vengono scartate, e sono supportati solo body di tipo `string` e `URLSearchParams`.
|
||||
* Le altre origini escono dalla sandbox con `Origin: null`, quindi un'API di terze parti risponde solo se invia `Access-Control-Allow-Origin: *`. Invece, chiamala da una logic function.
|
||||
* `fetch('/rest/people')` non viene mai associato alla Twenty API, perché la sandbox non ha un URL di pagina rispetto a cui risolvere un percorso relativo.
|
||||
|
||||
### Other gaps
|
||||
### Altre lacune
|
||||
|
||||
* **File contents.** `<input type="file">` gives your handler file metadata only, not the bytes, so `FileReader` and uploads are not possible yet.
|
||||
* **Drag-and-drop payloads.** Drag events fire, but `event.dataTransfer` is `undefined`.
|
||||
* **Node built-ins.** `fs`, `path` and `node:crypto` fail the build, so move that work into a [logic function](/l/it/developers/extend/apps/logic/logic-functions). Web Crypto, `fetch`, `TextEncoder` and `URL` are available.
|
||||
* **`\<iframe>`** is always re-sandboxed without `allow-same-origin`, so an embed relying on its own session renders logged out. It has no `onLoad` either.
|
||||
* **Contenuti dei file.** `<input type="file">` fornisce al tuo gestore solo i metadati del file, non i byte, quindi `FileReader` e gli upload non sono ancora possibili.
|
||||
* **Payload di drag-and-drop.** Gli eventi di drag vengono attivati, ma `event.dataTransfer` è `undefined`.
|
||||
* **Built-in di Node.** `fs`, `path` e `node:crypto` fanno fallire la build, quindi sposta quel lavoro in una [logic function](/l/it/developers/extend/apps/logic/logic-functions). Web Crypto, `fetch`, `TextEncoder` e `URL` sono disponibili.
|
||||
* **`\<iframe>`** viene sempre nuovamente messo in sandbox senza `allow-same-origin`, quindi un embed che dipende dalla propria sessione viene renderizzato come disconnesso. Non ha nemmeno `onLoad`.
|
||||
|
||||
@@ -56,4 +56,4 @@ Il **livello di layout** di un'app Twenty è tutto ciò che l'utente vede: dove
|
||||
|
||||
I componenti front-end vengono eseguiti all'interno di un Web Worker isolato usando Remote DOM: vengono renderizzati in modo nativo nella pagina (non all'interno di un iframe), ma non possono accedere direttamente alla pagina host o al DOM. La comunicazione con Twenty avviene tramite un'API host basata sul passaggio di messaggi.
|
||||
|
||||
Sono ancora in fase di sviluppo attivo: il sandbox implementa un DOM parziale, quindi gli utilizzi avanzati possono non funzionare. Vedi [Limitazioni attuali](/l/it/developers/extend/apps/layout/front-components#current-limitations).
|
||||
Sono ancora in fase di sviluppo attivo: la sandbox implementa un DOM parziale, quindi gli usi avanzati possono non funzionare. Vedi [Limitazioni attuali](/l/it/developers/extend/apps/layout/front-components#current-limitations).
|
||||
|
||||
@@ -743,29 +743,29 @@ Front components は現在も積極的に開発が進められています。
|
||||
|
||||
### イベント
|
||||
|
||||
Mouse, pointer, touch, drag, keyboard, focus, `input`/`change`/`submit`, `scroll`/`wheel`/`contextmenu` and `animationend`/`transitionend` cross to the host, plus a few per element: `load`/`error` on `<img>`, clipboard and composition on `<input>`/`\<textarea>`, media on `\<video>`/`\<audio>`, `toggle` on `\<details>`/`\<dialog>`. Anything else (`onAuxClick`, `onSelect`, `onInvalid`, `onReset`, `onAnimationStart`, pointer capture, `onLoad` off `<img>`) is dropped without warning.
|
||||
マウス、ポインター、タッチ、ドラッグ、キーボード、フォーカス、`input`/`change`/`submit`、`scroll`/`wheel`/`contextmenu`、そして `animationend`/`transitionend` はホストへ渡されます。さらに、要素ごとにいくつかのイベントも渡されます:`<img>` の `load`/`error`、`<input>`/`\<textarea>` のクリップボードおよびコンポジション、`\<video>`/`\<audio>` のメディア、`\<details>`/`\<dialog>` の `toggle` などです。 それ以外(`onAuxClick`、`onSelect`、`onInvalid`、`onReset`、`onAnimationStart`、pointer capture、`<img>` の `onLoad`)は、警告なしに破棄されます。
|
||||
|
||||
`document.addEventListener()` and `window.addEventListener()` register without error and never fire, which is why a drag stops as soon as the pointer leaves the element it started on. `event.preventDefault()` does not cross either; form submission, `dragover`/`drop` and link clicks are already guarded for you.
|
||||
`document.addEventListener()` と `window.addEventListener()` はエラーなく登録されますが、一度も発火しません。そのため、ドラッグは開始した要素からポインターが離れた瞬間に止まります。 `event.preventDefault()` も渡されません。フォーム送信、`dragover`/`drop`、およびリンクのクリックは、すでに保護されています。
|
||||
|
||||
### Attributes and styling
|
||||
### 属性とスタイリング
|
||||
|
||||
Each element forwards its own properties to the host DOM (`href` on `\<a>`, `src`/`alt` on `<img>`, `value`/`placeholder`/`disabled` on `<input>`, and so on), plus a common set on every element: `id`, `className`, `style`, `title`, `tabIndex`, `role`, `draggable` and any `aria-*` / `data-*` attribute (hyphenated, so `ariaLabel` is dropped). Anything outside that is silently discarded, so express custom state as `data-*`.
|
||||
各要素は自分自身のプロパティをホスト DOM にフォワードします(`\<a>` の `href`、`<img>` の `src`/`alt`、`<input>` の `value`/`placeholder`/`disabled` など)。さらに、すべての要素に共通のプロパティセットもフォワードされます:`id`、`className`、`style`、`title`、`tabIndex`、`role`、`draggable`、および任意の `aria-*` / `data-*` 属性(ハイフン区切りのため、`ariaLabel` は破棄されます)。 それ以外のものはすべて暗黙的に破棄されるため、カスタム状態は `data-*` として表現してください。
|
||||
|
||||
Component CSS, whether from `import './styles.css'`, CSS-in-JS or a `\<style>` element, is injected into the host page's `\<head>` **unscoped**. So class names collide with Twenty's own (prefix them, and never write bare `div { ... }` selectors), and `@media` matches the browser window rather than your widget (use `@container` with your own `container-type`). Inline `style` props are unaffected.
|
||||
コンポーネントの CSS(`import './styles.css'`、CSS-in-JS、または `\<style>` 要素のいずれであっても)は、ホストページの `\<head>` に **スコープなし(unscoped)** で挿入されます。 そのため、クラス名が Twenty 独自のクラス名と衝突します(プレフィックスを付け、決して素の `div { ... }` セレクタは書かないでください)。また、`@media` はウィジェットではなくブラウザウィンドウに対してマッチします(独自の `container-type` を指定した `@container` を使用してください)。 インラインの `style` props には影響しません。
|
||||
|
||||
### Storage and network
|
||||
### ストレージとネットワーク
|
||||
|
||||
`localStorage`, `sessionStorage`, IndexedDB, cookies, the Cache API and `BroadcastChannel` are all unavailable, since the component runs in a worker at an opaque origin. To persist state, call a [logic function](/l/ja/developers/extend/apps/logic/logic-functions) and use its [key-value store](/l/ja/developers/extend/apps/logic/key-value-store).
|
||||
`localStorage`、`sessionStorage`、IndexedDB、Cookie、Cache API、および `BroadcastChannel` はすべて利用できません。コンポーネントはオペークなオリジンの worker 内で実行されるためです。 状態を永続化するには、[ロジック関数](/l/ja/developers/extend/apps/logic/logic-functions)を呼び出し、その[キー・バリュー ストア](/l/ja/developers/extend/apps/logic/key-value-store)を使用してください。
|
||||
|
||||
`fetch` works, with caveats:
|
||||
`fetch` は動作しますが、いくつか注意点があります。
|
||||
|
||||
* Calls to the Twenty API and your app's routes are proxied by the host, so prefer [`RestApiClient`](#calling-the-twenty-rest-api). On proxied calls, `AbortSignal` and the other `RequestInit` options are dropped, and only `string` and `URLSearchParams` bodies are supported.
|
||||
* Other origins leave the sandbox with `Origin: null`, so a third-party API answers only if it sends `Access-Control-Allow-Origin: *`. Call it from a logic function instead.
|
||||
* `fetch('/rest/people')` is never matched to the Twenty API, because the sandbox has no page URL to resolve a relative path against.
|
||||
* Twenty API への呼び出しやアプリのルートへの呼び出しはホストによってプロキシされるため、[`RestApiClient`](#calling-the-twenty-rest-api) を優先して使用してください。 プロキシされた呼び出しでは、`AbortSignal` などの `RequestInit` オプションは破棄され、`string` と `URLSearchParams` のボディのみがサポートされます。
|
||||
* その他のオリジンからのリクエストは、`Origin: null` を付けてサンドボックスの外へ送信されるため、サードパーティ API は `Access-Control-Allow-Origin: *` を返す場合にのみ応答します。 代わりにロジック関数から呼び出してください。
|
||||
* `fetch('/rest/people')` は、サンドボックスに相対パスを解決するためのページ URL がないため、Twenty API には決してマッチしません。
|
||||
|
||||
### Other gaps
|
||||
### その他のギャップ
|
||||
|
||||
* **File contents.** `<input type="file">` gives your handler file metadata only, not the bytes, so `FileReader` and uploads are not possible yet.
|
||||
* **Drag-and-drop payloads.** Drag events fire, but `event.dataTransfer` is `undefined`.
|
||||
* **Node built-ins.** `fs`, `path` and `node:crypto` fail the build, so move that work into a [logic function](/l/ja/developers/extend/apps/logic/logic-functions). Web Crypto, `fetch`, `TextEncoder` and `URL` are available.
|
||||
* **`\<iframe>`** is always re-sandboxed without `allow-same-origin`, so an embed relying on its own session renders logged out. It has no `onLoad` either.
|
||||
* **ファイル内容。** `<input type="file">` は、ハンドラーにファイルのメタデータのみを渡し、バイト列は渡さないため、`FileReader` やアップロードはまだ利用できません。
|
||||
* **ドラッグ&ドロップのペイロード。** ドラッグイベントは発火しますが、`event.dataTransfer` は `undefined` です。
|
||||
* **Node 組み込みモジュール。** `fs`、`path`、`node:crypto` はビルドに失敗するため、その処理は [ロジック関数](/l/ja/developers/extend/apps/logic/logic-functions) に移動してください。 Web Crypto、`fetch`、`TextEncoder`、および `URL` は利用可能です。
|
||||
* **`\<iframe>`** は常に `allow-same-origin` なしで再サンドボックス化されるため、独自のセッションに依存する埋め込みは、ログアウト状態としてレンダリングされます。 また、`onLoad` もありません。
|
||||
|
||||
@@ -56,4 +56,4 @@ Twenty アプリの **レイアウトレイヤー** とは、ユーザーに見
|
||||
|
||||
フロントコンポーネントは Remote DOM を使用して、分離された Web Worker 内で実行されます。ページ内に *ネイティブに*(iframe 内ではなく)レンダリングされますが、ホストページや DOM へ直接アクセスすることはできません。 Twenty との通信は、メッセージパッシング型のホスト API を通じて行われます。
|
||||
|
||||
これらは依然として積極的に開発中です。サンドボックスは DOM を部分的にのみ実装しているため、高度な利用方法では失敗する場合があります。 [現在の制限事項](/l/ja/developers/extend/apps/layout/front-components#current-limitations)を参照してください。
|
||||
これらは依然として積極的に開発中です。サンドボックスは DOM を部分的にのみ実装しているため、高度な利用方法では失敗する場合があります。 [現在の制限](/l/ja/developers/extend/apps/layout/front-components#current-limitations) を参照してください。
|
||||
|
||||
@@ -703,69 +703,69 @@ const Card = () => {
|
||||
|
||||
## 현재 제한 사항
|
||||
|
||||
Front 컴포넌트는 활발히 개발 중입니다. 렌더링, 스타일링 및 이벤트 처리는 잘 작동합니다. 렌더링 *이후* 단계에 해당하는 작업(요소 측정, ref에서 DOM 메서드 호출, 트리 외부로의 포털링, 브라우저 스토리지 접근 등)은 현재 누락되어 있거나 불완전하며, 대부분은 조용히 실패합니다. 예외도 발생하지 않고, 스캐폴드가 전체 브라우저 DOM을 기준으로 타입이 지정되어 있기 때문에 TypeScript 오류도 발생하지 않습니다.
|
||||
Front 컴포넌트는 활발히 개발 중입니다. 렌더링, 스타일링 및 이벤트 처리는 잘 동작합니다. 렌더링을 *넘어서는* 작업(요소 측정, ref에 DOM 메서드 호출, 트리 바깥으로 포털링, 브라우저 스토리지 접근 등)은 현재 누락되었거나 불완전하며, 대부분 조용히 실패합니다. 예외도 발생하지 않고, 스캐폴드가 전체 브라우저 DOM을 기준으로 타입이 지정되어 있기 때문에 TypeScript 오류도 발생하지 않습니다.
|
||||
|
||||
이 중 하나가 작업을 막고 있다면, 우선순위를 높일 수 있도록 [issue를 생성](https://github.com/twentyhq/twenty/issues/new/choose)해 주세요.
|
||||
이 중 하나가 개발을 가로막는다면, 우선순위를 높일 수 있도록 [issue를 열어](https://github.com/twentyhq/twenty/issues/new/choose) 주세요.
|
||||
|
||||
### 레이아웃과 측정
|
||||
|
||||
아직 어떤 요소도 스스로를 측정할 수 없습니다.
|
||||
|
||||
| API | 무슨 일이 일어나는지 |
|
||||
| ------------------------------------------------------------- | ------------------------------------------------------------------------ |
|
||||
| `getBoundingClientRect()`, `getClientRects()` | 예외 발생(Throws) |
|
||||
| `offsetWidth`, `clientWidth`, `scrollWidth`, `offsetTop`, ... | 조용히 `undefined`가 되어 `width ?? 0`은 `0`을 반환하고, `width > 600`은 항상 false입니다. |
|
||||
| `ResizeObserver`, `IntersectionObserver` | `ReferenceError`가 발생합니다(`typeof` 가드는 동작함). |
|
||||
| `window.matchMedia()`, `window.getComputedStyle()` | 예외 발생(Throws) |
|
||||
| `window.innerWidth`, `innerHeight`, `devicePixelRatio` | 조용히 `undefined`가 됩니다. |
|
||||
| `new MutationObserver(fn)` | 생성은 되지만 이후 `.observe()`에서 예외가 발생합니다. |
|
||||
| API | 무슨 일이 일어나는지 |
|
||||
| ------------------------------------------------------------- | ------------------------------------------------------------------------- |
|
||||
| `getBoundingClientRect()`, `getClientRects()` | 예외 발생 |
|
||||
| `offsetWidth`, `clientWidth`, `scrollWidth`, `offsetTop`, ... | 조용히 `undefined`가 되어, `width ?? 0`은 `0`을 반환하고, `width > 600`은 항상 false입니다. |
|
||||
| `ResizeObserver`, `IntersectionObserver` | `ReferenceError` 발생(단, `typeof` 가드는 동작함) |
|
||||
| `window.matchMedia()`, `window.getComputedStyle()` | 예외 발생 |
|
||||
| `window.innerWidth`, `innerHeight`, `devicePixelRatio` | 조용히 `undefined`가 됨 |
|
||||
| `new MutationObserver(fn)` | 생성은 되지만 이후 `.observe()`에서 예외가 발생합니다. |
|
||||
|
||||
따라서 recharts의 `ResponsiveContainer`, Floating UI / Popper, 리스트 가상화, 드래그로 크기 조절 등은 아직 동작하지 않습니다. 대신 CSS로 레이아웃을 구성하세요. 스타일시트는 실제 페이지에 도달하므로 flexbox, grid, `aspect-ratio`, `clamp()`, `@container`는 모두 정상적으로 동작합니다.
|
||||
따라서 recharts의 `ResponsiveContainer`, Floating UI / Popper, 리스트 가상화, 드래그로 크기 조절 등은 아직 동작하지 않습니다. 대신 CSS에서 레이아웃을 구현하세요. 스타일시트는 실제 페이지에 도달하므로 flexbox, grid, `aspect-ratio`, `clamp()` 및 `@container`는 모두 정상적으로 동작합니다.
|
||||
|
||||
<Note>
|
||||
`requestAnimationFrame`, `fetch`, `setTimeout`, `queueMicrotask`는 `window.` 접두사 없이도 동작합니다. `window.requestAnimationFrame(...)` 등만 예외를 발생시킵니다.
|
||||
`requestAnimationFrame`, `fetch`, `setTimeout` 및 `queueMicrotask`는 `window.` 접두사 없이 동작합니다. `window.requestAnimationFrame(...)` 등만 예외를 발생시킵니다.
|
||||
</Note>
|
||||
|
||||
### DOM 액세스
|
||||
|
||||
`ref`는 `HTMLElement`가 아닌 샌드박스 요소를 제공합니다.
|
||||
`ref`는 `HTMLElement`가 아니라 샌드박스 요소를 반환합니다.
|
||||
|
||||
| 작성한 코드 | 무슨 일이 일어나는지 | 대신 사용할 것 |
|
||||
| ----------------------------------------------------------------------------------------------------------- | ---------------------------------------------- | --------------------------------------------------------------------------- |
|
||||
| `ref.current.focus()`, `.click()`, `.select()`, `.setSelectionRange()`, `.scrollIntoView()`, `video.play()` | 예외 발생(Throws) | 제어 컴포넌트 사용; 값을 `event.target`에서 읽기 |
|
||||
| `element.classList.add(...)` | 예외 발생(`classList`가 `undefined`임) | `className` 문자열을 직접 구성하세요. |
|
||||
| `document.getElementById()`, `getElementsByClassName()`, `createTreeWalker()` | 예외 발생(Throws) | 정상 동작하는 `querySelector()` / `querySelectorAll()` 사용 |
|
||||
| `document.activeElement` | 항상 `undefined`입니다. | `onFocus` / `onBlur`로 포커스를 추적하세요. |
|
||||
| `\<canvas>` | 아무것도 렌더링되지 않으며, 오류도 없습니다. | SVG를 사용하거나, 오프스크린에서 그린 뒤 `<img src={dataUrl}>`로 표시하세요. |
|
||||
| `createPortal(node, document.body)` | `isConnected`는 성공을 보고하지만 실제로는 아무것도 렌더링되지 않습니다. | `position: absolute`를 사용해 인라인으로 오버레이를 배치하거나, 라이브러리에 직접 렌더링한 컨테이너 요소를 전달하세요. |
|
||||
| 작성한 코드 | 무슨 일이 일어나는지 | 대신 사용할 것 |
|
||||
| ----------------------------------------------------------------------------------------------------------- | ----------------------------------------- | ------------------------------------------------------------------- |
|
||||
| `ref.current.focus()`, `.click()`, `.select()`, `.setSelectionRange()`, `.scrollIntoView()`, `video.play()` | 예외 발생 | 제어 컴포넌트를 사용하고 값을 `event.target`에서 읽습니다 |
|
||||
| `element.classList.add(...)` | 예외 발생(`classList`는 `undefined`임) | `className` 문자열을 직접 구성하세요. |
|
||||
| `document.getElementById()`, `getElementsByClassName()`, `createTreeWalker()` | 예외 발생 | 정상 동작하는 `querySelector()` / `querySelectorAll()`을 사용 |
|
||||
| `document.activeElement` | 항상 `undefined` | `onFocus` / `onBlur`로 포커스를 추적하세요. |
|
||||
| `\<canvas>` | 아무것도 렌더링되지 않으며, 오류도 없습니다. | SVG를 사용하거나, 오프스크린에서 그린 뒤 `<img src={dataUrl}>`로 표시하세요. |
|
||||
| `createPortal(node, document.body)` | `isConnected`는 성공으로 보고하지만 아무것도 렌더링되지 않습니다 | `position: absolute`로 인라인 오버레이를 사용하거나 라이브러리에 직접 렌더링한 컨테이너 요소를 전달하세요 |
|
||||
|
||||
이 포털 간극 때문에 Radix, Headless UI, MUI, react-select의 팝오버는 기본적으로 아무것도 렌더링하지 않습니다. 대부분은 container prop을 받으므로, 여러분이 렌더링한 요소를 가리키도록 설정하면 됩니다.
|
||||
이 포털 간극 때문에 Radix, Headless UI, MUI, react-select의 팝오버는 기본적으로 아무것도 렌더링하지 않습니다. 대부분 컨테이너 prop을 받으므로, 직접 렌더링한 요소를 가리키도록 설정하세요.
|
||||
|
||||
### 이벤트
|
||||
|
||||
Mouse, pointer, touch, drag, keyboard, focus, `input`/`change`/`submit`, `scroll`/`wheel`/`contextmenu` and `animationend`/`transitionend` cross to the host, plus a few per element: `load`/`error` on `<img>`, clipboard and composition on `<input>`/`\<textarea>`, media on `\<video>`/`\<audio>`, `toggle` on `\<details>`/`\<dialog>`. Anything else (`onAuxClick`, `onSelect`, `onInvalid`, `onReset`, `onAnimationStart`, pointer capture, `onLoad` off `<img>`) is dropped without warning.
|
||||
마우스, 포인터, 터치, 드래그, 키보드, 포커스, `input`/`change`/`submit`, `scroll`/`wheel`/`contextmenu` 그리고 `animationend`/`transitionend` 이벤트는 호스트로 전달되며, 여기에 요소별로 몇 가지가 더해집니다: `<img>`의 `load`/`error`, `<input>`/`\<textarea>`의 클립보드 및 조합(composition), `\<video>`/`\<audio>`의 미디어, `\<details>`/`\<dialog>`의 `toggle` 등입니다. 그 밖의 것들(`onAuxClick`, `onSelect`, `onInvalid`, `onReset`, `onAnimationStart`, 포인터 캡처, `<img>`의 `onLoad` 등)은 경고 없이 모두 무시됩니다.
|
||||
|
||||
`document.addEventListener()` and `window.addEventListener()` register without error and never fire, which is why a drag stops as soon as the pointer leaves the element it started on. `event.preventDefault()` does not cross either; form submission, `dragover`/`drop` and link clicks are already guarded for you.
|
||||
`document.addEventListener()`와 `window.addEventListener()`는 오류 없이 등록되지만 절대 실행되지 않으며, 이 때문에 드래그는 시작한 요소를 벗어나는 순간 중지됩니다. `event.preventDefault()` 역시 전달되지 않습니다. 폼 제출, `dragover`/`drop` 및 링크 클릭은 이미 보호되어 있습니다.
|
||||
|
||||
### Attributes and styling
|
||||
### 속성과 스타일링
|
||||
|
||||
Each element forwards its own properties to the host DOM (`href` on `\<a>`, `src`/`alt` on `<img>`, `value`/`placeholder`/`disabled` on `<input>`, and so on), plus a common set on every element: `id`, `className`, `style`, `title`, `tabIndex`, `role`, `draggable` and any `aria-*` / `data-*` attribute (hyphenated, so `ariaLabel` is dropped). Anything outside that is silently discarded, so express custom state as `data-*`.
|
||||
각 요소는 자신의 속성을 호스트 DOM으로 전달합니다(`href`는 `\<a>`, `src`/`alt`는 `<img>`, `value`/`placeholder`/`disabled`는 `<input>` 등). 또한 모든 요소에 공통으로 `id`, `className`, `style`, `title`, `tabIndex`, `role`, `draggable`, 그리고 하이픈이 포함된 모든 `aria-*` / `data-*` 속성(따라서 `ariaLabel`은 무시됨)을 전달합니다. 그 외의 속성은 조용히 폐기되므로, 사용자 정의 상태는 `data-*`로 표현하세요.
|
||||
|
||||
Component CSS, whether from `import './styles.css'`, CSS-in-JS or a `\<style>` element, is injected into the host page's `\<head>` **unscoped**. So class names collide with Twenty's own (prefix them, and never write bare `div { ... }` selectors), and `@media` matches the browser window rather than your widget (use `@container` with your own `container-type`). Inline `style` props are unaffected.
|
||||
컴포넌트 CSS는 `import './styles.css'`, CSS-in-JS 또는 `\<style>` 요소에서 오든, 호스트 페이지의 `\<head>`에 **범위 없이(unscoped)** 주입됩니다. 따라서 클래스 이름이 Twenty 자체 것과 충돌합니다(접두사를 붙이고, `div { ... }` 선택자를 직접 작성하지 마세요). 그리고 `@media`는 위젯이 아니라 브라우저 창을 기준으로 매칭됩니다(직접 지정한 `container-type`과 함께 `@container`를 사용하세요). 인라인 `style` prop은 영향을 받지 않습니다.
|
||||
|
||||
### Storage and network
|
||||
### 스토리지와 네트워크
|
||||
|
||||
`localStorage`, `sessionStorage`, IndexedDB, cookies, the Cache API and `BroadcastChannel` are all unavailable, since the component runs in a worker at an opaque origin. To persist state, call a [logic function](/l/ko/developers/extend/apps/logic/logic-functions) and use its [key-value store](/l/ko/developers/extend/apps/logic/key-value-store).
|
||||
`localStorage`, `sessionStorage`, IndexedDB, 쿠키, Cache API 및 `BroadcastChannel`은 모두 사용할 수 없습니다. 컴포넌트가 불투명한 origin의 워커에서 실행되기 때문입니다. 상태를 영속화하려면 [logic function](/l/ko/developers/extend/apps/logic/logic-functions)을 호출하고, 해당 [key-value store](/l/ko/developers/extend/apps/logic/key-value-store)를 사용하세요.
|
||||
|
||||
`fetch` works, with caveats:
|
||||
`fetch`는 동작하지만, 몇 가지 주의사항이 있습니다:
|
||||
|
||||
* Calls to the Twenty API and your app's routes are proxied by the host, so prefer [`RestApiClient`](#calling-the-twenty-rest-api). On proxied calls, `AbortSignal` and the other `RequestInit` options are dropped, and only `string` and `URLSearchParams` bodies are supported.
|
||||
* Other origins leave the sandbox with `Origin: null`, so a third-party API answers only if it sends `Access-Control-Allow-Origin: *`. Call it from a logic function instead.
|
||||
* `fetch('/rest/people')` is never matched to the Twenty API, because the sandbox has no page URL to resolve a relative path against.
|
||||
* Twenty API와 앱의 라우트로 가는 호출은 호스트에서 프록시되므로, [`RestApiClient`](#calling-the-twenty-rest-api)를 사용하는 것이 좋습니다. 프록시되는 호출에서는 `AbortSignal` 및 기타 `RequestInit` 옵션이 제거되며, `string`과 `URLSearchParams` 타입의 body만 지원됩니다.
|
||||
* 다른 오리진으로 나가는 요청은 `Origin: null`을 가진 채 샌드박스를 벗어나므로, 서드파티 API는 `Access-Control-Allow-Origin: *`를 보내는 경우에만 응답합니다. 대신 logic function에서 호출하세요.
|
||||
* 샌드박스에는 상대 경로를 해석할 페이지 URL이 없으므로, `fetch('/rest/people')`은 Twenty API와 절대 매칭되지 않습니다.
|
||||
|
||||
### Other gaps
|
||||
### 기타 제약 사항
|
||||
|
||||
* **File contents.** `<input type="file">` gives your handler file metadata only, not the bytes, so `FileReader` and uploads are not possible yet.
|
||||
* **Drag-and-drop payloads.** Drag events fire, but `event.dataTransfer` is `undefined`.
|
||||
* **Node built-ins.** `fs`, `path` and `node:crypto` fail the build, so move that work into a [logic function](/l/ko/developers/extend/apps/logic/logic-functions). Web Crypto, `fetch`, `TextEncoder` and `URL` are available.
|
||||
* **`\<iframe>`** is always re-sandboxed without `allow-same-origin`, so an embed relying on its own session renders logged out. It has no `onLoad` either.
|
||||
* **파일 내용.** `<input type="file">`은 핸들러에 바이트가 아닌 파일 메타데이터만 제공하므로, 현재는 `FileReader` 사용과 업로드가 불가능합니다.
|
||||
* **드래그 앤 드롭 페이로드.** 드래그 이벤트는 발생하지만, `event.dataTransfer`는 `undefined`입니다.
|
||||
* **Node 내장 모듈.** `fs`, `path` 및 `node:crypto`는 빌드에 실패하므로, 해당 작업은 [logic function](/l/ko/developers/extend/apps/logic/logic-functions)으로 옮기세요. Web Crypto, `fetch`, `TextEncoder` 및 `URL`은 사용할 수 있습니다.
|
||||
* \*\*`\<iframe>`\*\*은 항상 `allow-same-origin` 없이 다시 샌드박싱되므로, 자체 세션에 의존하는 임베드는 로그아웃된 상태로 렌더링됩니다. 또한 `onLoad`도 지원되지 않습니다.
|
||||
|
||||
@@ -703,9 +703,9 @@ Pentru a ramifica explicit în funcție de schema activă, citește-o cu `useCol
|
||||
|
||||
## Limitări actuale
|
||||
|
||||
Componentele Front sunt în dezvoltare activă. Redarea, stilizarea și gestionarea evenimentelor funcționează bine. Orice ajunge *dincolo de* redare (măsurarea unui element, apelarea unei metode DOM pe un ref, portarea în afara arborelui tău, accesarea stocării browserului) lipsește sau este incompletă astăzi, iar majoritatea eșuează în mod silențios: nu există excepție și nici eroare TypeScript, deoarece scheletul este tastat pentru întregul DOM al browserului.
|
||||
Componentele Front sunt în curs de dezvoltare activă. Redarea, stilizarea și gestionarea evenimentelor funcționează bine. Orice ajunge *dincolo de* redare (măsurarea unui element, apelarea unei metode DOM pe un ref, crearea unui portal în afara arborelui tău, accesarea spațiului de stocare al browserului) lipsește sau este incomplet astăzi, iar majoritatea eșuează în tăcere: fără excepție și fără eroare TypeScript, deoarece scheletul este tipizat pentru întregul DOM al browserului.
|
||||
|
||||
Dacă una dintre acestea te blochează, [deschide un tichet](https://github.com/twentyhq/twenty/issues/new/choose) pentru a fi prioritizată.
|
||||
Dacă unul dintre aceste lucruri te blochează, [deschide un tichet](https://github.com/twentyhq/twenty/issues/new/choose) ca să fie prioritar.
|
||||
|
||||
### Layout și măsurare
|
||||
|
||||
@@ -715,12 +715,12 @@ Nimic nu se poate măsura singur încă.
|
||||
| ------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
|
||||
| `getBoundingClientRect()`, `getClientRects()` | Aruncă o excepție |
|
||||
| `offsetWidth`, `clientWidth`, `scrollWidth`, `offsetTop`, ... | Este în mod silențios `undefined`, astfel încât `width ?? 0` produce `0`, iar `width > 600` este întotdeauna fals |
|
||||
| `ResizeObserver`, `IntersectionObserver` | `ReferenceError` (gardurile `typeof` funcționează) |
|
||||
| `ResizeObserver`, `IntersectionObserver` | `ReferenceError` (verificările cu `typeof` funcționează) |
|
||||
| `window.matchMedia()`, `window.getComputedStyle()` | Aruncă o excepție |
|
||||
| `window.innerWidth`, `innerHeight`, `devicePixelRatio` | Este în mod silențios `undefined` |
|
||||
| `new MutationObserver(fn)` | Se construiește, apoi `.observe()` aruncă o excepție |
|
||||
|
||||
Prin urmare, `ResponsiveContainer` din recharts, Floating UI / Popper, virtualizarea listelor și redimensionarea prin tragere nu funcționează încă. Fă layout-ul în CSS în schimb: foaia ta de stil ajunge la pagina reală, astfel încât flexbox, grid, `aspect-ratio`, `clamp()` și `@container` se comportă toate normal.
|
||||
Prin urmare, `ResponsiveContainer` din recharts, Floating UI / Popper, virtualizarea listelor și redimensionarea prin tragere nu funcționează încă. Fă layout-ul în CSS în schimb: fișierul tău de stiluri ajunge la pagina reală, astfel încât flexbox, grid, `aspect-ratio`, `clamp()` și `@container` se comportă toate normal.
|
||||
|
||||
<Note>
|
||||
`requestAnimationFrame`, `fetch`, `setTimeout` și `queueMicrotask` funcționează fără prefixul `window.`. Numai `window.requestAnimationFrame(...)` și cele similare aruncă o excepție.
|
||||
@@ -728,44 +728,44 @@ Prin urmare, `ResponsiveContainer` din recharts, Floating UI / Popper, virtualiz
|
||||
|
||||
### Acces DOM
|
||||
|
||||
Un `ref` îți oferă un element sandbox, nu un `HTMLElement`.
|
||||
Un `ref` îți oferă un element din sandbox, nu un `HTMLElement`.
|
||||
|
||||
| Ce scrii | Ce se întâmplă | Folosește în schimb |
|
||||
| ----------------------------------------------------------------------------------------------------------- | --------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
|
||||
| `ref.current.focus()`, `.click()`, `.select()`, `.setSelectionRange()`, `.scrollIntoView()`, `video.play()` | Aruncă o excepție | Componente controlate; citește valorile din `event.target` |
|
||||
| `element.classList.add(...)` | Aruncă o excepție (`classList` este `undefined`) | Construiește manual șirul `className` |
|
||||
| `element.classList.add(...)` | Aruncă o excepție (`classList` este `undefined`) | Construiește singur șirul `className` |
|
||||
| `document.getElementById()`, `getElementsByClassName()`, `createTreeWalker()` | Aruncă o excepție | `querySelector()` / `querySelectorAll()`, care funcționează |
|
||||
| `document.activeElement` | Întotdeauna `undefined` | Urmărește focusul cu `onFocus` / `onBlur` |
|
||||
| `\<canvas>` | Nu redă nimic, fără eroare | SVG sau desenează în offscreen și afișează un `<img src={dataUrl}>` |
|
||||
| `\<canvas>` | Nu redă nimic, fără eroare | SVG sau desenează offscreen și afișează un `<img src={dataUrl}>` |
|
||||
| `createPortal(node, document.body)` | Nu redă nimic, în timp ce `isConnected` raportează succes | Suprapuneri inline cu `position: absolute` sau transmite bibliotecii propriul tău element container |
|
||||
|
||||
Golul portalului este motivul pentru care popover-urile Radix, Headless UI, MUI și react-select nu redau nimic în mod implicit. Majoritatea acceptă o proprietate de tip container; indică-i un element pe care l-ai redat.
|
||||
|
||||
### Evenimente
|
||||
|
||||
Mouse, pointer, touch, drag, keyboard, focus, `input`/`change`/`submit`, `scroll`/`wheel`/`contextmenu` and `animationend`/`transitionend` cross to the host, plus a few per element: `load`/`error` on `<img>`, clipboard and composition on `<input>`/`\<textarea>`, media on `\<video>`/`\<audio>`, `toggle` on `\<details>`/`\<dialog>`. Anything else (`onAuxClick`, `onSelect`, `onInvalid`, `onReset`, `onAnimationStart`, pointer capture, `onLoad` off `<img>`) is dropped without warning.
|
||||
Mouse, pointer, touch, drag, tastatură, focus, `input`/`change`/`submit`, `scroll`/`wheel`/`contextmenu` și `animationend`/`transitionend` trec către gazdă, plus câteva per element: `load`/`error` pe `<img>`, clipboard și compoziție pe `<input>`/`\<textarea>`, media pe `\<video>`/`\<audio>`, `toggle` pe `\<details>`/`\<dialog>`. Orice altceva (`onAuxClick`, `onSelect`, `onInvalid`, `onReset`, `onAnimationStart`, pointer capture, `onLoad` de pe `<img>`) este eliminat fără avertisment.
|
||||
|
||||
`document.addEventListener()` and `window.addEventListener()` register without error and never fire, which is why a drag stops as soon as the pointer leaves the element it started on. `event.preventDefault()` does not cross either; form submission, `dragover`/`drop` and link clicks are already guarded for you.
|
||||
`document.addEventListener()` și `window.addEventListener()` se înregistrează fără eroare și nu se declanșează niciodată, motiv pentru care un drag se oprește imediat ce pointerul părăsește elementul de pe care a început. `event.preventDefault()` nu trece nici el; trimiterea formularelor, `dragover`/`drop` și clicurile pe linkuri sunt deja protejate pentru tine.
|
||||
|
||||
### Attributes and styling
|
||||
### Atribute și stilizare
|
||||
|
||||
Each element forwards its own properties to the host DOM (`href` on `\<a>`, `src`/`alt` on `<img>`, `value`/`placeholder`/`disabled` on `<input>`, and so on), plus a common set on every element: `id`, `className`, `style`, `title`, `tabIndex`, `role`, `draggable` and any `aria-*` / `data-*` attribute (hyphenated, so `ariaLabel` is dropped). Anything outside that is silently discarded, so express custom state as `data-*`.
|
||||
Fiecare element își transmite propriile proprietăți către DOM-ul gazdă (`href` pe `\<a>`, `src`/`alt` pe `<img>`, `value`/`placeholder`/`disabled` pe `<input>` și așa mai departe), plus un set comun pe fiecare element: `id`, `className`, `style`, `title`, `tabIndex`, `role`, `draggable` și orice atribut `aria-*` / `data-*` (cu cratimă, astfel încât `ariaLabel` este ignorat). Orice în afara acestora este ignorat în tăcere, așa că exprimă starea personalizată ca `data-*`.
|
||||
|
||||
Component CSS, whether from `import './styles.css'`, CSS-in-JS or a `\<style>` element, is injected into the host page's `\<head>` **unscoped**. So class names collide with Twenty's own (prefix them, and never write bare `div { ... }` selectors), and `@media` matches the browser window rather than your widget (use `@container` with your own `container-type`). Inline `style` props are unaffected.
|
||||
CSS-ul componentei, fie din `import './styles.css'`, CSS-in-JS sau un element `\<style>`, este injectat în `\<head>` al paginii gazdă **fără scope**. Astfel numele de clase intră în coliziune cu cele ale Twenty (prefixează-le și nu scrie niciodată un selector simplu `div { ... }`), iar `@media` se potrivește cu fereastra browserului, nu cu widgetul tău (folosește `@container` cu propriul tău `container-type`). Proprietățile `style` inline nu sunt afectate.
|
||||
|
||||
### Storage and network
|
||||
### Stocare și rețea
|
||||
|
||||
`localStorage`, `sessionStorage`, IndexedDB, cookies, the Cache API and `BroadcastChannel` are all unavailable, since the component runs in a worker at an opaque origin. To persist state, call a [logic function](/l/ro/developers/extend/apps/logic/logic-functions) and use its [key-value store](/l/ro/developers/extend/apps/logic/key-value-store).
|
||||
`localStorage`, `sessionStorage`, IndexedDB, cookie-urile, Cache API și `BroadcastChannel` nu sunt disponibile, deoarece componenta rulează într-un worker cu o origine opacă. Pentru a păstra starea, apelează o [logic function](/l/ro/developers/extend/apps/logic/logic-functions) și folosește [key-value store-ul](/l/ro/developers/extend/apps/logic/key-value-store) acesteia.
|
||||
|
||||
`fetch` works, with caveats:
|
||||
`fetch` funcționează, cu unele rezerve:
|
||||
|
||||
* Calls to the Twenty API and your app's routes are proxied by the host, so prefer [`RestApiClient`](#calling-the-twenty-rest-api). On proxied calls, `AbortSignal` and the other `RequestInit` options are dropped, and only `string` and `URLSearchParams` bodies are supported.
|
||||
* Other origins leave the sandbox with `Origin: null`, so a third-party API answers only if it sends `Access-Control-Allow-Origin: *`. Call it from a logic function instead.
|
||||
* `fetch('/rest/people')` is never matched to the Twenty API, because the sandbox has no page URL to resolve a relative path against.
|
||||
* Apelurile către Twenty API și către rutele aplicației tale sunt proxate de gazdă, așa că preferă [`RestApiClient`](#calling-the-twenty-rest-api). La apelurile proxate, `AbortSignal` și celelalte opțiuni `RequestInit` sunt eliminate, iar doar corpurile de tip `string` și `URLSearchParams` sunt acceptate.
|
||||
* Alte origini părăsesc sandbox-ul cu `Origin: null`, astfel încât un API terț răspunde doar dacă trimite `Access-Control-Allow-Origin: *`. Apelează-l dintr-o logic function în schimb.
|
||||
* `fetch('/rest/people')` nu este niciodată asociat cu Twenty API, deoarece sandbox-ul nu are un URL de pagină față de care să rezolve o cale relativă.
|
||||
|
||||
### Other gaps
|
||||
### Alte lacune
|
||||
|
||||
* **File contents.** `<input type="file">` gives your handler file metadata only, not the bytes, so `FileReader` and uploads are not possible yet.
|
||||
* **Drag-and-drop payloads.** Drag events fire, but `event.dataTransfer` is `undefined`.
|
||||
* **Node built-ins.** `fs`, `path` and `node:crypto` fail the build, so move that work into a [logic function](/l/ro/developers/extend/apps/logic/logic-functions). Web Crypto, `fetch`, `TextEncoder` and `URL` are available.
|
||||
* **`\<iframe>`** is always re-sandboxed without `allow-same-origin`, so an embed relying on its own session renders logged out. It has no `onLoad` either.
|
||||
* **Conținutul fișierului.** `<input type="file">` oferă handlerului tău doar metadatele fișierului, nu și octeții, astfel încât `FileReader` și încărcările nu sunt încă posibile.
|
||||
* **Payload-uri drag-and-drop.** Evenimentele de tip drag sunt declanșate, dar `event.dataTransfer` este `undefined`.
|
||||
* **Built-in-uri Node.** `fs`, `path` și `node:crypto` eșuează la build, așa că mută acea logică într-o [logic function](/l/ro/developers/extend/apps/logic/logic-functions). Web Crypto, `fetch`, `TextEncoder` și `URL` sunt disponibile.
|
||||
* **`\<iframe>`** este întotdeauna pus din nou în sandbox fără `allow-same-origin`, astfel încât un embed care se bazează pe propria sesiune este randat ca delogat. Nu are nici `onLoad`.
|
||||
|
||||
@@ -56,4 +56,4 @@ icon: table-columns
|
||||
|
||||
Componentele front rulează în interiorul unui Web Worker izolat folosind Remote DOM — acestea sunt redate *nativ* în pagină (nu într-un iframe), dar nu pot accesa direct pagina gazdă sau DOM-ul. Comunicarea cu Twenty se face printr-un API al gazdei bazat pe transmiterea de mesaje.
|
||||
|
||||
Sunt încă în curs de dezvoltare activă: sandbox-ul implementează un DOM parțial, astfel încât utilizările avansate pot eșua. Vezi [limitările actuale](/l/ro/developers/extend/apps/layout/front-components#current-limitations).
|
||||
Sunt încă în curs de dezvoltare activă: sandbox-ul implementează un DOM parțial, astfel încât utilizările avansate pot eșua. Vezi [Limitări actuale](/l/ro/developers/extend/apps/layout/front-components#current-limitations).
|
||||
|
||||
@@ -703,24 +703,24 @@ Etkin şemaya açıkça dallanmak için, `twenty-sdk/front-component` içindeki
|
||||
|
||||
## Mevcut sınırlamalar
|
||||
|
||||
Front bileşenleri aktif olarak geliştirilmektedir. Render etme, stil verme ve olayları işleme iyi çalışıyor. Render etmenin *ötesine* geçen her şey (bir öğeyi ölçmek, bir ref üzerinde bir DOM metodunu çağırmak, ağacınızın dışına portal oluşturmak, tarayıcı depolamasına dokunmak) bugün eksik veya tamamlanmamış durumda ve çoğu sessizce başarısız oluyor: hiçbir exception yok ve TypeScript hatası da yok, çünkü iskelet tam tarayıcı DOM’una göre type edilmiştir.
|
||||
Front bileşenleri aktif geliştirme aşamasındadır. Render etme, stil verme ve olayları işleme iyi çalışıyor. Render işleminin *ötesine* geçen her şey (bir öğeyi ölçmek, bir ref üzerinde bir DOM yöntemini çağırmak, ağacınızın dışına portal oluşturmak, tarayıcı depolamasına erişmek) bugün eksik ya da tamamlanmamış durumda ve çoğu sessizce başarısız olur: ne bir istisna fırlatılır ne de TypeScript hatası görülür; çünkü iskeletin türleri tam tarayıcı DOM’una göre tanımlanmıştır.
|
||||
|
||||
Bunlardan biri sizi engelliyorsa, önceliklendirilmesi için [open an issue](https://github.com/twentyhq/twenty/issues/new/choose).
|
||||
Bunlardan biri sizi engelliyorsa, önceliklendirilmesi için [bir issue açın](https://github.com/twentyhq/twenty/issues/new/choose).
|
||||
|
||||
### Yerleşim ve ölçüm
|
||||
|
||||
Hiçbir şey henüz kendi kendini ölçemiyor.
|
||||
Henüz hiçbir şey kendisini ölçemiyor.
|
||||
|
||||
| API | Ne olur |
|
||||
| ------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
|
||||
| `getBoundingClientRect()`, `getClientRects()` | Fırlatır |
|
||||
| `offsetWidth`, `clientWidth`, `scrollWidth`, `offsetTop`, ... | Sessizce `undefined`, bu yüzden `width ?? 0` sonucu `0` verir ve `width > 600` her zaman false olur |
|
||||
| `ResizeObserver`, `IntersectionObserver` | `ReferenceError` (`typeof` guard’ları çalışır) |
|
||||
| `window.matchMedia()`, `window.getComputedStyle()` | Fırlatır |
|
||||
| `window.innerWidth`, `innerHeight`, `devicePixelRatio` | Sessizce `undefined` |
|
||||
| `new MutationObserver(fn)` | Oluşturur, ardından `.observe()` fırlatır |
|
||||
| API | Ne olur |
|
||||
| ------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
|
||||
| `getBoundingClientRect()`, `getClientRects()` | Fırlatır |
|
||||
| `offsetWidth`, `clientWidth`, `scrollWidth`, `offsetTop`, ... | Sessizce `undefined`, bu yüzden `width ?? 0` `0` döner ve `width > 600` her zaman false olur |
|
||||
| `ResizeObserver`, `IntersectionObserver` | `ReferenceError` (`typeof` kontrolleri çalışır) |
|
||||
| `window.matchMedia()`, `window.getComputedStyle()` | Fırlatır |
|
||||
| `window.innerWidth`, `innerHeight`, `devicePixelRatio` | Sessizce `undefined` |
|
||||
| `new MutationObserver(fn)` | Oluşturulur, ardından `.observe()` fırlatır |
|
||||
|
||||
Bu yüzden recharts `ResponsiveContainer`, Floating UI / Popper, liste sanallaştırma ve sürükleyerek boyutlandırma henüz çalışmıyor. Bunun yerine yerleşimi CSS’te yapın: stil sayfanız gerçek sayfaya ulaştığı için flexbox, grid, `aspect-ratio`, `clamp()` ve `@container` normal şekilde davranır.
|
||||
Bu nedenle recharts `ResponsiveContainer`, Floating UI / Popper, liste sanallaştırma ve sürükleyerek yeniden boyutlandırma henüz çalışmıyor. Bunun yerine yerleşimi CSS ile yapın: stil sayfanız gerçek sayfaya erişir, bu nedenle flexbox, grid, `aspect-ratio`, `clamp()` ve `@container` normal şekilde davranır.
|
||||
|
||||
<Note>
|
||||
`requestAnimationFrame`, `fetch`, `setTimeout` ve `queueMicrotask` `window.` öneki olmadan çalışır. Yalnızca `window.requestAnimationFrame(...)` ve benzerleri fırlatır.
|
||||
@@ -730,42 +730,42 @@ Bu yüzden recharts `ResponsiveContainer`, Floating UI / Popper, liste sanallaş
|
||||
|
||||
Bir `ref` size bir `HTMLElement` değil, bir sandbox öğesi verir.
|
||||
|
||||
| Ne yazarsınız | Ne olur | Bunun yerine şunu kullanın |
|
||||
| ----------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
|
||||
| `ref.current.focus()`, `.click()`, `.select()`, `.setSelectionRange()`, `.scrollIntoView()`, `video.play()` | Fırlatır | Kontrollü bileşenler; değerleri `event.target` üzerinden okuyun |
|
||||
| `element.classList.add(...)` | Fırlatır (`classList` `undefined`’dır) | `className` string’ini kendiniz oluşturun |
|
||||
| `document.getElementById()`, `getElementsByClassName()`, `createTreeWalker()` | Fırlatır | Çalışan `querySelector()` / `querySelectorAll()` |
|
||||
| `document.activeElement` | Her zaman `undefined` | Odağı `onFocus` / `onBlur` ile takip edin |
|
||||
| `\<canvas>` | Hiçbir şey render etmez, hata yoktur | SVG kullanın veya ekranda olmayan bir yerde çizip bir `<img src={dataUrl}>` gösterin |
|
||||
| `createPortal(node, document.body)` | `isConnected` başarı bildirmesine rağmen hiçbir şey render etmez | Yer paylaşımlarını `position: absolute` ile satır içinde yapın veya kütüphaneye kendi container öğenizi verin |
|
||||
| Ne yazarsınız | Ne olur | Bunun yerine şunu kullanın |
|
||||
| ----------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
|
||||
| `ref.current.focus()`, `.click()`, `.select()`, `.setSelectionRange()`, `.scrollIntoView()`, `video.play()` | Fırlatır | Kontrollü bileşenler; değerleri `event.target` üzerinden okuyun |
|
||||
| `element.classList.add(...)` | Fırlatır (`classList` `undefined` durumundadır) | `className` dizgisini kendiniz oluşturun |
|
||||
| `document.getElementById()`, `getElementsByClassName()`, `createTreeWalker()` | Fırlatır | Çalışan `querySelector()` / `querySelectorAll()` |
|
||||
| `document.activeElement` | Her zaman `undefined` | Odağı `onFocus` / `onBlur` ile takip edin |
|
||||
| `\<canvas>` | Hiçbir şey render etmez, hata yoktur | SVG kullanın veya ekranda olmayan bir alana çizip bir `<img src={dataUrl}>` ile gösterin |
|
||||
| `createPortal(node, document.body)` | `isConnected` başarı bildirmesine rağmen hiçbir şey render etmez | `position: absolute` ile satır içi yerleştirilmiş bindirmeler veya kitaplığa kendi konteyner öğenizi iletin |
|
||||
|
||||
Portal boşluğu, Radix, Headless UI, MUI ve react-select popover’larının varsayılan olarak hiçbir şey render etmemesinin nedenidir. Çoğu bir container prop kabul eder; onu render ettiğiniz bir öğeye yönlendirin.
|
||||
|
||||
### Etkinlikler
|
||||
|
||||
Mouse, pointer, touch, drag, keyboard, focus, `input`/`change`/`submit`, `scroll`/`wheel`/`contextmenu` and `animationend`/`transitionend` cross to the host, plus a few per element: `load`/`error` on `<img>`, clipboard and composition on `<input>`/`\<textarea>`, media on `\<video>`/`\<audio>`, `toggle` on `\<details>`/`\<dialog>`. Anything else (`onAuxClick`, `onSelect`, `onInvalid`, `onReset`, `onAnimationStart`, pointer capture, `onLoad` off `<img>`) is dropped without warning.
|
||||
Mouse, pointer, touch, sürükleme, klavye, odak, `input`/`change`/`submit`, `scroll`/`wheel`/`contextmenu` ve `animationend`/`transitionend` ana bilgisayara iletilir, ayrıca birkaç tane de öğe başına vardır: `<img>` üzerinde `load`/`error`, `<input>`/`\<textarea>` üzerinde panoya ve bileşime ilişkin olaylar, `\<video>`/`\<audio>` üzerinde medya, `\<details>`/`\<dialog>` üzerinde `toggle`. Bunun dışındaki her şey (`onAuxClick`, `onSelect`, `onInvalid`, `onReset`, `onAnimationStart`, pointer capture, `<img>` üzerinde `onLoad`) uyarı verilmeden kaldırılır.
|
||||
|
||||
`document.addEventListener()` and `window.addEventListener()` register without error and never fire, which is why a drag stops as soon as the pointer leaves the element it started on. `event.preventDefault()` does not cross either; form submission, `dragover`/`drop` and link clicks are already guarded for you.
|
||||
`document.addEventListener()` ve `window.addEventListener()` hatasız olarak kaydolur ancak asla tetiklenmez; bu yüzden bir sürükleme, işaretçi başladığı öğeden ayrılır ayrılmaz durur. `event.preventDefault()` da geçmez; form gönderimi, `dragover`/`drop` ve bağlantı tıklamaları zaten sizin için korunmuştur.
|
||||
|
||||
### Attributes and styling
|
||||
### Öznitelikler ve stillendirme
|
||||
|
||||
Each element forwards its own properties to the host DOM (`href` on `\<a>`, `src`/`alt` on `<img>`, `value`/`placeholder`/`disabled` on `<input>`, and so on), plus a common set on every element: `id`, `className`, `style`, `title`, `tabIndex`, `role`, `draggable` and any `aria-*` / `data-*` attribute (hyphenated, so `ariaLabel` is dropped). Anything outside that is silently discarded, so express custom state as `data-*`.
|
||||
Her öğe, kendi özelliklerini host DOM’a iletir (`\<a>` üzerinde `href`, `<img>` üzerinde `src`/`alt`, `<input>` üzerinde `value`/`placeholder`/`disabled` vb.), ayrıca her öğede ortak bir küme vardır: `id`, `className`, `style`, `title`, `tabIndex`, `role`, `draggable` ve tireli olan tüm `aria-*` / `data-*` öznitelikleri (bu yüzden `ariaLabel` düşürülür). Bunun dışındaki her şey sessizce atılır, bu yüzden özel durumu `data-*` olarak ifade edin.
|
||||
|
||||
Component CSS, whether from `import './styles.css'`, CSS-in-JS or a `\<style>` element, is injected into the host page's `\<head>` **unscoped**. So class names collide with Twenty's own (prefix them, and never write bare `div { ... }` selectors), and `@media` matches the browser window rather than your widget (use `@container` with your own `container-type`). Inline `style` props are unaffected.
|
||||
Bileşen CSS’i, ister `import './styles.css'` ile, ister CSS-in-JS ile ya da bir `\<style>` öğesinden gelsin, host sayfanın `\<head>` kısmına **scope’suz** olarak enjekte edilir. Bu nedenle sınıf adları Twenty’nin kendi sınıf adlarıyla çakışır (onlara önek ekleyin ve asla çıplak `div { ... }` seçicileri yazmayın) ve `@media`, sizin bileşeniniz yerine tarayıcı penceresini hedefler (kendi `container-type` değerinizle `@container` kullanın). Satır içi `style` prop’ları etkilenmez.
|
||||
|
||||
### Storage and network
|
||||
### Depolama ve ağ
|
||||
|
||||
`localStorage`, `sessionStorage`, IndexedDB, cookies, the Cache API and `BroadcastChannel` are all unavailable, since the component runs in a worker at an opaque origin. To persist state, call a [logic function](/l/tr/developers/extend/apps/logic/logic-functions) and use its [key-value store](/l/tr/developers/extend/apps/logic/key-value-store).
|
||||
`localStorage`, `sessionStorage`, IndexedDB, çerezler, Cache API ve `BroadcastChannel`’ın tümü kullanılamaz, çünkü bileşen opak bir origin’e sahip bir worker içinde çalışır. Durumu kalıcı hale getirmek için bir [mantık fonksiyonu](/l/tr/developers/extend/apps/logic/logic-functions) çağırın ve onun [anahtar-değer deposunu](/l/tr/developers/extend/apps/logic/key-value-store) kullanın.
|
||||
|
||||
`fetch` works, with caveats:
|
||||
`fetch` çalışır, bazı sınırlamalarla:
|
||||
|
||||
* Calls to the Twenty API and your app's routes are proxied by the host, so prefer [`RestApiClient`](#calling-the-twenty-rest-api). On proxied calls, `AbortSignal` and the other `RequestInit` options are dropped, and only `string` and `URLSearchParams` bodies are supported.
|
||||
* Other origins leave the sandbox with `Origin: null`, so a third-party API answers only if it sends `Access-Control-Allow-Origin: *`. Call it from a logic function instead.
|
||||
* `fetch('/rest/people')` is never matched to the Twenty API, because the sandbox has no page URL to resolve a relative path against.
|
||||
* Twenty API’sine ve uygulamanızın rotalarına yapılan çağrılar host tarafından proxy’lenir, bu yüzden [`RestApiClient`](#calling-the-twenty-rest-api) kullanmayı tercih edin. Proxy’lenen çağrılarda `AbortSignal` ve diğer `RequestInit` seçenekleri kaldırılır ve yalnızca `string` ve `URLSearchParams` gövdeleri desteklenir.
|
||||
* Diğer origin’ler sandbox’tan `Origin: null` ile çıkar, bu yüzden üçüncü taraf bir API yalnızca `Access-Control-Allow-Origin: *` gönderirse yanıt verir. Bunun yerine onu bir mantık fonksiyonundan çağırın.
|
||||
* `fetch('/rest/people')` hiçbir zaman Twenty API’siyle eşleştirilmez, çünkü sandbox’un göreli yolu çözecek bir sayfa URL’si yoktur.
|
||||
|
||||
### Other gaps
|
||||
### Diğer eksikler
|
||||
|
||||
* **File contents.** `<input type="file">` gives your handler file metadata only, not the bytes, so `FileReader` and uploads are not possible yet.
|
||||
* **Drag-and-drop payloads.** Drag events fire, but `event.dataTransfer` is `undefined`.
|
||||
* **Node built-ins.** `fs`, `path` and `node:crypto` fail the build, so move that work into a [logic function](/l/tr/developers/extend/apps/logic/logic-functions). Web Crypto, `fetch`, `TextEncoder` and `URL` are available.
|
||||
* **`\<iframe>`** is always re-sandboxed without `allow-same-origin`, so an embed relying on its own session renders logged out. It has no `onLoad` either.
|
||||
* **Dosya içerikleri.** `<input type="file">` handler’ınıza yalnızca dosya meta verilerini verir, baytları vermez, bu yüzden `FileReader` ve yüklemeler henüz mümkün değildir.
|
||||
* **Sürükle-bırak yükleri.** Sürükleme olayları tetiklenir, ancak `event.dataTransfer` `undefined` durumundadır.
|
||||
* **Node yerleşikleri.** `fs`, `path` ve `node:crypto` build aşamasında başarısız olur; bu nedenle bu işi bir [mantık fonksiyonuna](/l/tr/developers/extend/apps/logic/logic-functions) taşıyın. Web Crypto, `fetch`, `TextEncoder` ve `URL` kullanılabilir durumdadır.
|
||||
* **`\<iframe>`** her zaman `allow-same-origin` olmadan yeniden sandbox’a alınır, bu nedenle kendi oturumuna güvenen bir yerleştirme, oturum kapalı olarak işlenir. `onLoad`’u da yoktur.
|
||||
|
||||
@@ -56,4 +56,4 @@ Bir Twenty uygulamasının **düzen katmanı**, kullanıcının gördüğü her
|
||||
|
||||
Ön uç bileşenleri, Remote DOM kullanan yalıtılmış bir Web Worker içinde çalışır — sayfada *yerel* olarak oluşturulurlar (bir iframe içinde değil), ancak ana makine sayfasına veya DOM'a doğrudan erişemezler. Twenty ile iletişim, mesaj iletimi yapan bir ana makine API'si aracılığıyla gerçekleşir.
|
||||
|
||||
Hâlâ etkin geliştirme aşamasındalar: sandbox kısmi bir DOM uygular, bu nedenle gelişmiş kullanımlar başarısız olabilir. [Geçerli kısıtlamalar](/l/tr/developers/extend/apps/layout/front-components#current-limitations) bölümüne bakın.
|
||||
Hâlâ etkin geliştirme aşamasındalar: sandbox kısmi bir DOM uygular, bu nedenle gelişmiş kullanımlar başarısız olabilir. [Mevcut sınırlamalara](/l/tr/developers/extend/apps/layout/front-components#current-limitations) bakın.
|
||||
|
||||
Reference in New Issue
Block a user