@crystallize/design-system 1.6.1 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/dist/index.css +53 -332
- package/dist/index.d.ts +15 -8
- package/dist/index.js +1736 -4555
- package/dist/index.mjs +1655 -2339
- package/package.json +1 -1
- package/src/action-menu/action-item-separator.tsx +14 -0
- package/src/action-menu/action-item.tsx +2 -2
- package/src/action-menu/action-menu.css +8 -0
- package/src/action-menu/action-menu.tsx +2 -1
- package/src/dropdown-menu/dropdown-menu-root.tsx +3 -1
- package/src/dropdown-menu/index.ts +5 -2
- package/src/iconography/subscription-contracts.tsx +4 -4
- package/src/iconography/subscription-plans.tsx +5 -5
- package/src/rich-text-editor/model/crystallize-to-lexical.ts +12 -1
- package/src/rich-text-editor/model/lexical-to-crystallize.ts +38 -38
- package/src/rich-text-editor/nodes/BaseNodes.ts +0 -7
- package/src/rich-text-editor/nodes/TableCellNodes.ts +0 -7
- package/src/rich-text-editor/plugins/ActionsPlugin/index.tsx +13 -2
- package/src/rich-text-editor/plugins/CodeActionMenuPlugin/components/CopyButton/index.tsx +3 -2
- package/src/rich-text-editor/plugins/CodeActionMenuPlugin/components/PrettierButton/index.tsx +0 -1
- package/src/rich-text-editor/plugins/FloatingTextFormatToolbarPlugin/index.css +17 -17
- package/src/rich-text-editor/plugins/FloatingTextFormatToolbarPlugin/index.tsx +1 -1
- package/src/rich-text-editor/plugins/MaxLengthPlugin/index.tsx +2 -7
- package/src/rich-text-editor/plugins/TableActionMenuPlugin/index.tsx +80 -149
- package/src/rich-text-editor/plugins/ToolbarPlugin/index.tsx +2 -2
- package/src/rich-text-editor/plugins/ToolbarPlugin/insert-table.tsx +55 -0
- package/src/rich-text-editor/rich-text-editor.css +10 -322
- package/src/rich-text-editor/rich-text-editor.stories.tsx +35 -5
- package/src/rich-text-editor/rich-text-editor.tsx +6 -39
- package/src/rich-text-editor/tests/rich-text-editor-code.test.tsx +10 -6
- package/src/rich-text-editor/tests/rich-text-editor-model-conversions.test.tsx +19 -7
- package/src/rich-text-editor/themes/CrystallizeRTEditorTheme.css +3 -11
- package/dist/TableComponent-I2YOOYOU.css +0 -281
- package/dist/TableComponent-QINOO453.mjs +0 -1377
- package/dist/chevron-down-3FRWSIKS.svg +0 -1
- package/dist/chunk-VUXQZRSP.mjs +0 -737
- package/dist/markdown-4BGQNLLT.svg +0 -1
- package/src/rich-text-editor/nodes/KeywordNode.ts +0 -73
- package/src/rich-text-editor/nodes/TableComponent.tsx +0 -1547
- package/src/rich-text-editor/nodes/TableNode.tsx +0 -398
- package/src/rich-text-editor/plugins/ComponentPickerPlugin/index.tsx +0 -320
- package/src/rich-text-editor/plugins/DragDropPastePlugin/index.ts +0 -40
- package/src/rich-text-editor/plugins/MarkdownShortcutPlugin/index.tsx +0 -16
- package/src/rich-text-editor/plugins/MarkdownTransformers/index.ts +0 -195
- package/src/rich-text-editor/plugins/SpeechToTextPlugin/index.ts +0 -113
- package/src/rich-text-editor/plugins/TableCellResizer/index.css +0 -12
- package/src/rich-text-editor/plugins/TableCellResizer/index.tsx +0 -386
- package/src/rich-text-editor/plugins/TablePlugin.tsx +0 -190
- package/src/rich-text-editor/plugins/TreeViewPlugin/index.tsx +0 -25
- package/src/rich-text-editor/plugins/TypingPerfPlugin/index.ts +0 -117
|
@@ -1,398 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
-
*
|
|
4
|
-
* This source code is licensed under the MIT license found in the
|
|
5
|
-
* LICENSE file in the root directory of this source tree.
|
|
6
|
-
*
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import * as React from 'react';
|
|
10
|
-
import { Suspense } from 'react';
|
|
11
|
-
import {
|
|
12
|
-
DecoratorNode,
|
|
13
|
-
type DOMConversionMap,
|
|
14
|
-
type DOMConversionOutput,
|
|
15
|
-
type DOMExportOutput,
|
|
16
|
-
type EditorConfig,
|
|
17
|
-
type LexicalEditor,
|
|
18
|
-
type LexicalNode,
|
|
19
|
-
type NodeKey,
|
|
20
|
-
type SerializedLexicalNode,
|
|
21
|
-
type Spread,
|
|
22
|
-
} from 'lexical';
|
|
23
|
-
|
|
24
|
-
export type Cell = {
|
|
25
|
-
colSpan: number;
|
|
26
|
-
json: string;
|
|
27
|
-
type: 'normal' | 'header';
|
|
28
|
-
id: string;
|
|
29
|
-
width: number | null;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
export type Row = {
|
|
33
|
-
cells: Array<Cell>;
|
|
34
|
-
height: null | number;
|
|
35
|
-
id: string;
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
export type Rows = Array<Row>;
|
|
39
|
-
|
|
40
|
-
export const cellHTMLCache: Map<string, string> = new Map();
|
|
41
|
-
export const cellTextContentCache: Map<string, string> = new Map();
|
|
42
|
-
|
|
43
|
-
const emptyEditorJSON =
|
|
44
|
-
'{"root":{"children":[{"children":[],"direction":null,"format":"","indent":0,"type":"paragraph","version":1}],"direction":null,"format":"","indent":0,"type":"root","version":1}}';
|
|
45
|
-
|
|
46
|
-
const plainTextEditorJSON = (text: string) =>
|
|
47
|
-
text === ''
|
|
48
|
-
? emptyEditorJSON
|
|
49
|
-
: `{"root":{"children":[{"children":[{"detail":0,"format":0,"mode":"normal","style":"","text":${text},"type":"text","version":1}],"direction":"ltr","format":"","indent":0,"type":"paragraph","version":1}],"direction":"ltr","format":"","indent":0,"type":"root","version":1}}`;
|
|
50
|
-
|
|
51
|
-
const TableComponent = React.lazy(
|
|
52
|
-
// @ts-ignore
|
|
53
|
-
() => import('./TableComponent'),
|
|
54
|
-
);
|
|
55
|
-
|
|
56
|
-
export function createUID(): string {
|
|
57
|
-
return Math.random()
|
|
58
|
-
.toString(36)
|
|
59
|
-
.replace(/[^a-z]+/g, '')
|
|
60
|
-
.substr(0, 5);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function createCell(type: 'normal' | 'header'): Cell {
|
|
64
|
-
return {
|
|
65
|
-
colSpan: 1,
|
|
66
|
-
id: createUID(),
|
|
67
|
-
json: emptyEditorJSON,
|
|
68
|
-
type,
|
|
69
|
-
width: null,
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export function createRow(): Row {
|
|
74
|
-
return {
|
|
75
|
-
cells: [],
|
|
76
|
-
height: null,
|
|
77
|
-
id: createUID(),
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export type SerializedTableNode = Spread<
|
|
82
|
-
{
|
|
83
|
-
rows: Rows;
|
|
84
|
-
type: 'tablesheet';
|
|
85
|
-
version: 1;
|
|
86
|
-
},
|
|
87
|
-
SerializedLexicalNode
|
|
88
|
-
>;
|
|
89
|
-
|
|
90
|
-
export function extractRowsFromHTML(tableElem: HTMLTableElement): Rows {
|
|
91
|
-
const rowElems = tableElem.querySelectorAll('tr');
|
|
92
|
-
const rows: Rows = [];
|
|
93
|
-
for (let y = 0; y < rowElems.length; y++) {
|
|
94
|
-
const rowElem = rowElems[y];
|
|
95
|
-
const cellElems = rowElem.querySelectorAll('td,th');
|
|
96
|
-
if (!cellElems || cellElems.length === 0) {
|
|
97
|
-
continue;
|
|
98
|
-
}
|
|
99
|
-
const cells: Array<Cell> = [];
|
|
100
|
-
for (let x = 0; x < cellElems.length; x++) {
|
|
101
|
-
const cellElem = cellElems[x] as HTMLElement;
|
|
102
|
-
const isHeader = cellElem.nodeName === 'TH';
|
|
103
|
-
const cell = createCell(isHeader ? 'header' : 'normal');
|
|
104
|
-
cell.json = plainTextEditorJSON(JSON.stringify(cellElem.innerText.replace(/\n/g, ' ')));
|
|
105
|
-
cells.push(cell);
|
|
106
|
-
}
|
|
107
|
-
const row = createRow();
|
|
108
|
-
row.cells = cells;
|
|
109
|
-
rows.push(row);
|
|
110
|
-
}
|
|
111
|
-
return rows;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
function convertTableElement(domNode: HTMLElement): null | DOMConversionOutput {
|
|
115
|
-
const rowElems = domNode.querySelectorAll('tr');
|
|
116
|
-
if (!rowElems || rowElems.length === 0) {
|
|
117
|
-
return null;
|
|
118
|
-
}
|
|
119
|
-
const rows: Rows = [];
|
|
120
|
-
for (let y = 0; y < rowElems.length; y++) {
|
|
121
|
-
const rowElem = rowElems[y];
|
|
122
|
-
const cellElems = rowElem.querySelectorAll('td,th');
|
|
123
|
-
if (!cellElems || cellElems.length === 0) {
|
|
124
|
-
continue;
|
|
125
|
-
}
|
|
126
|
-
const cells: Array<Cell> = [];
|
|
127
|
-
for (let x = 0; x < cellElems.length; x++) {
|
|
128
|
-
const cellElem = cellElems[x] as HTMLElement;
|
|
129
|
-
const isHeader = cellElem.nodeName === 'TH';
|
|
130
|
-
const cell = createCell(isHeader ? 'header' : 'normal');
|
|
131
|
-
cell.json = plainTextEditorJSON(JSON.stringify(cellElem.innerText.replace(/\n/g, ' ')));
|
|
132
|
-
cells.push(cell);
|
|
133
|
-
}
|
|
134
|
-
const row = createRow();
|
|
135
|
-
row.cells = cells;
|
|
136
|
-
rows.push(row);
|
|
137
|
-
}
|
|
138
|
-
return { node: $createTableNode(rows) };
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
export function exportTableCellsToHTML(
|
|
142
|
-
rows: Rows,
|
|
143
|
-
rect?: { startX: number; endX: number; startY: number; endY: number },
|
|
144
|
-
): HTMLElement {
|
|
145
|
-
const table = document.createElement('table');
|
|
146
|
-
const colGroup = document.createElement('colgroup');
|
|
147
|
-
const tBody = document.createElement('tbody');
|
|
148
|
-
const firstRow = rows[0];
|
|
149
|
-
|
|
150
|
-
for (let x = rect != null ? rect.startX : 0; x < (rect != null ? rect.endX + 1 : firstRow.cells.length); x++) {
|
|
151
|
-
const col = document.createElement('col');
|
|
152
|
-
colGroup.append(col);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
for (let y = rect != null ? rect.startY : 0; y < (rect != null ? rect.endY + 1 : rows.length); y++) {
|
|
156
|
-
const row = rows[y];
|
|
157
|
-
const cells = row.cells;
|
|
158
|
-
const rowElem = document.createElement('tr');
|
|
159
|
-
|
|
160
|
-
for (let x = rect != null ? rect.startX : 0; x < (rect != null ? rect.endX + 1 : cells.length); x++) {
|
|
161
|
-
const cell = cells[x];
|
|
162
|
-
const cellElem = document.createElement(cell.type === 'header' ? 'th' : 'td');
|
|
163
|
-
cellElem.innerHTML = cellHTMLCache.get(cell.json) || '';
|
|
164
|
-
rowElem.appendChild(cellElem);
|
|
165
|
-
}
|
|
166
|
-
tBody.appendChild(rowElem);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
table.appendChild(colGroup);
|
|
170
|
-
table.appendChild(tBody);
|
|
171
|
-
return table;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
export class TableNode extends DecoratorNode<JSX.Element> {
|
|
175
|
-
__rows: Rows;
|
|
176
|
-
|
|
177
|
-
static getType(): string {
|
|
178
|
-
return 'tablesheet';
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
static clone(node: TableNode): TableNode {
|
|
182
|
-
return new TableNode(Array.from(node.__rows), node.__key);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
static importJSON(serializedNode: SerializedTableNode): TableNode {
|
|
186
|
-
return $createTableNode(serializedNode.rows);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
exportJSON(): SerializedTableNode {
|
|
190
|
-
return {
|
|
191
|
-
rows: this.__rows,
|
|
192
|
-
type: 'tablesheet',
|
|
193
|
-
version: 1,
|
|
194
|
-
};
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
static importDOM(): DOMConversionMap | null {
|
|
198
|
-
return {
|
|
199
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
200
|
-
table: (_node: Node) => ({
|
|
201
|
-
conversion: convertTableElement,
|
|
202
|
-
priority: 0,
|
|
203
|
-
}),
|
|
204
|
-
};
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
exportDOM(): DOMExportOutput {
|
|
208
|
-
return { element: exportTableCellsToHTML(this.__rows) };
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
constructor(rows?: Rows, key?: NodeKey) {
|
|
212
|
-
super(key);
|
|
213
|
-
this.__rows = rows || [];
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
createDOM(): HTMLElement {
|
|
217
|
-
return document.createElement('div');
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
updateDOM(): false {
|
|
221
|
-
return false;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
mergeRows(startX: number, startY: number, mergeRows: Rows): void {
|
|
225
|
-
const self = this.getWritable();
|
|
226
|
-
const rows = self.__rows;
|
|
227
|
-
const endY = Math.min(rows.length, startY + mergeRows.length);
|
|
228
|
-
for (let y = startY; y < endY; y++) {
|
|
229
|
-
const row = rows[y];
|
|
230
|
-
const mergeRow = mergeRows[y - startY];
|
|
231
|
-
const cells = row.cells;
|
|
232
|
-
const cellsClone = Array.from(cells);
|
|
233
|
-
const rowClone = { ...row, cells: cellsClone };
|
|
234
|
-
const mergeCells = mergeRow.cells;
|
|
235
|
-
const endX = Math.min(cells.length, startX + mergeCells.length);
|
|
236
|
-
for (let x = startX; x < endX; x++) {
|
|
237
|
-
const cell = cells[x];
|
|
238
|
-
const mergeCell = mergeCells[x - startX];
|
|
239
|
-
const cellClone = { ...cell, json: mergeCell.json, type: mergeCell.type };
|
|
240
|
-
cellsClone[x] = cellClone;
|
|
241
|
-
}
|
|
242
|
-
rows[y] = rowClone;
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
updateCellJSON(x: number, y: number, json: string): void {
|
|
247
|
-
const self = this.getWritable();
|
|
248
|
-
const rows = self.__rows;
|
|
249
|
-
const row = rows[y];
|
|
250
|
-
const cells = row.cells;
|
|
251
|
-
const cell = cells[x];
|
|
252
|
-
const cellsClone = Array.from(cells);
|
|
253
|
-
const cellClone = { ...cell, json };
|
|
254
|
-
const rowClone = { ...row, cells: cellsClone };
|
|
255
|
-
cellsClone[x] = cellClone;
|
|
256
|
-
rows[y] = rowClone;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
updateCellType(x: number, y: number, type: 'header' | 'normal'): void {
|
|
260
|
-
const self = this.getWritable();
|
|
261
|
-
const rows = self.__rows;
|
|
262
|
-
const row = rows[y];
|
|
263
|
-
const cells = row.cells;
|
|
264
|
-
const cell = cells[x];
|
|
265
|
-
const cellsClone = Array.from(cells);
|
|
266
|
-
const cellClone = { ...cell, type };
|
|
267
|
-
const rowClone = { ...row, cells: cellsClone };
|
|
268
|
-
cellsClone[x] = cellClone;
|
|
269
|
-
rows[y] = rowClone;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
insertColumnAt(x: number): void {
|
|
273
|
-
const self = this.getWritable();
|
|
274
|
-
const rows = self.__rows;
|
|
275
|
-
for (let y = 0; y < rows.length; y++) {
|
|
276
|
-
const row = rows[y];
|
|
277
|
-
const cells = row.cells;
|
|
278
|
-
const cellsClone = Array.from(cells);
|
|
279
|
-
const rowClone = { ...row, cells: cellsClone };
|
|
280
|
-
const type = (cells[x] || cells[x - 1]).type;
|
|
281
|
-
cellsClone.splice(x, 0, createCell(type));
|
|
282
|
-
rows[y] = rowClone;
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
deleteColumnAt(x: number): void {
|
|
287
|
-
const self = this.getWritable();
|
|
288
|
-
const rows = self.__rows;
|
|
289
|
-
for (let y = 0; y < rows.length; y++) {
|
|
290
|
-
const row = rows[y];
|
|
291
|
-
const cells = row.cells;
|
|
292
|
-
const cellsClone = Array.from(cells);
|
|
293
|
-
const rowClone = { ...row, cells: cellsClone };
|
|
294
|
-
cellsClone.splice(x, 1);
|
|
295
|
-
rows[y] = rowClone;
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
addColumns(count: number): void {
|
|
300
|
-
const self = this.getWritable();
|
|
301
|
-
const rows = self.__rows;
|
|
302
|
-
for (let y = 0; y < rows.length; y++) {
|
|
303
|
-
const row = rows[y];
|
|
304
|
-
const cells = row.cells;
|
|
305
|
-
const cellsClone = Array.from(cells);
|
|
306
|
-
const rowClone = { ...row, cells: cellsClone };
|
|
307
|
-
const type = cells[cells.length - 1].type;
|
|
308
|
-
for (let x = 0; x < count; x++) {
|
|
309
|
-
cellsClone.push(createCell(type));
|
|
310
|
-
}
|
|
311
|
-
rows[y] = rowClone;
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
insertRowAt(y: number): void {
|
|
316
|
-
const self = this.getWritable();
|
|
317
|
-
const rows = self.__rows;
|
|
318
|
-
const prevRow = rows[y] || rows[y - 1];
|
|
319
|
-
const cellCount = prevRow.cells.length;
|
|
320
|
-
const row = createRow();
|
|
321
|
-
for (let x = 0; x < cellCount; x++) {
|
|
322
|
-
const cell = createCell(prevRow.cells[x].type);
|
|
323
|
-
row.cells.push(cell);
|
|
324
|
-
}
|
|
325
|
-
rows.splice(y, 0, row);
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
deleteRowAt(y: number): void {
|
|
329
|
-
const self = this.getWritable();
|
|
330
|
-
const rows = self.__rows;
|
|
331
|
-
rows.splice(y, 1);
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
addRows(count: number): void {
|
|
335
|
-
const self = this.getWritable();
|
|
336
|
-
const rows = self.__rows;
|
|
337
|
-
const prevRow = rows[rows.length - 1];
|
|
338
|
-
const cellCount = prevRow.cells.length;
|
|
339
|
-
|
|
340
|
-
for (let y = 0; y < count; y++) {
|
|
341
|
-
const row = createRow();
|
|
342
|
-
for (let x = 0; x < cellCount; x++) {
|
|
343
|
-
const cell = createCell(prevRow.cells[x].type);
|
|
344
|
-
row.cells.push(cell);
|
|
345
|
-
}
|
|
346
|
-
rows.push(row);
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
updateColumnWidth(x: number, width: number): void {
|
|
351
|
-
const self = this.getWritable();
|
|
352
|
-
const rows = self.__rows;
|
|
353
|
-
for (let y = 0; y < rows.length; y++) {
|
|
354
|
-
const row = rows[y];
|
|
355
|
-
const cells = row.cells;
|
|
356
|
-
const cellsClone = Array.from(cells);
|
|
357
|
-
const rowClone = { ...row, cells: cellsClone };
|
|
358
|
-
cellsClone[x].width = width;
|
|
359
|
-
rows[y] = rowClone;
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
decorate(_: LexicalEditor, config: EditorConfig): JSX.Element {
|
|
364
|
-
return (
|
|
365
|
-
<Suspense fallback="...">
|
|
366
|
-
<TableComponent nodeKey={this.__key} theme={config.theme} rows={this.__rows} />
|
|
367
|
-
</Suspense>
|
|
368
|
-
);
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
isInline(): false {
|
|
372
|
-
return false;
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
export function $isTableNode(node: LexicalNode | null | undefined): node is TableNode {
|
|
377
|
-
return node instanceof TableNode;
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
export function $createTableNode(rows: Rows): TableNode {
|
|
381
|
-
return new TableNode(rows);
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
export function $createTableNodeWithDimensions(
|
|
385
|
-
rowCount: number,
|
|
386
|
-
columnCount: number,
|
|
387
|
-
includeHeaders = true,
|
|
388
|
-
): TableNode {
|
|
389
|
-
const rows: Rows = [];
|
|
390
|
-
for (let y = 0; y < columnCount; y++) {
|
|
391
|
-
const row: Row = createRow();
|
|
392
|
-
rows.push(row);
|
|
393
|
-
for (let x = 0; x < rowCount; x++) {
|
|
394
|
-
row.cells.push(createCell(includeHeaders === true && (y === 0 || x === 0) ? 'header' : 'normal'));
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
return new TableNode(rows);
|
|
398
|
-
}
|