PHPackages                             flexible-ux/lexical-bundle - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. flexible-ux/lexical-bundle

ActiveSymfony-bundle

flexible-ux/lexical-bundle
==========================

A reusable Symfony form type providing a lightweight Lexical (Meta) rich-text editor, wired with AssetMapper, Stimulus and UX Icons.

v0.2.1(yesterday)018↑2566.7%MITPHP &gt;=8.2

Since Jul 19Compare

[ Source](https://github.com/Flexible-User-Experience/lexical-bundle)[ Packagist](https://packagist.org/packages/flexible-ux/lexical-bundle)[ Docs](https://github.com/Flexible-User-Experience/lexical-bundle)[ RSS](/packages/flexible-ux-lexical-bundle/feed)WikiDiscussions Synced today

READMEChangelogDependencies (9)Versions (3)Used By (0)

FlexibleUxLexicalBundle
=======================

[](#flexibleuxlexicalbundle)

A reusable Symfony bundle providing **`LexicalFormType`** — a lightweight rich-text editor form field built on Meta's [Lexical](https://lexical.dev), wired for [AssetMapper](https://symfony.com/doc/current/frontend/asset_mapper.html), [Stimulus](https://symfony.com/bundles/StimulusBundle) and [UX Icons](https://symfony.com/bundles/ux-icons).

The field renders a toolbar (bold, italic, underline, strikethrough, bulleted / numbered lists, link, unlink) and a contenteditable surface around a hidden ``. The editor reads the textarea's HTML on load and writes HTML back on every change, so it is a drop-in replacement for a plain textarea and **degrades to that textarea when JavaScript is disabled**. No build step is required — everything runs through AssetMapper's importmap.

Requirements
------------

[](#requirements)

- PHP 8.2+
- Symfony 7.4 or 8.x with AssetMapper, StimulusBundle and UX Icons

Installation
------------

[](#installation)

Make sure [Composer is installed](https://getcomposer.org/doc/00-intro.md) globally.

#### Step 1: Download the bundle

[](#step-1-download-the-bundle)

```
composer require flexible-ux/lexical-bundle
```

With **Symfony Flex**, `composer require` already wires the front-end for you: the Lexical packages are added to your `importmap.php` (from the bundle's `assets/package.json`) and the Stimulus controller is enabled in your `assets/controllers.json`. Skip to step 3.

#### Step 2 (without Flex): wire the front-end manually

[](#step-2-without-flex-wire-the-front-end-manually)

Add the Lexical packages to your importmap:

```
php bin/console importmap:require lexical @lexical/rich-text @lexical/html @lexical/list @lexical/link @lexical/history @lexical/utils
```

and enable the Stimulus controller in `assets/controllers.json`:

```
{
    "controllers": {
        "@flexible-ux/lexical-bundle": {
            "lexical": { "enabled": true, "fetch": "lazy" }
        }
    }
}
```

#### Step 3: Enable the bundle

[](#step-3-enable-the-bundle)

The bundle does not ship a Flex recipe yet, so register it in `config/bundles.php` (Flex and non-Flex alike):

```
// config/bundles.php
return [
    // ...
    FlexibleUx\FlexibleUxLexicalBundle::class => ['all' => true],
];
```

That's it. The bundle registers its AssetMapper path, the form theme and the toolbar icons automatically; the editor's CSS is imported by the controller, so there is nothing else to include.

Usage
-----

[](#usage)

```
use FlexibleUx\Form\Type\LexicalFormType;

$builder->add('description', LexicalFormType::class);
```

With options:

```
$builder->add('description', LexicalFormType::class, [
    'label'   => 'Description',
    'required' => false,
    'toolbar' => ['bold', 'italic', 'bullet', 'number', 'link', 'unlink'],
    'height'  => '320px',
]);
```

### Options

[](#options)

OptionTypeDefaultDescription`toolbar``string[]`all 12 buttons in four `|`-separated groupsOrdered toolbar entries: button names and `|` separators.`height``string``'200px'`Minimum editable height (any CSS length).`allowed_link_schemes``string[]``['http','https','mailto','tel']`URL schemes the link modal accepts.#### Toolbar and grouping

[](#toolbar-and-grouping)

Available buttons:

`bold` · `italic` · `underline` · `strikethrough` · `subscript` · `superscript` · `bullet` · `number` · `indent` · `outdent` · `link` · `unlink`

The toolbar renders **exactly the order you give**, and `|` draws a separator — so grouping is entirely yours to decide:

```
'toolbar' => ['bold', 'italic', '|', 'link', 'unlink'],   // two groups
'toolbar' => ['bold', 'italic', 'link'],                  // no separators at all
```

Leading, trailing and repeated separators are dropped, so a list can never render a stray or doubled divider. An unknown button name raises a clear `InvalidOptionsException` listing the valid ones.

The field extends `TextareaType`, so all textarea/text field options (`label`, `required`, `attr`, `constraints`, …) apply too.

#### Link schemes

[](#link-schemes)

Restrict (or widen) which link schemes the editor may produce — entries may be written with or without the trailing colon, and anything outside the list is rejected in the link modal:

```
$builder->add('description', LexicalFormType::class, [
    'allowed_link_schemes' => ['https'], // https-only links
]);
```

### Application-wide defaults

[](#application-wide-defaults)

Rather than repeating options at every call site, set defaults once. Every key mirrors a form option, and per-field options still win:

```
# config/packages/flexible_ux_lexical.yaml
flexible_ux_lexical:
    toolbar: ['bold', 'italic', '|', 'bullet', 'number', '|', 'link', 'unlink']
    height: '320px'
    allowed_link_schemes: ['https']
```

Run `php bin/console config:dump-reference flexible_ux_lexical` to see the full reference.

The editor stores **HTML**. When you render that HTML on a public page, output it as trusted markup (e.g. Twig's `|raw`) — links are restricted to `allowed_link_schemes` by the editor, but you remain responsible for sanitising any HTML that reaches the field from other sources.

How it works
------------

[](#how-it-works)

The bundle is deliberately split into four layers so each can be understood and overridden on its own:

- **PHP** — `FlexibleUx\Form\Type\LexicalFormType` exposes the `toolbar` / `height` options as view variables.
- **HTML** — the `lexical_widget` Twig form theme renders the toolbar, the editable surface and the link modal.
- **JS** — the `lexical` Stimulus controller mounts Lexical on the editable element and keeps the textarea in sync.
- **CSS** — `assets/styles/lexical.css` (imported by the controller).

See [`docs/index.md`](docs/index.md) for customisation, theming and translation details.

License
-------

[](#license)

Released under the [MIT License](LICENSE). Bundled icons are from [Lucide](https://lucide.dev) (ISC License).

###  Health Score

39

—

LowBetter than 84% of packages

Maintenance100

Actively maintained with recent releases

Popularity9

Limited adoption so far

Community2

Small or concentrated contributor base

Maturity37

Early-stage or recently created project

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

1d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/4e96d5cf1c3fe5912ca44c4de5b39a34a40b94bd9c23c3993e8b7c19737e68c3?d=identicon)[davidromani](/maintainers/davidromani)

---

Tags

symfonysymfony-uxeditorformwysiwygSymfony Bundleasset-mapperrich textlexicalstimulus

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/flexible-ux-lexical-bundle/health.svg)

```
[![Health](https://phpackages.com/badges/flexible-ux-lexical-bundle/health.svg)](https://phpackages.com/packages/flexible-ux-lexical-bundle)
```

###  Alternatives

[easycorp/easyadmin-bundle

Admin generator for Symfony applications

4.3k17.9M399](/packages/easycorp-easyadmin-bundle)[sylius/sylius

E-Commerce platform for PHP, based on Symfony framework.

8.5k5.9M753](/packages/sylius-sylius)[2lenet/crudit-bundle

The easy like Crud'it Bundle.

1616.4k14](/packages/2lenet-crudit-bundle)[symfony/symfony-demo

Symfony Demo Application

2.6k254.2k](/packages/symfony-symfony-demo)[prestashop/prestashop

PrestaShop is an Open Source e-commerce platform, committed to providing the best shopping cart experience for both merchants and customers.

9.1k18.1k](/packages/prestashop-prestashop)[ehyiah/ux-quill

Symfony UX Bundle to use Quill JS wysiwyg text editor with full and easy customisation

6492.2k3](/packages/ehyiah-ux-quill)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
