Lexical React - Headings, Lists, Toolbar

Lexical
19 Mar 202328:45

Summary

TLDRこの動画のスクリプトでは、React製のリッチテキストエディターツールキットであるLexicalを使って、ヘディングやリストを追加するツールバーの作り方を解説しています。最初にヘディングプラグインを作成し、選択したテキストをヘディングに変換する方法を示しています。次に、さまざまなヘディングレベルをサポートするよう機能を拡張します。さらに、リストプラグインを追加し、順序付きリストや順序なしリストを作成する方法を説明しています。このチュートリアルを通して、Lexicalを使ったリッチテキストエディターのカスタマイズ方法を実践的に学ぶことができます。

Takeaways

  • 🚀 この動画では、React の lexical エディターでツールバーを構築する方法を学びます。
  • 📝 前回の動画では、ヘッディングノードを挿入するだけでしたが、今回はテキストの選択とヘッディングへの変換、リストの追加など、より実践的な機能を追加しています。
  • 🔧 setBlocksType ヘルパーを使用して、選択したテキストをヘッディングに変換することができます。
  • ⌨️ ツールバーにボタンを追加し、タグに基づいてヘッディングの種類 (h1、h2、h3) を切り替えることができます。
  • 📖 スタイルシートを使ってヘッディングの見た目をカスタマイズできます。
  • ✅ lexical-list パッケージをインストールして、ordered list と unordered list のコマンドをツールバーに追加できます。
  • 🧩 プラグインを作成してツールバーの機能を構築し、ヘッディングとリストのプラグインを合成することができます。
  • 🔄 インストール時に node_modules の問題が発生した場合は、キャッシュをクリアしてパッケージを再インストールする必要があります。
  • 🧭 lexical のプレイグラウンドでさまざまなツールバーの実装例を確認できます。
  • 🏗 ツールバーの構築方法は多様で、開発者ごとにカスタマイズできるため、自分なりのソリューションを模索することが推奨されています。

Q & A

  • 1. Lexical Reactとは何ですか?

    -Lexical Reactは、Facebookが開発したリッチテキストエディタの構築を支援するライブラリです。ReactベースのコンポーネントとAPIを提供し、高度にカスタマイズ可能なテキストエディタの作成を可能にします。

  • 2. 前回の動画では何を行いましたか?

    -前回の動画では、基本的なボタンを作成し、そのボタンをクリックするとヘッディングノードが挿入されるようにしました。これは、ツールバーとエディターとのUIの対話の基礎となるものでした。

  • 3. 今回のゴールは何ですか?

    -今回の目標は、ツールバーをさらに拡張し、ヘッディングの使用をより実用的なものにすること、そしてリストのサポートを追加することです。つまり、UIとの対話をより深く行うことが目的です。

  • 4. セレクトされたテキストをヘッディングに変換するにはどうすればよいですか?

    -setBlocksTypeヘルパー関数を使用します。これにより、選択範囲とノード作成関数を渡すことで、その選択範囲をヘッディングノードで囲むことができます。

  • 5. 様々なヘッディングレベル(H1、H2、H3など)をどのように実装しますか?

    -各ヘッディングレベルに対応するボタンを作成し、そのボタンをクリックしたときに適切なヘッディングノードを作成するようにします。ボタンには独自のスタイルを適用することもできます。

  • 6. リストのサポートを追加するにはどうすればよいですか?

    -lexical-reactパッケージから提供されているlistPluginを使用します。このプラグインにより、ordered listやunordered listを挿入したり削除したりするコマンドが利用可能になります。

  • 7. リストノードをエディターに登録する必要があるのはなぜですか?

    -現在のLexicalの制約上、リストノードをエディターに明示的に登録する必要があります。プラグイン自体でノードを登録することはできないためです。この点は将来的に改善される可能性があります。

  • 8. ツールバーの構造をどのように構築しますか?

    -ツールバーの構造は、Reactコンポーネントを構成することで作成できます。ツールバー全体をひとつのプラグインとしてラップし、その中で個々のボタンを別のコンポーネントとして作成するのが一般的なアプローチです。

  • 9. Lexicalでツールバーを実装する方法は決まっていますか?

    -いいえ、ツールバーの実装方法は決まっていません。Lexicalはフレキシブルなので、Reactコンポーネントの構成方法は自由に選択できます。プレイグラウンドなどのサンプルを参考にしつつ、自分なりの実装方法を探ることが推奨されています。

  • 10. 動画の最後に言及されている「より興味深い使用例」とは何を指していますか?

    -動画の最後では、今後の動画でより高度でエキサイティングな機能の実装を行うことを示唆しています。たとえば、リッチテキストフォーマッティングの追加や、カスタムノードの作成などが考えられます。

