@lyfie/luthor 1.0.0 → 2.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.
- package/README.md +27 -155
- package/dist/index.css +1 -0
- package/dist/index.d.ts +33 -2288
- package/dist/index.js +1 -3
- package/package.json +9 -6
package/README.md
CHANGED
|
@@ -1,48 +1,11 @@
|
|
|
1
|
-
# Luthor
|
|
1
|
+
# Luthor Presets
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Presets and plug-and-play configurations for the Luthor headless editor.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
[](https://badge.fury.io/js/%40luthor%2Feditor)
|
|
8
|
-
[](https://opensource.org/licenses/MIT)
|
|
9
|
-
|
|
10
|
-
**[🚀 Demo](https://luthor.lyfie.app/demo)** • **[📖 Documentation](https://luthor.lyfie.app/docs)** • **[⚡ Playground](https://stackblitz.com/edit/vitejs-vite-bpg2kpze?file=src%2FEditor.tsx)**
|
|
11
|
-
|
|
12
|
-

|
|
13
|
-
|
|
14
|
-
---
|
|
15
|
-
|
|
16
|
-
## Why Luthor?
|
|
17
|
-
|
|
18
|
-
Rich text editors shouldn't be a nightmare. Luthor makes building them delightful:
|
|
19
|
-
|
|
20
|
-
- **🔒 Type-safe everything** - Commands and states inferred from your extensions. No runtime surprises.
|
|
21
|
-
- **🎨 Headless & flexible** - Build any UI you want. Style it your way.
|
|
22
|
-
- **🧩 Modular extensions** - Add only what you need, when you need it.
|
|
23
|
-
- **⚡ Production features** - HTML/Markdown export, image handling, tables, undo/redo.
|
|
24
|
-
- **⚛️ React-first** - Hooks, components, and patterns you already know.
|
|
25
|
-
|
|
26
|
-
```tsx
|
|
27
|
-
// Your extensions define your API - TypeScript knows everything ✨
|
|
28
|
-
const extensions = [boldExtension, listExtension, imageExtension] as const;
|
|
29
|
-
const { Provider, useEditor } = createEditorSystem<typeof extensions>();
|
|
30
|
-
|
|
31
|
-
function MyEditor() {
|
|
32
|
-
const { commands, activeStates } = useEditor();
|
|
33
|
-
|
|
34
|
-
// TypeScript autocompletes and validates these
|
|
35
|
-
commands.toggleBold(); // ✅ Available
|
|
36
|
-
commands.toggleUnorderedList(); // ✅ Available
|
|
37
|
-
commands.insertImage(); // ✅ Available
|
|
38
|
-
commands.nonExistent(); // ❌ TypeScript error
|
|
39
|
-
}
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
## Quick Start
|
|
5
|
+
## Install
|
|
43
6
|
|
|
44
7
|
```bash
|
|
45
|
-
npm install @lyfie/luthor
|
|
8
|
+
npm install @lyfie/luthor @lyfie/luthor-headless
|
|
46
9
|
```
|
|
47
10
|
|
|
48
11
|
Install the Lexical peer dependencies:
|
|
@@ -51,126 +14,35 @@ Install the Lexical peer dependencies:
|
|
|
51
14
|
npm install lexical @lexical/react @lexical/html @lexical/markdown @lexical/list @lexical/rich-text @lexical/selection @lexical/utils
|
|
52
15
|
```
|
|
53
16
|
|
|
54
|
-
|
|
55
|
-
import {
|
|
56
|
-
createEditorSystem,
|
|
57
|
-
boldExtension,
|
|
58
|
-
italicExtension,
|
|
59
|
-
listExtension,
|
|
60
|
-
RichText,
|
|
61
|
-
} from "@lyfie/luthor";
|
|
62
|
-
|
|
63
|
-
const extensions = [boldExtension, italicExtension, listExtension] as const;
|
|
64
|
-
const { Provider, useEditor } = createEditorSystem<typeof extensions>();
|
|
17
|
+
## Usage
|
|
65
18
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
return (
|
|
69
|
-
<div className="toolbar">
|
|
70
|
-
<button
|
|
71
|
-
onClick={() => commands.toggleBold()}
|
|
72
|
-
className={activeStates.bold ? "active" : ""}
|
|
73
|
-
>
|
|
74
|
-
Bold
|
|
75
|
-
</button>
|
|
76
|
-
<button
|
|
77
|
-
onClick={() => commands.toggleItalic()}
|
|
78
|
-
className={activeStates.italic ? "active" : ""}
|
|
79
|
-
>
|
|
80
|
-
Italic
|
|
81
|
-
</button>
|
|
82
|
-
<button onClick={() => commands.toggleUnorderedList()}>
|
|
83
|
-
Bullet List
|
|
84
|
-
</button>
|
|
85
|
-
</div>
|
|
86
|
-
);
|
|
87
|
-
}
|
|
19
|
+
```tsx
|
|
20
|
+
import { presetRegistry, defaultPreset } from "@lyfie/luthor";
|
|
88
21
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
<div className="editor-container">
|
|
92
|
-
<Toolbar />
|
|
93
|
-
<RichText placeholder="Start writing..." />
|
|
94
|
-
</div>
|
|
95
|
-
);
|
|
96
|
-
}
|
|
22
|
+
// Get a preset by id
|
|
23
|
+
const preset = presetRegistry.default;
|
|
97
24
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
<Provider extensions={extensions}>
|
|
101
|
-
<Editor />
|
|
102
|
-
</Provider>
|
|
103
|
-
);
|
|
104
|
-
}
|
|
25
|
+
// Or use a named preset directly
|
|
26
|
+
const explicit = defaultPreset;
|
|
105
27
|
```
|
|
106
28
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
## Features
|
|
29
|
+
## What is included
|
|
110
30
|
|
|
111
|
-
|
|
112
|
-
-
|
|
113
|
-
-
|
|
114
|
-
- **Rich Content**: Tables, images (upload/paste/alignment), links, code blocks
|
|
115
|
-
- **Advanced**: History (undo/redo), command palette, floating toolbar, context menus
|
|
31
|
+
- Preset definitions (toolbar, config, optional theme)
|
|
32
|
+
- Registry lookup by id
|
|
33
|
+
- Readme files describing each preset
|
|
116
34
|
|
|
117
|
-
|
|
118
|
-
- Toggle lists with intelligent nesting behavior
|
|
119
|
-
- Context-aware toolbar (indent/outdent appear when needed)
|
|
120
|
-
- Nested lists without keyboard shortcuts
|
|
121
|
-
- Clean UX that matches modern editors
|
|
35
|
+
## Customization
|
|
122
36
|
|
|
123
|
-
|
|
124
|
-
- **HTML** with semantic markup
|
|
125
|
-
- **Markdown** with GitHub Flavored syntax
|
|
126
|
-
- **JSON** for structured data
|
|
127
|
-
- Custom transformers for specialized formats
|
|
37
|
+
Presets are data objects. You can clone and override any field:
|
|
128
38
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
- Documentation platforms
|
|
140
|
-
- Blog editors
|
|
141
|
-
- Note-taking applications
|
|
142
|
-
- Comment systems
|
|
143
|
-
- Collaborative writing tools
|
|
144
|
-
|
|
145
|
-
## Community & Support
|
|
146
|
-
|
|
147
|
-
- **[💬 Discord](https://discord.gg/RAMYSDRag7)** - Get help, share ideas
|
|
148
|
-
- **[🐛 GitHub Issues](https://github.com/novincode/luthor/issues)** - Bug reports, feature requests
|
|
149
|
-
- **[💭 Discussions](https://github.com/novincode/luthor/discussions)** - Questions, showcase your projects
|
|
150
|
-
|
|
151
|
-
## Contributing
|
|
152
|
-
|
|
153
|
-
We welcome contributions! Whether you:
|
|
154
|
-
- Find and report bugs
|
|
155
|
-
- Suggest new features
|
|
156
|
-
- Contribute code or documentation
|
|
157
|
-
- Share projects built with Luthor
|
|
158
|
-
- Star the repo to show support
|
|
159
|
-
|
|
160
|
-
Check our [Contributing Guide](./CONTRIBUTING.md) to get started.
|
|
161
|
-
|
|
162
|
-
## Support This Project
|
|
163
|
-
|
|
164
|
-
Luthor is free and open source, built by developers for developers. If it's helping you build better editors, consider supporting its development:
|
|
165
|
-
|
|
166
|
-
- **⭐ Star this repository** to show your support
|
|
167
|
-
- **💝 [Sponsor the project](https://github.com/sponsors/novincode)** to help with maintenance and new features
|
|
168
|
-
- **📢 Share Luthor** with other developers
|
|
169
|
-
|
|
170
|
-
Your support keeps this project alive and helps us build better tools for the React community.
|
|
171
|
-
|
|
172
|
-
---
|
|
173
|
-
|
|
174
|
-
**Built with ❤️ by [novincode](https://github.com/novincode)**
|
|
175
|
-
|
|
176
|
-
MIT License - Use it however you want.</content>
|
|
39
|
+
```tsx
|
|
40
|
+
import { defaultPreset } from "@lyfie/luthor";
|
|
41
|
+
|
|
42
|
+
const myPreset = {
|
|
43
|
+
...defaultPreset,
|
|
44
|
+
id: "my-default",
|
|
45
|
+
label: "My Default",
|
|
46
|
+
toolbar: ["bold", "italic", "link"],
|
|
47
|
+
};
|
|
48
|
+
```
|
package/dist/index.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
:root,.luthor-editor-wrapper[data-editor-theme=light]{--luthor-bg: #ffffff;--luthor-fg: #0f172a;--luthor-border: #e2e8f0;--luthor-border-hover: #cbd5e1;--luthor-border-active: #94a3b8;--luthor-accent: #0f172a;--luthor-accent-hover: #1e293b;--luthor-shadow: rgba(0, 0, 0, .08);--luthor-muted: #f8fafc;--luthor-muted-fg: #64748b}.luthor-editor-wrapper[data-editor-theme=dark]{--luthor-bg: #0b0b0b;--luthor-fg: #f5f5f5;--luthor-border: #2b2b2b;--luthor-border-hover: #3f3f3f;--luthor-border-active: #525252;--luthor-accent: #f5f5f5;--luthor-accent-hover: #d4d4d8;--luthor-shadow: rgba(0, 0, 0, .5);--luthor-muted: #171717;--luthor-muted-fg: #a3a3a3}.luthor-editor-wrapper{border:1px solid var(--luthor-border);border-radius:10px;background-color:var(--luthor-bg);overflow:hidden;display:flex;flex-direction:column}.luthor-editor-header{background-color:var(--luthor-muted);border-bottom:1px solid var(--luthor-border)}.luthor-mode-tabs{display:flex;border-bottom:1px solid var(--luthor-border)}.luthor-mode-tab{padding:10px 16px;background:none;border:none;cursor:pointer;color:var(--luthor-muted-fg);font-size:14px;font-weight:600;border-bottom:2px solid transparent;transition:color .2s ease,border-color .2s ease}.luthor-mode-tab:hover{color:var(--luthor-fg)}.luthor-mode-tab.active{color:var(--luthor-accent);border-bottom-color:var(--luthor-accent)}.luthor-toolbar{display:flex;align-items:center;gap:6px;padding:8px 10px;flex-wrap:wrap;min-height:52px}.luthor-toolbar-section{display:flex;align-items:center;gap:4px;padding:0 6px}.luthor-toolbar-section:not(:last-child){border-right:1px solid var(--luthor-border);margin-right:8px;padding-right:8px}.luthor-toolbar-button{display:inline-flex;align-items:center;justify-content:center;min-width:34px;height:34px;padding:0 6px;border:1px solid transparent;border-radius:6px;background-color:transparent;color:var(--luthor-fg);cursor:pointer;transition:all .2s ease}.luthor-toolbar-button:hover{background-color:var(--luthor-muted);border-color:var(--luthor-border-hover)}.luthor-toolbar-button.active{background-color:var(--luthor-accent);border-color:var(--luthor-accent);color:var(--luthor-bg)}.luthor-toolbar-button:disabled{opacity:.5;cursor:not-allowed}.luthor-select{position:relative;display:inline-block}.luthor-select-trigger{display:flex;align-items:center;gap:8px;padding:6px 10px;border:1px solid var(--luthor-border);border-radius:6px;background-color:var(--luthor-bg);color:var(--luthor-fg);cursor:pointer;font-size:13px;min-width:140px;height:34px}.luthor-select-trigger.open{border-color:var(--luthor-accent)}.luthor-select-dropdown{position:absolute;top:100%;left:0;right:0;z-index:50;background-color:var(--luthor-bg);border:1px solid var(--luthor-border);border-radius:6px;margin-top:4px;box-shadow:0 6px 20px var(--luthor-shadow)}.luthor-select-option{width:100%;text-align:left;padding:8px 10px;background:none;border:none;cursor:pointer;color:var(--luthor-fg);font-size:13px}.luthor-select-option:hover{background-color:var(--luthor-muted)}.luthor-select-option.selected{background-color:var(--luthor-accent);color:var(--luthor-bg)}.luthor-dropdown{position:relative;display:inline-flex}.luthor-dropdown-content{position:absolute;top:calc(100% + 6px);left:0;z-index:60;min-width:180px;background-color:var(--luthor-bg);border:1px solid var(--luthor-border);border-radius:8px;box-shadow:0 12px 24px var(--luthor-shadow);padding:6px}.luthor-dropdown-item{width:100%;display:flex;align-items:center;gap:8px;padding:8px 10px;border:none;background:none;color:var(--luthor-fg);cursor:pointer;border-radius:6px}.luthor-dropdown-item:hover{background-color:var(--luthor-muted)}.luthor-file-input{display:none}.luthor-editor{min-height:320px;background-color:var(--luthor-bg)}.luthor-richtext-container{position:relative}.luthor-content-editable{min-height:300px;padding:18px;font-size:15px;line-height:1.6;color:var(--luthor-fg);outline:none}.luthor-placeholder{position:absolute;top:18px;left:18px;color:var(--luthor-muted-fg);pointer-events:none}.luthor-source-panel{padding:18px}.luthor-source-view{width:100%;min-height:280px;padding:12px;border:1px solid var(--luthor-border);border-radius:8px;font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;font-size:13px;background-color:var(--luthor-bg);color:var(--luthor-fg)}.luthor-command-palette-overlay{position:fixed;inset:0;background:#0006;display:flex;align-items:flex-start;justify-content:center;padding-top:10vh;z-index:1000}.luthor-command-palette{width:min(640px,92vw);background:var(--luthor-bg);border:1px solid var(--luthor-border);border-radius:12px;overflow:hidden;box-shadow:0 20px 40px var(--luthor-shadow)}.luthor-command-palette-header{display:flex;align-items:center;gap:8px;padding:12px 16px;border-bottom:1px solid var(--luthor-border)}.luthor-command-palette-icon{color:var(--luthor-muted-fg)}.luthor-command-palette-input{flex:1;border:none;outline:none;font-size:14px;background:transparent;color:var(--luthor-fg)}.luthor-command-palette-kbd{font-size:11px;padding:3px 6px;border-radius:4px;border:1px solid var(--luthor-border);color:var(--luthor-muted-fg);background:var(--luthor-muted)}.luthor-command-palette-list{max-height:320px;overflow-y:auto;padding:6px 0}.luthor-command-palette-group{padding:6px 16px}.luthor-command-palette-group-title{font-size:12px;color:var(--luthor-muted-fg);margin-bottom:4px}.luthor-command-palette-item{display:flex;align-items:center;justify-content:space-between;padding:8px 10px;border-radius:8px;cursor:pointer}.luthor-command-palette-item-content{display:flex;flex-direction:column;gap:2px}.luthor-command-palette-item:hover,.luthor-command-palette-item.selected{background:var(--luthor-muted)}.luthor-command-palette-item-title{font-size:14px;color:var(--luthor-fg)}.luthor-command-palette-item-description{font-size:12px;color:var(--luthor-muted-fg)}.luthor-command-palette-item-shortcut{font-size:11px;padding:2px 6px;border-radius:4px;border:1px solid var(--luthor-border);background:var(--luthor-muted);color:var(--luthor-muted-fg)}.luthor-command-palette-footer{border-top:1px solid var(--luthor-border);padding:10px 16px}.luthor-command-palette-hint{display:inline-flex;align-items:center;gap:8px;font-size:12px;color:var(--luthor-muted-fg)}.luthor-command-palette-empty{padding:20px;text-align:center;color:var(--luthor-muted-fg)}.luthor-dialog-overlay{position:fixed;inset:0;background-color:#00000080;display:flex;align-items:center;justify-content:center;z-index:1000}.luthor-dialog{background-color:var(--luthor-bg);border-radius:10px;box-shadow:0 20px 30px var(--luthor-shadow);min-width:360px;max-width:520px;max-height:90vh;overflow:hidden}.luthor-dialog-header{display:flex;align-items:center;justify-content:space-between;padding:16px 20px;border-bottom:1px solid var(--luthor-border)}.luthor-dialog-title{margin:0;font-size:16px;font-weight:600;color:var(--luthor-fg)}.luthor-dialog-close{background:none;border:none;color:var(--luthor-muted-fg);cursor:pointer;padding:4px;border-radius:6px}.luthor-dialog-close:hover{background-color:var(--luthor-muted);color:var(--luthor-fg)}.luthor-dialog-content{padding:18px 20px}.luthor-table-dialog{display:flex;flex-direction:column;gap:14px}.luthor-form-group{display:flex;flex-direction:column;gap:6px}.luthor-form-group label{font-size:13px;font-weight:600;color:var(--luthor-fg)}.luthor-input{padding:8px 12px;border:1px solid var(--luthor-border);border-radius:6px;background-color:var(--luthor-bg);color:var(--luthor-fg);font-size:13px}.luthor-input:focus{outline:none;border-color:var(--luthor-accent);box-shadow:0 0 0 3px #3b82f61f}.luthor-checkbox-label{display:flex;align-items:center;gap:8px;font-size:13px;color:var(--luthor-fg)}.luthor-checkbox{width:16px;height:16px;accent-color:var(--luthor-accent)}.luthor-dialog-actions{display:flex;justify-content:flex-end;gap:10px;margin-top:4px}.luthor-button-primary,.luthor-button-secondary{padding:8px 14px;border-radius:6px;font-size:13px;font-weight:600;cursor:pointer;border:1px solid}.luthor-button-primary{background-color:var(--luthor-accent);border-color:var(--luthor-accent);color:var(--luthor-bg)}.luthor-button-primary:hover{background-color:var(--luthor-accent-hover);border-color:var(--luthor-accent-hover)}.luthor-button-secondary{background-color:transparent;border-color:var(--luthor-border);color:var(--luthor-fg)}.luthor-button-secondary:hover{background-color:var(--luthor-muted);border-color:var(--luthor-border-hover)}.luthor-text-bold{font-weight:700}.luthor-text-italic{font-style:italic}.luthor-text-underline{text-decoration:underline}.luthor-text-strikethrough{text-decoration:line-through}.luthor-text-code,.luthor-code-block{font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace;background-color:var(--luthor-muted);border:1px solid var(--luthor-border);padding:2px 6px;border-radius:4px}.luthor-code-block{display:block;padding:12px;margin:12px 0}.luthor-paragraph{margin:8px 0}.luthor-heading-h1,.luthor-heading-h2,.luthor-heading-h3,.luthor-heading-h4,.luthor-heading-h5,.luthor-heading-h6{margin:16px 0 8px;font-weight:700}.luthor-heading-h1{font-size:28px}.luthor-heading-h2{font-size:24px}.luthor-heading-h3{font-size:20px}.luthor-heading-h4{font-size:18px}.luthor-heading-h5{font-size:16px}.luthor-heading-h6{font-size:14px}.luthor-list-ul,.luthor-list-ol{margin:10px 0 10px 20px}.luthor-list-li{margin:4px 0}.luthor-quote{border-left:4px solid var(--luthor-accent);background-color:var(--luthor-muted);padding:10px 14px;margin:12px 0;color:var(--luthor-fg)}.luthor-link{color:var(--luthor-accent);text-decoration:underline}.luthor-link:hover{color:var(--luthor-accent-hover)}.luthor-hr{margin:16px 0;border:none;border-top:1px solid var(--luthor-border);height:1px}.lexical-image{margin:1em 0;display:block;position:relative}.lexical-image img{max-width:100%;height:auto;border-radius:6px;display:block}.lexical-image.align-left{float:left;margin-right:1em;margin-bottom:1em}.lexical-image.align-right{float:right;margin-left:1em;margin-bottom:1em}.lexical-image.align-center{text-align:center;margin:1em auto}.lexical-image.align-center img{margin:0 auto}.lexical-image figcaption{margin-top:.5em;font-size:12px;color:var(--luthor-muted-fg);text-align:center;font-style:italic}.lexical-image.selected{outline:2px solid var(--luthor-accent);outline-offset:2px}.resizer{position:absolute;width:8px;height:8px;background:var(--luthor-accent);border:1px solid white;border-radius:50%}.resizer.ne{top:-4px;right:-4px;cursor:nesw-resize}.resizer.nw{top:-4px;left:-4px;cursor:nwse-resize}.resizer.se{bottom:-4px;right:-4px;cursor:nwse-resize}.resizer.sw{bottom:-4px;left:-4px;cursor:nesw-resize}.luthor-table{border-collapse:collapse;width:100%;margin:16px 0;border:1px solid var(--luthor-border)}.luthor-table-cell,.luthor-table-cell-header{border:1px solid var(--luthor-border);padding:8px 12px;text-align:left;min-width:80px;background-color:var(--luthor-bg)}.luthor-table-cell-header{background-color:var(--luthor-muted);font-weight:600}table[data-lexical-table-selection]{box-shadow:0 0 0 2px var(--luthor-accent)}table td[data-lexical-table-cell-selection]{background-color:#3b82f61a}.luthor-context-menu{position:fixed;background:var(--luthor-bg);border:1px solid var(--luthor-border);border-radius:8px;box-shadow:0 10px 30px var(--luthor-shadow);z-index:1000;min-width:160px;padding:6px 0;font-size:13px}.luthor-context-menu-item{padding:8px 14px;cursor:pointer;user-select:none}.luthor-context-menu-item:hover{background-color:var(--luthor-muted)}.luthor-context-menu-item-disabled{opacity:.5;cursor:not-allowed}.luthor-floating-toolbar{display:flex;align-items:center;gap:4px;padding:6px;background-color:var(--luthor-bg);border:1px solid var(--luthor-border);border-radius:8px;box-shadow:0 8px 24px var(--luthor-shadow)}.luthor-floating-toolbar-separator{width:1px;height:18px;background-color:var(--luthor-border);margin:0 4px}.luthor-html-embed-container{border:1px solid var(--luthor-border);border-radius:8px;padding:12px;margin:14px 0;background:var(--luthor-muted)}.luthor-html-embed-preview{padding:10px;border-radius:6px;background:var(--luthor-bg);border:1px solid var(--luthor-border)}.luthor-html-embed-editor{display:flex;flex-direction:column;gap:10px}.luthor-html-embed-textarea{width:100%;min-height:120px;padding:10px;border-radius:6px;border:1px solid var(--luthor-border);background:var(--luthor-bg);color:var(--luthor-fg);font-family:SFMono-Regular,Consolas,Liberation Mono,Menlo,monospace}.luthor-html-embed-toggle{align-self:flex-end;background:var(--luthor-accent);color:var(--luthor-bg);border:none;border-radius:6px;padding:6px 10px;cursor:pointer;font-size:12px;font-weight:600}.luthor-draggable-handle,.luthor-draggable-up-button,.luthor-draggable-down-button{width:24px;height:24px;border-radius:6px;border:1px solid var(--luthor-border);background:var(--luthor-bg);color:var(--luthor-muted-fg);display:flex;align-items:center;justify-content:center;cursor:pointer}.luthor-draggable-button-stack{display:flex;flex-direction:column;gap:6px;align-items:center}.luthor-draggable-drop-indicator{height:3px;background:var(--luthor-accent);border-radius:999px}.luthor-draggable-block-dragging,.luthor-draggable-block-is-dragging{opacity:.6}@media(max-width:768px){.luthor-toolbar{padding:6px}.luthor-toolbar-button{min-width:30px;height:30px}.luthor-content-editable{padding:14px;font-size:16px}.luthor-placeholder{top:14px;left:14px}}
|