card 1.20.0 → 1.20.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/card.gemspec +1 -1
  4. data/lib/card.rb +7 -3
  5. data/lib/card/act_manager/stage_director.rb +22 -10
  6. data/lib/card/cache/persistent.rb +15 -9
  7. data/lib/card/format/nest.rb +12 -5
  8. data/lib/card/format/nest/fetch.rb +2 -1
  9. data/lib/card/format/render.rb +5 -2
  10. data/lib/card/set/event.rb +7 -1
  11. data/lib/card/subcards.rb +3 -3
  12. data/lib/card/view/cache.rb +1 -1
  13. data/lib/card/view/fetch.rb +17 -5
  14. data/lib/card/view/options.rb +52 -26
  15. data/lib/cardio.rb +2 -1
  16. data/mod/account/spec/set/right/account_spec.rb +17 -3
  17. data/mod/admin/set/self/admin.rb +0 -2
  18. data/mod/admin/spec/set/self/admin_spec.rb +14 -11
  19. data/mod/bootstrap/set/all/bootstrap/helper.rb +27 -29
  20. data/mod/carrierwave/set/type/file.rb +1 -1
  21. data/mod/carrierwave/set/type/image.rb +18 -6
  22. data/mod/core/set/all/collection.rb +33 -7
  23. data/mod/core/set/all/fetch.rb +16 -3
  24. data/mod/core/set/all/permissions.rb +6 -12
  25. data/mod/core/set/all/trash.rb +3 -1
  26. data/mod/core/spec/set/all/collection_spec.rb +9 -8
  27. data/mod/email/set/all/notify.rb +27 -17
  28. data/mod/email/set/right/follow.rb +49 -36
  29. data/mod/email/set/type/email_template.rb +25 -69
  30. data/mod/email/set/type/email_template/email_config.rb +63 -0
  31. data/mod/email/set/type_plus_right/user/follow.rb +3 -3
  32. data/mod/machines/lib/stylesheets/style_cards.scss +292 -0
  33. data/mod/pointer/set/abstract/01_pointer.rb +8 -8
  34. data/mod/pointer/set/abstract/01_pointer/edit.rb +6 -2
  35. data/mod/prosemirror_editor/lib/javascript/script_prosemirror.js +12283 -11605
  36. data/mod/prosemirror_editor/lib/javascript/script_prosemirror_config.js.coffee +1 -1
  37. data/mod/standard/set/abstract/01_search_params.rb +1 -1
  38. data/mod/standard/set/abstract/search/paging.rb +4 -4
  39. data/mod/standard/set/all/comment.rb +67 -47
  40. data/mod/standard/set/all/links.rb +2 -2
  41. data/mod/standard/set/all/rich_html/content.rb +1 -1
  42. data/mod/standard/set/all/rich_html/editing.rb +3 -2
  43. data/mod/standard/set/all/rich_html/form.rb +21 -12
  44. data/mod/standard/set/all/rich_html/header.rb +9 -0
  45. data/mod/standard/set/all/rich_html/menu.rb +16 -12
  46. data/mod/standard/set/all/rich_html/toolbar.rb +140 -130
  47. data/mod/standard/set/all/rich_html/wrapper.rb +11 -1
  48. data/mod/standard/set/rstar/rules_editor.rb +2 -34
  49. data/mod/standard/set/self/search.rb +1 -1
  50. data/mod/standard/set/type/set.rb +4 -4
  51. data/mod/standard/spec/set/type/email_template/email_config_spec.rb +218 -0
  52. data/mod/standard/spec/set/type/email_template_spec.rb +3 -185
  53. data/spec/lib/card/cache_spec.rb +0 -1
  54. data/spec/lib/card/format/render_spec.rb +19 -0
  55. data/spec/lib/card/stage_director_spec.rb +1 -1
  56. data/tmpsets/set/mod001-core/all/actify.rb +5 -6
  57. data/tmpsets/set/mod001-core/all/fetch.rb +14 -12
  58. data/tmpsets/set/mod001-core/all/name.rb +1 -1
  59. data/tmpsets/set/mod001-core/all/permissions.rb +12 -22
  60. data/tmpsets/set/mod001-core/all/tracked_attributes.rb +76 -0
  61. data/tmpsets/set/mod001-core/all/utils.rb +40 -3
  62. data/tmpsets/set/mod002-history/all/history.rb +1 -2
  63. data/tmpsets/set/mod008-solid_cache/abstract/solid_cache.rb +1 -1
  64. data/tmpsets/set/mod013-carrierwave/abstract/attachment.rb +282 -0
  65. data/tmpsets/set/mod013-carrierwave/type/file.rb +155 -0
  66. data/tmpsets/set/mod013-carrierwave/type/image.rb +96 -0
  67. data/tmpsets/set/mod014-admin/self/admin.rb +113 -0
  68. data/tmpsets/set/mod014-admin/self/admin_info.rb +110 -0
  69. data/tmpsets/set/mod014-admin/self/version.rb +15 -0
  70. data/tmpsets/set/mod015-developer/all/event_viz.rb +59 -0
  71. data/tmpsets/set/mod015-developer/all/view_viz.rb +30 -0
  72. data/tmpsets/set/mod015-developer/right/debug.rb +96 -0
  73. metadata +15 -2
