@duskmoon-dev/el-markdown-input 0.8.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 +124 -0
- package/package.json +64 -0
package/README.md
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# `@duskmoon-dev/el-markdown-input`
|
|
2
|
+
|
|
3
|
+
A form-associated custom element providing a full-featured markdown editor.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Write / Preview tabs** — switch between editing and rendered output
|
|
8
|
+
- **Syntax highlighting** — backdrop technique with Prism.js (lazy CDN load)
|
|
9
|
+
- **File upload** — drag-and-drop, clipboard paste, or file picker with progress
|
|
10
|
+
- **Autocomplete** — `@mention` and `#reference` with keyboard navigation
|
|
11
|
+
- **Status bar** — live word / character count with optional `max-words` cap
|
|
12
|
+
- **Form participation** — native `<form>` submission via `ElementInternals`
|
|
13
|
+
- **LiveView hook** — first-class Phoenix LiveView integration
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
bun add @duskmoon-dev/el-markdown-input
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Basic Usage
|
|
22
|
+
|
|
23
|
+
```html
|
|
24
|
+
<script type="module">
|
|
25
|
+
import { register } from '@duskmoon-dev/el-markdown-input';
|
|
26
|
+
register();
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
<form method="post">
|
|
30
|
+
<el-dm-markdown-input name="body" placeholder="Write markdown…"></el-dm-markdown-input>
|
|
31
|
+
<button type="submit">Save</button>
|
|
32
|
+
</form>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Attributes
|
|
36
|
+
|
|
37
|
+
| Attribute | Type | Default | Description |
|
|
38
|
+
|--------------|---------|-----------------|-----------------------------------------------|
|
|
39
|
+
| `name` | string | `""` | Form field name |
|
|
40
|
+
| `value` | string | `""` | Initial markdown content |
|
|
41
|
+
| `placeholder`| string | `"Write markdown…"` | Textarea placeholder |
|
|
42
|
+
| `disabled` | boolean | `false` | Disables editing |
|
|
43
|
+
| `upload-url` | string | — | POST endpoint returning `{ url: string }` |
|
|
44
|
+
| `max-words` | number | — | Soft word cap in status bar |
|
|
45
|
+
| `dark` | boolean | `false` | Dark Prism theme + dark CSS variable defaults |
|
|
46
|
+
|
|
47
|
+
## Public API
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
el.getValue(): string
|
|
51
|
+
el.setValue(str: string): void
|
|
52
|
+
el.insertText(str: string): void
|
|
53
|
+
el.setSuggestions(list: Suggestion[]): void
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Events
|
|
57
|
+
|
|
58
|
+
| Event | Detail | When |
|
|
59
|
+
|-------------------|-------------------------------------------------|-----------------------------|
|
|
60
|
+
| `change` | `{ value: string }` | On every input |
|
|
61
|
+
| `upload-start` | `{ file: File }` | File accepted for upload |
|
|
62
|
+
| `upload-done` | `{ file: File, url: string, markdown: string }` | Upload completed |
|
|
63
|
+
| `upload-error` | `{ file: File, error: string }` | Upload failed |
|
|
64
|
+
| `mention-query` | `{ trigger: "@", query, resolve }` | User typed `@word` |
|
|
65
|
+
| `reference-query` | `{ trigger: "#", query, resolve }` | User typed `#word` |
|
|
66
|
+
|
|
67
|
+
## CSS Custom Properties
|
|
68
|
+
|
|
69
|
+
| Property | Default (light) | Purpose |
|
|
70
|
+
|-------------------|-------------------------|----------------------------|
|
|
71
|
+
| `--md-border` | `var(--color-outline)` | Editor border |
|
|
72
|
+
| `--md-border-focus` | `var(--color-primary)` | Focus ring colour |
|
|
73
|
+
| `--md-bg` | `var(--color-surface)` | Editor background |
|
|
74
|
+
| `--md-bg-toolbar` | `var(--color-surface-variant)` | Toolbar background |
|
|
75
|
+
| `--md-text` | `var(--color-on-surface)` | Primary text colour |
|
|
76
|
+
| `--md-text-muted` | `var(--color-on-surface-variant)` | Muted text colour |
|
|
77
|
+
| `--md-accent` | `var(--color-primary)` | Tab active indicator |
|
|
78
|
+
| `--md-radius` | `6px` | Border radius |
|
|
79
|
+
| `--md-upload-bar` | `var(--color-primary)` | Upload progress bar |
|
|
80
|
+
|
|
81
|
+
## File Upload
|
|
82
|
+
|
|
83
|
+
```html
|
|
84
|
+
<el-dm-markdown-input upload-url="/api/uploads"></el-dm-markdown-input>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
The endpoint must accept `POST multipart/form-data` with field `file` and respond with:
|
|
88
|
+
```json
|
|
89
|
+
{ "url": "https://cdn.example.com/file.png" }
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Autocomplete
|
|
93
|
+
|
|
94
|
+
```js
|
|
95
|
+
el.addEventListener('mention-query', async (e) => {
|
|
96
|
+
const users = await fetchUsers(e.detail.query);
|
|
97
|
+
e.detail.resolve(users.map(u => ({
|
|
98
|
+
id: u.handle,
|
|
99
|
+
label: u.name,
|
|
100
|
+
subtitle: u.email
|
|
101
|
+
})));
|
|
102
|
+
});
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Phoenix LiveView
|
|
106
|
+
|
|
107
|
+
```js
|
|
108
|
+
// app.js
|
|
109
|
+
import { MarkdownInputHook, register } from '@duskmoon-dev/el-markdown-input';
|
|
110
|
+
register();
|
|
111
|
+
|
|
112
|
+
let liveSocket = new LiveSocket('/live', Socket, {
|
|
113
|
+
hooks: { MarkdownInput: MarkdownInputHook }
|
|
114
|
+
});
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
```heex
|
|
118
|
+
<el-dm-markdown-input
|
|
119
|
+
id="body-input"
|
|
120
|
+
name="body"
|
|
121
|
+
data-value={@content}
|
|
122
|
+
phx-hook="MarkdownInput"
|
|
123
|
+
/>
|
|
124
|
+
```
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@duskmoon-dev/el-markdown-input",
|
|
3
|
+
"version": "0.8.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/cjs/index.js",
|
|
6
|
+
"module": "./dist/esm/index.js",
|
|
7
|
+
"types": "./dist/types/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/types/index.d.ts",
|
|
11
|
+
"import": "./dist/esm/index.js",
|
|
12
|
+
"require": "./dist/cjs/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./register": {
|
|
15
|
+
"types": "./dist/types/register.d.ts",
|
|
16
|
+
"import": "./dist/esm/register.js",
|
|
17
|
+
"require": "./dist/cjs/register.js"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist"
|
|
22
|
+
],
|
|
23
|
+
"scripts": {
|
|
24
|
+
"prebuild": "bun run clean",
|
|
25
|
+
"build": "bun run build:esm && bun run build:cjs && bun run build:types",
|
|
26
|
+
"build:esm": "bun build ./src/index.ts ./src/register.ts --outdir ./dist/esm --format esm --sourcemap --external @duskmoon-dev/el-base --external @duskmoon-dev/core",
|
|
27
|
+
"build:cjs": "bun build ./src/index.ts ./src/register.ts --outdir ./dist/cjs --format cjs --sourcemap --external @duskmoon-dev/el-base --external @duskmoon-dev/core",
|
|
28
|
+
"build:types": "tsc --emitDeclarationOnly --outDir ./dist/types",
|
|
29
|
+
"dev": "bun build ./src/index.ts --outdir ./dist/esm --format esm --sourcemap --external @duskmoon-dev/el-base --watch",
|
|
30
|
+
"clean": "del-cli dist",
|
|
31
|
+
"test": "bun test",
|
|
32
|
+
"typecheck": "tsc --noEmit",
|
|
33
|
+
"format": "prettier --write 'src/**/*.ts' '*.json'",
|
|
34
|
+
"format:check": "prettier --check 'src/**/*.ts' '*.json'",
|
|
35
|
+
"lint": "eslint src",
|
|
36
|
+
"lint:check": "eslint src --max-warnings 0",
|
|
37
|
+
"lint:fix": "eslint src --fix",
|
|
38
|
+
"release": "bun publish",
|
|
39
|
+
"release:dry-run": "bun publish --dry-run"
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@duskmoon-dev/el-base": "0.7.1",
|
|
43
|
+
"@duskmoon-dev/core": "^1.10.1"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"typescript": "^5.7.2"
|
|
47
|
+
},
|
|
48
|
+
"publishConfig": {
|
|
49
|
+
"access": "public"
|
|
50
|
+
},
|
|
51
|
+
"customElements": "custom-elements.json",
|
|
52
|
+
"keywords": [
|
|
53
|
+
"duskmoon-dev",
|
|
54
|
+
"duskmoon",
|
|
55
|
+
"custom-elements",
|
|
56
|
+
"customelements",
|
|
57
|
+
"web-components",
|
|
58
|
+
"webcomponents",
|
|
59
|
+
"html",
|
|
60
|
+
"markdown",
|
|
61
|
+
"editor",
|
|
62
|
+
"markdown-editor"
|
|
63
|
+
]
|
|
64
|
+
}
|