lexxy 0.9.32 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Binary file
Binary file
@@ -210,12 +210,6 @@
210
210
  inset-inline-end: 0;
211
211
  position: absolute;
212
212
  }
213
-
214
- lexxy-node-delete-button {
215
- inset-block-start: 1.5ch;
216
- inset-inline-end: 1.5ch;
217
- inset-inline-start: unset;
218
- }
219
213
  }
220
214
 
221
215
  &.attachment--error {
@@ -327,15 +321,6 @@
327
321
  outline-offset: var(--lexxy-focus-ring-offset);
328
322
  }
329
323
 
330
- .attachment--file {
331
- lexxy-node-delete-button {
332
- inset-block-start: 50%;
333
- inset-inline-end: 1ch;
334
- inset-inline-start: unset;
335
- transform: translate(0, -50%);
336
- }
337
- }
338
-
339
324
  /* Image galleries */
340
325
  /* ------------------------------------------------------------------------ */
341
326
 
@@ -372,43 +357,28 @@
372
357
  }
373
358
  }
374
359
 
375
- .attachment__caption {
376
- textarea {
377
- background: transparent;
378
- block-size: fit-content;
379
- border: 0;
380
- border-radius: var(--lexxy-radius);
381
- box-sizing: border-box;
382
- color: inherit;
360
+ .attachment__caption--editable {
361
+ box-sizing: border-box;
362
+ cursor: text;
363
+
364
+ .attachment__caption-text {
383
365
  display: block;
384
- font-size: inherit;
385
- font-family: inherit;
386
- inline-size: 100%;
387
- max-inline-size: 100%;
388
- padding: 0;
366
+ min-block-size: 1lh;
367
+ overflow-wrap: anywhere;
368
+ white-space: pre-wrap;
389
369
  text-align: center;
370
+ }
390
371
 
391
- @supports (resize: none) {
392
- resize: none;
393
- }
394
-
395
- &:focus {
396
- background: var(--lexxy-color-canvas);
397
- outline: 0;
398
- }
399
-
400
- &:placeholder-shown {
401
- overflow: hidden;
402
- text-overflow: ellipsis;
403
- white-space: nowrap;
404
- }
405
-
406
- @supports (field-sizing: content) {
407
- field-sizing: content;
408
- inline-size: 100%;
409
- }
372
+ &[data-placeholder] .attachment__caption-text {
373
+ overflow: hidden;
374
+ text-overflow: ellipsis;
375
+ white-space: nowrap;
410
376
  }
411
377
  }
378
+
379
+ .attachment__caption--editing .attachment__caption-text {
380
+ display: none;
381
+ }
412
382
  }
413
383
 
414
384
  /* Reserve the mounted height before upgrade so it doesn't shift layout on mount. */
@@ -636,7 +606,7 @@
636
606
  padding: 1ch;
637
607
  position: relative;
638
608
 
639
- &[aria-pressed="true"] {
609
+ &[aria-checked="true"] {
640
610
  background-color: var(--lexxy-color-selected);
641
611
 
642
612
  &:hover {
@@ -782,6 +752,10 @@
782
752
  grid-template-columns: repeat(auto-fill, minmax(var(--lexxy-toolbar-button-size), 1fr));
783
753
  max-inline-size: var(--max-inline-size);
784
754
 
755
+ .lexxy-highlight-colors__group {
756
+ display: contents;
757
+ }
758
+
785
759
  button {
786
760
  block-size: unset;
787
761
  inline-size: 100%;
@@ -796,7 +770,7 @@
796
770
  position: absolute;
797
771
  }
798
772
 
799
- &[aria-pressed="true"] {
773
+ &[aria-checked="true"] {
800
774
  background-color: transparent;
801
775
  box-shadow: 0 0 0 2px currentColor inset;
802
776
 
@@ -830,8 +804,7 @@
830
804
  position: absolute;
831
805
  z-index: 2;
832
806
 
833
- button,
834
- summary {
807
+ button {
835
808
  align-items: center;
836
809
  background: transparent;
837
810
  block-size: var(--button-size);
@@ -849,7 +822,7 @@
849
822
 
850
823
  @media(any-hover: hover) {
851
824
  &:hover:not([aria-disabled="true"]),
852
- [open] &:is(summary) {
825
+ &.lexxy-table-control__more-menu-trigger[aria-expanded="true"] {
853
826
  background: var(--lexxy-color-ink-medium);
854
827
 
855
828
  svg {
@@ -880,8 +853,10 @@
880
853
  }
881
854
  }
882
855
 
883
- summary {
884
- box-shadow: 0 0 0 1px inset rgba(128, 128, 128, 0.3);
856
+ .lexxy-table-control__more-menu-trigger {
857
+ aspect-ratio: auto;
858
+ box-shadow: 0 0 0 1px inset var(--lexxy-color-floating-controls-separator);
859
+ font-weight: normal;
885
860
  padding: 0 1.25ch;
886
861
  }
887
862
 
@@ -909,6 +884,7 @@
909
884
  white-space: nowrap;
910
885
 
911
886
  .lexxy-table-control__more-menu {
887
+ display: flex;
912
888
  gap: 0;
913
889
  position: relative;
914
890
 
@@ -924,6 +900,10 @@
924
900
  position: absolute;
925
901
  transform: translateX(-50%);
926
902
 
903
+ &[hidden] {
904
+ display: none;
905
+ }
906
+
927
907
  button {
928
908
  aspect-ratio: unset;
929
909
  flex-direction: row;
@@ -994,20 +974,73 @@
994
974
 
995
975
 
996
976
  /* --------------------------------------------------------------------------
997
- /* Attachment delete button */
977
+ /* Attachment toolbar */
998
978
 
999
- &:is(lexxy-node-delete-button) {
1000
- inset-block-start: 0;
1001
- inset-inline-start: 100%;
1002
- opacity: 0;
1003
- pointer-events: none;
979
+ &:is(lexxy-attachment-toolbar) {
980
+ display: flex;
981
+ /* The anchor is measured in px from the editor's top-left, so these stay physical. */
982
+ left: calc(var(--lexxy-anchor-left) + var(--lexxy-anchor-width));
983
+ top: var(--lexxy-anchor-top);
984
+ transform: translate(calc(-100% - 1.5ch), 1.5ch);
1004
985
 
1005
- .node--selected & {
1006
- opacity: 1;
1007
- pointer-events: auto;
986
+ &[hidden] {
987
+ display: none;
988
+ }
989
+
990
+ /* The divider is thinner than the button. */
991
+ &[data-node-type="horizontal_divider"] {
992
+ --button-size: 1.8lh;
993
+
994
+ top: calc(var(--lexxy-anchor-top) + var(--lexxy-anchor-height) / 2);
995
+ transform: translate(calc(-100% - 0.5ch), -50%);
996
+ }
997
+
998
+ &[data-presentation="inline"] {
999
+ --button-size: 1.6lh;
1000
+
1001
+ top: calc(var(--lexxy-anchor-top) + var(--lexxy-anchor-height) / 2);
1002
+ transform: translate(0.5ch, -50%);
1003
+
1004
+ &[data-overflow] {
1005
+ transform: translate(-100%, -50%);
1006
+ }
1008
1007
  }
1009
1008
 
1010
- .lexxy-node-delete:hover {
1009
+ .lexxy-floating-controls__group {
1010
+ display: flex;
1011
+ }
1012
+
1013
+ button[hidden] {
1014
+ display: none;
1015
+ }
1016
+
1017
+ .lexxy-attachment-toolbar__alternative-text {
1018
+ aspect-ratio: auto;
1019
+ margin-inline-end: calc(var(--lexxy-toolbar-spacing) + 1px);
1020
+ padding-inline: 1ch;
1021
+ position: relative;
1022
+
1023
+ span {
1024
+ display: inline-block;
1025
+ font-size: 0.9em;
1026
+ }
1027
+
1028
+ &:after {
1029
+ background-color: var(--lexxy-color-floating-controls-separator);
1030
+ block-size: 1.125em;
1031
+ content: "";
1032
+ display: block;
1033
+ inline-size: 1px;
1034
+ inset-block: 0;
1035
+ inset-inline-end: calc(-1 * var(--lexxy-toolbar-spacing));
1036
+ margin: auto;
1037
+ pointer-events: none;
1038
+ position: absolute;
1039
+ }
1040
+ }
1041
+
1042
+ .lexxy-attachment-toolbar__remove:hover,
1043
+ .lexxy-attachment-toolbar__remove:focus-visible {
1011
1044
  background-color: var(--lexxy-color-red);
1012
1045
  }
1013
1046
  }
@@ -1135,20 +1168,151 @@ action-text-attachment[content-type^="application/vnd.actiontext"] {
1135
1168
 
1136
1169
  outline: none;
1137
1170
  }
1171
+ }
1138
1172
 
1139
- lexxy-node-delete-button {
1140
- inset-inline-start: 0;
1141
- line-height: 1lh;
1173
+ /* --------------------------------------------------------------------------
1174
+ /* Screen readers need access to announcements and selection labels. */
1175
+ :where(lexxy-live-region, .lexxy-fake-selection) {
1176
+ block-size: 1px;
1177
+ border: 0;
1178
+ clip-path: inset(50%);
1179
+ inline-size: 1px;
1180
+ margin: -1px;
1181
+ overflow: hidden;
1182
+ padding: 0;
1183
+ position: absolute;
1184
+ white-space: nowrap;
1185
+ }
1142
1186
 
1143
- .lexxy-floating-controls__group {
1144
- --button-size: 1lh;
1187
+ /* The DOM Selection API requires selectable text. */
1188
+ .lexxy-fake-selection {
1189
+ -webkit-user-select: text;
1145
1190
 
1146
- background-color: var(--lexxy-color-accent-dark);
1147
- padding: 0;
1191
+ @supports (user-select: text) {
1192
+ user-select: text;
1193
+ }
1194
+ }
1148
1195
 
1149
- button {
1150
- border-radius: 50%;
1151
- }
1196
+
1197
+ /* Screen readers need the caption field outside the editor's textbox. */
1198
+ :where(.lexxy-caption-editor) {
1199
+ position: absolute;
1200
+ z-index: 2;
1201
+ box-sizing: border-box;
1202
+ background: var(--lexxy-color-canvas);
1203
+ border: 0;
1204
+ border-radius: var(--lexxy-radius);
1205
+ outline: 0;
1206
+ padding: 0;
1207
+ overflow: hidden;
1208
+
1209
+ @supports (resize: none) {
1210
+ resize: none;
1211
+ }
1212
+
1213
+ &[hidden] {
1214
+ display: none;
1215
+ }
1216
+ }
1217
+
1218
+ .lexxy-alternative-text-dialog {
1219
+ background: var(--lexxy-color-canvas);
1220
+ border: 2px solid var(--lexxy-color-selected-hover);
1221
+ border-radius: calc(var(--lexxy-radius) + var(--lexxy-toolbar-gap));
1222
+ box-shadow: var(--lexxy-shadow);
1223
+ box-sizing: border-box;
1224
+ color: var(--lexxy-color-ink);
1225
+ font: inherit;
1226
+ inline-size: 60%;
1227
+ inset-block: calc(var(--lexxy-anchor-bottom) + var(--lexxy-toolbar-spacing)) auto;
1228
+ inset-inline: 0;
1229
+ margin-block: 0;
1230
+ margin-inline: auto;
1231
+ min-inline-size: min(20rem, 100%);
1232
+ overflow: auto;
1233
+ padding: var(--lexxy-toolbar-spacing);
1234
+ z-index: 3;
1235
+
1236
+ h2 {
1237
+ font-size: inherit;
1238
+ font-weight: bold;
1239
+ line-height: 1.5;
1240
+ margin: 0;
1241
+ padding-block-start: calc(0.25 * var(--lexxy-text-small));
1242
+ padding-inline: calc(0.5 * var(--lexxy-text-small));
1243
+ text-align: center;
1244
+ }
1245
+
1246
+ .lexxy-alternative-text-dialog__controls {
1247
+ align-items: stretch;
1248
+ display: flex;
1249
+ flex-direction: column;
1250
+ gap: 0.5em;
1251
+ margin-block-start: 0.5em;
1252
+ }
1253
+
1254
+ textarea {
1255
+ background: var(--lexxy-color-canvas);
1256
+ border: 1px solid var(--lexxy-color-ink-lighter);
1257
+ border-radius: var(--lexxy-radius);
1258
+ box-sizing: border-box;
1259
+ color: inherit;
1260
+ display: block;
1261
+ font: inherit;
1262
+ font-size: var(--lexxy-text-small);
1263
+ font-weight: normal;
1264
+ min-block-size: calc(2lh + 1em + 2px);
1265
+ min-inline-size: 0;
1266
+ padding: 0.5em;
1267
+
1268
+ @supports (field-sizing: content) {
1269
+ field-sizing: content;
1270
+ }
1271
+
1272
+ @supports (resize: none) {
1273
+ resize: none;
1274
+ }
1275
+ }
1276
+
1277
+ button {
1278
+ background-color: var(--lexxy-color-ink-lightest);
1279
+ block-size: var(--lexxy-toolbar-button-size);
1280
+ border: 0;
1281
+ border-radius: var(--lexxy-radius);
1282
+ color: currentColor;
1283
+ cursor: pointer;
1284
+ display: grid;
1285
+ font-size: var(--lexxy-text-small);
1286
+ inline-size: 100%;
1287
+ line-height: inherit;
1288
+ padding-inline: 2ch;
1289
+ place-items: center;
1290
+
1291
+ &:hover {
1292
+ opacity: 0.8;
1293
+ }
1294
+ }
1295
+
1296
+ .lexxy-alternative-text-dialog__save {
1297
+ background-color: var(--lexxy-color-accent-dark);
1298
+ color: var(--lexxy-color-ink-inverted);
1299
+
1300
+ &:hover {
1301
+ background-color: var(--lexxy-color-accent-medium);
1302
+ }
1303
+ }
1304
+
1305
+ textarea:focus-visible {
1306
+ outline: var(--lexxy-focus-ring-size) solid var(--lexxy-focus-ring-color);
1307
+ outline-offset: var(--lexxy-focus-ring-offset);
1308
+ }
1309
+
1310
+ .lexxy-alternative-text-dialog__actions {
1311
+ display: flex;
1312
+ gap: 0.5em;
1313
+
1314
+ button {
1315
+ flex: 1;
1152
1316
  }
1153
1317
  }
1154
1318
  }
@@ -35,6 +35,7 @@
35
35
  --lexxy-color-selected-dark: var(--lexxy-color-blue);
36
36
  --lexxy-color-selected-50: color-mix(in oklch, var(--lexxy-color-selected-dark) 50%, transparent);
37
37
  --lexxy-color-code-bg: var(--lexxy-color-ink-lightest);
38
+ --lexxy-color-floating-controls-separator: rgba(128, 128, 128, 0.3);
38
39
 
39
40
  /* Text color highlights */
40
41
  --highlight-1: rgb(136, 118, 38);
@@ -49,11 +50,11 @@
49
50
 
50
51
  --highlight-bg-1: rgba(229, 223, 6, 0.3);
51
52
  --highlight-bg-2: rgba(255, 185, 87, 0.3);
52
- --highlight-bg-3: rgba(255, 118, 118, 0.3);
53
+ --highlight-bg-3: rgba(255, 118, 118, 0.3);
53
54
  --highlight-bg-4: rgba(248, 137, 216, 0.3);
54
- --highlight-bg-5: rgba(190, 165, 255, 0.3);
55
+ --highlight-bg-5: rgba(190, 165, 255, 0.3);
55
56
  --highlight-bg-6: rgba(124, 192, 252, 0.3);
56
- --highlight-bg-7: rgba(140, 255, 129, 0.3);
57
+ --highlight-bg-7: rgba(140, 255, 129, 0.3);
57
58
  --highlight-bg-8: rgba(221, 170, 123, 0.3);
58
59
  --highlight-bg-9: rgba(200, 200, 200, 0.3);
59
60
 
@@ -84,4 +85,4 @@
84
85
  --lexxy-radius: 0.5ch;
85
86
  --lexxy-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
86
87
  --lexxy-z-popup: 1000;
87
- }
88
+ }
@@ -0,0 +1,8 @@
1
+ <figure class="attachment attachment--preview">
2
+ <%= image_tag remote_image.url, width: remote_image.width, height: remote_image.height, alt: remote_image.try(:alt) %>
3
+ <% if caption = remote_image.try(:caption) %>
4
+ <figcaption class="attachment__caption">
5
+ <%= caption %>
6
+ </figcaption>
7
+ <% end %>
8
+ </figure>
@@ -9,6 +9,8 @@ module ActionText
9
9
 
10
10
  class Editor::LexxyEditor::Tag < Editor::Tag
11
11
  def render_in(view_context, ...)
12
+ options[:data] ||= {}
13
+ options[:data][:action_text_supports_alt] = Lexxy.supports_alternative_text?
12
14
  # Strip html_safe to preserve attribute escaping (see #749)
13
15
  options[:value] = options[:value].to_str if options[:value].respond_to?(:to_str)
14
16
  super
@@ -11,6 +11,7 @@ module Lexxy
11
11
  options[:value] ||= value
12
12
  options[:class] ||= "lexxy-content"
13
13
  options[:data] ||= {}
14
+ options[:data][:action_text_supports_alt] = Lexxy.supports_alternative_text?
14
15
  options[:data][:direct_upload_url] ||= main_app.rails_direct_uploads_url
15
16
  options[:data][:blob_url_template] ||= main_app.rails_service_blob_url(":signed_id", ":filename")
16
17
 
data/lib/lexxy/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Lexxy
2
- VERSION = "0.9.32"
2
+ VERSION = "1.0.0"
3
3
  end
data/lib/lexxy.rb CHANGED
@@ -2,6 +2,10 @@ require "lexxy/version"
2
2
 
3
3
  module Lexxy
4
4
  class << self
5
+ def supports_alternative_text?
6
+ ActionText::Attachment::ATTRIBUTES.include?("alt")
7
+ end
8
+
5
9
  # Check for ActionText::Editor with block-children support (rails/rails#56926)
6
10
  def supports_editor_adapter?
7
11
  !!(defined?(ActionText::Editor) && ActionText::Editor.instance_method(:editor_tag).parameters.assoc(:block))
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lexxy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.32
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jorge Manrubia
@@ -129,6 +129,7 @@ files:
129
129
  - app/assets/stylesheets/lexxy-editor.css
130
130
  - app/assets/stylesheets/lexxy-variables.css
131
131
  - app/assets/stylesheets/lexxy.css
132
+ - app/views/action_text/attachables/_remote_image.html.erb
132
133
  - app/views/action_text/attachables/_remote_video.html.erb
133
134
  - config/ci.rb
134
135
  - ext/Rakefile
@@ -150,7 +151,7 @@ licenses:
150
151
  metadata:
151
152
  homepage_uri: https://github.com/basecamp/lexxy
152
153
  source_code_uri: https://github.com/basecamp/lexxy
153
- changelog_uri: https://github.com/basecamp/lexxy
154
+ changelog_uri: https://github.com/basecamp/lexxy/releases
154
155
  rdoc_options: []
155
156
  require_paths:
156
157
  - lib