@prosekit/lit 0.0.3 → 0.0.5

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.
@@ -0,0 +1,236 @@
1
+ import {
2
+ __decorateClass,
3
+ blockComponentStyles,
4
+ commandListContext
5
+ } from "./chunk-J73E7P6J.js";
6
+
7
+ // src/components/autocomplete-popover/context.ts
8
+ import { createContext } from "@lit-labs/context";
9
+ var commandPopoverContext = createContext(
10
+ "prosekit-autocomplete-popover-context"
11
+ );
12
+
13
+ // src/components/autocomplete-list/component.ts
14
+ import { consume, provide } from "@lit-labs/context";
15
+ import "@prosekit/core";
16
+ import { html, LitElement } from "lit";
17
+ import { customElement, property, query, state } from "lit/decorators.js";
18
+
19
+ // src/utils/command-score.ts
20
+ import commandScoreModule from "@superhuman/command-score";
21
+ var commandScore = commandScoreModule;
22
+
23
+ // src/components/autocomplete-item/helpers.ts
24
+ function isAutocompleteItem(element) {
25
+ var _a;
26
+ return ((_a = element == null ? void 0 : element.tagName) == null ? void 0 : _a.toLowerCase()) === "prosekit-autocomplete-item";
27
+ }
28
+
29
+ // src/components/autocomplete-list/controller.ts
30
+ import { addKeymap } from "@prosekit/core";
31
+ import "lit";
32
+ var AutocompleteListController = class {
33
+ constructor(host, keymap) {
34
+ this.host = host;
35
+ this.keymap = keymap;
36
+ this.editor = null;
37
+ this.cleanup = null;
38
+ this.host.addController(this);
39
+ }
40
+ setEditor(editor) {
41
+ if (this.editor !== editor) {
42
+ this.editor = editor;
43
+ this.addExtension();
44
+ }
45
+ }
46
+ hostDisconnected() {
47
+ var _a;
48
+ (_a = this.cleanup) == null ? void 0 : _a.call(this);
49
+ this.cleanup = null;
50
+ }
51
+ addExtension() {
52
+ var _a;
53
+ (_a = this.cleanup) == null ? void 0 : _a.call(this);
54
+ this.cleanup = null;
55
+ if (!this.editor || !this.keymap) {
56
+ return;
57
+ }
58
+ const extension = addKeymap(this.keymap);
59
+ this.cleanup = this.editor.use(extension);
60
+ }
61
+ };
62
+
63
+ // src/components/autocomplete-list/component.ts
64
+ var AutocompleteList = class extends LitElement {
65
+ constructor() {
66
+ super(...arguments);
67
+ /** @hidden */
68
+ this.controller = new AutocompleteListController(this, {
69
+ ArrowUp: () => {
70
+ if (!this.active)
71
+ return false;
72
+ this.updateSelectedByChange(-1);
73
+ return true;
74
+ },
75
+ ArrowDown: () => {
76
+ if (!this.active)
77
+ return false;
78
+ this.updateSelectedByChange(1);
79
+ return true;
80
+ },
81
+ Escape: () => {
82
+ var _a, _b;
83
+ if (!this.active)
84
+ return false;
85
+ (_b = (_a = this.popoverContext) == null ? void 0 : _a.handleDismiss) == null ? void 0 : _b.call(_a);
86
+ return true;
87
+ },
88
+ Enter: () => {
89
+ if (!this.active)
90
+ return false;
91
+ this.handleSelect(this.selectedItem);
92
+ return true;
93
+ }
94
+ });
95
+ this.lastMouseMoveTime = 0;
96
+ this.popoverContext = null;
97
+ this.context = {
98
+ scores: /* @__PURE__ */ new Map(),
99
+ selectedValue: "",
100
+ registerValue: (value) => this.registerValue(value)
101
+ };
102
+ }
103
+ get active() {
104
+ var _a, _b;
105
+ return (_b = (_a = this.popoverContext) == null ? void 0 : _a.active) != null ? _b : false;
106
+ }
107
+ firstUpdated() {
108
+ this.selectFirstItem();
109
+ }
110
+ get items() {
111
+ var _a, _b, _c;
112
+ return (_c = (_b = (_a = this.defaultSlot) == null ? void 0 : _a.assignedElements({ flatten: true })) == null ? void 0 : _b.filter(isAutocompleteItem)) != null ? _c : [];
113
+ }
114
+ get availableItems() {
115
+ var _a, _b;
116
+ return (_b = (_a = this.items) == null ? void 0 : _a.filter((item) => !item.hidden)) != null ? _b : [];
117
+ }
118
+ get firstItem() {
119
+ var _a;
120
+ return (_a = this.availableItems[0]) != null ? _a : null;
121
+ }
122
+ get selectedItem() {
123
+ var _a;
124
+ return (_a = this.availableItems.find(
125
+ (item) => item.content === this.context.selectedValue
126
+ )) != null ? _a : null;
127
+ }
128
+ selectFirstItem() {
129
+ var _a, _b;
130
+ const selected = (_b = (_a = this.firstItem) == null ? void 0 : _a.content) != null ? _b : "";
131
+ this.updateValue(selected);
132
+ }
133
+ updateValue(selectedValue) {
134
+ if (this.context.selectedValue === selectedValue)
135
+ return;
136
+ this.context = { ...this.context, selectedValue };
137
+ }
138
+ registerValue(value) {
139
+ if (!this.context.scores.has(value)) {
140
+ this.context.scores.set(value, 0);
141
+ this.requestUpdate();
142
+ }
143
+ return () => {
144
+ this.context.scores.delete(value);
145
+ };
146
+ }
147
+ /** @hidden */
148
+ willUpdate(changedProperties) {
149
+ var _a, _b;
150
+ if (changedProperties.has("editor") && this.editor) {
151
+ this.controller.setEditor(this.editor);
152
+ }
153
+ const query2 = (_b = (_a = this.popoverContext) == null ? void 0 : _a.query) != null ? _b : "";
154
+ const scores = new Map(
155
+ this.items.map((item) => {
156
+ const content = item.content;
157
+ const score = commandScore(content, query2);
158
+ return [content, score];
159
+ })
160
+ );
161
+ this.context = { ...this.context, scores };
162
+ }
163
+ updateSelectedByChange(change) {
164
+ const items = this.availableItems;
165
+ if (items.length === 0) {
166
+ return;
167
+ }
168
+ const selectedItem = this.selectedItem;
169
+ const selectedIndex = selectedItem ? items.indexOf(selectedItem) : -1;
170
+ let nextIndex = selectedIndex + change;
171
+ if (nextIndex < 0) {
172
+ nextIndex = 0;
173
+ } else if (nextIndex >= items.length) {
174
+ nextIndex = items.length - 1;
175
+ }
176
+ if (selectedIndex !== nextIndex) {
177
+ this.updateValue(items[nextIndex].content);
178
+ }
179
+ }
180
+ handleMouseMove() {
181
+ this.lastMouseMoveTime = Date.now();
182
+ }
183
+ handleMouseOver(event) {
184
+ if (this.lastMouseMoveTime + 500 < Date.now()) {
185
+ return;
186
+ }
187
+ const target = event.target;
188
+ if (isAutocompleteItem(target)) {
189
+ this.updateValue(target.content);
190
+ }
191
+ }
192
+ handleClick(event) {
193
+ event.preventDefault();
194
+ const target = event.target;
195
+ const item = target == null ? void 0 : target.closest("prosekit-autocomplete-item");
196
+ if (item && isAutocompleteItem(item)) {
197
+ this.handleSelect(item);
198
+ }
199
+ }
200
+ handleMouseDown(event) {
201
+ event.preventDefault();
202
+ }
203
+ handleSelect(item) {
204
+ var _a, _b, _c;
205
+ (_b = (_a = this.popoverContext) == null ? void 0 : _a.handleSubmit) == null ? void 0 : _b.call(_a);
206
+ (_c = item == null ? void 0 : item.onSelect) == null ? void 0 : _c.call(item);
207
+ }
208
+ /** @hidden */
209
+ render() {
210
+ return html`<div role="listbox" aria-label="Suggestions" @mousemove="${this.handleMouseMove.bind(this)}" @mouseover="${this.handleMouseOver.bind(this)}" @click="${this.handleClick.bind(this)}" @mousedown="${this.handleMouseDown.bind(this)}"><slot></slot></div>`;
211
+ }
212
+ };
213
+ /** @hidden */
214
+ AutocompleteList.styles = blockComponentStyles;
215
+ __decorateClass([
216
+ property({ attribute: false })
217
+ ], AutocompleteList.prototype, "editor", 2);
218
+ __decorateClass([
219
+ consume({ context: commandPopoverContext, subscribe: true }),
220
+ state()
221
+ ], AutocompleteList.prototype, "popoverContext", 2);
222
+ __decorateClass([
223
+ provide({ context: commandListContext }),
224
+ state()
225
+ ], AutocompleteList.prototype, "context", 2);
226
+ __decorateClass([
227
+ query("slot")
228
+ ], AutocompleteList.prototype, "defaultSlot", 2);
229
+ AutocompleteList = __decorateClass([
230
+ customElement("prosekit-autocomplete-list")
231
+ ], AutocompleteList);
232
+
233
+ export {
234
+ commandPopoverContext,
235
+ AutocompleteList
236
+ };
@@ -18,9 +18,16 @@ import { css } from "lit";
18
18
  var componentStyles = css`:host{box-sizing:border-box}:host *,:host ::after,:host ::before{box-sizing:inherit}`;