@@ -18,37 +18,50 @@ format :html do
18
18
  end
19
19
 
20
20
  view :follow_item, tags: :unknown_ok, cache: :never do |args|
21
- if card.new_card? || !card.include_item?(args[:condition])
22
- button_view = :add_follow_rule_button
23
- form_opts = { add_item: args[:condition] }
24
- else
25
- button_view = :delete_follow_rule_button
26
- form_opts = { drop_item: args[:condition] }
27
- end
28
-
29
- text = if (option_card = Card.fetch args[:condition])
30
- option_card.description(card.rule_set)
31
- else
32
- card.rule_set.follow_label
33
- end
34
- link_target = if card.rule_set.tag.codename == "self"
35
- card.rule_set_name.left
36
- else
37
- "#{card.rule_set_name}+by name"
38
- end
21
+ condition = args[:condition]
39
22
  wrap do
40
- card_form(
41
- { action: :update, name: card.name, success: { view: :follow_item } },
42
- hidden: { condition: args[:condition] }.merge(form_opts)
43
- ) do
44
- output [
45
- _optional_render(button_view, args),
46
- link_to_card(link_target, text)
23
+ card_form action: :update, success: { view: :follow_item } do
24
+ [
25
+ follow_item_hidden_tags(condition),
26
+ follow_item_button(condition),
27
+ follow_item_link(condition)
47
28
  ]
48
29
  end
49
30
  end
50
31
  end
51
32
 
33
+ def add_follow_item? condition
34
+ card.new_card? || !card.include_item?(condition)
35
+ end
36
+
37
+ def follow_item_hidden_tags condition
38
+ condkey = add_follow_item?(condition) ? :add_item : :drop_item
39
+ hidden_tags condition: condition, condkey => condition
40
+ end
41
+
42
+ def follow_item_button condition
43
+ action = add_follow_item?(condition) ? :add : :delete
44
+ _optional_render "#{action}_follow_rule_button"
45
+ end
46
+
47
+ def follow_item_link condition
48
+ link_to_card follow_item_link_target, follow_item_link_text(condition)
49
+ end
50
+
51
+ def follow_item_link_target
52
+ set = card.rule_set
53
+ setname = set.cardname
54
+ set.tag.codename == "self" ? setname.left : setname.field("by name")
55
+ end
56
+
57
+ def follow_item_link_text condition
58
+ if (option_card = Card.fetch condition)
59
+ option_card.description card.rule_set
60
+ else
61
+ card.rule_set.follow_label
62
+ end
63
+ end
64
+
52
65
  def default_follow_status_args args
53
66
  args[:card_key] ||= card.set_prototype.key
54
67
  end
@@ -60,9 +73,11 @@ format :html do
60
73
  end
61
74
 
62
75
  def follow_status_link name, key
63
- link_to_related key, "more options",
64
- path: { related: { name: name, view: :edit_single_rule } },
65
- class: "btn update-follow-link", "data-card_key" => key
76
+ # simplified this to straight link for now.
77
+ # consider restoring to slotter action
78
+ link_to_card name, "more options",
79
+ path: { view: :edit_single_rule },
80
+ class: "btn update-follow-link", "data-card_key" => key
66
81
  end
67
82
 
68
83
  view :follow_status_delete_options, cache: :never do
@@ -77,19 +92,17 @@ format :html do
77
92
  end
78
93
 
79
94
  view :delete_follow_rule_button do
80
- button_tag(
81
- type: :submit,
82
- class: "btn-xs btn-item-delete btn-primary", "aria-label" => "Left Align"
83
- ) do
95
+ button_tag(type: :submit,
96
+ class: "btn-xs btn-item-delete btn-primary",
97
+ "aria-label" => "Left Align") do
84
98
  tag :span, class: "glyphicon glyphicon-ok", "aria-hidden" => "true"
85
99
  end
86
100
  end
87
101
 
88
102
  view :add_follow_rule_button do
89
- button_tag(
90
- type: :submit,
91
- class: "btn-xs btn-item-add", "aria-label" => "Left Align"
92
- ) do
103
+ button_tag(type: :submit,
104
+ class: "btn-xs btn-item-add",
105
+ "aria-label" => "Left Align") do
93
106
  tag :span, class: "glyphicon glyphicon-plus", "aria-hidden" => "true"
94
107
  end
95
108
  end
@@ -10,82 +10,38 @@ rescue Net::SMTPError => exception
10
10
  errors.add :exception, exception.message
11
11
  end
12
12
 
13
- def process_email_field field, config, args
14
- config[field] =
15
- if args[field]
16
- args[field]
17
- elsif (field_card = fetch(trait: field))
18
- # configuration can be anything visible to configurer
19
- user = (args[:follower] && Card.fetch(args[:follower])) ||
20
- field_card.updater
21
- Auth.as(user) do
22
- yield(field_card)
23
- end
24
- else
25
- ""
26
- end
27
- end
28
-
29
- def process_message_field field, config, args, format, special_args=nil
30
- process_email_field(field, config, args) do |field_card|
31
- content_args = args.clone
32
- content_args.merge! special_args if special_args
33
- field_card.contextual_content args[:context], { format: format },
34
- content_args
35
- end
36
- end
37
-
38
- def email_config args={}
39
- config = {}
40
- args[:context] ||= self
41
-
42
- [:to, :from, :cc, :bcc].each do |field_name|
43
- process_email_field(field_name, config, args) do |field_card|
44
- field_card.process_email_addresses(
45
- args[:context], { format: "email_text" }, args
46
- )
47
- end
48
- end
49
- process_email_field(:attach, config, args) do |field_card|
50
- field_card.extended_item_contents args[:context]
51
- end
52
- process_message_field :subject, config, args, "email_text",
53
- content_opts: { chunk_list: :nest_only }
54
- process_message_field :text_message, config, args, "email_text"
55
- process_message_field :html_message, config, args, "email_html"
13
+ def process_html_message config, args, inline_attachment_url
14
+ process_message_field(
15
+ :html_message, config,
16
+ args.merge(inline_attachment_url: inline_attachment_url),
17
+ "email_html"
18
+ )
56
19
  if config[:html_message].present?
57
20
  config[:html_message] = Card::Mailer.layout config[:html_message]
58
21
  end
59
-
60
- from_name, from_email =
61
- if config[:from] =~ /(.*)\<(.*)>/
62
- [Regexp.last_match(1).strip, Regexp.last_match(2)]
63
- else
64
- [nil, config[:from]]
65
- end
66
-
67
- if (default_from = Card::Mailer.default[:from])
68
- config[:from] =
69
- if from_email
70
- %("#{from_name || from_email}" <#{default_from}>)
71
- else
72
- default_from
73
- end
74
- config[:reply_to] ||= config[:from]
75
- elsif config[:from].blank?
76
- config[:from] = Card[Card::WagnBotID].account.email
77
- end
78
- config.select { |_k, v| v.present? }
22
+ config
79
23
  end
80
24
 
81
25
  format do
82
26
  view :mail, perms: :none, cache: :never do |args|
83
- args = card.email_config(args)
84
- text_message = args.delete(:text_message)
85
- html_message = args.delete(:html_message)
86
- attachment_list = args.delete(:attach)
87
- alternative = (text_message.present? && html_message.present?)
88
- mail = Card::Mailer.new_mail(args) do
27
+ config = card.email_config(args)
28
+ text_message = config.delete(:text_message)
29
+ attachment_list = config.delete(:attach)
30
+ email_card = card # card is not accessible in the new_mail block
31
+ mail = Card::Mailer.new_mail(config) do
32
+ # inline attachments only work in the binding of this block
33
+ # so the current solution is to create a lambda here and pass it
34
+ # to the view where it is needed to create the image tag
35
+ # (see core view in Type::Image::EmailHtmlFormat)
36
+ inline_attachment_url =
37
+ lambda do |path|
38
+ attachments.inline[path] = ::File.read path
39
+ attachments[path].url
40
+ end
41
+ email_card.process_html_message config, args, inline_attachment_url
42
+ html_message = config.delete(:html_message)
43
+ alternative = (text_message.present? && html_message.present?)
44
+
89
45
  if alternative
90
46
  if attachment_list && !attachment_list.empty?
91
47
  content_type "multipart/mixed"
@@ -0,0 +1,63 @@
1
+ def email_config args={}
2
+ config = {}
3
+ args[:context] ||= self
4
+
5
+ [:to, :from, :cc, :bcc].each do |field_name|
6
+ process_email_field(field_name, config, args) do |field_card|
7
+ field_card.process_email_addresses(
8
+ args[:context], { format: "email_text" }, args
9
+ )
10
+ end
11
+ end
12
+ process_email_field(:attach, config, args) do |field_card|
13
+ field_card.extended_item_contents args[:context]
14
+ end
15
+ process_message_field :subject, config, args, "email_text",
16
+ content_opts: { chunk_list: :nest_only }
17
+ process_message_field :text_message, config, args, "email_text"
18
+
19
+ from_name, from_email =
20
+ if config[:from] =~ /(.*)\<(.*)>/
21
+ [Regexp.last_match(1).strip, Regexp.last_match(2)]
22
+ else
23
+ [nil, config[:from]]
24
+ end
25
+
26
+ if (default_from = Card::Mailer.default[:from])
27
+ config[:from] =
28
+ if from_email
29
+ %("#{from_name || from_email}" <#{default_from}>)
30
+ else
31
+ default_from
32
+ end
33
+ config[:reply_to] ||= config[:from]
34
+ elsif config[:from].blank?
35
+ config[:from] = Card[Card::WagnBotID].account.email
36
+ end
37
+ config.select { |_k, v| v.present? }
38
+ end
39
+
40
+ def process_email_field field, config, args
41
+ config[field] =
42
+ if args[field]
43
+ args[field]
44
+ elsif (field_card = fetch(trait: field))
45
+ # configuration can be anything visible to configurer
46
+ user = (args[:follower] && Card.fetch(args[:follower])) ||
47
+ field_card.updater
48
+ Auth.as(user) do
49
+ yield(field_card)
50
+ end
51
+ else
52
+ ""
53
+ end
54
+ end
55
+
56
+ def process_message_field field, config, args, format, special_args=nil
57
+ process_email_field(field, config, args) do |field_card|
58
+ content_args = args.clone
59
+ content_args.merge! special_args if special_args
60
+ field_card.contextual_content args[:context], { format: format },
61
+ content_args
62
+ end
63
+ end
@@ -120,9 +120,9 @@ format :html do
120
120
  subformat(rule[:card]).render_follow_item condition: option,
121
121
  hide: hide_buttons
122
122
  end
123
- end.join("\n")
124
- end.join("\n")
125
- end.join("\n")
123
+ end
124
+ end
125
+ end
126
126
  end
127
127
  end
128
128
  end
@@ -855,3 +855,295 @@ html>body .open-view {
855
855
  }
856
856
 
857
857
 
858
+ /*-------------------------- */
859
+ /*- ProseMirror - */
860
+ /*-------------------------- */
861
+
862
+ .ProseMirror {
863
+ position: relative;
864
+ }
865
+
866
+ .ProseMirror {
867
+ white-space: pre-wrap;
868
+ }
869
+
870
+ .ProseMirror ul, .ProseMirror ol {
871
+ padding-left: 30px;
872
+ cursor: default;
873
+ }
874
+
875
+ .ProseMirror blockquote {
876
+ padding-left: 1em;
877
+ border-left: 3px solid #eee;
878
+ margin-left: 0; margin-right: 0;
879
+ }
880
+
881
+ .ProseMirror pre {
882
+ white-space: pre-wrap;
883
+ }
884
+
885
+ .ProseMirror li {
886
+ position: relative;
887
+ pointer-events: none; /* Don't do weird stuff with marker clicks */
888
+ }
889
+ .ProseMirror li > * {
890
+ pointer-events: auto;
891
+ }
892
+
893
+ .ProseMirror-nodeselection *::selection, .ProseMirror-widget *::selection { background: transparent; }
894
+ .ProseMirror-nodeselection *::-moz-selection, .ProseMirror-widget *::-moz-selection { background: transparent; }
895
+
896
+ .ProseMirror-selectednode {
897
+ outline: 2px solid #8cf;
898
+ }
899
+
900
+ /* Make sure li selections wrap around markers */
901
+
902
+ li.ProseMirror-selectednode {
903
+ outline: none;
904
+ }
905
+
906
+ li.ProseMirror-selectednode:after {
907
+ content: "";
908
+ position: absolute;
909
+ left: -32px;
910
+ right: -2px; top: -2px; bottom: -2px;
911
+ border: 2px solid #8cf;
912
+ pointer-events: none;
913
+ }
914
+
915
+
916
+ .ProseMirror-textblock-dropdown {
917
+ min-width: 3em;
918
+ }
919
+
920
+ .ProseMirror-menu {
921
+ margin: 0 -4px;
922
+ line-height: 1;
923
+ }
924
+
925
+ .ProseMirror-tooltip .ProseMirror-menu {
926
+ width: -webkit-fit-content;
927
+ width: fit-content;
928
+ white-space: pre;
929
+ }
930
+
931
+ .ProseMirror-menuitem {
932
+ margin-right: 3px;
933
+ display: inline-block;
934
+ }
935
+
936
+ .ProseMirror-menuseparator {
937
+ border-right: 1px solid #ddd;
938
+ margin-right: 3px;
939
+ }
940
+
941
+ .ProseMirror-menu-dropdown, .ProseMirror-menu-dropdown-menu {
942
+ font-size: 90%;
943
+ white-space: nowrap;
944
+ }
945
+
946
+ .ProseMirror-menu-dropdown {
947
+ vertical-align: 1px;
948
+ cursor: pointer;
949
+ }
950
+
951
+ .ProseMirror-menu-dropdown-wrap {
952
+ padding: 1px 14px 1px 4px;
953
+ display: inline-block;
954
+ position: relative;
955
+ }
956
+
957
+ .ProseMirror-menu-dropdown:after {
958
+ content: "";
959
+ border-left: 4px solid transparent;
960
+ border-right: 4px solid transparent;
961
+ border-top: 4px solid currentColor;
962
+ opacity: .6;
963
+ position: absolute;
964
+ right: 2px;
965
+ top: calc(50% - 2px);
966
+ }
967
+
968
+ .ProseMirror-menu-dropdown-menu, .ProseMirror-menu-submenu {
969
+ position: absolute;
970
+ background: white;
971
+ color: #666;
972
+ border: 1px solid #aaa;
973
+ padding: 2px;
974
+ }
975
+
976
+ .ProseMirror-menu-dropdown-menu {
977
+ z-index: 15;
978
+ min-width: 6em;
979
+ }
980
+
981
+ .ProseMirror-menu-dropdown-item {
982
+ cursor: pointer;
983
+ padding: 2px 8px 2px 4px;
984
+ }
985
+
986
+ .ProseMirror-menu-dropdown-item:hover {
987
+ background: #f2f2f2;
988
+ }
989
+
990
+ .ProseMirror-menu-submenu-wrap {
991
+ position: relative;
992
+ margin-right: -4px;
993
+ }
994
+
995
+ .ProseMirror-menu-submenu-label:after {
996
+ content: "";
997
+ border-top: 4px solid transparent;
998
+ border-bottom: 4px solid transparent;
999
+ border-left: 4px solid currentColor;
1000
+ opacity: .6;
1001
+ position: absolute;
1002
+ right: 4px;
1003
+ top: calc(50% - 4px);
1004
+ }
1005
+
1006
+ .ProseMirror-menu-submenu {
1007
+ display: none;
1008
+ min-width: 4em;
1009
+ left: 100%;
1010
+ top: -3px;
1011
+ }
1012
+
1013
+ .ProseMirror-menu-active {
1014
+ background: #eee;
1015
+ border-radius: 4px;
1016
+ }
1017
+
1018
+ .ProseMirror-menu-active {
1019
+ background: #eee;
1020
+ border-radius: 4px;
1021
+ }
1022
+
1023
+ .ProseMirror-menu-disabled {
1024
+ opacity: .3;
1025
+ }
1026
+
1027
+ .ProseMirror-menu-submenu-wrap:hover .ProseMirror-menu-submenu, .ProseMirror-menu-submenu-wrap-active .ProseMirror-menu-submenu {
1028
+ display: block;
1029
+ }
1030
+
1031
+ .ProseMirror-menubar {
1032
+ border-top-left-radius: inherit;
1033
+ border-top-right-radius: inherit;
1034
+ position: relative;
1035
+ min-height: 1em;
1036
+ color: #666;
1037
+ padding: 1px 6px;
1038
+ top: 0; left: 0; right: 0;
1039
+ border-bottom: 1px solid silver;
1040
+ background: white;
1041
+ z-index: 10;
1042
+ -moz-box-sizing: border-box;
1043
+ box-sizing: border-box;
1044
+ overflow: visible;
1045
+ }
1046
+
1047
+ .ProseMirror-icon {
1048
+ display: inline-block;
1049
+ line-height: .8;
1050
+ vertical-align: -2px; /* Compensate for padding */
1051
+ padding: 2px 8px;
1052
+ cursor: pointer;
1053
+ }
1054
+
1055
+ .ProseMirror-icon svg {
1056
+ fill: currentColor;
1057
+ height: 1em;
1058
+ }
1059
+
1060
+ .ProseMirror-icon span {
1061
+ vertical-align: text-top;
1062
+ }
1063
+
1064
+
1065
+
1066
+ /* Add space around the hr to make clicking it easier */
1067
+
1068
+ .ProseMirror-example-setup-style hr {
1069
+ position: relative;
1070
+ height: 6px;
1071
+ border: none;
1072
+ }
1073
+
1074
+ .ProseMirror-example-setup-style hr:after {
1075
+ content: "";
1076
+ position: absolute;
1077
+ left: 10px;
1078
+ right: 10px;
1079
+ top: 2px;
1080
+ border-top: 2px solid silver;
1081
+ }
1082
+
1083
+ .ProseMirror-example-setup-style img {
1084
+ cursor: default;
1085
+ }
1086
+
1087
+ .ProseMirror-example-setup-style table {
1088
+ border-collapse: collapse;
1089
+ }
1090
+
1091
+ .ProseMirror-example-setup-style td {
1092
+ vertical-align: top;
1093
+ border: 1px solid #ddd;
1094
+ padding: 3px 5px;
1095
+ }
1096
+
1097
+ .ProseMirror-prompt {
1098
+ background: white;
1099
+ padding: 5px 10px 5px 15px;
1100
+ border: 1px solid silver;
1101
+ position: fixed;
1102
+ border-radius: 3px;
1103
+ z-index: 11;
1104
+ box-shadow: -.5px 2px 5px rgba(0, 0, 0, .2);
1105
+ }
1106
+
1107
+ .ProseMirror-prompt h5 {
1108
+ margin: 0;
1109
+ font-weight: normal;
1110
+ font-size: 100%;
1111
+ color: #444;
1112
+ }
1113
+
1114
+ .ProseMirror-prompt input[type="text"],
1115
+ .ProseMirror-prompt textarea {
1116
+ background: #eee;
1117
+ border: none;
1118
+ outline: none;
1119
+ }
1120
+
1121
+ .ProseMirror-prompt input[type="text"] {
1122
+ padding: 0 4px;
1123
+ }
1124
+
1125
+ .ProseMirror-prompt-close {
1126
+ position: absolute;
1127
+ left: 2px; top: 1px;
1128
+ color: #666;
1129
+ border: none; background: transparent; padding: 0;
1130
+ }
1131
+
1132
+ .ProseMirror-prompt-close:after {
1133
+ content: "✕";
1134
+ font-size: 12px;
1135
+ }
1136
+
1137
+ .ProseMirror-invalid {
1138
+ background: #ffc;
1139
+ border: 1px solid #cc7;
1140
+ border-radius: 4px;
1141
+ padding: 5px 10px;
1142
+ position: absolute;
1143
+ min-width: 10em;
1144
+ }
1145
+
1146
+ .ProseMirror-prompt-buttons {
1147
+ margin-top: 5px;
1148
+ display: none;
1149
+ }