Outlines

00:00

🔩 ヘッダープラグインの拡張

この段落では、前回のビデオで作成した基本的な見出しボタンをさらに拡張し、テキスト選択に応じて見出しを作成できるように変更しています。さらに、H1、H2、H3の見出しタイプに対応するボタンを作成し、スタイルを適用しています。

05:00

🛠️ ツールバーの作成

この段落では、見出しボタンをツールバーに統合するために、新しいツールバーコンポーネントを作成しています。見出しの各レベルに対応するボタンを作成し、それぞれにスタイルを適用しています。また、H1にはアンダーラインを、H2には太字を、H3には通常のスタイルを適用しています。

10:02

📝 リストサポートの追加

この段落では、リストのサポートを追加するために、lexical-listパッケージをインストールしています。次に、順序付きリストと順序なしリストに対応するボタンを作成し、リストプラグインをインポートしてエディタに登録しています。

15:02

✨ リストコマンドの実装

この段落では、リストコマンドの実装について説明しています。リストコマンドを呼び出すためのクリックハンドラを作成し、EditorオブジェクトのdispatchCommandメソッドを使用してリストコマンドを発行しています。また、リストノードをエディタに登録する必要があることを説明しています。

20:03

🐞 バグの修正とデモ

この段落では、リストコマンドが正しく機能しない問題を解決するために、node_modulesをクリーンインストールしています。その後、ヘッディングとリストの機能を実際に使用してデモを行い、ツールバープラグインの拡張方法について言及しています。

25:03

🎬 まとめ

この最終段落では、Lexicalでのツールバーの作成方法について総括しています。プラグインの構成を説明し、さまざまな方法でツールバーを実装できることを示唆しています。最後に、今後の動画でより興味深い使用例を取り上げることを示唆しています。

Mindmap

Keywords

💡lexical

Lexicalはリッチテキストエディタを構築するためのJavaScriptライブラリです。この動画では、React向けのlexicalライブラリの使い方を学びます。lexicalを使うことで、簡単にカスタマイズ可能なコンテンツ編集機能を備えたWebアプリケーションを構築できます。

💡プラグイン

プラグインとは、lexicalエディターの機能を拡張するための小さなモジュールのことです。この動画では、ヘッディングプラグインやリストプラグインなど、様々なプラグインの作り方と利用方法が説明されています。プラグインを使うことで、必要な機能のみを自由に組み合わせ、カスタマイズできます。

💡ツールバー

ツールバーとは、エディターの上部や側面に配置されるUIコンポーネントで、様々な編集機能へのアクセスを提供します。この動画では、ヘッディングやリストの変更を行うボタンを持つシンプルなツールバーの作成方法が示されています。ユーザーはこのツールバーからエディター内のコンテンツに対して操作を行えます。

💡コマンド

lexicalにおけるコマンドとは、エディター内のコンテンツに対して実行される操作のことです。この動画では、insertUnorderedListコマンドやinsertOrderedListコマンドなど、リストに関連したコマンドが説明されています。プラグインはコマンドをディスパッチして、エディターの状態を更新します。

💡ノード

lexicalのノードとは、エディター内のコンテンツを表す構造化データの単位を指します。ヘッディングノードやリストノードなど、様々なタイプのノードが存在します。この動画では、ヘッディングノードの作成やリストノードの登録方法が説明されています。ノードを適切に操作することで、エディターのコンテンツを制御できます。

💡コンポーザブル

コンポーザブルとは、複数のプラグインやコンポーネントを組み合わせて一つの機能を構築できることを指します。この動画の最後で、lexicalのプラグインはコンポーザブルであり、Reactコンポーネントと同様に自由に組み合わせられると説明されています。この柔軟性が、lexicalの大きな利点の一つです。

💡セレクション

セレクションとは、エディター内で選択されたテキストやノードの範囲を指します。この動画では、getRangeSelectionメソッドを使ってセレクションを取得し、setBlocksTypeメソッドでセレクションをヘッディングに変換する方法が説明されています。セレクションを適切に扱うことは、エディターのユーザー体験を向上させる上で重要です。

💡スタイリング

スタイリングとは、エディター内のノードやコンポーネントの外観をCSSで制御することを指します。この動画では、ヘッディングノードにフォントサイズやスタイルを適用する方法が示されています。適切なスタイリングを行うことで、エディターの見た目をカスタマイズでき、ブランディングにも役立ちます。

