@livepreso/react-plugin-textfield 0.5.1 → 0.6.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.
Files changed (177) hide show
  1. package/.rush/temp/shrinkwrap-deps.json +2 -2
  2. package/CHANGELOG.json +37 -0
  3. package/CHANGELOG.md +15 -1
  4. package/components/BorderEdgeToggle.js +72 -0
  5. package/components/BubbleMenu.js +107 -19
  6. package/components/BubbleMenu.module.scss +0 -1
  7. package/components/InsertTokenDialog.js +1 -1
  8. package/components/InsertTokenDialog.module.scss +1 -1
  9. package/components/LinkEditDialog.js +2 -2
  10. package/components/LinkEditDialog.module.scss +1 -1
  11. package/components/TableDensityPicker.js +48 -0
  12. package/components/{color-picker/ColorPicker.module.scss → TableDensityPicker.module.scss} +4 -3
  13. package/components/TableToolbar.js +4 -0
  14. package/components/VerticalAlignToggle.js +8 -8
  15. package/components/color-picker/ColorPickerCombo.js +5 -5
  16. package/components/color-picker/ColorPickerCombo.module.scss +1 -1
  17. package/components/editor-toolbars/EditorMenu.js +2 -1
  18. package/components/editor-toolbars/EditorMenu.module.scss +1 -1
  19. package/components/editor-toolbars/EditorToolbar.js +10 -7
  20. package/components/editor-toolbars/EditorToolbar.module.scss +11 -68
  21. package/components/editor-toolbars/SimpleButton.module.scss +1 -1
  22. package/components/editor-toolbars/SubMenu.js +59 -3
  23. package/components/table-creator/TableCreatorCombo.js +4 -4
  24. package/components/table-creator/TableCreatorCombo.module.scss +1 -1
  25. package/components/tiptap/Table.js +172 -5
  26. package/components/tiptap/TableCells.js +33 -0
  27. package/components/tiptap/token/Token.module.scss +1 -1
  28. package/components/tiptap/token/TokenList.module.scss +1 -1
  29. package/components/utils.js +0 -49
  30. package/configs/table-toolbar-configuration.js +87 -8
  31. package/configs/toolbar-configuration.js +3 -3
  32. package/constants.js +16 -1
  33. package/index.js +11 -4
  34. package/index.module.scss +63 -22
  35. package/package.json +3 -4
  36. package/utils/generate-border-icon.js +22 -0
  37. package/utils/generate-vertical-alignment-icon.js +1 -1
  38. package/components/Popover.js +0 -43
  39. package/components/Popover.module.scss +0 -80
  40. package/components/Select/Select.js +0 -71
  41. package/components/Select/Select.module.scss +0 -100
  42. package/components/Select/SelectGroup.js +0 -37
  43. package/components/Select/index.js +0 -1
  44. package/components/Tooltip.js +0 -34
  45. package/components/Tooltip.module.scss +0 -87
  46. package/components/color-picker/ColorPicker.js +0 -28
  47. package/components/color-picker/ColorPickerChip.js +0 -22
  48. package/components/color-picker/ColorPickerChip.module.scss +0 -25
  49. package/components/editor-toolbars/ToolbarButton.js +0 -26
  50. package/components/editor-toolbars/ToolbarToggle.js +0 -35
  51. package/components/editor-toolbars/ToolbarToggleGroup.js +0 -43
  52. package/components/style.module.scss +0 -63
  53. package/icons/AddColumnLeft.js +0 -15
  54. package/icons/AddColumnRight.js +0 -15
  55. package/icons/AddRowAbove.js +0 -15
  56. package/icons/AddRowBelow.js +0 -15
  57. package/icons/AlignHorizontalCenter.js +0 -13
  58. package/icons/AlignHorizontalLeft.js +0 -13
  59. package/icons/AlignHorizontalRight.js +0 -13
  60. package/icons/AlignVerticalBottom.js +0 -13
  61. package/icons/AlignVerticalCenter.js +0 -13
  62. package/icons/AlignVerticalTop.js +0 -13
  63. package/icons/Backspace.js +0 -13
  64. package/icons/Bold.js +0 -14
  65. package/icons/BorderAll.js +0 -13
  66. package/icons/BorderBottom.js +0 -13
  67. package/icons/BorderClear.js +0 -13
  68. package/icons/BorderHorizontal.js +0 -13
  69. package/icons/BorderInner.js +0 -13
  70. package/icons/BorderLeft.js +0 -13
  71. package/icons/BorderOuter.js +0 -13
  72. package/icons/BorderRight.js +0 -13
  73. package/icons/BorderTop.js +0 -13
  74. package/icons/BorderVertical.js +0 -13
  75. package/icons/Close.js +0 -13
  76. package/icons/Delete.js +0 -13
  77. package/icons/EvenlyDistribute.js +0 -14
  78. package/icons/FitWidth.js +0 -13
  79. package/icons/FitWidthArrows.js +0 -21
  80. package/icons/FormatAlignCenter.js +0 -13
  81. package/icons/FormatAlignJustify.js +0 -13
  82. package/icons/FormatAlignLeft.js +0 -13
  83. package/icons/FormatAlignRight.js +0 -13
  84. package/icons/FormatBold.js +0 -13
  85. package/icons/FormatClear.js +0 -13
  86. package/icons/FormatColorFill.js +0 -13
  87. package/icons/FormatColorText.js +0 -13
  88. package/icons/FormatItalic.js +0 -13
  89. package/icons/FormatLineSpacing.js +0 -13
  90. package/icons/FormatListBulleted.js +0 -13
  91. package/icons/FormatListNumbered.js +0 -13
  92. package/icons/FormatStrikethrough.js +0 -13
  93. package/icons/FormatUnderlined.js +0 -13
  94. package/icons/HelpCenter.js +0 -13
  95. package/icons/HorizontalRule.js +0 -13
  96. package/icons/Italic.js +0 -14
  97. package/icons/ItalicIcon.js +0 -18
  98. package/icons/Link.js +0 -13
  99. package/icons/LinkOff.js +0 -13
  100. package/icons/MergeCells.js +0 -14
  101. package/icons/MoreVert.js +0 -13
  102. package/icons/Redo.js +0 -13
  103. package/icons/RemoveColumnOutline.js +0 -28
  104. package/icons/RemoveRowOutline.js +0 -25
  105. package/icons/SplitCells.js +0 -14
  106. package/icons/SplitScene.js +0 -13
  107. package/icons/Subscript.js +0 -13
  108. package/icons/Superscript.js +0 -13
  109. package/icons/Underline.js +0 -14
  110. package/icons/Undo.js +0 -13
  111. package/icons/VerticalAlignBottom.js +0 -13
  112. package/icons/VerticalAlignCenter.js +0 -13
  113. package/icons/VerticalAlignTop.js +0 -13
  114. package/icons/WandStars.js +0 -13
  115. package/icons/add_column_left.svg +0 -6
  116. package/icons/add_column_right.svg +0 -6
  117. package/icons/add_row_above.svg +0 -6
  118. package/icons/add_row_below.svg +0 -6
  119. package/icons/align_horizontal_center.svg +0 -1
  120. package/icons/align_horizontal_left.svg +0 -1
  121. package/icons/align_horizontal_right.svg +0 -1
  122. package/icons/align_vertical_bottom.svg +0 -1
  123. package/icons/align_vertical_center.svg +0 -1
  124. package/icons/align_vertical_top.svg +0 -1
  125. package/icons/backspace.svg +0 -1
  126. package/icons/bold.svg +0 -1
  127. package/icons/border_all.svg +0 -1
  128. package/icons/border_bottom.svg +0 -1
  129. package/icons/border_clear.svg +0 -1
  130. package/icons/border_horizontal.svg +0 -1
  131. package/icons/border_inner.svg +0 -1
  132. package/icons/border_left.svg +0 -1
  133. package/icons/border_outer.svg +0 -1
  134. package/icons/border_right.svg +0 -1
  135. package/icons/border_top.svg +0 -1
  136. package/icons/border_vertical.svg +0 -1
  137. package/icons/close.svg +0 -1
  138. package/icons/delete.svg +0 -1
  139. package/icons/evenly_distribute.svg +0 -5
  140. package/icons/fit_width.svg +0 -1
  141. package/icons/fit_width_arrows.svg +0 -12
  142. package/icons/format_align_center.svg +0 -1
  143. package/icons/format_align_justify.svg +0 -1
  144. package/icons/format_align_left.svg +0 -1
  145. package/icons/format_align_right.svg +0 -1
  146. package/icons/format_bold.svg +0 -1
  147. package/icons/format_clear.svg +0 -1
  148. package/icons/format_color_fill.svg +0 -1
  149. package/icons/format_italic.svg +0 -1
  150. package/icons/format_line_spacing.svg +0 -1
  151. package/icons/format_list_bulleted.svg +0 -1
  152. package/icons/format_list_numbered.svg +0 -1
  153. package/icons/format_strikethrough.svg +0 -1
  154. package/icons/format_underlined.svg +0 -1
  155. package/icons/help_center.svg +0 -1
  156. package/icons/horizontal_rule.svg +0 -1
  157. package/icons/index.js +0 -199
  158. package/icons/italic.svg +0 -1
  159. package/icons/link.svg +0 -1
  160. package/icons/link_off.svg +0 -1
  161. package/icons/merge_cells.svg +0 -5
  162. package/icons/more_vert.svg +0 -1
  163. package/icons/redo.svg +0 -1
  164. package/icons/remove_column_outline.svg +0 -20
  165. package/icons/remove_row_outline.svg +0 -17
  166. package/icons/split_cells.svg +0 -5
  167. package/icons/split_scene.svg +0 -1
  168. package/icons/subscript.svg +0 -1
  169. package/icons/superscript.svg +0 -1
  170. package/icons/underline.svg +0 -1
  171. package/icons/undo.svg +0 -1
  172. package/icons/vertical_align_bottom.svg +0 -1
  173. package/icons/vertical_align_center.svg +0 -1
  174. package/icons/vertical_align_top.svg +0 -1
  175. package/icons/wand_stars.svg +0 -1
  176. package/scripts/extract-svg.js +0 -290
  177. package/variables.scss +0 -6
