luxen-ui 0.6.2 → 0.7.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/cdn/chunks/decorate.js +1 -1
- package/cdn/chunks/floating-ui.dom.js +2 -0
- package/cdn/chunks/floating-ui.dom.js.map +1 -0
- package/cdn/chunks/lit.js +1 -1
- package/cdn/chunks/module.js +717 -0
- package/cdn/chunks/module.js.map +1 -0
- package/cdn/chunks/native.js +2 -0
- package/cdn/chunks/native.js.map +1 -0
- package/cdn/custom-elements.json +10269 -7939
- package/cdn/elements/avatar/avatar.js +7 -7
- package/cdn/elements/avatar/avatar.js.map +1 -1
- package/cdn/elements/carousel/carousel.js +5 -5
- package/cdn/elements/carousel-item/carousel-item.js +1 -1
- package/cdn/elements/dialog/dialog.js +1 -1
- package/cdn/elements/dialog/dialog.styles.js +1 -1
- package/cdn/elements/drawer/drawer.js +1 -1
- package/cdn/elements/dropdown/dropdown.js +1 -1
- package/cdn/elements/dropdown-item/dropdown-item.js +5 -5
- package/cdn/elements/icon/icon.js +1 -1
- package/cdn/elements/popover/popover.js +2 -2
- package/cdn/elements/prose-editor/index.d.ts +2 -0
- package/cdn/elements/prose-editor/index.d.ts.map +1 -0
- package/cdn/elements/prose-editor/index.js +2 -0
- package/cdn/elements/prose-editor/index.js.map +1 -0
- package/cdn/elements/prose-editor/prose-editor.d.ts +110 -0
- package/cdn/elements/prose-editor/prose-editor.d.ts.map +1 -0
- package/cdn/elements/prose-editor/prose-editor.js +180 -0
- package/cdn/elements/prose-editor/prose-editor.js.map +1 -0
- package/cdn/elements/rating/rating.js +5 -5
- package/cdn/elements/spinner/spinner.js +1 -1
- package/cdn/elements/sticky-bar/sticky-bar.js +1 -1
- package/cdn/elements/stories-viewer/stories-viewer.js +7 -7
- package/cdn/elements/story/story.js +1 -1
- package/cdn/elements/tooltip/tooltip.js +2 -2
- package/cdn/elements/tree/tree.js +1 -1
- package/cdn/elements/tree-item/tree-item.js +4 -4
- package/cdn/registry.d.ts +1 -1
- package/cdn/registry.d.ts.map +1 -1
- package/cdn/registry.js.map +1 -1
- package/cdn/shared/controllers/popover.js +1 -1
- package/cdn/shared/controllers/popover.js.map +1 -1
- package/cdn/shared/styles/host.styles.js +1 -1
- package/cdn/standalone.css +132 -1
- package/cdn/standalone.js +25567 -149
- package/cdn/standalone.js.map +1 -1
- package/cdn/styles/elements/prose-editor.css +129 -0
- package/cdn/styles/elements/toast.css +1 -1
- package/dist/css/elements/prose-editor.css +129 -0
- package/dist/css/elements/toast.css +1 -1
- package/dist/custom-elements.json +10269 -7939
- package/dist/elements/prose-editor/index.d.ts +2 -0
- package/dist/elements/prose-editor/index.d.ts.map +1 -0
- package/dist/elements/prose-editor/index.js +4 -0
- package/dist/elements/prose-editor/prose-editor.css +133 -0
- package/dist/elements/prose-editor/prose-editor.d.ts +111 -0
- package/dist/elements/prose-editor/prose-editor.d.ts.map +1 -0
- package/dist/elements/prose-editor/prose-editor.js +475 -0
- package/dist/registry.d.ts +1 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/templates/elements/prose-editor.md +216 -0
- package/elements.json +7 -0
- package/package.json +8 -1
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
---
|
|
2
|
+
outline: deep
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Prose Editor
|
|
6
|
+
|
|
7
|
+
A rich text editor built on [Tiptap](https://tiptap.dev) (ProseMirror). Form-associated — its value is the editor HTML, so it submits inside a `<form>` like a native field.
|
|
8
|
+
|
|
9
|
+
```html
|
|
10
|
+
<l-prose-editor placeholder="Write something…"></l-prose-editor>
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
The editable area renders in light DOM, so its content styles ship as a separate stylesheet you import once globally. See [Importing](#importing).
|
|
14
|
+
|
|
15
|
+
<ElementSpec
|
|
16
|
+
tag="l-prose-editor"
|
|
17
|
+
type="shadow"
|
|
18
|
+
/>
|
|
19
|
+
|
|
20
|
+
## Options
|
|
21
|
+
|
|
22
|
+
### Basic
|
|
23
|
+
|
|
24
|
+
The default toolbar covers headings, marks, lists, links, code, an emoji picker and undo/redo. Set initial content with `initial-html`.
|
|
25
|
+
|
|
26
|
+
```html
|
|
27
|
+
<l-prose-editor
|
|
28
|
+
placeholder="Write something…"
|
|
29
|
+
initial-html="<h2>Release notes</h2><p>This editor ships with a <strong>default</strong> toolbar covering headings, marks, lists, links and more.</p><ul><li>Built on Tiptap</li><li>Form-associated</li></ul>"
|
|
30
|
+
></l-prose-editor>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Toolbar preset
|
|
34
|
+
|
|
35
|
+
Set `toolbar-preset="minimal"` for a compact bold/italic/underline toolbar.
|
|
36
|
+
|
|
37
|
+
```html
|
|
38
|
+
<l-prose-editor
|
|
39
|
+
toolbar-preset="minimal"
|
|
40
|
+
placeholder="Bold, italic, underline only…"
|
|
41
|
+
></l-prose-editor>
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Custom toolbar
|
|
45
|
+
|
|
46
|
+
Set `toolbar` to a comma-separated list of commands to build your own layout. Use `divider` to insert a separator.
|
|
47
|
+
|
|
48
|
+
```html
|
|
49
|
+
<l-prose-editor
|
|
50
|
+
toolbar="bold,italic,link,divider,bulletlist,orderedlist,divider,undo,redo"
|
|
51
|
+
placeholder="Custom toolbar…"
|
|
52
|
+
></l-prose-editor>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Available commands: `heading-1`, `heading-2`, `heading-3`, `bold`, `italic`, `underline`, `strike`, `highlight`, `bulletlist`, `orderedlist`, `blockquote`, `code-block`, `horizontal-rule`, `link`, `emoji`, `attachment`, `undo`, `redo`, `divider`.
|
|
56
|
+
|
|
57
|
+
### Toolbar placement
|
|
58
|
+
|
|
59
|
+
Set `toolbar-placement="bottom"` to move the toolbar below the content.
|
|
60
|
+
|
|
61
|
+
```html
|
|
62
|
+
<l-prose-editor
|
|
63
|
+
toolbar-placement="bottom"
|
|
64
|
+
placeholder="Toolbar sits below the content…"
|
|
65
|
+
></l-prose-editor>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Examples
|
|
69
|
+
|
|
70
|
+
### Form integration
|
|
71
|
+
|
|
72
|
+
The editor participates in forms via its `name` attribute. The submitted value is the HTML string; `required` blocks submission while empty.
|
|
73
|
+
|
|
74
|
+
```html
|
|
75
|
+
<form
|
|
76
|
+
class="flex flex-col items-start gap-4"
|
|
77
|
+
onsubmit="
|
|
78
|
+
event.preventDefault();
|
|
79
|
+
const data = new FormData(event.target);
|
|
80
|
+
alert('description = ' + data.get('description'));
|
|
81
|
+
"
|
|
82
|
+
>
|
|
83
|
+
<label class="flex w-full flex-col gap-1">
|
|
84
|
+
<span class="text-sm font-medium">Description</span>
|
|
85
|
+
<l-prose-editor
|
|
86
|
+
name="description"
|
|
87
|
+
required
|
|
88
|
+
toolbar-preset="minimal"
|
|
89
|
+
placeholder="Describe your product…"
|
|
90
|
+
></l-prose-editor>
|
|
91
|
+
</label>
|
|
92
|
+
<button
|
|
93
|
+
type="submit"
|
|
94
|
+
class="l-button"
|
|
95
|
+
data-variant="primary"
|
|
96
|
+
>
|
|
97
|
+
Submit
|
|
98
|
+
</button>
|
|
99
|
+
</form>
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Accessibility
|
|
103
|
+
|
|
104
|
+
### Criteria
|
|
105
|
+
|
|
106
|
+
| Check | Description |
|
|
107
|
+
|-------|-------------|
|
|
108
|
+
| Toolbar role | The toolbar uses `role="toolbar"` with an accessible label |
|
|
109
|
+
| Button state | Each toolbar button exposes `aria-pressed` reflecting whether the mark/format is active |
|
|
110
|
+
| Button label | Icon-only buttons carry an `aria-label` and `title` describing the action |
|
|
111
|
+
| Focus state | Visible focus ring on toolbar buttons for keyboard users |
|
|
112
|
+
| Form validation | When `required`, an empty editor reports a `valueMissing` validation message to the form |
|
|
113
|
+
|
|
114
|
+
### Rules
|
|
115
|
+
- Associate a visible `<label>` with the editor, or set `aria-label` on the host element
|
|
116
|
+
- Keep custom toolbars logically ordered so keyboard users encounter commands in a predictable sequence
|
|
117
|
+
|
|
118
|
+
### Keyboard interactions
|
|
119
|
+
|
|
120
|
+
| Key | Description |
|
|
121
|
+
|-----|-------------|
|
|
122
|
+
| Tab | Moves focus into the toolbar, then into the editable content |
|
|
123
|
+
| Ctrl/Cmd + B | Toggles bold |
|
|
124
|
+
| Ctrl/Cmd + I | Toggles italic |
|
|
125
|
+
| Ctrl/Cmd + U | Toggles underline |
|
|
126
|
+
| Ctrl/Cmd + Z | Undo |
|
|
127
|
+
| Ctrl/Cmd + Shift + Z | Redo |
|
|
128
|
+
| Escape | Closes the emoji picker when open |
|
|
129
|
+
|
|
130
|
+
## API reference
|
|
131
|
+
|
|
132
|
+
### Importing
|
|
133
|
+
|
|
134
|
+
Import the element and the content stylesheet once globally. The stylesheet styles the editable area, which renders in light DOM to avoid `contenteditable` caret bugs inside shadow trees.
|
|
135
|
+
|
|
136
|
+
```js
|
|
137
|
+
import 'luxen-ui/prose-editor';
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
```css
|
|
141
|
+
@import 'luxen-ui/css/prose-editor';
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Attributes & Properties
|
|
145
|
+
|
|
146
|
+
<ApiTable :data="[
|
|
147
|
+
{ Attribute: 'initial-html', Description: 'Initial content as an HTML string' },
|
|
148
|
+
{ Attribute: 'initial-json', Description: 'Initial content as a serialized ProseMirror JSON string. Used when `initial-html` is not set' },
|
|
149
|
+
{ Attribute: 'toolbar-preset', Description: 'Built-in toolbar layout: `default` (full) or `minimal`. Defaults to `default`' },
|
|
150
|
+
{ Attribute: 'toolbar', Description: 'Comma-separated list of commands. Overrides `toolbar-preset` when set' },
|
|
151
|
+
{ Attribute: 'toolbar-placement', Description: 'Where the toolbar sits: `top` (default) or `bottom`. Reflects to attribute' },
|
|
152
|
+
{ Attribute: 'editor-class', Description: 'Class applied to the editable element. Defaults to `prose` (for Tailwind Typography)' },
|
|
153
|
+
{ Attribute: 'placeholder', Description: 'Text shown when the editor is empty' },
|
|
154
|
+
{ Attribute: 'autofocus', Description: 'Focus the editor on creation' },
|
|
155
|
+
{ Attribute: 'name', Description: 'Form field name. The submitted value is the editor HTML' },
|
|
156
|
+
{ Attribute: 'required', Description: 'Marks the field invalid while the editor is empty' },
|
|
157
|
+
{ Attribute: 'disabled', Description: 'Disables editing' },
|
|
158
|
+
{ Property: 'editor', Description: 'The underlying Tiptap `Editor` instance. Available after first render' },
|
|
159
|
+
]" />
|
|
160
|
+
|
|
161
|
+
### Methods
|
|
162
|
+
|
|
163
|
+
<ApiTable :data="[
|
|
164
|
+
{ Method: 'getHTML()', Description: 'Returns the content as an HTML string. An empty paragraph resolves to `\'\'`' },
|
|
165
|
+
{ Method: 'getJSON()', Description: 'Returns the content as ProseMirror JSON' },
|
|
166
|
+
{ Method: 'clear()', Description: 'Removes all content' },
|
|
167
|
+
{ Method: 'focus()', Description: 'Focuses the editable content' },
|
|
168
|
+
{ Method: 'blur()', Description: 'Removes focus from the editable content' },
|
|
169
|
+
]" />
|
|
170
|
+
|
|
171
|
+
### Events
|
|
172
|
+
|
|
173
|
+
<ApiTable :data="[
|
|
174
|
+
{ Event: 'change', Description: 'Fired when the content changes. `event.detail` is `{ html, json }`' },
|
|
175
|
+
{ Event: 'add-file', Description: 'Fired when the `attachment` toolbar button is clicked. Wire up your own upload flow' },
|
|
176
|
+
]" />
|
|
177
|
+
|
|
178
|
+
### Slots
|
|
179
|
+
|
|
180
|
+
<ApiTable :data="[
|
|
181
|
+
{ Slot: 'toolbar-start', Description: 'Content placed before the generated toolbar buttons' },
|
|
182
|
+
{ Slot: 'toolbar-end', Description: 'Content placed after the generated toolbar buttons' },
|
|
183
|
+
]" />
|
|
184
|
+
|
|
185
|
+
### CSS Parts
|
|
186
|
+
|
|
187
|
+
<ApiTable :data="[
|
|
188
|
+
{ Part: 'wrapper', Description: 'The editor frame wrapping the toolbar and content' },
|
|
189
|
+
{ Part: 'toolbar', Description: 'The toolbar row' },
|
|
190
|
+
{ Part: 'toolbar-button', Description: 'Any toolbar button' },
|
|
191
|
+
{ Part: 'divider', Description: 'A toolbar divider' },
|
|
192
|
+
{ Part: 'editor', Description: 'The container around the editable content' },
|
|
193
|
+
]" />
|
|
194
|
+
|
|
195
|
+
### CSS custom properties
|
|
196
|
+
|
|
197
|
+
<ApiTable :data="[
|
|
198
|
+
{ Name: '--border-color', Description: 'Color of the editor frame border' },
|
|
199
|
+
{ Name: '--border-width', Description: 'Width of the editor frame border' },
|
|
200
|
+
{ Name: '--border-radius', Description: 'Corner radius of the editor frame' },
|
|
201
|
+
{ Name: '--background', Description: 'Background color of the editor' },
|
|
202
|
+
{ Name: '--color', Description: 'Text color of the editor' },
|
|
203
|
+
{ Name: '--toolbar-background', Description: 'Background color of the toolbar' },
|
|
204
|
+
{ Name: '--toolbar-padding', Description: 'Padding around the toolbar' },
|
|
205
|
+
{ Name: '--toolbar-gap', Description: 'Gap between toolbar buttons' },
|
|
206
|
+
{ Name: '--toolbar-divider-color', Description: 'Color of toolbar dividers' },
|
|
207
|
+
{ Name: '--toolbar-button-size', Description: 'Size of toolbar buttons' },
|
|
208
|
+
{ Name: '--toolbar-button-radius', Description: 'Corner radius of toolbar buttons' },
|
|
209
|
+
{ Name: '--toolbar-button-color', Description: 'Icon color of inactive toolbar buttons' },
|
|
210
|
+
{ Name: '--toolbar-button-color-active', Description: 'Icon color of hovered/active toolbar buttons' },
|
|
211
|
+
{ Name: '--toolbar-button-background-hover', Description: 'Background of hovered toolbar buttons' },
|
|
212
|
+
{ Name: '--toolbar-button-background-active', Description: 'Background of active toolbar buttons' },
|
|
213
|
+
{ Name: '--content-padding', Description: 'Padding of the editable content area' },
|
|
214
|
+
{ Name: '--content-min-height', Description: 'Minimum height of the editable content area' },
|
|
215
|
+
{ Name: '--placeholder-color', Description: 'Color of the placeholder text' },
|
|
216
|
+
]" />
|
package/elements.json
CHANGED
|
@@ -127,6 +127,13 @@
|
|
|
127
127
|
"inSkill": true,
|
|
128
128
|
"inMockups": false
|
|
129
129
|
},
|
|
130
|
+
{
|
|
131
|
+
"name": "prose-editor",
|
|
132
|
+
"displayName": "Prose editor",
|
|
133
|
+
"kind": "element",
|
|
134
|
+
"inSkill": true,
|
|
135
|
+
"inMockups": true
|
|
136
|
+
},
|
|
130
137
|
{
|
|
131
138
|
"name": "rating",
|
|
132
139
|
"displayName": "Rating",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "luxen-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Modern web components and CSS-first UI library built with Lit. Framework-agnostic, customizable prefix, design tokens.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"custom-elements",
|
|
@@ -113,9 +113,16 @@
|
|
|
113
113
|
"provenance": true
|
|
114
114
|
},
|
|
115
115
|
"dependencies": {
|
|
116
|
+
"@emoji-mart/data": "^1.2.1",
|
|
116
117
|
"@floating-ui/dom": "^1.7.6",
|
|
118
|
+
"@tiptap/core": "^3.23.6",
|
|
119
|
+
"@tiptap/extension-highlight": "^3.23.6",
|
|
120
|
+
"@tiptap/extensions": "^3.23.6",
|
|
121
|
+
"@tiptap/pm": "^3.23.6",
|
|
122
|
+
"@tiptap/starter-kit": "^3.23.6",
|
|
117
123
|
"embla-carousel": "^8.6.0",
|
|
118
124
|
"embla-carousel-autoplay": "^8.6.0",
|
|
125
|
+
"emoji-mart": "^5.6.0",
|
|
119
126
|
"iconify-icon": "^3.0.2",
|
|
120
127
|
"lit": "^3.3.3"
|
|
121
128
|
},
|