💡コンポーネント

コンポーネントとは、Reactアプリケーションを構成する再利用可能な UIの構成単位のことです。この動画では、ボタンコンポーネントをレンダリングしてツールバーを作成する例が示されています。lexicalはReactベースなので、コンポーネントを自由に作成・組み合わせることができます。

💡アップデート

アップデートとは、lexicalエディターの状態を変更することを指します。この動画では、コマンドをディスパッチする際にアップデートが自動的に行われると説明されています。明示的にeditor.updateを呼び出す必要がある場合もあります。アップデート処理を適切に行うことで、エディターの状態が常に最新に保たれます。

Highlights

The tutorial covers building an editor in Lexical React, expanding on the previous video where a basic button was created to insert a heading node.

The objective is to make the toolbar more versatile by allowing users to select text and convert it into different heading levels (H1, H2, H3), as well as add support for ordered and unordered lists.

The setBlocksType helper from Lexical is introduced, which allows wrapping a selected range in a specified block type by providing a creator function.

The tutorial walks through checking if the selection is a range selection, as setBlocksType only works with range selections.

The tutorial demonstrates creating multiple buttons for H1, H2, and H3 headings by mapping over an array of tags and rendering buttons with respective click handlers.

Styling is applied to the different heading levels using CSS to illustrate how custom styles can be added.

The tutorial introduces adding support for ordered and unordered lists by installing the @lexical/list package and registering the necessary list nodes.

A separate toolbar plugin is created for the list functionality, which dispatches the appropriate commands (insertOrderedList or insertUnorderedList) based on the button clicked.

The tutorial explains the importance of registering list nodes on the editor's initial configuration due to constraints in the current implementation.

The tutorial highlights the flexibility of Lexical React in building toolbars by composing plugins and components, encouraging exploration and finding custom solutions.

The setBlocksType helper allows wrapping a selected range in a specified block type by providing a creator function.

Styling is applied to the different heading levels using CSS to illustrate how custom styles can be added.

A separate toolbar plugin is created for the list functionality, which dispatches the appropriate commands (insertOrderedList or insertUnorderedList) based on the button clicked.

The tutorial explains the importance of registering list nodes on the editor's initial configuration due to constraints in the current implementation.

The tutorial highlights the flexibility of Lexical React in building toolbars by composing plugins and components, encouraging exploration and finding custom solutions.

Transcripts

play00:00

hey everyone it's AC from the lexical

play00:02

team uh today we're going to continue on

play00:04

our tutorial for how to build an editor

play00:05

in lexical react

play00:07

um last time we left off with just kind

play00:09

of a basic uh button that inserts a

play00:13

heading node

play00:14

um so it's kind of the beginnings of a

play00:16

toolbar and a little bit of like how to

play00:17

interact with the editor through the UI

play00:20

So today we're going to expand the

play00:21

toolbar a little more and try to like

play00:24

work a little more with like a more I

play00:27

guess interesting or like practical

play00:28

application of something like headings

play00:31

and then also maybe add support for

play00:33

lists

play00:34

um and and doing so kind of expand our

play00:36

toolbar a bit and and work a little bit

play00:39

with more with the UI so um let's Dive

play00:42

In

play00:44

so like I said last time we did set up

play00:47

this uh heading plugin which does

play00:49

something really it basically is

play00:50

connected to this button

play00:52

so we render a button here when we click

play00:54

it we get the root element of the

play00:56

lexical editor and we append um we

play00:58

create a text node a pin that and create

play01:01

a heading node a pin that to pin the

play01:02

text onto the heading node and then

play01:04

append the heading into the root so

play01:05

that's a bit of a mouthful but that's

play01:06

you know more or less we're just kind of

play01:09

like creating a heading node so you

play01:10

can't like

play01:11

choose the text it's hard coded you

play01:14

select the editor you click heading and

play01:15

inserts hello world all right so that's

play01:18

that's pretty much it and so what would

play01:20

be like a more typical I suppose is um

play01:24

for you to like highlight some text or

play01:25

select some text and then be able to

play01:28

convert that into a heading right or

play01:30

convert that into uh change the block

play01:32

type of it so to speak right

play01:35

um and so uh let's try to do that first

play01:38

right let's try to see if we can make it

play01:39

so we can just instead of hard inserting

play01:42

a hard-coded hello world heading we can

play01:44

just select arbitrary text and convert

play01:46

it into uh to a heading so that's step

play01:48

one

play01:49

um so

play01:51

first of all let's get rid of this my

play01:54