19
19
 
20
20
  // src/styles/block-component.styles.ts
21
- var blockComponentStyles = css2`${componentStyles}:host{display:block}`;
21
+ var blockComponentStyles = css2`${componentStyles}:host{display:block}:host([hidden]){display:none}`;
22
+
23
+ // src/components/autocomplete-list/context.ts
24
+ import { createContext } from "@lit-labs/context";
25
+ var commandListContext = createContext(
26
+ "prosekit-autocomplete-list-context"
27
+ );
22
28
 
23
29
  export {
24
30
  __decorateClass,
25
- blockComponentStyles
31
+ blockComponentStyles,
32
+ commandListContext
26
33
  };
@@ -0,0 +1,69 @@
1
+ import {
2
+ __decorateClass,
3
+ blockComponentStyles,
4
+ commandListContext
5
+ } from "./chunk-J73E7P6J.js";
6
+
7
+ // src/components/autocomplete-item/component.ts
8
+ import { consume } from "@lit-labs/context";
9
+ import { LitElement, html } from "lit";
10
+ import { customElement, property, query, state } from "lit/decorators.js";
11
+ var AutocompleteItem = class extends LitElement {
12
+ constructor() {
13
+ super(...arguments);
14
+ this.value = "";
15
+ this.selected = false;
16
+ }
17
+ get content() {
18
+ const text = this.value || this.textContent || "";
19
+ return text.trim().toLowerCase();
20
+ }
21
+ willUpdate(changedProperties) {
22
+ var _a, _b;
23
+ const content = this.content;
24
+ this.selected = content === ((_a = this.listContext) == null ? void 0 : _a.selectedValue);
25
+ const score = ((_b = this.listContext) == null ? void 0 : _b.scores.get(content)) || 0;
26
+ this.inert = score <= 0;
27
+ this.hidden = score <= 0;
28
+ if (changedProperties.has("listContext") && this.listContext) {
29
+ this.listContext.registerValue(this.content);
30
+ }
31
+ }
32
+ updated(changedProperties) {
33
+ if (this.selected && changedProperties.has("selected") && !changedProperties.get("selected")) {
34
+ this.scrollIntoView({ block: "nearest" });
35
+ }
36
+ }
37
+ /** @hidden */
38
+ render() {
39
+ if (this.hidden) {
40
+ return null;
41
+ }
42
+ return html`<div role="option" aria-selected="${this.selected}"><slot></slot></div>`;
43
+ }
44
+ };
45
+ /** @hidden */
46
+ AutocompleteItem.styles = blockComponentStyles;
47
+ __decorateClass([
48
+ property({ type: String, reflect: true, attribute: "data-value" })
49
+ ], AutocompleteItem.prototype, "value", 2);
50
+ __decorateClass([
51
+ property({ type: Boolean, reflect: true, attribute: "data-selected" })
52
+ ], AutocompleteItem.prototype, "selected", 2);
53
+ __decorateClass([
54
+ property({ attribute: false })
55
+ ], AutocompleteItem.prototype, "onSelect", 2);
56
+ __decorateClass([
57
+ query("slot")
58
+ ], AutocompleteItem.prototype, "defaultSlot", 2);
59
+ __decorateClass([
60
+ consume({ context: commandListContext, subscribe: true }),
61
+ state({})
62
+ ], AutocompleteItem.prototype, "listContext", 2);
63
+ AutocompleteItem = __decorateClass([
64
+ customElement("prosekit-autocomplete-item")
65
+ ], AutocompleteItem);
66
+
67
+ export {
68
+ AutocompleteItem
69
+ };
@@ -0,0 +1,7 @@
1
+ type AutocompleteListContext = {
2
+ scores: Map<string, number>;
3
+ selectedValue: string;
4
+ registerValue: (value: string) => VoidFunction;
5
+ };
6
+
7
+ export { AutocompleteListContext as A };
@@ -0,0 +1,8 @@
1
+ type AutocompletePopoverContext = {
2
+ active: boolean;
3
+ query: string;
4
+ handleDismiss: VoidFunction;
5
+ handleSubmit: VoidFunction;
6
+ };
7
+
8
+ export { AutocompletePopoverContext as A };
@@ -0,0 +1,16 @@
1
+ import * as lit from 'lit';
2
+ import { LitElement, CSSResultGroup, PropertyValues } from 'lit';
3
+ import { A as AutocompleteListContext } from './context-19474449.js';
4
+
5
+ interface AutocompleteEmptyProps {
6
+ }
7
+ declare class AutocompleteEmpty extends LitElement implements AutocompleteEmptyProps {
8
+ /** @hidden */
9
+ static styles: CSSResultGroup;
10
+ listContext?: AutocompleteListContext;
11
+ protected willUpdate(_changedProperties: PropertyValues<this>): void;
12
+ /** @hidden */
13
+ render(): lit.TemplateResult<1> | null;
14
+ }
15
+
16
+ export { AutocompleteEmpty, AutocompleteEmptyProps };
@@ -0,0 +1,46 @@
1
+ import {
2
+ __decorateClass,
3
+ blockComponentStyles,
4
+ commandListContext
5
+ } from "./chunk-J73E7P6J.js";
6
+
7
+ // src/components/autocomplete-empty/index.ts
8
+ import { consume } from "@lit-labs/context";
9
+ import { LitElement, html } from "lit";
10
+ import { customElement, state } from "lit/decorators.js";
11
+ var AutocompleteEmpty = class extends LitElement {
12
+ willUpdate(_changedProperties) {
13
+ var _a;
14
+ const scores = (_a = this.listContext) == null ? void 0 : _a.scores;
15
+ let hasMatch = false;
16
+ if (scores) {
17
+ for (const score of scores.values()) {
18
+ if (score > 0) {
19
+ hasMatch = true;
20
+ break;
21
+ }
22
+ }
23
+ }
24
+ this.hidden = hasMatch;
25
+ this.inert = hasMatch;
26
+ }
27
+ /** @hidden */
28
+ render() {
29
+ if (this.hidden) {
30
+ return null;
31
+ }
32
+ return html`<div role="option"><slot></slot></div>`;
33
+ }
34
+ };
35
+ /** @hidden */
36
+ AutocompleteEmpty.styles = blockComponentStyles;
37
+ __decorateClass([
38
+ consume({ context: commandListContext, subscribe: true }),
39
+ state()
40
+ ], AutocompleteEmpty.prototype, "listContext", 2);
41
+ AutocompleteEmpty = __decorateClass([
42
+ customElement("prosekit-autocomplete-empty")
43
+ ], AutocompleteEmpty);
44
+ export {
45
+ AutocompleteEmpty
46
+ };
@@ -0,0 +1,31 @@
1
+ import * as lit from 'lit';
2
+ import { LitElement, CSSResultGroup, PropertyValues } from 'lit';
3
+ import { A as AutocompleteListContext } from './context-19474449.js';
4
+
5
+ interface AutocompleteItemProps {
6
+ value?: string;
7
+ onSelect: VoidFunction;
8
+ }
9
+ /**
10
+ * Command menu item. Becomes active on pointer enter or through keyboard
11
+ * navigation. Preferably pass a `value`, otherwise the value will be inferred
12
+ * from the rendered item's `textContent`.
13
+ */
14
+ declare class AutocompleteItem extends LitElement implements Partial<AutocompleteItemProps> {
15
+ /** @hidden */
16
+ static styles: CSSResultGroup;
17
+ value: string;
18
+ selected: boolean;
19
+ /** @hidden */
20
+ onSelect?: VoidFunction;
21
+ /** @hidden */
22
+ defaultSlot?: HTMLSlotElement;
23
+ listContext?: AutocompleteListContext;
24
+ get content(): string;
25
+ protected willUpdate(changedProperties: PropertyValues<this>): void;
26
+ protected updated(changedProperties: PropertyValues<this>): void;
27
+ /** @hidden */
28
+ render(): lit.TemplateResult<1> | null;
29
+ }
30
+
31
+ export { AutocompleteItem, AutocompleteItemProps };
@@ -0,0 +1,7 @@
1
+ import {
2
+ AutocompleteItem
3
+ } from "./chunk-UDTISUHF.js";
4
+ import "./chunk-J73E7P6J.js";
5
+ export {
6
+ AutocompleteItem
7
+ };
@@ -0,0 +1,42 @@
1
+ import * as lit from 'lit';
2
+ import { LitElement, CSSResultGroup, PropertyValues } from 'lit';
3
+ import { Editor } from '@prosekit/core';
4
+ import { A as AutocompletePopoverContext } from './context-436a56d3.js';
5
+ import { A as AutocompleteListContext } from './context-19474449.js';
6
+
7
+ interface AutocompleteListProps {
8
+ editor: Editor;
9
+ }
10
+ declare class AutocompleteList extends LitElement implements Partial<AutocompleteListProps> {
11
+ /** @hidden */
12
+ static styles: CSSResultGroup;
13
+ /** @hidden */
14
+ private controller;
15
+ private get active();
16
+ private lastMouseMoveTime;
17
+ editor?: Editor;
18
+ popoverContext: AutocompletePopoverContext | null;
19
+ context: AutocompleteListContext;
20
+ protected firstUpdated(): void;
21
+ private get items();
22
+ private get availableItems();
23
+ private get firstItem();
24
+ private get selectedItem();
25
+ selectFirstItem(): void;
26
+ private updateValue;
27
+ private registerValue;
28
+ /** @hidden */
29
+ defaultSlot?: HTMLSlotElement;
30
+ /** @hidden */
31
+ willUpdate(changedProperties: PropertyValues<this>): void;
32
+ private updateSelectedByChange;
33
+ private handleMouseMove;
34
+ private handleMouseOver;
35
+ private handleClick;
36
+ private handleMouseDown;
37
+ private handleSelect;
38
+ /** @hidden */
39
+ render(): lit.TemplateResult<1>;
40
+ }
41
+
42
+ export { AutocompleteList, AutocompleteListProps };
@@ -0,0 +1,8 @@
1
+ import {
2
+ AutocompleteList
3
+ } from "./chunk-65QAWC7L.js";
4
+ import "./chunk-UDTISUHF.js";
5
+ import "./chunk-J73E7P6J.js";
6
+ export {
7
+ AutocompleteList
8
+ };
@@ -0,0 +1,46 @@
1
+ import * as lit from 'lit';
2
+ import { LitElement, CSSResultGroup } from 'lit';
3
+ import { ComputePositionConfig } from '@floating-ui/dom';
4
+ import { Editor } from '@prosekit/core';
5
+ import { A as AutocompletePopoverContext } from './context-436a56d3.js';
6
+
7
+ /**
8
+ * The `PopoverOptions` interface defines the options that can be passed to the
9
+ * `computePosition` function from Floating UI. These options are used to
10
+ * configure the positioning of the popover element relative to its reference
11
+ * element. For more information on the available options, please refer to the
12
+ * Floating UI documentation.
13
+ *
14
+ * https://floating-ui.com/docs/computeposition#options
15
+ */
16
+ type PopoverOptions = ComputePositionConfig;
17
+
18
+ interface AutocompletePopoverProps {
19
+ editor: Editor;
20
+ regex: RegExp;
21
+ popoverOptions?: PopoverOptions;
22
+ }
23
+ declare class AutocompletePopover extends LitElement implements Partial<AutocompletePopoverProps> {
24
+ /** @hidden */
25
+ static styles: CSSResultGroup;
26
+ /** @hidden */
27
+ private controller;
28
+ editor?: Editor;
29
+ regex?: RegExp;
30
+ popoverOptions: PopoverOptions;
31
+ context: AutocompletePopoverContext;
32
+ /** @hidden */
33
+ onSelect?: VoidFunction;
34
+ private get list();
35
+ private updateContext;
36
+ /** @hidden */
37
+ defaultSlot?: HTMLSlotElement;
38
+ /** @hidden */
39
+ protected get active(): boolean;
40
+ /** @hidden */
41
+ willUpdate(): void;
42
+ /** @hidden */
43
+ render(): lit.TemplateResult<1>;
44
+ }
45
+
46
+ export { AutocompletePopover, AutocompletePopoverProps, PopoverOptions };