@domternal/theme 0.2.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.
@@ -0,0 +1,219 @@
1
+ // =============================================================================
2
+ // Emoji Picker & Suggestion Styles
3
+ // =============================================================================
4
+ // Both components live outside .dm-toolbar, so we use .dm-editor base variables
5
+ // (--dm-surface, --dm-border-color, --dm-text, --dm-hover, --dm-active, --dm-accent)
6
+ // with hardcoded fallbacks for standalone usage.
7
+ // =============================================================================
8
+
9
+ // ─── Toolbar Emoji Picker Panel ─────────────────────────────────────────────
10
+
11
+ .dm-emoji-picker {
12
+ position: absolute;
13
+ z-index: 100;
14
+ width: 20rem;
15
+ max-height: 22rem;
16
+ display: flex;
17
+ flex-direction: column;
18
+ background: var(--dm-surface, #f8f9fa);
19
+ border: 1px solid var(--dm-border-color, #e0e0e0);
20
+ border-radius: 0.25rem;
21
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
22
+ overflow: hidden;
23
+ animation: dm-fade-in 0.2s ease;
24
+ }
25
+
26
+ // Search input
27
+ .dm-emoji-picker-search {
28
+ flex-shrink: 0;
29
+ padding: 0.5rem;
30
+ border-bottom: 1px solid var(--dm-border-color, #e0e0e0);
31
+
32
+ input {
33
+ width: 100%;
34
+ padding: 0.375rem 0.5rem;
35
+ border: 1px solid var(--dm-border-color, #e0e0e0);
36
+ border-radius: 0.25rem;
37
+ background: var(--dm-bg, #ffffff);
38
+ color: var(--dm-text, #1a1a1a);
39
+ font-size: 0.8125rem;
40
+ outline: none;
41
+ box-sizing: border-box;
42
+
43
+ &:focus {
44
+ border-color: var(--dm-accent, #2563eb);
45
+ }
46
+
47
+ &::placeholder {
48
+ color: var(--dm-muted, #999999);
49
+ }
50
+ }
51
+ }
52
+
53
+ // Category tabs
54
+ .dm-emoji-picker-tabs {
55
+ display: flex;
56
+ align-items: center;
57
+ flex-shrink: 0;
58
+ padding: 0.375rem 0.5rem;
59
+ gap: 0.1rem;
60
+ border-bottom: 1px solid var(--dm-border-color, #e0e0e0);
61
+ overflow-x: auto;
62
+
63
+ // Hide scrollbar
64
+ scrollbar-width: none;
65
+ &::-webkit-scrollbar { display: none; }
66
+ }
67
+
68
+ .dm-emoji-picker-tab {
69
+ display: flex;
70
+ align-items: center;
71
+ justify-content: center;
72
+ width: 2rem;
73
+ height: 2rem;
74
+ flex-shrink: 0;
75
+ padding: 0;
76
+ border: none;
77
+ border-radius: 0.375rem;
78
+ background: transparent;
79
+ cursor: pointer;
80
+ font-size: 1.25rem;
81
+ line-height: 1;
82
+ opacity: 0.5;
83
+ transition: opacity 0.15s, background-color 0.15s;
84
+
85
+ &:hover {
86
+ opacity: 1;
87
+ background: var(--dm-hover, rgba(0, 0, 0, 0.06));
88
+ }
89
+
90
+ &--active {
91
+ opacity: 1;
92
+ background: var(--dm-active, rgba(0, 0, 0, 0.12));
93
+ }
94
+ }
95
+
96
+ // Scrollable grid
97
+ .dm-emoji-picker-grid {
98
+ flex: 1;
99
+ overflow-y: auto;
100
+ padding: 0.25rem 0.5rem 0.5rem;
101
+ display: grid;
102
+ grid-template-columns: repeat(8, 1fr);
103
+ gap: 0.125rem;
104
+ align-content: start;
105
+ }
106
+
107
+ // Category heading in grid
108
+ .dm-emoji-picker-category-label {
109
+ grid-column: 1 / -1;
110
+ font-size: 0.6875rem;
111
+ font-weight: 600;
112
+ color: var(--dm-text, #1a1a1a);
113
+ opacity: 0.6;
114
+ padding: 0.375rem 0 0.125rem;
115
+ text-transform: uppercase;
116
+ letter-spacing: 0.03em;
117
+ }
118
+
119
+ // Individual emoji button in grid
120
+ .dm-emoji-swatch {
121
+ display: flex;
122
+ align-items: center;
123
+ justify-content: center;
124
+ width: 2rem;
125
+ height: 2rem;
126
+ padding: 0;
127
+ border: none;
128
+ border-radius: 0.25rem;
129
+ background: transparent;
130
+ cursor: pointer;
131
+ font-size: 1.25rem;
132
+ line-height: 1;
133
+ transition: background-color 0.1s, transform 0.1s;
134
+
135
+ &:hover {
136
+ background: var(--dm-hover, rgba(0, 0, 0, 0.06));
137
+ transform: scale(1.15);
138
+ }
139
+ }
140
+
141
+ // "No emoji found" message
142
+ .dm-emoji-picker-empty {
143
+ grid-column: 1 / -1;
144
+ padding: 1rem;
145
+ text-align: center;
146
+ color: var(--dm-text, #1a1a1a);
147
+ opacity: 0.5;
148
+ font-size: 0.8125rem;
149
+ }
150
+
151
+ // ─── Inline Suggestion Dropdown ─────────────────────────────────────────────
152
+
153
+ .dm-emoji-suggestion {
154
+ position: absolute;
155
+ z-index: 100;
156
+ min-width: 12rem;
157
+ max-width: 18rem;
158
+ padding: 0.25rem;
159
+ background: var(--dm-surface, #f8f9fa);
160
+ border: 1px solid var(--dm-border-color, #e0e0e0);
161
+ border-radius: 0.25rem;
162
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
163
+ animation: dm-fade-in 0.2s ease;
164
+ }
165
+
166
+ .dm-emoji-suggestion-item {
167
+ display: flex;
168
+ align-items: center;
169
+ gap: 0.5rem;
170
+ width: 100%;
171
+ padding: 0.375rem 0.5rem;
172
+ border: none;
173
+ border-radius: 0.25rem;
174
+ background: transparent;
175
+ color: var(--dm-text, #1a1a1a);
176
+ cursor: pointer;
177
+ font-size: 0.8125rem;
178
+ line-height: 1.4;
179
+ text-align: left;
180
+ transition: background-color 0.1s;
181
+
182
+ &:hover,
183
+ &--selected {
184
+ background: var(--dm-hover, rgba(0, 0, 0, 0.06));
185
+ }
186
+ }
187
+
188
+ .dm-emoji-suggestion-emoji {
189
+ font-size: 1.125rem;
190
+ line-height: 1;
191
+ flex-shrink: 0;
192
+ }
193
+
194
+ .dm-emoji-suggestion-name {
195
+ overflow: hidden;
196
+ text-overflow: ellipsis;
197
+ white-space: nowrap;
198
+ }
199
+
200
+ .dm-emoji-suggestion-empty {
201
+ padding: 0.5rem;
202
+ text-align: center;
203
+ color: var(--dm-text, #1a1a1a);
204
+ opacity: 0.5;
205
+ font-size: 0.8125rem;
206
+ }
207
+
208
+ // ─── Inline Emoji Node ──────────────────────────────────────────────────────
209
+
210
+ .dm-editor .ProseMirror span.emoji {
211
+ cursor: default;
212
+ font-style: normal;
213
+ padding: 0 0.05em;
214
+
215
+ &.ProseMirror-selectednode {
216
+ outline: 2px solid var(--dm-accent, #2563eb);
217
+ border-radius: 0.15em;
218
+ }
219
+ }
@@ -0,0 +1,24 @@
1
+ // =============================================================================
2
+ // Floating Menu Styles
3
+ // =============================================================================
4
+
5
+ .dm-floating-menu {
6
+ position: absolute;
7
+ display: flex;
8
+ flex-direction: column;
9
+ gap: var(--dm-toolbar-gap);
10
+ padding: var(--dm-toolbar-padding);
11
+ background: var(--dm-toolbar-bg);
12
+ border: var(--dm-toolbar-border);
13
+ border-radius: var(--dm-button-border-radius);
14
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
15
+ visibility: hidden;
16
+ opacity: 0;
17
+ transition: opacity 0.2s ease, visibility 0.2s;
18
+ z-index: 50;
19
+
20
+ &[data-show] {
21
+ visibility: visible;
22
+ opacity: 1;
23
+ }
24
+ }
@@ -0,0 +1,224 @@
1
+ // =============================================================================
2
+ // Image Styles
3
+ // =============================================================================
4
+ // Image extension renders as <img> with optional float inline styles.
5
+ // Base img styles are in _content.scss — this file adds float constraints.
6
+ // =============================================================================
7
+
8
+ .dm-editor .ProseMirror {
9
+ img {
10
+ // Floated images shouldn't exceed 60% width
11
+ &[style*="float: left"],
12
+ &[style*="float: right"] {
13
+ max-width: 60%;
14
+ }
15
+ }
16
+ }
17
+
18
+ // Resizable image wrapper (NodeView)
19
+ .dm-editor .ProseMirror {
20
+ .dm-image-resizable {
21
+ position: relative;
22
+ display: inline-block;
23
+ max-width: 100%;
24
+ margin: 0.75em 0;
25
+ line-height: 0;
26
+
27
+ img {
28
+ display: block;
29
+ max-width: 100%;
30
+ height: auto;
31
+ }
32
+
33
+ // Float variants via data attribute
34
+ &[data-float="left"] { float: left; margin: 0 1em 1em 0; }
35
+ &[data-float="right"] { float: right; margin: 0 0 1em 1em; }
36
+ &[data-float="center"] {
37
+ display: block;
38
+ width: fit-content;
39
+ margin-left: auto;
40
+ margin-right: auto;
41
+ }
42
+ &[data-float="left"],
43
+ &[data-float="right"] {
44
+ max-width: 60%;
45
+ z-index: 1; // above inline text so clicks always hit the image, not the paragraph behind
46
+ }
47
+
48
+ // Selected state — accent outline + visible handles
49
+ &.ProseMirror-selectednode {
50
+ outline: 2px solid var(--dm-accent, #2563eb);
51
+
52
+ .dm-image-handle {
53
+ display: block;
54
+ }
55
+ }
56
+ }
57
+
58
+ // Resize handles — hidden by default, shown on selection
59
+ .dm-image-handle {
60
+ display: none;
61
+ position: absolute;
62
+ width: 8px;
63
+ height: 8px;
64
+ background: var(--dm-accent, #2563eb);
65
+ border: 1px solid #fff;
66
+ border-radius: 1px;
67
+ z-index: 5;
68
+
69
+ &-nw { top: -4px; left: -4px; cursor: nw-resize; }
70
+ &-ne { top: -4px; right: -4px; cursor: ne-resize; }
71
+ &-sw { bottom: -4px; left: -4px; cursor: sw-resize; }
72
+ &-se { bottom: -4px; right: -4px; cursor: se-resize; }
73
+ }
74
+ }
75
+
76
+ // =============================================================================
77
+ // Image Insert Popover (appended to document.body — same pattern as link popover)
78
+ // =============================================================================
79
+
80
+ .dm-image-popover {
81
+ position: fixed;
82
+ display: flex;
83
+ align-items: center;
84
+ gap: 0.25rem;
85
+ padding: 0.25rem;
86
+ background: #f8f9fa;
87
+ border: 1px solid #e0e0e0;
88
+ border-radius: 0.25rem;
89
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
90
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
91
+ Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
92
+ visibility: hidden;
93
+ opacity: 0;
94
+ transition: opacity 0.2s ease, visibility 0.2s;
95
+ z-index: 60;
96
+
97
+ &[data-show] {
98
+ visibility: visible;
99
+ opacity: 1;
100
+ }
101
+ }
102
+
103
+ .dm-image-popover-input {
104
+ border: 1px solid #e0e0e0;
105
+ border-radius: 0.25rem;
106
+ padding: 0.25rem 0.5rem;
107
+ font-size: 0.8125rem;
108
+ font-family: inherit;
109
+ min-width: 14rem;
110
+ outline: none;
111
+ background: #fff;
112
+ color: #1a1a1a;
113
+
114
+ &:focus {
115
+ border-color: #2563eb;
116
+ }
117
+ }
118
+
119
+ .dm-image-popover-btn {
120
+ display: inline-flex;
121
+ align-items: center;
122
+ justify-content: center;
123
+ width: 1.5rem;
124
+ height: 1.5rem;
125
+ padding: 0;
126
+ border: none;
127
+ border-radius: 0.25rem;
128
+ background: transparent;
129
+ color: #1a1a1a;
130
+ cursor: pointer;
131
+ transition: background-color 0.15s, color 0.15s;
132
+
133
+ &:hover {
134
+ background: rgba(0, 0, 0, 0.06);
135
+ }
136
+
137
+ svg {
138
+ width: 0.875rem;
139
+ height: 0.875rem;
140
+ }
141
+ }
142
+
143
+ .dm-image-popover-apply:hover {
144
+ color: #2563eb;
145
+ }
146
+
147
+ .dm-image-popover-browse:hover {
148
+ color: #2563eb;
149
+ }
150
+
151
+ // Dark theme override
152
+ [data-theme="dark"] .dm-image-popover,
153
+ .dm-theme-dark .dm-image-popover {
154
+ background: #2a2a2a;
155
+ border-color: #404040;
156
+
157
+ .dm-image-popover-input {
158
+ background: #1a1a1a;
159
+ border-color: #404040;
160
+ color: #e0e0e0;
161
+
162
+ &:focus {
163
+ border-color: #3b82f6;
164
+ }
165
+ }
166
+
167
+ .dm-image-popover-btn {
168
+ color: #e0e0e0;
169
+
170
+ &:hover {
171
+ background: rgba(255, 255, 255, 0.1);
172
+ }
173
+ }
174
+
175
+ .dm-image-popover-apply:hover {
176
+ color: #3b82f6;
177
+ }
178
+ }
179
+
180
+ // Auto dark mode — follows system preference
181
+ @media (prefers-color-scheme: dark) {
182
+ .dm-theme-auto .dm-image-popover {
183
+ background: #2a2a2a;
184
+ border-color: #404040;
185
+
186
+ .dm-image-popover-input {
187
+ background: #1a1a1a;
188
+ border-color: #404040;
189
+ color: #e0e0e0;
190
+
191
+ &:focus {
192
+ border-color: #3b82f6;
193
+ }
194
+ }
195
+
196
+ .dm-image-popover-btn {
197
+ color: #e0e0e0;
198
+
199
+ &:hover {
200
+ background: rgba(255, 255, 255, 0.1);
201
+ }
202
+ }
203
+
204
+ .dm-image-popover-apply:hover {
205
+ color: #3b82f6;
206
+ }
207
+ }
208
+ }
209
+
210
+ // Drag-and-drop overlay — shown when dragging image files over the editor
211
+ .dm-editor.dm-dragover {
212
+ outline: 2px dashed var(--dm-accent);
213
+ outline-offset: -2px;
214
+
215
+ &::after {
216
+ content: '';
217
+ position: absolute;
218
+ inset: 0;
219
+ background: var(--dm-accent);
220
+ opacity: 0.05;
221
+ pointer-events: none;
222
+ z-index: 10;
223
+ }
224
+ }
@@ -0,0 +1,44 @@
1
+ // =============================================================================
2
+ // Invisible Characters
3
+ // =============================================================================
4
+ // Styles for the InvisibleChars extension decorations.
5
+ // Widget decorations (¶, ↵) use .invisible-char with type modifiers.
6
+ // Inline decorations (spaces, nbsp) use [data-char] attributes.
7
+ // =============================================================================
8
+
9
+ .dm-editor .ProseMirror {
10
+ // Widget decorations (paragraph marks, hard breaks)
11
+ .invisible-char {
12
+ color: var(--dm-invisible-char-color, var(--dm-muted, #999));
13
+ pointer-events: none;
14
+ user-select: none;
15
+ }
16
+
17
+ // Inline space decorations — overlay · on the invisible space character
18
+ [data-char="space"] {
19
+ position: relative;
20
+
21
+ &::after {
22
+ content: '·';
23
+ position: absolute;
24
+ inset: 0;
25
+ text-align: center;
26
+ color: var(--dm-invisible-char-color, var(--dm-muted, #999));
27
+ pointer-events: none;
28
+ }
29
+ }
30
+
31
+ // Inline non-breaking space decorations — overlay ° on the nbsp character
32
+ [data-char="nbsp"] {
33
+ position: relative;
34
+
35
+ &::after {
36
+ content: '°';
37
+ position: absolute;
38
+ inset: 0;
39
+ text-align: center;
40
+ color: var(--dm-invisible-char-color, var(--dm-muted, #999));
41
+ pointer-events: none;
42
+ }
43
+ }
44
+ }
@@ -0,0 +1,144 @@
1
+ // =============================================================================
2
+ // Link Popover Styles
3
+ // =============================================================================
4
+ // The popover is appended to document.body (to escape overflow:hidden on
5
+ // .dm-editor), so it can't inherit CSS variables from .dm-editor / .dm-toolbar.
6
+ // We hardcode fallback values that match the light theme defaults.
7
+ // =============================================================================
8
+
9
+ .dm-link-popover {
10
+ position: fixed;
11
+ display: flex;
12
+ align-items: center;
13
+ gap: 0.25rem;
14
+ padding: 0.25rem;
15
+ background: #f8f9fa;
16
+ border: 1px solid #e0e0e0;
17
+ border-radius: 0.25rem;
18
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
19
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
20
+ Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
21
+ visibility: hidden;
22
+ opacity: 0;
23
+ transition: opacity 0.2s ease, visibility 0.2s;
24
+ z-index: 60;
25
+
26
+ &[data-show] {
27
+ visibility: visible;
28
+ opacity: 1;
29
+ }
30
+ }
31
+
32
+ .dm-link-popover-input {
33
+ border: 1px solid #e0e0e0;
34
+ border-radius: 0.25rem;
35
+ padding: 0.25rem 0.5rem;
36
+ font-size: 0.8125rem;
37
+ font-family: inherit;
38
+ min-width: 14rem;
39
+ outline: none;
40
+ background: #fff;
41
+ color: #1a1a1a;
42
+
43
+ &:focus {
44
+ border-color: #2563eb;
45
+ }
46
+ }
47
+
48
+ .dm-link-popover-btn {
49
+ display: inline-flex;
50
+ align-items: center;
51
+ justify-content: center;
52
+ width: 1.5rem;
53
+ height: 1.5rem;
54
+ padding: 0;
55
+ border: none;
56
+ border-radius: 0.25rem;
57
+ background: transparent;
58
+ color: #1a1a1a;
59
+ cursor: pointer;
60
+ transition: background-color 0.15s, color 0.15s;
61
+
62
+ &:hover {
63
+ background: rgba(0, 0, 0, 0.06);
64
+ }
65
+
66
+ svg {
67
+ width: 0.875rem;
68
+ height: 0.875rem;
69
+ }
70
+ }
71
+
72
+ .dm-link-popover-apply:hover {
73
+ color: #2563eb;
74
+ }
75
+
76
+ .dm-link-popover-remove:hover {
77
+ color: #dc2626;
78
+ }
79
+
80
+ // Pending-link decoration — highlights the text range while the popover
81
+ // input has focus (browser hides native selection on editor blur).
82
+ .dm-link-pending {
83
+ background-color: rgba(37, 99, 235, 0.12);
84
+ border-radius: 1px;
85
+ }
86
+
87
+ // Dark theme override
88
+ [data-theme="dark"] .dm-link-popover,
89
+ .dm-theme-dark .dm-link-popover {
90
+ background: #2a2a2a;
91
+ border-color: #404040;
92
+
93
+ .dm-link-popover-input {
94
+ background: #1a1a1a;
95
+ border-color: #404040;
96
+ color: #e0e0e0;
97
+
98
+ &:focus {
99
+ border-color: #3b82f6;
100
+ }
101
+ }
102
+
103
+ .dm-link-popover-btn {
104
+ color: #e0e0e0;
105
+
106
+ &:hover {
107
+ background: rgba(255, 255, 255, 0.1);
108
+ }
109
+ }
110
+
111
+ .dm-link-popover-apply:hover {
112
+ color: #3b82f6;
113
+ }
114
+ }
115
+
116
+ // Auto dark mode — follows system preference
117
+ @media (prefers-color-scheme: dark) {
118
+ .dm-theme-auto .dm-link-popover {
119
+ background: #2a2a2a;
120
+ border-color: #404040;
121
+
122
+ .dm-link-popover-input {
123
+ background: #1a1a1a;
124
+ border-color: #404040;
125
+ color: #e0e0e0;
126
+
127
+ &:focus {
128
+ border-color: #3b82f6;
129
+ }
130
+ }
131
+
132
+ .dm-link-popover-btn {
133
+ color: #e0e0e0;
134
+
135
+ &:hover {
136
+ background: rgba(255, 255, 255, 0.1);
137
+ }
138
+ }
139
+
140
+ .dm-link-popover-apply:hover {
141
+ color: #3b82f6;
142
+ }
143
+ }
144
+ }
@@ -0,0 +1,25 @@
1
+ // =============================================================================
2
+ // Mention Styles
3
+ // =============================================================================
4
+ // Mention renders as span.mention[data-type="mention"]
5
+ // =============================================================================
6
+
7
+ .dm-editor .ProseMirror {
8
+ .mention {
9
+ display: inline;
10
+ background: var(--dm-mention-bg);
11
+ color: var(--dm-mention-color);
12
+ border-radius: var(--dm-mention-border-radius);
13
+ padding: 0.1em 0.3em;
14
+ font-weight: 500;
15
+ font-size: 0.95em;
16
+ white-space: nowrap;
17
+ }
18
+
19
+ // In-progress mention suggestion (typing @name)
20
+ .mention-suggestion {
21
+ text-decoration: underline;
22
+ text-decoration-color: var(--dm-accent, #2563eb);
23
+ text-underline-offset: 2px;
24
+ }
25
+ }
@@ -0,0 +1,16 @@
1
+ // =============================================================================
2
+ // Placeholder Extension Styles
3
+ // =============================================================================
4
+ // Works with the Placeholder extension which adds data-placeholder attribute
5
+ // and .is-empty / .is-editor-empty classes via decorations.
6
+ // =============================================================================
7
+
8
+ .dm-editor .ProseMirror {
9
+ .is-empty::before {
10
+ content: attr(data-placeholder);
11
+ float: left;
12
+ color: var(--dm-placeholder-color);
13
+ pointer-events: none;
14
+ height: 0;
15
+ }
16
+ }