@june-ai/june-ui 0.2.9 → 0.2.11
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 +1 -0
- package/dist/{chunk-JSRO5CRO.js → chunk-2TBT4VRQ.js} +366 -67
- package/dist/{chunk-GFCROSGQ.cjs → chunk-TD6GKOUR.cjs} +456 -157
- package/dist/entry-core.cjs +10 -2
- package/dist/entry-core.d.cts +44 -3
- package/dist/entry-core.d.ts +44 -3
- package/dist/entry-core.js +9 -1
- package/dist/index.cjs +15 -7
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +9 -1
- package/dist/june.css +52 -0
- package/package.json +1 -1
|
@@ -141,7 +141,7 @@ function OpenUIDevtoolsGate() {
|
|
|
141
141
|
|
|
142
142
|
// src/engine/renderer/june-renderer.tsx
|
|
143
143
|
import { Renderer } from "@openuidev/react-lang";
|
|
144
|
-
import { Fragment, useCallback as useCallback2, useMemo as
|
|
144
|
+
import { Fragment, useCallback as useCallback2, useMemo as useMemo4, useRef as useRef2 } from "react";
|
|
145
145
|
|
|
146
146
|
// src/core/context.ts
|
|
147
147
|
import { createContext as createContext2, useContext as useContext2 } from "react";
|
|
@@ -224,9 +224,16 @@ function createActionHandler(options) {
|
|
|
224
224
|
};
|
|
225
225
|
}
|
|
226
226
|
|
|
227
|
+
// src/features/document-editor/document-bridge.tsx
|
|
228
|
+
import { useMemo as useMemo2 } from "react";
|
|
229
|
+
|
|
227
230
|
// src/features/document-editor/document-context.ts
|
|
228
231
|
import { createContext as createContext3, useContext as useContext3, useSyncExternalStore } from "react";
|
|
229
232
|
var JuneDocumentContext = createContext3({});
|
|
233
|
+
var DocumentEditorConfigContext = createContext3({});
|
|
234
|
+
function useDocumentEditorConfig() {
|
|
235
|
+
return useContext3(DocumentEditorConfigContext);
|
|
236
|
+
}
|
|
230
237
|
function useDocumentOptions() {
|
|
231
238
|
return useContext3(JuneDocumentContext);
|
|
232
239
|
}
|
|
@@ -608,13 +615,20 @@ function useDocumentBridge(options) {
|
|
|
608
615
|
|
|
609
616
|
// src/features/document-editor/document-bridge.tsx
|
|
610
617
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
611
|
-
function DocumentBridge({
|
|
618
|
+
function DocumentBridge({
|
|
619
|
+
children,
|
|
620
|
+
documentEditor,
|
|
621
|
+
...options
|
|
622
|
+
}) {
|
|
612
623
|
const value = useDocumentBridge(options);
|
|
613
|
-
|
|
624
|
+
const presentation = documentEditor?.presentation;
|
|
625
|
+
const width = documentEditor?.width;
|
|
626
|
+
const config = useMemo2(() => ({ presentation, width }), [presentation, width]);
|
|
627
|
+
return /* @__PURE__ */ jsx2(JuneDocumentContext.Provider, { value, children: /* @__PURE__ */ jsx2(DocumentEditorConfigContext.Provider, { value: config, children }) });
|
|
614
628
|
}
|
|
615
629
|
|
|
616
630
|
// src/themes/theme-provider.tsx
|
|
617
|
-
import { useMemo as
|
|
631
|
+
import { useMemo as useMemo3, useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
618
632
|
|
|
619
633
|
// src/themes/dark.ts
|
|
620
634
|
var darkTheme = {
|
|
@@ -675,7 +689,7 @@ function useResolvedTheme(mode) {
|
|
|
675
689
|
function JuneThemeProvider({ mode, vars, className, style, children }) {
|
|
676
690
|
const explicit = mode !== void 0;
|
|
677
691
|
const resolved = useResolvedTheme(mode ?? "system");
|
|
678
|
-
const mergedStyle =
|
|
692
|
+
const mergedStyle = useMemo3(() => {
|
|
679
693
|
const own = resolveThemeVars(vars, resolved);
|
|
680
694
|
if (!explicit && !own && !style) return void 0;
|
|
681
695
|
const base = explicit ? resolved === "dark" ? darkTheme : lightTheme : void 0;
|
|
@@ -686,7 +700,7 @@ function JuneThemeProvider({ mode, vars, className, style, children }) {
|
|
|
686
700
|
...style
|
|
687
701
|
};
|
|
688
702
|
}, [explicit, resolved, vars, style]);
|
|
689
|
-
const context =
|
|
703
|
+
const context = useMemo3(() => ({ mode: mode ?? "system", theme: resolved }), [mode, resolved]);
|
|
690
704
|
return /* @__PURE__ */ jsx3(JuneContext.Provider, { value: context, children: /* @__PURE__ */ jsx3(
|
|
691
705
|
"div",
|
|
692
706
|
{
|
|
@@ -1056,7 +1070,7 @@ var STATEMENT_START = /^\$?[A-Za-z_]\w*\s*=/;
|
|
|
1056
1070
|
var PENDING_IDENTIFIER = /^\s*\$?[A-Za-z_]\w*\s*$/;
|
|
1057
1071
|
var FENCE = /^(`{3,})\s*([\w-]*)/;
|
|
1058
1072
|
var OPENUI_FENCE_LANGS = /* @__PURE__ */ new Set(["", "openui", "openui-lang", "openuilang"]);
|
|
1059
|
-
function scan(line, state) {
|
|
1073
|
+
function scan(line, state, preserveQuote = false) {
|
|
1060
1074
|
for (let i = 0; i < line.length; i++) {
|
|
1061
1075
|
const ch = line[i];
|
|
1062
1076
|
if (state.quote) {
|
|
@@ -1070,7 +1084,95 @@ function scan(line, state) {
|
|
|
1070
1084
|
state.depth = Math.max(0, state.depth - 1);
|
|
1071
1085
|
}
|
|
1072
1086
|
}
|
|
1073
|
-
state.quote = null;
|
|
1087
|
+
if (!preserveQuote) state.quote = null;
|
|
1088
|
+
}
|
|
1089
|
+
function quoteClosesLater(lines, from, state) {
|
|
1090
|
+
const probe = { depth: state.depth, quote: state.quote };
|
|
1091
|
+
for (let i = from; i < lines.length; i++) {
|
|
1092
|
+
const line = lines[i];
|
|
1093
|
+
if (probe.depth === 0 && STATEMENT_START.test(line.trim())) return false;
|
|
1094
|
+
scan(line, probe, true);
|
|
1095
|
+
if (!probe.quote) return true;
|
|
1096
|
+
}
|
|
1097
|
+
return false;
|
|
1098
|
+
}
|
|
1099
|
+
function decodeLangString(raw) {
|
|
1100
|
+
let out = "";
|
|
1101
|
+
for (let i = 0; i < raw.length; i++) {
|
|
1102
|
+
const ch = raw[i];
|
|
1103
|
+
if (ch === "\\" && i + 1 < raw.length) {
|
|
1104
|
+
const next = raw[i + 1];
|
|
1105
|
+
out += next === "n" ? "\n" : next === "t" ? " " : next === "r" ? "\r" : next === "b" ? "\b" : next === "f" ? "\f" : next;
|
|
1106
|
+
i++;
|
|
1107
|
+
continue;
|
|
1108
|
+
}
|
|
1109
|
+
out += ch;
|
|
1110
|
+
}
|
|
1111
|
+
return out.replace(/\r/g, "");
|
|
1112
|
+
}
|
|
1113
|
+
function foldMultilineStrings(source) {
|
|
1114
|
+
let out = "";
|
|
1115
|
+
let i = 0;
|
|
1116
|
+
while (i < source.length) {
|
|
1117
|
+
if (source.startsWith('"""', i)) {
|
|
1118
|
+
const end = source.indexOf('"""', i + 3);
|
|
1119
|
+
if (end < 0) {
|
|
1120
|
+
const nl = source.indexOf("\n", i);
|
|
1121
|
+
if (nl < 0) {
|
|
1122
|
+
out += source.slice(i);
|
|
1123
|
+
break;
|
|
1124
|
+
}
|
|
1125
|
+
out += source.slice(i, nl + 1);
|
|
1126
|
+
i = nl + 1;
|
|
1127
|
+
continue;
|
|
1128
|
+
}
|
|
1129
|
+
out += JSON.stringify(source.slice(i + 3, end).replace(/\r/g, ""));
|
|
1130
|
+
i = end + 3;
|
|
1131
|
+
continue;
|
|
1132
|
+
}
|
|
1133
|
+
if (source[i] !== '"') {
|
|
1134
|
+
out += source[i];
|
|
1135
|
+
i++;
|
|
1136
|
+
continue;
|
|
1137
|
+
}
|
|
1138
|
+
let j = i + 1;
|
|
1139
|
+
let closed = false;
|
|
1140
|
+
let hasNewline = false;
|
|
1141
|
+
while (j < source.length) {
|
|
1142
|
+
const ch = source[j];
|
|
1143
|
+
if (ch === "\\") {
|
|
1144
|
+
j += 2;
|
|
1145
|
+
continue;
|
|
1146
|
+
}
|
|
1147
|
+
if (ch === "\n") {
|
|
1148
|
+
if (STATEMENT_START.test(source.slice(j + 1))) break;
|
|
1149
|
+
hasNewline = true;
|
|
1150
|
+
}
|
|
1151
|
+
if (ch === '"') {
|
|
1152
|
+
closed = true;
|
|
1153
|
+
break;
|
|
1154
|
+
}
|
|
1155
|
+
j++;
|
|
1156
|
+
}
|
|
1157
|
+
if (!closed) {
|
|
1158
|
+
const nl = source.indexOf("\n", i);
|
|
1159
|
+
if (nl < 0) {
|
|
1160
|
+
out += source.slice(i);
|
|
1161
|
+
break;
|
|
1162
|
+
}
|
|
1163
|
+
out += source.slice(i, nl + 1);
|
|
1164
|
+
i = nl + 1;
|
|
1165
|
+
continue;
|
|
1166
|
+
}
|
|
1167
|
+
if (!hasNewline) {
|
|
1168
|
+
out += source.slice(i, j + 1);
|
|
1169
|
+
i = j + 1;
|
|
1170
|
+
continue;
|
|
1171
|
+
}
|
|
1172
|
+
out += JSON.stringify(decodeLangString(source.slice(i + 1, j)));
|
|
1173
|
+
i = j + 1;
|
|
1174
|
+
}
|
|
1175
|
+
return out;
|
|
1074
1176
|
}
|
|
1075
1177
|
function splitResponse(source, options = {}) {
|
|
1076
1178
|
const markdown = options.markdown === true;
|
|
@@ -1092,8 +1194,15 @@ function splitResponse(source, options = {}) {
|
|
|
1092
1194
|
text = [];
|
|
1093
1195
|
if (joined) (seenUi ? after : before).push(joined);
|
|
1094
1196
|
};
|
|
1095
|
-
|
|
1197
|
+
const lines = input.split(/\r?\n/);
|
|
1198
|
+
for (let index = 0; index < lines.length; index++) {
|
|
1199
|
+
const line = lines[index];
|
|
1096
1200
|
const trimmed = line.trim();
|
|
1201
|
+
if (state.quote) {
|
|
1202
|
+
ui.push(line);
|
|
1203
|
+
scan(line, state, true);
|
|
1204
|
+
continue;
|
|
1205
|
+
}
|
|
1097
1206
|
if (codeFence !== null) {
|
|
1098
1207
|
text.push(line);
|
|
1099
1208
|
if (trimmed.startsWith(codeFence)) {
|
|
@@ -1122,7 +1231,8 @@ function splitResponse(source, options = {}) {
|
|
|
1122
1231
|
flushText();
|
|
1123
1232
|
seenUi = true;
|
|
1124
1233
|
ui.push(line);
|
|
1125
|
-
scan(line, state);
|
|
1234
|
+
scan(line, state, true);
|
|
1235
|
+
if (state.quote && !quoteClosesLater(lines, index + 1, state)) state.quote = null;
|
|
1126
1236
|
continue;
|
|
1127
1237
|
}
|
|
1128
1238
|
if (trimmed === "") {
|
|
@@ -1134,7 +1244,7 @@ function splitResponse(source, options = {}) {
|
|
|
1134
1244
|
flushText();
|
|
1135
1245
|
return {
|
|
1136
1246
|
before,
|
|
1137
|
-
ui: ui.join("\n"),
|
|
1247
|
+
ui: foldMultilineStrings(ui.join("\n")),
|
|
1138
1248
|
after,
|
|
1139
1249
|
pure: !sawFence && before.length === 0 && after.length === 0
|
|
1140
1250
|
};
|
|
@@ -1144,7 +1254,7 @@ function splitResponse(source, options = {}) {
|
|
|
1144
1254
|
function resolveMixedContent(response, options = {}) {
|
|
1145
1255
|
const { mixedContent = true, isStreaming = false, repair = true, markdown = false } = options;
|
|
1146
1256
|
const parts = mixedContent && response ? splitResponse(response, { streaming: isStreaming, markdown }) : null;
|
|
1147
|
-
const raw = parts && !parts.pure ? parts.ui : response;
|
|
1257
|
+
const raw = parts && !parts.pure ? parts.ui : typeof response === "string" ? foldMultilineStrings(response) : response;
|
|
1148
1258
|
const ui = !repair || !mixedContent || isStreaming || typeof raw !== "string" || raw.length === 0 ? raw : normalizeProgram(raw);
|
|
1149
1259
|
const before = parts?.before ?? [];
|
|
1150
1260
|
const after = parts?.after ?? [];
|
|
@@ -1224,6 +1334,7 @@ function JuneRenderer(props) {
|
|
|
1224
1334
|
onError,
|
|
1225
1335
|
onJuneError,
|
|
1226
1336
|
documents,
|
|
1337
|
+
documentEditor,
|
|
1227
1338
|
onResponseChange,
|
|
1228
1339
|
responseChangeDelay,
|
|
1229
1340
|
loadingFallback = null,
|
|
@@ -1267,8 +1378,8 @@ function JuneRenderer(props) {
|
|
|
1267
1378
|
);
|
|
1268
1379
|
}, []);
|
|
1269
1380
|
const handleDocumentError = useCallback2((error) => latest.current.onJuneError?.(error), []);
|
|
1270
|
-
const runtime =
|
|
1271
|
-
const content =
|
|
1381
|
+
const runtime = useMemo4(() => ({ isStreaming }), [isStreaming]);
|
|
1382
|
+
const content = useMemo4(
|
|
1272
1383
|
() => resolveMixedContent(response, { mixedContent, isStreaming, repair, markdown: textFormat === "markdown" }),
|
|
1273
1384
|
[response, mixedContent, isStreaming, repair, textFormat]
|
|
1274
1385
|
);
|
|
@@ -1280,6 +1391,7 @@ function JuneRenderer(props) {
|
|
|
1280
1391
|
DocumentBridge,
|
|
1281
1392
|
{
|
|
1282
1393
|
documents,
|
|
1394
|
+
documentEditor,
|
|
1283
1395
|
response,
|
|
1284
1396
|
onResponseChange,
|
|
1285
1397
|
responseChangeDelay,
|
|
@@ -1643,7 +1755,7 @@ function defineJuneAction(definition) {
|
|
|
1643
1755
|
}
|
|
1644
1756
|
|
|
1645
1757
|
// src/features/streaming/use-june-stream.ts
|
|
1646
|
-
import { useCallback as useCallback3, useEffect as useEffect3, useMemo as
|
|
1758
|
+
import { useCallback as useCallback3, useEffect as useEffect3, useMemo as useMemo5, useRef as useRef3, useState } from "react";
|
|
1647
1759
|
|
|
1648
1760
|
// src/features/streaming/stream-handler.ts
|
|
1649
1761
|
function isReadableStream(source) {
|
|
@@ -1906,7 +2018,7 @@ function useJuneStream(options = {}) {
|
|
|
1906
2018
|
},
|
|
1907
2019
|
[clearTimer]
|
|
1908
2020
|
);
|
|
1909
|
-
return
|
|
2021
|
+
return useMemo5(
|
|
1910
2022
|
() => ({ ...state, start, startFetch, abort, reset }),
|
|
1911
2023
|
[state, start, startFetch, abort, reset]
|
|
1912
2024
|
);
|
|
@@ -1935,7 +2047,7 @@ function DocumentDraft({ title, words, state }) {
|
|
|
1935
2047
|
|
|
1936
2048
|
// src/features/document-editor/document-editor.tsx
|
|
1937
2049
|
import { useEditor } from "@tiptap/react";
|
|
1938
|
-
import { useCallback as useCallback4, useEffect as useEffect7, useId, useMemo as
|
|
2050
|
+
import { useCallback as useCallback4, useEffect as useEffect7, useId, useMemo as useMemo6, useRef as useRef8, useState as useState6 } from "react";
|
|
1939
2051
|
|
|
1940
2052
|
// src/features/document-editor/document-bubble.tsx
|
|
1941
2053
|
import { useEditorState as useEditorState2 } from "@tiptap/react";
|
|
@@ -2115,6 +2227,10 @@ var PATHS = {
|
|
|
2115
2227
|
/* @__PURE__ */ jsx8("path", { d: "M18 6 6 18" }),
|
|
2116
2228
|
/* @__PURE__ */ jsx8("path", { d: "m6 6 12 12" })
|
|
2117
2229
|
] }),
|
|
2230
|
+
pencil: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
2231
|
+
/* @__PURE__ */ jsx8("path", { d: "M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z" }),
|
|
2232
|
+
/* @__PURE__ */ jsx8("path", { d: "m15 5 4 4" })
|
|
2233
|
+
] }),
|
|
2118
2234
|
maximize: /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
2119
2235
|
/* @__PURE__ */ jsx8("path", { d: "M8 3H5a2 2 0 0 0-2 2v3" }),
|
|
2120
2236
|
/* @__PURE__ */ jsx8("path", { d: "M21 8V5a2 2 0 0 0-2-2h-3" }),
|
|
@@ -3603,15 +3719,15 @@ function DocumentEditorImpl(props) {
|
|
|
3603
3719
|
className
|
|
3604
3720
|
} = props;
|
|
3605
3721
|
const ctxOptions = useDocumentOptions();
|
|
3606
|
-
const options =
|
|
3722
|
+
const options = useMemo6(() => ({ ...ctxOptions, ...props.options }), [ctxOptions, props.options]);
|
|
3607
3723
|
const optionsRef = useRef8(options);
|
|
3608
3724
|
optionsRef.current = options;
|
|
3609
|
-
const store =
|
|
3725
|
+
const store = useMemo6(() => options.store ?? getDefaultDocumentStore(), [options.store]);
|
|
3610
3726
|
const instanceId = useId();
|
|
3611
3727
|
const { theme: contextTheme } = useJuneTheme();
|
|
3612
3728
|
const resolvedTheme = theme === "auto" ? contextTheme : theme;
|
|
3613
3729
|
const contentKey = typeof content === "string" ? content : content ? JSON.stringify(content) : "";
|
|
3614
|
-
const parsed =
|
|
3730
|
+
const parsed = useMemo6(() => {
|
|
3615
3731
|
if (!contentKey) return { json: null, error: null };
|
|
3616
3732
|
try {
|
|
3617
3733
|
return { json: parseDocumentContent(contentKey), error: null };
|
|
@@ -3663,7 +3779,7 @@ function DocumentEditorImpl(props) {
|
|
|
3663
3779
|
);
|
|
3664
3780
|
const saveRef = useRef8(async () => {
|
|
3665
3781
|
});
|
|
3666
|
-
const autosave =
|
|
3782
|
+
const autosave = useMemo6(() => {
|
|
3667
3783
|
const delay = options.autosaveDelay ?? 1500;
|
|
3668
3784
|
return delay > 0 ? debounce(() => void saveRef.current(), delay) : null;
|
|
3669
3785
|
}, [options.autosaveDelay]);
|
|
@@ -3715,7 +3831,7 @@ function DocumentEditorImpl(props) {
|
|
|
3715
3831
|
return () => clearTimeout(t);
|
|
3716
3832
|
}, [saveState, options.onSave]);
|
|
3717
3833
|
const [initialJson] = useState6(() => store.get(documentId)?.json ?? parsed.json ?? emptyDoc());
|
|
3718
|
-
const extensions =
|
|
3834
|
+
const extensions = useMemo6(() => createDocumentExtensions(), []);
|
|
3719
3835
|
const onUpdateRef = useRef8(() => {
|
|
3720
3836
|
});
|
|
3721
3837
|
onUpdateRef.current = (json) => {
|
|
@@ -3940,9 +4056,186 @@ function DocumentEditorImpl(props) {
|
|
|
3940
4056
|
);
|
|
3941
4057
|
}
|
|
3942
4058
|
|
|
4059
|
+
// src/features/document-editor/document-preview.tsx
|
|
4060
|
+
import { useEffect as useEffect8, useMemo as useMemo7, useState as useState7 } from "react";
|
|
4061
|
+
import { createPortal } from "react-dom";
|
|
4062
|
+
|
|
4063
|
+
// src/features/document-editor/document-presentation.ts
|
|
4064
|
+
function resolveDocumentPresentation(documentPresentation, configured) {
|
|
4065
|
+
if (documentPresentation === "inline" || documentPresentation === "side-panel") return documentPresentation;
|
|
4066
|
+
if (configured === "inline" || configured === "side-panel") return configured;
|
|
4067
|
+
return "inline";
|
|
4068
|
+
}
|
|
4069
|
+
function documentPanelWidth(width) {
|
|
4070
|
+
if (typeof width === "number" && Number.isFinite(width)) return `${width}px`;
|
|
4071
|
+
if (typeof width === "string" && width.trim()) return width.trim();
|
|
4072
|
+
return void 0;
|
|
4073
|
+
}
|
|
4074
|
+
|
|
4075
|
+
// src/features/document-editor/document-preview.tsx
|
|
4076
|
+
import { Fragment as Fragment5, jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
4077
|
+
var FORMAT_LABEL = {
|
|
4078
|
+
docx: "Word document",
|
|
4079
|
+
pdf: "PDF",
|
|
4080
|
+
html: "Web page",
|
|
4081
|
+
markdown: "Markdown",
|
|
4082
|
+
txt: "Plain text"
|
|
4083
|
+
};
|
|
4084
|
+
function DocumentPreview(props) {
|
|
4085
|
+
const { documentId, title = "Untitled document", content, editable = true, exportFormats } = props;
|
|
4086
|
+
const { theme: contextTheme } = useJuneTheme();
|
|
4087
|
+
const resolvedTheme = props.theme && props.theme !== "auto" ? props.theme : contextTheme;
|
|
4088
|
+
const ctxOptions = useDocumentOptions();
|
|
4089
|
+
const editorConfig = useDocumentEditorConfig();
|
|
4090
|
+
const presentation = resolveDocumentPresentation(props.presentation, editorConfig.presentation);
|
|
4091
|
+
const panelWidth = documentPanelWidth(editorConfig.width);
|
|
4092
|
+
const store = useMemo7(() => props.options?.store ?? ctxOptions.store ?? getDefaultDocumentStore(), [props.options?.store, ctxOptions.store]);
|
|
4093
|
+
const storedJson = useDocumentValue(store, documentId, (record) => record?.json);
|
|
4094
|
+
const [open, setOpen] = useState7(false);
|
|
4095
|
+
const [preferStore, setPreferStore] = useState7(false);
|
|
4096
|
+
const [notice, setNotice] = useState7(null);
|
|
4097
|
+
const contentKey = typeof content === "string" ? content : content ? JSON.stringify(content) : "";
|
|
4098
|
+
const options = props.options ?? ctxOptions;
|
|
4099
|
+
useEffect8(() => {
|
|
4100
|
+
setPreferStore(false);
|
|
4101
|
+
}, [contentKey]);
|
|
4102
|
+
const doc = useMemo7(() => {
|
|
4103
|
+
try {
|
|
4104
|
+
const fromContent = contentKey ? parseDocumentContent(contentKey) : null;
|
|
4105
|
+
return preferStore && storedJson ? storedJson : fromContent;
|
|
4106
|
+
} catch {
|
|
4107
|
+
return null;
|
|
4108
|
+
}
|
|
4109
|
+
}, [contentKey, preferStore, storedJson]);
|
|
4110
|
+
const html = useMemo7(() => doc ? docToHtml(doc) : "", [doc]);
|
|
4111
|
+
const formats = (exportFormats ?? [...ALL_EXPORT_FORMATS]).filter((format2) => listDocumentExporters().includes(format2));
|
|
4112
|
+
useEffect8(() => {
|
|
4113
|
+
if (!notice) return;
|
|
4114
|
+
const timer = setTimeout(() => setNotice(null), 2e3);
|
|
4115
|
+
return () => clearTimeout(timer);
|
|
4116
|
+
}, [notice]);
|
|
4117
|
+
useEffect8(() => {
|
|
4118
|
+
if (!open || presentation !== "side-panel" || typeof document === "undefined") return;
|
|
4119
|
+
const prev = document.body.style.overflow;
|
|
4120
|
+
document.body.style.overflow = "hidden";
|
|
4121
|
+
return () => {
|
|
4122
|
+
document.body.style.overflow = prev;
|
|
4123
|
+
};
|
|
4124
|
+
}, [open, presentation]);
|
|
4125
|
+
const close = () => {
|
|
4126
|
+
setPreferStore(true);
|
|
4127
|
+
setOpen(false);
|
|
4128
|
+
};
|
|
4129
|
+
const handleExport = async (format2) => {
|
|
4130
|
+
if (!doc) return;
|
|
4131
|
+
try {
|
|
4132
|
+
const result = await exportDocument(format2, { documentId, title, json: doc });
|
|
4133
|
+
if (result.blob) downloadResult(result);
|
|
4134
|
+
options.onExport?.({ documentId, format: format2, ...result });
|
|
4135
|
+
} catch (error) {
|
|
4136
|
+
options.onError?.(toJuneError(error, "EXPORT_ERROR"));
|
|
4137
|
+
setNotice("Export failed");
|
|
4138
|
+
}
|
|
4139
|
+
};
|
|
4140
|
+
const handleCopy = async () => {
|
|
4141
|
+
if (!doc) return;
|
|
4142
|
+
setNotice(await copyDocumentToClipboard({ title, json: doc }) ? "Copied" : "Copy failed");
|
|
4143
|
+
};
|
|
4144
|
+
const editor = /* @__PURE__ */ jsx17(
|
|
4145
|
+
DocumentEditorImpl,
|
|
4146
|
+
{
|
|
4147
|
+
documentId: props.documentId,
|
|
4148
|
+
title: props.title,
|
|
4149
|
+
content: props.content,
|
|
4150
|
+
documentType: props.documentType,
|
|
4151
|
+
status: props.status,
|
|
4152
|
+
editable: props.editable,
|
|
4153
|
+
exportFormats: props.exportFormats,
|
|
4154
|
+
theme: props.theme,
|
|
4155
|
+
generating: props.generating,
|
|
4156
|
+
options: props.options
|
|
4157
|
+
}
|
|
4158
|
+
);
|
|
4159
|
+
const closeBar = /* @__PURE__ */ jsx17("div", { className: "june-doc-editor__bar", children: /* @__PURE__ */ jsxs11("button", { type: "button", className: "june-doc__btn june-doc__btn--ghost", "aria-label": "Close document", onClick: close, children: [
|
|
4160
|
+
/* @__PURE__ */ jsx17(Icon, { name: "close", size: 16 }),
|
|
4161
|
+
/* @__PURE__ */ jsx17("span", { children: "Close" })
|
|
4162
|
+
] }) });
|
|
4163
|
+
return /* @__PURE__ */ jsxs11(Fragment5, { children: [
|
|
4164
|
+
!open ? /* @__PURE__ */ jsxs11("section", { className: "june-doc june-doc-card", "data-theme": resolvedTheme, "aria-label": title, children: [
|
|
4165
|
+
/* @__PURE__ */ jsxs11("div", { className: "june-doc-card__bar", children: [
|
|
4166
|
+
/* @__PURE__ */ jsx17("span", { className: "june-doc-card__title", children: title }),
|
|
4167
|
+
/* @__PURE__ */ jsxs11("div", { className: "june-doc-card__actions", children: [
|
|
4168
|
+
notice ? /* @__PURE__ */ jsx17("span", { className: "june-doc-card__notice", children: notice }) : null,
|
|
4169
|
+
/* @__PURE__ */ jsx17(
|
|
4170
|
+
Dropdown,
|
|
4171
|
+
{
|
|
4172
|
+
align: "end",
|
|
4173
|
+
className: "june-doc__menu",
|
|
4174
|
+
trigger: ({ open: menuOpen, toggle }) => /* @__PURE__ */ jsxs11("button", { type: "button", className: "june-doc__btn june-doc__btn--ghost", "aria-label": "Download", "aria-haspopup": "menu", "aria-expanded": menuOpen, onClick: toggle, children: [
|
|
4175
|
+
/* @__PURE__ */ jsx17(Icon, { name: "download", size: 16 }),
|
|
4176
|
+
/* @__PURE__ */ jsx17("span", { children: "Download" })
|
|
4177
|
+
] }),
|
|
4178
|
+
children: (dismiss) => /* @__PURE__ */ jsx17("div", { role: "menu", "aria-label": "Download options", children: formats.map((format2) => /* @__PURE__ */ jsx17(
|
|
4179
|
+
"button",
|
|
4180
|
+
{
|
|
4181
|
+
type: "button",
|
|
4182
|
+
role: "menuitem",
|
|
4183
|
+
className: "june-doc__menu-item",
|
|
4184
|
+
onClick: () => {
|
|
4185
|
+
dismiss();
|
|
4186
|
+
void handleExport(format2);
|
|
4187
|
+
},
|
|
4188
|
+
children: /* @__PURE__ */ jsx17("span", { className: "june-doc__menu-label", children: FORMAT_LABEL[format2] ?? format2.toUpperCase() })
|
|
4189
|
+
},
|
|
4190
|
+
format2
|
|
4191
|
+
)) })
|
|
4192
|
+
}
|
|
4193
|
+
),
|
|
4194
|
+
/* @__PURE__ */ jsx17("button", { type: "button", className: "june-doc__btn june-doc__btn--icon june-doc__btn--ghost", "aria-label": "Copy document", title: "Copy", onClick: () => void handleCopy(), children: /* @__PURE__ */ jsx17(Icon, { name: "copy", size: 16 }) }),
|
|
4195
|
+
editable ? /* @__PURE__ */ jsx17("button", { type: "button", className: "june-doc__btn june-doc__btn--icon june-doc__btn--ghost", "aria-label": "Edit document", title: "Edit", onClick: () => setOpen(true), children: /* @__PURE__ */ jsx17(Icon, { name: "pencil", size: 16 }) }) : null
|
|
4196
|
+
] })
|
|
4197
|
+
] }),
|
|
4198
|
+
/* @__PURE__ */ jsx17("div", { className: "june-doc-card__canvas", children: /* @__PURE__ */ jsx17("div", { className: "june-doc-card__sheet", children: /* @__PURE__ */ jsx17("div", { className: "june-doc__prose", dangerouslySetInnerHTML: { __html: html } }) }) })
|
|
4199
|
+
] }) : null,
|
|
4200
|
+
open && presentation === "inline" ? /* @__PURE__ */ jsxs11("section", { className: "june-doc june-doc-inline", "data-theme": resolvedTheme, "aria-label": title, onKeyDown: (event) => {
|
|
4201
|
+
if (event.key !== "Escape" || event.defaultPrevented) return;
|
|
4202
|
+
if (event.currentTarget.querySelector(".june-doc--fullscreen")) return;
|
|
4203
|
+
close();
|
|
4204
|
+
}, children: [
|
|
4205
|
+
closeBar,
|
|
4206
|
+
editor
|
|
4207
|
+
] }) : null,
|
|
4208
|
+
open && presentation === "side-panel" && typeof document !== "undefined" ? createPortal(
|
|
4209
|
+
/* @__PURE__ */ jsx17("div", { className: "june-doc-modal", "data-theme": resolvedTheme, onMouseDown: close, children: /* @__PURE__ */ jsxs11(
|
|
4210
|
+
"div",
|
|
4211
|
+
{
|
|
4212
|
+
className: "june-doc june-doc-modal__panel",
|
|
4213
|
+
role: "dialog",
|
|
4214
|
+
"aria-modal": "true",
|
|
4215
|
+
"aria-label": title,
|
|
4216
|
+
tabIndex: -1,
|
|
4217
|
+
"data-theme": resolvedTheme,
|
|
4218
|
+
style: panelWidth ? { width: panelWidth, maxWidth: "100vw" } : void 0,
|
|
4219
|
+
onMouseDown: (event) => event.stopPropagation(),
|
|
4220
|
+
onKeyDown: (event) => {
|
|
4221
|
+
if (event.key !== "Escape" || event.defaultPrevented) return;
|
|
4222
|
+
if (event.currentTarget.querySelector(".june-doc--fullscreen")) return;
|
|
4223
|
+
close();
|
|
4224
|
+
},
|
|
4225
|
+
children: [
|
|
4226
|
+
closeBar,
|
|
4227
|
+
/* @__PURE__ */ jsx17("div", { className: "june-doc-modal__body", children: editor })
|
|
4228
|
+
]
|
|
4229
|
+
}
|
|
4230
|
+
) }),
|
|
4231
|
+
document.body
|
|
4232
|
+
) : null
|
|
4233
|
+
] });
|
|
4234
|
+
}
|
|
4235
|
+
|
|
3943
4236
|
// src/features/document-editor/document-component.tsx
|
|
3944
|
-
import { jsx as
|
|
3945
|
-
var DOCUMENT_COMPONENT_DESCRIPTION = 'Custom component. An editable document. DocumentEditor(documentId, title, content, documentType?, status?, editable?, exportFormats?). Place it in the root container (Card or Stack). "content" is the full document body as one Markdown string. Reuse documentId when revising the same document. Use it only when the user asks to create or revise a document.';
|
|
4237
|
+
import { jsx as jsx18 } from "react/jsx-runtime";
|
|
4238
|
+
var DOCUMENT_COMPONENT_DESCRIPTION = 'Custom component. An editable document. DocumentEditor(documentId, title, content, documentType?, status?, editable?, exportFormats?, presentation?). Place it in the root container (Card or Stack). "content" is the full document body as one Markdown string. Reuse documentId when revising the same document. Use it only when the user asks to create or revise a document. presentation is "inline" or "side-panel"; omit it to use the app default.';
|
|
3946
4239
|
var documentProps = z.object({
|
|
3947
4240
|
documentId: z.string().describe("Stable id. Reuse it when revising the same document."),
|
|
3948
4241
|
title: z.string().describe("Document title. Do not repeat it as a heading in content."),
|
|
@@ -3950,28 +4243,30 @@ var documentProps = z.object({
|
|
|
3950
4243
|
documentType: z.string().optional().describe("Kind of document, such as proposal, contract or invoice."),
|
|
3951
4244
|
status: z.string().optional().describe('Use "draft" for generated documents.'),
|
|
3952
4245
|
editable: z.boolean().optional().describe("Whether the user can edit. Defaults to true."),
|
|
3953
|
-
exportFormats: z.array(z.string()).optional().describe("Export formats to offer, such as html, markdown, docx.")
|
|
4246
|
+
exportFormats: z.array(z.string()).optional().describe("Export formats to offer, such as html, markdown, docx."),
|
|
4247
|
+
presentation: z.enum(["inline", "side-panel"]).optional().describe('Where Edit opens the editor: "inline" in the chat, or "side-panel". Omit to use the app default.')
|
|
3954
4248
|
});
|
|
3955
4249
|
function DocumentEditor(props) {
|
|
3956
4250
|
const { isStreaming } = useJuneRuntime();
|
|
3957
4251
|
if (props.generating || isStreaming) {
|
|
3958
|
-
return /* @__PURE__ */
|
|
4252
|
+
return /* @__PURE__ */ jsx18(DocumentDraft, { title: props.title, state: "drafting" });
|
|
3959
4253
|
}
|
|
3960
|
-
return /* @__PURE__ */
|
|
4254
|
+
return /* @__PURE__ */ jsx18(DocumentEditorImpl, { ...props });
|
|
3961
4255
|
}
|
|
3962
4256
|
function OpenUIDocument({ props }) {
|
|
3963
|
-
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3974
|
-
);
|
|
4257
|
+
const { isStreaming } = useJuneRuntime();
|
|
4258
|
+
const shared = {
|
|
4259
|
+
documentId: props.documentId,
|
|
4260
|
+
title: props.title,
|
|
4261
|
+
content: props.content,
|
|
4262
|
+
documentType: props.documentType,
|
|
4263
|
+
status: props.status,
|
|
4264
|
+
editable: props.editable,
|
|
4265
|
+
exportFormats: props.exportFormats,
|
|
4266
|
+
presentation: props.presentation
|
|
4267
|
+
};
|
|
4268
|
+
if (isStreaming) return /* @__PURE__ */ jsx18(DocumentDraft, { title: props.title, state: "drafting" });
|
|
4269
|
+
return /* @__PURE__ */ jsx18(DocumentPreview, { ...shared });
|
|
3975
4270
|
}
|
|
3976
4271
|
var JuneDocumentEditorComponent = defineComponent3({
|
|
3977
4272
|
name: "DocumentEditor",
|
|
@@ -4009,7 +4304,7 @@ function getDocumentEditorRules(options = {}) {
|
|
|
4009
4304
|
return [
|
|
4010
4305
|
`WHEN TO USE ${name}: use it only when the user asks you to create, draft, write, prepare, generate or revise an editable document (${types}, or similar). Put the finished document inside ${name}.`,
|
|
4011
4306
|
`WHEN NOT TO USE ${name}: for explanations ("explain what an NDA is"), factual answers, comparisons, brainstorming and general questions, answer with normal text and the other components. Never open ${name} for those.`,
|
|
4012
|
-
`${name}(documentId, title, content, documentType?, status?, editable?, exportFormats?): "content" is the whole document body as Markdown inside ONE double-quoted string. Write line breaks as \\n and escape double quotes as \\". Supported Markdown: headings (#, ##, ###), paragraphs, **bold**, *italic*, lists, > quotes, [links](https://...), and tables.`,
|
|
4307
|
+
`${name}(documentId, title, content, documentType?, status?, editable?, exportFormats?, presentation?): "content" is the whole document body as Markdown inside ONE double-quoted string. Write line breaks as \\n and escape double quotes as \\". Supported Markdown: headings (#, ##, ###), paragraphs, **bold**, *italic*, lists, > quotes, [links](https://...), and tables. presentation is optional: "inline" or "side-panel". Omit it to use the app default.`,
|
|
4013
4308
|
`Do not repeat the title as a heading inside "content"; the title is shown separately. Structure the document with headings, short paragraphs and tables where useful. Keep a professional tone.`,
|
|
4014
4309
|
`EDITING: when the user asks to change an existing document (add a section, rewrite a part, change the title), write ${name} again with the SAME documentId and the COMPLETE updated content, starting from the current document text you were given. Copy every unchanged section exactly as it was. Change only what was requested. The app merges your version with the user's own edits.`,
|
|
4015
4310
|
`If the user asks for a document but leaves out details, write the document anyway and use clear placeholders such as [CLIENT NAME], [DATE], [AMOUNT]. Do not stop to ask unless the request is impossible to interpret.`,
|
|
@@ -4044,8 +4339,8 @@ ${docToMarkdown2(r.json)}
|
|
|
4044
4339
|
}
|
|
4045
4340
|
|
|
4046
4341
|
// src/features/tool-approval/tool-approval.tsx
|
|
4047
|
-
import { useId as useId2, useState as
|
|
4048
|
-
import { Fragment as
|
|
4342
|
+
import { useId as useId2, useState as useState8 } from "react";
|
|
4343
|
+
import { Fragment as Fragment6, jsx as jsx19, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
4049
4344
|
var defaultToolApprovalLabels = {
|
|
4050
4345
|
approve: "Approve",
|
|
4051
4346
|
reject: "Reject",
|
|
@@ -4083,8 +4378,8 @@ function ToolApproval({
|
|
|
4083
4378
|
}) {
|
|
4084
4379
|
const labels = { ...defaultToolApprovalLabels, ...labelOverrides };
|
|
4085
4380
|
const options = request.options?.length ? request.options : ["approve", "reject"];
|
|
4086
|
-
const [draft, setDraft] =
|
|
4087
|
-
const [draftError, setDraftError] =
|
|
4381
|
+
const [draft, setDraft] = useState8(null);
|
|
4382
|
+
const [draftError, setDraftError] = useState8(null);
|
|
4088
4383
|
const titleId = useId2();
|
|
4089
4384
|
const pending = status === "pending";
|
|
4090
4385
|
const decide = (decision) => {
|
|
@@ -4102,7 +4397,7 @@ function ToolApproval({
|
|
|
4102
4397
|
setDraft(null);
|
|
4103
4398
|
decide({ choice: "edit", editedArguments });
|
|
4104
4399
|
};
|
|
4105
|
-
return /* @__PURE__ */
|
|
4400
|
+
return /* @__PURE__ */ jsxs12(
|
|
4106
4401
|
"section",
|
|
4107
4402
|
{
|
|
4108
4403
|
className: className ? `june-approval ${className}` : "june-approval",
|
|
@@ -4110,14 +4405,14 @@ function ToolApproval({
|
|
|
4110
4405
|
"data-status": status,
|
|
4111
4406
|
"data-risk": request.risk,
|
|
4112
4407
|
children: [
|
|
4113
|
-
/* @__PURE__ */
|
|
4114
|
-
/* @__PURE__ */
|
|
4115
|
-
request.risk && /* @__PURE__ */
|
|
4116
|
-
request.sideEffect && /* @__PURE__ */
|
|
4408
|
+
/* @__PURE__ */ jsxs12("header", { className: "june-approval__header", children: [
|
|
4409
|
+
/* @__PURE__ */ jsx19("strong", { id: titleId, className: "june-approval__tool", children: request.tool }),
|
|
4410
|
+
request.risk && /* @__PURE__ */ jsx19("span", { className: "june-approval__badge", "data-risk": request.risk, children: labels.risk(request.risk) }),
|
|
4411
|
+
request.sideEffect && /* @__PURE__ */ jsx19("span", { className: "june-approval__badge", children: labels.sideEffect[request.sideEffect] })
|
|
4117
4412
|
] }),
|
|
4118
|
-
request.description && /* @__PURE__ */
|
|
4119
|
-
draft !== null ? /* @__PURE__ */
|
|
4120
|
-
/* @__PURE__ */
|
|
4413
|
+
request.description && /* @__PURE__ */ jsx19("p", { className: "june-approval__description", children: request.description }),
|
|
4414
|
+
draft !== null ? /* @__PURE__ */ jsxs12("div", { className: "june-approval__edit", children: [
|
|
4415
|
+
/* @__PURE__ */ jsx19(
|
|
4121
4416
|
"textarea",
|
|
4122
4417
|
{
|
|
4123
4418
|
"aria-label": labels.edit,
|
|
@@ -4128,12 +4423,12 @@ function ToolApproval({
|
|
|
4128
4423
|
spellCheck: false
|
|
4129
4424
|
}
|
|
4130
4425
|
),
|
|
4131
|
-
draftError && /* @__PURE__ */
|
|
4132
|
-
] }) : hasArguments(request.arguments) ? renderArguments ? renderArguments(request.arguments) : /* @__PURE__ */
|
|
4133
|
-
pending ? /* @__PURE__ */
|
|
4134
|
-
/* @__PURE__ */
|
|
4135
|
-
/* @__PURE__ */
|
|
4136
|
-
] }) : options.map((choice) => /* @__PURE__ */
|
|
4426
|
+
draftError && /* @__PURE__ */ jsx19("p", { role: "alert", className: "june-approval__error", children: draftError })
|
|
4427
|
+
] }) : hasArguments(request.arguments) ? renderArguments ? renderArguments(request.arguments) : /* @__PURE__ */ jsx19("pre", { className: "june-approval__args", children: format(request.arguments) }) : null,
|
|
4428
|
+
pending ? /* @__PURE__ */ jsx19("div", { className: "june-approval__actions", children: draft !== null ? /* @__PURE__ */ jsxs12(Fragment6, { children: [
|
|
4429
|
+
/* @__PURE__ */ jsx19("button", { type: "button", className: "june-approval__button", "data-variant": "primary", onClick: saveEdit, disabled, children: labels.save }),
|
|
4430
|
+
/* @__PURE__ */ jsx19("button", { type: "button", className: "june-approval__button", onClick: () => setDraft(null), disabled, children: labels.cancel })
|
|
4431
|
+
] }) : options.map((choice) => /* @__PURE__ */ jsx19(
|
|
4137
4432
|
"button",
|
|
4138
4433
|
{
|
|
4139
4434
|
type: "button",
|
|
@@ -4144,7 +4439,7 @@ function ToolApproval({
|
|
|
4144
4439
|
children: labels[choice]
|
|
4145
4440
|
},
|
|
4146
4441
|
choice
|
|
4147
|
-
)) }) : /* @__PURE__ */
|
|
4442
|
+
)) }) : /* @__PURE__ */ jsxs12("p", { className: "june-approval__status", role: "status", children: [
|
|
4148
4443
|
labels.status[status],
|
|
4149
4444
|
status === "failed" && error ? `: ${error}` : null
|
|
4150
4445
|
] })
|
|
@@ -4154,12 +4449,12 @@ function ToolApproval({
|
|
|
4154
4449
|
}
|
|
4155
4450
|
|
|
4156
4451
|
// src/features/tool-approval/tool-approval-list.tsx
|
|
4157
|
-
import { jsx as
|
|
4452
|
+
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
4158
4453
|
function ToolApprovalList({ approvals, pendingOnly = false, renderItem, labels, className }) {
|
|
4159
4454
|
const entries = pendingOnly ? approvals.entries.filter((e) => e.status === "pending") : approvals.entries;
|
|
4160
4455
|
if (entries.length === 0) return null;
|
|
4161
|
-
return /* @__PURE__ */
|
|
4162
|
-
(entry) => renderItem ? /* @__PURE__ */
|
|
4456
|
+
return /* @__PURE__ */ jsx20("div", { className: className ? `june-approval-list ${className}` : "june-approval-list", children: entries.map(
|
|
4457
|
+
(entry) => renderItem ? /* @__PURE__ */ jsx20("div", { children: renderItem(entry, approvals.decide) }, entry.request.id) : /* @__PURE__ */ jsx20(
|
|
4163
4458
|
ToolApproval,
|
|
4164
4459
|
{
|
|
4165
4460
|
request: entry.request,
|
|
@@ -4174,11 +4469,11 @@ function ToolApprovalList({ approvals, pendingOnly = false, renderItem, labels,
|
|
|
4174
4469
|
}
|
|
4175
4470
|
|
|
4176
4471
|
// src/features/tool-approval/use-tool-approval.ts
|
|
4177
|
-
import { useCallback as useCallback5, useEffect as
|
|
4472
|
+
import { useCallback as useCallback5, useEffect as useEffect9, useMemo as useMemo8, useRef as useRef9, useState as useState9 } from "react";
|
|
4178
4473
|
var counter = 0;
|
|
4179
4474
|
var nextId = () => `june-approval-${++counter}`;
|
|
4180
4475
|
function useToolApproval() {
|
|
4181
|
-
const [entries, setEntries] =
|
|
4476
|
+
const [entries, setEntries] = useState9([]);
|
|
4182
4477
|
const waiters = useRef9(/* @__PURE__ */ new Map());
|
|
4183
4478
|
const settle = useCallback5((id, decision) => {
|
|
4184
4479
|
const resolve = waiters.current.get(id);
|
|
@@ -4223,15 +4518,15 @@ function useToolApproval() {
|
|
|
4223
4518
|
},
|
|
4224
4519
|
[request]
|
|
4225
4520
|
);
|
|
4226
|
-
|
|
4521
|
+
useEffect9(() => {
|
|
4227
4522
|
const map = waiters.current;
|
|
4228
4523
|
return () => {
|
|
4229
4524
|
map.forEach((resolve) => resolve({ choice: "reject" }));
|
|
4230
4525
|
map.clear();
|
|
4231
4526
|
};
|
|
4232
4527
|
}, []);
|
|
4233
|
-
const pending =
|
|
4234
|
-
return
|
|
4528
|
+
const pending = useMemo8(() => entries.filter((e) => e.status === "pending"), [entries]);
|
|
4529
|
+
return useMemo8(
|
|
4235
4530
|
() => ({ entries, pending, request, decide, setStatus, dismiss, confirmAction }),
|
|
4236
4531
|
[entries, pending, request, decide, setStatus, dismiss, confirmAction]
|
|
4237
4532
|
);
|
|
@@ -4335,6 +4630,8 @@ export {
|
|
|
4335
4630
|
runAction,
|
|
4336
4631
|
createActionHandler,
|
|
4337
4632
|
JuneDocumentContext,
|
|
4633
|
+
DocumentEditorConfigContext,
|
|
4634
|
+
useDocumentEditorConfig,
|
|
4338
4635
|
useDocumentOptions,
|
|
4339
4636
|
mergeDocuments,
|
|
4340
4637
|
createDocumentStore,
|
|
@@ -4379,6 +4676,8 @@ export {
|
|
|
4379
4676
|
downloadResult,
|
|
4380
4677
|
copyDocumentToClipboard,
|
|
4381
4678
|
ALL_EXPORT_FORMATS,
|
|
4679
|
+
resolveDocumentPresentation,
|
|
4680
|
+
documentPanelWidth,
|
|
4382
4681
|
DOCUMENT_COMPONENT_DESCRIPTION,
|
|
4383
4682
|
DocumentEditor,
|
|
4384
4683
|
JuneDocumentEditorComponent,
|