playbook_ui 16.3.0 → 16.4.0.pre.alpha.PLAY2846reactadvancedtablecalcheaderpinnedrows15356
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.
- checksums.yaml +4 -4
- data/app/pb_kits/playbook/pb_advanced_table/Components/CustomCell.tsx +17 -4
- data/app/pb_kits/playbook/pb_advanced_table/Components/TableHeaderCell.tsx +3 -1
- data/app/pb_kits/playbook/pb_advanced_table/Context/AdvancedTableContext.tsx +5 -2
- data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableActions.ts +21 -9
- data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableState.ts +5 -2
- data/app/pb_kits/playbook/pb_advanced_table/SubKits/TableHeader.tsx +9 -11
- data/app/pb_kits/playbook/pb_advanced_table/Utilities/ExpansionControlHelpers.tsx +25 -1
- data/app/pb_kits/playbook/pb_advanced_table/Utilities/RowModelUtils.ts +100 -0
- data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +65 -1
- data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +12 -2
- data/app/pb_kits/playbook/pb_advanced_table/advanced_table.html.erb +2 -2
- data/app/pb_kits/playbook/pb_advanced_table/advanced_table.rb +9 -0
- data/app/pb_kits/playbook/pb_advanced_table/advanced_table.test.jsx +109 -2
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_cascade_collapse.jsx +50 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_cascade_collapse.md +1 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pinned_rows_rails.html.erb +57 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pinned_rows_rails.md +7 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sort_parent_only.jsx +175 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sort_parent_only.md +5 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +3 -0
- data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +3 -1
- data/app/pb_kits/playbook/pb_advanced_table/index.js +130 -29
- data/app/pb_kits/playbook/pb_advanced_table/scss_partials/advanced_table_sticky_mixin.scss +6 -2
- data/app/pb_kits/playbook/pb_advanced_table/table_body.html.erb +21 -4
- data/app/pb_kits/playbook/pb_advanced_table/table_body.rb +115 -9
- data/app/pb_kits/playbook/pb_advanced_table/table_row.html.erb +3 -1
- data/app/pb_kits/playbook/pb_advanced_table/table_row.rb +12 -1
- data/app/pb_kits/playbook/pb_advanced_table/table_subrow_header.html.erb +4 -1
- data/app/pb_kits/playbook/pb_advanced_table/table_subrow_header.rb +9 -1
- data/app/pb_kits/playbook/pb_button/_button_mixins.scss +6 -1
- data/app/pb_kits/playbook/pb_button/docs/_button_full_width_rails.md +19 -0
- data/app/pb_kits/playbook/pb_button/docs/_button_full_width_react.md +23 -0
- data/app/pb_kits/playbook/pb_circle_icon_button/_circle_icon_button.scss +5 -0
- data/app/pb_kits/playbook/pb_collapsible/index.js +15 -26
- data/app/pb_kits/playbook/pb_date_picker/date_picker_helper.ts +3 -1
- data/app/pb_kits/playbook/pb_dialog/docs/_dialog_compound_components.html.erb +1 -1
- data/app/pb_kits/playbook/pb_dialog/docs/_dialog_compound_components.jsx +6 -3
- data/app/pb_kits/playbook/pb_dialog/docs/_dialog_full_height.html.erb +3 -3
- data/app/pb_kits/playbook/pb_dialog/docs/_dialog_full_height.jsx +6 -3
- data/app/pb_kits/playbook/pb_dialog/docs/_dialog_full_height_placement.html.erb +3 -3
- data/app/pb_kits/playbook/pb_dialog/docs/_dialog_full_height_placement.jsx +6 -3
- data/app/pb_kits/playbook/pb_dropdown/_dropdown.scss +3 -0
- data/app/pb_kits/playbook/pb_dropdown/_dropdown.tsx +1 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_closing_options_rails.html.erb +16 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_closing_options_rails.md +1 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_custom_event_type.html.erb +224 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_custom_event_type.md +7 -0
- data/app/pb_kits/playbook/pb_dropdown/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_dropdown/dropdown.rb +8 -1
- data/app/pb_kits/playbook/pb_dropdown/index.js +255 -46
- data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownTrigger.tsx +19 -14
- data/app/pb_kits/playbook/pb_fixed_confirmation_toast/_fixed_confirmation_toast.scss +4 -0
- data/app/pb_kits/playbook/pb_fixed_confirmation_toast/_fixed_confirmation_toast.tsx +3 -0
- data/app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_fixed_confirmation_toast_nav_margin.html.erb +46 -0
- data/app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_fixed_confirmation_toast_nav_margin.jsx +42 -0
- data/app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_fixed_confirmation_toast_nav_margin_rails.md +1 -0
- data/app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/_fixed_confirmation_toast_nav_margin_react.md +1 -0
- data/app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_fixed_confirmation_toast/docs/index.js +2 -1
- data/app/pb_kits/playbook/pb_fixed_confirmation_toast/fixed_confirmation_toast.rb +7 -1
- data/app/pb_kits/playbook/pb_icon/icon.rb +7 -1
- data/app/pb_kits/playbook/pb_list/_list_mixin.scss +4 -4
- data/app/pb_kits/playbook/pb_multi_level_select/_helper_functions.tsx +1 -1
- data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +27 -16
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_placeholder.html.erb +109 -0
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_placeholder.jsx +127 -0
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_placeholder.md +1 -0
- data/app/pb_kits/playbook/pb_multi_level_select/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_multi_level_select/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_multi_level_select/multi_level_select.rb +3 -0
- data/app/pb_kits/playbook/pb_multi_level_select/multi_level_select.test.jsx +27 -0
- data/app/pb_kits/playbook/pb_popover/docs/_popover_placement.jsx +81 -0
- data/app/pb_kits/playbook/pb_popover/docs/_popover_placement_react.md +1 -0
- data/app/pb_kits/playbook/pb_popover/docs/_popover_position.html.erb +128 -0
- data/app/pb_kits/playbook/pb_popover/docs/_popover_position_rails.md +1 -0
- data/app/pb_kits/playbook/pb_popover/docs/example.yml +2 -0
- data/app/pb_kits/playbook/pb_popover/docs/index.js +2 -1
- data/app/pb_kits/playbook/pb_rich_text_editor/_rich_text_editor.tsx +35 -134
- data/app/pb_kits/playbook/pb_rich_text_editor/_tiptap_editor.tsx +51 -0
- data/app/pb_kits/playbook/pb_rich_text_editor/_trix_editor.tsx +206 -0
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_default.jsx +56 -0
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_default.md +1 -0
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/example.yml +13 -21
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/index.js +0 -10
- data/app/pb_kits/playbook/pb_rich_text_editor/inlineFocus.ts +5 -4
- data/app/pb_kits/playbook/pb_selectable_list/_selectable_list.scss +19 -1
- data/app/pb_kits/playbook/pb_table/_table.tsx +24 -21
- data/app/pb_kits/playbook/pb_table/docs/_sections.yml +1 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant_external_filter_rails.html.erb +45 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant_external_filter_rails.md +39 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_variant_rails.md +2 -1
- data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_with_card_title_props.jsx +152 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_with_card_title_props.md +17 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_with_card_title_props_rails.html.erb +121 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_with_filter_with_card_title_props_rails.md +17 -0
- data/app/pb_kits/playbook/pb_table/docs/example.yml +3 -0
- data/app/pb_kits/playbook/pb_table/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_table/table.html.erb +17 -13
- data/app/pb_kits/playbook/pb_table/table.rb +8 -0
- data/app/pb_kits/playbook/pb_table/table.test.js +33 -0
- data/app/pb_kits/playbook/pb_textarea/_textarea.scss +4 -1
- data/app/pb_kits/playbook/pb_typeahead/_typeahead.tsx +105 -3
- data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_with_highlight.jsx +20 -8
- data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_with_highlight.md +3 -0
- data/app/pb_kits/playbook/utilities/_hover.scss +6 -3
- data/app/pb_kits/playbook/utilities/domHelpers.ts +50 -0
- data/dist/chunks/{_pb_line_graph-CKBPxTmM.js → _pb_line_graph-D6s5rymw.js} +1 -1
- data/dist/chunks/_typeahead-BNp_YiTh.js +1 -0
- data/dist/chunks/componentRegistry-DRSp5D_e.js +1 -0
- data/dist/chunks/{globalProps-DLCfJwiU.js → globalProps-Ds_6HBhX.js} +1 -1
- data/dist/chunks/lib-BaO72ugL.js +29 -0
- data/dist/chunks/vendor.js +5 -5
- data/dist/menu.yml +3 -2
- data/dist/playbook-rails-react-bindings.js +1 -1
- data/dist/playbook-rails.js +1 -1
- data/dist/playbook.css +1 -1
- data/lib/playbook/pb_forms_helper.rb +3 -0
- data/lib/playbook/version.rb +2 -2
- metadata +42 -32
- data/app/pb_kits/playbook/pb_button/docs/_button_full_width.md +0 -1
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_attributes.html.erb +0 -5
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_attributes.jsx +0 -15
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_default.html.erb +0 -1
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_focus.html.erb +0 -3
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_focus.jsx +0 -17
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_inline.html.erb +0 -6
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_inline.jsx +0 -16
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_label.jsx +0 -28
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_label.md +0 -1
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_preview.html.erb +0 -35
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_preview.jsx +0 -45
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_required_indicator.html.erb +0 -10
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_required_indicator.jsx +0 -22
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_required_indicator.md +0 -3
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_simple.html.erb +0 -1
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_simple.jsx +0 -13
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_sticky.html.erb +0 -1
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_sticky.jsx +0 -15
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_templates.html.erb +0 -115
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_templates.jsx +0 -42
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_toolbar_bottom.html.erb +0 -4
- data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_toolbar_bottom.jsx +0 -14
- data/app/pb_kits/playbook/pb_rich_text_editor/rich_text_editor.html.erb +0 -5
- data/app/pb_kits/playbook/pb_rich_text_editor/rich_text_editor.rb +0 -63
- data/dist/chunks/_typeahead-B7bktFm6.js +0 -1
- data/dist/chunks/componentRegistry-DzmmLR2x.js +0 -1
- data/dist/chunks/lib-QT_7rPYf.js +0 -29
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
<%= pb_rails("flex", props: { justify: "around", margin_bottom: "sm", orientation: "row", wrap: true }) do %>
|
|
2
|
+
<%= pb_rails("button", props: { text: "Top", variant: "secondary", id: "placement-popover-top" }) %>
|
|
3
|
+
<%= pb_rails("popover", props: {
|
|
4
|
+
close_on_click: "outside",
|
|
5
|
+
trigger_element_id: "placement-popover-top",
|
|
6
|
+
tooltip_id: "placement-tooltip-top",
|
|
7
|
+
position: "top",
|
|
8
|
+
offset: true
|
|
9
|
+
}) do %>
|
|
10
|
+
Popover: top
|
|
11
|
+
<% end %>
|
|
12
|
+
<%= pb_rails("button", props: { text: "Top start", variant: "secondary", id: "placement-popover-top-start" }) %>
|
|
13
|
+
<%= pb_rails("popover", props: {
|
|
14
|
+
close_on_click: "outside",
|
|
15
|
+
trigger_element_id: "placement-popover-top-start",
|
|
16
|
+
tooltip_id: "placement-tooltip-top-start",
|
|
17
|
+
position: "top-start",
|
|
18
|
+
offset: true
|
|
19
|
+
}) do %>
|
|
20
|
+
Popover: top start
|
|
21
|
+
<% end %>
|
|
22
|
+
<%= pb_rails("button", props: { text: "Top end", variant: "secondary", id: "placement-popover-top-end" }) %>
|
|
23
|
+
<%= pb_rails("popover", props: {
|
|
24
|
+
close_on_click: "outside",
|
|
25
|
+
trigger_element_id: "placement-popover-top-end",
|
|
26
|
+
tooltip_id: "placement-tooltip-top-end",
|
|
27
|
+
position: "top-end",
|
|
28
|
+
offset: true
|
|
29
|
+
}) do %>
|
|
30
|
+
Popover: top end
|
|
31
|
+
<% end %>
|
|
32
|
+
<% end %>
|
|
33
|
+
<%= pb_rails("flex", props: { justify: "around", margin_bottom: "sm", orientation: "row", wrap: true }) do %>
|
|
34
|
+
<%= pb_rails("button", props: { text: "Bottom", variant: "secondary", id: "placement-popover-bottom" }) %>
|
|
35
|
+
<%= pb_rails("popover", props: {
|
|
36
|
+
close_on_click: "outside",
|
|
37
|
+
trigger_element_id: "placement-popover-bottom",
|
|
38
|
+
tooltip_id: "placement-tooltip-bottom",
|
|
39
|
+
position: "bottom",
|
|
40
|
+
offset: true
|
|
41
|
+
}) do %>
|
|
42
|
+
Popover: bottom
|
|
43
|
+
<% end %>
|
|
44
|
+
<%= pb_rails("button", props: { text: "Bottom start", variant: "secondary", id: "placement-popover-bottom-start" }) %>
|
|
45
|
+
<%= pb_rails("popover", props: {
|
|
46
|
+
close_on_click: "outside",
|
|
47
|
+
trigger_element_id: "placement-popover-bottom-start",
|
|
48
|
+
tooltip_id: "placement-tooltip-bottom-start",
|
|
49
|
+
position: "bottom-start",
|
|
50
|
+
offset: true
|
|
51
|
+
}) do %>
|
|
52
|
+
Popover: bottom start
|
|
53
|
+
<% end %>
|
|
54
|
+
<%= pb_rails("button", props: { text: "Bottom end", variant: "secondary", id: "placement-popover-bottom-end" }) %>
|
|
55
|
+
<%= pb_rails("popover", props: {
|
|
56
|
+
close_on_click: "outside",
|
|
57
|
+
trigger_element_id: "placement-popover-bottom-end",
|
|
58
|
+
tooltip_id: "placement-tooltip-bottom-end",
|
|
59
|
+
position: "bottom-end",
|
|
60
|
+
offset: true
|
|
61
|
+
}) do %>
|
|
62
|
+
Popover: bottom end
|
|
63
|
+
<% end %>
|
|
64
|
+
<% end %>
|
|
65
|
+
<%= pb_rails("flex", props: { justify: "around", margin_bottom: "sm", orientation: "row", wrap: true }) do %>
|
|
66
|
+
<%= pb_rails("button", props: { text: "Left", variant: "secondary", id: "placement-popover-left" }) %>
|
|
67
|
+
<%= pb_rails("popover", props: {
|
|
68
|
+
close_on_click: "outside",
|
|
69
|
+
trigger_element_id: "placement-popover-left",
|
|
70
|
+
tooltip_id: "placement-tooltip-left",
|
|
71
|
+
position: "left",
|
|
72
|
+
offset: true
|
|
73
|
+
}) do %>
|
|
74
|
+
Popover: left
|
|
75
|
+
<% end %>
|
|
76
|
+
<%= pb_rails("button", props: { text: "Left start", variant: "secondary", id: "placement-popover-left-start" }) %>
|
|
77
|
+
<%= pb_rails("popover", props: {
|
|
78
|
+
close_on_click: "outside",
|
|
79
|
+
trigger_element_id: "placement-popover-left-start",
|
|
80
|
+
tooltip_id: "placement-tooltip-left-start",
|
|
81
|
+
position: "left-start",
|
|
82
|
+
offset: true
|
|
83
|
+
}) do %>
|
|
84
|
+
Popover: left start
|
|
85
|
+
<% end %>
|
|
86
|
+
<%= pb_rails("button", props: { text: "Left end", variant: "secondary", id: "placement-popover-left-end" }) %>
|
|
87
|
+
<%= pb_rails("popover", props: {
|
|
88
|
+
close_on_click: "outside",
|
|
89
|
+
trigger_element_id: "placement-popover-left-end",
|
|
90
|
+
tooltip_id: "placement-tooltip-left-end",
|
|
91
|
+
position: "left-end",
|
|
92
|
+
offset: true
|
|
93
|
+
}) do %>
|
|
94
|
+
Popover: left end
|
|
95
|
+
<% end %>
|
|
96
|
+
<% end %>
|
|
97
|
+
<%= pb_rails("flex", props: { justify: "around", orientation: "row", wrap: true }) do %>
|
|
98
|
+
<%= pb_rails("button", props: { text: "Right", variant: "secondary", id: "placement-popover-right" }) %>
|
|
99
|
+
<%= pb_rails("popover", props: {
|
|
100
|
+
close_on_click: "outside",
|
|
101
|
+
trigger_element_id: "placement-popover-right",
|
|
102
|
+
tooltip_id: "placement-tooltip-right",
|
|
103
|
+
position: "right",
|
|
104
|
+
offset: true
|
|
105
|
+
}) do %>
|
|
106
|
+
Popover: right
|
|
107
|
+
<% end %>
|
|
108
|
+
<%= pb_rails("button", props: { text: "Right start", variant: "secondary", id: "placement-popover-right-start" }) %>
|
|
109
|
+
<%= pb_rails("popover", props: {
|
|
110
|
+
close_on_click: "outside",
|
|
111
|
+
trigger_element_id: "placement-popover-right-start",
|
|
112
|
+
tooltip_id: "placement-tooltip-right-start",
|
|
113
|
+
position: "right-start",
|
|
114
|
+
offset: true
|
|
115
|
+
}) do %>
|
|
116
|
+
Popover: right start
|
|
117
|
+
<% end %>
|
|
118
|
+
<%= pb_rails("button", props: { text: "Right end", variant: "secondary", id: "placement-popover-right-end" }) %>
|
|
119
|
+
<%= pb_rails("popover", props: {
|
|
120
|
+
close_on_click: "outside",
|
|
121
|
+
trigger_element_id: "placement-popover-right-end",
|
|
122
|
+
tooltip_id: "placement-tooltip-right-end",
|
|
123
|
+
position: "right-end",
|
|
124
|
+
offset: true
|
|
125
|
+
}) do %>
|
|
126
|
+
Popover: right end
|
|
127
|
+
<% end %>
|
|
128
|
+
<% end %>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Use the `position` prop to control where the popover appears relative to its trigger. Valid values include `top`, `bottom`, `left`, `right`, and aligned variants such as `top-start`, `top-end`, `bottom-start`, `bottom-end`, `left-start`, `left-end`, `right-start`, and `right-end`.
|
|
@@ -7,6 +7,7 @@ examples:
|
|
|
7
7
|
- popover_scroll_height: Scroll and Height Settings
|
|
8
8
|
- popover_actionable_content: With Actionable Content
|
|
9
9
|
- popover_append_to: Append To
|
|
10
|
+
- popover_position: Position
|
|
10
11
|
|
|
11
12
|
react:
|
|
12
13
|
- popover_default: Default
|
|
@@ -16,3 +17,4 @@ examples:
|
|
|
16
17
|
- popover_scroll_height: Scroll and Height Settings
|
|
17
18
|
- popover_actionable_content: With Actionable Content
|
|
18
19
|
- popover_append_to: Append To
|
|
20
|
+
- popover_placement: Placement
|
|
@@ -4,4 +4,5 @@ export { default as PopoverClose } from './_popover_close.jsx'
|
|
|
4
4
|
export { default as PopoverZIndex } from './_popover_z_index.jsx'
|
|
5
5
|
export { default as PopoverScrollHeight } from './_popover_scroll_height.jsx'
|
|
6
6
|
export { default as PopoverActionableContent } from './_popover_actionable_content.jsx'
|
|
7
|
-
export { default as PopoverAppendTo } from './_popover_append_to.jsx'
|
|
7
|
+
export { default as PopoverAppendTo } from './_popover_append_to.jsx'
|
|
8
|
+
export { default as PopoverPlacement } from './_popover_placement.jsx'
|
|
@@ -1,33 +1,12 @@
|
|
|
1
1
|
import React, { useEffect, useState, useRef } from 'react'
|
|
2
2
|
import classnames from 'classnames'
|
|
3
|
-
import { TrixEditor } from 'react-trix'
|
|
4
3
|
|
|
5
|
-
import inlineFocus from './inlineFocus'
|
|
6
|
-
import useFocus from './useFocus'
|
|
7
4
|
import Caption from '../pb_caption/_caption'
|
|
8
5
|
import colors from '../tokens/exports/_colors.module.scss'
|
|
9
6
|
import { globalProps, GlobalProps } from '../utilities/globalProps'
|
|
10
7
|
import { buildAriaProps, buildDataProps, noop, buildHtmlProps } from '../utilities/props'
|
|
11
|
-
|
|
12
|
-
import
|
|
13
|
-
import './_dedupe_trix_toolbar'
|
|
14
|
-
|
|
15
|
-
Trix.config.textAttributes.inlineCode = {
|
|
16
|
-
tagName: 'code',
|
|
17
|
-
inheritable: true,
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
import EditorToolbar from './TipTap/Toolbar'
|
|
21
|
-
|
|
22
|
-
type Editor = {
|
|
23
|
-
attributeIsActive?: ([any]: string) => boolean,
|
|
24
|
-
element?: HTMLElement,
|
|
25
|
-
getSelectedDocument?: () => any,
|
|
26
|
-
getSelectedRange?: () => Array<number>,
|
|
27
|
-
insertHTML?: ([any]: string) => void,
|
|
28
|
-
loadHTML?: ([any]: string) => void,
|
|
29
|
-
setSelectedRange?: (range: Array<number>) => void,
|
|
30
|
-
}
|
|
8
|
+
import TipTapEditor from './_tiptap_editor'
|
|
9
|
+
import TrixTextEditor from './_trix_editor'
|
|
31
10
|
|
|
32
11
|
type RichTextEditorProps = {
|
|
33
12
|
aria?: { [key: string]: string },
|
|
@@ -55,6 +34,8 @@ type RichTextEditorProps = {
|
|
|
55
34
|
template: string,
|
|
56
35
|
value?: string,
|
|
57
36
|
maxWidth?: string
|
|
37
|
+
TrixEditor?: React.ComponentType<any>,
|
|
38
|
+
trixInstance?: any,
|
|
58
39
|
} & GlobalProps
|
|
59
40
|
|
|
60
41
|
const RichTextEditor = (props: RichTextEditorProps): React.ReactElement => {
|
|
@@ -84,50 +65,19 @@ const RichTextEditor = (props: RichTextEditorProps): React.ReactElement => {
|
|
|
84
65
|
maxWidth = "md",
|
|
85
66
|
requiredIndicator = false,
|
|
86
67
|
label,
|
|
68
|
+
TrixEditor,
|
|
69
|
+
trixInstance: trixInstance = undefined,
|
|
87
70
|
} = props
|
|
88
71
|
|
|
89
72
|
const ariaProps = buildAriaProps(aria),
|
|
90
73
|
dataProps = buildDataProps(data),
|
|
91
|
-
[editor, setEditor] = useState<Editor>(),
|
|
92
74
|
[showToolbarOnFocus, setShowToolbarOnFocus] = useState(false),
|
|
93
75
|
containerRef = useRef<HTMLDivElement>(null)
|
|
94
76
|
|
|
95
77
|
const htmlProps = buildHtmlProps(htmlOptions)
|
|
96
78
|
|
|
97
79
|
const fieldId = id ? (id as string) : null
|
|
98
|
-
const labelElementId = fieldId ? `${fieldId}-label` :
|
|
99
|
-
|
|
100
|
-
const handleOnEditorReady = (editorInstance: Editor) => {
|
|
101
|
-
setEditor(editorInstance)
|
|
102
|
-
|
|
103
|
-
setTimeout(() => {
|
|
104
|
-
const oldId = editorInstance.element?.getAttribute("input")
|
|
105
|
-
if (!oldId) return
|
|
106
|
-
|
|
107
|
-
const hiddenInput = document.getElementById(oldId) as HTMLElement | null
|
|
108
|
-
if (!hiddenInput) return
|
|
109
|
-
|
|
110
|
-
const hiddenInputId = (inputOptions.id as string) || oldId
|
|
111
|
-
|
|
112
|
-
if (hiddenInputId !== oldId) {
|
|
113
|
-
hiddenInput.id = hiddenInputId
|
|
114
|
-
editorInstance.element?.setAttribute("input", hiddenInputId)
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
if (inputOptions.name) {
|
|
118
|
-
hiddenInput.setAttribute("name", inputOptions.name as string)
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
const editorDomId = (id as string) || `${hiddenInputId}_trix`
|
|
122
|
-
const trixLabelId = ((id as string) || hiddenInputId) + "-label"
|
|
123
|
-
|
|
124
|
-
if (label) {
|
|
125
|
-
editorInstance.element?.setAttribute("aria-labelledby", trixLabelId)
|
|
126
|
-
}
|
|
127
|
-
editorInstance.element!.id = editorDomId
|
|
128
|
-
})
|
|
129
|
-
}
|
|
130
|
-
|
|
80
|
+
const labelElementId = fieldId ? `${fieldId}-label` : undefined
|
|
131
81
|
useEffect(() => {
|
|
132
82
|
if (!advancedEditor || !fieldId || !labelElementId) return
|
|
133
83
|
|
|
@@ -139,34 +89,6 @@ const RichTextEditor = (props: RichTextEditorProps): React.ReactElement => {
|
|
|
139
89
|
dom.setAttribute("aria-multiline", "true")
|
|
140
90
|
}, [advancedEditor, fieldId, labelElementId])
|
|
141
91
|
|
|
142
|
-
// DOM manipulation must wait for editor to be ready
|
|
143
|
-
if (editor && editor.element) {
|
|
144
|
-
const toolbarElement = editor.element.parentElement.querySelector('trix-toolbar') as HTMLElement,
|
|
145
|
-
blockCodeButton = toolbarElement.querySelector('[data-trix-attribute=code]') as HTMLElement
|
|
146
|
-
|
|
147
|
-
// replace default trix "block code" button with "inline code" button
|
|
148
|
-
let inlineCodeButton = toolbarElement.querySelector('[data-trix-attribute=inlineCode]') as HTMLElement
|
|
149
|
-
if (!inlineCodeButton) {
|
|
150
|
-
inlineCodeButton = blockCodeButton.cloneNode(true) as HTMLElement
|
|
151
|
-
blockCodeButton.hidden = true
|
|
152
|
-
// set button attributes
|
|
153
|
-
inlineCodeButton.dataset.trixAttribute = 'inlineCode'
|
|
154
|
-
blockCodeButton.insertAdjacentElement('afterend', inlineCodeButton)
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
if (toolbarBottom) editor.element.after(toolbarElement)
|
|
158
|
-
|
|
159
|
-
focus
|
|
160
|
-
? (document.addEventListener('trix-focus', useFocus),
|
|
161
|
-
document.addEventListener('trix-blur', useFocus),
|
|
162
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
163
|
-
useFocus())
|
|
164
|
-
: null
|
|
165
|
-
|
|
166
|
-
document.addEventListener('trix-focus', inlineFocus)
|
|
167
|
-
document.addEventListener('trix-blur', inlineFocus)
|
|
168
|
-
}
|
|
169
|
-
|
|
170
92
|
//===========focus prop with advanced editor=================
|
|
171
93
|
const isClickInPopover = (event: Event): boolean => {
|
|
172
94
|
return !!(event.target as Element).closest('.pb_tiptap_toolbar_dropdown_popover')
|
|
@@ -203,26 +125,6 @@ const RichTextEditor = (props: RichTextEditorProps): React.ReactElement => {
|
|
|
203
125
|
|
|
204
126
|
//============= end focus prop with advanced editor=================
|
|
205
127
|
|
|
206
|
-
useEffect(() => {
|
|
207
|
-
if (!editor || !template) return
|
|
208
|
-
editor.loadHTML('')
|
|
209
|
-
editor.setSelectedRange([0, 0])
|
|
210
|
-
editor.insertHTML(template)
|
|
211
|
-
}, [editor, template])
|
|
212
|
-
|
|
213
|
-
useEffect(() => {
|
|
214
|
-
if (!editor?.element) return
|
|
215
|
-
editor.element.addEventListener('click', ({ target }: Event) => {
|
|
216
|
-
const trixEditorContainer = (target as Element).closest('.pb_rich_text_editor_kit')
|
|
217
|
-
if (!trixEditorContainer) return
|
|
218
|
-
|
|
219
|
-
const anchorElement = (target as Element).closest('a')
|
|
220
|
-
if (!anchorElement) return
|
|
221
|
-
|
|
222
|
-
if (anchorElement.hasAttribute('href')) window.open(anchorElement.href)
|
|
223
|
-
})
|
|
224
|
-
}, [editor])
|
|
225
|
-
|
|
226
128
|
// Generate CSS classes
|
|
227
129
|
const css = classnames(
|
|
228
130
|
'pb_rich_text_editor_kit',
|
|
@@ -279,35 +181,34 @@ const RichTextEditor = (props: RichTextEditorProps): React.ReactElement => {
|
|
|
279
181
|
|
|
280
182
|
</label>
|
|
281
183
|
)}
|
|
282
|
-
{
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
{
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
}
|
|
184
|
+
{advancedEditor ? (
|
|
185
|
+
<TipTapEditor
|
|
186
|
+
editor={advancedEditor}
|
|
187
|
+
extensions={extensions}
|
|
188
|
+
inputHeight={inputHeight}
|
|
189
|
+
inputMinHeight={inputMinHeight}
|
|
190
|
+
shouldShowToolbar={shouldShowToolbar}
|
|
191
|
+
simple={simple}
|
|
192
|
+
sticky={sticky}
|
|
193
|
+
>
|
|
194
|
+
{children}
|
|
195
|
+
</TipTapEditor>
|
|
196
|
+
) : (
|
|
197
|
+
<TrixTextEditor
|
|
198
|
+
TrixEditor={TrixEditor}
|
|
199
|
+
focus={focus}
|
|
200
|
+
id={id}
|
|
201
|
+
inputOptions={inputOptions}
|
|
202
|
+
label={label}
|
|
203
|
+
name={name}
|
|
204
|
+
onChange={onChange}
|
|
205
|
+
placeholder={placeholder}
|
|
206
|
+
template={template}
|
|
207
|
+
toolbarBottom={toolbarBottom}
|
|
208
|
+
trixInstance={trixInstance}
|
|
209
|
+
value={value}
|
|
210
|
+
/>
|
|
211
|
+
)}
|
|
311
212
|
</div>
|
|
312
213
|
)
|
|
313
214
|
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import classnames from 'classnames'
|
|
3
|
+
|
|
4
|
+
import EditorToolbar from './TipTap/Toolbar'
|
|
5
|
+
|
|
6
|
+
type TipTapEditorProps = {
|
|
7
|
+
children?: React.ReactNode | React.ReactNode[],
|
|
8
|
+
editor: unknown,
|
|
9
|
+
extensions?: { [key: string]: string }[],
|
|
10
|
+
inputHeight?: 'sm' | 'md' | 'lg',
|
|
11
|
+
inputMinHeight?: 'sm' | 'md' | 'lg',
|
|
12
|
+
shouldShowToolbar: boolean,
|
|
13
|
+
simple?: boolean,
|
|
14
|
+
sticky?: boolean,
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const TipTapEditor = ({
|
|
18
|
+
children,
|
|
19
|
+
editor,
|
|
20
|
+
extensions,
|
|
21
|
+
inputHeight,
|
|
22
|
+
inputMinHeight,
|
|
23
|
+
shouldShowToolbar,
|
|
24
|
+
simple = false,
|
|
25
|
+
sticky = false,
|
|
26
|
+
}: TipTapEditorProps): React.ReactElement => {
|
|
27
|
+
return (
|
|
28
|
+
<div
|
|
29
|
+
className={classnames(
|
|
30
|
+
'pb_rich_text_editor_advanced_container',
|
|
31
|
+
{
|
|
32
|
+
[`input_height_${inputHeight}`]: !!inputHeight,
|
|
33
|
+
[`input_min_height_${inputMinHeight}`]: !!inputMinHeight,
|
|
34
|
+
'toolbar-active': shouldShowToolbar,
|
|
35
|
+
}
|
|
36
|
+
)}
|
|
37
|
+
>
|
|
38
|
+
{shouldShowToolbar && (
|
|
39
|
+
<EditorToolbar
|
|
40
|
+
editor={editor}
|
|
41
|
+
extensions={extensions}
|
|
42
|
+
simple={simple}
|
|
43
|
+
sticky={sticky}
|
|
44
|
+
/>
|
|
45
|
+
)}
|
|
46
|
+
{children}
|
|
47
|
+
</div>
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export default TipTapEditor
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import React, { useEffect, useState } from 'react'
|
|
2
|
+
|
|
3
|
+
import inlineFocus from './inlineFocus'
|
|
4
|
+
import applyFocusState from './useFocus'
|
|
5
|
+
import './_dedupe_trix_toolbar'
|
|
6
|
+
|
|
7
|
+
type Editor = {
|
|
8
|
+
element?: HTMLElement,
|
|
9
|
+
insertHTML?: (html: string) => void,
|
|
10
|
+
loadHTML?: (html: string) => void,
|
|
11
|
+
setSelectedRange?: (range: Array<number>) => void,
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
type TrixConfig = {
|
|
15
|
+
textAttributes?: {
|
|
16
|
+
inlineCode?: {
|
|
17
|
+
tagName: string,
|
|
18
|
+
inheritable: boolean,
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
type TrixInstance = {
|
|
24
|
+
config: TrixConfig,
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
type TrixEditorComponentProps = {
|
|
28
|
+
className: string,
|
|
29
|
+
fileParamName?: string,
|
|
30
|
+
mergeTags: unknown[],
|
|
31
|
+
onChange: (html: string, text: string) => void,
|
|
32
|
+
onEditorReady: (editorInstance: Editor) => void,
|
|
33
|
+
placeholder?: string,
|
|
34
|
+
value?: string,
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
type TrixTextEditorProps = {
|
|
38
|
+
TrixEditor?: React.ComponentType<TrixEditorComponentProps>,
|
|
39
|
+
focus?: boolean,
|
|
40
|
+
id?: string,
|
|
41
|
+
inputOptions?: { [key: string]: string | number | boolean | (() => void) },
|
|
42
|
+
label?: string,
|
|
43
|
+
name?: string,
|
|
44
|
+
onChange: (html: string, text: string) => void,
|
|
45
|
+
placeholder?: string,
|
|
46
|
+
template: string,
|
|
47
|
+
toolbarBottom?: boolean,
|
|
48
|
+
trixInstance?: TrixInstance,
|
|
49
|
+
value?: string,
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const TrixTextEditor = ({
|
|
53
|
+
TrixEditor,
|
|
54
|
+
focus = false,
|
|
55
|
+
id,
|
|
56
|
+
inputOptions = {},
|
|
57
|
+
label,
|
|
58
|
+
name,
|
|
59
|
+
onChange,
|
|
60
|
+
placeholder,
|
|
61
|
+
template,
|
|
62
|
+
toolbarBottom = false,
|
|
63
|
+
trixInstance = undefined,
|
|
64
|
+
value = '',
|
|
65
|
+
}: TrixTextEditorProps): React.ReactElement => {
|
|
66
|
+
const [editor, setEditor] = useState<Editor>()
|
|
67
|
+
|
|
68
|
+
useEffect(() => {
|
|
69
|
+
const textAttributes = trixInstance?.config?.textAttributes
|
|
70
|
+
if (!textAttributes) return
|
|
71
|
+
|
|
72
|
+
textAttributes.inlineCode = {
|
|
73
|
+
tagName: 'code',
|
|
74
|
+
inheritable: true,
|
|
75
|
+
}
|
|
76
|
+
}, [trixInstance])
|
|
77
|
+
|
|
78
|
+
const handleOnEditorReady = (editorInstance: Editor) => {
|
|
79
|
+
setEditor(editorInstance)
|
|
80
|
+
|
|
81
|
+
setTimeout(() => {
|
|
82
|
+
const oldId = editorInstance.element?.getAttribute('input')
|
|
83
|
+
if (!oldId) return
|
|
84
|
+
|
|
85
|
+
const hiddenInput = document.getElementById(oldId) as HTMLElement | null
|
|
86
|
+
if (!hiddenInput) return
|
|
87
|
+
|
|
88
|
+
const hiddenInputId = (inputOptions.id as string) || oldId
|
|
89
|
+
|
|
90
|
+
if (hiddenInputId !== oldId) {
|
|
91
|
+
hiddenInput.id = hiddenInputId
|
|
92
|
+
editorInstance.element?.setAttribute('input', hiddenInputId)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (inputOptions.name) {
|
|
96
|
+
hiddenInput.setAttribute('name', inputOptions.name as string)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const editorDomId = (id as string) || `${hiddenInputId}_trix`
|
|
100
|
+
const trixLabelId = ((id as string) || hiddenInputId) + '-label'
|
|
101
|
+
|
|
102
|
+
if (label) {
|
|
103
|
+
editorInstance.element?.setAttribute('aria-labelledby', trixLabelId)
|
|
104
|
+
}
|
|
105
|
+
if (editorInstance.element) {
|
|
106
|
+
editorInstance.element.id = editorDomId
|
|
107
|
+
}
|
|
108
|
+
})
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
useEffect(() => {
|
|
112
|
+
if (!editor || !editor.element) return
|
|
113
|
+
|
|
114
|
+
const toolbarElement = editor.element.parentElement?.querySelector('trix-toolbar') as HTMLElement | null
|
|
115
|
+
if (!toolbarElement) return
|
|
116
|
+
|
|
117
|
+
const blockCodeButton = toolbarElement.querySelector('[data-trix-attribute=code]') as HTMLElement | null
|
|
118
|
+
if (!blockCodeButton) return
|
|
119
|
+
|
|
120
|
+
let inlineCodeButton = toolbarElement.querySelector('[data-trix-attribute=inlineCode]') as HTMLElement | null
|
|
121
|
+
if (!inlineCodeButton) {
|
|
122
|
+
inlineCodeButton = blockCodeButton.cloneNode(true) as HTMLElement
|
|
123
|
+
blockCodeButton.hidden = true
|
|
124
|
+
inlineCodeButton.dataset.trixAttribute = 'inlineCode'
|
|
125
|
+
blockCodeButton.insertAdjacentElement('afterend', inlineCodeButton)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (toolbarBottom) {
|
|
129
|
+
editor.element.after(toolbarElement)
|
|
130
|
+
}
|
|
131
|
+
}, [editor, toolbarBottom])
|
|
132
|
+
|
|
133
|
+
useEffect(() => {
|
|
134
|
+
if (!focus) return
|
|
135
|
+
|
|
136
|
+
document.addEventListener('trix-focus', applyFocusState)
|
|
137
|
+
document.addEventListener('trix-blur', applyFocusState)
|
|
138
|
+
applyFocusState()
|
|
139
|
+
|
|
140
|
+
return () => {
|
|
141
|
+
document.removeEventListener('trix-focus', applyFocusState)
|
|
142
|
+
document.removeEventListener('trix-blur', applyFocusState)
|
|
143
|
+
}
|
|
144
|
+
}, [focus])
|
|
145
|
+
|
|
146
|
+
useEffect(() => {
|
|
147
|
+
document.addEventListener('trix-focus', inlineFocus)
|
|
148
|
+
document.addEventListener('trix-blur', inlineFocus)
|
|
149
|
+
|
|
150
|
+
return () => {
|
|
151
|
+
document.removeEventListener('trix-focus', inlineFocus)
|
|
152
|
+
document.removeEventListener('trix-blur', inlineFocus)
|
|
153
|
+
}
|
|
154
|
+
}, [])
|
|
155
|
+
|
|
156
|
+
useEffect(() => {
|
|
157
|
+
if (!editor || !template) return
|
|
158
|
+
editor.loadHTML && editor.loadHTML('')
|
|
159
|
+
editor.setSelectedRange && editor.setSelectedRange([0, 0])
|
|
160
|
+
editor.insertHTML && editor.insertHTML(template)
|
|
161
|
+
}, [editor, template])
|
|
162
|
+
|
|
163
|
+
useEffect(() => {
|
|
164
|
+
if (!editor?.element) return
|
|
165
|
+
|
|
166
|
+
const clickHandler = ({ target }: Event) => {
|
|
167
|
+
const trixEditorContainer = (target as Element).closest('.pb_rich_text_editor_kit')
|
|
168
|
+
if (!trixEditorContainer) return
|
|
169
|
+
|
|
170
|
+
const anchorElement = (target as Element).closest('a') as HTMLAnchorElement | null
|
|
171
|
+
if (!anchorElement) return
|
|
172
|
+
|
|
173
|
+
if (anchorElement.hasAttribute('href')) window.open(anchorElement.href)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
editor.element.addEventListener('click', clickHandler)
|
|
177
|
+
|
|
178
|
+
return () => {
|
|
179
|
+
editor.element?.removeEventListener('click', clickHandler)
|
|
180
|
+
}
|
|
181
|
+
}, [editor])
|
|
182
|
+
|
|
183
|
+
if (!TrixEditor) {
|
|
184
|
+
return (
|
|
185
|
+
<div style={{ color: 'red', padding: '1em', border: '1px solid #f00', background: '#fff0f0' }}>
|
|
186
|
+
<strong>Trix Editor is not available.</strong>
|
|
187
|
+
<br />
|
|
188
|
+
Please import <code>TrixEditor</code> from <code>react-trix</code> and pass it as a prop to <code>RichTextEditor</code>.
|
|
189
|
+
<br />
|
|
190
|
+
<pre>{`import { TrixEditor } from 'react-trix';\n<RichTextEditor TrixEditor={TrixEditor} ... />`}</pre>
|
|
191
|
+
</div>
|
|
192
|
+
)
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return React.createElement(TrixEditor, {
|
|
196
|
+
className: '',
|
|
197
|
+
fileParamName: name,
|
|
198
|
+
mergeTags: [],
|
|
199
|
+
onChange,
|
|
200
|
+
onEditorReady: handleOnEditorReady,
|
|
201
|
+
placeholder,
|
|
202
|
+
value,
|
|
203
|
+
})
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export default TrixTextEditor
|