that's annoying me for some reason it's

play01:56

just having plug-in for us

play01:59

um so

play02:00

what we can do first so let's go

play02:03

explodes is a helper called set blocks

play02:05

type

play02:07

um and that basically is going to allow

play02:09

you to pass in a selection and a Creator

play02:13

function and it's going to try to wrap

play02:15

your selection in whatever block type is

play02:17

created by the function you provide and

play02:19

I'll show you how that works in a sec

play02:21

um so first let's get rid of this piece

play02:23

we don't need this anymore instead of

play02:25

getting the root we'll need to get this

play02:28

selection

play02:29

so the way you do that in lexical is

play02:31

just with something similar to get root

play02:33

it's called get selection

play02:35

second thing you want to do is check if

play02:37

it's a range selection there are three

play02:40

types of selection in lexical right now

play02:42

um grid selection

play02:44

range selection and node selection and

play02:47

for purposes of this we're just going to

play02:49

want to deal with range selection that's

play02:50

when you're selecting like a range of

play02:52

nodes usually some text is involved and

play02:55

it's kind of the most common one and you

play02:58

usually have to special case the other

play02:59

ones so we'll we'll just deal with the

play03:01

range selection for now and if you want

play03:03

to layer in node selection and grid

play03:05

selection in your own editor that's

play03:06

something that may be the subject of

play03:07

future videos

play03:09

so um check if it's a range selection

play03:11

and by the way set blocks type only

play03:13

works with range selection or maybe grid

play03:15

selection so we have to do this check

play03:17

anyway

play03:18

um so set block stop experimental comes

play03:21

from lexical selection

play03:24

um I

play03:25

didn't think I had that installed but I

play03:33

interesting

play03:34

it must be cash from earlier

play03:37

um but anyway so yeah we have set block

play03:39

types experiments so we're probably

play03:40

going to want to like

play03:42

actually go and make sure we have this

play03:47

so obviously PM install

play03:50

that

play03:52

you'd have to do this typically to get

play03:54

access to this utility

play03:56

um

play03:58

I was playing around earlier and I think

play03:59

I

play04:00

installed it and didn't clear out the

play04:03

module cache

play04:05

so that's probably why I'm able to

play04:06

import it here

play04:09

um

play04:10

and what's actually happening is that

play04:13

probably installed

play04:16

I actually don't want it to be a

play04:19

hard dependency let's make it a Dev

play04:22

dependency

play04:25

um

play04:28

and then we need to all these versions

play04:30

to match so I'm just going to downgrade

play04:31

it to eight zero

play04:33

like the rest of my electrical packages

play04:35

for now

play04:36

and then we'll just run that one more

play04:38

time to make sure we have the right

play04:39

version

play04:42

uh what did I do

play04:44

oh trailing comma

play04:46

okay let's get rid of that

play04:51

cool so that should work fine and then

play04:54

we have it's still called in actually

play04:56

0.9 is called set blocks type and we

play04:58

dropped the experimental tag so this is

play05:00

a stable API but on 0.8 which is the

play05:03

version I'm using in this series so far

play05:06

um it's just called set block type

play05:07

experimental so that's why we have to do

play05:09

that for now

play05:11

um so we won't need these anymore

play05:16

and we'll still need to create heading

play05:17

notes what we're going to do with this

play05:18

is the API here it takes you can see two

play05:21

parameters selection element Creator as

play05:23

I mentioned before so we can pass as

play05:24

parameter one the selection which we got

play05:27

from git selection and then we'll pass

play05:29

the Creator function

play05:30

which to mirror the functionality we

play05:32

have now we just do create heading node

play05:34

and we would say it's an H1

play05:40

cool and so why are we complaining

play05:42

indentation okay

play05:46

better

play05:49

what have I done

play05:54

okay cool

play05:57

um really need to work on my editor

play05:58

environment this is like not

play06:01

having to fix indentation manually is

play06:03

not ideal anyway so um now what we

play06:06

should expect to see let's refresh this

play06:07

to make sure we got all the changes um

play06:09

we're just going to see like this when

play06:12

you click heading should be converted

play06:14

into

play06:14

and so that's kind of similar behaviors

play06:17

before so let's change the text so my

play06:19

name is AC

play06:21

oops and then

play06:24

Okay cool so that works so now instead

play06:26

of like just inserting hard-coded text

play06:27

we're just converting whatever is we

play06:30

select into a heading so that's a good

play06:32

step in the right direction

play06:33

so if we're going to expand this out a

play06:35

little more

play06:36

um we'd probably want to support like

play06:38

