@livepreso/react-plugin-textfield 0.1.3 → 0.2.1

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.
@@ -0,0 +1,28 @@
1
+ @import "../../../variables.scss";
2
+
3
+ .token,
4
+ :global(.sp-presenter-overlay) .token {
5
+ position: relative;
6
+ // wanted this to be var(--brand-primary-light)
7
+ // but the branding definitions do not extend into the sp-presenter-overlay scope
8
+ background-color: $active-color;
9
+ color: $toolbar-color;
10
+ font-size: 0.9em;
11
+ line-height: 1em;
12
+ border-radius: 0.8rem;
13
+ box-decoration-break: clone;
14
+ padding: 0.2em 0.4em;
15
+ cursor: pointer;
16
+
17
+ // Hit area
18
+ &:after {
19
+ content: "";
20
+ position: absolute;
21
+ inset: -5px;
22
+ }
23
+
24
+ // zero-width space to prevent collapse when empty
25
+ &::after {
26
+ content: "\200B";
27
+ }
28
+ }
@@ -0,0 +1,93 @@
1
+ import React, {
2
+ forwardRef,
3
+ useEffect,
4
+ useImperativeHandle,
5
+ useState,
6
+ } from "react";
7
+ import classNames from "classnames";
8
+ import style from "./TokenList.module.scss";
9
+ import buttonStyle from "../../editor-toolbars/SimpleButton.module.scss";
10
+ import InsertTokenDialog from "../../InsertTokenDialog";
11
+ import { Separator } from "radix-ui";
12
+
13
+ // the UI associated with the suggestion dropdown
14
+ export const TokenList = forwardRef(
15
+ ({ items, choices, command }, forwardedRef) => {
16
+ const [selectedIndex, setSelectedIndex] = useState(0);
17
+
18
+ const selectItem = (index) => {
19
+ const item = items[index];
20
+
21
+ if (item) {
22
+ command({ id: item.id, label: item.label });
23
+ }
24
+ };
25
+
26
+ const upHandler = () => {
27
+ setSelectedIndex((selectedIndex + items.length - 1) % items.length);
28
+ };
29
+
30
+ const downHandler = () => {
31
+ setSelectedIndex((selectedIndex + 1) % items.length);
32
+ };
33
+
34
+ const enterHandler = () => {
35
+ selectItem(selectedIndex);
36
+ };
37
+
38
+ useEffect(() => setSelectedIndex(0), [items]);
39
+
40
+ useImperativeHandle(forwardedRef, () => ({
41
+ onKeyDown: ({ event }) => {
42
+ if (event.key === "ArrowUp") {
43
+ upHandler();
44
+ return true;
45
+ }
46
+
47
+ if (event.key === "ArrowDown") {
48
+ downHandler();
49
+ return true;
50
+ }
51
+
52
+ if (event.key === "Enter") {
53
+ enterHandler();
54
+ return true;
55
+ }
56
+ return false;
57
+ },
58
+ }));
59
+
60
+ return (
61
+ <div
62
+ className={classNames(style.root, "interactive")}
63
+ data-companywide-interactive
64
+ ref={forwardedRef}
65
+ >
66
+ <div className={style.tokenPopup}>
67
+ <div className={style.dropdownMenu}>
68
+ {items.length ? (
69
+ items.map(({ id, label }, index) => (
70
+ <button
71
+ className={classNames(buttonStyle.button, style.suggestion, {
72
+ [style.isSelected]: index === selectedIndex,
73
+ })}
74
+ key={id}
75
+ onClick={() => selectItem(index)}
76
+ >
77
+ {label}
78
+ </button>
79
+ ))
80
+ ) : (
81
+ <div className={style.item}>No result</div>
82
+ )}
83
+ </div>
84
+ <Separator.Root className={style.separator} />
85
+ <InsertTokenDialog
86
+ tokens={choices}
87
+ onChange={(token) => command(token)}
88
+ />
89
+ </div>
90
+ </div>
91
+ );
92
+ },
93
+ );
@@ -0,0 +1,58 @@
1
+ @import "../../style.module.scss";
2
+
3
+ :global(.sp-presenter-overlay) {
4
+ .root {
5
+ @extend %root;
6
+
7
+ .token-popup {
8
+ z-index: 1000;
9
+ background: var(--white);
10
+ display: flex;
11
+ flex-direction: column;
12
+ }
13
+
14
+ /* Dropdown menu */
15
+ .dropdown-menu {
16
+ display: flex;
17
+ flex-direction: column;
18
+ overflow: auto;
19
+ position: relative;
20
+ }
21
+
22
+ .separator {
23
+ @extend %separator-horizontal;
24
+ flex: none;
25
+ }
26
+
27
+ .button {
28
+ @extend %item-vertical;
29
+ align-items: center;
30
+ background-color: transparent;
31
+ display: flex;
32
+ text-align: left;
33
+ width: 100%;
34
+ border-radius: none;
35
+
36
+ &:first-child {
37
+ padding-top: 8px;
38
+ }
39
+
40
+ &:last-child {
41
+ padding-bottom: 8px;
42
+ }
43
+ }
44
+
45
+ .suggestion {
46
+ padding-left: 12px;
47
+
48
+ &:hover,
49
+ &:hover.is-selected {
50
+ background-color: var(--sp-toolbar-hover-color);
51
+ }
52
+
53
+ &.is-selected {
54
+ background-color: var(--sp-toolbar-hover-color);
55
+ }
56
+ }
57
+ }
58
+ }
@@ -0,0 +1,92 @@
1
+ // modified from http://github.com/ueberdosis/tiptap/blob/main/demos/src/Nodes/Mention/React/suggestion.js
2
+ // the output of the function is a configuration object for the [Suggestion engine](https://tiptap.dev/docs/editor/api/utilities/suggestion)
3
+ // that Tiptap uses to drive the mention / Token plugin's output
4
+
5
+ import { computePosition, flip, shift } from "@floating-ui/react-dom";
6
+ import { posToDOMRect, ReactRenderer } from "@tiptap/react";
7
+ import { TokenList } from "./TokenList";
8
+
9
+ export const TOKEN_TRIGGER_CHAR = "@";
10
+
11
+ const updatePosition = (editor, element) => {
12
+ const virtualElement = {
13
+ getBoundingClientRect: () =>
14
+ posToDOMRect(
15
+ editor.view,
16
+ editor.state.selection.from,
17
+ editor.state.selection.to,
18
+ ),
19
+ };
20
+
21
+ computePosition(virtualElement, element, {
22
+ placement: "bottom-start",
23
+ strategy: "absolute",
24
+ middleware: [shift(), flip()],
25
+ }).then(({ x, y, strategy }) => {
26
+ element.style.width = "max-content";
27
+ element.style.position = strategy;
28
+ element.style.left = `${x}px`;
29
+ element.style.top = `${y}px`;
30
+ });
31
+ };
32
+
33
+ // TODO wrap this in a useMemo hook or similar to avoid unnecessary instantiations of Fuse
34
+ export function generateSuggestionConfiguration({ tokens = [], fuse }) {
35
+ return {
36
+ char: TOKEN_TRIGGER_CHAR,
37
+ items: ({ query }) => {
38
+ if (query === "") return tokens.slice(0, 5);
39
+ return fuse.search(query, { limit: 5 }).map((r) => r.item);
40
+ },
41
+ // this is a cached value for use in
42
+ choices: tokens,
43
+ // Disable UI if editor is not in editable mode or another condition is met
44
+ allow: ({ editor, state, range }) => editor.isEditable && tokens.length > 0,
45
+ render: () => {
46
+ let component;
47
+ return {
48
+ onStart: (props) => {
49
+ component = new ReactRenderer(TokenList, {
50
+ props: { ...props, choices: tokens },
51
+ editor: props.editor,
52
+ });
53
+
54
+ if (!props.clientRect) {
55
+ return;
56
+ }
57
+
58
+ component.element.style.position = "absolute";
59
+
60
+ window.Bridge.UI.overlay.appendChild(component.element);
61
+
62
+ updatePosition(props.editor, component.element);
63
+ },
64
+
65
+ onUpdate(props) {
66
+ component.updateProps(props);
67
+
68
+ if (!props.clientRect) {
69
+ return;
70
+ }
71
+
72
+ updatePosition(props.editor, component.element);
73
+ },
74
+
75
+ onKeyDown(props) {
76
+ if (props.event.key === "Escape") {
77
+ component.destroy();
78
+
79
+ return true;
80
+ }
81
+
82
+ return component.ref?.onKeyDown(props);
83
+ },
84
+
85
+ onExit() {
86
+ component.element.remove();
87
+ component.destroy();
88
+ },
89
+ };
90
+ },
91
+ };
92
+ }
@@ -4,13 +4,23 @@ import {
4
4
  TABLE_TOOLBAR_IDS,
5
5
  } from "../constants";
