lit-tip-tap 0.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 ADDED
@@ -0,0 +1,90 @@
1
+ # lit-tip-tap
2
+
3
+ Add a rich text editor easily with this component.
4
+
5
+ Lit web component wrapping [TipTap 3](https://tiptap.dev).
6
+
7
+ ## Install
8
+
9
+ ```sh
10
+ pnpm add lit-tip-tap lit @tiptap/core @tiptap/pm @tiptap/starter-kit
11
+ ```
12
+
13
+ ## `<lit-tip-tap>`
14
+
15
+ ### Properties
16
+
17
+ - `extensions` (`AnyExtension[]`, default `[]`) — TipTap extensions. Falls back to `StarterKit` when empty. Setting this re-initializes the editor, preserving content.
18
+ - `initialString` (`string`, default `''`) — HTML string used as initial editor content.
19
+ - `tiptap` (`Editor`) — The underlying TipTap `Editor` instance (read-only, available after connect).
20
+
21
+ ### Initial Content
22
+
23
+ Set content via the `initialString` property, or provide a `<template>` child:
24
+
25
+ ```html
26
+ <lit-tip-tap initial-string="Starting content here."></lit-tip-tap>
27
+ ```
28
+
29
+ ```html
30
+ <lit-tip-tap>
31
+ <template>
32
+ <p>Starting content here.</p>
33
+ </template>
34
+ </lit-tip-tap>
35
+ ```
36
+
37
+ A `<template>` child takes precedence over `initialString`.
38
+
39
+ ### Getters
40
+
41
+ - `html` — Current content as HTML.
42
+ - `json` — Current content as TipTap JSON.
43
+ - `value` — Alias for `html`.
44
+ - `textContent` — Plain text content.
45
+
46
+ ### Events
47
+
48
+ - `change` — Fires on every content update.
49
+
50
+ ### Slots
51
+
52
+ - `toolbar` — Slot for a toolbar component. Slotted elements receive the `tiptap` editor instance automatically.
53
+
54
+ ## `<lit-tip-tap-toolbar>`
55
+
56
+ A batteries-included toolbar. Slot it into `<lit-tip-tap>` and it auto-wires to the editor.
57
+
58
+ Buttons: heading select, bold, italic, strikethrough, code, bullet list, numbered list, indent left/right, blockquote, horizontal rule, clear formatting.
59
+
60
+ All buttons expose a `part` attribute for styling with `::part()`.
61
+
62
+ ## Code example
63
+
64
+ ```html
65
+ <script type="module">
66
+ import 'lit-tip-tap/registered';
67
+ import Underline from '@tiptap/extension-underline';
68
+
69
+ const editor = document.querySelector('lit-tip-tap');
70
+
71
+ // Add an extension reactively
72
+ editor.extensions = [...editor.extensions, Underline];
73
+
74
+ // Listen for changes
75
+ editor.addEventListener('change', () => {
76
+ console.log('HTML:', editor.html);
77
+ console.log('HTML (value):', editor.value);
78
+ console.log('JSON:', editor.json);
79
+ console.log('Text:', editor.textContent);
80
+ });
81
+
82
+ // Programmatic access to TipTap
83
+ editor.tiptap.commands.focus();
84
+ editor.tiptap.commands.toggleBold();
85
+ </script>
86
+
87
+ <lit-tip-tap initial-string="<p>Hello <strong>world</strong></p>">
88
+ <lit-tip-tap-toolbar slot="toolbar"></lit-tip-tap-toolbar>
89
+ </lit-tip-tap>
90
+ ```
@@ -0,0 +1,234 @@
1
+ var S = (i) => {
2
+ throw TypeError(i);
3
+ };
4
+ var g = (i, e, t) => e.has(i) || S("Cannot " + t);
5
+ var h = (i, e, t) => (g(i, e, "read from private field"), t ? t.call(i) : e.get(i)), d = (i, e, t) => e.has(i) ? S("Cannot add the same private member more than once") : e instanceof WeakSet ? e.add(i) : e.set(i, t), C = (i, e, t, s) => (g(i, e, "write to private field"), s ? s.call(i, t) : e.set(i, t), t), p = (i, e, t) => (g(i, e, "access private method"), t);
6
+ import { css as x, LitElement as y, html as L } from "lit";
7
+ import { property as k } from "lit/decorators.js";
8
+ import { Extension as A, Editor as H } from "@tiptap/core";
9
+ import q from "@tiptap/starter-kit";
10
+ import { createRef as I, ref as w } from "lit/directives/ref.js";
11
+ import { classMap as r } from "lit/directives/class-map.js";
12
+ const B = x`
13
+ code {
14
+ background-color: rgba(0, 0, 0, 0.05);
15
+ border-radius: 0.25em;
16
+ padding: 0.15em 0.3em;
17
+ font-size: 0.9em;
18
+ }
19
+
20
+ pre code {
21
+ display: block;
22
+ background-color: rgba(0, 0, 0, 0.05);
23
+ border-radius: 0.375em;
24
+ padding: 0.75em 1em;
25
+ font-size: 0.9em;
26
+ }
27
+
28
+ blockquote {
29
+ border-left: 3px solid rgba(0, 0, 0, 0.2);
30
+ margin-left: 0.5rem;
31
+ padding-left: 0.5rem;
32
+ }
33
+ `;
34
+ var P = Object.defineProperty, _ = (i, e, t, s) => {
35
+ for (var n = void 0, a = i.length - 1, l; a >= 0; a--)
36
+ (l = i[a]) && (n = l(e, t, n) || n);
37
+ return n && P(e, t, n), n;
38
+ }, c, o, f, m;
39
+ const $ = class $ extends y {
40
+ constructor() {
41
+ super(...arguments);
42
+ d(this, o);
43
+ d(this, c);
44
+ C(this, c, A.create({
45
+ onUpdate: () => {
46
+ this.dispatchEvent(new Event("change"));
47
+ }
48
+ })), this.extensions = [], this._tipTapEl = I(), this.initialString = "";
49
+ }
50
+ addExtension(...t) {
51
+ const s = this.tiptap.getJSON(), n = this._tipTapEl.value;
52
+ this.tiptap.destroy(), this.extensions = [...this.extensions, ...t], this.tiptap = p(this, o, f).call(this, this.extensions), n && (this.tiptap.mount(n), this.tiptap.commands.setContent(s)), p(this, o, m).call(this);
53
+ }
54
+ get initialContents() {
55
+ const t = this.querySelector("template");
56
+ return t ? (this.initialString = t.innerHTML.trim(), this.initialString) : this.initialString;
57
+ }
58
+ connectedCallback() {
59
+ super.connectedCallback(), this.tiptap = p(this, o, f).call(this, this.extensions), p(this, o, m).call(this);
60
+ }
61
+ firstUpdated() {
62
+ if (!this._tipTapEl.value)
63
+ throw new Error("Lit tip tap mounting div not present!");
64
+ this.tiptap.mount(this._tipTapEl.value), this.tiptap.commands.setContent(this.initialContents);
65
+ }
66
+ disconnectedCallback() {
67
+ super.disconnectedCallback(), this.tiptap?.destroy();
68
+ }
69
+ get html() {
70
+ return this.tiptap?.getHTML() ?? "";
71
+ }
72
+ get json() {
73
+ return this.tiptap?.getJSON();
74
+ }
75
+ get value() {
76
+ return this.html;
77
+ }
78
+ get textContent() {
79
+ return this.tiptap?.getText() ?? "";
80
+ }
81
+ render() {
82
+ return L`<div>
83
+ <slot name="toolbar"></slot>
84
+ <div ${w(this._tipTapEl)}></div>
85
+ </div>`;
86
+ }
87
+ };
88
+ c = new WeakMap(), o = new WeakSet(), f = function(t) {
89
+ const s = [
90
+ ...t.length > 0 ? t : [q],
91
+ h(this, c)
92
+ ];
93
+ return new H({ extensions: s, injectCSS: !0 });
94
+ }, m = function() {
95
+ this.querySelectorAll("[slot]").forEach((s) => {
96
+ s.tiptap = this.tiptap;
97
+ });
98
+ }, $.styles = B;
99
+ let b = $;
100
+ _([
101
+ k({ attribute: !1 })
102
+ ], b.prototype, "extensions");
103
+ _([
104
+ k()
105
+ ], b.prototype, "initialString");
106
+ var z = Object.defineProperty, M = (i, e, t, s) => {
107
+ for (var n = void 0, a = i.length - 1, l; a >= 0; a--)
108
+ (l = i[a]) && (n = l(e, t, n) || n);
109
+ return n && z(e, t, n), n;
110
+ }, u;
111
+ const E = class E extends y {
112
+ constructor() {
113
+ super(...arguments);
114
+ d(this, u, () => {
115
+ this.requestUpdate();
116
+ });
117
+ }
118
+ willUpdate(t) {
119
+ t.has("tiptap") && (t.get("tiptap")?.off(
120
+ "transaction",
121
+ h(this, u)
122
+ ), this.tiptap?.on("transaction", h(this, u)));
123
+ }
124
+ render() {
125
+ return L`<div part="toolbar">
126
+ <select
127
+ part="heading-select"
128
+ @change=${(t) => {
129
+ if (t.target instanceof HTMLSelectElement) {
130
+ const { value: s } = t.target;
131
+ if (s === "paragraph")
132
+ this.tiptap?.chain().focus().setParagraph().run();
133
+ else {
134
+ const n = Number(s);
135
+ this.tiptap?.chain().focus().toggleHeading({ level: n }).run();
136
+ }
137
+ }
138
+ }}
139
+ >
140
+ <option value="paragraph">Paragraph</option>
141
+ <option value="1">Heading 1</option>
142
+ <option value="2">Heading 2</option>
143
+ <option value="3">Heading 3</option>
144
+ </select>
145
+ <button
146
+ part="button bold-button"
147
+ class=${r({ "is-active": this.tiptap?.isActive("bold") ?? !1 })}
148
+ @click=${() => this.tiptap?.chain().focus().toggleBold().run()}
149
+ >
150
+ Bold
151
+ </button>
152
+ <button
153
+ part="button italic-button"
154
+ class=${r({ "is-active": this.tiptap?.isActive("italic") ?? !1 })}
155
+ @click=${() => this.tiptap?.chain().focus().toggleItalic().run()}
156
+ >
157
+ Italic
158
+ </button>
159
+ <button
160
+ part="button strike-button"
161
+ class=${r({ "is-active": this.tiptap?.isActive("strike") ?? !1 })}
162
+ @click=${() => this.tiptap?.chain().focus().toggleStrike().run()}
163
+ >
164
+ Strikethrough
165
+ </button>
166
+ <button
167
+ part="button code-button"
168
+ class=${r({ "is-active": this.tiptap?.isActive("code") ?? !1 })}
169
+ @click=${() => this.tiptap?.chain().focus().toggleCode().run()}
170
+ >
171
+ Code
172
+ </button>
173
+ <button
174
+ part="button bullet-list-button"
175
+ class=${r({ "is-active": this.tiptap?.isActive("bulletList") ?? !1 })}
176
+ @click=${() => this.tiptap?.chain().focus().toggleBulletList().run()}
177
+ >
178
+ Bullet List
179
+ </button>
180
+ <button
181
+ part="button ordered-list-button"
182
+ class=${r({ "is-active": this.tiptap?.isActive("orderedList") ?? !1 })}
183
+ @click=${() => this.tiptap?.chain().focus().toggleOrderedList().run()}
184
+ >
185
+ Numbered List
186
+ </button>
187
+ <button
188
+ part="button indent-left-button"
189
+ @click=${() => this.tiptap?.chain().focus().liftListItem("listItem").run()}
190
+ >
191
+ Indent Left
192
+ </button>
193
+ <button
194
+ part="button indent-right-button"
195
+ @click=${() => this.tiptap?.chain().focus().sinkListItem("listItem").run()}
196
+ >
197
+ Indent Right
198
+ </button>
199
+ <button
200
+ part="button blockquote-button"
201
+ class=${r({ "is-active": this.tiptap?.isActive("blockquote") ?? !1 })}
202
+ @click=${() => this.tiptap?.chain().focus().toggleBlockquote().run()}
203
+ >
204
+ Blockquote
205
+ </button>
206
+ <button
207
+ part="button horizontal-rule-button"
208
+ @click=${() => this.tiptap?.chain().focus().setHorizontalRule().run()}
209
+ >
210
+ Horizontal Rule
211
+ </button>
212
+ <button
213
+ part="button clear-formatting-button"
214
+ @click=${() => this.tiptap?.chain().focus().unsetAllMarks().run()}
215
+ >
216
+ Clear Formatting
217
+ </button>
218
+ </div>`;
219
+ }
220
+ };
221
+ u = new WeakMap(), E.styles = x`
222
+ button.is-active {
223
+ background-color: rgba(0, 0, 0, 0.1);
224
+ font-weight: bold;
225
+ }
226
+ `;
227
+ let v = E;
228
+ M([
229
+ k({ attribute: !1 })
230
+ ], v.prototype, "tiptap");
231
+ export {
232
+ b as L,
233
+ v as a
234
+ };
@@ -0,0 +1,5 @@
1
+ import { L as T, a as i } from "./lit-tip-tap-toolbar-DlicURCM.js";
2
+ export {
3
+ T as LitTipTap,
4
+ i as LitTipTapToolbar
5
+ };
@@ -0,0 +1,7 @@
1
+ import { L as t, a as i } from "./lit-tip-tap-toolbar-DlicURCM.js";
2
+ customElements.define("lit-tip-tap", t);
3
+ customElements.define("lit-tip-tap-toolbar", i);
4
+ export {
5
+ t as LitTipTap,
6
+ i as LitTipTapToolbar
7
+ };
@@ -0,0 +1,2 @@
1
+ declare const _default: import("lit").CSSResult;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ export { LitTipTap } from './lit-tip-tap.js';
2
+ export { LitTipTapToolbar } from './lit-tip-tap-toolbar.js';
@@ -0,0 +1,4 @@
1
+ export { LitTipTap } from './lit-tip-tap.js';
2
+ export { LitTipTapToolbar } from './lit-tip-tap-toolbar.js';
3
+ import './lit-tip-tap.register.js';
4
+ import './lit-tip-tap-toolbar.register.js';
@@ -0,0 +1,9 @@
1
+ import { Editor } from '@tiptap/core';
2
+ import { LitElement } from 'lit';
3
+ export declare class LitTipTapToolbar extends LitElement {
4
+ #private;
5
+ static styles: import("lit").CSSResult;
6
+ tiptap?: Editor;
7
+ willUpdate(changed: Map<PropertyKey, unknown>): void;
8
+ render(): import("lit").TemplateResult<1>;
9
+ }
@@ -0,0 +1,6 @@
1
+ import { LitTipTapToolbar } from './lit-tip-tap-toolbar.js';
2
+ declare global {
3
+ interface HTMLElementTagNameMap {
4
+ 'lit-tip-tap-toolbar': LitTipTapToolbar;
5
+ }
6
+ }
@@ -0,0 +1,20 @@
1
+ import { LitElement } from 'lit';
2
+ import { Editor, type AnyExtension } from '@tiptap/core';
3
+ export declare class LitTipTap extends LitElement {
4
+ #private;
5
+ static styles: import("lit").CSSResult;
6
+ tiptap: Editor;
7
+ extensions: AnyExtension[];
8
+ addExtension(...newExtensions: AnyExtension[]): void;
9
+ _tipTapEl: import("lit/directives/ref.js").Ref<HTMLDivElement>;
10
+ initialString: string;
11
+ get initialContents(): string;
12
+ connectedCallback(): void;
13
+ firstUpdated(): void;
14
+ disconnectedCallback(): void;
15
+ get html(): string;
16
+ get json(): import("@tiptap/core").DocumentType<Record<string, any> | undefined, import("@tiptap/core").NodeType<string, Record<string, any> | undefined, any, (import("@tiptap/core").NodeType<any, any, any, any> | import("@tiptap/core").TextType<import("@tiptap/core").MarkType<any, any>>)[]>[]>;
17
+ get value(): string;
18
+ get textContent(): string;
19
+ render(): import("lit").TemplateResult<1>;
20
+ }
@@ -0,0 +1,6 @@
1
+ import { LitTipTap } from './lit-tip-tap.js';
2
+ declare global {
3
+ interface HTMLElementTagNameMap {
4
+ 'lit-tip-tap': LitTipTap;
5
+ }
6
+ }
@@ -0,0 +1,2 @@
1
+ import '../src/lit-tip-tap.register.js';
2
+ import '../src/lit-tip-tap-toolbar.register.js';
@@ -0,0 +1 @@
1
+ import '../src/lit-tip-tap.register.js';
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "lit-tip-tap",
3
+ "version": "0.0.0",
4
+ "type": "module",
5
+ "main": "./dist/lit-tip-tap.js",
6
+ "module": "./dist/lit-tip-tap.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/lit-tip-tap.js"
12
+ },
13
+ "./registered": {
14
+ "types": "./dist/index.registered.d.ts",
15
+ "import": "./dist/lit-tip-tap.registered.js"
16
+ }
17
+ },
18
+ "files": [
19
+ "dist"
20
+ ],
21
+ "peerDependencies": {
22
+ "@tiptap/core": "^3.19.0",
23
+ "@tiptap/pm": "^3.19.0",
24
+ "@tiptap/starter-kit": "^3.19.0",
25
+ "lit": "^3.3.1"
26
+ },
27
+ "devDependencies": {
28
+ "@tiptap/core": "^3.19.0",
29
+ "@tiptap/pm": "^3.19.0",
30
+ "@tiptap/starter-kit": "^3.19.0",
31
+ "@vitest/browser-playwright": "^4.0.18",
32
+ "eslint": "^9.39.2",
33
+ "eslint-config-prettier": "^10.1.8",
34
+ "eslint-plugin-lit": "^2.2.1",
35
+ "lit": "^3.3.1",
36
+ "prettier": "^3.8.1",
37
+ "typescript": "~5.9.3",
38
+ "typescript-eslint": "^8.55.0",
39
+ "vite": "^7.3.1",
40
+ "vitest": "^4.0.18"
41
+ },
42
+ "scripts": {
43
+ "dev": "vite",
44
+ "build": "rm -rf dist && tsc -p tsconfig.build.json && vite build",
45
+ "preview": "vite preview",
46
+ "lint": "eslint src",
47
+ "lint:fix": "eslint src --fix",
48
+ "format": "prettier --write src",
49
+ "format:check": "prettier --check src",
50
+ "test": "vitest",
51
+ "test:run": "vitest run"
52
+ }
53
+ }