different heading types and this kind of

play06:40

like leads us into how you could like

play06:42

maybe start building a toolbar right so

play06:45

right now we just have a single button

play06:46

called heading

play06:47

but like there are different types of

play06:48

headings right so we could call this

play06:50

instead like

play06:51

H1 we could say well like that's now

play06:55

gonna just insert an H1 and that would

play06:57

imply that we'll add h2h3h4 whatever

play07:00

right so let's add support for

play07:01

um through H3 let's say

play07:05

um so you can see here that we're

play07:06

passing in the tag we want to create to

play07:08

create heading node

play07:09

so we just need like maybe for now a

play07:11

couple more we could do a drop down or

play07:13

something theoretically just to keep it

play07:14

simple let's add a couple more buttons

play07:15

We'll add H1 H2 and H3 and we'll kind of

play07:18

continue to expand our toolbar here so

play07:21

um one way we can do that is probably by

play07:23

just saying like

play07:24

let's add a wrapper around this

play07:27

and then

play07:30

let's have a

play07:33

um

play07:40

keeping it simple for now hardcoding

play07:42

some things

play07:43

we're just going to map these uh tags

play07:48

to buttons

play07:52

whoops did I like drop that button for

play07:54

my clipboard somehow

play07:57

I did great

play08:00

um

play08:01

so it's okay not hard to rewrite

play08:06

um

play08:08

so we have our click Handler

play08:10

and then uh we had we need a key

play08:14

actually

play08:16

since we're

play08:18

using map and then we'll have in here

play08:22

tag Dot

play08:24

two uppercase just like that for now

play08:29

um and so then let's see we're not

play08:32

really returning this are we let's do

play08:34

this instead to make it return the

play08:36

actual react element

play08:39

um

play08:40

and then we should be good yeah so we

play08:41

have H1 h2h3 there but that's not really

play08:43

doing it it's all going to insert it's

play08:45

all going to call the same click Handler

play08:46

right now right so it's all gonna um

play08:49

to insert an H1 so we need to kind of

play08:52

adapt that click Handler a bit so what

play08:54

we can do here instead is maybe say like

play08:56

um

play08:58

we have a tag

play09:00

which is

play09:01

um

play09:08

something like this that

play09:12

and then we'll pass the tag in here

play09:16

and then we'll have to change this

play09:18

because this will just typically take

play09:21

the event

play09:23

instead of doing that

play09:26

we'll call it on click

play09:29

and we'll pass in the tech

play09:33

cool

play09:35

um

play09:37

that should work

play09:40

fine unless I'm missing something

play09:42

so H1 gives us that H2 H3 and this is

play09:47

just like user agent Styles right so we

play09:49

have additional styling applied to H1

play09:51

from the last video

play09:52

where we added we're just kind of

play09:55

playing around with classes so we added

play09:56

a weird background color to H1

play09:59

um so we could do

play10:01

um you know we could have

play10:04

instead of relying on user agent Styles

play10:06

we can add our own here right we can say

play10:09

uh glyph editor H2 and probably

play10:15

H3 would be glyph

play10:19

editor H3

play10:21

and then

play10:23

make sure we have a comma

play10:25

go to the styles

play10:31

so this will be H2 this would be h

play10:36

three

play10:39

um let's go to something like let's say

play10:41

we'll set we can control the font sizes

play10:43

right

play10:44

so maybe this font size is going to be

play10:46

like

play10:46

um I don't know

play10:49

let's say

play10:51

48 pixels would be hard

play10:54

and you might want to use like

play10:56

em or something in real life so don't

play10:58

don't take this as like

play11:01

best practices this is just me

play11:04

giving a few examples

play11:06

um so

play11:08

uh now we have that maybe let's say just

play11:11

to make it interesting let's say like we

play11:13

want to

play11:15

at an underline to our H1s

play11:19

and our H2S would be like what's

play11:23

something we could do to this like maybe

play11:24

these are

play11:26

uh italic

play11:29

which

play11:30

um

play11:31

it's escaping me how you do that now uh

play11:36

hmm why am I forgetting how to add

play11:39

italic

play11:41

uh

play11:42

styles to text anyway

play11:44

um so let's say like maybe instead of

play11:46

that

play11:47

um we'll do font weight

play11:54

people

play11:57

um and maybe we want that here too so

play11:59

this will be bold and underlined

play12:01

this will be just bold and this will be

play12:03

just like a

play12:05

regular regular text so now H1 becomes

play12:09

underlined

play12:10

H2 becomes just bold

play12:13

H3 becomes

play12:16

