@liveblocks/react-tiptap 2.16.1-ai2 → 2.16.1-ai3
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/dist/LiveblocksExtension.js +5 -4
- package/dist/LiveblocksExtension.js.map +1 -1
- package/dist/LiveblocksExtension.mjs +5 -4
- package/dist/LiveblocksExtension.mjs.map +1 -1
- package/dist/ai/AiExtension.js +174 -104
- package/dist/ai/AiExtension.js.map +1 -1
- package/dist/ai/AiExtension.mjs +175 -106
- package/dist/ai/AiExtension.mjs.map +1 -1
- package/dist/ai/AiToolbar.js +176 -84
- package/dist/ai/AiToolbar.js.map +1 -1
- package/dist/ai/AiToolbar.mjs +181 -89
- package/dist/ai/AiToolbar.mjs.map +1 -1
- package/dist/comments/FloatingComposer.js +1 -4
- package/dist/comments/FloatingComposer.js.map +1 -1
- package/dist/comments/FloatingComposer.mjs +2 -5
- package/dist/comments/FloatingComposer.mjs.map +1 -1
- package/dist/index.d.mts +42 -10
- package/dist/index.d.ts +42 -10
- package/dist/index.js.map +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/toolbar/Toolbar.js +1 -1
- package/dist/toolbar/Toolbar.js.map +1 -1
- package/dist/toolbar/Toolbar.mjs +1 -1
- package/dist/toolbar/Toolbar.mjs.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/types.mjs.map +1 -1
- package/dist/utils.js +85 -3
- package/dist/utils.js.map +1 -1
- package/dist/utils.mjs +84 -3
- package/dist/utils.mjs.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.mjs +1 -1
- package/package.json +6 -6
- package/src/styles/index.css +115 -59
- package/src/styles/utils.css +6 -0
- package/styles.css +1 -1
- package/styles.css.map +1 -1
package/dist/utils.js
CHANGED
|
@@ -58,8 +58,8 @@ const mapFragment = (fragment, callback) => {
|
|
|
58
58
|
});
|
|
59
59
|
return model.Fragment.from(content);
|
|
60
60
|
};
|
|
61
|
-
function
|
|
62
|
-
const { from, to } =
|
|
61
|
+
function getDomRange(editor, range) {
|
|
62
|
+
const { from, to } = range;
|
|
63
63
|
const fromPos = editor.view.domAtPos(from);
|
|
64
64
|
const endPos = editor.view.domAtPos(to);
|
|
65
65
|
const domRange = document.createRange();
|
|
@@ -73,9 +73,91 @@ function compareSelections(a, b) {
|
|
|
73
73
|
}
|
|
74
74
|
return a.eq(b);
|
|
75
75
|
}
|
|
76
|
+
const DOCUMENT_TEXT_TRUNCATION = "[\u2026]";
|
|
77
|
+
const DOCUMENT_TEXT_BLOCK_SEPARATOR = " ";
|
|
78
|
+
function getDocumentText(editor, maxLength = 1e4) {
|
|
79
|
+
const { selection, doc } = editor.state;
|
|
80
|
+
const selectionLength = selection.to - selection.from;
|
|
81
|
+
if (maxLength >= doc.content.size) {
|
|
82
|
+
return {
|
|
83
|
+
beforeSelection: doc.textBetween(
|
|
84
|
+
0,
|
|
85
|
+
selection.from,
|
|
86
|
+
DOCUMENT_TEXT_BLOCK_SEPARATOR
|
|
87
|
+
),
|
|
88
|
+
selection: doc.textBetween(
|
|
89
|
+
selection.from,
|
|
90
|
+
selection.to,
|
|
91
|
+
DOCUMENT_TEXT_BLOCK_SEPARATOR
|
|
92
|
+
),
|
|
93
|
+
afterSelection: doc.textBetween(
|
|
94
|
+
selection.to,
|
|
95
|
+
doc.content.size,
|
|
96
|
+
DOCUMENT_TEXT_BLOCK_SEPARATOR
|
|
97
|
+
)
|
|
98
|
+
};
|
|
99
|
+
} else if (selectionLength > maxLength) {
|
|
100
|
+
const selectionStart = doc.textBetween(
|
|
101
|
+
selection.from,
|
|
102
|
+
selection.from + Math.floor(maxLength / 2) - DOCUMENT_TEXT_TRUNCATION.length,
|
|
103
|
+
DOCUMENT_TEXT_BLOCK_SEPARATOR
|
|
104
|
+
);
|
|
105
|
+
const selectionEnd = doc.textBetween(
|
|
106
|
+
selection.to - Math.floor(maxLength / 2) + DOCUMENT_TEXT_TRUNCATION.length,
|
|
107
|
+
selection.to,
|
|
108
|
+
DOCUMENT_TEXT_BLOCK_SEPARATOR
|
|
109
|
+
);
|
|
110
|
+
return {
|
|
111
|
+
beforeSelection: "",
|
|
112
|
+
selection: `${selectionStart}${DOCUMENT_TEXT_TRUNCATION}${selectionEnd}`,
|
|
113
|
+
afterSelection: ""
|
|
114
|
+
};
|
|
115
|
+
} else {
|
|
116
|
+
let beforeLength = Math.min(
|
|
117
|
+
selection.from,
|
|
118
|
+
Math.floor((maxLength - selectionLength) / 2)
|
|
119
|
+
);
|
|
120
|
+
const afterLength = Math.min(
|
|
121
|
+
doc.content.size - selection.to,
|
|
122
|
+
maxLength - selectionLength - beforeLength
|
|
123
|
+
);
|
|
124
|
+
if (beforeLength + afterLength + selectionLength < maxLength) {
|
|
125
|
+
beforeLength = Math.min(
|
|
126
|
+
selection.from,
|
|
127
|
+
maxLength - selectionLength - afterLength
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
let beforeSelection = doc.textBetween(
|
|
131
|
+
Math.max(0, selection.from - beforeLength),
|
|
132
|
+
selection.from,
|
|
133
|
+
DOCUMENT_TEXT_BLOCK_SEPARATOR
|
|
134
|
+
);
|
|
135
|
+
let afterSelection = doc.textBetween(
|
|
136
|
+
selection.to,
|
|
137
|
+
Math.min(doc.content.size, selection.to + afterLength),
|
|
138
|
+
DOCUMENT_TEXT_BLOCK_SEPARATOR
|
|
139
|
+
);
|
|
140
|
+
if (selection.from - beforeLength > 0) {
|
|
141
|
+
beforeSelection = `${DOCUMENT_TEXT_TRUNCATION}${beforeSelection}`;
|
|
142
|
+
}
|
|
143
|
+
if (selection.to + afterLength < doc.content.size) {
|
|
144
|
+
afterSelection = `${afterSelection}${DOCUMENT_TEXT_TRUNCATION}`;
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
beforeSelection,
|
|
148
|
+
selection: doc.textBetween(
|
|
149
|
+
selection.from,
|
|
150
|
+
selection.to,
|
|
151
|
+
DOCUMENT_TEXT_BLOCK_SEPARATOR
|
|
152
|
+
),
|
|
153
|
+
afterSelection
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
}
|
|
76
157
|
|
|
77
158
|
exports.compareSelections = compareSelections;
|
|
78
|
-
exports.
|
|
159
|
+
exports.getDocumentText = getDocumentText;
|
|
160
|
+
exports.getDomRange = getDomRange;
|
|
79
161
|
exports.getMentionsFromNode = getMentionsFromNode;
|
|
80
162
|
exports.getRangeFromRelativeSelections = getRangeFromRelativeSelections;
|
|
81
163
|
exports.getRectFromCoords = getRectFromCoords;
|
package/dist/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sources":["../src/utils.ts"],"sourcesContent":["import type { ClientRectObject } from \"@floating-ui/react-dom\";\nimport type { Editor, Range } from \"@tiptap/core\";\nimport type { Node as ProseMirrorNode } from \"@tiptap/pm/model\";\nimport { Fragment } from \"@tiptap/pm/model\";\nimport type { EditorState, Selection } from \"@tiptap/pm/state\";\nimport {\n getRelativeSelection,\n relativePositionToAbsolutePosition,\n ySyncPluginKey,\n} from \"y-prosemirror\";\nimport type { RelativePosition } from \"yjs\";\n\nimport type { YSyncPluginState } from \"./types\";\nimport { LIVEBLOCKS_MENTION_TYPE } from \"./types\";\n\nexport const getRelativeSelectionFromState = (state: EditorState) => {\n const pluginState = ySyncPluginKey.getState(state) as YSyncPluginState;\n if (!pluginState) return null;\n return getRelativeSelection(pluginState.binding, state);\n};\n\nexport const getRangeFromRelativeSelections = (\n pos: { anchor: RelativePosition; head: RelativePosition },\n state: EditorState\n) => {\n const pluginState = ySyncPluginKey.getState(state) as YSyncPluginState;\n if (!pluginState || !pluginState.binding) return { from: 0, to: 0 };\n const { doc, type, mapping } = pluginState.binding;\n const anchor =\n relativePositionToAbsolutePosition(doc, type, pos.anchor, mapping) ?? 0;\n const head =\n relativePositionToAbsolutePosition(doc, type, pos.head, mapping) ?? 0;\n\n const from = anchor > head ? head : anchor;\n const to = anchor > head ? anchor : head;\n return { from, to };\n};\n\nexport const getRectFromCoords = (coords: {\n top: number;\n left: number;\n right: number;\n bottom: number;\n}): ClientRectObject => {\n return {\n ...coords,\n x: coords.left,\n y: coords.top,\n width: coords.right - coords.left,\n height: coords.bottom - coords.top,\n };\n};\n\nexport const getMentionsFromNode = (\n node: ProseMirrorNode,\n range: Range\n): { notificationId: string; userId: string }[] => {\n const result: { notificationId: string; userId: string }[] = [];\n node.nodesBetween(range.from, range.to, (child) => {\n if (child.type.name === LIVEBLOCKS_MENTION_TYPE) {\n const mention = child.attrs as { id?: string; notificationId?: string };\n if (mention.id && mention.notificationId) {\n result.push({\n notificationId: mention.notificationId,\n userId: mention.id,\n });\n }\n }\n });\n return result;\n};\n\n// How to modify data in transformPasted, inspired by: https://discuss.prosemirror.net/t/modify-specific-node-on-copy-and-paste-in-clipboard/4901/4\nexport const mapFragment = (\n fragment: Fragment,\n callback: (\n node: ProseMirrorNode\n ) => ProseMirrorNode | ProseMirrorNode[] | Fragment | null\n): Fragment => {\n const content: ProseMirrorNode[] = [];\n fragment.forEach((node) => {\n if (node.content.childCount > 0) {\n content.push(\n node.type.create(node.attrs, mapFragment(node.content, callback))\n );\n return;\n }\n content.push(callback(node) as ProseMirrorNode);\n });\n\n return Fragment.from(content);\n};\n\nexport function getDomRangeFromSelection(\n selection: { from: number; to: number } | number,\n editor: Editor\n) {\n const { from, to } =\n typeof selection === \"number\"\n ? { from: selection, to: selection }\n : selection;\n const fromPos = editor.view.domAtPos(from);\n const endPos = editor.view.domAtPos(to);\n\n const domRange = document.createRange();\n domRange.setStart(fromPos.node, fromPos.offset);\n domRange.setEnd(endPos.node, endPos.offset);\n\n return domRange;\n}\n\nexport function compareSelections(\n a: Selection | null | undefined,\n b: Selection | null | undefined\n) {\n if (!a || !b) {\n return false;\n }\n\n return a.eq(b);\n}\n"],"names":["ySyncPluginKey","getRelativeSelection","relativePositionToAbsolutePosition","LIVEBLOCKS_MENTION_TYPE","Fragment"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"utils.js","sources":["../src/utils.ts"],"sourcesContent":["import type { ClientRectObject } from \"@floating-ui/react-dom\";\nimport type { Editor, Range } from \"@tiptap/core\";\nimport type { Node as ProseMirrorNode } from \"@tiptap/pm/model\";\nimport { Fragment } from \"@tiptap/pm/model\";\nimport type { EditorState, Selection } from \"@tiptap/pm/state\";\nimport {\n getRelativeSelection,\n relativePositionToAbsolutePosition,\n ySyncPluginKey,\n} from \"y-prosemirror\";\nimport type { RelativePosition } from \"yjs\";\n\nimport type { YSyncPluginState } from \"./types\";\nimport { LIVEBLOCKS_MENTION_TYPE } from \"./types\";\n\nexport const getRelativeSelectionFromState = (state: EditorState) => {\n const pluginState = ySyncPluginKey.getState(state) as YSyncPluginState;\n if (!pluginState) return null;\n return getRelativeSelection(pluginState.binding, state);\n};\n\nexport const getRangeFromRelativeSelections = (\n pos: { anchor: RelativePosition; head: RelativePosition },\n state: EditorState\n) => {\n const pluginState = ySyncPluginKey.getState(state) as YSyncPluginState;\n if (!pluginState || !pluginState.binding) return { from: 0, to: 0 };\n const { doc, type, mapping } = pluginState.binding;\n const anchor =\n relativePositionToAbsolutePosition(doc, type, pos.anchor, mapping) ?? 0;\n const head =\n relativePositionToAbsolutePosition(doc, type, pos.head, mapping) ?? 0;\n\n const from = anchor > head ? head : anchor;\n const to = anchor > head ? anchor : head;\n return { from, to };\n};\n\nexport const getRectFromCoords = (coords: {\n top: number;\n left: number;\n right: number;\n bottom: number;\n}): ClientRectObject => {\n return {\n ...coords,\n x: coords.left,\n y: coords.top,\n width: coords.right - coords.left,\n height: coords.bottom - coords.top,\n };\n};\n\nexport const getMentionsFromNode = (\n node: ProseMirrorNode,\n range: Range\n): { notificationId: string; userId: string }[] => {\n const result: { notificationId: string; userId: string }[] = [];\n node.nodesBetween(range.from, range.to, (child) => {\n if (child.type.name === LIVEBLOCKS_MENTION_TYPE) {\n const mention = child.attrs as { id?: string; notificationId?: string };\n if (mention.id && mention.notificationId) {\n result.push({\n notificationId: mention.notificationId,\n userId: mention.id,\n });\n }\n }\n });\n return result;\n};\n\n// How to modify data in transformPasted, inspired by: https://discuss.prosemirror.net/t/modify-specific-node-on-copy-and-paste-in-clipboard/4901/4\nexport const mapFragment = (\n fragment: Fragment,\n callback: (\n node: ProseMirrorNode\n ) => ProseMirrorNode | ProseMirrorNode[] | Fragment | null\n): Fragment => {\n const content: ProseMirrorNode[] = [];\n fragment.forEach((node) => {\n if (node.content.childCount > 0) {\n content.push(\n node.type.create(node.attrs, mapFragment(node.content, callback))\n );\n return;\n }\n content.push(callback(node) as ProseMirrorNode);\n });\n\n return Fragment.from(content);\n};\n\nexport function getDomRange(editor: Editor, range: Range) {\n const { from, to } = range;\n const fromPos = editor.view.domAtPos(from);\n const endPos = editor.view.domAtPos(to);\n\n const domRange = document.createRange();\n domRange.setStart(fromPos.node, fromPos.offset);\n domRange.setEnd(endPos.node, endPos.offset);\n\n return domRange;\n}\n\nexport function compareSelections(\n a: Selection | null | undefined,\n b: Selection | null | undefined\n) {\n if (!a || !b) {\n return false;\n }\n\n return a.eq(b);\n}\n\nexport type DocumentText = {\n beforeSelection: string;\n selection: string;\n afterSelection: string;\n};\n\nconst DOCUMENT_TEXT_TRUNCATION = \"[…]\";\nconst DOCUMENT_TEXT_BLOCK_SEPARATOR = \" \";\n\nexport function getDocumentText(\n editor: Editor,\n maxLength = 10_000\n): DocumentText {\n const { selection, doc } = editor.state;\n\n const selectionLength = selection.to - selection.from;\n\n if (maxLength >= doc.content.size) {\n // If the document is smaller than the maximum length, return the entire document\n return {\n beforeSelection: doc.textBetween(\n 0,\n selection.from,\n DOCUMENT_TEXT_BLOCK_SEPARATOR\n ),\n selection: doc.textBetween(\n selection.from,\n selection.to,\n DOCUMENT_TEXT_BLOCK_SEPARATOR\n ),\n afterSelection: doc.textBetween(\n selection.to,\n doc.content.size,\n DOCUMENT_TEXT_BLOCK_SEPARATOR\n ),\n };\n } else if (selectionLength > maxLength) {\n // If the selection is too large, truncate its middle to still allow continuations\n const selectionStart = doc.textBetween(\n selection.from,\n selection.from +\n Math.floor(maxLength / 2) -\n DOCUMENT_TEXT_TRUNCATION.length,\n DOCUMENT_TEXT_BLOCK_SEPARATOR\n );\n const selectionEnd = doc.textBetween(\n selection.to -\n Math.floor(maxLength / 2) +\n DOCUMENT_TEXT_TRUNCATION.length,\n selection.to,\n DOCUMENT_TEXT_BLOCK_SEPARATOR\n );\n\n return {\n beforeSelection: \"\",\n selection: `${selectionStart}${DOCUMENT_TEXT_TRUNCATION}${selectionEnd}`,\n afterSelection: \"\",\n };\n } else {\n // If the selection is smaller than (or equal to) the maximum length, extract as much as possible from the document around the selection\n\n // Start by taking as much as possible after the selection\n let beforeLength = Math.min(\n selection.from,\n Math.floor((maxLength - selectionLength) / 2)\n );\n const afterLength = Math.min(\n doc.content.size - selection.to,\n maxLength - selectionLength - beforeLength\n );\n\n // If needed (e.g. the selection is near the end), compensate before the selection\n if (beforeLength + afterLength + selectionLength < maxLength) {\n beforeLength = Math.min(\n selection.from,\n maxLength - selectionLength - afterLength\n );\n }\n\n let beforeSelection = doc.textBetween(\n Math.max(0, selection.from - beforeLength),\n selection.from,\n DOCUMENT_TEXT_BLOCK_SEPARATOR\n );\n let afterSelection = doc.textBetween(\n selection.to,\n Math.min(doc.content.size, selection.to + afterLength),\n DOCUMENT_TEXT_BLOCK_SEPARATOR\n );\n\n // Add leading truncation if `beforeSelection` doesn't contain the document's start\n if (selection.from - beforeLength > 0) {\n beforeSelection = `${DOCUMENT_TEXT_TRUNCATION}${beforeSelection}`;\n }\n\n // Add trailing truncation if `afterSelection` doesn't contain the document's end\n if (selection.to + afterLength < doc.content.size) {\n afterSelection = `${afterSelection}${DOCUMENT_TEXT_TRUNCATION}`;\n }\n\n return {\n beforeSelection,\n selection: doc.textBetween(\n selection.from,\n selection.to,\n DOCUMENT_TEXT_BLOCK_SEPARATOR\n ),\n afterSelection,\n };\n }\n}\n"],"names":["ySyncPluginKey","getRelativeSelection","relativePositionToAbsolutePosition","LIVEBLOCKS_MENTION_TYPE","Fragment"],"mappings":"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"}
|
package/dist/utils.mjs
CHANGED
|
@@ -56,8 +56,8 @@ const mapFragment = (fragment, callback) => {
|
|
|
56
56
|
});
|
|
57
57
|
return Fragment.from(content);
|
|
58
58
|
};
|
|
59
|
-
function
|
|
60
|
-
const { from, to } =
|
|
59
|
+
function getDomRange(editor, range) {
|
|
60
|
+
const { from, to } = range;
|
|
61
61
|
const fromPos = editor.view.domAtPos(from);
|
|
62
62
|
const endPos = editor.view.domAtPos(to);
|
|
63
63
|
const domRange = document.createRange();
|
|
@@ -71,6 +71,87 @@ function compareSelections(a, b) {
|
|
|
71
71
|
}
|
|
72
72
|
return a.eq(b);
|
|
73
73
|
}
|
|
74
|
+
const DOCUMENT_TEXT_TRUNCATION = "[\u2026]";
|
|
75
|
+
const DOCUMENT_TEXT_BLOCK_SEPARATOR = " ";
|
|
76
|
+
function getDocumentText(editor, maxLength = 1e4) {
|
|
77
|
+
const { selection, doc } = editor.state;
|
|
78
|
+
const selectionLength = selection.to - selection.from;
|
|
79
|
+
if (maxLength >= doc.content.size) {
|
|
80
|
+
return {
|
|
81
|
+
beforeSelection: doc.textBetween(
|
|
82
|
+
0,
|
|
83
|
+
selection.from,
|
|
84
|
+
DOCUMENT_TEXT_BLOCK_SEPARATOR
|
|
85
|
+
),
|
|
86
|
+
selection: doc.textBetween(
|
|
87
|
+
selection.from,
|
|
88
|
+
selection.to,
|
|
89
|
+
DOCUMENT_TEXT_BLOCK_SEPARATOR
|
|
90
|
+
),
|
|
91
|
+
afterSelection: doc.textBetween(
|
|
92
|
+
selection.to,
|
|
93
|
+
doc.content.size,
|
|
94
|
+
DOCUMENT_TEXT_BLOCK_SEPARATOR
|
|
95
|
+
)
|
|
96
|
+
};
|
|
97
|
+
} else if (selectionLength > maxLength) {
|
|
98
|
+
const selectionStart = doc.textBetween(
|
|
99
|
+
selection.from,
|
|
100
|
+
selection.from + Math.floor(maxLength / 2) - DOCUMENT_TEXT_TRUNCATION.length,
|
|
101
|
+
DOCUMENT_TEXT_BLOCK_SEPARATOR
|
|
102
|
+
);
|
|
103
|
+
const selectionEnd = doc.textBetween(
|
|
104
|
+
selection.to - Math.floor(maxLength / 2) + DOCUMENT_TEXT_TRUNCATION.length,
|
|
105
|
+
selection.to,
|
|
106
|
+
DOCUMENT_TEXT_BLOCK_SEPARATOR
|
|
107
|
+
);
|
|
108
|
+
return {
|
|
109
|
+
beforeSelection: "",
|
|
110
|
+
selection: `${selectionStart}${DOCUMENT_TEXT_TRUNCATION}${selectionEnd}`,
|
|
111
|
+
afterSelection: ""
|
|
112
|
+
};
|
|
113
|
+
} else {
|
|
114
|
+
let beforeLength = Math.min(
|
|
115
|
+
selection.from,
|
|
116
|
+
Math.floor((maxLength - selectionLength) / 2)
|
|
117
|
+
);
|
|
118
|
+
const afterLength = Math.min(
|
|
119
|
+
doc.content.size - selection.to,
|
|
120
|
+
maxLength - selectionLength - beforeLength
|
|
121
|
+
);
|
|
122
|
+
if (beforeLength + afterLength + selectionLength < maxLength) {
|
|
123
|
+
beforeLength = Math.min(
|
|
124
|
+
selection.from,
|
|
125
|
+
maxLength - selectionLength - afterLength
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
let beforeSelection = doc.textBetween(
|
|
129
|
+
Math.max(0, selection.from - beforeLength),
|
|
130
|
+
selection.from,
|
|
131
|
+
DOCUMENT_TEXT_BLOCK_SEPARATOR
|
|
132
|
+
);
|
|
133
|
+
let afterSelection = doc.textBetween(
|
|
134
|
+
selection.to,
|
|
135
|
+
Math.min(doc.content.size, selection.to + afterLength),
|
|
136
|
+
DOCUMENT_TEXT_BLOCK_SEPARATOR
|
|
137
|
+
);
|
|
138
|
+
if (selection.from - beforeLength > 0) {
|
|
139
|
+
beforeSelection = `${DOCUMENT_TEXT_TRUNCATION}${beforeSelection}`;
|
|
140
|
+
}
|
|
141
|
+
if (selection.to + afterLength < doc.content.size) {
|
|
142
|
+
afterSelection = `${afterSelection}${DOCUMENT_TEXT_TRUNCATION}`;
|
|
143
|
+
}
|
|
144
|
+
return {
|
|
145
|
+
beforeSelection,
|
|
146
|
+
selection: doc.textBetween(
|
|
147
|
+
selection.from,
|
|
148
|
+
selection.to,
|
|
149
|
+
DOCUMENT_TEXT_BLOCK_SEPARATOR
|
|
150
|
+
),
|
|
151
|
+
afterSelection
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
}
|
|
74
155
|
|
|
75
|
-
export { compareSelections,
|
|
156
|
+
export { compareSelections, getDocumentText, getDomRange, getMentionsFromNode, getRangeFromRelativeSelections, getRectFromCoords, getRelativeSelectionFromState, mapFragment };
|
|
76
157
|
//# sourceMappingURL=utils.mjs.map
|
package/dist/utils.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.mjs","sources":["../src/utils.ts"],"sourcesContent":["import type { ClientRectObject } from \"@floating-ui/react-dom\";\nimport type { Editor, Range } from \"@tiptap/core\";\nimport type { Node as ProseMirrorNode } from \"@tiptap/pm/model\";\nimport { Fragment } from \"@tiptap/pm/model\";\nimport type { EditorState, Selection } from \"@tiptap/pm/state\";\nimport {\n getRelativeSelection,\n relativePositionToAbsolutePosition,\n ySyncPluginKey,\n} from \"y-prosemirror\";\nimport type { RelativePosition } from \"yjs\";\n\nimport type { YSyncPluginState } from \"./types\";\nimport { LIVEBLOCKS_MENTION_TYPE } from \"./types\";\n\nexport const getRelativeSelectionFromState = (state: EditorState) => {\n const pluginState = ySyncPluginKey.getState(state) as YSyncPluginState;\n if (!pluginState) return null;\n return getRelativeSelection(pluginState.binding, state);\n};\n\nexport const getRangeFromRelativeSelections = (\n pos: { anchor: RelativePosition; head: RelativePosition },\n state: EditorState\n) => {\n const pluginState = ySyncPluginKey.getState(state) as YSyncPluginState;\n if (!pluginState || !pluginState.binding) return { from: 0, to: 0 };\n const { doc, type, mapping } = pluginState.binding;\n const anchor =\n relativePositionToAbsolutePosition(doc, type, pos.anchor, mapping) ?? 0;\n const head =\n relativePositionToAbsolutePosition(doc, type, pos.head, mapping) ?? 0;\n\n const from = anchor > head ? head : anchor;\n const to = anchor > head ? anchor : head;\n return { from, to };\n};\n\nexport const getRectFromCoords = (coords: {\n top: number;\n left: number;\n right: number;\n bottom: number;\n}): ClientRectObject => {\n return {\n ...coords,\n x: coords.left,\n y: coords.top,\n width: coords.right - coords.left,\n height: coords.bottom - coords.top,\n };\n};\n\nexport const getMentionsFromNode = (\n node: ProseMirrorNode,\n range: Range\n): { notificationId: string; userId: string }[] => {\n const result: { notificationId: string; userId: string }[] = [];\n node.nodesBetween(range.from, range.to, (child) => {\n if (child.type.name === LIVEBLOCKS_MENTION_TYPE) {\n const mention = child.attrs as { id?: string; notificationId?: string };\n if (mention.id && mention.notificationId) {\n result.push({\n notificationId: mention.notificationId,\n userId: mention.id,\n });\n }\n }\n });\n return result;\n};\n\n// How to modify data in transformPasted, inspired by: https://discuss.prosemirror.net/t/modify-specific-node-on-copy-and-paste-in-clipboard/4901/4\nexport const mapFragment = (\n fragment: Fragment,\n callback: (\n node: ProseMirrorNode\n ) => ProseMirrorNode | ProseMirrorNode[] | Fragment | null\n): Fragment => {\n const content: ProseMirrorNode[] = [];\n fragment.forEach((node) => {\n if (node.content.childCount > 0) {\n content.push(\n node.type.create(node.attrs, mapFragment(node.content, callback))\n );\n return;\n }\n content.push(callback(node) as ProseMirrorNode);\n });\n\n return Fragment.from(content);\n};\n\nexport function getDomRangeFromSelection(\n selection: { from: number; to: number } | number,\n editor: Editor\n) {\n const { from, to } =\n typeof selection === \"number\"\n ? { from: selection, to: selection }\n : selection;\n const fromPos = editor.view.domAtPos(from);\n const endPos = editor.view.domAtPos(to);\n\n const domRange = document.createRange();\n domRange.setStart(fromPos.node, fromPos.offset);\n domRange.setEnd(endPos.node, endPos.offset);\n\n return domRange;\n}\n\nexport function compareSelections(\n a: Selection | null | undefined,\n b: Selection | null | undefined\n) {\n if (!a || !b) {\n return false;\n }\n\n return a.eq(b);\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"utils.mjs","sources":["../src/utils.ts"],"sourcesContent":["import type { ClientRectObject } from \"@floating-ui/react-dom\";\nimport type { Editor, Range } from \"@tiptap/core\";\nimport type { Node as ProseMirrorNode } from \"@tiptap/pm/model\";\nimport { Fragment } from \"@tiptap/pm/model\";\nimport type { EditorState, Selection } from \"@tiptap/pm/state\";\nimport {\n getRelativeSelection,\n relativePositionToAbsolutePosition,\n ySyncPluginKey,\n} from \"y-prosemirror\";\nimport type { RelativePosition } from \"yjs\";\n\nimport type { YSyncPluginState } from \"./types\";\nimport { LIVEBLOCKS_MENTION_TYPE } from \"./types\";\n\nexport const getRelativeSelectionFromState = (state: EditorState) => {\n const pluginState = ySyncPluginKey.getState(state) as YSyncPluginState;\n if (!pluginState) return null;\n return getRelativeSelection(pluginState.binding, state);\n};\n\nexport const getRangeFromRelativeSelections = (\n pos: { anchor: RelativePosition; head: RelativePosition },\n state: EditorState\n) => {\n const pluginState = ySyncPluginKey.getState(state) as YSyncPluginState;\n if (!pluginState || !pluginState.binding) return { from: 0, to: 0 };\n const { doc, type, mapping } = pluginState.binding;\n const anchor =\n relativePositionToAbsolutePosition(doc, type, pos.anchor, mapping) ?? 0;\n const head =\n relativePositionToAbsolutePosition(doc, type, pos.head, mapping) ?? 0;\n\n const from = anchor > head ? head : anchor;\n const to = anchor > head ? anchor : head;\n return { from, to };\n};\n\nexport const getRectFromCoords = (coords: {\n top: number;\n left: number;\n right: number;\n bottom: number;\n}): ClientRectObject => {\n return {\n ...coords,\n x: coords.left,\n y: coords.top,\n width: coords.right - coords.left,\n height: coords.bottom - coords.top,\n };\n};\n\nexport const getMentionsFromNode = (\n node: ProseMirrorNode,\n range: Range\n): { notificationId: string; userId: string }[] => {\n const result: { notificationId: string; userId: string }[] = [];\n node.nodesBetween(range.from, range.to, (child) => {\n if (child.type.name === LIVEBLOCKS_MENTION_TYPE) {\n const mention = child.attrs as { id?: string; notificationId?: string };\n if (mention.id && mention.notificationId) {\n result.push({\n notificationId: mention.notificationId,\n userId: mention.id,\n });\n }\n }\n });\n return result;\n};\n\n// How to modify data in transformPasted, inspired by: https://discuss.prosemirror.net/t/modify-specific-node-on-copy-and-paste-in-clipboard/4901/4\nexport const mapFragment = (\n fragment: Fragment,\n callback: (\n node: ProseMirrorNode\n ) => ProseMirrorNode | ProseMirrorNode[] | Fragment | null\n): Fragment => {\n const content: ProseMirrorNode[] = [];\n fragment.forEach((node) => {\n if (node.content.childCount > 0) {\n content.push(\n node.type.create(node.attrs, mapFragment(node.content, callback))\n );\n return;\n }\n content.push(callback(node) as ProseMirrorNode);\n });\n\n return Fragment.from(content);\n};\n\nexport function getDomRange(editor: Editor, range: Range) {\n const { from, to } = range;\n const fromPos = editor.view.domAtPos(from);\n const endPos = editor.view.domAtPos(to);\n\n const domRange = document.createRange();\n domRange.setStart(fromPos.node, fromPos.offset);\n domRange.setEnd(endPos.node, endPos.offset);\n\n return domRange;\n}\n\nexport function compareSelections(\n a: Selection | null | undefined,\n b: Selection | null | undefined\n) {\n if (!a || !b) {\n return false;\n }\n\n return a.eq(b);\n}\n\nexport type DocumentText = {\n beforeSelection: string;\n selection: string;\n afterSelection: string;\n};\n\nconst DOCUMENT_TEXT_TRUNCATION = \"[…]\";\nconst DOCUMENT_TEXT_BLOCK_SEPARATOR = \" \";\n\nexport function getDocumentText(\n editor: Editor,\n maxLength = 10_000\n): DocumentText {\n const { selection, doc } = editor.state;\n\n const selectionLength = selection.to - selection.from;\n\n if (maxLength >= doc.content.size) {\n // If the document is smaller than the maximum length, return the entire document\n return {\n beforeSelection: doc.textBetween(\n 0,\n selection.from,\n DOCUMENT_TEXT_BLOCK_SEPARATOR\n ),\n selection: doc.textBetween(\n selection.from,\n selection.to,\n DOCUMENT_TEXT_BLOCK_SEPARATOR\n ),\n afterSelection: doc.textBetween(\n selection.to,\n doc.content.size,\n DOCUMENT_TEXT_BLOCK_SEPARATOR\n ),\n };\n } else if (selectionLength > maxLength) {\n // If the selection is too large, truncate its middle to still allow continuations\n const selectionStart = doc.textBetween(\n selection.from,\n selection.from +\n Math.floor(maxLength / 2) -\n DOCUMENT_TEXT_TRUNCATION.length,\n DOCUMENT_TEXT_BLOCK_SEPARATOR\n );\n const selectionEnd = doc.textBetween(\n selection.to -\n Math.floor(maxLength / 2) +\n DOCUMENT_TEXT_TRUNCATION.length,\n selection.to,\n DOCUMENT_TEXT_BLOCK_SEPARATOR\n );\n\n return {\n beforeSelection: \"\",\n selection: `${selectionStart}${DOCUMENT_TEXT_TRUNCATION}${selectionEnd}`,\n afterSelection: \"\",\n };\n } else {\n // If the selection is smaller than (or equal to) the maximum length, extract as much as possible from the document around the selection\n\n // Start by taking as much as possible after the selection\n let beforeLength = Math.min(\n selection.from,\n Math.floor((maxLength - selectionLength) / 2)\n );\n const afterLength = Math.min(\n doc.content.size - selection.to,\n maxLength - selectionLength - beforeLength\n );\n\n // If needed (e.g. the selection is near the end), compensate before the selection\n if (beforeLength + afterLength + selectionLength < maxLength) {\n beforeLength = Math.min(\n selection.from,\n maxLength - selectionLength - afterLength\n );\n }\n\n let beforeSelection = doc.textBetween(\n Math.max(0, selection.from - beforeLength),\n selection.from,\n DOCUMENT_TEXT_BLOCK_SEPARATOR\n );\n let afterSelection = doc.textBetween(\n selection.to,\n Math.min(doc.content.size, selection.to + afterLength),\n DOCUMENT_TEXT_BLOCK_SEPARATOR\n );\n\n // Add leading truncation if `beforeSelection` doesn't contain the document's start\n if (selection.from - beforeLength > 0) {\n beforeSelection = `${DOCUMENT_TEXT_TRUNCATION}${beforeSelection}`;\n }\n\n // Add trailing truncation if `afterSelection` doesn't contain the document's end\n if (selection.to + afterLength < doc.content.size) {\n afterSelection = `${afterSelection}${DOCUMENT_TEXT_TRUNCATION}`;\n }\n\n return {\n beforeSelection,\n selection: doc.textBetween(\n selection.from,\n selection.to,\n DOCUMENT_TEXT_BLOCK_SEPARATOR\n ),\n afterSelection,\n };\n }\n}\n"],"names":[],"mappings":"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"}
|
package/dist/version.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const PKG_NAME = "@liveblocks/react-tiptap";
|
|
4
|
-
const PKG_VERSION = typeof "2.16.1-
|
|
4
|
+
const PKG_VERSION = typeof "2.16.1-ai3" === "string" && "2.16.1-ai3";
|
|
5
5
|
const PKG_FORMAT = typeof "cjs" === "string" && "cjs";
|
|
6
6
|
|
|
7
7
|
exports.PKG_FORMAT = PKG_FORMAT;
|
package/dist/version.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const PKG_NAME = "@liveblocks/react-tiptap";
|
|
2
|
-
const PKG_VERSION = typeof "2.16.1-
|
|
2
|
+
const PKG_VERSION = typeof "2.16.1-ai3" === "string" && "2.16.1-ai3";
|
|
3
3
|
const PKG_FORMAT = typeof "esm" === "string" && "esm";
|
|
4
4
|
|
|
5
5
|
export { PKG_FORMAT, PKG_NAME, PKG_VERSION };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@liveblocks/react-tiptap",
|
|
3
|
-
"version": "2.16.1-
|
|
3
|
+
"version": "2.16.1-ai3",
|
|
4
4
|
"description": "A tiptap react plugin to enable collaboration, comments, live cursors, and more.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -42,11 +42,11 @@
|
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@floating-ui/react-dom": "^2.1.2",
|
|
45
|
-
"@liveblocks/client": "2.16.1-
|
|
46
|
-
"@liveblocks/core": "2.16.1-
|
|
47
|
-
"@liveblocks/react": "2.16.1-
|
|
48
|
-
"@liveblocks/react-ui": "2.16.1-
|
|
49
|
-
"@liveblocks/yjs": "2.16.1-
|
|
45
|
+
"@liveblocks/client": "2.16.1-ai3",
|
|
46
|
+
"@liveblocks/core": "2.16.1-ai3",
|
|
47
|
+
"@liveblocks/react": "2.16.1-ai3",
|
|
48
|
+
"@liveblocks/react-ui": "2.16.1-ai3",
|
|
49
|
+
"@liveblocks/yjs": "2.16.1-ai3",
|
|
50
50
|
"@radix-ui/react-select": "^2.1.2",
|
|
51
51
|
"@radix-ui/react-toggle": "^1.1.0",
|
|
52
52
|
"@tiptap/core": "^2.7.2",
|
package/src/styles/index.css
CHANGED
|
@@ -276,8 +276,16 @@
|
|
|
276
276
|
}
|
|
277
277
|
|
|
278
278
|
.lb-tiptap-ai-toolbar-portal {
|
|
279
|
+
display: flex;
|
|
280
|
+
flex-direction: column;
|
|
281
|
+
gap: 8px;
|
|
279
282
|
inline-size: var(--lb-tiptap-editor-width);
|
|
280
283
|
outline: none;
|
|
284
|
+
pointer-events: none;
|
|
285
|
+
|
|
286
|
+
&:where([data-liveblocks-ai-toolbar-flip]) {
|
|
287
|
+
flex-direction: column-reverse;
|
|
288
|
+
}
|
|
281
289
|
}
|
|
282
290
|
|
|
283
291
|
.lb-tiptap-ai-toolbar-container {
|
|
@@ -294,38 +302,16 @@
|
|
|
294
302
|
display: flex;
|
|
295
303
|
flex-direction: column;
|
|
296
304
|
color: var(--lb-foreground);
|
|
305
|
+
pointer-events: auto;
|
|
297
306
|
}
|
|
298
307
|
|
|
299
|
-
.lb-tiptap-ai-toolbar-output-container
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
border-block-end: 1px solid var(--lb-foreground-subtle);
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
.lb-tiptap-ai-toolbar-output {
|
|
306
|
-
&::before {
|
|
307
|
-
content: "\FEFF";
|
|
308
|
-
display: inline-block;
|
|
309
|
-
vertical-align: middle;
|
|
310
|
-
user-select: none;
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
/* stylelint-disable-next-line selector-class-pattern */
|
|
314
|
-
:where(.collaboration-cursor__label) {
|
|
315
|
-
display: flex;
|
|
316
|
-
gap: 0.1875em;
|
|
317
|
-
align-items: center;
|
|
318
|
-
|
|
319
|
-
:where(.lb-icon-container) {
|
|
320
|
-
margin-inline-start: -0.125em;
|
|
308
|
+
.lb-tiptap-ai-toolbar-output-container,
|
|
309
|
+
.lb-tiptap-ai-toolbar-content {
|
|
310
|
+
max-block-size: calc(6lh + 2 * var(--lb-tiptap-ai-toolbar-padding));
|
|
321
311
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
block-size: 1em;
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
}
|
|
312
|
+
/* overflow-block: auto; doesn't work as expected */
|
|
313
|
+
/* stylelint-disable-next-line plugin/use-logical-properties-and-values */
|
|
314
|
+
overflow-y: auto;
|
|
329
315
|
}
|
|
330
316
|
|
|
331
317
|
.lb-tiptap-ai-toolbar-content {
|
|
@@ -333,30 +319,26 @@
|
|
|
333
319
|
grid-template-columns: auto 1fr auto;
|
|
334
320
|
inline-size: 100%;
|
|
335
321
|
min-inline-size: 0;
|
|
322
|
+
padding: var(--lb-tiptap-ai-toolbar-padding);
|
|
336
323
|
outline: none;
|
|
337
324
|
}
|
|
338
325
|
|
|
339
|
-
.lb-tiptap-ai-toolbar-output-container
|
|
340
|
-
|
|
341
|
-
max-block-size: calc(6lh + 2 * var(--lb-tiptap-ai-toolbar-padding));
|
|
342
|
-
padding: var(--lb-tiptap-ai-toolbar-padding);
|
|
326
|
+
.lb-tiptap-ai-toolbar-output-container {
|
|
327
|
+
--lb-line-height-crop: calc(1lh - 1em) / -2;
|
|
343
328
|
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
329
|
+
display: flex;
|
|
330
|
+
flex-direction: column;
|
|
331
|
+
padding: calc(var(--lb-spacing) + var(--lb-line-height-crop))
|
|
332
|
+
var(--lb-spacing);
|
|
333
|
+
border-block-end: 1px solid var(--lb-foreground-subtle);
|
|
347
334
|
}
|
|
348
335
|
|
|
349
|
-
.lb-tiptap-ai-toolbar-
|
|
350
|
-
position: relative;
|
|
351
|
-
z-index: auto;
|
|
352
|
-
display: grid;
|
|
353
|
-
margin-block: calc(-1 * var(--lb-tiptap-ai-toolbar-padding));
|
|
354
|
-
line-height: $lb-button-size;
|
|
355
|
-
|
|
336
|
+
.lb-tiptap-ai-toolbar-output {
|
|
356
337
|
&::before {
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
338
|
+
content: "\FEFF";
|
|
339
|
+
display: inline-block;
|
|
340
|
+
vertical-align: middle;
|
|
341
|
+
user-select: none;
|
|
360
342
|
}
|
|
361
343
|
}
|
|
362
344
|
|
|
@@ -394,6 +376,19 @@
|
|
|
394
376
|
}
|
|
395
377
|
}
|
|
396
378
|
|
|
379
|
+
.lb-tiptap-ai-toolbar-custom-prompt-container {
|
|
380
|
+
position: relative;
|
|
381
|
+
z-index: auto;
|
|
382
|
+
display: grid;
|
|
383
|
+
margin-block: calc(-1 * var(--lb-tiptap-ai-toolbar-padding));
|
|
384
|
+
|
|
385
|
+
&::before {
|
|
386
|
+
/* The space is important when handling new lines */
|
|
387
|
+
content: attr(data-value) " ";
|
|
388
|
+
visibility: hidden;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
397
392
|
.lb-tiptap-ai-toolbar-custom-prompt,
|
|
398
393
|
.lb-tiptap-ai-toolbar-custom-prompt-container::before {
|
|
399
394
|
/* Overlap the textarea and its value to auto-size it */
|
|
@@ -401,12 +396,42 @@
|
|
|
401
396
|
box-sizing: inherit;
|
|
402
397
|
inline-size: 100%;
|
|
403
398
|
min-inline-size: 0;
|
|
404
|
-
padding:
|
|
399
|
+
padding: calc(
|
|
400
|
+
var(--lb-tiptap-ai-toolbar-padding) + ($lb-button-size - 1lh) / 2
|
|
401
|
+
)
|
|
402
|
+
var(--lb-tiptap-ai-toolbar-padding);
|
|
405
403
|
font: inherit;
|
|
406
404
|
letter-spacing: inherit;
|
|
407
405
|
white-space: pre-wrap;
|
|
408
406
|
}
|
|
409
407
|
|
|
408
|
+
.lb-tiptap-ai-toolbar-error {
|
|
409
|
+
--lb-dynamic-background: var(--lb-background-destructive-subtle);
|
|
410
|
+
|
|
411
|
+
position: relative;
|
|
412
|
+
display: flex;
|
|
413
|
+
gap: calc(0.5 * var(--lb-spacing));
|
|
414
|
+
align-items: center;
|
|
415
|
+
padding: var(--lb-tiptap-ai-toolbar-padding);
|
|
416
|
+
background: var(--lb-dynamic-background);
|
|
417
|
+
color: var(--lb-destructive);
|
|
418
|
+
font-size: 0.875em;
|
|
419
|
+
text-wrap: balance;
|
|
420
|
+
|
|
421
|
+
&::after {
|
|
422
|
+
content: "";
|
|
423
|
+
position: absolute;
|
|
424
|
+
inset: 0;
|
|
425
|
+
border-block-start: 1px solid var(--lb-destructive-moderate);
|
|
426
|
+
opacity: 0.35;
|
|
427
|
+
pointer-events: none;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
:where(.lb-icon-container) {
|
|
431
|
+
color: var(--lb-destructive-secondary);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
410
435
|
.lb-tiptap-ai-toolbar-halo {
|
|
411
436
|
--lb-tiptap-ai-toolbar-halo-blur: 16px;
|
|
412
437
|
--lb-tiptap-ai-toolbar-halo-outset: 8px;
|
|
@@ -422,6 +447,8 @@
|
|
|
422
447
|
pointer-events: none;
|
|
423
448
|
transition-duration: 1s;
|
|
424
449
|
transition-property: opacity;
|
|
450
|
+
animation: lb-animation-ai-toolbar-halo-scale-in 1s
|
|
451
|
+
cubic-bezier(0.165, 0.84, 0.44, 1) both;
|
|
425
452
|
|
|
426
453
|
&:where(:not([data-active])) {
|
|
427
454
|
opacity: 0.5;
|
|
@@ -440,7 +467,7 @@
|
|
|
440
467
|
content: "";
|
|
441
468
|
position: absolute;
|
|
442
469
|
inset: 0;
|
|
443
|
-
opacity: 0.
|
|
470
|
+
opacity: 0.175;
|
|
444
471
|
animation-timing-function: cubic-bezier(0.455, 0.03, 0.515, 0.955);
|
|
445
472
|
animation-iteration-count: infinite;
|
|
446
473
|
}
|
|
@@ -474,8 +501,7 @@
|
|
|
474
501
|
transparent 80%
|
|
475
502
|
);
|
|
476
503
|
background-position: top left;
|
|
477
|
-
background-size:
|
|
478
|
-
background-repeat: space;
|
|
504
|
+
background-size: 75% 100%;
|
|
479
505
|
animation-name: lb-animation-ai-toolbar-halo-horizontal;
|
|
480
506
|
animation-duration: 6s;
|
|
481
507
|
animation-delay: -2s;
|
|
@@ -484,8 +510,6 @@
|
|
|
484
510
|
}
|
|
485
511
|
|
|
486
512
|
.lb-tiptap-ai-toolbar-halo-vertical {
|
|
487
|
-
opacity: 0;
|
|
488
|
-
|
|
489
513
|
&::before {
|
|
490
514
|
inset-block-start: -50%;
|
|
491
515
|
inline-size: 100%;
|
|
@@ -526,20 +550,20 @@
|
|
|
526
550
|
}
|
|
527
551
|
|
|
528
552
|
.lb-tiptap-ai-toolbar-thinking {
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
align-
|
|
553
|
+
@include truncate;
|
|
554
|
+
|
|
555
|
+
align-self: center;
|
|
532
556
|
min-inline-size: 0;
|
|
557
|
+
max-inline-size: fit-content;
|
|
533
558
|
padding-inline: var(--lb-tiptap-ai-toolbar-padding);
|
|
534
|
-
color: var(--lb-foreground-
|
|
535
|
-
cursor: wait;
|
|
559
|
+
color: var(--lb-foreground-tertiary);
|
|
536
560
|
user-select: none;
|
|
537
|
-
animation: lb-animation-shimmer 8s linear infinite;
|
|
561
|
+
animation: lb-animation-ai-toolbar-shimmer 8s linear infinite;
|
|
538
562
|
}
|
|
539
563
|
|
|
540
564
|
.lb-tiptap-ai-toolbar-dropdown {
|
|
541
565
|
inline-size: min(250px, 100%);
|
|
542
|
-
|
|
566
|
+
pointer-events: auto;
|
|
543
567
|
}
|
|
544
568
|
|
|
545
569
|
/*************************************
|
|
@@ -600,6 +624,38 @@
|
|
|
600
624
|
* Animations *
|
|
601
625
|
*************************************/
|
|
602
626
|
|
|
627
|
+
@keyframes lb-animation-ai-toolbar-shimmer {
|
|
628
|
+
from,
|
|
629
|
+
to {
|
|
630
|
+
mask-image: linear-gradient(
|
|
631
|
+
90deg,
|
|
632
|
+
#000 8%,
|
|
633
|
+
rgb(0 0 0 / 50%) 20%,
|
|
634
|
+
rgb(0 0 0 / 50%) 80%,
|
|
635
|
+
#000 92%
|
|
636
|
+
);
|
|
637
|
+
mask-size: 400% 100%;
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
from {
|
|
641
|
+
mask-position: 200% 0;
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
to {
|
|
645
|
+
mask-position: -200% 0;
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
@keyframes lb-animation-ai-toolbar-halo-scale-in {
|
|
650
|
+
from {
|
|
651
|
+
transform: scale(0.5);
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
to {
|
|
655
|
+
transform: scale(1);
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
|
|
603
659
|
@keyframes lb-animation-ai-toolbar-halo-horizontal {
|
|
604
660
|
from {
|
|
605
661
|
transform: translateX(-50%);
|