6
6
 
7
- const generateGroup = (id, { label = null, items = [], options = {} } = {}) => {
7
+ const generateGroup = (
8
+ id,
9
+ { label = null, items: itemsConfig = [], options = {} } = {},
10
+ ) => {
11
+ // a given generator can return null
12
+ // if the item will not funciton with the supplied options
13
+ const items = itemsConfig
14
+ .map((generator) => generator(options))
15
+ .filter(Boolean);
16
+
17
+ // if, having run the generators, the group has no items, return null
8
18
  if (items.length === 0) return null;
9
19
 
10
20
  return {
11
21
  id,
12
22
  label,
13
- items: items.map((generator) => generator(options)),
23
+ items,
14
24
  };
15
25
  };
16
26
 
@@ -75,10 +85,12 @@ export const generateToolbarConfiguration = ({
75
85
  itemGenerators = {},
76
86
  textStyles = [],
77
87
  colors = [],
88
+ tokens = [],
78
89
  } = {}) => {
79
90
  const options = {
80
91
  textStyles,
81
92
  colors,
93
+ tokens,
82
94
  };
83
95
 
84
96
  const generateItem = (item) => {
@@ -1,6 +1,6 @@
1
1
  import { tableItemGenerators } from "./table-toolbar-configuration";
2
2
  import { generateToolbarConfiguration } from "./generate-toolbar-configuration";
3
- import { TABLE, TOOLBAR_SCOPES } from "../constants";
3
+ import { TABLE, TOKEN, TOOLBAR_SCOPES } from "../constants";
4
4
  import { primaryItemGenerators } from "./toolbar-configuration";
5
5
 
6
6
  const testUniqueIds = (options) => {
@@ -26,9 +26,11 @@ export const generateToolbarOptions = ({
26
26
  tableToolbarConfig = [],
27
27
  textStyles = [],
28
28
  colors = [],
29
+ tokens = [],
29
30
  } = {}) => {
30
31
  const includeTableEditor = toolbarConfig.includes(TABLE);
31
- const options = { textStyles, colors };
32
+ const includeToken = toolbarConfig.includes(TOKEN) && tokens.length > 0;
33
+ const options = { textStyles, colors, tokens: includeToken ? tokens : [] };
32
34
 
33
35
  const primaryOptions = generateToolbarConfiguration({
34
36
  toolbar: toolbarConfig,
@@ -23,6 +23,7 @@ import LinkEditDialog from "../components/LinkEditDialog";
23
23
  import { Gapcursor } from "@tiptap/extensions";
24
24
  import { ColorPickerCombo } from "../components/color-picker/ColorPickerCombo";
25
25
  import { TableCreatorCombo } from "../components/table-creator/TableCreatorCombo";
26
+ import { TOKEN_TRIGGER_CHAR } from "../components/tiptap/token/utils";
26
27
 
27
28
  function generateTextStyleTest(textStyles) {
28
29
  return (editor) => {
@@ -283,6 +284,19 @@ const removeLinkButton = () => ({
283
284
  enabled: (editor) => editor.isActive("link"),
284
285
  icon: <icons.LinkOff />,
285
286
  });
287
+ const insertTokenButton = ({ tokens = [] }) =>
288
+ tokens.length
289
+ ? {
290
+ id: PRIMARY_TOOLBAR_IDS.INSERT_TOKEN,
291
+ label: "Insert token",
292
+ type: TOOLBAR_COMPONENT_TYPES.BUTTON,
293
+ icon: <icons.WandStars />,
294
+ // Token extension is always enabled, so nothing to load here
295
+ extensions: [],
296
+ command: (editor) =>
297
+ editor.chain().focus().insertContent(TOKEN_TRIGGER_CHAR).run(),
298
+ }
299
+ : null;
286
300
 
287
301
  const clearFormattingButton = () => ({
288
302
  id: PRIMARY_TOOLBAR_IDS.CLEAR_FORMATTING,
@@ -333,6 +347,7 @@ export const primaryItemGenerators = {
333
347
  [PRIMARY_TOOLBAR_IDS.ORDERED_LIST]: numberedListButton,
334
348
  [PRIMARY_TOOLBAR_IDS.INSERT_LINK]: addLinkButton,
335
349
  [PRIMARY_TOOLBAR_IDS.REMOVE_LINK]: removeLinkButton,
350
+ [PRIMARY_TOOLBAR_IDS.INSERT_TOKEN]: insertTokenButton,
336
351
  [PRIMARY_TOOLBAR_IDS.CLEAR_FORMATTING]: clearFormattingButton,
337
352
  [PRIMARY_TOOLBAR_IDS.INSERT_TABLE]: insertTableButton,
338
353
  };
package/constants.js CHANGED
@@ -9,6 +9,10 @@ export const TOOLBAR_COMPONENT_TYPES = Object.freeze({
9
9
  CUSTOM: "custom",
10
10
  });
11
11
 
12
+ export const NODE_TYPES = Object.freeze({
13
+ TOKEN: "token",
14
+ });
15
+
12
16
  /**
13
17
  * What a toolbar option can affect, and where they will appear in the editor.
14
18
  *
@@ -30,6 +34,7 @@ export const BLOCK = "block";
30
34
  export const TEXT_STYLE = "text-style";
31
35
  export const ALIGNMENT = "alignment";
32
36
  export const LINK = "link";
37
+ export const TOKEN = "token";
33
38
  export const LIST = "list";
34
39
  export const CLEAR_FORMATTING = "clear-formatting";
35
40
  export const TABLE = "table";
@@ -48,6 +53,7 @@ export const PRIMARY_TOOLBAR_IDS = Object.freeze({
48
53
  TEXT_ALIGN: "textAlign",
49
54
  INSERT_LINK: "insertLink",
50
55
  REMOVE_LINK: "unlink",
56
+ INSERT_TOKEN: "insertToken",
51
57
  ORDERED_LIST: "orderedList",
52
58
  UNORDERED_LIST: "unorderedList",
53
59
  INSERT_TABLE: "insertTable",
@@ -107,6 +113,10 @@ const PRIMARY_TOOLBAR_GROUPS = Object.freeze({
107
113
  label: "Links",
108
114
  items: [PRIMARY_TOOLBAR_IDS.INSERT_LINK, PRIMARY_TOOLBAR_IDS.REMOVE_LINK],
109
115
  },
116
+ [TOKEN]: {
117
+ label: "Tokens",
118
+ items: [PRIMARY_TOOLBAR_IDS.INSERT_TOKEN],
119
+ },
110
120
  [TABLE]: { label: "Insert table", items: [PRIMARY_TOOLBAR_IDS.INSERT_TABLE] },
111
121
  [CLEAR_FORMATTING]: {
112
122
  label: "Clear formatting",
@@ -170,6 +180,7 @@ export const COMPLETE_TOOLBAR_CONFIG = [
170
180
  TEXT_STYLE,
171
181
  ALIGNMENT,
172
182
  LINK,
183
+ TOKEN,
173
184
  TABLE,
174
185
  CLEAR_FORMATTING,
175
186
  ];
@@ -185,7 +196,12 @@ export const DEFAULT_TABLE_TOOLBAR_CONFIG = [...COMPLETE_TABLE_TOOLBAR_CONFIG];
185
196
 
186
197
  // Alternative toolbar configurations
187
198
  export const MINIMAL_TOOLBAR_CONFIG = [UNDO_REDO];
188
- export const SIMPLE_TOOLBAR_CONFIG = [UNDO_REDO, TEXT_STYLE, CLEAR_FORMATTING];
199
+ export const SIMPLE_TOOLBAR_CONFIG = [
200
+ UNDO_REDO,
201
+ TEXT_STYLE,
202
+ TOKEN,
203
+ CLEAR_FORMATTING,
204
+ ];
189
205
 
190
206
  export const SIMPLE_TABLE_TOOLBAR_CONFIG = [
191
207
  DELETE_TABLE,
@@ -196,3 +212,9 @@ export const SIMPLE_TABLE_TOOLBAR_CONFIG = [
196
212
  TABLE_TOOLBAR_IDS.REMOVE_ROW,
197
213
  ],
198
214
  ];
215
+
216
+ // these are passed to the editable so it knows what mode it is in -
217
+ // useful for plugins that behave differently in different modes
218
+ export const MODE_CMS = "cms";
219
+ export const MODE_PREP = "prep";
220
+ export const MODE_UNMANAGED = "unmanaged";
@@ -0,0 +1,13 @@
1
+ import * as React from "react";
2
+ const HelpCenter = (props) => (
3
+ <svg
4
+ xmlns="http://www.w3.org/2000/svg"
5
+ height="24px"
6
+ viewBox="0 -960 960 960"
7
+ width="24px"
8
+ {...props}
9
+ >
10
+ <path d="M480.77-257.31q17.15 0 28.96-11.81 11.81-11.8 11.81-28.96 0-17.15-11.81-28.96-11.81-11.81-28.96-11.81t-28.96 11.81Q440-315.23 440-298.08q0 17.16 11.81 28.96 11.81 11.81 28.96 11.81Zm-28.31-143.23h56.31q.77-31.38 8.96-47.81 8.19-16.42 33.04-41.27 31.92-31.92 45.65-54.26 13.73-22.35 13.73-50.81 0-49.92-34.07-80.5-34.08-30.58-87.77-30.58-48.85 0-83.5 24.89-34.66 24.88-49.27 64.8l51.38 20.62q8.54-25.46 28.39-41.58 19.84-16.11 49.77-16.11 32.38 0 50.57 17.57 18.2 17.58 18.2 42.73 0 18.54-11 36.39t-33.93 38.54q-32.61 29.38-44.53 54.54-11.93 25.15-11.93 62.84ZM140-140v-680h680v680H140Zm60-60h560v-560H200v560Zm0 0v-560 560Z" />
11
+ </svg>
12
+ );
13
+ export default HelpCenter;
@@ -0,0 +1,13 @@
1
+ import * as React from "react";
2
+ const MoreVert = (props) => (
3
+ <svg
4
+ xmlns="http://www.w3.org/2000/svg"
5
+ height="24px"
6
+ viewBox="0 -960 960 960"
7
+ width="24px"
8
+ {...props}
9
+ >
10
+ <path d="M480-189.23q-24.75 0-42.37-17.63Q420-224.48 420-249.23q0-24.75 17.63-42.38 17.62-17.62 42.37-17.62 24.75 0 42.37 17.62Q540-273.98 540-249.23q0 24.75-17.63 42.37-17.62 17.63-42.37 17.63ZM480-420q-24.75 0-42.37-17.63Q420-455.25 420-480q0-24.75 17.63-42.37Q455.25-540 480-540q24.75 0 42.37 17.63Q540-504.75 540-480q0 24.75-17.63 42.37Q504.75-420 480-420Zm0-230.77q-24.75 0-42.37-17.62Q420-686.02 420-710.77q0-24.75 17.63-42.37 17.62-17.63 42.37-17.63 24.75 0 42.37 17.63Q540-735.52 540-710.77q0 24.75-17.63 42.38-17.62 17.62-42.37 17.62Z" />
11
+ </svg>
12
+ );
13
+ export default MoreVert;
@@ -0,0 +1,13 @@
1
+ import * as React from "react";
2
+ const WandStars = (props) => (
3
+ <svg
4
+ xmlns="http://www.w3.org/2000/svg"
5
+ height="24px"
6
+ viewBox="0 -960 960 960"
7
+ width="24px"
8
+ {...props}
9
+ >
10
+ <path d="M182.15-140 140-182.15 445.23-488l-174.84-43.08L453-644.46 437.16-860l164.76 139.08L801-802l-80.08 199.69L860-438.16 644.46-453l-114 182.61L487-445.23 182.15-140Zm23.62-523.85L140-729.62l65.77-65.76 65.77 65.76-65.77 65.77ZM555-422.61l57.23-93.24 109.54 8.16L651-591.77l41.16-101.39L590.77-652l-84.08-70.16 8.16 108.93L422-555.38l106.15 26.23L555-422.61ZM729.62-140l-65.77-65.77 65.77-65.77 65.76 65.77L729.62-140ZM572.08-572.69Z" />
11
+ </svg>
12
+ );
13
+ export default WandStars;
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M480.77-257.31q17.15 0 28.96-11.81 11.81-11.8 11.81-28.96 0-17.15-11.81-28.96-11.81-11.81-28.96-11.81t-28.96 11.81Q440-315.23 440-298.08q0 17.16 11.81 28.96 11.81 11.81 28.96 11.81Zm-28.31-143.23h56.31q.77-31.38 8.96-47.81 8.19-16.42 33.04-41.27 31.92-31.92 45.65-54.26 13.73-22.35 13.73-50.81 0-49.92-34.07-80.5-34.08-30.58-87.77-30.58-48.85 0-83.5 24.89-34.66 24.88-49.27 64.8l51.38 20.62q8.54-25.46 28.39-41.58 19.84-16.11 49.77-16.11 32.38 0 50.57 17.57 18.2 17.58 18.2 42.73 0 18.54-11 36.39t-33.93 38.54q-32.61 29.38-44.53 54.54-11.93 25.15-11.93 62.84ZM140-140v-680h680v680H140Zm60-60h560v-560H200v560Zm0 0v-560 560Z"/></svg>
package/icons/index.js CHANGED
@@ -41,12 +41,14 @@ import FormatListBulleted from "./FormatListBulleted.js";
41
41
  import FormatListNumbered from "./FormatListNumbered.js";
42
42
  import FormatStrikethrough from "./FormatStrikethrough.js";
43
43
  import FormatUnderlined from "./FormatUnderlined.js";
44
+ import HelpCenter from "./HelpCenter.js";
44
45
  import HorizontalRule from "./HorizontalRule.js";
45
46
  import Italic from "./Italic.js";
46
47
  import ItalicIcon from "./ItalicIcon.js";
47
48
  import Link from "./Link.js";
48
49
  import LinkOff from "./LinkOff.js";
49
50
  import MergeCells from "./MergeCells.js";
51
+ import MoreVert from "./MoreVert.js";
50
52
  import Redo from "./Redo.js";
51
53
  import RemoveColumnOutline from "./RemoveColumnOutline.js";
52
54
  import RemoveRowOutline from "./RemoveRowOutline.js";
@@ -59,6 +61,7 @@ import Undo from "./Undo.js";
59
61
  import VerticalAlignBottom from "./VerticalAlignBottom.js";
60
62
  import VerticalAlignCenter from "./VerticalAlignCenter.js";
61
63
  import VerticalAlignTop from "./VerticalAlignTop.js";
64
+ import WandStars from "./WandStars.js";
62
65
 
63
66
  export const MATERIAL_SVG_PARAMS = {
64
67
  style: "sharp",
@@ -101,19 +104,20 @@ export {
101
104
  FormatBold,
102
105
  FormatClear,
103
106
  FormatColorFill,
104
- FormatColorText,
105
107
  FormatItalic,
106
108
  FormatLineSpacing,
107
109
  FormatListBulleted,
108
110
  FormatListNumbered,
109
111
  FormatStrikethrough,
110
112
  FormatUnderlined,
113
+ HelpCenter,
111
114
  HorizontalRule,
112
115
  Italic,
113
116
  ItalicIcon,
114
117
  Link,
115
118
  LinkOff,
116
119
  MergeCells,
120
+ MoreVert,
117
121
  Redo,
118
122
  RemoveColumnOutline,
119
123
  RemoveRowOutline,
@@ -126,6 +130,7 @@ export {
126
130
  VerticalAlignBottom,
127
131
  VerticalAlignCenter,
128
132
  VerticalAlignTop,
133
+ WandStars,
129
134
  };
130
135
 
131
136
  export default {
@@ -170,12 +175,14 @@ export default {
170
175
  FormatListNumbered,
171
176
  FormatStrikethrough,
172
177
  FormatUnderlined,
178
+ HelpCenter,
173
179
  HorizontalRule,
174
180
  Italic,
175
181
  ItalicIcon,
176
182
  Link,
177
183
  LinkOff,
178
184
  MergeCells,
185
+ MoreVert,
179
186
  Redo,
180
187
  RemoveColumnOutline,
181
188
  RemoveRowOutline,
@@ -188,4 +195,5 @@ export default {
188
195
  VerticalAlignBottom,
189
196
  VerticalAlignCenter,
190
197
  VerticalAlignTop,
198
+ WandStars,
191
199
  };
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M480-189.23q-24.75 0-42.37-17.63Q420-224.48 420-249.23q0-24.75 17.63-42.38 17.62-17.62 42.37-17.62 24.75 0 42.37 17.62Q540-273.98 540-249.23q0 24.75-17.63 42.37-17.62 17.63-42.37 17.63ZM480-420q-24.75 0-42.37-17.63Q420-455.25 420-480q0-24.75 17.63-42.37Q455.25-540 480-540q24.75 0 42.37 17.63Q540-504.75 540-480q0 24.75-17.63 42.37Q504.75-420 480-420Zm0-230.77q-24.75 0-42.37-17.62Q420-686.02 420-710.77q0-24.75 17.63-42.37 17.62-17.63 42.37-17.63 24.75 0 42.37 17.63Q540-735.52 540-710.77q0 24.75-17.63 42.38-17.62 17.62-42.37 17.62Z"/></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M182.15-140 140-182.15 445.23-488l-174.84-43.08L453-644.46 437.16-860l164.76 139.08L801-802l-80.08 199.69L860-438.16 644.46-453l-114 182.61L487-445.23 182.15-140Zm23.62-523.85L140-729.62l65.77-65.76 65.77 65.76-65.77 65.77ZM555-422.61l57.23-93.24 109.54 8.16L651-591.77l41.16-101.39L590.77-652l-84.08-70.16 8.16 108.93L422-555.38l106.15 26.23L555-422.61ZM729.62-140l-65.77-65.77 65.77-65.77 65.76 65.77L729.62-140ZM572.08-572.69Z"/></svg>