3281d37bdf80098c411a4101736bfd7c5e568d8d
5
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
75c22a2119 |
feat(front-component-renderer): forward file input metadata (#20458)
## Summary `<input type=\"file\">` inside front-components was silently non-functional: - The host-side `serializeEvent` did not read `target.files`, so the worker received an empty `onChange` detail. - `SerializedEventData` had no `files` field. - The `html-input` schema in `AllowedHtmlElements` exposed neither `accept`, `multiple`, nor `capture` — the worker could not even configure the picker. This PR forwards file metadata (`name`, `size`, `type`, `lastModified`) through the existing serialized event detail and accepts the missing attributes on the `html-input` remote element. A new Storybook play test guards the regression by uploading single and multiple files via `userEvent.upload`. Reading file contents inside the worker is intentionally out of scope here and will need a separate host API bridge (the host has the `File` objects on the real input element; passing bytes through `postMessage` is a bigger design call). |
||
|
|
f634a4a0c0 |
fix(front-component): preserve caret position on controlled input/textarea updates (#20416)
## Problem In the front-component sandbox, typing in the middle of a pre-filled `<input>` or `<textarea>` caused the caret to jump to the end on every keystroke. Characters appeared at the correct position, but editing mid-string was effectively broken. Root cause: the remote-DOM bridge round-trips every keystroke through the worker. By the time the updated `value` prop arrives back at the host, React applies it by setting `inputElement.value = X` directly, which browsers always reset the caret to the end. Typing at the end was unaffected, which is why this went unnoticed in search fields and similar append-only inputs. ## Fix For text-like `<input>` types and `<textarea>`, the `value` prop is now applied imperatively through a ref callback instead of being passed as a React controlled prop: - If the DOM value already matches the incoming prop, the assignment is skipped entirely. - If a write is needed and the element is focused, `selectionStart` and `selectionEnd` are captured before the assignment and restored afterwards with `setSelectionRange`. Non-text input types (checkbox, radio, file, color, range) and all other host elements are unaffected. ## Testing Drop the repro from the issue into any front-component, click between two characters in the pre-filled value, and type — the caret should now stay at the insertion point. Fixes #20409 --------- Co-authored-by: Charles Bochet <charles@twenty.com> |
||
|
|
eb1ca1b9ec |
perf(sdk): split twenty-sdk barrel into per-purpose subpaths to cut logic-function bundle ~700x (#19834)
## Summary
Logic-function bundles produced by the twenty-sdk CLI were ~1.18 MB even
for a one-line handler. Root cause: the SDK shipped as a single bundled
barrel (`twenty-sdk` → `dist/index.mjs`) that co-mingled server-side
definition factories with the front-component runtime, validation (zod),
and React. With no `\"sideEffects\"` declaration on the SDK package,
esbuild had to assume every module-level statement could have side
effects and refused to drop unused code.
This PR restructures the SDK so consumers' bundlers can tree-shake at
the leaf level:
- **Reorganized SDK source.** All server-side definition factories now
live under `src/sdk/define/` (agents, application, fields,
logic-functions, objects, page-layouts, roles, skills, views,
navigation-menu-items, etc.). All front-component runtime
(components, hooks, host APIs, command primitives) lives under
`src/sdk/front-component/`. The legacy bare `src/sdk/index.ts` is
removed; the bare `twenty-sdk` entry no longer exists.
- **Split the build configs by purpose / runtime env.** Replaced
`vite.config.sdk.ts` with two purpose-specific configs:
- `vite.config.define.ts` — node target, externals from package
`dependencies`, emits to `dist/define/**`
- `vite.config.front-component.ts` — browser/React target, emits to
`dist/front-component/**`
Both use `preserveModules: true` so each leaf ships as its own `.mjs`.
- **\`\"sideEffects\": false\`** on `twenty-sdk` so esbuild can drop
unreferenced re-exports.
- **\`package.json\` exports + \`typesVersions\`** updated: dropped the
bare \`.\` entry, added \`./front-component\`, and pointed \`./define\`
at the new per-module dist layout.
- **Migrated every internal/example/community app** to the new subpath
imports (`twenty-sdk/define`, `twenty-sdk/front-component`,
`twenty-sdk/ui`).
- **Added \`bundle-investigation\` internal app** that reproduces the
bundle bloat and demonstrates the fix.
- Cleaned up dead \`twenty-sdk/dist/sdk/...\` references in the
front-component story builder, the call-recording app, and the SDK
tsconfig.
## Bundle size impact
Measured with esbuild using the same options as the SDK CLI
(\`packages/twenty-apps/internal/bundle-investigation\`):
| Variant | Imports | Before | After |
| ----------------------- |
------------------------------------------------------- | ---------- |
--------- |
| \`01-bare\` | \`defineLogicFunction\` from \`twenty-sdk/define\` |
1177 KB | **1.6 KB** |
| \`02-with-sdk-client\` | + \`CoreApiClient\` from
\`twenty-client-sdk/core\` | 1177 KB | **1.9 KB** |
| \`03-fetch-issues\` | + GitHub GraphQL fetch + JWT signing + 2
mutations | 1181 KB | **5.8 KB** |
| \`05-via-define-subpath\` | same as \`01\`, via the public subpath |
1177 KB | **1.7 KB** |
That's a ~735× reduction on the bare baseline. Knock-on benefits for
Lambda warm + cold starts, S3 upload size, and \`/tmp\` disk usage in
warm containers.
## Test plan
- [x] \`npx nx run twenty-sdk:build\` succeeds
- [x] \`npx nx run twenty-sdk:typecheck\` passes
- [x] \`npx nx run twenty-sdk:test:unit\` passes (31 files / 257 tests)
- [x] \`npx nx run-many -t typecheck
--projects=twenty-front,twenty-server,twenty-front-component-renderer,twenty-sdk,twenty-shared,bundle-investigation\`
passes
- [x] \`node
packages/twenty-apps/internal/bundle-investigation/scripts/build-variants.mjs\`
produces the sizes above
- [ ] CI green
Made with [Cursor](https://cursor.com)
|
||
|
|
48c540eb6f |
Add event forwarding stories to the front component renderer (#19721)
Add Storybook stories and example components to test event forwarding through the front component renderer: form events (text input, checkbox, focus/blur, submit), keyboard events (key/code/modifiers), and host API calls (navigate, snackbar, progress, close panel) |
||
|
|
37908114fc |
[SDK] Extract twenty-front-component-renderer outside of twenty-sdk ( 2.8MB ) (#19021)
Followup https://github.com/twentyhq/twenty/pull/19010 ## Dependency diagram ``` ┌─────────────────────┐ │ twenty-front │ │ (React frontend) │ └─────────┬───────────┘ │ imports runtime: │ FrontComponentRenderer │ FrontComponentRendererWithSdkClient │ useFrontComponentExecutionContext ▼ ┌──────────────────────────────────┐ ┌─────────────────────────┐ │ twenty-front-component-renderer │────────▶│ twenty-sdk │ │ (remote-dom host + worker) │ │ (app developer SDK) │ │ │ │ │ │ imports from twenty-sdk: │ │ Public API: │ │ • types only: │ │ defineFrontComponent │ │ FrontComponentExecutionContext│ │ navigate, closeSide… │ │ NavigateFunction │ │ useFrontComponent… │ │ CloseSidePanelFunction │ │ Command components │ │ CommandConfirmation… │ │ conditional avail. │ │ OpenCommandConfirmation… │ │ │ │ EnqueueSnackbarFunction │ │ Internal only: │ │ etc. │ │ frontComponentHost… │ │ │ │ front-component-build │ │ owns locally: │ │ esbuild plugins │ │ • ALLOWED_HTML_ELEMENTS │ │ │ │ • EVENT_TO_REACT │ └────────────┬────────────┘ │ • HTML_TAG_TO_CUSTOM_ELEMENT… │ │ │ • SerializedEventData │ │ types │ • PropertySchema │ ▼ │ • frontComponentHostComm… │ ┌─────────────────────────┐ │ (local ref to globalThis) │ │ twenty-shared │ │ • setFrontComponentExecution… │ │ (common types/utils) │ │ (local impl, same keys) │ │ AppPath, SidePanelP… │ │ │ │ EnqueueSnackbarParams │ └──────────────────────────────────┘ │ isDefined, … │ │ └─────────────────────────┘ │ also depends on ▼ twenty-shared (types) @remote-dom/* (runtime) @quilted/threads (runtime) react (runtime) ``` **Key points:** - **`twenty-front`** depends on the renderer, **not** on `twenty-sdk` directly (for rendering) - **`twenty-front-component-renderer`** depends on `twenty-sdk` for **types only** (function signatures, `FrontComponentExecutionContext`). The runtime bridge (`frontComponentHostCommunicationApi`) is shared via `globalThis` keys, not module imports - **`twenty-sdk`** has no dependency on the renderer — clean one-way dependency - The renderer owns all remote-dom infrastructure (element schemas, event mappings, custom element tags) that was previously leaking through the SDK's public API - The SDK's `./build` entry point was removed entirely (unused) |