@37signals/lexxy 0.1.22-beta → 0.1.23-beta

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,451 @@
1
+ @import url("lexxy-variables.css");
2
+
3
+ :where(lexxy-editor) {
4
+ --lexxy-editor-padding: 1ch;
5
+ --lexxy-editor-rows: 8lh;
6
+ @supports (min-block-size: attr(rows lh)) {
7
+ --lexxy-editor-rows: attr(rows lh, 8lh);
8
+ }
9
+
10
+ --lexxy-toolbar-gap: 2px;
11
+
12
+ border: 1px solid var(--lexxy-color-ink-lighter);
13
+ border-radius: calc(var(--lexxy-radius) + var(--lexxy-toolbar-gap));
14
+ background-color: var(--lexxy-color-canvas);
15
+ display: block;
16
+ overflow: visible;
17
+ position: relative;
18
+ transition: opacity 150ms;
19
+
20
+ input,
21
+ button,
22
+ summary {
23
+ &:focus-visible {
24
+ outline: var(--lexxy-focus-ring-size) solid var(--lexxy-focus-ring-color);
25
+ outline-offset: var(--lexxy-focus-ring-offset);
26
+ }
27
+ }
28
+
29
+ button,
30
+ summary {
31
+ -webkit-appearance: none;
32
+ appearance: none;
33
+ background: var(--lexxy-color-canvas);
34
+ border: none;
35
+ border-radius: var(--lexxy-radius);
36
+ cursor: pointer;
37
+ font-size: inherit;
38
+ inline-size: auto;
39
+
40
+ @media(any-hover: hover) {
41
+ &:hover:not([aria-disabled="true"]) {
42
+ background: var(--lexxy-color-ink-lightest);
43
+ }
44
+ }
45
+ }
46
+
47
+ .node--selected {
48
+ &:has(img) img,
49
+ &:not(:has(img)) {
50
+ outline: var(--lexxy-focus-ring-size) solid var(--lexxy-focus-ring-color);
51
+ outline-offset: var(--lexxy-focus-ring-offset);
52
+ }
53
+ }
54
+
55
+ action-text-attachment {
56
+ cursor: pointer;
57
+ }
58
+ }
59
+
60
+ /* Placeholder */
61
+ :where(.lexxy-editor--empty) {
62
+ .lexxy-editor__content:not(:has(ul, ol))::before {
63
+ content: attr(placeholder);
64
+ color: currentColor;
65
+ cursor: text;
66
+ opacity: 0.66;
67
+ pointer-events: none;
68
+ position: absolute;
69
+ white-space: pre-line;
70
+ }
71
+ }
72
+
73
+ :where(.lexxy-editor__content) {
74
+ min-block-size: var(--lexxy-editor-rows);
75
+ outline: 0;
76
+ padding: var(--lexxy-editor-padding);
77
+ }
78
+
79
+ :where(.lexxy-editor--drag-over) {
80
+ background-color: var(--lexxy-color-selected);
81
+ border-radius: var(--lexxy-radius);
82
+ outline: 2px dashed var(--lexxy-color-selected-dark);
83
+ }
84
+
85
+ /* Toolbar
86
+ /* -------------------------------------------------------------------------- */
87
+
88
+ :where(lexxy-toolbar) {
89
+ --lexxy-toolbar-icon-size: 1em;
90
+
91
+ border-block-end: 1px solid var(--lexxy-color-ink-lighter);
92
+ color: currentColor;
93
+ display: flex;
94
+ font-size: inherit;
95
+ gap: var(--lexxy-toolbar-gap);
96
+ max-inline-size: 100%;
97
+ padding: 2px;
98
+ position: relative;
99
+
100
+ &[data-attachments="false"] button[name="upload"]{
101
+ display: none;
102
+ }
103
+ }
104
+
105
+ :where(.lexxy-editor__toolbar-button) {
106
+ aspect-ratio: 1;
107
+ block-size: 2lh;
108
+ color: currentColor;
109
+ display: grid;
110
+ place-items: center;
111
+
112
+ &:is(:active):not([aria-disabled="true"]),
113
+ &[aria-pressed="true"] {
114
+ background-color: var(--lexxy-color-selected);
115
+
116
+ &:hover {
117
+ background-color: var(--lexxy-color-selected-hover);
118
+ }
119
+ }
120
+
121
+ &[aria-disabled="true"] {
122
+ cursor: default;
123
+ opacity: 0.3;
124
+ }
125
+
126
+ svg {
127
+ -webkit-touch-callout: none;
128
+ block-size: var(--lexxy-toolbar-icon-size);
129
+ fill: currentColor;
130
+ grid-area: 1/1;
131
+ inline-size: var(--lexxy-toolbar-icon-size);
132
+ user-select: none;
133
+ }
134
+ }
135
+
136
+ :where(.lexxy-editor__toolbar-spacer) {
137
+ flex: 1;
138
+ }
139
+
140
+ /* Make sure spacer is only displayed if there's another button before it */
141
+ * + :where(.lexxy-editor__toolbar-spacer) {
142
+ min-inline-size: 1lh;
143
+ }
144
+
145
+ :where(.lexxy-editor__toolbar-overflow) {
146
+ display: none;
147
+ justify-self: flex-end;
148
+ position: relative;
149
+ z-index: 1;
150
+
151
+ summary {
152
+ list-style: none;
153
+
154
+ &::-webkit-details-marker {
155
+ display: none;
156
+ }
157
+
158
+ [open] & {
159
+ background-color: var(--lexxy-color-ink-lightest);
160
+ }
161
+ }
162
+ }
163
+
164
+ :where(.lexxy-editor__toolbar-overflow-menu) {
165
+ background-color: var(--lexxy-color-canvas);
166
+ border-radius: calc(var(--lexxy-radius) + var(--lexxy-toolbar-gap));
167
+ box-shadow: var(--lexxy-shadow);
168
+ display: grid;
169
+ grid-template-columns: repeat(4, 1fr);
170
+ gap: var(--lexxy-toolbar-gap);
171
+ inset-inline-end: 0;
172
+ padding: var(--lexxy-toolbar-gap);
173
+ position: absolute;
174
+
175
+ .lexxy-editor__toolbar-spacer {
176
+ display: none;
177
+ }
178
+
179
+ * + .lexxy-editor__toolbar-spacer + button {
180
+ margin-left: 0.5lh;
181
+ }
182
+ }
183
+
184
+ /* Dropdowns
185
+ /* -------------------------------------------------------------------------- */
186
+
187
+ :where(.lexxy-editor__toolbar-dropdown) {
188
+ position: relative;
189
+ user-select: none;
190
+ -webkit-user-select: none;
191
+
192
+ .lexxy-editor__toolbar-dropdown-content {
193
+ --dropdown-padding: 1ch;
194
+ --dropdown-gap: calc(var(--dropdown-padding) / 2);
195
+
196
+ background-color: var(--lexxy-color-canvas);
197
+ border: 2px solid var(--lexxy-color-selected-hover);
198
+ border-radius: var(--lexxy-radius);
199
+ border-start-start-radius: 0;
200
+ box-sizing: border-box;
201
+ color: var(--lexxy-color-ink);
202
+ display: flex;
203
+ gap: var(--dropdown-gap);
204
+ inset-block-start: 2lh;
205
+ inset-inline-start: 0;
206
+ max-inline-size: 40ch;
207
+ margin: 0;
208
+ padding: var(--dropdown-padding);
209
+ position: absolute;
210
+ z-index: 3;
211
+ }
212
+
213
+ &:is([open]) .lexxy-editor__toolbar-button {
214
+ background-color: var(--lexxy-color-selected-hover);
215
+ border-end-end-radius: 0;
216
+ border-end-start-radius: 0;
217
+
218
+ &:hover {
219
+ background-color: var(--lexxy-color-selected-hover);
220
+ }
221
+ }
222
+
223
+ [overflowing] & {
224
+ position: static;
225
+
226
+ .lexxy-editor__toolbar-dropdown-content {
227
+ --dropdown-padding: 0.5ch;
228
+ inset-inline-end: var(--dropdown-padding);
229
+ inset-inline-start: var(--dropdown-padding);
230
+ }
231
+ }
232
+ }
233
+
234
+ /* Link dropdown
235
+ /* -------------------------------------------------------------------------- */
236
+
237
+ :where(lexxy-link-dropdown) {
238
+
239
+ > * { flex: 1; }
240
+
241
+ .lexxy-editor__toolbar-dropdown-actions {
242
+ display: flex;
243
+ font-size: var(--lexxy-text-small);
244
+ flex: 1 1 0%;
245
+ gap: 1ch;
246
+ margin-block-start: 1ch;
247
+ }
248
+
249
+ input[type="url"],
250
+ button {
251
+ line-height: 1.5lh;
252
+ padding-inline: 1ch;
253
+ }
254
+
255
+ input[type="url"] {
256
+ background-color: var(--lexxy-color-canvas);
257
+ border: 1px solid var(--lexxy-color-ink-lighter);
258
+ border-radius: var(--lexxy-radius);
259
+ color: var(--lexxy-color-text);
260
+ box-sizing: border-box;
261
+ inline-size: 100%;
262
+ min-inline-size: 40ch;
263
+
264
+ [overflowing] & {
265
+ min-inline-size: 0;
266
+ }
267
+ }
268
+
269
+ button {
270
+ background-color: var(--lexxy-color-ink-lightest);
271
+ color: var(--lexxy-color-text);
272
+ inline-size: 100%;
273
+ justify-content: center;
274
+ }
275
+
276
+ button[type="submit"] {
277
+ background-color: var(--lexxy-color-accent-dark);
278
+ color: var(--lexxy-color-ink-inverted);
279
+
280
+ &:hover {
281
+ background-color: var(--lexxy-color-accent-medium);
282
+ }
283
+ }
284
+ }
285
+
286
+ /* Color dropdown
287
+ /* -------------------------------------------------------------------------- */
288
+
289
+ :where(lexxy-highlight-dropdown) {
290
+ display: flex;
291
+ flex-direction: column;
292
+
293
+ [data-button-group] {
294
+ display: flex;
295
+ justify-items: flex-start;
296
+ flex-direction: row;
297
+ gap: var(--dropdown-gap);
298
+
299
+ button {
300
+ aspect-ratio: 1 / 1;
301
+ inline-size: var(--button-size);
302
+ min-inline-size: var(--button-size);
303
+ max-inline-size: var(--button-size);
304
+
305
+ &:after {
306
+ align-self: center;
307
+ content: "Aa";
308
+ display: inline-block;
309
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
310
+ position: absolute;
311
+ inset-block-start: 0;
312
+ inset-block-end: 0;
313
+ inset-inline-end: 0;
314
+ inset-inline-start: 0;
315
+ }
316
+ }
317
+ }
318
+
319
+ button {
320
+ --button-size: 2lh;
321
+
322
+ color: var(--lexxy-color-text);
323
+ flex: 1;
324
+ min-block-size: var(--button-size);
325
+ position: relative;
326
+
327
+ &:hover {
328
+ opacity: 0.8;
329
+ }
330
+
331
+ &[aria-pressed="true"] {
332
+ box-shadow: 0 0 0 2px currentColor inset;
333
+
334
+ &:after {
335
+ content: "✓";
336
+ }
337
+ }
338
+ }
339
+
340
+ .lexxy-editor__toolbar-dropdown-reset[disabled] {
341
+ display: none;
342
+ }
343
+
344
+ [overflowing] & {
345
+ inline-size: fit-content;
346
+
347
+ [data-button-group] {
348
+ flex-wrap: wrap;
349
+
350
+ button {
351
+ --button-size: 1.6lh;
352
+
353
+ &:after {
354
+ font-size: 0.9em;
355
+ }
356
+ }
357
+ }
358
+ }
359
+ }
360
+
361
+
362
+ /* Language picker
363
+ /* -------------------------------------------------------------------------- */
364
+
365
+ :where(.lexxy-code-language-picker) {
366
+ -webkit-appearance: none;
367
+ appearance: none;
368
+ background-color: var(--lexxy-color-canvas);
369
+ background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='m12 19.5c-.7 0-1.3-.3-1.7-.8l-9.8-11.1c-.7-.8-.6-1.9.2-2.6.8-.6 1.9-.6 2.5.2l8.6 9.8c0 .1.2.1.4 0l8.6-9.8c.7-.8 1.8-.9 2.6-.2s.9 1.8.2 2.6l-9.8 11.1c-.4.5-1.1.8-1.7.8z' fill='%23000'/%3E%3C/svg%3E");
370
+ background-position: center right 1ch;
371
+ background-repeat: no-repeat;
372
+ background-size: 1ch;
373
+ block-size: 1.5lh;
374
+ border: 1px solid var(--lexxy-color-ink-lighter);
375
+ border-radius: var(--lexxy-radius);
376
+ color: var(--lexxy-color-ink);
377
+ font-family: var(--lexxy-font-base);
378
+ font-size: var(--lexxy-text-small);
379
+ font-weight: normal;
380
+ inset-inline-end: var(--lexxy-editor-padding);
381
+ margin: 0.5ch 0.5ch 0 -0.5ch;
382
+ padding: 0 2ch 0 1ch;
383
+ text-align: start;
384
+
385
+ @media (prefers-color-scheme: dark) {
386
+ background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='m12 19.5c-.7 0-1.3-.3-1.7-.8l-9.8-11.1c-.7-.8-.6-1.9.2-2.6.8-.6 1.9-.6 2.5.2l8.6 9.8c0 .1.2.1.4 0l8.6-9.8c.7-.8 1.8-.9 2.6-.2s.9 1.8.2 2.6l-9.8 11.1c-.4.5-1.1.8-1.7.8z' fill='%23fff'/%3E%3C/svg%3E");
387
+ }
388
+ }
389
+
390
+ /* Prompt
391
+ /* ------------------------------------------------------------------------ */
392
+
393
+ :where(.lexxy-prompt-menu) {
394
+ --lexxy-prompt-avatar-size: 24px;
395
+ --lexxy-prompt-min-width: 20ch;
396
+ --lexxy-prompt-padding: 0.5ch;
397
+
398
+ background-color: var(--lexxy-color-canvas);
399
+ border-radius: calc(var(--lexxy-prompt-padding) * 2);
400
+ box-shadow: var(--lexxy-shadow);
401
+ color: var(--lexxy-color-ink);
402
+ font-family: var(--lexxy-font-base);
403
+ font-size: var(--lexxy-text-small);
404
+ list-style: none;
405
+ margin: 0;
406
+ max-block-size: 200px;
407
+ min-inline-size: var(--lexxy-prompt-min-width);
408
+ overflow: auto;
409
+ padding: var(--lexxy-prompt-padding);
410
+ visibility: hidden;
411
+ z-index: var(--lexxy-z-popup);
412
+ }
413
+
414
+ :where(.lexxy-prompt-menu--visible) {
415
+ visibility: initial;
416
+ }
417
+
418
+ :where(.lexxy-prompt-menu__item) {
419
+ align-items: center;
420
+ border-radius: var(--lexxy-radius);
421
+ cursor: pointer;
422
+ display: flex;
423
+ gap: var(--lexxy-prompt-padding);
424
+ padding: var(--lexxy-prompt-padding);
425
+ white-space: nowrap;
426
+
427
+ &:hover {
428
+ background-color: var(--lexxy-color-ink-lightest);
429
+ }
430
+
431
+ &[aria-selected] {
432
+ background-color: var(--lexxy-color-selected);
433
+ }
434
+
435
+ img {
436
+ block-size: var(--lexxy-prompt-avatar-size);
437
+ border-radius: 50%;
438
+ flex-shrink: 0;
439
+ inline-size: var(--lexxy-prompt-avatar-size);
440
+ margin: 0;
441
+ }
442
+
443
+ + & {
444
+ margin-top: 2px;
445
+ }
446
+ }
447
+
448
+ :where(.lexxy-prompt-menu__item--empty) {
449
+ color: var(--lexxy-color-ink-medium);
450
+ padding: var(--lexxy-prompt-padding);
451
+ }
@@ -0,0 +1,73 @@
1
+ :root {
2
+ /* Colors */
3
+ --lexxy-color-ink: oklch(20% 0 0);
4
+ --lexxy-color-ink-medium: oklch(40% 0 0);
5
+ --lexxy-color-ink-light: oklch(60% 0 0);
6
+ --lexxy-color-ink-lighter: oklch(85% 0 0);
7
+ --lexxy-color-ink-lightest: oklch(96% 0 0);
8
+ --lexxy-color-ink-inverted: white;
9
+
10
+ --lexxy-color-accent-dark: oklch(57% 0.19 260);
11
+ --lexxy-color-accent-medium: oklch(75% 0.196 258);
12
+ --lexxy-color-accent-light: oklch(88% 0.026 254);
13
+ --lexxy-color-accent-lightest: oklch(92% 0.026 254);
14
+
15
+ --lexxy-color-red: oklch(60% 0.15 27);
16
+ --lexxy-color-green: oklch(60% 0.15 145);
17
+ --lexxy-color-blue: oklch(66% 0.196 258);
18
+ --lexxy-color-purple: oklch(60% 0.15 305);
19
+
20
+ --lexxy-color-code-token-att: #d73a49;
21
+ --lexxy-color-code-token-comment: #6a737d;
22
+ --lexxy-color-code-token-function: #6f42c1;
23
+ --lexxy-color-code-token-operator: #d73a49;
24
+ --lexxy-color-code-token-property: #005cc5;
25
+ --lexxy-color-code-token-punctuation: #24292e;
26
+ --lexxy-color-code-token-selector: #22863a;
27
+ --lexxy-color-code-token-variable: #e36209;
28
+
29
+ --lexxy-color-canvas: var(--lexxy-color-ink-inverted);
30
+ --lexxy-color-text: var(--lexxy-color-ink);
31
+ --lexxy-color-text-subtle: var(--lexxy-color-ink-medium);
32
+ --lexxy-color-link: var(--lexxy-color-accent-dark);
33
+ --lexxy-color-selected: var(--lexxy-color-accent-lightest);
34
+ --lexxy-color-selected-hover: var(--lexxy-color-accent-light);
35
+ --lexxy-color-selected-dark: var(--lexxy-color-blue);
36
+ --lexxy-color-code-bg: var(--lexxy-color-ink-lightest);
37
+
38
+ --highlight-1: rgb(136, 118, 38);
39
+ --highlight-2: rgb(185, 94, 6);
40
+ --highlight-3: rgb(207, 0, 0);
41
+ --highlight-4: rgb(216, 28, 170);
42
+ --highlight-5: rgb(144, 19, 254);
43
+ --highlight-6: rgb(5, 98, 185);
44
+ --highlight-7: rgb(17, 138, 15);
45
+ --highlight-8: rgb(148, 82, 22);
46
+ --highlight-9: rgb(102, 102, 102);
47
+
48
+ --highlight-bg-1: rgba(229, 223, 6, 0.3);
49
+ --highlight-bg-2: rgba(255, 185, 87, 0.3);
50
+ --highlight-bg-3: rgba(255, 118, 118, 0.3);
51
+ --highlight-bg-4: rgba(248, 137, 216, 0.3);
52
+ --highlight-bg-5: rgba(190, 165, 255, 0.3);
53
+ --highlight-bg-6: rgba(124, 192, 252, 0.3);
54
+ --highlight-bg-7: rgba(140, 255, 129, 0.3);
55
+ --highlight-bg-8: rgba(221, 170, 123, 0.3);
56
+ --highlight-bg-9: rgba(200, 200, 200, 0.3);
57
+
58
+ /* Typography */
59
+ --lexxy-font-base: system-ui, sans-serif;
60
+ --lexxy-font-mono: ui-monospace, "Menlo", "Monaco", Consolas, monospace;
61
+ --lexxy-text-small: 0.875rem;
62
+ --lexxy-content-margin: 1rem;
63
+
64
+ /* Focus ring */
65
+ --lexxy-focus-ring-color: var(--lexxy-color-accent-dark);
66
+ --lexxy-focus-ring-offset: 0;
67
+ --lexxy-focus-ring-size: 2px;
68
+
69
+ /* Misc */
70
+ --lexxy-radius: 0.5ch;
71
+ --lexxy-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
72
+ --lexxy-z-popup: 1000;
73
+ }
@@ -0,0 +1,2 @@
1
+ @import url("lexxy-content.css");
2
+ @import url("lexxy-editor.css");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@37signals/lexxy",
3
- "version": "0.1.22-beta",
3
+ "version": "0.1.23-beta",
4
4
  "description": "Lexxy - A modern rich text editor for Rails.",
5
5
  "module": "dist/lexxy.esm.js",
6
6
  "type": "module",
@@ -17,12 +17,13 @@
17
17
  "@rollup/plugin-terser": "^0.4.4",
18
18
  "eslint": "^9.15.0",
19
19
  "rollup": "^4.44.1",
20
+ "rollup-plugin-copy": "^3.5.0",
20
21
  "rollup-plugin-gzip": "^4.1.1"
21
22
  },
22
23
  "scripts": {
23
24
  "build": "rollup -c",
24
25
  "build:npm": "rollup -c rollup.config.npm.mjs",
25
- "watch": "rollup -wc",
26
+ "watch": "NODE_ENV=development rollup -wc --watch.onEnd=\"rails restart\"",
26
27
  "lint": "eslint",
27
28
  "prerelease": "yarn build:npm",
28
29
  "release": "yarn build:npm && yarn publish"