@haklex/rich-plugin-table 0.0.64 → 0.0.66

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/README.md CHANGED
@@ -1,35 +1,66 @@
1
1
  # @haklex/rich-plugin-table
2
2
 
3
- 表格编辑插件。
3
+ Table editing plugin with cell resizing and row/column manipulation.
4
4
 
5
- ## 安装
5
+ ## Installation
6
6
 
7
7
  ```bash
8
- pnpm add @haklex/rich-plugin-table @haklex/rich-editor
8
+ pnpm add @haklex/rich-plugin-table
9
9
  ```
10
10
 
11
- ## 导出
11
+ ## Peer Dependencies
12
12
 
13
- ```ts
14
- export { TableCellResizerPlugin } from './TableCellResizerPlugin'
15
- export { TableRowColumnHandlesPlugin } from './TableRowColumnHandlesPlugin'
16
- ```
13
+ | Package | Version |
14
+ | --- | --- |
15
+ | `@lexical/react` | `^0.41.0` |
16
+ | `@lexical/table` | `^0.41.0` |
17
+ | `lexical` | `^0.41.0` |
18
+ | `lucide-react` | `^0.574.0` |
19
+ | `react` | `>= 19` |
20
+ | `react-dom` | `>= 19` |
17
21
 
18
- ## 使用
22
+ ## Usage
19
23
 
20
24
  ```tsx
21
- import {
22
- TableCellResizerPlugin,
23
- TableRowColumnHandlesPlugin
25
+ import {
26
+ TableCellResizerPlugin,
27
+ TableRowColumnHandlesPlugin,
24
28
  } from '@haklex/rich-plugin-table'
25
- import { RichEditor } from '@haklex/rich-editor'
29
+ import '@haklex/rich-plugin-table/style.css'
26
30
 
27
- <RichEditor>
28
- <TableRowColumnHandlesPlugin />
29
- <TableCellResizerPlugin />
30
- </RichEditor>
31
+ function Editor() {
32
+ return (
33
+ <RichEditor>
34
+ <TableCellResizerPlugin />
35
+ <TableRowColumnHandlesPlugin />
36
+ </RichEditor>
37
+ )
38
+ }
31
39
  ```
32
40
 
41
+ This plugin provides two complementary components:
42
+
43
+ - **TableCellResizerPlugin** -- Allows users to resize table columns by dragging cell borders.
44
+ - **TableRowColumnHandlesPlugin** -- Renders handles for inserting, deleting, and reordering rows and columns.
45
+
46
+ ## Exports
47
+
48
+ | Export | Type | Description |
49
+ | --- | --- | --- |
50
+ | `TableCellResizerPlugin` | Component | Cell border drag-to-resize plugin |
51
+ | `TableRowColumnHandlesPlugin` | Component | Row/column insert, delete, and reorder handles |
52
+
53
+ ## Sub-path Exports
54
+
55
+ | Path | Description |
56
+ | --- | --- |
57
+ | `@haklex/rich-plugin-table` | Plugin components |
58
+ | `@haklex/rich-plugin-table/style.css` | Stylesheet |
59
+
60
+ ## Part of Haklex
61
+
62
+ This package is part of the [Haklex](../../README.md) rich editor ecosystem.
63
+
33
64
  ## License
34
65
 
35
66
  MIT
