@longline/aqua-ui 1.0.197 → 1.0.199
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/hooks/useAssemblyAIRecorder/SpeechManager.d.ts +12 -0
- package/hooks/useAssemblyAIRecorder/SpeechManager.js +26 -0
- package/hooks/useAssemblyAIRecorder/useAssemblyAIRecorder.d.ts +4 -0
- package/hooks/useAssemblyAIRecorder/useAssemblyAIRecorder.js +13 -2
- package/hooks/useOpenAIStream/useOpenAIStream.js +19 -13
- package/inputs/Editor/Editor.d.ts +5 -1
- package/inputs/Editor/Editor.js +6 -6
- package/inputs/Editor/menu/MenuBar.d.ts +9 -1
- package/inputs/Editor/menu/MenuBar.js +6 -5
- package/inputs/Editor/menu/MenuSeparator.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
type StopFn = () => void;
|
|
2
|
+
/**
|
|
3
|
+
* Global SpeechManager module that:
|
|
4
|
+
* - Maintains a reference to the currently active transcription session
|
|
5
|
+
* - Automatically stops any existing session before starting a new one
|
|
6
|
+
*/
|
|
7
|
+
declare class SpeechManager {
|
|
8
|
+
private static currentStopFn;
|
|
9
|
+
static startNewSession(stopFn: StopFn): void;
|
|
10
|
+
static stopCurrentSession(): void;
|
|
11
|
+
}
|
|
12
|
+
export { SpeechManager };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global SpeechManager module that:
|
|
3
|
+
* - Maintains a reference to the currently active transcription session
|
|
4
|
+
* - Automatically stops any existing session before starting a new one
|
|
5
|
+
*/
|
|
6
|
+
var SpeechManager = /** @class */ (function () {
|
|
7
|
+
function SpeechManager() {
|
|
8
|
+
}
|
|
9
|
+
SpeechManager.startNewSession = function (stopFn) {
|
|
10
|
+
// Stop previous session, if any
|
|
11
|
+
if (this.currentStopFn) {
|
|
12
|
+
this.currentStopFn();
|
|
13
|
+
}
|
|
14
|
+
// Register new session
|
|
15
|
+
this.currentStopFn = stopFn;
|
|
16
|
+
};
|
|
17
|
+
SpeechManager.stopCurrentSession = function () {
|
|
18
|
+
if (this.currentStopFn) {
|
|
19
|
+
this.currentStopFn();
|
|
20
|
+
this.currentStopFn = null;
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
SpeechManager.currentStopFn = null;
|
|
24
|
+
return SpeechManager;
|
|
25
|
+
}());
|
|
26
|
+
export { SpeechManager };
|
|
@@ -15,6 +15,10 @@ type TRecordingStatus = 'idle' | 'connecting' | 'recording';
|
|
|
15
15
|
* @returns An object containing:
|
|
16
16
|
* - recordingStatus: 'idle' | 'connecting' | 'recording'
|
|
17
17
|
* - toggleRecording: function to start or stop recording
|
|
18
|
+
*
|
|
19
|
+
* The `SpeechManager` singleton is use to keep track of which
|
|
20
|
+
* AssemblyAIRecorder is currently recording; when a new recording is started,
|
|
21
|
+
* the current one is stopped.
|
|
18
22
|
*/
|
|
19
23
|
declare const useAssemblyAIRecorder: (url: string, onTranscript: TranscriptCallback) => {
|
|
20
24
|
recordingStatus: TRecordingStatus;
|
|
@@ -35,6 +35,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
35
35
|
}
|
|
36
36
|
};
|
|
37
37
|
import { useRef, useState, useEffect, useCallback } from 'react';
|
|
38
|
+
import { SpeechManager } from './SpeechManager';
|
|
38
39
|
//
|
|
39
40
|
// The audio processing needs a worklet that runs in a separate thread.
|
|
40
41
|
// Ordinarily such a worklet would have to reside in a separate JavaScript
|
|
@@ -59,6 +60,10 @@ var moduleScript = /* js */ "\nconst MAX_16BIT_INT = 32767\nclass AudioProcessor
|
|
|
59
60
|
* @returns An object containing:
|
|
60
61
|
* - recordingStatus: 'idle' | 'connecting' | 'recording'
|
|
61
62
|
* - toggleRecording: function to start or stop recording
|
|
63
|
+
*
|
|
64
|
+
* The `SpeechManager` singleton is use to keep track of which
|
|
65
|
+
* AssemblyAIRecorder is currently recording; when a new recording is started,
|
|
66
|
+
* the current one is stopped.
|
|
62
67
|
*/
|
|
63
68
|
var useAssemblyAIRecorder = function (url, onTranscript) {
|
|
64
69
|
// State to track the current recording status
|
|
@@ -213,13 +218,19 @@ var useAssemblyAIRecorder = function (url, onTranscript) {
|
|
|
213
218
|
cleanup();
|
|
214
219
|
return [2 /*return*/];
|
|
215
220
|
}
|
|
221
|
+
// Turn off any other speech recording through the SpeechManager singleton.
|
|
222
|
+
// Register this stream as the current one.
|
|
223
|
+
console.log("START SESSION");
|
|
224
|
+
SpeechManager.startNewSession(function () {
|
|
225
|
+
cleanup();
|
|
226
|
+
});
|
|
216
227
|
// Update state to show we are connecting
|
|
217
228
|
setRecordingStatus('connecting');
|
|
218
229
|
return [4 /*yield*/, fetchToken()];
|
|
219
230
|
case 1:
|
|
220
231
|
token = _a.sent();
|
|
221
232
|
if (!token) {
|
|
222
|
-
|
|
233
|
+
console.error('Failed to get temp token');
|
|
223
234
|
setRecordingStatus('idle');
|
|
224
235
|
return [2 /*return*/];
|
|
225
236
|
}
|
|
@@ -272,7 +283,7 @@ var useAssemblyAIRecorder = function (url, onTranscript) {
|
|
|
272
283
|
*/
|
|
273
284
|
useEffect(function () {
|
|
274
285
|
return function () {
|
|
275
|
-
|
|
286
|
+
SpeechManager.stopCurrentSession();
|
|
276
287
|
};
|
|
277
288
|
}, []);
|
|
278
289
|
return {
|
|
@@ -51,6 +51,11 @@ import { useCallback, useRef } from 'react';
|
|
|
51
51
|
*/
|
|
52
52
|
var useOpenAIStream = function (url) {
|
|
53
53
|
var abortRef = useRef(null);
|
|
54
|
+
// Get CSRF token, if any, from cookie:
|
|
55
|
+
var getCsrfTokenFromCookie = function () {
|
|
56
|
+
var match = document.cookie.match(/XSRF-TOKEN=([^;]+)/);
|
|
57
|
+
return match ? decodeURIComponent(match[1]) : null;
|
|
58
|
+
};
|
|
54
59
|
/**
|
|
55
60
|
* Streams a prompt to a backend AI endpoint and handles streamed chunks.
|
|
56
61
|
*
|
|
@@ -64,10 +69,10 @@ var useOpenAIStream = function (url) {
|
|
|
64
69
|
}
|
|
65
70
|
return __awaiter(void 0, __spreadArray([prompt_1, onText_1], args_1, true), void 0, function (prompt, onText, options) {
|
|
66
71
|
var controller, response, reader, decoder, buffer, isDone, _a, done, value, parts, _b, parts_1, part, jsonStr, data, content, err_1;
|
|
67
|
-
var _c, _d, _e;
|
|
72
|
+
var _c, _d, _e, _f;
|
|
68
73
|
if (options === void 0) { options = { temperature: 0, top_p: 0 }; }
|
|
69
|
-
return __generator(this, function (
|
|
70
|
-
switch (
|
|
74
|
+
return __generator(this, function (_g) {
|
|
75
|
+
switch (_g.label) {
|
|
71
76
|
case 0:
|
|
72
77
|
controller = new AbortController();
|
|
73
78
|
abortRef.current = controller;
|
|
@@ -75,6 +80,7 @@ var useOpenAIStream = function (url) {
|
|
|
75
80
|
method: 'POST',
|
|
76
81
|
headers: {
|
|
77
82
|
'Content-Type': 'application/json',
|
|
83
|
+
'X-CSRF-TOKEN': (_c = getCsrfTokenFromCookie()) !== null && _c !== void 0 ? _c : '',
|
|
78
84
|
'Accept': 'text/event-stream',
|
|
79
85
|
'Connection': 'keep-alive',
|
|
80
86
|
'Cache-Control': 'no-cache, no-transform'
|
|
@@ -87,7 +93,7 @@ var useOpenAIStream = function (url) {
|
|
|
87
93
|
signal: controller.signal
|
|
88
94
|
})];
|
|
89
95
|
case 1:
|
|
90
|
-
response =
|
|
96
|
+
response = _g.sent();
|
|
91
97
|
if (!response.ok) {
|
|
92
98
|
console.error("OpenAI stream request failed: ".concat(response.statusText));
|
|
93
99
|
return [2 /*return*/];
|
|
@@ -100,19 +106,19 @@ var useOpenAIStream = function (url) {
|
|
|
100
106
|
decoder = new TextDecoder('utf-8');
|
|
101
107
|
buffer = '';
|
|
102
108
|
isDone = false;
|
|
103
|
-
|
|
109
|
+
_g.label = 2;
|
|
104
110
|
case 2:
|
|
105
111
|
if (!!isDone) return [3 /*break*/, 11];
|
|
106
112
|
return [4 /*yield*/, reader.read()];
|
|
107
113
|
case 3:
|
|
108
|
-
_a =
|
|
114
|
+
_a = _g.sent(), done = _a.done, value = _a.value;
|
|
109
115
|
if (done)
|
|
110
116
|
return [3 /*break*/, 11];
|
|
111
117
|
buffer += decoder.decode(value, { stream: true });
|
|
112
118
|
parts = buffer.split('\n\n');
|
|
113
119
|
buffer = parts.pop(); // Keep partial data for next chunk
|
|
114
120
|
_b = 0, parts_1 = parts;
|
|
115
|
-
|
|
121
|
+
_g.label = 4;
|
|
116
122
|
case 4:
|
|
117
123
|
if (!(_b < parts_1.length)) return [3 /*break*/, 10];
|
|
118
124
|
part = parts_1[_b];
|
|
@@ -122,19 +128,19 @@ var useOpenAIStream = function (url) {
|
|
|
122
128
|
isDone = true;
|
|
123
129
|
return [3 /*break*/, 10];
|
|
124
130
|
}
|
|
125
|
-
|
|
131
|
+
_g.label = 5;
|
|
126
132
|
case 5:
|
|
127
|
-
|
|
133
|
+
_g.trys.push([5, 8, , 9]);
|
|
128
134
|
data = JSON.parse(jsonStr);
|
|
129
|
-
content = (
|
|
135
|
+
content = (_f = (_e = (_d = data.choices) === null || _d === void 0 ? void 0 : _d[0]) === null || _e === void 0 ? void 0 : _e.delta) === null || _f === void 0 ? void 0 : _f.content;
|
|
130
136
|
if (!content) return [3 /*break*/, 7];
|
|
131
137
|
return [4 /*yield*/, onText(content)];
|
|
132
138
|
case 6:
|
|
133
|
-
|
|
134
|
-
|
|
139
|
+
_g.sent();
|
|
140
|
+
_g.label = 7;
|
|
135
141
|
case 7: return [3 /*break*/, 9];
|
|
136
142
|
case 8:
|
|
137
|
-
err_1 =
|
|
143
|
+
err_1 = _g.sent();
|
|
138
144
|
console.error('Failed to parse chunk:', jsonStr);
|
|
139
145
|
return [3 /*break*/, 9];
|
|
140
146
|
case 9:
|
|
@@ -44,6 +44,10 @@ interface IEditorProps {
|
|
|
44
44
|
* If set, allow fullscreen mode (adding a toolbar button).
|
|
45
45
|
*/
|
|
46
46
|
allowFullscreen?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* If set, adds code and code block buttons to menu bar.
|
|
49
|
+
*/
|
|
50
|
+
codeButtons?: boolean;
|
|
47
51
|
/**
|
|
48
52
|
* URL for OpenAI requests.
|
|
49
53
|
* If not present, no OpenAI controls will be available.
|
|
@@ -60,7 +64,7 @@ interface IEditorProps {
|
|
|
60
64
|
onChange?: (value: any) => void;
|
|
61
65
|
}
|
|
62
66
|
declare const Editor: {
|
|
63
|
-
({ fluid, error, disabled, transparent, ghost, allowFullscreen, ...props }: IEditorProps): React.JSX.Element;
|
|
67
|
+
({ fluid, error, disabled, transparent, ghost, allowFullscreen, codeButtons, ...props }: IEditorProps): React.JSX.Element;
|
|
64
68
|
displayName: string;
|
|
65
69
|
};
|
|
66
70
|
export { Editor, IEditorProps };
|
package/inputs/Editor/Editor.js
CHANGED
|
@@ -83,18 +83,18 @@ var EditorBase = function (props) {
|
|
|
83
83
|
}; }, []);
|
|
84
84
|
return (React.createElement(InputWrapper, { fluid: props.fluid, ghost: props.ghost, error: props.error, disabled: props.disabled, transparent: props.transparent, flex: props.flex },
|
|
85
85
|
React.createElement("div", { className: props.className, ref: wrapperRef },
|
|
86
|
-
!props.disabled && !props.ghost &&
|
|
87
|
-
React.createElement(MenuBar, { allowFullscreen: props.allowFullscreen, fullscreen: fullscreen, editor: editor, onToggleFullscreen: handleToggleFullscreen, openAIurl: props.openAIurl, assemblyAIurl: props.assemblyAIurl }),
|
|
88
86
|
React.createElement(Wrapper, { className: fullscreen ? 'fullscreen' : '' },
|
|
87
|
+
!props.disabled && !props.ghost &&
|
|
88
|
+
React.createElement(MenuBar, { allowFullscreen: props.allowFullscreen, codeButtons: props.codeButtons, fullscreen: fullscreen, editor: editor, onToggleFullscreen: handleToggleFullscreen, openAIurl: props.openAIurl, assemblyAIurl: props.assemblyAIurl }),
|
|
89
89
|
React.createElement(EditorContent, { editor: editor, ref: setRef })))));
|
|
90
90
|
};
|
|
91
91
|
var pulse = keyframes(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n from {\n opacity: .15;\n }\n to {\n opacity: 1;\n }\n"], ["\n from {\n opacity: .15;\n }\n to {\n opacity: 1;\n }\n"])));
|
|
92
92
|
var Wrapper = styled.div(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n position: absolute;\n left: 0;\n top: 0;\n right: 0;\n bottom: 0;\n overflow-y: scroll;\n\n &.fullscreen {\n padding: 32px 32px 32px 32px;\n }\n\n .tiptap {\n border: none;\n outline: none;\n // Define colors for placeholder text.\n ::placeholder {\n color: rgb(from ", " r g b / 50%);\n opacity: 1 !important; /* Firefox applies opacity */\n }\n // Define colors for selected text.\n ::selection {\n background-color: ", ";\n color: ", ";\n } \n }\n\n // Content styles:\n .tiptap {\n code {\n background-color: ", ";\n color: ", ";\n outline: solid 1px ", ";\n border-radius: 4px;\n padding: 0 4px 0px 4px;\n }\n\n pre {\n background-color: ", ";\n border-radius: 4px;\n color: ", ";\n outline: solid 1px ", ";\n padding: 8px 12px 8px 12px;\n code {\n background-color: transparent;\n outline: none;\n border-radius: none;\n padding: 0 0 0 0;\n }\n }\n\n // The 'mark' is used to show a small animated circle inside the last\n // element being rendered from AI input.\n mark {\n display: inline-block;\n width: 10px;\n height: 10px;\n border-radius: 50%;\n color: transparent;\n background-color: ", ";\n animation: ", " 1s infinite alternate ease-in-out;\n vertical-align: middle;\n margin-left: 4px;\n margin-right: 4px;\n }\n }\n"], ["\n position: absolute;\n left: 0;\n top: 0;\n right: 0;\n bottom: 0;\n overflow-y: scroll;\n\n &.fullscreen {\n padding: 32px 32px 32px 32px;\n }\n\n .tiptap {\n border: none;\n outline: none;\n // Define colors for placeholder text.\n ::placeholder {\n color: rgb(from ", " r g b / 50%);\n opacity: 1 !important; /* Firefox applies opacity */\n }\n // Define colors for selected text.\n ::selection {\n background-color: ", ";\n color: ", ";\n } \n }\n\n // Content styles:\n .tiptap {\n code {\n background-color: ", ";\n color: ", ";\n outline: solid 1px ", ";\n border-radius: 4px;\n padding: 0 4px 0px 4px;\n }\n\n pre {\n background-color: ", ";\n border-radius: 4px;\n color: ", ";\n outline: solid 1px ", ";\n padding: 8px 12px 8px 12px;\n code {\n background-color: transparent;\n outline: none;\n border-radius: none;\n padding: 0 0 0 0;\n }\n }\n\n // The 'mark' is used to show a small animated circle inside the last\n // element being rendered from AI input.\n mark {\n display: inline-block;\n width: 10px;\n height: 10px;\n border-radius: 50%;\n color: transparent;\n background-color: ", ";\n animation: ", " 1s infinite alternate ease-in-out;\n vertical-align: middle;\n margin-left: 4px;\n margin-right: 4px;\n }\n }\n"])), function (p) { return p.theme.colors.primary[3]; }, function (p) { return p.theme.colors.primary[2]; }, function (p) { return p.theme.colors.neutral[100]; }, function (p) { return p.theme.colors.primary[3]; }, function (p) { return p.theme.colors.neutral[100]; }, function (p) { return p.theme.colors.primary[1]; }, function (p) { return p.theme.colors.primary[3]; }, function (p) { return p.theme.colors.neutral[100]; }, function (p) { return p.theme.colors.primary[1]; }, function (p) { return p.theme.colors.primary[1]; }, pulse);
|
|
93
|
-
var EditorStyled = styled(EditorBase)(
|
|
93
|
+
var EditorStyled = styled(EditorBase)(templateObject_4 || (templateObject_4 = __makeTemplateObject(["\n position: relative;\n box-sizing: border-box;\n width: 100%;\n background-color: ", ";\n\n // Editor has a fixed height, unless it flexes; then it will fill its \n // container vertically.\n height: 120px;\n ", "\n"], ["\n position: relative;\n box-sizing: border-box;\n width: 100%;\n background-color: ", ";\n\n // Editor has a fixed height, unless it flexes; then it will fill its \n // container vertically.\n height: 120px;\n ", "\n"])), function (p) { return p.theme.colors.neutral[100]; }, function (p) { return p.flex && css(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n height: 100%; \n "], ["\n height: 100%; \n "]))); });
|
|
94
94
|
var Editor = function (_a) {
|
|
95
|
-
var _b = _a.fluid, fluid = _b === void 0 ? false : _b, _c = _a.error, error = _c === void 0 ? false : _c, _d = _a.disabled, disabled = _d === void 0 ? false : _d, _e = _a.transparent, transparent = _e === void 0 ? false : _e, _f = _a.ghost, ghost = _f === void 0 ? false : _f, _g = _a.allowFullscreen, allowFullscreen = _g === void 0 ? false : _g, props = __rest(_a, ["fluid", "error", "disabled", "transparent", "ghost", "allowFullscreen"]);
|
|
96
|
-
return React.createElement(EditorStyled, __assign({ fluid: fluid, error: error, disabled: disabled, transparent: transparent, ghost: ghost, allowFullscreen: allowFullscreen }, props));
|
|
95
|
+
var _b = _a.fluid, fluid = _b === void 0 ? false : _b, _c = _a.error, error = _c === void 0 ? false : _c, _d = _a.disabled, disabled = _d === void 0 ? false : _d, _e = _a.transparent, transparent = _e === void 0 ? false : _e, _f = _a.ghost, ghost = _f === void 0 ? false : _f, _g = _a.allowFullscreen, allowFullscreen = _g === void 0 ? false : _g, _h = _a.codeButtons, codeButtons = _h === void 0 ? false : _h, props = __rest(_a, ["fluid", "error", "disabled", "transparent", "ghost", "allowFullscreen", "codeButtons"]);
|
|
96
|
+
return React.createElement(EditorStyled, __assign({ fluid: fluid, error: error, disabled: disabled, transparent: transparent, ghost: ghost, allowFullscreen: allowFullscreen, codeButtons: codeButtons }, props));
|
|
97
97
|
};
|
|
98
98
|
Editor.displayName = 'Editor';
|
|
99
99
|
export { Editor };
|
|
100
|
-
var templateObject_1, templateObject_2, templateObject_3, templateObject_4
|
|
100
|
+
var templateObject_1, templateObject_2, templateObject_3, templateObject_4;
|
|
@@ -12,10 +12,18 @@ interface IProps {
|
|
|
12
12
|
/** Is editor currently fullscreen? This will affect toolbar positioning. */
|
|
13
13
|
fullscreen?: boolean;
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
15
|
+
* If set, adds code and code block buttons to MenuBar.
|
|
16
|
+
*/
|
|
17
|
+
codeButtons?: boolean;
|
|
18
|
+
/**
|
|
19
|
+
* URL for OpenAI requests.
|
|
16
20
|
* If not present, no AI controls will be available.
|
|
17
21
|
*/
|
|
18
22
|
openAIurl?: string;
|
|
23
|
+
/**
|
|
24
|
+
* URL for AssemblyAI requests.
|
|
25
|
+
* If not present, no AI controls will be available.
|
|
26
|
+
*/
|
|
19
27
|
assemblyAIurl?: string;
|
|
20
28
|
/** Fired when fullscreen mode must be toggled. */
|
|
21
29
|
onToggleFullscreen: () => void;
|
|
@@ -27,9 +27,10 @@ var MenuBarBase = function (props) {
|
|
|
27
27
|
React.createElement(MenuSeparator, null),
|
|
28
28
|
React.createElement(OrderedListButton, { editor: props.editor }),
|
|
29
29
|
React.createElement(BulletListButton, { editor: props.editor }),
|
|
30
|
-
React.createElement(
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
props.codeButtons && React.createElement(React.Fragment, null,
|
|
31
|
+
React.createElement(MenuSeparator, null),
|
|
32
|
+
React.createElement(CodeButton, { editor: props.editor }),
|
|
33
|
+
React.createElement(CodeBlockButton, { editor: props.editor })),
|
|
33
34
|
(props.openAIurl || props.allowFullscreen) && React.createElement(MenuSeparator, null),
|
|
34
35
|
props.openAIurl &&
|
|
35
36
|
React.createElement(OpenAIButton, { url: props.openAIurl, editor: props.editor }),
|
|
@@ -38,7 +39,7 @@ var MenuBarBase = function (props) {
|
|
|
38
39
|
props.allowFullscreen &&
|
|
39
40
|
React.createElement(FullscreenButton, { fullscreen: props.fullscreen, editor: props.editor, onClick: props.onToggleFullscreen }))));
|
|
40
41
|
};
|
|
41
|
-
var MenuBar = styled(MenuBarBase)(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n // Keep MenuBar at top of editor; it must not scroll when the editor\n // content scrolls.\n position:
|
|
42
|
-
var Buttons = styled.div(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n border-radius: 4px;\n padding: 2px;\n\n // Flex-align buttons and separators:\n display: flex;\n flex-direction: row;\n gap: 4px;\n"], ["\n border-radius: 4px;\n padding: 2px;\n\n // Flex-align buttons and separators:\n display: flex;\n flex-direction: row;\n gap: 4px;\n"])));
|
|
42
|
+
var MenuBar = styled(MenuBarBase)(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n // Keep MenuBar at top of editor; it must not scroll when the editor\n // content scrolls.\n position: sticky;\n left: ", "px;\n top: ", "px;\n z-index: 1;\n background-color: ", ";\n border-bottom: solid 1px ", ";\n"], ["\n // Keep MenuBar at top of editor; it must not scroll when the editor\n // content scrolls.\n position: sticky;\n left: ", "px;\n top: ", "px;\n z-index: 1;\n background-color: ", ";\n border-bottom: solid 1px ", ";\n"])), function (p) { return p.fullscreen ? 32 : 0; }, function (p) { return p.fullscreen ? 32 : 0; }, function (p) { return p.theme.colors.neutral[100]; }, function (p) { return p.theme.colors.neutral[80]; });
|
|
43
|
+
var Buttons = styled.div(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n border-radius: 4px;\n padding: 2px;\n\n // Flex-align buttons and separators:\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n gap: 4px;\n"], ["\n border-radius: 4px;\n padding: 2px;\n\n // Flex-align buttons and separators:\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n gap: 4px;\n"])));
|
|
43
44
|
export { MenuBar };
|
|
44
45
|
var templateObject_1, templateObject_2;
|
|
@@ -18,7 +18,7 @@ import styled from 'styled-components';
|
|
|
18
18
|
var MenuSeparatorBase = function (props) {
|
|
19
19
|
return React.createElement("div", { className: props.className });
|
|
20
20
|
};
|
|
21
|
-
var MenuSeparatorStyled = styled(MenuSeparatorBase)(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n position: relative;\n width: 1px;\n margin-left: 2px;\n margin-right: 2px; \n &:before {\n content: '';\n position: absolute;\n top:
|
|
21
|
+
var MenuSeparatorStyled = styled(MenuSeparatorBase)(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n position: relative;\n width: 1px;\n margin-left: 2px;\n margin-right: 2px; \n &:before {\n content: '';\n position: absolute;\n top: 4px;\n left: 0;\n bottom: 4px;\n border-left: solid 1px ", ";\n }\n"], ["\n position: relative;\n width: 1px;\n margin-left: 2px;\n margin-right: 2px; \n &:before {\n content: '';\n position: absolute;\n top: 4px;\n left: 0;\n bottom: 4px;\n border-left: solid 1px ", ";\n }\n"])), function (p) { return p.theme.colors.neutral[80]; });
|
|
22
22
|
var MenuSeparator = function (props) { return React.createElement(MenuSeparatorStyled, __assign({}, props)); };
|
|
23
23
|
export { MenuSeparator };
|
|
24
24
|
var templateObject_1;
|