so wait a second

play12:19

hmm

play12:23

so let's go H1 H2 H3 so that that's like

play12:28

can't really tell that it's applying rh2

play12:30

Styles so we can add a color of like

play12:33

[Music]

play12:33

um

play12:34

let's go green

play12:38

so

play12:42

we should see that update

play12:45

unless I missed something somewhere

play12:47

of course but that's not the problem

play12:51

um so

play13:02

why is there two not

play13:05

with editor H2 oh

play13:08

you're not allowed to just say green I

play13:10

suppose

play13:13

right no quotes

play13:16

not bad

play13:19

there we go much better

play13:21

now we have green green H2S and uh

play13:25

regular size regular colored h3s

play13:27

underlines on our H1s

play13:29

so yeah you can kind of add whatever

play13:30

Styles you want to your headings you can

play13:32

make them do whatever you want that's

play13:33

just kind of a just a quick example

play13:36

um so let's talk about how we could do

play13:38

something like let me fix this type

play13:40

script error first so I probably wanted

play13:41

to do something like

play13:45

uh

play13:47

uh

play13:56

so

play14:01

heading tag and then I would just do

play14:03

like

play14:10

um

play14:13

probably

play14:21

could even make this configurable right

play14:24

um

play14:25

through a prop but I'll say constant

play14:27

heading tags

play14:30

this type

play14:32

whoops

play14:37

hang tag array

play14:41

cool so that'll make task group quiet

play14:44

um

play14:46

right so now we have these buttons so

play14:48

now let's try to see if we can add lists

play14:51

really quick and so we'll just expand

play14:52

our toolbar out and add a couple more

play14:54

buttons

play14:55

um owner to listen order list

play14:57

um

play14:58

conversion I guess that'll be a little

play15:00

bit different we can't use set block

play15:02

types for that because lists are a

play15:03

little more complicated that's why we

play15:04

have the list the list package

play15:06

and plug in for that

play15:09

um and so the first thing we'll need to

play15:11

do there is ADD

play15:14

um add that package so we can just

play15:17

improve install

play15:20

um I think that's how you do that oh

play15:22

it's just dead now right and then

play15:24

um at let's go

play15:27

slash list and this is just going to

play15:28

give us access to some of the thing like

play15:30

the nodes and things that we need in

play15:33

order to actually use a list plugin so

play15:35

we expose the list plugin from lexical

play15:39

react but you still need to register the

play15:41

nodes and things like that to support it

play15:43

um

play15:44

and so we'll need to

play15:47

um and you have to access the commands

play15:49

and things all that against is Alex list

play15:51

package

play15:52

and so once we have that

play15:54

um we will need to oh we will need to

play15:58

make sure we have the same

play16:01

why I thought I said Dev

play16:04

okay

play16:06

so let's go here

play16:11

and let's go to eight

play16:16

and then

play16:21

just run and install and then I'm gonna

play16:24

restart this Dev server because

play16:29

just to make sure we get all the

play16:31

new node modules picked up

play16:34

cool

play16:35

um so that looks

play16:37

right now that we have a list so we can

play16:39

add we now we can try adding

play16:42

list plugin here

play16:46

and that comes from the lexical react

play16:48

package as you can see uh and so let's

play16:51

look at what that does for a sec

play16:54

so if we go to list plugin

play16:57

Maybe

play17:00

here we go we can look at the so we

play17:01

actually ship like Source Maps or source

play17:04

files with the npm package so you can

play17:08

actually see

play17:10

in development in the node modules like

play17:12

what's going on but uh here you can see

play17:15

this is the list plugin right

play17:16

so there's subtracting over a lot of

play17:18

things but like the public API here is

play17:20

we're just

play17:21

um we're calling use list in here

play17:25

um and so

play17:26

that is just registering a bunch of

play17:29

commands effectively so what that does

play17:31

is it makes it so you can dispatch these

play17:33

commands in the editor and it'll do

play17:35

certain things like insert a number list

play17:37

insert a bullet list you know remove a

play17:39

list whatever right so all you have to

play17:42

do is dispatch those commands and that's

play17:43

sort of the what the plugin provides out

play17:45

of the box

play17:46

so um

play17:48

if we go here

play17:50

uh let's see how do we want to do this

play17:52

we're going to need a button to like

play17:53

dispatch the commands right we have our

play17:55

heading plugin we don't want to add

play17:57

lists to that right because then it

play17:59

wouldn't be having plug-in anymore so

play18:01

I'm thinking what we do is we add

play18:03

a toolbar plugin

play18:06