@@ -1 +1 @@
1
- {"version":3,"file":"TableCellResizerPlugin.d.ts","sourceRoot":"","sources":["../src/TableCellResizerPlugin.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAqC,YAAY,EAAE,MAAM,OAAO,CAAA;AAuP5E,wBAAgB,sBAAsB,IAAI,YAAY,CAIrD"}
1
+ {"version":3,"file":"TableCellResizerPlugin.d.ts","sourceRoot":"","sources":["../src/TableCellResizerPlugin.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAqC,YAAY,EAAE,MAAM,OAAO,CAAC;AAiP7E,wBAAgB,sBAAsB,IAAI,YAAY,CAIrD"}
@@ -1 +1 @@
1
- {"version":3,"file":"TableRowColumnHandlesPlugin.d.ts","sourceRoot":"","sources":["../src/TableRowColumnHandlesPlugin.tsx"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAA;AA6YzC,wBAAgB,2BAA2B,IAAI,YAAY,CAO1D"}
1
+ {"version":3,"file":"TableRowColumnHandlesPlugin.d.ts","sourceRoot":"","sources":["../src/TableRowColumnHandlesPlugin.tsx"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AA6X1C,wBAAgB,2BAA2B,IAAI,YAAY,CAI1D"}
package/dist/index.mjs CHANGED
@@ -13,12 +13,8 @@ var rowColHandle = "t6ga9o3";
13
13
  var rowColHandleVisible = "t6ga9o4";
14
14
  var handleBtn = "t6ga9o5";
15
15
  const RESIZER_HANDLE_ATTR = "data-table-resizer-handle";
16
- function TableCellResizerInner({
17
- editor
18
- }) {
19
- const [activeCell, setActiveCell] = useState(
20
- null
21
- );
16
+ function TableCellResizerInner({ editor }) {
17
+ const [activeCell, setActiveCell] = useState(null);
22
18
  const [resizing, setResizing] = useState(false);
23
19
  const [direction, setDirection] = useState(null);
24
20
  const [handlePos, setHandlePos] = useState({ right: null, bottom: null });
@@ -184,9 +180,9 @@ function TableCellResizerInner({
184
180
  handlePos.right && /* @__PURE__ */ jsx(
185
181
  "div",
186
182
  {
187
- "data-testid": "table-cell-resizer-right",
188
- "data-table-resizer-handle": "true",
189
183
  className: `${resizeHandle} ${direction === "right" ? resizeHandleActive : ""}`,
184
+ "data-table-resizer-handle": "true",
185
+ "data-testid": "table-cell-resizer-right",
190
186
  style: {
191
187
  top: handlePos.right.top,
192
188
  left: handlePos.right.left,
@@ -201,9 +197,9 @@ function TableCellResizerInner({
201
197
  handlePos.bottom && /* @__PURE__ */ jsx(
202
198
  "div",
203
199
  {
204
- "data-testid": "table-cell-resizer-bottom",
205
- "data-table-resizer-handle": "true",
206
200
  className: `${resizeHandle} ${direction === "bottom" ? resizeHandleActive : ""}`,
201
+ "data-table-resizer-handle": "true",
202
+ "data-testid": "table-cell-resizer-bottom",
207
203
  style: {
208
204
  top: handlePos.bottom.top,
209
205
  left: handlePos.bottom.left,
@@ -297,60 +293,57 @@ function TableRowColumnHandlesInner({
297
293
  hoveringHandleRef.current = false;
298
294
  scheduleHide();
299
295
  }, [scheduleHide]);
300
- const updateHandlesFromAnchor = useCallback(
301
- (anchor) => {
302
- if (anchor !== void 0) {
303
- activeAnchorRef.current = anchor;
304
- }
305
- const activeAnchor = activeAnchorRef.current;
306
- if (!activeAnchor) return;
307
- const { table, rowIndex, colIndex } = activeAnchor;
308
- if (!table.isConnected) {
309
- activeAnchorRef.current = null;
310
- setRowHandle((s) => ({ ...s, visible: false }));
311
- setColHandle((s) => ({ ...s, visible: false }));
312
- return;
313
- }
314
- const rows = table.querySelectorAll("tr");
315
- const row = rows[rowIndex];
316
- if (!row) {
317
- activeAnchorRef.current = null;
318
- setRowHandle((s) => ({ ...s, visible: false }));
319
- setColHandle((s) => ({ ...s, visible: false }));
320
- return;
321
- }
322
- const cells = row.querySelectorAll("td, th");
323
- const cell = cells[colIndex] ?? cells[0];
324
- if (!cell) {
325
- activeAnchorRef.current = null;
326
- setRowHandle((s) => ({ ...s, visible: false }));
327
- setColHandle((s) => ({ ...s, visible: false }));
328
- return;
329
- }
330
- tableRef.current = table;
331
- const resolvedColIndex = cell.cellIndex;
332
- activeAnchorRef.current = { table, rowIndex, colIndex: resolvedColIndex };
333
- const cellRect = cell.getBoundingClientRect();
334
- const tableRect = table.getBoundingClientRect();
335
- const cellPage = toPagePosition(cellRect);
336
- const tablePage = toPagePosition(tableRect);
337
- setRowHandle({
338
- visible: true,
339
- top: cellPage.top + cellRect.height / 2 - ROW_HANDLE_HEIGHT / 2,
340
- left: tablePage.left - 38,
341
- rowIndex,
342
- colIndex: resolvedColIndex
343
- });
344
- setColHandle({
345
- visible: true,
346
- top: tablePage.top - 22,
347
- left: cellPage.left + cellRect.width / 2 - COL_HANDLE_WIDTH / 2,
348
- rowIndex,
349
- colIndex: resolvedColIndex
350
- });
351
- },
352
- []
353
- );
296
+ const updateHandlesFromAnchor = useCallback((anchor) => {
297
+ if (anchor !== void 0) {
298
+ activeAnchorRef.current = anchor;
299
+ }
300
+ const activeAnchor = activeAnchorRef.current;
301
+ if (!activeAnchor) return;
302
+ const { table, rowIndex, colIndex } = activeAnchor;
303
+ if (!table.isConnected) {
304
+ activeAnchorRef.current = null;
305
+ setRowHandle((s) => ({ ...s, visible: false }));
306
+ setColHandle((s) => ({ ...s, visible: false }));
307
+ return;
308
+ }
309
+ const rows = table.querySelectorAll("tr");
310
+ const row = rows[rowIndex];
311
+ if (!row) {
312
+ activeAnchorRef.current = null;
313
+ setRowHandle((s) => ({ ...s, visible: false }));
314
+ setColHandle((s) => ({ ...s, visible: false }));
315
+ return;
316
+ }
317
+ const cells = row.querySelectorAll("td, th");
318
+ const cell = cells[colIndex] ?? cells[0];
319
+ if (!cell) {
320
+ activeAnchorRef.current = null;
321
+ setRowHandle((s) => ({ ...s, visible: false }));
322
+ setColHandle((s) => ({ ...s, visible: false }));
323
+ return;
324
+ }
325
+ tableRef.current = table;
326
+ const resolvedColIndex = cell.cellIndex;
327
+ activeAnchorRef.current = { table, rowIndex, colIndex: resolvedColIndex };
328
+ const cellRect = cell.getBoundingClientRect();
329
+ const tableRect = table.getBoundingClientRect();
330
+ const cellPage = toPagePosition(cellRect);
331
+ const tablePage = toPagePosition(tableRect);
332
+ setRowHandle({
333
+ visible: true,
334
+ top: cellPage.top + cellRect.height / 2 - ROW_HANDLE_HEIGHT / 2,
335
+ left: tablePage.left - 38,
336
+ rowIndex,
337
+ colIndex: resolvedColIndex
338
+ });
339
+ setColHandle({
340
+ visible: true,
341
+ top: tablePage.top - 22,
342
+ left: cellPage.left + cellRect.width / 2 - COL_HANDLE_WIDTH / 2,
343
+ rowIndex,
344
+ colIndex: resolvedColIndex
345
+ });
346
+ }, []);
354
347
  useEffect(() => {
355
348
  const rootElement = editor.getRootElement();
356
349
  if (!rootElement) return;
@@ -476,19 +469,10 @@ function TableRowColumnHandlesInner({
476
469
  onMouseEnter: handleEnter,
477
470
  onMouseLeave: handleLeave,
478
471
  children: [
479
- /* @__PURE__ */ jsx(
480
- "button",
481
- {
482
- type: "button",
483
- className: handleBtn,
484
- onClick: addRowBelow,
485
- "aria-label": "Add row",
486
- children: /* @__PURE__ */ jsx(Plus, { size: ICON_SIZE })
487
- }
488
- ),
472
+ /* @__PURE__ */ jsx("button", { "aria-label": "Add row", className: handleBtn, type: "button", onClick: addRowBelow, children: /* @__PURE__ */ jsx(Plus, { size: ICON_SIZE }) }),
489
473
  /* @__PURE__ */ jsxs(DropdownMenu, { children: [
490
474
  /* @__PURE__ */ jsx(DropdownMenuTrigger, { className: handleBtn, children: /* @__PURE__ */ jsx(GripVertical, { size: ICON_SIZE }) }),
491
- /* @__PURE__ */ jsxs(DropdownMenuContent, { side: "right", align: "start", sideOffset: 4, children: [
475
+ /* @__PURE__ */ jsxs(DropdownMenuContent, { align: "start", side: "right", sideOffset: 4, children: [
492
476
  /* @__PURE__ */ jsxs(DropdownMenuItem, { onClick: insertRowAbove, children: [
493
477
  /* @__PURE__ */ jsx(ArrowUp, { size: 14 }),
494
478
  "Insert row above"
@@ -498,17 +482,10 @@ function TableRowColumnHandlesInner({
498
482
  "Insert row below"
499
483
  ] }),
500
484
  /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
501
- /* @__PURE__ */ jsxs(
502
- DropdownMenuItem,
503
- {
504
- className: menuItemDestructive,
505
- onClick: deleteRow,
506
- children: [
507
- /* @__PURE__ */ jsx(Trash2, { size: 14 }),
508
- "Delete row"
509
- ]
510
- }
511
- )
485
+ /* @__PURE__ */ jsxs(DropdownMenuItem, { className: menuItemDestructive, onClick: deleteRow, children: [
486
+ /* @__PURE__ */ jsx(Trash2, { size: 14 }),
487
+ "Delete row"
488
+ ] })
512
489
  ] })
513
490
  ] })
514
491
  ]
@@ -525,16 +502,16 @@ function TableRowColumnHandlesInner({
525
502
  /* @__PURE__ */ jsx(
526
503
  "button",
527
504
  {
528
- type: "button",
505
+ "aria-label": "Add column",
529
506
  className: handleBtn,
507
+ type: "button",
530
508
  onClick: addColumnLeft,
531
- "aria-label": "Add column",
532
509
  children: /* @__PURE__ */ jsx(Plus, { size: ICON_SIZE })
533
510
  }
534
511
  ),
535
512
  /* @__PURE__ */ jsxs(DropdownMenu, { children: [
536
513
  /* @__PURE__ */ jsx(DropdownMenuTrigger, { className: handleBtn, children: /* @__PURE__ */ jsx(GripVertical, { size: ICON_SIZE }) }),
537
- /* @__PURE__ */ jsxs(DropdownMenuContent, { side: "bottom", align: "start", sideOffset: 4, children: [
514
+ /* @__PURE__ */ jsxs(DropdownMenuContent, { align: "start", side: "bottom", sideOffset: 4, children: [
538
515
  /* @__PURE__ */ jsxs(DropdownMenuItem, { onClick: insertColumnLeft, children: [
539
516
  /* @__PURE__ */ jsx(ArrowLeft, { size: 14 }),
540
517
  "Insert column left"
@@ -544,17 +521,10 @@ function TableRowColumnHandlesInner({
544
521
  "Insert column right"
545
522
  ] }),
546
523
  /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
547
- /* @__PURE__ */ jsxs(
548
- DropdownMenuItem,
549
- {
550
- className: menuItemDestructive,
551
- onClick: deleteColumn,
552
- children: [
553
- /* @__PURE__ */ jsx(Trash2, { size: 14 }),
554
- "Delete column"
555
- ]
556
- }
557
- )
524
+ /* @__PURE__ */ jsxs(DropdownMenuItem, { className: menuItemDestructive, onClick: deleteColumn, children: [
525
+ /* @__PURE__ */ jsx(Trash2, { size: 14 }),
526
+ "Delete column"
527
+ ] })
558
528
  ] })
559
529
  ] })
560
530
  ]
@@ -564,10 +534,7 @@ function TableRowColumnHandlesInner({
564
534
  }
565
535
  function TableRowColumnHandlesPlugin() {
566
536
  const [editor] = useLexicalComposerContext();
567
- return createPortal(
568
- /* @__PURE__ */ jsx(TableRowColumnHandlesInner, { editor }),
569
- document.body
570
- );
537
+ return createPortal(/* @__PURE__ */ jsx(TableRowColumnHandlesInner, { editor }), document.body);
571
538
  }
572
539
  export {
573
540
  TableCellResizerPlugin,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@haklex/rich-plugin-table",
3
3
  "type": "module",
4
- "version": "0.0.64",
4
+ "version": "0.0.66",
5
5
  "description": "Table editing plugin",
6
6
  "license": "MIT",
7
7
  "exports": {
@@ -24,8 +24,8 @@
24
24
  "react-dom": ">=19"
25
25
  },
26
26
  "dependencies": {
27
- "@haklex/rich-editor-ui": "0.0.64",
28
- "@haklex/rich-style-token": "0.0.64"
27
+ "@haklex/rich-style-token": "0.0.66",
28
+ "@haklex/rich-editor-ui": "0.0.66"
29
29
  },
30
30
  "devDependencies": {
31
31
  "@lexical/react": "^0.41.0",
@@ -45,6 +45,11 @@
45
45
  "publishConfig": {
46
46
  "access": "public"
47
47
  },
48
+ "repository": {
49
+ "type": "git",
50
+ "url": "https://github.com/Innei/haklex.git",
51
+ "directory": "packages/rich-plugin-table"
52
+ },
48
53
  "scripts": {
49
54
  "build": "vite build",
50
55
  "dev:build": "vite build --watch"
package/LICENSE DELETED
@@ -1,28 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2024 Innei
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
22
-
23
-
24
- Additional Terms and Conditions
25
-
26
- ----------------
27
-
28
- Use of this software is governed by the terms of MIT and, in addition, by the terms and conditions described in the additional file (ADDITIONAL_TERMS.md). By using this software, you agree to abide by these additional terms and conditions.