@@ -1,5 +1,5 @@
1
1
  {
2
- "../../content/react-plugin-textfield": "../../content/react-plugin-textfield:PTuiaNrHYDSJw/Ha/cCGhwsG802uyQtRQiJefw08ufY=:",
2
+ "../../content/react-plugin-textfield": "../../content/react-plugin-textfield:WYj65vjFgDMTKI64ejk+PEiCQkGdzJw91G8OiyO6j9k=:",
3
3
  "@babel/code-frame@7.29.0": "@babel/code-frame@7.29.0:kW1E61/G1tPYp8ZHZtSkSne0DKMWSVn35WiB3NdzlCw=:",
4
4
  "@babel/compat-data@7.29.0": "@babel/compat-data@7.29.0:a57bU0z+Tu3qDgKTY6g83xpry+Ltpm2tGQHpJnQeNyU=:",
5
5
  "@babel/core@7.29.0": "@babel/core@7.29.0:q5im1Hft4sBHQef0WtCXclby5g4txy9LJX/q/yC0g5g=:",
@@ -173,7 +173,7 @@
173
173
  "eslint-scope@8.4.0": "eslint-scope@8.4.0:8sCuk/6sg3/iCXu4ikInhuUYyvcQoTXETHdBY6JCzr0=:",
174
174
  "eslint-visitor-keys@3.4.3": "eslint-visitor-keys@3.4.3:JgR2rf9Jpzva8lFrKE+5yhxLwgC8qNXtm9LsuSBeAT8=:",
175
175
  "eslint-visitor-keys@4.2.1": "eslint-visitor-keys@4.2.1:uyQNsuDcPZL1cJ29uclbt/ITeoMox36b0gbaWL8EB2E=:",
176
- "eslint@9.15.0(jiti@1.21.7)": "eslint@9.15.0(jiti@1.21.7):BBMkLm2PafjLl1mwKS36oeb1WbB2SxRLnq5E+fRoC04=:",
176
+ "eslint@9.15.0(jiti@1.21.7)": "eslint@9.15.0(jiti@1.21.7):5s8tqOQH56eedeB7EmuDjwdx9JjZeyXi4IS97WDGhbA=:",
177
177
  "espree@10.4.0": "espree@10.4.0:NLXs2uyUi7cK0j1u0OxWFDO6zYcblsb73pCi4SupIOE=:",
178
178
  "esquery@1.7.0": "esquery@1.7.0:7lTtVBqirWgWzvUR2UO+6Vgzeyg40AnBbmtPEJHSYnI=:",
179
179
  "esrecurse@4.3.0": "esrecurse@4.3.0:Uyo8CNm+VUgeJSS5C3ZgOky7Jzoy9NqvDpoJmqgzC1s=:",
package/CHANGELOG.json CHANGED
@@ -1,6 +1,43 @@
1
1
  {
2
2
  "name": "@livepreso/react-plugin-textfield",
3
3
  "entries": [
4
+ {
5
+ "version": "0.6.0",
6
+ "tag": "@livepreso/react-plugin-textfield_v0.6.0",
7
+ "date": "Thu, 17 Sep 2026 01:30:15 GMT",
8
+ "comments": {
9
+ "minor": [
10
+ {
11
+ "comment": "Refactor to use react-plugin-ui for base components. New table editing features: border selection, density (cell padding)."
12
+ }
13
+ ],
14
+ "dependency": [
15
+ {
16
+ "comment": "Updating dependency \"@livepreso/content-react\" to `2.3.1`"
17
+ },
18
+ {
19
+ "comment": "Updating dependency \"@livepreso/react-plugin-ui\" to `1.0.0`"
20
+ }
21
+ ]
22
+ }
23
+ },
24
+ {
25
+ "version": "0.5.2",
26
+ "tag": "@livepreso/react-plugin-textfield_v0.5.2",
27
+ "date": "Tue, 08 Sep 2026 00:30:21 GMT",
28
+ "comments": {
29
+ "patch": [
30
+ {
31
+ "comment": "Provide slidePath when getting values from CMSVals"
32
+ }
33
+ ],
34
+ "dependency": [
35
+ {
36
+ "comment": "Updating dependency \"@livepreso/content-react\" to `2.3.0`"
37
+ }
38
+ ]
39
+ }
40
+ },
4
41
  {
5
42
  "version": "0.5.1",
6
43
  "tag": "@livepreso/react-plugin-textfield_v0.5.1",
package/CHANGELOG.md CHANGED
@@ -1,6 +1,20 @@
1
1
  # Change Log - @livepreso/react-plugin-textfield
2
2
 
3
- This log was last generated on Thu, 03 Sep 2026 03:12:08 GMT and should not be manually modified.
3
+ This log was last generated on Thu, 17 Sep 2026 01:30:15 GMT and should not be manually modified.
4
+
5
+ ## 0.6.0
6
+ Thu, 17 Sep 2026 01:30:15 GMT
7
+
8
+ ### Minor changes
9
+
10
+ - Refactor to use react-plugin-ui for base components. New table editing features: border selection, density (cell padding).
11
+
12
+ ## 0.5.2
13
+ Tue, 08 Sep 2026 00:30:21 GMT
14
+
15
+ ### Patches
16
+
17
+ - Provide slidePath when getting values from CMSVals
4
18
 
5
19
  ## 0.5.1
6
20
  Thu, 03 Sep 2026 03:12:08 GMT
@@ -0,0 +1,72 @@
1
+ import React from "react";
2
+
3
+ import icons from "@livepreso/react-plugin-ui/icons";
4
+ import { Tooltip } from "radix-ui";
5
+ import {
6
+ ToolbarRoot,
7
+ ToolbarToggleGroup,
8
+ } from "@livepreso/react-plugin-ui/toolbar";
9
+
10
+ /**
11
+ * A component that renders a toggle group for enabling/disabling individual
12
+ * border edges on a table cell.
13
+ *
14
+ * @param {Object} props - The component props
15
+ * @param {string} props.id - The unique identifier for the toggle group
16
+ * @param {string} props.className - CSS class name to apply to the toolbar
17
+ * @param {Function} props.onChange - Callback triggered with the full set of active edges when the selection changes
18
+ * @param {string[]} props.value - The currently active border edges
19
+ * @returns {React.Element} A toolbar component containing border edge toggle options
20
+ */
21
+ export function BorderEdgeToggle({
22
+ id,
23
+ className,
24
+ onChange = () => {},
25
+ value,
26
+ }) {
27
+ return (
28
+ <Tooltip.Provider delayDuration={800} skipDelayDuration={500}>
29
+ <ToolbarRoot className={className}>
30
+ <ToolbarToggleGroup
31
+ key={id}
32
+ label="Border"
33
+ type="multiple"
34
+ value={value}
35
+ options={[
36
+ {
37
+ id: "border-top",
38
+ tooltip: "Top border",
39
+ label: "Top",
40
+ value: "top",
41
+ icon: <icons.BorderTop />,
42
+ },
43
+ {
44
+ id: "border-right",
45
+ tooltip: "Right border",
46
+ label: "Right",
47
+ value: "right",
48
+ icon: <icons.BorderRight />,
49
+ },
50
+ {
51
+ id: "border-bottom",
52
+ tooltip: "Bottom border",
53
+ label: "Bottom",
54
+ value: "bottom",
55
+ icon: <icons.BorderBottom />,
56
+ },
57
+ {
58
+ id: "border-left",
59
+ tooltip: "Left border",
60
+ label: "Left",
61
+ value: "left",
62
+ icon: <icons.BorderLeft />,
63
+ },
64
+ ]}
65
+ onValueChange={(value) => {
66
+ onChange(value);
67
+ }}
68
+ />
69
+ </ToolbarRoot>
70
+ </Tooltip.Provider>
71
+ );
72
+ }
@@ -6,19 +6,111 @@ import { computePosition } from "@floating-ui/react-dom";
6
6
  import { Plugin, PluginKey } from "@tiptap/pm/state";
7
7
 
8
8
  import { OverlayPortal, useTransitions } from "@livepreso/content-react";
9
+ import { getTestRect } from "@livepreso/react-plugin-ui/floating-menu";
9
10
  import style from "./BubbleMenu.module.scss";
10
11
  import { EDITABLE_OUTER_SELECTOR } from "../constants";
11
- import { getTestRect } from "./utils";
12
+
13
+ // Radix wraps Popover/Select content in this; dialogs and buttons get no wrapper.
14
+ const POPPER_CONTENT_SELECTOR = "[data-radix-popper-content-wrapper]";
12
15
 
13
16
  class UnscaledBubbleMenuView extends BubbleMenuView {
17
+ constructor(options) {
18
+ super(options);
19
+
20
+ // The presenter rescales on container resize without a window resize event.
21
+ window.Bridge?.Event?.on("resize", this.resizeHandler, "deck");
22
+
23
+ // Upstream's blur guard checks `element.parentNode`, which for our portaled
24
+ // menu is the whole overlay — so app chrome counts as toolbar and it never
25
+ // hides. Re-register with a guard scoped to our own surfaces.
26
+ this.editor.off("blur", this.blurHandler);
27
+ this.blurHandler = (payload) => this.handleBlur(payload);
28
+ this.editor.on("blur", this.blurHandler);
29
+
30
+ // Accounts for focus moving to another editor field, by comparing the field
31
+ // the focus landed in against this one.
32
+ this.focusInHandler = ({ target }) => {
33
+ if (!this.isVisible) {
34
+ return;
35
+ }
36
+
37
+ const field = target?.closest?.(`.${EDITABLE_OUTER_SELECTOR}`);
38
+ const ownField = this.view.dom.closest(`.${EDITABLE_OUTER_SELECTOR}`);
39
+
40
+ if (field && field !== ownField) {
41
+ this.hide();
42
+ }
43
+ };
44
+
45
+ this.presenterEl = window.Bridge.UI.overlay.closest("#presenter");
46
+ this.presenterEl?.addEventListener("focusin", this.focusInHandler);
47
+
48
+ // Default scrollTarget is window, but `scroll` doesn't bubble.
49
+ const scroller = this.view.dom.closest(`.${EDITABLE_OUTER_SELECTOR}`);
50
+
51
+ if (scroller) {
52
+ this.scrollTarget?.removeEventListener("scroll", this.resizeHandler);
53
+ this.scrollTarget = scroller;
54
+ this.scrollTarget.addEventListener("scroll", this.resizeHandler);
55
+ }
56
+ }
57
+
58
+ handleBlur({ event }) {
59
+ if (this.editor.isDestroyed) {
60
+ this.destroy();
61
+ return;
62
+ }
63
+
64
+ if (this.preventHide) {
65
+ this.preventHide = false;
66
+ return;
67
+ }
68
+
69
+ const focused = event?.relatedTarget;
70
+
71
+ // Focus returned to the editor.
72
+ if (focused === this.view.dom) {
73
+ return;
74
+ }
75
+
76
+ // A toolbar of this editor, or a popover/select opened from one.
77
+ if (
78
+ focused instanceof Element &&
79
+ (focused.closest(`.${style.bubbleMenu}`) ||
80
+ focused.closest(POPPER_CONTENT_SELECTOR))
81
+ ) {
82
+ return;
83
+ }
84
+
85
+ this.hide();
86
+ }
87
+
14
88
  show() {
89
+ // Prevent element being re-appended when it's already here.
90
+ if (this.isVisible) {
91
+ return;
92
+ }
93
+
15
94
  this.element.style.visibility = "visible";
16
95
  this.element.style.opacity = "1";
96
+
97
+ // Re-attach so the toolbar is the overlay's last child while visible.
98
+ // Appending to the element's parent instead of `Bridge.UI.overlay` keeps
99
+ // this a move within one parent. OverlayPortal owns this node, so
100
+ // re-parenting it would break React's teardown.
101
+ this.element.parentNode?.appendChild(this.element);
102
+
103
+ this.isVisible = true;
17
104
  }
18
105
 
19
106
  hide() {
107
+ if (!this.isVisible) {
108
+ return;
109
+ }
110
+
20
111
  this.element.style.visibility = "hidden";
21
112
  this.element.style.opacity = "0";
113
+ this.isVisible = false;
22
114
  }
23
115
 
24
116
  updatePosition() {
@@ -42,31 +134,26 @@ class UnscaledBubbleMenuView extends BubbleMenuView {
42
134
  const cell = (closestSelector && el.closest(closestSelector)) || dom;
43
135
  const cellRect = cell.getBoundingClientRect();
44
136
 
45
- // Content most likely appears in a scrollable area that can be masked.
46
- // maskSelector gives the opportunity to supply what to use as the the
47
- // backup hittest if content goes outside of the bounds.
48
- if (maskSelector) {
49
- const container = el.closest(maskSelector);
137
+ // The field is the scroll/clip area by default; maskSelector overrides it
138
+ // for decks that use a wrapper of their own.
139
+ const container = maskSelector
140
+ ? el.closest(maskSelector)
141
+ : el.closest(`.${EDITABLE_OUTER_SELECTOR}`);
50
142
 
51
- if (!container) {
143
+ if (!container) {
144
+ if (maskSelector) {
52
145
  console.warn(
53
146
  `BubbleMenu maskSelector '${maskSelector}' was not found in the DOM.`,
54
147
  );
55
- return cellRect;
56
148
  }
57
149
 
58
- const containerRect = container.getBoundingClientRect();
59
- return getTestRect(cellRect, containerRect);
60
- }
61
-
62
- // cell has extended beyond visible bounds, use slide article as the reference
63
- if (cellRect.top < 0 || cellRect.left < 0) {
64
- console.warn(
65
- "BubbleMenu content extends beyond visible bounds. Supply a maskSelector to TextField for a fallback hit-test rect.",
66
- );
150
+ return cellRect;
67
151
  }
68
152
 
69
- return cellRect;
153
+ // `cellRect` is the cell's full geometry even where an ancestor clips it.
154
+ // An unclipped rect attaches floating-ui's flip/shift to an off-screen
155
+ // anchor.
156
+ return getTestRect(cellRect, container.getBoundingClientRect());
70
157
  };
71
158
 
72
159
  const virtualElement = {
@@ -87,7 +174,8 @@ class UnscaledBubbleMenuView extends BubbleMenuView {
87
174
 
88
175
  destroy() {
89
176
  super.destroy();
90
- window.removeEventListener("resize", this.onResize);
177
+ window.Bridge?.Event?.off("resize", this.resizeHandler, "deck");
178
+ this.presenterEl?.removeEventListener("focusin", this.focusInHandler);
91
179
  }
92
180
  }
93
181
 
@@ -4,6 +4,5 @@
4
4
  top: 0;
5
5
  left: 0;
6
6
  width: max-content;
7
- // z-index: 9999;
8
7
  }
9
8
  }
@@ -3,7 +3,7 @@ import { Dialog } from "radix-ui";
3
3
  import style from "./InsertTokenDialog.module.scss";
4
4
  import tokenStyle from "./tiptap/token/Token.module.scss";
5
5
  import classNames from "classnames";
6
- import icons, { Close } from "../icons";
6
+ import icons, { Close } from "@livepreso/react-plugin-ui/icons";
7
7
  import { SimpleButton } from "./editor-toolbars/SimpleButton";
8
8
  import { TOKEN_TRIGGER_CHAR } from "./tiptap/token/utils";
9
9
 
@@ -1,4 +1,4 @@
1
- @import "./style.module.scss";
1
+ @import "@livepreso/react-plugin-ui/styles/placeholders.module.scss";
2
2
 
3
3
  :global(.sp-presenter-overlay) {
4
4
  .overlay {
@@ -2,8 +2,8 @@ import React, { useEffect, useState } from "react";
2
2
  import { Dialog } from "radix-ui";
3
3
  import style from "./LinkEditDialog.module.scss";
4
4
  import classNames from "classnames";
5
- import { Close } from "../icons";
6
- import { ToolbarToggle } from "./editor-toolbars/ToolbarToggle";
5
+ import { Close } from "@livepreso/react-plugin-ui/icons";
6
+ import { ToolbarToggle } from "@livepreso/react-plugin-ui/toolbar";
7
7
 
8
8
  const LinkEditDialog = ({
9
9
  icon,
@@ -1,4 +1,4 @@
1
- @import "./style.module.scss";
1
+ @import "@livepreso/react-plugin-ui/styles/placeholders.module.scss";
2
2
 
3
3
  :global(.sp-presenter-overlay) {
4
4
  .overlay {
@@ -0,0 +1,48 @@
1
+ import React from "react";
2
+
3
+ import icons from "@livepreso/react-plugin-ui/icons";
4
+ import { Select } from "@livepreso/react-plugin-ui/select";
5
+ import {
6
+ TABLE_DENSITY_SPACIOUS,
7
+ TABLE_DENSITY_NORMAL,
8
+ TABLE_DENSITY_DENSE,
9
+ } from "./tiptap/Table";
10
+
11
+ import style from "./TableDensityPicker.module.scss";
12
+
13
+ const densityIconMap = {
14
+ [TABLE_DENSITY_SPACIOUS]: icons.DensityLarge,
15
+ [TABLE_DENSITY_NORMAL]: icons.DensityMedium,
16
+ [TABLE_DENSITY_DENSE]: icons.DensitySmall,
17
+ };
18
+
19
+ const densityOptions = [
20
+ { label: "Spacious", value: TABLE_DENSITY_SPACIOUS },
21
+ { label: "Normal", value: TABLE_DENSITY_NORMAL },
22
+ { label: "Dense", value: TABLE_DENSITY_DENSE },
23
+ ];
24
+
25
+ /**
26
+ * A component that renders an icon reflecting the current table padding
27
+ * density, alongside a dropdown to change it.
28
+ *
29
+ * @param {Object} props - The component props
30
+ * @param {string} props.value - The currently active density
31
+ * @param {Function} props.onChange - Callback triggered with the newly selected density
32
+ * @returns {React.Element} An icon and dropdown for setting table density
33
+ */
34
+ export function TableDensityPicker({ value, onChange = () => {} }) {
35
+ const Icon = densityIconMap[value];
36
+
37
+ return (
38
+ <div className={style.row}>
39
+ {Icon && <Icon />}
40
+ <Select
41
+ label="Table density"
42
+ options={densityOptions}
43
+ value={value}
44
+ onValueChange={onChange}
45
+ />
46
+ </div>
47
+ );
48
+ }
@@ -1,8 +1,9 @@
1
1
  :global(.sp-presenter-overlay) {
2
- .options {
2
+ .row {
3
3
  display: flex;
4
4
  flex-direction: row;
5
- flex-wrap: wrap;
6
- width: 180px;
5
+ justify-content: center;
6
+ align-items: center;
7
+ gap: 8px;
7
8
  }
8
9
  }
@@ -25,6 +25,10 @@ export function TableToolbar({
25
25
  placement: "bottom-start",
26
26
  closestSelector: "table",
27
27
  maskSelector,
28
+ // Never flip above the field — that lands on the PrimaryToolbar. With
29
+ // no room below, shift nudges it up over the table's last rows.
30
+ flip: false,
31
+ shift: { crossAxis: true, padding: 8 },
28
32
  }}
29
33
  shouldShow={({ editor }) => {
30
34
  return editor.isFocused && editor.isActive("table");
@@ -1,10 +1,11 @@
1
1
  import React from "react";
2
2
 
3
- import icons from "../icons";
4
- import { Toolbar, Tooltip } from "radix-ui";
5
- import { ToolbarToggleGroup } from "./editor-toolbars/ToolbarToggleGroup";
6
- import toolbarBaseStyle from "./editor-toolbars/EditorToolbar.module.scss";
7
- import classNames from "classnames";
3
+ import icons from "@livepreso/react-plugin-ui/icons";
4
+ import { Tooltip } from "radix-ui";
5
+ import {
6
+ ToolbarRoot,
7
+ ToolbarToggleGroup,
8
+ } from "@livepreso/react-plugin-ui/toolbar";
8
9
 
9
10
  /**
10
11
  * A component that renders a toggle group for vertical alignment options.
@@ -16,7 +17,6 @@ import classNames from "classnames";
16
17
  * @param {string} props.value - The currently selected vertical alignment value
17
18
  * @returns {React.Element} A toolbar component containing vertical alignment toggle options
18
19
  */
19
-
20
20
  export function VerticalAlignToggle({
21
21
  id,
22
22
  className,
@@ -25,7 +25,7 @@ export function VerticalAlignToggle({
25
25
  }) {
26
26
  return (
27
27
  <Tooltip.Provider delayDuration={800} skipDelayDuration={500}>
28
- <Toolbar.Root className={classNames(toolbarBaseStyle.root, className)}>
28
+ <ToolbarRoot className={className}>
29
29
  <ToolbarToggleGroup
30
30
  key={id}
31
31
  label="Vertical alignment"
@@ -59,7 +59,7 @@ export function VerticalAlignToggle({
59
59
  }}
60
60
  defaultValue="top"
61
61
  />
62
- </Toolbar.Root>
62
+ </ToolbarRoot>
63
63
  </Tooltip.Provider>
64
64
  );
65
65
  }
@@ -1,12 +1,12 @@
1
1
  import React from "react";
2
2
  import classNames from "classnames";
3
3
 
4
- import { ColorPicker } from "./ColorPicker";
5
- import { Popover } from "../Popover";
4
+ import { ColorPickerBasic } from "@livepreso/react-plugin-ui/color-picker";
5
+ import { Popover } from "@livepreso/react-plugin-ui/popover";
6
6
  import { ChevronDownIcon } from "@radix-ui/react-icons";
7
- import { ToolbarButton } from "../editor-toolbars/ToolbarButton";
7
+ import { ToolbarButton } from "@livepreso/react-plugin-ui/toolbar";
8
+ import toolbarStyle from "@livepreso/react-plugin-ui/toolbar/toolbar.module.scss";
8
9
  import { TextColorIcon } from "./TextColorIcon";
9
- import toolbarStyle from "../editor-toolbars/EditorToolbar.module.scss";
10
10
  import style from "./ColorPickerCombo.module.scss";
11
11
 
12
12
  export function ColorPickerCombo({
@@ -33,7 +33,7 @@ export function ColorPickerCombo({
33
33
  trigger={<ChevronDownIcon disabled={disabled} />}
34
34
  disabled={disabled}
35
35
  >
36
- <ColorPicker
36
+ <ColorPickerBasic
37
37
  colors={colors}
38
38
  // null and empty string may be valid for "no color"
39
39
  value={typeof pickerValue === "undefined" ? value : pickerValue}
@@ -1,4 +1,4 @@
1
- @import "../style.module.scss";
1
+ @import "@livepreso/react-plugin-ui/styles/placeholders.module.scss";
2
2
 
3
3
  :global(.sp-presenter-overlay) {
4
4
  .container {
@@ -60,7 +60,7 @@ export function EditorMenu({
60
60
  }
61
61
 
62
62
  if (type === TOOLBAR_COMPONENT_TYPES.SUB) {
63
- const { items, renderItem } = itemsProps;
63
+ const { items, renderItem, keepOpenOnInteract } = itemsProps;
64
64
  const { isEnabled, value } = getState(id, editorState);
65
65
 
66
66
  return (
@@ -73,6 +73,7 @@ export function EditorMenu({
73
73
  renderItem={(item) =>
74
74
  renderItem(item, { editor, value, ...states })
75
75
  }
76
+ keepOpenOnInteract={keepOpenOnInteract}
76
77
  />
77
78
  );
78
79
  }
@@ -1,4 +1,4 @@
1
- @import "../style.module.scss";
1
+ @import "@livepreso/react-plugin-ui/styles/placeholders.module.scss";
2
2
 
3
3
  :global(.sp-presenter-overlay) {
4
4
  button.trigger {
@@ -1,13 +1,16 @@
1
1
  import React from "react";
2
2
  import { Toolbar, Tooltip as TooltipPrimitive } from "radix-ui";
3
3
 
4
- import { Tooltip } from "../Tooltip";
4
+ import {
5
+ ToolbarButton,
6
+ ToolbarRoot,
7
+ ToolbarToggle,
8
+ ToolbarToggleGroup,
9
+ } from "@livepreso/react-plugin-ui/toolbar";
10
+ import { Tooltip } from "@livepreso/react-plugin-ui/tooltip";
11
+ import { Popover } from "@livepreso/react-plugin-ui/popover";
5
12
  import { TOOLBAR_COMPONENT_TYPES } from "../../constants";
6
- import { Popover } from "../Popover";
7
13
  import { getState } from "./utils";
8
- import { ToolbarButton } from "./ToolbarButton";
9
- import { ToolbarToggle } from "./ToolbarToggle";
10
- import { ToolbarToggleGroup } from "./ToolbarToggleGroup";
11
14
  import style from "./EditorToolbar.module.scss";
12
15
 
13
16
  export function EditorToolbar({
@@ -20,7 +23,7 @@ export function EditorToolbar({
20
23
 
21
24
  return (
22
25
  <TooltipPrimitive.Provider delayDuration={800} skipDelayDuration={500}>
23
- <Toolbar.Root className={style.root} aria-label="Formatting options">
26
+ <ToolbarRoot aria-label="Formatting options">
24
27
  {configuration.flatMap(({ id: groupId, items = [] }, index) => [
25
28
  index !== 0 && (
26
29
  <Toolbar.Separator
@@ -140,7 +143,7 @@ export function EditorToolbar({
140
143
  })}
141
144
  </div>,
142
145
  ])}
143
- </Toolbar.Root>
146
+ </ToolbarRoot>
144
147
  </TooltipPrimitive.Provider>
145
148
  );
146
149
  }
@@ -1,75 +1,18 @@
1
- @import "../style.module.scss";
1
+ @import "@livepreso/react-plugin-ui/styles/placeholders.module.scss";
2
2
 
3
+ // .root, .item, and .toggle-group moved to
4
+ // @livepreso/react-plugin-ui/toolbar (ToolbarRoot/ToolbarButton/
5
+ // ToolbarToggle/ToolbarToggleGroup now own that styling). What's left here is
6
+ // specific to this toolbar's own layout, not to an individual item's look.
3
7
  :global(.sp-presenter-overlay) {
4
- .root {
5
- @extend %root;
6
- padding: 6px;
7
- // min-width: 100%;
8
- // min-width: 0;
9
- // min-height: 0;
8
+ .item-group {
10
9
  display: flex;
11
- flex-wrap: wrap;
10
+ flex-direction: row;
12
11
  align-items: center;
13
- row-gap: 8px;
14
-
15
- // Loz: gets rid of the forced height applied to spans
16
- // I don't like it...
17
- > span {
18
- line-height: 0;
19
- }
20
-
21
- .item-group {
22
- display: flex;
23
- flex-direction: row;
24
- align-items: center;
25
- height: $item-height;
26
- }
27
-
28
- .item {
29
- @extend %item;
30
- flex: 0 0 auto;
31
- height: $item-height;
32
- padding: 0 5px;
33
- margin: 0 2px;
34
- border-radius: 4px;
35
- display: inline-flex;
36
- align-items: center;
37
- justify-content: center;
38
-
39
- &:hover {
40
- @extend %hover;
41
- }
42
-
43
- &:focus {
44
- @extend %focus;
45
- }
46
-
47
- &.toggle {
48
- &[data-state="on"] {
49
- @extend %active;
50
- }
51
- }
52
-
53
- &[data-disabled],
54
- &[disabled] {
55
- @extend %disabled;
56
- }
57
- }
58
-
59
- .toggle-group {
60
- display: flex;
61
- align-items: center;
62
- justify-content: center;
63
-
64
- // Loz: gets rid of the forced height applied to spans
65
- // I don't like it...
66
- > span {
67
- line-height: 0;
68
- }
69
- }
12
+ height: $item-height;
13
+ }
70
14
 
71
- .separator {
72
- @extend %separator-vertical;
73
- }
15
+ .separator {
16
+ @extend %separator-vertical;
74
17
  }
75
18
  }
@@ -1,4 +1,4 @@
1
- @import "../style.module.scss";
1
+ @import "@livepreso/react-plugin-ui/styles/placeholders.module.scss";
2
2
 
3
3
  :global(.sp-presenter-overlay) {
4
4
  .button {