and then from here we would say like we

play18:09

probably still want to have the editor

play18:13

um and then we would want to return so

play18:16

you can kind of compose plugins which I

play18:18

think is

play18:20

kind of cool but let's just do maybe

play18:23

let's make this a div so we can style it

play18:26

because I got a few of them we're gonna

play18:28

need to

play18:30

and then

play18:31

um we can return heading plugin here

play18:35

and then maybe

play18:38

um we'll make a list

play18:44

toolbar plugin

play18:47

let's rename this so it's consistent

play18:53

so now we have heading toolbar plugin

play18:59

you could probably rename this

play19:02

later but so we won't need this in here

play19:04

anymore we just need toolbar plugin

play19:06

and then we can have list toolbar plugin

play19:11

probably just copy this

play19:16

so let's make this list toolbar plugin

play19:20

and so

play19:22

um

play19:23

we're gonna need the click Handler still

play19:27

um

play19:29

actually we could still use tags right

play19:31

because

play19:35

uh list

play19:37

still

play19:38

the list uh

play19:41

still uh plugins sorry

play19:44

the list yeah list plugins still

play19:45

distinguish between those two right you

play19:47

can have or UL so we can kind of use

play19:48

tags to distinguish between those two

play19:51

um we'll need to do something different

play19:52

in here right we can't use set blocks

play19:54

type we don't really care about

play19:56

selection

play19:58

we don't even need to care about

play19:59

editor.update because when you dispatch

play20:01

a command it's implicitly wrapped in an

play20:03

update

play20:04

um and if there's not already one

play20:05

ongoing so we can uh kind of we don't

play20:07

even have to worry about that really and

play20:10

we can say I was hoping that we could

play20:13

we'll come back to this

play20:15

um piece for now let's not do that

play20:20

um I think we might export the tag types

play20:23

from the list package

play20:26

um let me see list tag type no

play20:31

um for now let's go uh just oh well

play20:35

UL like that and we'll fix it later so

play20:39

um we'll get to the interesting part

play20:41

so if uh tag

play20:45

triple equals ol

play20:48

then we want to do editor dot dispatch

play20:50

commands insert order list

play20:54

and you do have to like add the second

play20:55

argument even if you um

play20:58

even if you don't uh plan to

play21:01

even if it isn't it's just undefined

play21:03

which it is in this case right with this

play21:05

touch dispatch command with the install

play21:06

order list command um the payload type

play21:09

is void

play21:10

um but you have to add it anyway we

play21:12

should probably do something about that

play21:14

but

play21:15

not right now so return

play21:18

and then um if you if it's not then we

play21:22

would do dispatch command we would do

play21:25

insert unorderless command

play21:30

like that so that becomes our click and

play21:33

then we just have

play21:35

list tags.map

play21:38

and then

play21:40

um

play21:41

I guess we don't need

play21:43

that

play21:45

this returns a jsx element

play21:51

um

play21:53

and I'm missing something

play21:57

um

play22:00

list tags oh we have to do the same

play22:03

thing we did before

play22:04

so that's fine let's do type

play22:08

list tag

play22:14

s below

play22:18

or UL

play22:22

and this would be a list tag array

play22:27

and this would be a list tag right

play22:32

um

play22:33

oh sorry not an array just a list tag

play22:40

um and that should

play22:42

work for some reason we still see

play22:43

console areas where we have

play22:45

list plugin list node and or List item

play22:48

node not registered on editor okay good

play22:50

point so we need to register those on

play22:53

the editor because we're using them in

play22:55

list plugin it's not super obvious that

play22:57

you have to do that that's why we have

play22:59

this console error in here ideally

play23:01

there'd be a way for the plugin to

play23:02

register the node itself but there are

play23:04

some constraints we have right now that

play23:06

we haven't been able to work through yet

play23:07

that don't allow you to register the

play23:09

node on the plugin itself you have to do

play23:11

it when you create the editor in the

play23:12

initial config and so that kind of is a

play23:15

little bit weird it mixes some concerns

play23:17

um once again would love to fix that but

play23:19

for now you need to

play23:21

import these and register them on the

play23:23

editor so you have a list noted on this

play23:24

side of the node right

play23:26

and then that should fix our errors I

play23:29

think

play23:31

um but we have a weird thing here where

play23:33

our styling's messed up

play23:34

so let's see if we can sort that out

play23:36

real quick

play23:38

um

play23:39

let's go with this probably just needs

play23:44

to be

play23:46

a fragment

play23:49

for now and then this can have a class

play23:53

name

play23:54

of a toolbar

