5htp-core 0.6.0-73 → 0.6.0-79

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.
@@ -5,8 +5,9 @@
5
5
  // Npm
6
6
  import React from 'react';
7
7
  import { JSX, ComponentChild } from 'preact';
8
- import { Button, Menu, MenuProps } from '@mantine/core';
9
- import { Props as ButtonProps } from './Button';
8
+ import { Menu, MenuProps } from '@mantine/core';
9
+ import Button, { Props as ButtonProps } from './Button';
10
+ import Popover, { Props as PopoverProps } from './containers/Popover';
10
11
 
11
12
  // Core libs
12
13
  import { useMantineInput, InputBaseProps } from './utils';
@@ -26,6 +27,21 @@ export default ({
26
27
  label, children,
27
28
  menuProps = {}, size, icon, ...btnProps
28
29
  }: Props) => {
30
+ return (
31
+ <Popover content={(
32
+ <div class="card bg white col menu">
33
+ {children}
34
+ </div>
35
+ )}>
36
+ <Button {...btnProps}
37
+ size={size}
38
+ suffix={<i src="angle-down" />}
39
+ >
40
+ {icon && <i src={icon} />}
41
+ {label}
42
+ </Button>
43
+ </Popover>
44
+ )
29
45
  return (
30
46
  <Menu {...menuProps} size={size}>
31
47
  <Menu.Target>
@@ -111,6 +111,7 @@ export default ({ value, setValue, props }: {
111
111
  let {
112
112
  // Decoration
113
113
  title,
114
+ toolbar,
114
115
  // Actions
115
116
  preview = true
116
117
  } = props;
@@ -240,7 +241,7 @@ export default ({ value, setValue, props }: {
240
241
  theme: ExampleTheme,
241
242
  }}>
242
243
  <div className="editor-container">
243
- <ToolbarPlugin setIsLinkEditMode={setIsLinkEditMode} />
244
+ <ToolbarPlugin setIsLinkEditMode={setIsLinkEditMode} display={toolbar} />
244
245
  <div className="editor-inner">
245
246
  <RichTextPlugin
246
247
  contentEditable={
@@ -92,7 +92,7 @@ export default function ElementFormatDropdown({
92
92
  popover={{ tag: 'li' }}
93
93
  >
94
94
  {FormatOptions.map((option) => (
95
- <Button icon={isRTL ? option.iconRTL : option.icon}
95
+ <Button size="s" icon={isRTL ? option.iconRTL : option.icon}
96
96
  onClick={() => {
97
97
  if (option.value === 'indent')
98
98
  editor.dispatchCommand(INDENT_CONTENT_COMMAND, undefined);
@@ -1,10 +1,6 @@
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
- */
1
+ /*----------------------------------
2
+ - DEPENDANCES
3
+ ----------------------------------*/
8
4
 
9
5
  // Core
10
6
  import Button from '@client/components/Button';
@@ -49,6 +45,7 @@ import {
49
45
  } from '@lexical/utils';
50
46
  import {
51
47
  $createParagraphNode,
48
+ $createTextNode,
52
49
  $getNodeByKey,
53
50
  $getRoot,
54
51
  $getSelection,
@@ -94,6 +91,47 @@ import { INSERT_PAGE_BREAK } from '../plugins/PageBreakPlugin';
94
91
  import { InsertPollDialog } from '../plugins/PollPlugin';
95
92
  import { InsertTableDialog } from '../plugins/TablePlugin';
96
93
 
94
+ /*----------------------------------
95
+ - TYPES
96
+ ----------------------------------*/
97
+ export type TToolbarDisplay = {
98
+ // Default to true
99
+ blocks?: boolean,
100
+ formatting?: boolean | {
101
+ bold?: boolean,
102
+ italic?: boolean,
103
+ underline?: boolean,
104
+ code?: boolean,
105
+ link?: boolean,
106
+ },
107
+ styles?: boolean | {
108
+ strikethrough?: boolean,
109
+ subscript?: boolean,
110
+ superscript?: boolean,
111
+ clear?: boolean,
112
+ },
113
+ insert?: boolean | {
114
+ horizontalRule?: boolean,
115
+ pageBreak?: boolean,
116
+ code?: boolean,
117
+ image?: boolean,
118
+ inlineImage?: boolean,
119
+ table?: boolean,
120
+ poll?: boolean,
121
+ columns?: boolean,
122
+ stickyNote?: boolean,
123
+ collapsibleContainer?: boolean,
124
+ },
125
+ alignment?: boolean,
126
+ custom?: (
127
+ editor: LexicalEditor,
128
+ getSelection: typeof $getSelection
129
+ ) => React.JSX.Element,
130
+ }
131
+
132
+ /*----------------------------------
133
+ - UTILS
134
+ ----------------------------------*/
97
135
  function getCodeLanguageOptions(): [string, string][] {
98
136
  const options: [string, string][] = [];
99
137
 
@@ -116,16 +154,18 @@ function dropDownActiveClass(active: boolean) {
116
154
  }
117
155
  }
118
156
 
119
-
120
-
121
157
  function Divider(): React.JSX.Element {
122
158
  return <div className="divider" />;
123
159
  }
124
160
 
161
+ /*----------------------------------
162
+ - COMPONENT
163
+ ----------------------------------*/
125
164
  export default function ToolbarPlugin({
126
- setIsLinkEditMode,
165
+ setIsLinkEditMode, display
127
166
  }: {
128
167
  setIsLinkEditMode: Dispatch<boolean>;
168
+ display?: TToolbarDisplay
129
169
  }): React.JSX.Element {
130
170
 
131
171
  const { modal } = useContext();
@@ -497,7 +537,13 @@ export default function ToolbarPlugin({
497
537
 
498
538
  <Divider /> */}
499
539
 
500
- {blockTypeNames.includes(blockType) && activeEditor === editor && (
540
+ {display?.custom && display?.custom(editor, $getSelection)}
541
+
542
+ {(
543
+ blockTypeNames.includes(blockType)
544
+ &&
545
+ display?.blocks
546
+ ) && activeEditor === editor && (
501
547
  <>
502
548
  <BlockFormatDropDown
503
549
  disabled={!isEditable}
@@ -526,49 +572,48 @@ export default function ToolbarPlugin({
526
572
  ))}
527
573
  </div>
528
574
  </DropDown>
529
- ) : (
575
+ ) : display?.formatting !== false && (
530
576
  <>
531
- <Button icon="bold" size="s"
532
- disabled={!isEditable}
533
- onClick={() => {
534
- activeEditor.dispatchCommand(FORMAT_TEXT_COMMAND, 'bold');
535
- }}
536
- active={isBold}
537
- title={IS_APPLE ? 'Bold (⌘B)' : 'Bold (Ctrl+B)'}
538
- />
539
- <Button icon="italic" size="s"
540
- disabled={!isEditable}
541
- onClick={() => {
542
- activeEditor.dispatchCommand(FORMAT_TEXT_COMMAND, 'italic');
543
- }}
544
- active={isItalic}
545
- title={IS_APPLE ? 'Italic (⌘I)' : 'Italic (Ctrl+I)'}
546
- />
547
- <Button icon="underline" size="s"
548
- disabled={!isEditable}
549
- onClick={() => {
550
- activeEditor.dispatchCommand(FORMAT_TEXT_COMMAND, 'underline');
551
- }}
552
- active={isUnderline}
553
- title={IS_APPLE ? 'Underline (⌘U)' : 'Underline (Ctrl+U)'}
554
- />
577
+ {display?.formatting === true || display?.formatting?.bold !== false && (
578
+ <Button icon="bold" size="s"
579
+ disabled={!isEditable}
580
+ onClick={() => {
581
+ activeEditor.dispatchCommand(FORMAT_TEXT_COMMAND, 'bold');
582
+ }}
583
+ active={isBold}
584
+ title={IS_APPLE ? 'Bold (⌘B)' : 'Bold (Ctrl+B)'}
585
+ />
586
+ )}
587
+ {display?.formatting === true || display?.formatting?.italic !== false && (
588
+ <Button icon="italic" size="s"
589
+ disabled={!isEditable}
590
+ onClick={() => {
591
+ activeEditor.dispatchCommand(FORMAT_TEXT_COMMAND, 'italic');
592
+ }}
593
+ active={isItalic}
594
+ title={IS_APPLE ? 'Italic (⌘I)' : 'Italic (Ctrl+I)'}
595
+ />
596
+ )}
555
597
 
556
- {canViewerSeeInsertCodeButton && (
557
- <Button icon="code" size="s"
598
+ {display?.formatting === true || display?.formatting?.underline !== false && (
599
+ <Button icon="underline" size="s"
558
600
  disabled={!isEditable}
559
601
  onClick={() => {
560
- activeEditor.dispatchCommand(FORMAT_TEXT_COMMAND, 'code');
602
+ activeEditor.dispatchCommand(FORMAT_TEXT_COMMAND, 'underline');
561
603
  }}
562
- active={isCode}
563
- title="Insert code block"
604
+ active={isUnderline}
605
+ title={IS_APPLE ? 'Underline (⌘U)' : 'Underline (Ctrl+U)'}
606
+ />
607
+ )}
608
+
609
+ {display?.formatting === true || display?.formatting?.link !== false && (
610
+ <Button icon="link" size="s"
611
+ disabled={!isEditable}
612
+ onClick={insertLink}
613
+ active={isLink}
614
+ title="Insert link"
564
615
  />
565
616
  )}
566
- <Button icon="link" size="s"
567
- disabled={!isEditable}
568
- onClick={insertLink}
569
- active={isLink}
570
- title="Insert link"
571
- />
572
617
 
573
618
  {/* <DropdownColorPicker
574
619
  disabled={!isEditable}
@@ -589,52 +634,62 @@ export default function ToolbarPlugin({
589
634
  title="bg color"
590
635
  /> */}
591
636
 
592
- <DropDown popover={{ tag: 'li' }} icon="font" size="s"
593
- disabled={!isEditable}
594
- hint="Formatting options for additional text styles"
595
- >
596
-
597
- <Button icon="strikethrough" size="s"
598
- onClick={() => {
599
- activeEditor.dispatchCommand( FORMAT_TEXT_COMMAND, 'strikethrough');
600
- }}
601
- active={isStrikethrough}
602
- title="Format text with a strikethrough"
637
+ {display?.styles !== false && (
638
+ <DropDown popover={{ tag: 'li' }} icon="font" size="s"
639
+ disabled={!isEditable}
640
+ hint="Formatting options for additional text styles"
603
641
  >
604
- Strikethrough
605
- </Button>
606
642
 
607
- <Button icon="subscript" size="s"
608
- onClick={() => {
609
- activeEditor.dispatchCommand(FORMAT_TEXT_COMMAND, 'subscript');
610
- }}
611
- active={isSubscript}
612
- title="Format text with a subscript"
613
- >
614
- Subscript
615
- </Button>
643
+ {display?.styles === true || display?.styles?.strikethrough !== false && (
644
+ <Button icon="strikethrough" size="s"
645
+ onClick={() => {
646
+ activeEditor.dispatchCommand( FORMAT_TEXT_COMMAND, 'strikethrough');
647
+ }}
648
+ active={isStrikethrough}
649
+ title="Format text with a strikethrough"
650
+ >
651
+ Strikethrough
652
+ </Button>
653
+ )}
616
654
 
617
- <Button icon="superscript" size="s"
618
- onClick={() => {
619
- activeEditor.dispatchCommand(
620
- FORMAT_TEXT_COMMAND,
621
- 'superscript',
622
- );
623
- }}
624
- active={isSuperscript}
625
- title="Format text with a superscript">
626
- Superscript
627
- </Button>
655
+ {display?.styles === true || display?.styles?.subscript !== false && (
656
+ <Button icon="subscript" size="s"
657
+ onClick={() => {
658
+ activeEditor.dispatchCommand(FORMAT_TEXT_COMMAND, 'subscript');
659
+ }}
660
+ active={isSubscript}
661
+ title="Format text with a subscript"
662
+ >
663
+ Subscript
664
+ </Button>
665
+ )}
628
666
 
629
- <Button icon="empty-set" size="s"
630
- onClick={clearFormatting}
631
- title="Clear all text formatting">
632
- Clear Formatting
633
- </Button>
667
+ {display?.styles === true || display?.styles?.superscript !== false && (
668
+ <Button icon="superscript" size="s"
669
+ onClick={() => {
670
+ activeEditor.dispatchCommand(
671
+ FORMAT_TEXT_COMMAND,
672
+ 'superscript',
673
+ );
674
+ }}
675
+ active={isSuperscript}
676
+ title="Format text with a superscript">
677
+ Superscript
678
+ </Button>
679
+ )}
634
680
 
635
- </DropDown>
681
+ {display?.styles === true || display?.styles?.clear !== false && (
682
+ <Button icon="empty-set" size="s"
683
+ onClick={clearFormatting}
684
+ title="Clear all text formatting">
685
+ Clear Formatting
686
+ </Button>
687
+ )}
688
+
689
+ </DropDown>
690
+ )}
636
691
 
637
- {canViewerSeeInsertDropdown && (
692
+ {(canViewerSeeInsertDropdown && display?.insert !== false) && (
638
693
  <>
639
694
  <Divider />
640
695
  <DropDown popover={{ tag: 'li' }}
@@ -644,29 +699,48 @@ export default function ToolbarPlugin({
644
699
  hint="Insert specialized editor node"
645
700
  >
646
701
 
647
- <Button icon="horizontal-rule" size="s" onClick={() => {
648
- activeEditor.dispatchCommand( INSERT_HORIZONTAL_RULE_COMMAND, undefined, );
649
- }}>
650
- Horizontal Rule
651
- </Button>
702
+ {display?.insert === true || display?.insert?.horizontalRule !== false && (
703
+ <Button icon="horizontal-rule" size="s" onClick={() => {
704
+ activeEditor.dispatchCommand( INSERT_HORIZONTAL_RULE_COMMAND, undefined, );
705
+ }}>
706
+ Horizontal Rule
707
+ </Button>
708
+ )}
652
709
 
653
- <Button icon="page-break" size="s" onClick={() => {
654
- activeEditor.dispatchCommand(INSERT_PAGE_BREAK, undefined);
655
- }}>
656
- Page Break
657
- </Button>
710
+ {display?.insert === true || display?.insert?.pageBreak !== false && (
711
+ <Button icon="page-break" size="s" onClick={() => {
712
+ activeEditor.dispatchCommand(INSERT_PAGE_BREAK, undefined);
713
+ }}>
714
+ Page Break
715
+ </Button>
716
+ )}
658
717
 
659
- <Button icon="image" size="s" onClick={() => {
660
- modal.show('Insert Image', InsertImageDialog, { editor: activeEditor });
661
- }}>
662
- Image
663
- </Button>
718
+ {(canViewerSeeInsertCodeButton && (display?.insert === true || display?.insert?.code !== false)) && (
719
+ <Button icon="code" size="s"
720
+ disabled={!isEditable}
721
+ onClick={() => {
722
+ activeEditor.dispatchCommand(FORMAT_TEXT_COMMAND, 'code');
723
+ }}
724
+ active={isCode}
725
+ title="Insert code block"
726
+ />
727
+ )}
728
+
729
+ {display?.insert === true || display?.insert?.image !== false && (
730
+ <Button icon="image" size="s" onClick={() => {
731
+ modal.show('Insert Image', InsertImageDialog, { editor: activeEditor });
732
+ }}>
733
+ Image
734
+ </Button>
735
+ )}
664
736
 
665
- <Button icon="image" size="s" onClick={() => {
666
- modal.show('Insert Inline Image', InsertInlineImageDialog, { editor: activeEditor });
667
- }}>
668
- Inline Image
669
- </Button>
737
+ {display?.insert === true || display?.insert?.inlineImage !== false && (
738
+ <Button icon="image" size="s" onClick={() => {
739
+ modal.show('Insert Inline Image', InsertInlineImageDialog, { editor: activeEditor });
740
+ }}>
741
+ Inline Image
742
+ </Button>
743
+ )}
670
744
 
671
745
  {/* <Button
672
746
  onClick={() => {
@@ -680,24 +754,30 @@ export default function ToolbarPlugin({
680
754
  <span className="text">Excalidraw</span>
681
755
  </Button> */}
682
756
 
683
- <Button icon="table" size="s" onClick={() => {
684
- modal.show('Insert Table', InsertTableDialog, { editor: activeEditor });
685
- }}>
686
- Table
687
- </Button>
688
-
689
- <Button icon="poll" size="s" onClick={() => {
690
- modal.show('Insert Poll', InsertPollDialog, { editor: activeEditor });
691
- }}>
692
- Poll
693
- </Button>
757
+ {display?.insert === true || display?.insert?.table !== false && (
758
+ <Button icon="table" size="s" onClick={() => {
759
+ modal.show('Insert Table', InsertTableDialog, { editor: activeEditor });
760
+ }}>
761
+ Table
762
+ </Button>
763
+ )}
694
764
 
695
- <Button icon="columns" size="s" onClick={() => {
696
- modal.show('Insert Columns Layout', InsertLayoutDialog, { editor: activeEditor });
697
- }} >
698
- Columns Layout
699
- </Button>
765
+ {display?.insert === true || display?.insert?.poll !== false && (
766
+ <Button icon="poll" size="s" onClick={() => {
767
+ modal.show('Insert Poll', InsertPollDialog, { editor: activeEditor });
768
+ }}>
769
+ Poll
770
+ </Button>
771
+ )}
700
772
 
773
+ {display?.insert === true || display?.insert?.columns !== false && (
774
+ <Button icon="columns" size="s" onClick={() => {
775
+ modal.show('Insert Columns Layout', InsertLayoutDialog, { editor: activeEditor });
776
+ }} >
777
+ Columns Layout
778
+ </Button>
779
+ )}
780
+
701
781
  {/* <Button
702
782
  onClick={() => {
703
783
  modal.show('Insert Equation', (onClose) => (
@@ -712,24 +792,28 @@ export default function ToolbarPlugin({
712
792
  <span className="text">Equation</span>
713
793
  </Button> */}
714
794
 
715
- <Button icon="sticky-note" size="s" onClick={() => {
716
- editor.update(() => {
717
- const root = $getRoot();
718
- const stickyNode = $createStickyNode(0, 0);
719
- root.append(stickyNode);
720
- });
721
- }}>
722
- Sticky Note
723
- </Button>
795
+ {display?.insert === true || display?.insert?.stickyNote !== false && (
796
+ <Button icon="sticky-note" size="s" onClick={() => {
797
+ editor.update(() => {
798
+ const root = $getRoot();
799
+ const stickyNode = $createStickyNode(0, 0);
800
+ root.append(stickyNode);
801
+ });
802
+ }}>
803
+ Sticky Note
804
+ </Button>
805
+ )}
724
806
 
725
- <Button icon="caret-right" size="s" onClick={() => {
726
- editor.dispatchCommand(
727
- INSERT_COLLAPSIBLE_COMMAND,
728
- undefined,
729
- );
730
- }}>
731
- Collapsible container
732
- </Button>
807
+ {display?.insert === true || display?.insert?.collapsibleContainer !== false && (
808
+ <Button icon="caret-right" size="s" onClick={() => {
809
+ editor.dispatchCommand(
810
+ INSERT_COLLAPSIBLE_COMMAND,
811
+ undefined,
812
+ );
813
+ }}>
814
+ Collapsible container
815
+ </Button>
816
+ )}
733
817
 
734
818
  {/*EmbedConfigs.map((embedConfig) => (
735
819
  <Button
@@ -749,13 +833,17 @@ export default function ToolbarPlugin({
749
833
  )}
750
834
  </>
751
835
  )}
752
- <Divider />
753
- <ElementFormatDropdown
754
- disabled={!isEditable}
755
- value={elementFormat}
756
- editor={activeEditor}
757
- isRTL={isRTL}
758
- />
836
+
837
+ {display?.alignment !== false && <>
838
+ <Divider />
839
+ <ElementFormatDropdown
840
+ disabled={!isEditable}
841
+ value={elementFormat}
842
+ editor={activeEditor}
843
+ isRTL={isRTL}
844
+ />
845
+ </>}
846
+
759
847
  </div>
760
848
  );
761
849
  }
@@ -7,6 +7,7 @@ import React from 'react';
7
7
 
8
8
  // Core libs
9
9
  import { useInput, InputBaseProps, InputWrapper } from '../utils';
10
+ import type { TToolbarDisplay } from './ToolbarPlugin';
10
11
 
11
12
  // Special componets
12
13
  import type TEditor from './Editor';
@@ -19,6 +20,7 @@ import './style.less';
19
20
  export type Props = {
20
21
  preview?: boolean,
21
22
  title: string,
23
+ toolbar?: TToolbarDisplay
22
24
  }
23
25
 
24
26
  /*----------------------------------
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "5htp-core",
3
3
  "description": "Convenient TypeScript framework designed for Performance and Productivity.",
4
- "version": "0.6.0-73",
4
+ "version": "0.6.0-79",
5
5
  "author": "Gaetan Le Gac (https://github.com/gaetanlegac)",
6
6
  "repository": "git://github.com/gaetanlegac/5htp-core.git",
7
7
  "license": "MIT",
@@ -94,7 +94,8 @@ export function Route(options: Omit<TControllerDefinition, 'controller'> = {}) {
94
94
  export default abstract class Service<
95
95
  TConfig extends {},
96
96
  THooks extends THooksList,
97
- TApplication extends Application
97
+ TApplication extends Application,
98
+ TParent extends AnyService | Application = Application
98
99
  > {
99
100
 
100
101
  public started?: Promise<void>;
@@ -104,6 +105,7 @@ export default abstract class Service<
104
105
  public metas!: TServiceMetas;
105
106
  public bindings: string[] = []
106
107
 
108
+ public parent: TParent;
107
109
  public app: TApplication;
108
110
  public config: TConfig = {} as TConfig;
109
111
 
package/types/icons.d.ts CHANGED
@@ -1 +1 @@
1
- export type TIcones = "times"|"solid/spinner-third"|"long-arrow-right"|"sack-dollar"|"bell"|"bullseye"|"project-diagram"|"user-friends"|"eye"|"lock"|"comments"|"phone"|"chalkboard-teacher"|"rocket"|"chart-bar"|"crosshairs"|"user-circle"|"plus-circle"|"comments-alt"|"arrow-right"|"user-shield"|"shield-alt"|"chart-line"|"money-bill-wave"|"star"|"link"|"file-alt"|"long-arrow-left"|"user-plus"|"mouse-pointer"|"thumbs-up"|"dollar-sign"|"key"|"user"|"at"|"search"|"lightbulb"|"magnet"|"brands/linkedin"|"angle-up"|"angle-down"|"paper-plane"|"solid/crown"|"brands/discord"|"pen"|"plus"|"file"|"envelope"|"calendar-alt"|"clock"|"cog"|"trash"|"ellipsis-h"|"binoculars"|"times-circle"|"coins"|"angle-right"|"download"|"check"|"info-circle"|"check-circle"|"exclamation-circle"|"meh-rolling-eyes"|"arrow-left"|"bars"|"solid/star"|"solid/star-half-alt"|"regular/star"|"chevron-left"|"power-off"|"question-circle"|"plane-departure"|"brands/whatsapp"|"wind"|"play"|"minus-circle"|"external-link"|"map-marker-alt"|"arrow-to-bottom"|"broom"|"solid/check-circle"|"solid/exclamation-triangle"|"solid/times-circle"|"exclamation-triangle"|"minus"|"users"|"bug"|"comment-alt"|"solid/magic"|"briefcase"|"map-marker"|"fire"|"industry"|"calendar"|"globe"|"magic"|"building"|"graduation-cap"|"coin"|"unlink"|"bold"|"italic"|"underline"|"strikethrough"|"subscript"|"superscript"|"code"|"font"|"empty-set"|"horizontal-rule"|"page-break"|"image"|"table"|"poll"|"columns"|"sticky-note"|"caret-right"|"align-left"|"align-center"|"align-right"|"align-justify"|"indent"|"outdent"|"list-ul"|"check-square"|"h1"|"h2"|"h3"|"h4"|"list-ol"|"paragraph"|"quote-left"
1
+ export type TIcones = "times"|"solid/spinner-third"|"long-arrow-right"|"sack-dollar"|"bell"|"bullseye"|"project-diagram"|"user-friends"|"eye"|"lock"|"comments"|"phone"|"chalkboard-teacher"|"rocket"|"chart-bar"|"crosshairs"|"arrow-right"|"plus-circle"|"comments-alt"|"user-circle"|"user-plus"|"mouse-pointer"|"thumbs-up"|"dollar-sign"|"link"|"key"|"user"|"at"|"user-shield"|"shield-alt"|"chart-line"|"money-bill-wave"|"star"|"file-alt"|"long-arrow-left"|"magnet"|"paper-plane"|"plus"|"calendar-alt"|"clock"|"cog"|"trash"|"ellipsis-h"|"binoculars"|"brands/linkedin"|"search"|"lightbulb"|"angle-up"|"angle-down"|"solid/crown"|"brands/discord"|"pen"|"file"|"envelope"|"coins"|"times-circle"|"angle-right"|"download"|"check"|"info-circle"|"check-circle"|"exclamation-circle"|"meh-rolling-eyes"|"arrow-left"|"solid/star"|"solid/star-half-alt"|"regular/star"|"chevron-left"|"power-off"|"bars"|"plane-departure"|"brands/whatsapp"|"wind"|"play"|"minus-circle"|"question-circle"|"external-link"|"exclamation-triangle"|"solid/check-circle"|"solid/exclamation-triangle"|"solid/times-circle"|"broom"|"comment-alt"|"minus"|"map-marker-alt"|"arrow-to-bottom"|"users"|"bug"|"solid/magic"|"briefcase"|"map-marker"|"fire"|"magic"|"globe"|"industry"|"calendar"|"building"|"graduation-cap"|"coin"|"unlink"|"bold"|"italic"|"underline"|"strikethrough"|"subscript"|"superscript"|"code"|"font"|"empty-set"|"horizontal-rule"|"page-break"|"image"|"table"|"poll"|"columns"|"sticky-note"|"caret-right"|"align-left"|"align-center"|"align-right"|"align-justify"|"indent"|"outdent"|"list-ul"|"check-square"|"h1"|"h2"|"h3"|"h4"|"list-ol"|"paragraph"|"quote-left"