@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.
Files changed (2) hide show
  1. package/README.md +124 -0
  2. 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
+ }