play23:58

wrapper

play24:00

cannot type this morning

play24:03

toolbar wrapper and then

play24:05

um

play24:06

from there you can do

play24:10

um

play24:17

two of our wrapper and then you can have

play24:19

[Music]

play24:19

um

play24:22

just display Flex

play24:25

cool and so that fixes us up now there

play24:27

so now we just have like a toolbar with

play24:29

display Flex that's kind of

play24:30

accommodating the width of all of the

play24:32

child elements

play24:33

um so that's pretty straightforward

play24:35

there so now what we would expect is

play24:37

that when we

play24:38

um you know now that we have these

play24:40

commands wired up we can change print

play24:42

all these different formats right so I

play24:43

would say hello we have H1 h2h3 working

play24:46

ol

play24:47

UL

play24:48

still not quite working

play24:51

um

play24:52

I think I might know why that is

play24:56

sometimes when you install these

play24:59

packages

play25:01

so like we basically rely on object

play25:03

references for the command creation

play25:06

I'd like to like detect commands so like

play25:08

you're not you're not like

play25:09

um matching a string when we decide

play25:11

which command listeners to trigger

play25:13

you're actually matching an object

play25:14

reference so it's like a shared object

play25:15

reference across these modules and that

play25:18

can actually be a little bit weird

play25:20

um sometimes when you're installing

play25:22

packages because you can end up having

play25:23

different object references for the

play25:26

command identity and so like this insert

play25:28

ordered list command is actually an

play25:30

object and so when we decide you know

play25:32

when we dispatch this command and let's

play25:33

go is like okay we need to trigger you

play25:35

know any command list associated with

play25:37

this command it's looking for this exact

play25:40

object reference in the command listener

play25:43

map that we have and so if it's two

play25:44

different references obviously they

play25:45

won't match and you won't run any

play25:47

listeners and so I suspect that's what's

play25:49

happening here because I've done some

play25:50

weird things with my um

play25:52

with my node modules

play25:56

um and it's like installing different

play25:57

versions and things so I'm going to just

play25:59

get rid of that

play26:02

um let's get rid of package lock as well

play26:07

and let's just do a fresh install

play26:17

Okay cool so we have that package

play26:18

installed now

play26:20

so let's

play26:24

start the dev server back up

play26:34

so on a fresh install this should work

play26:42

okay so we're good now so we're able to

play26:45

convert between these different types at

play26:47

this point and so you should also be

play26:50

able to like if we have separate

play26:52

paragraphs

play26:53

making both headings convert them both

play26:56

to list right so all this should work

play26:58

just out of the box and it does work

play27:00

pretty well so um that's pretty much it

play27:04

there I'm not sure why am I still seeing

play27:06

type errors probably because

play27:10

the ID hasn't caught up with the with

play27:12

the reinstall

play27:14

um

play27:16

so let me try reopening this file

play27:20

still nothing

play27:28

she's a bit weird

play27:31

so I might have to restart vs code to

play27:33

get that to work probably but anyway

play27:35

that's in a nutshell like how you would

play27:36

set these things up

play27:38

um in lexical and um

play27:41

you know you have like your headings

play27:42

list you have kind of the beginnings of

play27:45

a toolbar here and I mean there are many

play27:47

many different ways to do a toolbar in

play27:49

lexical it's just as flexible as

play27:51

reactive is really like all you're doing

play27:53

is um

play27:54

you know accessing the editor and like

play27:56

dispatching commands or like calling

play27:58

editor updates or whatever with some

play27:59

buttons so how you do it's really up to

play28:02

you like the one way to do it is just to

play28:04

have a toolbar plug-in in the composer

play28:06

and then have like you know kind of

play28:08

compose little pieces of that UI through

play28:11

other plugins plugins are totally

play28:13

composable and then just like react

play28:15

components and so that's a good way to

play28:16

go at it but like I said there are many

play28:19

ways to do this you can check out the

play28:20

playground

play28:21

um on you know our GitHub uh repo for

play28:24

examples for our example of how to do it

play28:26

but they're like once again many many

play28:28

ways to do this so encourage you to uh

play28:31

you know explore and find your own

play28:33

Solutions

play28:33

um but anyways I hope this was helpful

play28:35

and we'll continue in a future video and

play28:37

maybe work on some more interesting uh

play28:40

and exciting use cases for like school

play28:42

thank you

Rate This

5.0 / 5 (0 votes)

Related Tags
プログラミングReactLexicalエディターUIチュートリアルツールバーヘッディングリストソフトウェア開発
Do you need a summary in English?