@reportwright/viewer 0.12.1 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +78 -0
- package/README.md +16 -1
- package/THIRD-PARTY-NOTICES.md +52 -0
- package/dist/{chunk-S2IUUI6N.js → chunk-BF7GCWZY.js} +67 -49
- package/dist/chunk-BF7GCWZY.js.map +6 -0
- package/dist/chunk-BR5K6SBL.js +324 -0
- package/dist/chunk-BR5K6SBL.js.map +6 -0
- package/dist/{peer/chunk-BQFI3DHK.js → chunk-CNDUJ7IV.js} +289 -25
- package/dist/chunk-CNDUJ7IV.js.map +6 -0
- package/dist/{chunk-VNOWPSE6.js → chunk-EK5CJY22.js} +1223 -899
- package/dist/chunk-EK5CJY22.js.map +6 -0
- package/dist/{chunk-2BPBQMH2.js → chunk-F5EPQTPF.js} +3 -3
- package/dist/chunk-FEM2QVOO.js +18 -0
- package/dist/{chunk-3D2KFKG2.js → chunk-IFYCJZNS.js} +8 -6
- package/dist/chunk-IFYCJZNS.js.map +6 -0
- package/dist/{chunk-NR2G4TMG.js → chunk-L6YEIVVD.js} +43 -22
- package/dist/chunk-L6YEIVVD.js.map +6 -0
- package/dist/{chunk-DPVJEFKP.js → chunk-PQNM6ET7.js} +4 -4
- package/dist/{chunk-DPVJEFKP.js.map → chunk-PQNM6ET7.js.map} +1 -1
- package/dist/{chunk-Z7MKH66Z.js → chunk-QFLVVM3H.js} +225 -11
- package/dist/chunk-QFLVVM3H.js.map +6 -0
- package/dist/{chunk-PGP3QA6L.js → chunk-TZXEEVKE.js} +1301 -70
- package/dist/chunk-TZXEEVKE.js.map +6 -0
- package/dist/{chunk-Q6MMPKQA.js → chunk-UHHURTSV.js} +11 -10
- package/dist/chunk-UHHURTSV.js.map +6 -0
- package/dist/{chunk-M6AYND5G.js → chunk-UJL7C2AS.js} +16 -7
- package/dist/chunk-UJL7C2AS.js.map +6 -0
- package/dist/chunk-YIX3OJXU.js +34 -0
- package/dist/designer.d.ts +11 -3
- package/dist/designer.js +587 -386
- package/dist/designer.js.map +3 -3
- package/dist/engine.worker.js +16729 -18
- package/dist/engine.worker.js.map +3 -3
- package/dist/peer/{chunk-6I2EAAVN.js → chunk-2CD5COHN.js} +43 -22
- package/dist/peer/chunk-2CD5COHN.js.map +6 -0
- package/dist/peer/{chunk-BMAXIBP2.js → chunk-3CBV5SAI.js} +4 -4
- package/dist/peer/{chunk-BMAXIBP2.js.map → chunk-3CBV5SAI.js.map} +1 -1
- package/dist/peer/{chunk-WSNRD2AQ.js → chunk-45GVDKP5.js} +11 -10
- package/dist/{chunk-Q6MMPKQA.js.map → peer/chunk-45GVDKP5.js.map} +1 -1
- package/dist/peer/{chunk-R4VX5UC7.js → chunk-LWXQX3NJ.js} +3 -3
- package/dist/{chunk-6TPZ7G74.js → peer/chunk-MKY3SDXU.js} +289 -25
- package/dist/peer/chunk-MKY3SDXU.js.map +6 -0
- package/dist/peer/chunk-S6LSPHSU.js +17 -0
- package/dist/peer/chunk-S6LSPHSU.js.map +6 -0
- package/dist/peer/{chunk-TSC4RAH3.js → chunk-VZHHNQYB.js} +1301 -70
- package/dist/peer/chunk-VZHHNQYB.js.map +6 -0
- package/dist/peer/{chunk-WQGENQZO.js → chunk-YITWGAR4.js} +8 -6
- package/dist/peer/chunk-YITWGAR4.js.map +6 -0
- package/dist/peer/chunk-Z5II55QT.js +33 -0
- package/dist/peer/chunk-Z5II55QT.js.map +6 -0
- package/dist/peer/designer.js +444 -243
- package/dist/peer/designer.js.map +3 -3
- package/dist/peer/engine.worker.js +16729 -17
- package/dist/peer/engine.worker.js.map +3 -3
- package/dist/peer/viewer.js +14 -11
- package/dist/peer/viewer.js.map +1 -1
- package/dist/viewer.d.ts +2 -1
- package/dist/viewer.js +14 -11
- package/dist/viewer.js.map +1 -1
- package/package.json +4 -2
- package/dist/chunk-3D2KFKG2.js.map +0 -6
- package/dist/chunk-6TPZ7G74.js.map +0 -6
- package/dist/chunk-BRB34AJ2.js +0 -16
- package/dist/chunk-M6AYND5G.js.map +0 -6
- package/dist/chunk-NR2G4TMG.js.map +0 -6
- package/dist/chunk-PGP3QA6L.js.map +0 -6
- package/dist/chunk-S2IUUI6N.js.map +0 -6
- package/dist/chunk-ULKEEARQ.js +0 -553
- package/dist/chunk-ULKEEARQ.js.map +0 -6
- package/dist/chunk-VNOWPSE6.js.map +0 -6
- package/dist/chunk-Z7MKH66Z.js.map +0 -6
- package/dist/peer/chunk-2FZTYEDE.js +0 -15
- package/dist/peer/chunk-6I2EAAVN.js.map +0 -6
- package/dist/peer/chunk-BQFI3DHK.js.map +0 -6
- package/dist/peer/chunk-TSC4RAH3.js.map +0 -6
- package/dist/peer/chunk-WQGENQZO.js.map +0 -6
- package/dist/peer/chunk-WSNRD2AQ.js.map +0 -6
- /package/dist/{chunk-2BPBQMH2.js.map → chunk-F5EPQTPF.js.map} +0 -0
- /package/dist/{chunk-BRB34AJ2.js.map → chunk-FEM2QVOO.js.map} +0 -0
- /package/dist/{peer/chunk-2FZTYEDE.js.map → chunk-YIX3OJXU.js.map} +0 -0
- /package/dist/peer/{chunk-R4VX5UC7.js.map → chunk-LWXQX3NJ.js.map} +0 -0
package/dist/designer.js
CHANGED
|
@@ -13,16 +13,18 @@ import {
|
|
|
13
13
|
setShadowStyles,
|
|
14
14
|
t,
|
|
15
15
|
uiFontCss
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-L6YEIVVD.js";
|
|
17
17
|
import {
|
|
18
18
|
customFonts,
|
|
19
|
-
fontStore,
|
|
20
19
|
fontsBase,
|
|
20
|
+
loadFontStore,
|
|
21
21
|
loadModelFonts,
|
|
22
22
|
origin,
|
|
23
|
+
reportFetch,
|
|
23
24
|
setAssetBase,
|
|
25
|
+
setFetchPolicy,
|
|
24
26
|
setStandalone
|
|
25
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-CNDUJ7IV.js";
|
|
26
28
|
import {
|
|
27
29
|
BASE_STYLE,
|
|
28
30
|
DEFAULT_THEME,
|
|
@@ -31,10 +33,10 @@ import {
|
|
|
31
33
|
ITEMS,
|
|
32
34
|
ODATA_DEFAULT_PAGES,
|
|
33
35
|
ODATA_MAX_PAGES,
|
|
34
|
-
PAGE_SIZES,
|
|
35
36
|
PALETTES,
|
|
36
37
|
TEXT_STYLE_PROPS,
|
|
37
38
|
THEME_COLORS,
|
|
39
|
+
TextMeasurer,
|
|
38
40
|
XmlError,
|
|
39
41
|
bestXmlRows,
|
|
40
42
|
buildDataSets,
|
|
@@ -43,7 +45,7 @@ import {
|
|
|
43
45
|
detectFields,
|
|
44
46
|
evalValue,
|
|
45
47
|
findItemNamed,
|
|
46
|
-
|
|
48
|
+
finishText,
|
|
47
49
|
functionTable,
|
|
48
50
|
isDynamic,
|
|
49
51
|
isTablix,
|
|
@@ -52,31 +54,29 @@ import {
|
|
|
52
54
|
layoutItems,
|
|
53
55
|
loadBarcodes,
|
|
54
56
|
loadSources,
|
|
55
|
-
normBox,
|
|
56
57
|
normalizeMatrix,
|
|
57
58
|
odataMetadata,
|
|
58
59
|
parseBorder,
|
|
59
60
|
parseXml,
|
|
60
61
|
render,
|
|
61
|
-
reportFetch,
|
|
62
|
-
resolvePage,
|
|
63
62
|
resolveParameters,
|
|
64
|
-
setFetchPolicy,
|
|
65
63
|
shiftItems,
|
|
66
64
|
sourceRows,
|
|
67
65
|
sourceUrl,
|
|
68
66
|
stylePropsFor,
|
|
69
67
|
themeContext,
|
|
70
|
-
toPt,
|
|
71
68
|
toText,
|
|
72
69
|
validate,
|
|
73
70
|
withPartProps,
|
|
74
71
|
xmlRowPaths
|
|
75
|
-
} from "./chunk-
|
|
72
|
+
} from "./chunk-EK5CJY22.js";
|
|
76
73
|
import {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
74
|
+
PAGE_SIZES,
|
|
75
|
+
fromPt,
|
|
76
|
+
normBox,
|
|
77
|
+
resolvePage,
|
|
78
|
+
toPt
|
|
79
|
+
} from "./chunk-BR5K6SBL.js";
|
|
80
80
|
import "./chunk-72S6DETS.js";
|
|
81
81
|
import {
|
|
82
82
|
currencyOf
|
|
@@ -86,20 +86,20 @@ import {
|
|
|
86
86
|
fontFaceCss,
|
|
87
87
|
fontFamilyCss,
|
|
88
88
|
pageToSvg
|
|
89
|
-
} from "./chunk-
|
|
89
|
+
} from "./chunk-UJL7C2AS.js";
|
|
90
90
|
import {
|
|
91
91
|
BUNDLED_FAMILIES,
|
|
92
92
|
FONT_FAMILIES,
|
|
93
93
|
allFontKeys,
|
|
94
94
|
fallbackKeys,
|
|
95
95
|
resolveFontKey
|
|
96
|
-
} from "./chunk-
|
|
96
|
+
} from "./chunk-QFLVVM3H.js";
|
|
97
97
|
import {
|
|
98
98
|
__toESM
|
|
99
99
|
} from "./chunk-OLLMACWA.js";
|
|
100
100
|
|
|
101
101
|
// src/embed/designer.js
|
|
102
|
-
var
|
|
102
|
+
var import_react23 = __toESM(require_react(), 1);
|
|
103
103
|
var import_client = __toESM(require_client(), 1);
|
|
104
104
|
|
|
105
105
|
// src/importers/rdlx.js
|
|
@@ -6867,10 +6867,10 @@ function readReportFile(name2, text) {
|
|
|
6867
6867
|
}
|
|
6868
6868
|
|
|
6869
6869
|
// src/designer/Designer.jsx
|
|
6870
|
-
var
|
|
6870
|
+
var import_react22 = __toESM(require_react(), 1);
|
|
6871
6871
|
|
|
6872
6872
|
// src/designer/ui.jsx
|
|
6873
|
-
var
|
|
6873
|
+
var import_react3 = __toESM(require_react(), 1);
|
|
6874
6874
|
|
|
6875
6875
|
// src/designer/fieldCheck.js
|
|
6876
6876
|
function exprParts(value) {
|
|
@@ -7004,13 +7004,9 @@ function useStore(api, selector = identity) {
|
|
|
7004
7004
|
import_react.default.useDebugValue(slice);
|
|
7005
7005
|
return slice;
|
|
7006
7006
|
}
|
|
7007
|
-
|
|
7008
|
-
|
|
7009
|
-
|
|
7010
|
-
Object.assign(useBoundStore, api);
|
|
7011
|
-
return useBoundStore;
|
|
7012
|
-
};
|
|
7013
|
-
var create = ((createState) => createState ? createImpl(createState) : createImpl);
|
|
7007
|
+
|
|
7008
|
+
// src/designer/store.js
|
|
7009
|
+
var import_react2 = __toESM(require_react(), 1);
|
|
7014
7010
|
|
|
7015
7011
|
// node_modules/immer/dist/immer.mjs
|
|
7016
7012
|
var NOTHING = /* @__PURE__ */ Symbol.for("immer-nothing");
|
|
@@ -7859,6 +7855,17 @@ function pageOf2(def, key2 = "body") {
|
|
|
7859
7855
|
return resolvePage({ ...def.page || {}, ...sec?.page || {} });
|
|
7860
7856
|
}
|
|
7861
7857
|
var rid = () => Math.random().toString(36).slice(2, 10);
|
|
7858
|
+
function stableId(key2, taken) {
|
|
7859
|
+
let h = 2166136261;
|
|
7860
|
+
for (let i2 = 0; i2 < key2.length; i2++) {
|
|
7861
|
+
h ^= key2.charCodeAt(i2);
|
|
7862
|
+
h = Math.imul(h, 16777619);
|
|
7863
|
+
}
|
|
7864
|
+
let id = `i${(h >>> 0).toString(36)}`;
|
|
7865
|
+
for (let k = 2; taken.has(id); k++) id = `i${(h >>> 0).toString(36)}_${k}`;
|
|
7866
|
+
taken.add(id);
|
|
7867
|
+
return id;
|
|
7868
|
+
}
|
|
7862
7869
|
function walk(def, fn3) {
|
|
7863
7870
|
const go = (list2, parent, section) => list2.forEach((it, i2) => {
|
|
7864
7871
|
fn3(it, list2, i2, parent, section);
|
|
@@ -7884,9 +7891,15 @@ function normalize(def) {
|
|
|
7884
7891
|
if (x && typeof x === "object") x.items || (x.items = []);
|
|
7885
7892
|
}
|
|
7886
7893
|
const used = allNames(d);
|
|
7894
|
+
const ids = /* @__PURE__ */ new Set();
|
|
7887
7895
|
walk(d, (it) => {
|
|
7888
|
-
it.id
|
|
7896
|
+
if (it.id) ids.add(it.id);
|
|
7897
|
+
});
|
|
7898
|
+
const path = /* @__PURE__ */ new Map();
|
|
7899
|
+
walk(d, (it, list2, i2, parent, section) => {
|
|
7900
|
+
path.set(it, `${parent ? path.get(parent) : section}/${i2}`);
|
|
7889
7901
|
if (!it.name) it.name = uniqueName(used, ITEMS[it.type]?.label.replace(/\s/g, "") || "Item");
|
|
7902
|
+
it.id || (it.id = stableId(`${path.get(it)}/${it.name}`, ids));
|
|
7890
7903
|
if (NESTING.has(it.type)) it.items || (it.items = []);
|
|
7891
7904
|
if (it.type === "table" && Array.isArray(it.columns)) tableSync(it);
|
|
7892
7905
|
});
|
|
@@ -7910,7 +7923,7 @@ function findItem(def, id) {
|
|
|
7910
7923
|
});
|
|
7911
7924
|
return hit;
|
|
7912
7925
|
}
|
|
7913
|
-
var
|
|
7926
|
+
var newDesignerStore = () => createStore((set2, get2) => ({
|
|
7914
7927
|
id: null,
|
|
7915
7928
|
def: null,
|
|
7916
7929
|
saved: true,
|
|
@@ -8041,7 +8054,18 @@ var useDesigner = create((set2, get2) => ({
|
|
|
8041
8054
|
set2({ rev: (res.headers.get("etag") || "").replace(/^W\/|"/g, "") || null, conflict: null });
|
|
8042
8055
|
}
|
|
8043
8056
|
}));
|
|
8044
|
-
var
|
|
8057
|
+
var active = newDesignerStore();
|
|
8058
|
+
var DesignerStore = (0, import_react2.createContext)(null);
|
|
8059
|
+
var activateStore = (store) => {
|
|
8060
|
+
active = store;
|
|
8061
|
+
};
|
|
8062
|
+
var activeStore2 = () => active;
|
|
8063
|
+
var useDesignerStore = () => (0, import_react2.useContext)(DesignerStore) || active;
|
|
8064
|
+
var useDesigner = (sel) => useStore(useDesignerStore(), sel);
|
|
8065
|
+
useDesigner.getState = () => active.getState();
|
|
8066
|
+
useDesigner.setState = (...a) => active.setState(...a);
|
|
8067
|
+
useDesigner.subscribe = (fn3) => active.subscribe(fn3);
|
|
8068
|
+
var S = () => active.getState();
|
|
8045
8069
|
function bodyWidth(def, key2 = "body") {
|
|
8046
8070
|
return pageOf2(def, key2).bodyWidth;
|
|
8047
8071
|
}
|
|
@@ -8089,7 +8113,7 @@ function addItem(type, section, x, y, extra = {}, parentId = null) {
|
|
|
8089
8113
|
} else {
|
|
8090
8114
|
const sec = secOf(d, section);
|
|
8091
8115
|
sec.items.push(it);
|
|
8092
|
-
if (it.y + it.h > sec.height) sec.height = Math.ceil(it.y + it.h + (isBodyKey(section) ? 24 : 4));
|
|
8116
|
+
if (it.y + it.h > (sec.height || 0)) sec.height = Math.ceil(it.y + it.h + (isBodyKey(section) ? 24 : 4));
|
|
8093
8117
|
}
|
|
8094
8118
|
});
|
|
8095
8119
|
S().select({ kind: "items", ids: [id] });
|
|
@@ -8115,9 +8139,21 @@ function insertItem(type, section, x, y, extra = {}, parentId = null) {
|
|
|
8115
8139
|
function updateItem(id, recipe, key2) {
|
|
8116
8140
|
S().apply((d) => {
|
|
8117
8141
|
const f = findItem(d, id);
|
|
8118
|
-
if (f)
|
|
8142
|
+
if (!f) return;
|
|
8143
|
+
recipe(f.item, d, f.section, f);
|
|
8144
|
+
minSize(f.item);
|
|
8145
|
+
const nf = findItem(d, id);
|
|
8146
|
+
if (nf) growToFit(d, nf);
|
|
8119
8147
|
}, key2);
|
|
8120
8148
|
}
|
|
8149
|
+
function minSize(it) {
|
|
8150
|
+
for (const k of ["w", "h"]) if (typeof it[k] === "number" && !(it[k] >= 0)) it[k] = 0;
|
|
8151
|
+
if (it.type === "line") {
|
|
8152
|
+
if (it.w === 0 && it.h === 0) it.w = 1;
|
|
8153
|
+
return;
|
|
8154
|
+
}
|
|
8155
|
+
for (const k of ["w", "h"]) if (typeof it[k] === "number" && it[k] < 1) it[k] = 1;
|
|
8156
|
+
}
|
|
8121
8157
|
function moveItems(ids, dx, dy) {
|
|
8122
8158
|
if (!dx && !dy) return;
|
|
8123
8159
|
if (S().cells && wouldOverlap(S().def, ids, (it) => ({ x: it.x + dx, y: it.y + dy, w: it.w, h: it.h }))) {
|
|
@@ -8248,14 +8284,16 @@ function duplicateSelection() {
|
|
|
8248
8284
|
const f = findItem(d, id);
|
|
8249
8285
|
if (!f) continue;
|
|
8250
8286
|
const copy = cloneWithIds(f.item, used);
|
|
8251
|
-
copy.x +=
|
|
8252
|
-
copy.y +=
|
|
8287
|
+
copy.x += PASTE_OFFSET;
|
|
8288
|
+
copy.y += PASTE_OFFSET;
|
|
8289
|
+
growToFit(d, { ...f, item: copy });
|
|
8253
8290
|
f.list.push(copy);
|
|
8254
8291
|
newIds.push(copy.id);
|
|
8255
8292
|
}
|
|
8256
8293
|
});
|
|
8257
8294
|
if (newIds.length) S().select({ kind: "items", ids: newIds });
|
|
8258
8295
|
}
|
|
8296
|
+
var PASTE_OFFSET = 12;
|
|
8259
8297
|
var CLIP = "pagewright/items@1";
|
|
8260
8298
|
async function copySelection() {
|
|
8261
8299
|
const { sel, def } = S();
|
|
@@ -8270,43 +8308,41 @@ async function copySelection() {
|
|
|
8270
8308
|
return items.length;
|
|
8271
8309
|
}
|
|
8272
8310
|
var memClip = null;
|
|
8273
|
-
|
|
8274
|
-
let text = null;
|
|
8275
|
-
try {
|
|
8276
|
-
text = await navigator.clipboard.readText();
|
|
8277
|
-
} catch {
|
|
8278
|
-
text = memClip;
|
|
8279
|
-
}
|
|
8280
|
-
if (!text || !text.includes(CLIP)) text = memClip;
|
|
8281
|
-
let data;
|
|
8311
|
+
var clipOf = (text) => {
|
|
8282
8312
|
try {
|
|
8283
|
-
|
|
8313
|
+
const d = JSON.parse(text);
|
|
8314
|
+
return d?.kind === CLIP && Array.isArray(d.items) ? d : null;
|
|
8284
8315
|
} catch {
|
|
8285
|
-
return
|
|
8316
|
+
return null;
|
|
8286
8317
|
}
|
|
8287
|
-
|
|
8318
|
+
};
|
|
8319
|
+
function pasteItems(section = "body", text = null) {
|
|
8320
|
+
const st = active;
|
|
8321
|
+
const data = clipOf(text) || clipOf(memClip);
|
|
8322
|
+
if (!data) return 0;
|
|
8288
8323
|
const ids = [];
|
|
8289
|
-
|
|
8324
|
+
st.getState().apply((d) => {
|
|
8290
8325
|
const used = allNames(d);
|
|
8291
8326
|
for (const it of data.items) {
|
|
8292
8327
|
const c = cloneWithIds(it, used);
|
|
8293
|
-
c.x +=
|
|
8294
|
-
c.y +=
|
|
8328
|
+
c.x += PASTE_OFFSET;
|
|
8329
|
+
c.y += PASTE_OFFSET;
|
|
8295
8330
|
if (c.type === "table" && !isBodyKey(section)) continue;
|
|
8296
8331
|
secOf(d, section).items.push(c);
|
|
8332
|
+
growToFit(d, { section, parent: null, item: c });
|
|
8297
8333
|
ids.push(c.id);
|
|
8298
8334
|
}
|
|
8299
8335
|
});
|
|
8300
|
-
if (ids.length)
|
|
8336
|
+
if (ids.length) st.getState().select({ kind: "items", ids });
|
|
8301
8337
|
return ids.length;
|
|
8302
8338
|
}
|
|
8303
|
-
function rowsOf(t3, part,
|
|
8339
|
+
function rowsOf(t3, part, create = false) {
|
|
8304
8340
|
const m = /^g(\d+)([hf])$/.exec(part);
|
|
8305
8341
|
const holder = m ? t3.groups?.[Number(m[1])] : t3;
|
|
8306
8342
|
if (!holder) return null;
|
|
8307
8343
|
const key2 = m ? m[2] === "h" ? "header" : "footer" : part;
|
|
8308
8344
|
if (!holder[key2]) {
|
|
8309
|
-
if (!
|
|
8345
|
+
if (!create) return [];
|
|
8310
8346
|
holder[key2] = [];
|
|
8311
8347
|
}
|
|
8312
8348
|
return holder[key2];
|
|
@@ -8506,6 +8542,7 @@ function tableRemoveGroup(id, level) {
|
|
|
8506
8542
|
}
|
|
8507
8543
|
var IMAGE_MAX = 10 * 1024 * 1024;
|
|
8508
8544
|
async function uploadImages(files, T) {
|
|
8545
|
+
const st = active;
|
|
8509
8546
|
const names = [];
|
|
8510
8547
|
let err = null;
|
|
8511
8548
|
for (const f of files) {
|
|
@@ -8524,7 +8561,7 @@ async function uploadImages(files, T) {
|
|
|
8524
8561
|
r.readAsDataURL(f);
|
|
8525
8562
|
});
|
|
8526
8563
|
const base2 = f.name.replace(/\.[^.]+$/, "").replace(/\W+/g, "_").replace(/^_+|_+$/g, "") || "image";
|
|
8527
|
-
|
|
8564
|
+
st.getState().apply((d) => {
|
|
8528
8565
|
d.images || (d.images = {});
|
|
8529
8566
|
let n = base2, k = 2;
|
|
8530
8567
|
while (d.images[n]) n = `${base2}${k++}`;
|
|
@@ -8591,6 +8628,13 @@ function wouldOverlap(def, ids, rectOf2) {
|
|
|
8591
8628
|
}
|
|
8592
8629
|
return false;
|
|
8593
8630
|
}
|
|
8631
|
+
function setMatrixShow(v, show) {
|
|
8632
|
+
const pct = !!show && show !== "value";
|
|
8633
|
+
if (pct) v.show = show;
|
|
8634
|
+
else delete v.show;
|
|
8635
|
+
if (pct && (!v.format || v.format === "N0")) v.format = "P1";
|
|
8636
|
+
else if (!pct && v.format === "P1") v.format = "N0";
|
|
8637
|
+
}
|
|
8594
8638
|
|
|
8595
8639
|
// src/designer/ui.jsx
|
|
8596
8640
|
var import_jsx_runtime = __toESM(require_jsx_runtime(), 1);
|
|
@@ -8602,8 +8646,8 @@ function TextInput({ value, onChange, mono, invalid, className, ...rest }) {
|
|
|
8602
8646
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { className: `input${mono ? " mono" : ""}${invalid ? " invalid" : ""}${className ? ` ${className}` : ""}`, value: value ?? "", onChange: (e) => onChange(e.target.value), ...rest });
|
|
8603
8647
|
}
|
|
8604
8648
|
function NumberInput({ value, onChange, step = 0.5, min, ...rest }) {
|
|
8605
|
-
const [draft, setDraft] = (0,
|
|
8606
|
-
(0,
|
|
8649
|
+
const [draft, setDraft] = (0, import_react3.useState)(value ?? "");
|
|
8650
|
+
(0, import_react3.useEffect)(() => {
|
|
8607
8651
|
setDraft(value ?? "");
|
|
8608
8652
|
}, [value]);
|
|
8609
8653
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -8639,18 +8683,18 @@ function ColorInput({ value, onChange }) {
|
|
|
8639
8683
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TextInput, { value, onChange: (v) => onChange(v === "" ? void 0 : v), mono: true, placeholder: T("i_colorPh") })
|
|
8640
8684
|
] });
|
|
8641
8685
|
}
|
|
8642
|
-
var FieldScope = (0,
|
|
8686
|
+
var FieldScope = (0, import_react3.createContext)(void 0);
|
|
8643
8687
|
var issueText = (T, i2) => i2.suggest ? T("ux_unknownFieldSuggest", { name: i2.name, suggest: i2.suggest }) : T("ux_unknownField", { name: i2.name });
|
|
8644
8688
|
function ExprInput({ value, onChange, onOpen, placeholder: placeholder2 }) {
|
|
8645
8689
|
const T = useT();
|
|
8646
|
-
const scope = (0,
|
|
8690
|
+
const scope = (0, import_react3.useContext)(FieldScope);
|
|
8647
8691
|
const dataSets = useDesigner((s) => s.def?.dataSets);
|
|
8648
8692
|
const err = value ? checkValue(value) : null;
|
|
8649
8693
|
const issues = !err && value && scope !== void 0 ? fieldIssues(value, dataSets, scope) : [];
|
|
8650
8694
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
8651
8695
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "expr-row", children: [
|
|
8652
8696
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(TextInput, { value, onChange, mono: true, invalid: !!err, className: issues.length ? "squiggle" : void 0, "aria-invalid": err || issues.length ? true : void 0, placeholder: placeholder2 || T("i_exprPh") }),
|
|
8653
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: "fx", title: T("i_openExprEditor"), "aria-label": T("i_openExprEditor")
|
|
8697
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: "fx", title: T("i_openExprEditor"), "aria-label": `fx: ${T("i_openExprEditor")}`, onClick: onOpen, type: "button", children: "fx" })
|
|
8654
8698
|
] }),
|
|
8655
8699
|
err && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "err", children: err }),
|
|
8656
8700
|
issues.map((i2, k) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "warn", "data-testid": "field-warning", children: issueText(T, i2) }, k))
|
|
@@ -8670,14 +8714,19 @@ function Check({ label, checked, onChange }) {
|
|
|
8670
8714
|
] });
|
|
8671
8715
|
}
|
|
8672
8716
|
function Dialog({ title, children, onClose, footer, wide, className = "" }) {
|
|
8673
|
-
(0,
|
|
8717
|
+
const ref = (0, import_react3.useRef)(null);
|
|
8718
|
+
(0, import_react3.useEffect)(() => {
|
|
8719
|
+
const inOther = (e) => {
|
|
8720
|
+
const mine = ref.current?.closest(".designer");
|
|
8721
|
+
return e.composedPath().some((n) => n !== mine && n?.classList?.contains("designer"));
|
|
8722
|
+
};
|
|
8674
8723
|
const k = (e) => {
|
|
8675
|
-
if (e.key === "Escape" && !e.defaultPrevented) onClose();
|
|
8724
|
+
if (e.key === "Escape" && !e.defaultPrevented && !inOther(e)) onClose();
|
|
8676
8725
|
};
|
|
8677
8726
|
window.addEventListener("keydown", k);
|
|
8678
8727
|
return () => window.removeEventListener("keydown", k);
|
|
8679
8728
|
}, [onClose]);
|
|
8680
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "scrim", onPointerDown: (e) => {
|
|
8729
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "scrim", ref, onPointerDown: (e) => {
|
|
8681
8730
|
if (e.target === e.currentTarget) onClose();
|
|
8682
8731
|
}, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: `dialog${wide ? " wide" : ""}${className ? ` ${className}` : ""}`, role: "dialog", "aria-modal": "true", "aria-label": title, children: [
|
|
8683
8732
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("header", { children: title }),
|
|
@@ -8687,20 +8736,20 @@ function Dialog({ title, children, onClose, footer, wide, className = "" }) {
|
|
|
8687
8736
|
}
|
|
8688
8737
|
|
|
8689
8738
|
// src/embed/link.js
|
|
8690
|
-
var
|
|
8739
|
+
var import_react4 = __toESM(require_react(), 1);
|
|
8691
8740
|
function Link({ href, children, prefetch, replace: replace2, scroll, shallow, ...rest }) {
|
|
8692
|
-
return (0,
|
|
8741
|
+
return (0, import_react4.createElement)("a", { href: typeof href === "string" ? href : String(href?.pathname || ""), ...rest }, children);
|
|
8693
8742
|
}
|
|
8694
8743
|
|
|
8695
8744
|
// src/designer/SvgHtml.jsx
|
|
8696
|
-
var
|
|
8745
|
+
var import_react5 = __toESM(require_react(), 1);
|
|
8697
8746
|
var import_jsx_runtime2 = __toESM(require_jsx_runtime(), 1);
|
|
8698
8747
|
function SvgHtml({ html, as: Tag2 = "span", ...rest }) {
|
|
8699
|
-
const ref = (0,
|
|
8748
|
+
const ref = (0, import_react5.useRef)(
|
|
8700
8749
|
/** @type {HTMLElement|null} */
|
|
8701
8750
|
null
|
|
8702
8751
|
);
|
|
8703
|
-
(0,
|
|
8752
|
+
(0, import_react5.useLayoutEffect)(() => {
|
|
8704
8753
|
if (!ref.current) return;
|
|
8705
8754
|
ref.current.innerHTML = deferStyleAttributes(html);
|
|
8706
8755
|
applyStyleAttributes(ref.current);
|
|
@@ -8709,7 +8758,7 @@ function SvgHtml({ html, as: Tag2 = "span", ...rest }) {
|
|
|
8709
8758
|
}
|
|
8710
8759
|
|
|
8711
8760
|
// src/designer/Canvas.jsx
|
|
8712
|
-
var
|
|
8761
|
+
var import_react8 = __toESM(require_react(), 1);
|
|
8713
8762
|
|
|
8714
8763
|
// src/designer/tableGen.js
|
|
8715
8764
|
var HEAD = { fontWeight: "bold", backgroundColor: "#f1f5f9", borderBottom: "0.75 solid #94a3b8" };
|
|
@@ -8841,24 +8890,28 @@ function instantPicks(fields, rows = []) {
|
|
|
8841
8890
|
}
|
|
8842
8891
|
|
|
8843
8892
|
// src/designer/Reuse.jsx
|
|
8844
|
-
var
|
|
8893
|
+
var import_react7 = __toESM(require_react(), 1);
|
|
8845
8894
|
|
|
8846
8895
|
// src/designer/Fonts.jsx
|
|
8847
|
-
var
|
|
8896
|
+
var import_react6 = __toESM(require_react(), 1);
|
|
8848
8897
|
var import_jsx_runtime3 = __toESM(require_jsx_runtime(), 1);
|
|
8849
8898
|
function useFontFamilies() {
|
|
8850
8899
|
const fonts = useDesigner((s) => s.fonts);
|
|
8851
8900
|
return [...BUNDLED_FAMILIES, ...[...new Set(fonts.map((f) => f.family))].sort()];
|
|
8852
8901
|
}
|
|
8853
|
-
var refresh = async () =>
|
|
8902
|
+
var refresh = async () => {
|
|
8903
|
+
const api = activeStore2();
|
|
8904
|
+
const fonts = await customFonts(true);
|
|
8905
|
+
api.getState().setUi({ fonts });
|
|
8906
|
+
};
|
|
8854
8907
|
function FontsDialog({ onClose }) {
|
|
8855
8908
|
const fonts = useDesigner((s) => s.fonts);
|
|
8856
|
-
const [file, setFile] = (0,
|
|
8857
|
-
const [family, setFamily] = (0,
|
|
8858
|
-
const [weight, setWeight] = (0,
|
|
8859
|
-
const [style, setStyle] = (0,
|
|
8860
|
-
const [busy, setBusy] = (0,
|
|
8861
|
-
const [msg, setMsg] = (0,
|
|
8909
|
+
const [file, setFile] = (0, import_react6.useState)(null);
|
|
8910
|
+
const [family, setFamily] = (0, import_react6.useState)("");
|
|
8911
|
+
const [weight, setWeight] = (0, import_react6.useState)("");
|
|
8912
|
+
const [style, setStyle] = (0, import_react6.useState)("");
|
|
8913
|
+
const [busy, setBusy] = (0, import_react6.useState)(false);
|
|
8914
|
+
const [msg, setMsg] = (0, import_react6.useState)(null);
|
|
8862
8915
|
const upload = async () => {
|
|
8863
8916
|
if (!file) return;
|
|
8864
8917
|
setBusy(true);
|
|
@@ -8949,30 +9002,33 @@ var apply = (fn3, key2) => S2().apply(fn3, key2);
|
|
|
8949
9002
|
var server = () => S2().embed?.server || "";
|
|
8950
9003
|
var noServer = () => !!S2().embed && !S2().embed.server;
|
|
8951
9004
|
var pending = /* @__PURE__ */ new Map();
|
|
8952
|
-
function fetchReused(id, force = false) {
|
|
9005
|
+
function fetchReused(id, force = false, api = activeStore2()) {
|
|
8953
9006
|
if (!id || typeof id !== "string" || id.startsWith("=")) return Promise.resolve(null);
|
|
8954
|
-
|
|
8955
|
-
if (
|
|
8956
|
-
|
|
8957
|
-
const
|
|
8958
|
-
|
|
8959
|
-
useDesigner.setState((s) => ({ reused: { ...s.reused, [id]: d } }));
|
|
9007
|
+
const st = api.getState();
|
|
9008
|
+
if (!force && st.reused[id]) return Promise.resolve(st.reused[id]);
|
|
9009
|
+
const server2 = st.embed?.server || "", key2 = `${server2} ${id}`;
|
|
9010
|
+
const keep = (d) => {
|
|
9011
|
+
api.setState((s) => ({ reused: { ...s.reused, [id]: d } }));
|
|
8960
9012
|
return d;
|
|
8961
|
-
}
|
|
8962
|
-
pending.
|
|
8963
|
-
return
|
|
9013
|
+
};
|
|
9014
|
+
if (pending.has(key2)) return pending.get(key2).then(keep);
|
|
9015
|
+
if (st.embed && !server2) return Promise.resolve(null);
|
|
9016
|
+
const p = fetch(`${server2}/api/reports/${encodeURIComponent(id)}`).then((r) => r.ok ? r.json() : { __error: `HTTP ${r.status}` }).catch((e) => ({ __error: e.message })).finally(() => pending.delete(key2));
|
|
9017
|
+
pending.set(key2, p);
|
|
9018
|
+
return p.then(keep);
|
|
8964
9019
|
}
|
|
8965
9020
|
function useReused(id) {
|
|
9021
|
+
const api = useDesignerStore();
|
|
8966
9022
|
const d = useDesigner((s) => id ? s.reused[id] : void 0);
|
|
8967
|
-
(0,
|
|
8968
|
-
fetchReused(id);
|
|
8969
|
-
}, [id]);
|
|
9023
|
+
(0, import_react7.useEffect)(() => {
|
|
9024
|
+
fetchReused(id, false, api);
|
|
9025
|
+
}, [id, api]);
|
|
8970
9026
|
return d && !d.__error ? d : null;
|
|
8971
9027
|
}
|
|
8972
9028
|
var listCache = null;
|
|
8973
9029
|
function ReportSelect({ value, onChange, exclude, ...rest }) {
|
|
8974
|
-
const [list2, setList] = (0,
|
|
8975
|
-
(0,
|
|
9030
|
+
const [list2, setList] = (0, import_react7.useState)(listCache || []);
|
|
9031
|
+
(0, import_react7.useEffect)(() => {
|
|
8976
9032
|
if (noServer()) return;
|
|
8977
9033
|
fetch(`${server()}/api/reports`).then((r) => r.ok ? r.json() : []).then((l) => {
|
|
8978
9034
|
listCache = Array.isArray(l) ? l : [];
|
|
@@ -9039,7 +9095,7 @@ function ThemeSection() {
|
|
|
9039
9095
|
const id = useDesigner((s) => s.id);
|
|
9040
9096
|
const families = useFontFamilies();
|
|
9041
9097
|
const src = def.theme;
|
|
9042
|
-
const [mode, setMode] = (0,
|
|
9098
|
+
const [mode, setMode] = (0, import_react7.useState)(!src ? "own" : String(src).startsWith("=") ? "expr" : "report");
|
|
9043
9099
|
const td = def.themeDef || {};
|
|
9044
9100
|
const setTd = (fn3, key2) => apply((d) => {
|
|
9045
9101
|
d.themeDef || (d.themeDef = {});
|
|
@@ -9058,7 +9114,7 @@ function ThemeSection() {
|
|
|
9058
9114
|
else x.fonts[k][p] = v;
|
|
9059
9115
|
}, `theme.font.${k}.${p}`);
|
|
9060
9116
|
const consts = Object.entries(td.constants || {});
|
|
9061
|
-
const [newConst, setNewConst] = (0,
|
|
9117
|
+
const [newConst, setNewConst] = (0, import_react7.useState)("");
|
|
9062
9118
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "cat", "data-testid": "theme", children: [
|
|
9063
9119
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CatHead, { children: T("theme") }),
|
|
9064
9120
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Field, { label: T("themeSource"), children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
@@ -9118,7 +9174,7 @@ function LayersPanel() {
|
|
|
9118
9174
|
const T = useT2();
|
|
9119
9175
|
const layers = useDesigner((s) => s.def.layers) || [];
|
|
9120
9176
|
const readOnly2 = useDesigner((s) => s.readOnly);
|
|
9121
|
-
const [name2, setName] = (0,
|
|
9177
|
+
const [name2, setName] = (0, import_react7.useState)("");
|
|
9122
9178
|
const set2 = (fn3, key2) => apply((d) => {
|
|
9123
9179
|
d.layers || (d.layers = []);
|
|
9124
9180
|
fn3(d.layers, d);
|
|
@@ -9273,7 +9329,7 @@ function PartsPanel() {
|
|
|
9273
9329
|
const libs = useDesigner((s) => s.def.libraries) || [];
|
|
9274
9330
|
const id = useDesigner((s) => s.id);
|
|
9275
9331
|
const readOnly2 = useDesigner((s) => s.readOnly);
|
|
9276
|
-
const [pick, setPick] = (0,
|
|
9332
|
+
const [pick, setPick] = (0, import_react7.useState)("");
|
|
9277
9333
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "pane", "data-testid": "parts-panel", children: [
|
|
9278
9334
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("h4", { children: [
|
|
9279
9335
|
T("parts"),
|
|
@@ -9402,7 +9458,7 @@ function PublishPart({ item }) {
|
|
|
9402
9458
|
if (v === void 0 || v === "") delete q2[k];
|
|
9403
9459
|
else q2[k] = v;
|
|
9404
9460
|
}, `part${i2}.q${j}.${k}`);
|
|
9405
|
-
const [newProp, setNewProp] = (0,
|
|
9461
|
+
const [newProp, setNewProp] = (0, import_react7.useState)("");
|
|
9406
9462
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "cat", "data-testid": "publish-part", children: [
|
|
9407
9463
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CatHead, { children: T("reportPart") }),
|
|
9408
9464
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Check, { label: T("publishPart"), checked: !!p, onChange: (on) => set2((l) => {
|
|
@@ -9531,12 +9587,12 @@ function useDesignIssues() {
|
|
|
9531
9587
|
const def = useDesigner((s) => s.def);
|
|
9532
9588
|
const extents = useDesigner((s) => s.extents);
|
|
9533
9589
|
const saveCheck = useDesigner((s) => s.saveCheck);
|
|
9534
|
-
return (0,
|
|
9590
|
+
return (0, import_react8.useMemo)(() => {
|
|
9535
9591
|
const bands = sectionList(def).map((s) => ({ key: s.key, items: secOf(def, s.key)?.items || [], width: bodyWidth(def, s.key) }));
|
|
9536
9592
|
return [...designIssues(def, bands, extents || {}), ...checkIssues(bands, [...validate(def).errors, ...saveCheck?.missing || []])];
|
|
9537
9593
|
}, [def, extents, saveCheck]);
|
|
9538
9594
|
}
|
|
9539
|
-
var IssueMap = (0,
|
|
9595
|
+
var IssueMap = (0, import_react8.createContext)(/* @__PURE__ */ new Map());
|
|
9540
9596
|
function issueLine(T, i2) {
|
|
9541
9597
|
if (i2.kind === "overlap") return T("ux_issueOverlap", { name: i2.name, other: i2.other });
|
|
9542
9598
|
if (i2.kind === "wide") return T("ux_issueWide", { name: i2.name, width: i2.width, room: i2.room });
|
|
@@ -9601,9 +9657,9 @@ function Canvas() {
|
|
|
9601
9657
|
const bands = sectionList(def);
|
|
9602
9658
|
const widths2 = Object.fromEntries(bands.map((s) => [s.key, bodyWidth(def, s.key)]));
|
|
9603
9659
|
const bw = Math.max(...Object.values(widths2));
|
|
9604
|
-
const scrollRef = (0,
|
|
9605
|
-
const [fitW, setFitW] = (0,
|
|
9606
|
-
(0,
|
|
9660
|
+
const scrollRef = (0, import_react8.useRef)(null);
|
|
9661
|
+
const [fitW, setFitW] = (0, import_react8.useState)(0);
|
|
9662
|
+
(0, import_react8.useEffect)(() => {
|
|
9607
9663
|
if (zoom !== "fit" || !scrollRef.current) return;
|
|
9608
9664
|
const el = scrollRef.current;
|
|
9609
9665
|
const ro = new ResizeObserver(() => setFitW(el.clientWidth));
|
|
@@ -9611,10 +9667,10 @@ function Canvas() {
|
|
|
9611
9667
|
return () => ro.disconnect();
|
|
9612
9668
|
}, [zoom]);
|
|
9613
9669
|
const scale = zoom === "fit" ? Math.max(0.3, Math.min(3, ((fitW || 900) - 80) / bw)) : zoom * PX;
|
|
9614
|
-
const [drag, setDrag] = (0,
|
|
9670
|
+
const [drag, setDrag] = (0, import_react8.useState)(null);
|
|
9615
9671
|
const T = useT2();
|
|
9616
9672
|
const issues = useDesignIssues();
|
|
9617
|
-
const byId = (0,
|
|
9673
|
+
const byId = (0, import_react8.useMemo)(() => {
|
|
9618
9674
|
const m = /* @__PURE__ */ new Map();
|
|
9619
9675
|
for (const i2 of issues) m.set(i2.id, [...m.get(i2.id) || [], issueLine(T, i2)]);
|
|
9620
9676
|
return m;
|
|
@@ -9695,9 +9751,9 @@ function Band({ section, label, scale, bw: bandW, drag, setDrag, phBox = null })
|
|
|
9695
9751
|
const off = phBox || mb?.off || null;
|
|
9696
9752
|
const contentList = useDesigner((s) => s.def.sections?.content);
|
|
9697
9753
|
const bw = off?.w || bandW;
|
|
9698
|
-
const ref = (0,
|
|
9699
|
-
const [marquee, setMarquee] = (0,
|
|
9700
|
-
const [dropping, setDropping] = (0,
|
|
9754
|
+
const ref = (0, import_react8.useRef)(null);
|
|
9755
|
+
const [marquee, setMarquee] = (0, import_react8.useState)(null);
|
|
9756
|
+
const [dropping, setDropping] = (0, import_react8.useState)(false);
|
|
9701
9757
|
const h = drag?.mode === "band" && drag.section === section ? drag.h : sec.height || 0;
|
|
9702
9758
|
const DROP_ROOM = 96;
|
|
9703
9759
|
const toPt3 = (e) => {
|
|
@@ -9871,8 +9927,9 @@ var alerted = 0;
|
|
|
9871
9927
|
function alertOnce(msg) {
|
|
9872
9928
|
if (Date.now() - alerted > 3e3) {
|
|
9873
9929
|
alerted = Date.now();
|
|
9874
|
-
|
|
9875
|
-
|
|
9930
|
+
const api = activeStore2();
|
|
9931
|
+
api.setState({ saveError: msg });
|
|
9932
|
+
setTimeout(() => api.setState({ saveError: null }), 3e3);
|
|
9876
9933
|
}
|
|
9877
9934
|
}
|
|
9878
9935
|
function fieldStyle(f) {
|
|
@@ -9880,11 +9937,31 @@ function fieldStyle(f) {
|
|
|
9880
9937
|
const format = formatFor({ name: f.field, type: f.type }, (st.sample?.dataSets?.[f.dataSet] || []).slice(0, 200), { currency: st.def?.currency });
|
|
9881
9938
|
return format ? { format } : {};
|
|
9882
9939
|
}
|
|
9940
|
+
function useItemKeys(item) {
|
|
9941
|
+
const T = useT2();
|
|
9942
|
+
const type = T(`item_${item.type}`) === `item_${item.type}` ? ITEMS[item.type]?.label || item.type : T(`item_${item.type}`);
|
|
9943
|
+
return {
|
|
9944
|
+
tabIndex: 0,
|
|
9945
|
+
role: "group",
|
|
9946
|
+
"data-item-key": item.id,
|
|
9947
|
+
"aria-label": T("b9_itemLabel", { type, name: item.name, x: round(item.x), y: round(item.y) }),
|
|
9948
|
+
onKeyDown: (e) => {
|
|
9949
|
+
if (e.target !== e.currentTarget || e.key !== "Enter" && e.key !== " ") return;
|
|
9950
|
+
e.preventDefault();
|
|
9951
|
+
e.stopPropagation();
|
|
9952
|
+
const st = useDesigner.getState();
|
|
9953
|
+
const cur2 = st.sel.kind === "items" ? st.sel.ids : [];
|
|
9954
|
+
const ids = !e.shiftKey ? [item.id] : cur2.includes(item.id) ? cur2.filter((i2) => i2 !== item.id) : [...cur2, item.id];
|
|
9955
|
+
st.select(ids.length ? { kind: "items", ids } : { kind: "report" });
|
|
9956
|
+
}
|
|
9957
|
+
};
|
|
9958
|
+
}
|
|
9883
9959
|
function useItemDrag(item, scale, setDrag) {
|
|
9884
9960
|
return (e) => {
|
|
9885
9961
|
if (e.button !== 0) return;
|
|
9886
9962
|
e.preventDefault();
|
|
9887
9963
|
e.stopPropagation();
|
|
9964
|
+
e.currentTarget.closest?.("[data-item-key]")?.focus({ preventScroll: true });
|
|
9888
9965
|
const st = useDesigner.getState();
|
|
9889
9966
|
let ids;
|
|
9890
9967
|
if (e.shiftKey) {
|
|
@@ -9957,8 +10034,8 @@ function AnyItem(props) {
|
|
|
9957
10034
|
return layer?.locked ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "layer-locked", "data-locked": props.item.name, children: el }) : el;
|
|
9958
10035
|
}
|
|
9959
10036
|
function NestChildren({ item, scale, drag, setDrag, section }) {
|
|
9960
|
-
const ref = (0,
|
|
9961
|
-
const [over, setOver] = (0,
|
|
10037
|
+
const ref = (0, import_react8.useRef)(null);
|
|
10038
|
+
const [over, setOver] = (0, import_react8.useState)(false);
|
|
9962
10039
|
const accepts = (e) => e.dataTransfer.types.includes(MIME_TOOL) || e.dataTransfer.types.includes(MIME_FIELD) || e.dataTransfer.types.includes(MIME_PART);
|
|
9963
10040
|
const onDrop = (e) => {
|
|
9964
10041
|
setOver(false);
|
|
@@ -10003,8 +10080,9 @@ function ItemView({ item, scale, drag, setDrag, bw, nest, section }) {
|
|
|
10003
10080
|
const selected = useDesigner((s) => s.sel.kind === "items" && s.sel.ids.includes(item.id));
|
|
10004
10081
|
const single = useDesigner((s) => s.sel.kind === "items" && s.sel.ids.length === 1);
|
|
10005
10082
|
const onDown = useItemDrag(item, scale, setDrag);
|
|
10083
|
+
const keys = useItemKeys(item);
|
|
10006
10084
|
const r = rectOf(item, drag);
|
|
10007
|
-
const problems = (0,
|
|
10085
|
+
const problems = (0, import_react8.useContext)(IssueMap).get(item.id);
|
|
10008
10086
|
const onHandle = (dir) => (e) => {
|
|
10009
10087
|
e.preventDefault();
|
|
10010
10088
|
e.stopPropagation();
|
|
@@ -10063,6 +10141,7 @@ function ItemView({ item, scale, drag, setDrag, bw, nest, section }) {
|
|
|
10063
10141
|
title: problems?.join("\n"),
|
|
10064
10142
|
style: { left: r.x * scale, top: r.y * scale, width: Math.max(r.w * scale, 2), height: Math.max(r.h * scale, 2) },
|
|
10065
10143
|
onPointerDown: onDown,
|
|
10144
|
+
...keys,
|
|
10066
10145
|
children: [
|
|
10067
10146
|
nest ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(NestBox, { item: { ...item, ...r }, scale }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ItemBody, { item: { ...item, ...r }, scale }),
|
|
10068
10147
|
nest && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(NestChildren, { item, scale, drag, setDrag, section }),
|
|
@@ -10080,8 +10159,8 @@ function NestBox({ item, scale }) {
|
|
|
10080
10159
|
}
|
|
10081
10160
|
var LIVE = /* @__PURE__ */ new Set(["chart", "matrix", "barcode", "sparkline", "databar", "bullet", "iconset", "rangebar", "richtext"]);
|
|
10082
10161
|
var measurer = null;
|
|
10083
|
-
async function paintItemSvg(shape2, def, sample) {
|
|
10084
|
-
const store =
|
|
10162
|
+
async function paintItemSvg(shape2, def, sample, api = activeStore2()) {
|
|
10163
|
+
const store = await loadFontStore();
|
|
10085
10164
|
await Promise.all([store.load(), customFonts()]);
|
|
10086
10165
|
if (shape2.type === "barcode" || hasType(shape2.items, "barcode")) await loadBarcodes();
|
|
10087
10166
|
measurer || (measurer = new TextMeasurer(store));
|
|
@@ -10092,7 +10171,7 @@ async function paintItemSvg(shape2, def, sample) {
|
|
|
10092
10171
|
} catch {
|
|
10093
10172
|
}
|
|
10094
10173
|
const base2 = { fontFamily: "Inter", fontSize: 9, color: "#1f2937", padding: 2, lineHeight: 1.25, textAlign: "auto", verticalAlign: "top", ...def.styles?.base || {} };
|
|
10095
|
-
const theme3 = themeContext(typeof def.theme === "string" &&
|
|
10174
|
+
const theme3 = themeContext(typeof def.theme === "string" && api.getState().reused[def.theme]?.themeDef || def.themeDef);
|
|
10096
10175
|
const ctxBase = { params, globals: { PageNumber: 1, TotalPages: 1, ExecutionTime: /* @__PURE__ */ new Date(), ReportName: def.name }, dataSets, fields: null, locale: def.locale, currency: def.currency, functions: functionTable(def), theme: theme3 };
|
|
10097
10176
|
let seq = 0;
|
|
10098
10177
|
const lc = {
|
|
@@ -10134,20 +10213,21 @@ async function paintItemSvg(shape2, def, sample) {
|
|
|
10134
10213
|
return { html: pageToSvg({ items }, shape2.w, h, { background: false }), h, w };
|
|
10135
10214
|
}
|
|
10136
10215
|
function LivePreview({ item, scale }) {
|
|
10216
|
+
const api = useDesignerStore();
|
|
10137
10217
|
const sample = useDesigner((s) => s.sample);
|
|
10138
10218
|
const def = useDesigner((s) => s.def);
|
|
10139
|
-
const [svg, setSvg] = (0,
|
|
10219
|
+
const [svg, setSvg] = (0, import_react8.useState)(null);
|
|
10140
10220
|
const { x, y, ...shape2 } = item;
|
|
10141
10221
|
const key2 = JSON.stringify(shape2);
|
|
10142
|
-
(0,
|
|
10222
|
+
(0, import_react8.useEffect)(() => {
|
|
10143
10223
|
let alive = true;
|
|
10144
10224
|
const t3 = setTimeout(async () => {
|
|
10145
10225
|
try {
|
|
10146
|
-
const out = await paintItemSvg(shape2, def, sample);
|
|
10226
|
+
const out = await paintItemSvg(shape2, def, sample, api);
|
|
10147
10227
|
if (alive) {
|
|
10148
10228
|
setSvg(out);
|
|
10149
|
-
const ex2 =
|
|
10150
|
-
if (Math.round(ex2[item.id]?.w || 0) !== Math.round(out.w))
|
|
10229
|
+
const ex2 = api.getState().extents || {};
|
|
10230
|
+
if (Math.round(ex2[item.id]?.w || 0) !== Math.round(out.w)) api.setState({ extents: { ...ex2, [item.id]: { w: out.w } } });
|
|
10151
10231
|
}
|
|
10152
10232
|
} catch (e) {
|
|
10153
10233
|
if (alive) setSvg({ error: e.message });
|
|
@@ -10169,9 +10249,9 @@ function PartPreview({ item, scale }) {
|
|
|
10169
10249
|
const p = (lib?.parts || []).find((q2) => q2.name === item.part);
|
|
10170
10250
|
const src = p && findItemNamed(lib, p.item);
|
|
10171
10251
|
const props = { ...Object.fromEntries((p?.properties || []).map((q2) => [q2.name, q2.default ?? null])), ...item.properties || {} };
|
|
10172
|
-
const [svg, setSvg] = (0,
|
|
10252
|
+
const [svg, setSvg] = (0, import_react8.useState)(null);
|
|
10173
10253
|
const key2 = JSON.stringify([src, props]);
|
|
10174
|
-
(0,
|
|
10254
|
+
(0, import_react8.useEffect)(() => {
|
|
10175
10255
|
if (!src) return void 0;
|
|
10176
10256
|
let alive = true;
|
|
10177
10257
|
const t3 = setTimeout(() => {
|
|
@@ -10281,17 +10361,18 @@ function TableView({ item, scale, drag, setDrag }) {
|
|
|
10281
10361
|
const readOnly2 = useDesigner((s) => s.readOnly);
|
|
10282
10362
|
const tableSelected = sel.kind === "items" && sel.ids.includes(item.id);
|
|
10283
10363
|
const onGrip = useItemDrag(item, scale, setDrag);
|
|
10364
|
+
const keys = useItemKeys(item);
|
|
10284
10365
|
const r = rectOf(item, drag);
|
|
10285
10366
|
const widths2 = item.columns.map((c, i2) => drag?.mode === "col" && drag.id === item.id && drag.col === i2 ? drag.w : c.width);
|
|
10286
|
-
const [dropCell, setDropCell] = (0,
|
|
10287
|
-
const [menu, setMenu] = (0,
|
|
10288
|
-
const problems = (0,
|
|
10289
|
-
const tblRef = (0,
|
|
10367
|
+
const [dropCell, setDropCell] = (0, import_react8.useState)(null);
|
|
10368
|
+
const [menu, setMenu] = (0, import_react8.useState)(null);
|
|
10369
|
+
const problems = (0, import_react8.useContext)(IssueMap).get(item.id);
|
|
10370
|
+
const tblRef = (0, import_react8.useRef)(null);
|
|
10290
10371
|
const chosen = sel.kind === "cell" && sel.id === item.id ? selCells(sel) : [];
|
|
10291
|
-
(0,
|
|
10372
|
+
(0, import_react8.useEffect)(() => {
|
|
10292
10373
|
if (!menu) return void 0;
|
|
10293
10374
|
const close = (e) => {
|
|
10294
|
-
if (e.type === "keydown" ? e.key === "Escape" : !e.
|
|
10375
|
+
if (e.type === "keydown" ? e.key === "Escape" : !e.composedPath().some((n) => n.classList?.contains("cell-menu"))) setMenu(null);
|
|
10295
10376
|
};
|
|
10296
10377
|
window.addEventListener("pointerdown", close, true);
|
|
10297
10378
|
window.addEventListener("keydown", close);
|
|
@@ -10304,6 +10385,7 @@ function TableView({ item, scale, drag, setDrag }) {
|
|
|
10304
10385
|
e.stopPropagation();
|
|
10305
10386
|
if (e.button !== 0) return;
|
|
10306
10387
|
e.preventDefault();
|
|
10388
|
+
e.currentTarget.closest("[data-item-key]")?.focus({ preventScroll: true });
|
|
10307
10389
|
const st = useDesigner.getState();
|
|
10308
10390
|
const here = { part, row: ri, col: ci };
|
|
10309
10391
|
const cur2 = st.sel.kind === "cell" && st.sel.id === item.id ? st.sel : null;
|
|
@@ -10379,7 +10461,7 @@ function TableView({ item, scale, drag, setDrag }) {
|
|
|
10379
10461
|
const h = t3.header?.[t3.header.length - 1]?.cells?.[ci];
|
|
10380
10462
|
if (h && (!h.value || /^Column \d+$/.test(h.value))) h.value = f.field.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/^./, (c) => c.toUpperCase());
|
|
10381
10463
|
if (h && f.type === "number") h.style = { ...h.style || {}, textAlign: "right" };
|
|
10382
|
-
} else if ((part === "footer" || /^g\d+
|
|
10464
|
+
} else if ((part === "footer" || /^g\d+[hf]$/.test(part)) && f.type === "number") {
|
|
10383
10465
|
cell.value = `=Sum(Fields.${f.field})`;
|
|
10384
10466
|
cell.style = { ...cell.style || {}, ...fieldStyle(f) };
|
|
10385
10467
|
} else cell.value = `=Fields.${f.field}`;
|
|
@@ -10387,7 +10469,7 @@ function TableView({ item, scale, drag, setDrag }) {
|
|
|
10387
10469
|
useDesigner.getState().select({ kind: "cell", id: item.id, part, row: ri, col: ci });
|
|
10388
10470
|
};
|
|
10389
10471
|
let first = true;
|
|
10390
|
-
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { ref: tblRef, className: `tbl${tableSelected ? " sel" : ""}${problems ? " issue" : ""}`, "data-item": item.name, style: { left: r.x * scale, top: r.y * scale }, children: [
|
|
10472
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { ref: tblRef, className: `tbl${tableSelected ? " sel" : ""}${problems ? " issue" : ""}`, "data-item": item.name, style: { left: r.x * scale, top: r.y * scale }, ...keys, children: [
|
|
10391
10473
|
problems && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "issue-tag", title: problems.join("\n"), "aria-label": problems.join(". "), children: "!" }),
|
|
10392
10474
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "grip", title: "Select or move the table", onPointerDown: onGrip, children: "⠿" }),
|
|
10393
10475
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "col-handles", "aria-label": T("ux_columns"), role: "group", children: widths2.map((w, ci) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
@@ -10517,13 +10599,13 @@ function TableView({ item, scale, drag, setDrag }) {
|
|
|
10517
10599
|
}
|
|
10518
10600
|
|
|
10519
10601
|
// src/designer/Inspector.jsx
|
|
10520
|
-
var
|
|
10602
|
+
var import_react12 = __toESM(require_react(), 1);
|
|
10521
10603
|
|
|
10522
10604
|
// src/designer/ExpressionEditor.jsx
|
|
10523
|
-
var
|
|
10605
|
+
var import_react10 = __toESM(require_react(), 1);
|
|
10524
10606
|
|
|
10525
10607
|
// src/designer/ExprCode.jsx
|
|
10526
|
-
var
|
|
10608
|
+
var import_react9 = __toESM(require_react(), 1);
|
|
10527
10609
|
|
|
10528
10610
|
// node_modules/@marijn/find-cluster-break/src/index.js
|
|
10529
10611
|
var rangeFrom = [];
|
|
@@ -12267,8 +12349,8 @@ var StateField = class _StateField {
|
|
|
12267
12349
|
way it is initialized. Can be useful when you need to provide a
|
|
12268
12350
|
non-default starting value for the field.
|
|
12269
12351
|
*/
|
|
12270
|
-
init(
|
|
12271
|
-
return [this, initField.of({ field: this, create
|
|
12352
|
+
init(create) {
|
|
12353
|
+
return [this, initField.of({ field: this, create })];
|
|
12272
12354
|
}
|
|
12273
12355
|
/**
|
|
12274
12356
|
State field instances can be used as
|
|
@@ -13496,10 +13578,10 @@ var RangeSet = class _RangeSet {
|
|
|
13496
13578
|
for (; ; ) {
|
|
13497
13579
|
let curTo = Math.min(cursor.to, to);
|
|
13498
13580
|
if (cursor.point) {
|
|
13499
|
-
let
|
|
13500
|
-
let openCount = cursor.pointFrom < from ?
|
|
13501
|
-
iterator.point(pos, curTo, cursor.point,
|
|
13502
|
-
openRanges = Math.min(cursor.openEnd(curTo),
|
|
13581
|
+
let active2 = cursor.activeForPoint(cursor.to);
|
|
13582
|
+
let openCount = cursor.pointFrom < from ? active2.length + 1 : cursor.point.startSide < 0 ? active2.length : Math.min(active2.length, openRanges);
|
|
13583
|
+
iterator.point(pos, curTo, cursor.point, active2, openCount, cursor.pointRank);
|
|
13584
|
+
openRanges = Math.min(cursor.openEnd(curTo), active2.length);
|
|
13503
13585
|
} else if (curTo > pos) {
|
|
13504
13586
|
iterator.span(pos, curTo, cursor.active, openRanges);
|
|
13505
13587
|
openRanges = cursor.openEnd(curTo);
|
|
@@ -13913,14 +13995,14 @@ var SpanCursor = class {
|
|
|
13913
13995
|
activeForPoint(to) {
|
|
13914
13996
|
if (!this.active.length)
|
|
13915
13997
|
return this.active;
|
|
13916
|
-
let
|
|
13998
|
+
let active2 = [];
|
|
13917
13999
|
for (let i2 = this.active.length - 1; i2 >= 0; i2--) {
|
|
13918
14000
|
if (this.activeRank[i2] < this.pointRank)
|
|
13919
14001
|
break;
|
|
13920
14002
|
if (this.activeTo[i2] > to || this.activeTo[i2] == to && this.active[i2].endSide >= this.point.endSide)
|
|
13921
|
-
|
|
14003
|
+
active2.push(this.active[i2]);
|
|
13922
14004
|
}
|
|
13923
|
-
return
|
|
14005
|
+
return active2.reverse();
|
|
13924
14006
|
}
|
|
13925
14007
|
openEnd(to) {
|
|
13926
14008
|
let open = 0;
|
|
@@ -15439,9 +15521,9 @@ var viewPlugin = /* @__PURE__ */ Facet.define({
|
|
|
15439
15521
|
}
|
|
15440
15522
|
});
|
|
15441
15523
|
var ViewPlugin = class _ViewPlugin {
|
|
15442
|
-
constructor(id,
|
|
15524
|
+
constructor(id, create, domEventHandlers, domEventObservers, buildExtensions) {
|
|
15443
15525
|
this.id = id;
|
|
15444
|
-
this.create =
|
|
15526
|
+
this.create = create;
|
|
15445
15527
|
this.domEventHandlers = domEventHandlers;
|
|
15446
15528
|
this.domEventObservers = domEventObservers;
|
|
15447
15529
|
this.baseExtensions = buildExtensions(this);
|
|
@@ -15457,9 +15539,9 @@ var ViewPlugin = class _ViewPlugin {
|
|
|
15457
15539
|
Define a plugin from a constructor function that creates the
|
|
15458
15540
|
plugin's value, given an editor view.
|
|
15459
15541
|
*/
|
|
15460
|
-
static define(
|
|
15542
|
+
static define(create, spec) {
|
|
15461
15543
|
const { eventHandlers, eventObservers, provide, decorations: deco } = spec || {};
|
|
15462
|
-
return new _ViewPlugin(nextPluginID++,
|
|
15544
|
+
return new _ViewPlugin(nextPluginID++, create, eventHandlers, eventObservers, (plugin) => {
|
|
15463
15545
|
let ext = [];
|
|
15464
15546
|
if (deco)
|
|
15465
15547
|
ext.push(decorations.of((view) => {
|
|
@@ -15547,11 +15629,11 @@ function getIsolatedRanges(view, line2) {
|
|
|
15547
15629
|
RangeSet.spans(sets, line2.from, line2.to, {
|
|
15548
15630
|
point() {
|
|
15549
15631
|
},
|
|
15550
|
-
span(fromDoc, toDoc,
|
|
15632
|
+
span(fromDoc, toDoc, active2, open) {
|
|
15551
15633
|
let from = fromDoc - line2.from, to = toDoc - line2.from;
|
|
15552
15634
|
let level = result;
|
|
15553
|
-
for (let i2 =
|
|
15554
|
-
let direction =
|
|
15635
|
+
for (let i2 = active2.length - 1; i2 >= 0; i2--, open--) {
|
|
15636
|
+
let direction = active2[i2].spec.bidiIsolate, update;
|
|
15555
15637
|
if (direction == null)
|
|
15556
15638
|
direction = autoDirection(line2.text, from, to);
|
|
15557
15639
|
if (open > 0 && level.length && (update = level[level.length - 1]).to == from && update.direction == direction) {
|
|
@@ -16781,7 +16863,7 @@ var TileUpdate = class {
|
|
|
16781
16863
|
let pendingLineAttrs = null;
|
|
16782
16864
|
let b = this.builder, markCount = -1;
|
|
16783
16865
|
let openEnd = RangeSet.spans(this.decorations, from, to, {
|
|
16784
|
-
point: (from2, to2, deco,
|
|
16866
|
+
point: (from2, to2, deco, active2, openStart, index) => {
|
|
16785
16867
|
if (deco instanceof PointDecoration) {
|
|
16786
16868
|
if (this.disallowBlockEffectsFor[index]) {
|
|
16787
16869
|
if (deco.block)
|
|
@@ -16789,8 +16871,8 @@ var TileUpdate = class {
|
|
|
16789
16871
|
if (to2 > this.view.state.doc.lineAt(from2).to)
|
|
16790
16872
|
throw new RangeError("Decorations that replace line breaks may not be specified via plugins");
|
|
16791
16873
|
}
|
|
16792
|
-
markCount =
|
|
16793
|
-
if (openStart >
|
|
16874
|
+
markCount = active2.length;
|
|
16875
|
+
if (openStart > active2.length) {
|
|
16794
16876
|
b.continueWidget(to2 - from2);
|
|
16795
16877
|
} else {
|
|
16796
16878
|
let widget = deco.widget || (deco.block ? NullWidget.block : NullWidget.inline);
|
|
@@ -16802,7 +16884,7 @@ var TileUpdate = class {
|
|
|
16802
16884
|
b.addBlockWidget(tile);
|
|
16803
16885
|
} else {
|
|
16804
16886
|
b.ensureLine(pendingLineAttrs);
|
|
16805
|
-
b.addInlineWidget(tile,
|
|
16887
|
+
b.addInlineWidget(tile, active2, openStart);
|
|
16806
16888
|
}
|
|
16807
16889
|
}
|
|
16808
16890
|
pendingLineAttrs = null;
|
|
@@ -16812,7 +16894,7 @@ var TileUpdate = class {
|
|
|
16812
16894
|
if (to2 > from2)
|
|
16813
16895
|
this.text.skip(to2 - from2);
|
|
16814
16896
|
},
|
|
16815
|
-
span: (from2, to2,
|
|
16897
|
+
span: (from2, to2, active2, openStart) => {
|
|
16816
16898
|
for (let pos = from2; pos < to2; ) {
|
|
16817
16899
|
let chars = this.text.next(Math.min(512, to2 - pos));
|
|
16818
16900
|
if (chars == null) {
|
|
@@ -16821,12 +16903,12 @@ var TileUpdate = class {
|
|
|
16821
16903
|
pos++;
|
|
16822
16904
|
} else {
|
|
16823
16905
|
b.ensureLine(pendingLineAttrs);
|
|
16824
|
-
b.addText(chars,
|
|
16906
|
+
b.addText(chars, active2, pos == from2 ? openStart : active2.length);
|
|
16825
16907
|
pos += chars.length;
|
|
16826
16908
|
}
|
|
16827
16909
|
pendingLineAttrs = null;
|
|
16828
16910
|
}
|
|
16829
|
-
markCount =
|
|
16911
|
+
markCount = active2.length;
|
|
16830
16912
|
}
|
|
16831
16913
|
});
|
|
16832
16914
|
if (markCount > -1)
|
|
@@ -18815,9 +18897,9 @@ handlers.mousedown = (view, event) => {
|
|
|
18815
18897
|
if (mustFocus)
|
|
18816
18898
|
view.observer.ignore(() => {
|
|
18817
18899
|
focusPreventScroll(view.contentDOM);
|
|
18818
|
-
let
|
|
18819
|
-
if (
|
|
18820
|
-
|
|
18900
|
+
let active2 = view.root.activeElement;
|
|
18901
|
+
if (active2 && !active2.contains(view.contentDOM))
|
|
18902
|
+
active2.blur();
|
|
18821
18903
|
});
|
|
18822
18904
|
let mouseSel = view.inputState.mouseSelection;
|
|
18823
18905
|
if (mouseSel) {
|
|
@@ -28860,7 +28942,7 @@ function scrollIntoView2(container2, element) {
|
|
|
28860
28942
|
function score(option) {
|
|
28861
28943
|
return (option.boost || 0) * 100 + (option.apply ? 10 : 0) + (option.info ? 5 : 0) + (option.type ? 1 : 0);
|
|
28862
28944
|
}
|
|
28863
|
-
function sortOptions(
|
|
28945
|
+
function sortOptions(active2, state) {
|
|
28864
28946
|
let options = [];
|
|
28865
28947
|
let sections = null, dynamicSectionScore = null;
|
|
28866
28948
|
let addOption = (option) => {
|
|
@@ -28875,7 +28957,7 @@ function sortOptions(active, state) {
|
|
|
28875
28957
|
}
|
|
28876
28958
|
};
|
|
28877
28959
|
let conf = state.facet(completionConfig);
|
|
28878
|
-
for (let a of
|
|
28960
|
+
for (let a of active2)
|
|
28879
28961
|
if (a.hasResult()) {
|
|
28880
28962
|
let getMatch = a.result.getMatch;
|
|
28881
28963
|
if (a.result.filter === false) {
|
|
@@ -28938,12 +29020,12 @@ var CompletionDialog = class _CompletionDialog {
|
|
|
28938
29020
|
setSelected(selected, id) {
|
|
28939
29021
|
return selected == this.selected || selected >= this.options.length ? this : new _CompletionDialog(this.options, makeAttrs(id, selected), this.tooltip, this.timestamp, selected, this.disabled);
|
|
28940
29022
|
}
|
|
28941
|
-
static build(
|
|
28942
|
-
if (prev && !didSetActive &&
|
|
29023
|
+
static build(active2, state, id, prev, conf, didSetActive) {
|
|
29024
|
+
if (prev && !didSetActive && active2.some((s) => s.isPending))
|
|
28943
29025
|
return prev.setDisabled();
|
|
28944
|
-
let options = sortOptions(
|
|
29026
|
+
let options = sortOptions(active2, state);
|
|
28945
29027
|
if (!options.length)
|
|
28946
|
-
return prev &&
|
|
29028
|
+
return prev && active2.some((a) => a.isPending) ? prev.setDisabled() : null;
|
|
28947
29029
|
let selected = state.facet(completionConfig).selectOnOpen ? 0 : -1;
|
|
28948
29030
|
if (prev && prev.selected != selected && prev.selected != -1) {
|
|
28949
29031
|
let selectedValue = prev.options[prev.selected].completion;
|
|
@@ -28954,7 +29036,7 @@ var CompletionDialog = class _CompletionDialog {
|
|
|
28954
29036
|
}
|
|
28955
29037
|
}
|
|
28956
29038
|
return new _CompletionDialog(options, makeAttrs(id, selected), {
|
|
28957
|
-
pos:
|
|
29039
|
+
pos: active2.reduce((a, b) => b.hasResult() ? Math.min(a, b.from) : a, 1e8),
|
|
28958
29040
|
create: createTooltip,
|
|
28959
29041
|
above: conf.aboveCursor
|
|
28960
29042
|
}, prev ? prev.timestamp : Date.now(), selected, false);
|
|
@@ -28967,8 +29049,8 @@ var CompletionDialog = class _CompletionDialog {
|
|
|
28967
29049
|
}
|
|
28968
29050
|
};
|
|
28969
29051
|
var CompletionState = class _CompletionState {
|
|
28970
|
-
constructor(
|
|
28971
|
-
this.active =
|
|
29052
|
+
constructor(active2, id, open) {
|
|
29053
|
+
this.active = active2;
|
|
28972
29054
|
this.id = id;
|
|
28973
29055
|
this.open = open;
|
|
28974
29056
|
}
|
|
@@ -28978,7 +29060,7 @@ var CompletionState = class _CompletionState {
|
|
|
28978
29060
|
update(tr) {
|
|
28979
29061
|
let { state } = tr, conf = state.facet(completionConfig);
|
|
28980
29062
|
let sources = conf.override || state.languageDataAt("autocomplete", cur(state)).map(asSource);
|
|
28981
|
-
let
|
|
29063
|
+
let active2 = sources.map((source) => {
|
|
28982
29064
|
let value = this.active.find((s) => s.source == source) || new ActiveSource(
|
|
28983
29065
|
source,
|
|
28984
29066
|
this.active.some(
|
|
@@ -28989,17 +29071,17 @@ var CompletionState = class _CompletionState {
|
|
|
28989
29071
|
);
|
|
28990
29072
|
return value.update(tr, conf);
|
|
28991
29073
|
});
|
|
28992
|
-
if (
|
|
28993
|
-
|
|
29074
|
+
if (active2.length == this.active.length && active2.every((a, i2) => a == this.active[i2]))
|
|
29075
|
+
active2 = this.active;
|
|
28994
29076
|
let open = this.open, didSet = tr.effects.some((e) => e.is(setActiveEffect));
|
|
28995
29077
|
if (open && tr.docChanged)
|
|
28996
29078
|
open = open.map(tr.changes);
|
|
28997
|
-
if (tr.selection ||
|
|
28998
|
-
open = CompletionDialog.build(
|
|
28999
|
-
else if (open && open.disabled && !
|
|
29079
|
+
if (tr.selection || active2.some((a) => a.hasResult() && tr.changes.touchesRange(a.from, a.to)) || !sameResults(active2, this.active) || didSet)
|
|
29080
|
+
open = CompletionDialog.build(active2, state, this.id, open, conf, didSet);
|
|
29081
|
+
else if (open && open.disabled && !active2.some((a) => a.isPending))
|
|
29000
29082
|
open = null;
|
|
29001
|
-
if (!open &&
|
|
29002
|
-
|
|
29083
|
+
if (!open && active2.every((a) => !a.isPending) && active2.some((a) => a.hasResult()))
|
|
29084
|
+
active2 = active2.map((a) => a.hasResult() ? new ActiveSource(
|
|
29003
29085
|
a.source,
|
|
29004
29086
|
0
|
|
29005
29087
|
/* State.Inactive */
|
|
@@ -29007,7 +29089,7 @@ var CompletionState = class _CompletionState {
|
|
|
29007
29089
|
for (let effect of tr.effects)
|
|
29008
29090
|
if (effect.is(setSelectedEffect))
|
|
29009
29091
|
open = open && open.setSelected(effect.value, this.id);
|
|
29010
|
-
return
|
|
29092
|
+
return active2 == this.active && open == this.open ? this : new _CompletionState(active2, this.id, open);
|
|
29011
29093
|
}
|
|
29012
29094
|
get tooltip() {
|
|
29013
29095
|
return this.open ? this.open.tooltip : null;
|
|
@@ -29092,9 +29174,9 @@ var ActiveSource = class _ActiveSource {
|
|
|
29092
29174
|
/* State.Inactive */
|
|
29093
29175
|
);
|
|
29094
29176
|
else if (effect.is(setActiveEffect)) {
|
|
29095
|
-
for (let
|
|
29096
|
-
if (
|
|
29097
|
-
value =
|
|
29177
|
+
for (let active2 of effect.value)
|
|
29178
|
+
if (active2.source == value.source)
|
|
29179
|
+
value = active2;
|
|
29098
29180
|
}
|
|
29099
29181
|
}
|
|
29100
29182
|
return value;
|
|
@@ -29238,8 +29320,8 @@ var closeCompletion = (view) => {
|
|
|
29238
29320
|
return true;
|
|
29239
29321
|
};
|
|
29240
29322
|
var RunningQuery = class {
|
|
29241
|
-
constructor(
|
|
29242
|
-
this.active =
|
|
29323
|
+
constructor(active2, context) {
|
|
29324
|
+
this.active = active2;
|
|
29243
29325
|
this.context = context;
|
|
29244
29326
|
this.time = Date.now();
|
|
29245
29327
|
this.updates = [];
|
|
@@ -29256,9 +29338,9 @@ var completionPlugin = /* @__PURE__ */ ViewPlugin.fromClass(class {
|
|
|
29256
29338
|
this.debounceAccept = -1;
|
|
29257
29339
|
this.pendingStart = false;
|
|
29258
29340
|
this.composing = 0;
|
|
29259
|
-
for (let
|
|
29260
|
-
if (
|
|
29261
|
-
this.startQuery(
|
|
29341
|
+
for (let active2 of view.state.field(completionState).active)
|
|
29342
|
+
if (active2.isPending)
|
|
29343
|
+
this.startQuery(active2);
|
|
29262
29344
|
}
|
|
29263
29345
|
update(update) {
|
|
29264
29346
|
let cState = update.state.field(completionState);
|
|
@@ -29303,19 +29385,19 @@ var completionPlugin = /* @__PURE__ */ ViewPlugin.fromClass(class {
|
|
|
29303
29385
|
this.debounceUpdate = -1;
|
|
29304
29386
|
this.pendingStart = false;
|
|
29305
29387
|
let { state } = this.view, cState = state.field(completionState);
|
|
29306
|
-
for (let
|
|
29307
|
-
if (
|
|
29308
|
-
this.startQuery(
|
|
29388
|
+
for (let active2 of cState.active) {
|
|
29389
|
+
if (active2.isPending && !this.running.some((r) => r.active.source == active2.source))
|
|
29390
|
+
this.startQuery(active2);
|
|
29309
29391
|
}
|
|
29310
29392
|
if (this.running.length && cState.open && cState.open.disabled)
|
|
29311
29393
|
this.debounceAccept = setTimeout(() => this.accept(), this.view.state.facet(completionConfig).updateSyncTime);
|
|
29312
29394
|
}
|
|
29313
|
-
startQuery(
|
|
29395
|
+
startQuery(active2) {
|
|
29314
29396
|
let { state } = this.view, pos = cur(state);
|
|
29315
|
-
let context = new CompletionContext(state, pos,
|
|
29316
|
-
let pending2 = new RunningQuery(
|
|
29397
|
+
let context = new CompletionContext(state, pos, active2.explicit, this.view);
|
|
29398
|
+
let pending2 = new RunningQuery(active2, context);
|
|
29317
29399
|
this.running.push(pending2);
|
|
29318
|
-
Promise.resolve(
|
|
29400
|
+
Promise.resolve(active2.source(context)).then((result) => {
|
|
29319
29401
|
if (!pending2.context.aborted) {
|
|
29320
29402
|
pending2.done = result || null;
|
|
29321
29403
|
this.scheduleAccept();
|
|
@@ -29348,26 +29430,26 @@ var completionPlugin = /* @__PURE__ */ ViewPlugin.fromClass(class {
|
|
|
29348
29430
|
if (query.done) {
|
|
29349
29431
|
let pos = cur(query.updates.length ? query.updates[0].startState : this.view.state);
|
|
29350
29432
|
let limit = Math.min(pos, query.done.from + (query.active.explicit ? 0 : 1));
|
|
29351
|
-
let
|
|
29433
|
+
let active2 = new ActiveResult(query.active.source, query.active.explicit, limit, query.done, query.done.from, (_a2 = query.done.to) !== null && _a2 !== void 0 ? _a2 : pos);
|
|
29352
29434
|
for (let tr of query.updates)
|
|
29353
|
-
|
|
29354
|
-
if (
|
|
29355
|
-
updated.push(
|
|
29435
|
+
active2 = active2.update(tr, conf);
|
|
29436
|
+
if (active2.hasResult()) {
|
|
29437
|
+
updated.push(active2);
|
|
29356
29438
|
continue;
|
|
29357
29439
|
}
|
|
29358
29440
|
}
|
|
29359
29441
|
let current2 = cState.active.find((a) => a.source == query.active.source);
|
|
29360
29442
|
if (current2 && current2.isPending) {
|
|
29361
29443
|
if (query.done == null) {
|
|
29362
|
-
let
|
|
29444
|
+
let active2 = new ActiveSource(
|
|
29363
29445
|
query.active.source,
|
|
29364
29446
|
0
|
|
29365
29447
|
/* State.Inactive */
|
|
29366
29448
|
);
|
|
29367
29449
|
for (let tr of query.updates)
|
|
29368
|
-
|
|
29369
|
-
if (!
|
|
29370
|
-
updated.push(
|
|
29450
|
+
active2 = active2.update(tr, conf);
|
|
29451
|
+
if (!active2.isPending)
|
|
29452
|
+
updated.push(active2);
|
|
29371
29453
|
} else {
|
|
29372
29454
|
this.startQuery(current2);
|
|
29373
29455
|
}
|
|
@@ -29824,12 +29906,12 @@ var theme2 = EditorView.theme({
|
|
|
29824
29906
|
"&.cm-focused .cm-selectionBackground, .cm-selectionBackground": { background: "var(--accent-soft)" }
|
|
29825
29907
|
});
|
|
29826
29908
|
var UNKNOWN = Decoration.mark({ class: "cm-unknown-field" });
|
|
29827
|
-
var ExprCode = (0,
|
|
29828
|
-
const host = (0,
|
|
29829
|
-
const view = (0,
|
|
29830
|
-
const latest2 = (0,
|
|
29909
|
+
var ExprCode = (0, import_react9.forwardRef)(function ExprCode2({ value, onChange, fields, parameters, invalid, check }, ref) {
|
|
29910
|
+
const host = (0, import_react9.useRef)(null);
|
|
29911
|
+
const view = (0, import_react9.useRef)(null);
|
|
29912
|
+
const latest2 = (0, import_react9.useRef)({ onChange, fields, parameters, check });
|
|
29831
29913
|
latest2.current = { onChange, fields, parameters, check };
|
|
29832
|
-
(0,
|
|
29914
|
+
(0, import_react9.useImperativeHandle)(ref, () => ({
|
|
29833
29915
|
insert(text) {
|
|
29834
29916
|
const v = view.current;
|
|
29835
29917
|
if (!v) return;
|
|
@@ -29843,7 +29925,7 @@ var ExprCode = (0, import_react8.forwardRef)(function ExprCode2({ value, onChang
|
|
|
29843
29925
|
view.current?.focus();
|
|
29844
29926
|
}
|
|
29845
29927
|
}));
|
|
29846
|
-
(0,
|
|
29928
|
+
(0, import_react9.useEffect)(() => {
|
|
29847
29929
|
const complete = (ctx) => {
|
|
29848
29930
|
const m = ctx.matchBefore(/(Fields|Parameters|Globals)\.\w*$/);
|
|
29849
29931
|
if (m) {
|
|
@@ -29932,8 +30014,8 @@ var SNIPPETS = {
|
|
|
29932
30014
|
function ExpressionEditor({ value, dataSet, onSave, onClose, title }) {
|
|
29933
30015
|
const def = useDesigner((s) => s.def);
|
|
29934
30016
|
const sample = useDesigner((s) => s.sample);
|
|
29935
|
-
const [text, setText] = (0,
|
|
29936
|
-
const ta = (0,
|
|
30017
|
+
const [text, setText] = (0, import_react10.useState)(value ?? "");
|
|
30018
|
+
const ta = (0, import_react10.useRef)(null);
|
|
29937
30019
|
const dsName = dataSet || def.dataSets?.[0]?.name;
|
|
29938
30020
|
const ds = def.dataSets?.find((d) => d.name === dsName);
|
|
29939
30021
|
const fields = fieldNames(ds).filter((n) => !(ds?.fields || []).some((f) => f.name === n && f.type === "object"));
|
|
@@ -29943,7 +30025,7 @@ function ExpressionEditor({ value, dataSet, onSave, onClose, title }) {
|
|
|
29943
30025
|
const insert2 = (s) => ta.current?.insert(s);
|
|
29944
30026
|
const err = checkValue(text);
|
|
29945
30027
|
const issues = err ? [] : check(text);
|
|
29946
|
-
const preview = (0,
|
|
30028
|
+
const preview = (0, import_react10.useMemo)(() => {
|
|
29947
30029
|
if (err || !sample?.dataSets) return null;
|
|
29948
30030
|
const rows = sample.dataSets[dsName] || [];
|
|
29949
30031
|
const params = Object.fromEntries((def.parameters || []).map((p) => [p.name, p.default ?? null]));
|
|
@@ -30016,7 +30098,7 @@ function ExpressionEditor({ value, dataSet, onSave, onClose, title }) {
|
|
|
30016
30098
|
}
|
|
30017
30099
|
|
|
30018
30100
|
// src/designer/CondFormat.jsx
|
|
30019
|
-
var
|
|
30101
|
+
var import_react11 = __toESM(require_react(), 1);
|
|
30020
30102
|
|
|
30021
30103
|
// src/designer/cfRules.js
|
|
30022
30104
|
var CF_OPS = ["eq", "ne", "lt", "le", "gt", "ge", "between", "top", "bottom", "aboveAvg", "belowAvg", "contains", "startsWith", "empty", "notEmpty"];
|
|
@@ -30136,7 +30218,7 @@ function CondFormat({ title, cf: start, fields, thisValue, kind, custom, onApply
|
|
|
30136
30218
|
const lang2 = useDesigner((s) => s.lang);
|
|
30137
30219
|
const T = (k, v) => t(lang2, k, v);
|
|
30138
30220
|
const blank = () => ({ field: thisValue ? void 0 : fields[0], op: "gt", value: "", format: kind === "chart" ? { backgroundColor: "#dc2626" } : { color: "#b42318", fontWeight: "bold" } });
|
|
30139
|
-
const [cf, setCf] = (0,
|
|
30221
|
+
const [cf, setCf] = (0, import_react11.useState)(() => JSON.parse(JSON.stringify(start || { mode: "first", rules: [blank()] })));
|
|
30140
30222
|
const rules = cf.rules || [];
|
|
30141
30223
|
const setRule = (i2, patch) => setCf((c) => ({ ...c, rules: c.rules.map((r, j) => j === i2 ? { ...r, ...patch } : r) }));
|
|
30142
30224
|
const setFmt = (i2, k, v) => setCf((c) => ({ ...c, rules: c.rules.map((r, j) => {
|
|
@@ -30227,7 +30309,7 @@ var catLabel = (tk, cat) => tk(`cat_${cat}`, cat);
|
|
|
30227
30309
|
function Inspector() {
|
|
30228
30310
|
const sel = useDesigner((s) => s.sel);
|
|
30229
30311
|
const def = useDesigner((s) => s.def);
|
|
30230
|
-
const [expr, setExpr] = (0,
|
|
30312
|
+
const [expr, setExpr] = (0, import_react12.useState)(null);
|
|
30231
30313
|
const openExpr = (cfg) => setExpr(cfg);
|
|
30232
30314
|
let body;
|
|
30233
30315
|
if (sel.kind === "items" && sel.ids.length > 1) body = /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Multi, { ids: sel.ids });
|
|
@@ -30242,13 +30324,13 @@ function Inspector() {
|
|
|
30242
30324
|
const one = sel.kind === "items" && sel.ids.length === 1 ? findItem(def, sel.ids[0])?.item : sel.kind === "cell" ? findItem(def, sel.id)?.item : null;
|
|
30243
30325
|
const scope = one ? one.dataSet || def.dataSets?.[0]?.name || null : void 0;
|
|
30244
30326
|
const selKey = sel.kind === "items" ? `i:${sel.ids.join(",")}` : sel.kind === "cell" ? `c:${sel.id}:${sel.part}:${sel.row}:${sel.col}:${sel.cells?.length || 0}` : `${sel.kind}:${sel.section || ""}`;
|
|
30245
|
-
const ref = (0,
|
|
30246
|
-
(0,
|
|
30327
|
+
const ref = (0, import_react12.useRef)(null);
|
|
30328
|
+
(0, import_react12.useLayoutEffect)(() => {
|
|
30247
30329
|
const pane = ref.current?.closest(".dright");
|
|
30248
30330
|
if (pane) pane.scrollTop = 0;
|
|
30249
30331
|
}, [selKey]);
|
|
30250
|
-
const [closed, setClosed] = (0,
|
|
30251
|
-
(0,
|
|
30332
|
+
const [closed, setClosed] = (0, import_react12.useState)(() => /* @__PURE__ */ new Set());
|
|
30333
|
+
(0, import_react12.useLayoutEffect)(() => {
|
|
30252
30334
|
for (const h of ref.current?.querySelectorAll(".cat > h5") || []) {
|
|
30253
30335
|
const shut = closed.has(h.textContent);
|
|
30254
30336
|
h.querySelector("button")?.setAttribute("aria-expanded", String(!shut));
|
|
@@ -30267,13 +30349,13 @@ function Inspector() {
|
|
|
30267
30349
|
});
|
|
30268
30350
|
};
|
|
30269
30351
|
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { "data-testid": "inspector", ref, onClick: toggle, children: [
|
|
30270
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(FieldScope.Provider, { value: scope, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
30352
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(FieldScope.Provider, { value: scope, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_react12.Fragment, { children: body }, selKey) }),
|
|
30271
30353
|
expr && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ExpressionEditor, { ...expr, onClose: () => setExpr(null) })
|
|
30272
30354
|
] });
|
|
30273
30355
|
}
|
|
30274
|
-
function Geo({ label, value, onChange }) {
|
|
30356
|
+
function Geo({ label, value, onChange, min }) {
|
|
30275
30357
|
const unit = useDesigner((s) => s.unit);
|
|
30276
|
-
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Field, { label: `${label} (${unit})`, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(NumberInput, { value: round(fromPt(value ?? 0, unit) * 100) / 100, step: unit === "pt" ? 1 : unit === "in" ? 0.05 : 0.5, onChange: (v) => onChange(round(toPt(v, unit))) }) });
|
|
30358
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Field, { label: `${label} (${unit})`, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(NumberInput, { value: round(fromPt(value ?? 0, unit) * 100) / 100, min: min == null ? void 0 : round(fromPt(min, unit) * 100) / 100, step: unit === "pt" ? 1 : unit === "in" ? 0.05 : 0.5, onChange: (v) => onChange(round(toPt(v, unit))) }) });
|
|
30277
30359
|
}
|
|
30278
30360
|
function PropEditor({ p: spec, value, onChange, openExpr, dataSet, item }) {
|
|
30279
30361
|
const T = useT3();
|
|
@@ -30338,7 +30420,7 @@ function OverflowTarget({ value, onChange, self }) {
|
|
|
30338
30420
|
}
|
|
30339
30421
|
function ExprOr({ p, value, onChange, openExpr, dataSet, children }) {
|
|
30340
30422
|
const T = useT3();
|
|
30341
|
-
const [on, setOn] = (0,
|
|
30423
|
+
const [on, setOn] = (0, import_react12.useState)(isDynamic(value));
|
|
30342
30424
|
const label = T(on ? "useFixed" : "useExpr");
|
|
30343
30425
|
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Field, { label: p.label, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "expr-row", children: [
|
|
30344
30426
|
on ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ExprInput, { value, onChange: (v) => onChange(v || void 0), onOpen: () => openExpr({ value, dataSet, onSave: onChange, title: p.label }), placeholder: "=IIf(Fields.amount < 0, 'bold', 'normal')" }) : children,
|
|
@@ -30351,7 +30433,7 @@ function ExprOr({ p, value, onChange, openExpr, dataSet, children }) {
|
|
|
30351
30433
|
function PaletteEditor({ label, value, onChange }) {
|
|
30352
30434
|
const T = useT3();
|
|
30353
30435
|
const custom = Array.isArray(value);
|
|
30354
|
-
const [text, setText] = (0,
|
|
30436
|
+
const [text, setText] = (0, import_react12.useState)(custom ? value.join(", ") : "");
|
|
30355
30437
|
const parse2 = (t3) => t3.split(/[\s,;]+/).map((x) => x.trim()).filter((x) => /^#[0-9a-f]{6}$/i.test(x));
|
|
30356
30438
|
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { display: "grid", gap: 6 }, children: [
|
|
30357
30439
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Field, { label, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
@@ -30378,17 +30460,18 @@ function PaletteEditor({ label, value, onChange }) {
|
|
|
30378
30460
|
custom && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { display: "flex", gap: 3, flexWrap: "wrap" }, "aria-hidden": "true", children: value.map((c, i2) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { style: { width: 14, height: 14, borderRadius: 3, background: c, border: "1px solid var(--line)" } }, i2)) })
|
|
30379
30461
|
] });
|
|
30380
30462
|
}
|
|
30381
|
-
var
|
|
30463
|
+
var reportLists = /* @__PURE__ */ new Map();
|
|
30382
30464
|
function ReportPicker({ value, onChange }) {
|
|
30383
|
-
const [list2, setList] = (0,
|
|
30384
|
-
const listId = (0,
|
|
30385
|
-
(0,
|
|
30465
|
+
const [list2, setList] = (0, import_react12.useState)(() => reportLists.get(useDesigner.getState().embed?.server || "") || []);
|
|
30466
|
+
const listId = (0, import_react12.useState)(() => `reports-${Math.random().toString(36).slice(2, 8)}`)[0];
|
|
30467
|
+
(0, import_react12.useEffect)(() => {
|
|
30386
30468
|
const embed = useDesigner.getState().embed;
|
|
30387
|
-
if (reportList || embed && !embed.server) return;
|
|
30388
30469
|
const server2 = embed?.server || "";
|
|
30470
|
+
if (reportLists.has(server2) || embed && !embed.server) return;
|
|
30389
30471
|
fetch(`${server2}/api/reports`).then((r) => r.ok ? r.json() : []).then((l) => {
|
|
30390
|
-
|
|
30391
|
-
|
|
30472
|
+
const v = Array.isArray(l) ? l : [];
|
|
30473
|
+
reportLists.set(server2, v);
|
|
30474
|
+
setList(v);
|
|
30392
30475
|
}).catch(() => {
|
|
30393
30476
|
});
|
|
30394
30477
|
}, []);
|
|
@@ -30422,8 +30505,8 @@ function ItemProps({ item, section, openExpr }) {
|
|
|
30422
30505
|
const tk = useTk();
|
|
30423
30506
|
const def = useDesigner((s) => s.def);
|
|
30424
30507
|
const spec = ITEMS[item.type];
|
|
30425
|
-
const [nameErr, setNameErr] = (0,
|
|
30426
|
-
const [find2, setFind] = (0,
|
|
30508
|
+
const [nameErr, setNameErr] = (0, import_react12.useState)(null);
|
|
30509
|
+
const [find2, setFind] = (0, import_react12.useState)("");
|
|
30427
30510
|
const q2 = find2.trim().toLowerCase();
|
|
30428
30511
|
const hit = (p, type) => !q2 || propLabel(tk, p, type).toLowerCase().includes(q2) || p.key.toLowerCase().includes(q2);
|
|
30429
30512
|
const props = (spec?.props || []).filter((p) => (!p.showIf || p.showIf(item)) && hit(p, item.type));
|
|
@@ -30475,8 +30558,8 @@ function ItemProps({ item, section, openExpr }) {
|
|
|
30475
30558
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "grid2", children: [
|
|
30476
30559
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Geo, { label: "X", value: item.x, onChange: (v) => setGeo("x", Math.max(0, v)) }),
|
|
30477
30560
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Geo, { label: "Y", value: item.y, onChange: (v) => setGeo("y", Math.max(0, v)) }),
|
|
30478
|
-
item.type !== "table" && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Geo, { label: T("i_width"), value: item.w, onChange: (v) => setGeo("w", Math.max(0, v)) }),
|
|
30479
|
-
item.type !== "table" && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Geo, { label: T("i_height"), value: item.h, onChange: (v) => setGeo("h", Math.max(0, v)) }),
|
|
30561
|
+
item.type !== "table" && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Geo, { label: T("i_width"), value: item.w, min: item.type === "line" ? 0 : 1, onChange: (v) => setGeo("w", Math.max(0, v)) }),
|
|
30562
|
+
item.type !== "table" && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Geo, { label: T("i_height"), value: item.h, min: item.type === "line" ? 0 : 1, onChange: (v) => setGeo("h", Math.max(0, v)) }),
|
|
30480
30563
|
item.type === "table" && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Field, { label: T("tableSize"), hint: T("tableSizeHint"), children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(TextInput, { value: `${round(item.w)} × ${round(item.h)} pt`, readOnly: true, "data-testid": "table-size" }) })
|
|
30481
30564
|
] }),
|
|
30482
30565
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "hint", children: (() => {
|
|
@@ -30567,7 +30650,7 @@ function PivotEditor({ item, openExpr }) {
|
|
|
30567
30650
|
const def = useDesigner((s) => s.def);
|
|
30568
30651
|
const fields = fieldsOf2(def, item.dataSet);
|
|
30569
30652
|
const spec = normalizeMatrix(item);
|
|
30570
|
-
const [pick, setPick] = (0,
|
|
30653
|
+
const [pick, setPick] = (0, import_react12.useState)({ rowGroups: "", columnGroups: "", values: "" });
|
|
30571
30654
|
const edit = (fn3, key2) => updateItem(item.id, (it) => {
|
|
30572
30655
|
if (!isTablix(it)) {
|
|
30573
30656
|
const n = normalizeMatrix(it);
|
|
@@ -30646,7 +30729,17 @@ function PivotEditor({ item, openExpr }) {
|
|
|
30646
30729
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Field, { label: T("groupExpandLevels"), children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(NumberInput, { value: g.expandLevels ?? "", step: 1, onChange: (v) => setK(list2, i2, "expandLevels", Number.isFinite(v) && v >= 0 ? Math.round(v) : void 0) }) })
|
|
30647
30730
|
] })
|
|
30648
30731
|
] }),
|
|
30649
|
-
(i2 < spec[list2].length - 1 || list2 === "rowGroups" && g.parent) && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Check, { label: T("pivotCollapsible"), checked: g.collapsible, onChange: (v) =>
|
|
30732
|
+
(i2 < spec[list2].length - 1 || list2 === "rowGroups" && g.parent) && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Check, { label: T("pivotCollapsible"), checked: g.collapsible, onChange: (v) => edit((it) => {
|
|
30733
|
+
const o = it[list2][i2];
|
|
30734
|
+
if (v) {
|
|
30735
|
+
o.collapsible = true;
|
|
30736
|
+
o.initiallyCollapsed = true;
|
|
30737
|
+
} else {
|
|
30738
|
+
delete o.collapsible;
|
|
30739
|
+
delete o.initiallyCollapsed;
|
|
30740
|
+
}
|
|
30741
|
+
}, `${item.id}.${list2}${i2}.collapsible`) }),
|
|
30742
|
+
" ",
|
|
30650
30743
|
g.collapsible && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Check, { label: T("pivotStartCollapsed"), checked: g.initiallyCollapsed, onChange: (v) => setK(list2, i2, "initiallyCollapsed", v) }),
|
|
30651
30744
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { "data-testid": `pivot-${list2}${i2}-action`, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ActionEditor, { label: T("ux_headerAction"), value: g.action, onChange: (v) => setK(list2, i2, "action", v), openExpr, dataSet: item.dataSet }) }),
|
|
30652
30745
|
g.total && g.total !== "none" && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { "data-testid": `pivot-${list2}${i2}-total-action`, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ActionEditor, { label: T("ux_totalAction"), value: g.totalAction, onChange: (v) => setK(list2, i2, "totalAction", v), openExpr, dataSet: item.dataSet }) })
|
|
@@ -30672,7 +30765,7 @@ function PivotEditor({ item, openExpr }) {
|
|
|
30672
30765
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "grid2", children: [
|
|
30673
30766
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Field, { label: T("pivotLabel"), children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(TextInput, { value: v.label || "", onChange: (x) => setK("values", i2, "label", x) }) }),
|
|
30674
30767
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Field, { label: T("pivotFormat"), children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(TextInput, { value: v.format || "", onChange: (x) => setK("values", i2, "format", x), placeholder: "N0" }) }),
|
|
30675
|
-
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Field, { label: T("pivotShow"), children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Select, { value: v.show || "value", options: shows, onChange: (x) =>
|
|
30768
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Field, { label: T("pivotShow"), children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Select, { value: v.show || "value", options: shows, onChange: (x) => edit((it) => setMatrixShow(it.values[i2], x), `${item.id}.values${i2}.show`) }) })
|
|
30676
30769
|
] }),
|
|
30677
30770
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { "data-testid": `pivot-values${i2}-action`, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ActionEditor, { label: T("ux_cellAction"), value: v.action, onChange: (x) => setK("values", i2, "action", x), openExpr, dataSet: item.dataSet }) }),
|
|
30678
30771
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Field, { label: T("cellBookmark"), children: exprField("values", i2, "bookmark", v.bookmark, T("cellBookmark")) })
|
|
@@ -30714,8 +30807,8 @@ function GroupsEditor({ table: table2, openExpr }) {
|
|
|
30714
30807
|
const T = useT3();
|
|
30715
30808
|
const def = useDesigner((s) => s.def);
|
|
30716
30809
|
const fields = fieldsOf2(def, table2.dataSet);
|
|
30717
|
-
const [pick, setPick] = (0,
|
|
30718
|
-
const [drill, setDrill] = (0,
|
|
30810
|
+
const [pick, setPick] = (0, import_react12.useState)("");
|
|
30811
|
+
const [drill, setDrill] = (0, import_react12.useState)(false);
|
|
30719
30812
|
const setG = (i2, k, v) => updateItem(table2.id, (t3) => {
|
|
30720
30813
|
if (v === void 0 || v === "" || v === false) delete t3.groups[i2][k];
|
|
30721
30814
|
else t3.groups[i2][k] = v;
|
|
@@ -30957,7 +31050,7 @@ rimary" ? void 0 : v), "aria-label": `${T("overlayAxis")} ${i2 + 1}` }) }),
|
|
|
30957
31050
|
}
|
|
30958
31051
|
function CfButton({ label, title, target, at: at2, kind, fields, apply: apply2, testid }) {
|
|
30959
31052
|
const T = useT3();
|
|
30960
|
-
const [open, setOpen] = (0,
|
|
31053
|
+
const [open, setOpen] = (0, import_react12.useState)(false);
|
|
30961
31054
|
const n = target?.cf?.rules?.length || 0;
|
|
30962
31055
|
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(import_jsx_runtime10.Fragment, { children: [
|
|
30963
31056
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("button", { type: "button", className: "btn sm", onClick: () => setOpen(true), "data-testid": testid, children: [
|
|
@@ -31024,14 +31117,16 @@ function VisualEditor({ cell, setCell, openExpr, dataSet }) {
|
|
|
31024
31117
|
}
|
|
31025
31118
|
var reportParams = /* @__PURE__ */ new Map();
|
|
31026
31119
|
function useReportParams(id) {
|
|
31027
|
-
const
|
|
31028
|
-
(0,
|
|
31120
|
+
const srv = () => useDesigner.getState().embed?.server || "";
|
|
31121
|
+
const [list2, setList] = (0, import_react12.useState)(() => reportParams.get(`${srv()} ${id}`) ?? null);
|
|
31122
|
+
(0, import_react12.useEffect)(() => {
|
|
31029
31123
|
if (!id || isDynamic(id)) {
|
|
31030
31124
|
setList(null);
|
|
31031
31125
|
return;
|
|
31032
31126
|
}
|
|
31033
|
-
|
|
31034
|
-
|
|
31127
|
+
const key2 = `${srv()} ${id}`;
|
|
31128
|
+
if (reportParams.has(key2)) {
|
|
31129
|
+
setList(reportParams.get(key2));
|
|
31035
31130
|
return;
|
|
31036
31131
|
}
|
|
31037
31132
|
let alive = true;
|
|
@@ -31044,7 +31139,7 @@ function useReportParams(id) {
|
|
|
31044
31139
|
fetch(`${server2}/api/reports/${encodeURIComponent(id)}`).then((r) => r.ok ? r.json() : null).then((r) => {
|
|
31045
31140
|
const d = r?.definition || r;
|
|
31046
31141
|
const ps = d && typeof d === "object" ? (d.parameters || []).map((p) => ({ name: p.name, required: !!p.required && p.default == null, prompt: p.prompt })) : null;
|
|
31047
|
-
if (ps) reportParams.set(
|
|
31142
|
+
if (ps) reportParams.set(key2, ps);
|
|
31048
31143
|
if (alive) setList(ps);
|
|
31049
31144
|
}).catch(() => {
|
|
31050
31145
|
if (alive) setList(null);
|
|
@@ -31058,7 +31153,7 @@ function useReportParams(id) {
|
|
|
31058
31153
|
function ParamMap({ value, onChange, known, openExpr, dataSet, testid }) {
|
|
31059
31154
|
const T = useT3();
|
|
31060
31155
|
const map = value || {};
|
|
31061
|
-
const [extra, setExtra] = (0,
|
|
31156
|
+
const [extra, setExtra] = (0, import_react12.useState)("");
|
|
31062
31157
|
const knownNames = new Set((known || []).map((p) => p.name));
|
|
31063
31158
|
const names = [...(known || []).map((p) => p.name), ...Object.keys(map).filter((k) => !knownNames.has(k))];
|
|
31064
31159
|
const set2 = (k, v, keep) => {
|
|
@@ -31477,7 +31572,7 @@ function ReportProps() {
|
|
|
31477
31572
|
const T = useT3();
|
|
31478
31573
|
const def = useDesigner((s) => s.def);
|
|
31479
31574
|
const families = useFontFamilies();
|
|
31480
|
-
const [fontsOpen, setFontsOpen] = (0,
|
|
31575
|
+
const [fontsOpen, setFontsOpen] = (0, import_react12.useState)(false);
|
|
31481
31576
|
const set2 = (fn3, key2) => useDesigner.getState().apply(fn3, key2);
|
|
31482
31577
|
const m = Array.isArray(def.page?.margins) ? def.page.margins : [36, 36, 36, 36];
|
|
31483
31578
|
const base2 = def.styles?.base || {};
|
|
@@ -31556,7 +31651,7 @@ function ReportProps() {
|
|
|
31556
31651
|
function ReportImages() {
|
|
31557
31652
|
const T = useT3();
|
|
31558
31653
|
const images = useDesigner((s) => s.def.images) || {};
|
|
31559
|
-
const [err, setErr] = (0,
|
|
31654
|
+
const [err, setErr] = (0, import_react12.useState)(null);
|
|
31560
31655
|
const set2 = (fn3) => useDesigner.getState().apply((d) => {
|
|
31561
31656
|
d.images || (d.images = {});
|
|
31562
31657
|
fn3(d.images);
|
|
@@ -31595,7 +31690,7 @@ function EmbeddedPicker({ item, onPick }) {
|
|
|
31595
31690
|
const images = useDesigner((s) => s.def.images) || {};
|
|
31596
31691
|
const names = Object.keys(images);
|
|
31597
31692
|
const cur2 = /^embedded:(.+)$/.exec(String(item.src || ""))?.[1];
|
|
31598
|
-
const [err, setErr] = (0,
|
|
31693
|
+
const [err, setErr] = (0, import_react12.useState)(null);
|
|
31599
31694
|
const upload = async (files) => {
|
|
31600
31695
|
setErr(null);
|
|
31601
31696
|
const r = await uploadImages(files, T);
|
|
@@ -31680,7 +31775,7 @@ function NamedStyles() {
|
|
|
31680
31775
|
const styleNames = useStyleNames();
|
|
31681
31776
|
const def = useDesigner((s) => s.def);
|
|
31682
31777
|
const named = def.styles?.named || {};
|
|
31683
|
-
const [newName, setNewName] = (0,
|
|
31778
|
+
const [newName, setNewName] = (0, import_react12.useState)("");
|
|
31684
31779
|
const setS = (name2, k, v) => useDesigner.getState().apply((d) => {
|
|
31685
31780
|
var _a2, _b;
|
|
31686
31781
|
d.styles || (d.styles = {});
|
|
@@ -31715,7 +31810,7 @@ function NamedStyles() {
|
|
|
31715
31810
|
}
|
|
31716
31811
|
|
|
31717
31812
|
// src/designer/DataPanel.jsx
|
|
31718
|
-
var
|
|
31813
|
+
var import_react15 = __toESM(require_react(), 1);
|
|
31719
31814
|
|
|
31720
31815
|
// src/designer/explore.js
|
|
31721
31816
|
var key = (k) => /^[A-Za-z_$][\w$]*$/.test(k) ? `.${k}` : `['${k}']`;
|
|
@@ -31751,7 +31846,7 @@ function bestRows(root) {
|
|
|
31751
31846
|
}
|
|
31752
31847
|
|
|
31753
31848
|
// src/designer/ODataEditor.jsx
|
|
31754
|
-
var
|
|
31849
|
+
var import_react13 = __toESM(require_react(), 1);
|
|
31755
31850
|
var import_jsx_runtime11 = __toESM(require_jsx_runtime(), 1);
|
|
31756
31851
|
var OPS3 = ["eq", "ne", "gt", "ge", "lt", "le", "contains", "startswith", "endswith"];
|
|
31757
31852
|
var OP_LABEL = { eq: "=", ne: "≠", gt: ">", ge: "≥", lt: "<", le: "≤" };
|
|
@@ -31766,7 +31861,7 @@ async function readMetadata(s) {
|
|
|
31766
31861
|
return odataMetadata(await res.text());
|
|
31767
31862
|
}
|
|
31768
31863
|
function ODataEditor({ s, setS, T }) {
|
|
31769
|
-
const [meta2, setMeta] = (0,
|
|
31864
|
+
const [meta2, setMeta] = (0, import_react13.useState)(null);
|
|
31770
31865
|
const sets = meta2?.sets || [];
|
|
31771
31866
|
const set2 = sets.find((x) => x.name === s.entitySet);
|
|
31772
31867
|
const props = set2 ? set2.properties : (s.select || []).map((name2) => ({ name: name2, type: s.types?.[name2] || "" }));
|
|
@@ -31857,7 +31952,7 @@ function ODataEditor({ s, setS, T }) {
|
|
|
31857
31952
|
}
|
|
31858
31953
|
|
|
31859
31954
|
// src/designer/SqlBuilder.jsx
|
|
31860
|
-
var
|
|
31955
|
+
var import_react14 = __toESM(require_react(), 1);
|
|
31861
31956
|
|
|
31862
31957
|
// src/designer/sqlBuild.js
|
|
31863
31958
|
var FILTER_OPS2 = ["=", "<>", "<", "<=", ">", ">=", "like", "in", "is null", "is not null"];
|
|
@@ -31930,8 +32025,8 @@ function normalizeSchema(body) {
|
|
|
31930
32025
|
return tables;
|
|
31931
32026
|
}
|
|
31932
32027
|
function useSchema(connection) {
|
|
31933
|
-
const [st, setSt] = (0,
|
|
31934
|
-
(0,
|
|
32028
|
+
const [st, setSt] = (0, import_react14.useState)(() => schemas.has(connection) ? { tables: schemas.get(connection) } : { loading: !!connection });
|
|
32029
|
+
(0, import_react14.useEffect)(() => {
|
|
31935
32030
|
if (!connection) {
|
|
31936
32031
|
setSt({});
|
|
31937
32032
|
return void 0;
|
|
@@ -31965,8 +32060,8 @@ function SqlBuilder({ s, setS, T, kind, onManual }) {
|
|
|
31965
32060
|
const nb = { ...b, ...patch };
|
|
31966
32061
|
setS({ ...s, builder: nb, query: buildSql(nb, kind) });
|
|
31967
32062
|
};
|
|
31968
|
-
const [find2, setFind] = (0,
|
|
31969
|
-
const [preview, setPreview] = (0,
|
|
32063
|
+
const [find2, setFind] = (0, import_react14.useState)("");
|
|
32064
|
+
const [preview, setPreview] = (0, import_react14.useState)(null);
|
|
31970
32065
|
const sql = buildSql(b, kind);
|
|
31971
32066
|
const tableOf2 = (name2) => (schema.tables || []).find((t3) => t3.name === name2);
|
|
31972
32067
|
const colsOf = (alias) => tableOf2(b.tables.find((t3) => t3.alias === alias)?.name)?.columns || [];
|
|
@@ -31995,7 +32090,7 @@ function SqlBuilder({ s, setS, T, kind, onManual }) {
|
|
|
31995
32090
|
if (from.t === to.t || b.joins.some((j) => j.from.t === from.t && j.from.c === from.c && j.to.t === to.t && j.to.c === to.c)) return;
|
|
31996
32091
|
set2({ joins: [...b.joins, { type: "inner", from, to }] });
|
|
31997
32092
|
};
|
|
31998
|
-
const offered = (0,
|
|
32093
|
+
const offered = (0, import_react14.useMemo)(() => b.tables.flatMap((t3) => suggestJoins(b, schema.tables, t3.alias)).filter((j, i2, a) => !b.joins.some((x) => x.from.t === j.from.t && x.from.c === j.from.c && x.to.t === j.to.t && x.to.c === j.to.c) && a.findIndex((y) => JSON.stringify(y) === JSON.stringify(j)) === i2), [b, schema.tables]);
|
|
31999
32094
|
const runPreview = async () => {
|
|
32000
32095
|
setPreview({ loading: true });
|
|
32001
32096
|
try {
|
|
@@ -32158,7 +32253,7 @@ function SqlBuilder({ s, setS, T, kind, onManual }) {
|
|
|
32158
32253
|
] });
|
|
32159
32254
|
}
|
|
32160
32255
|
function JoinAdder({ allCols, split, onAdd, T }) {
|
|
32161
|
-
const [a, setA] = (0,
|
|
32256
|
+
const [a, setA] = (0, import_react14.useState)(""), [z, setZ] = (0, import_react14.useState)("");
|
|
32162
32257
|
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "qb-row", children: [
|
|
32163
32258
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Select, { value: a, allowEmpty: true, options: allCols, onChange: (v) => setA(v || ""), "aria-label": T("qb_joinFrom") }),
|
|
32164
32259
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: "=" }),
|
|
@@ -32175,17 +32270,18 @@ function JoinAdder({ allCols, split, onAdd, T }) {
|
|
|
32175
32270
|
var import_jsx_runtime13 = __toESM(require_jsx_runtime(), 1);
|
|
32176
32271
|
var NAME2 = /^[A-Za-z_][\w]*$/;
|
|
32177
32272
|
var noSourceKey = (def) => (def?.dataSources || []).length ? null : "r4_noDataSource";
|
|
32178
|
-
async function loadSample() {
|
|
32179
|
-
const
|
|
32180
|
-
|
|
32273
|
+
async function loadSample(store) {
|
|
32274
|
+
const api = store?.getState ? store : activeStore();
|
|
32275
|
+
const { def } = api.getState();
|
|
32276
|
+
api.setState({ sample: { loading: true } });
|
|
32181
32277
|
try {
|
|
32182
32278
|
const params = resolveParameters(def, {});
|
|
32183
32279
|
const sources = await loadSources(def, { params, baseUrl: origin(), sqlPreview: true, fetch: reportFetch(origin(), void 0, { sqlPreview: true }) });
|
|
32184
32280
|
const ctx = { params, globals: { ExecutionTime: /* @__PURE__ */ new Date() }, dataSets: {}, fields: null, locale: def.locale, currency: def.currency, functions: functionTable(def) };
|
|
32185
32281
|
const dataSets = buildDataSets(def, sources, ctx);
|
|
32186
|
-
|
|
32282
|
+
api.setState({ sample: { dataSets, sources, at: Date.now() } });
|
|
32187
32283
|
} catch (e) {
|
|
32188
|
-
|
|
32284
|
+
api.setState({ sample: { error: e.message } });
|
|
32189
32285
|
}
|
|
32190
32286
|
}
|
|
32191
32287
|
function DataPanel() {
|
|
@@ -32193,8 +32289,8 @@ function DataPanel() {
|
|
|
32193
32289
|
const lang2 = useDesigner((s) => s.lang);
|
|
32194
32290
|
const T = (k, v) => t(lang2, k, v);
|
|
32195
32291
|
const sample = useDesigner((s) => s.sample);
|
|
32196
|
-
const [dlg, setDlg] = (0,
|
|
32197
|
-
const [open, setOpen] = (0,
|
|
32292
|
+
const [dlg, setDlg] = (0, import_react15.useState)(null);
|
|
32293
|
+
const [open, setOpen] = (0, import_react15.useState)(() => new Set((def.dataSets || []).map((d) => d.name)));
|
|
32198
32294
|
const toggle = (n) => setOpen((s) => {
|
|
32199
32295
|
const x = new Set(s);
|
|
32200
32296
|
x.has(n) ? x.delete(n) : x.add(n);
|
|
@@ -32343,10 +32439,10 @@ function ParamDialog({ index, onClose }) {
|
|
|
32343
32439
|
const lang2 = useDesigner((s) => s.lang);
|
|
32344
32440
|
const T = (k, v) => t(lang2, k, v);
|
|
32345
32441
|
const orig = index != null ? def.parameters[index] : null;
|
|
32346
|
-
const [p, setP] = (0,
|
|
32347
|
-
const [columns, setColumns] = (0,
|
|
32348
|
-
const [live, setLive] = (0,
|
|
32349
|
-
const [choicesText, setChoicesText] = (0,
|
|
32442
|
+
const [p, setP] = (0, import_react15.useState)(orig || { name: "", type: "string", prompt: "", default: "", required: false });
|
|
32443
|
+
const [columns, setColumns] = (0, import_react15.useState)(String(def.parameterLayout?.columns || 1));
|
|
32444
|
+
const [live, setLive] = (0, import_react15.useState)(def.liveParameters !== false);
|
|
32445
|
+
const [choicesText, setChoicesText] = (0, import_react15.useState)(() => (p.options || []).map(optionLine).join("\n"));
|
|
32350
32446
|
const fromFields = (def.dataSets?.find((d) => d.name === p.optionsFrom?.dataSet)?.fields || []).map((f) => f.name);
|
|
32351
32447
|
const labelOpts = [...fromFields.map((f) => ({ value: `=Fields.${f}`, label: f })), ...p.optionsFrom?.label && !fromFields.some((f) => `=Fields.${f}` === p.optionsFrom.label) ? [{ value: p.optionsFrom.label, label: p.optionsFrom.label }] : []];
|
|
32352
32448
|
const err = !NAME2.test(p.name) ? T("paramNameRule") : !uniqueIn(def.parameters, p.name, index) ? T("paramNameTaken") : p.optionsFrom && !p.optionsFrom.value ? T("ux_paramPickValueField") : null;
|
|
@@ -32493,7 +32589,7 @@ function SourceDialog({ index, onClose }) {
|
|
|
32493
32589
|
const lang2 = useDesigner((s2) => s2.lang);
|
|
32494
32590
|
const T = (k, v) => t(lang2, k, v);
|
|
32495
32591
|
const orig = index != null ? def.dataSources[index] : null;
|
|
32496
|
-
const [s, setS] = (0,
|
|
32592
|
+
const [s, setS] = (0, import_react15.useState)(() => ({
|
|
32497
32593
|
name: "",
|
|
32498
32594
|
type: "rest",
|
|
32499
32595
|
method: "GET",
|
|
@@ -32557,11 +32653,11 @@ function SourceDialog({ index, onClose }) {
|
|
|
32557
32653
|
if (!err && s.type === "sql" && !s.connection) err = "Pick a connection";
|
|
32558
32654
|
if (!err && s.type === "sql" && s.procedure != null && !s.procedure) err = "Pick a stored procedure";
|
|
32559
32655
|
if (!err && s.type === "sql" && s.procedure == null && !/^\s*(select|with)\b/i.test(s.query || "")) err = "Write a SELECT query";
|
|
32560
|
-
const [conns, setConns] = (0,
|
|
32656
|
+
const [conns, setConns] = (0, import_react15.useState)(null);
|
|
32561
32657
|
const procs = (conns || []).find((c) => c.name === s.connection)?.procs || [];
|
|
32562
32658
|
const sqlKind = (conns || []).find((c) => c.name === s.connection)?.kind || "sqlite";
|
|
32563
|
-
const [probe, setProbe] = (0,
|
|
32564
|
-
(0,
|
|
32659
|
+
const [probe, setProbe] = (0, import_react15.useState)(null);
|
|
32660
|
+
(0, import_react15.useEffect)(() => {
|
|
32565
32661
|
if (s.type !== "sql" || conns) return;
|
|
32566
32662
|
fetch("/api/data/sql/connections").then((r) => r.ok ? r.json() : []).then(setConns).catch(() => setConns([]));
|
|
32567
32663
|
}, [s.type, conns]);
|
|
@@ -32754,13 +32850,13 @@ function DataSetDialog({ index, onClose, onSaved }) {
|
|
|
32754
32850
|
const lang2 = useDesigner((s) => s.lang);
|
|
32755
32851
|
const T = (k, v) => t(lang2, k, v);
|
|
32756
32852
|
const orig = index != null ? def.dataSets[index] : null;
|
|
32757
|
-
const [d, setD] = (0,
|
|
32758
|
-
const [detect, setDetect] = (0,
|
|
32759
|
-
const [pathTyped, setPathTyped] = (0,
|
|
32853
|
+
const [d, setD] = (0, import_react15.useState)(() => ({ name: "", source: def.dataSources?.[0]?.name, path: "$", fields: [], sort: [], ...orig ? JSON.parse(JSON.stringify(orig)) : {} }));
|
|
32854
|
+
const [detect, setDetect] = (0, import_react15.useState)({ state: "idle" });
|
|
32855
|
+
const [pathTyped, setPathTyped] = (0, import_react15.useState)(!!orig);
|
|
32760
32856
|
const nested = !!d.relation;
|
|
32761
32857
|
const parents = (def.dataSets || []).filter((x, i2) => i2 !== index && x.name !== d.name);
|
|
32762
32858
|
const err = !NAME2.test(d.name) ? T("dsNameRule") : !uniqueIn(def.dataSets, d.name, index) ? T("dsNameTaken") : nested ? !d.relation.parent ? T("dsPickParent") : null : !d.source ? T("dsPickSource") : null;
|
|
32763
|
-
const [explore, setExplore] = (0,
|
|
32859
|
+
const [explore, setExplore] = (0, import_react15.useState)(null);
|
|
32764
32860
|
const loadSourceRaw = async (name2) => {
|
|
32765
32861
|
const params = resolveParameters(useDesigner.getState().def, {});
|
|
32766
32862
|
const src = useDesigner.getState().def.dataSources.find((s) => s.name === name2);
|
|
@@ -33010,7 +33106,7 @@ function DataSetDialog({ index, onClose, onSaved }) {
|
|
|
33010
33106
|
}
|
|
33011
33107
|
|
|
33012
33108
|
// src/designer/Outline.jsx
|
|
33013
|
-
var
|
|
33109
|
+
var import_react16 = __toESM(require_react(), 1);
|
|
33014
33110
|
var import_jsx_runtime14 = __toESM(require_jsx_runtime(), 1);
|
|
33015
33111
|
var MIME = "application/x-pw-outline";
|
|
33016
33112
|
function Outline() {
|
|
@@ -33019,11 +33115,32 @@ function Outline() {
|
|
|
33019
33115
|
const lang2 = useDesigner((s) => s.lang);
|
|
33020
33116
|
const readOnly2 = useDesigner((s) => s.readOnly);
|
|
33021
33117
|
const T = (k, v) => t(lang2, k, v);
|
|
33022
|
-
const [drop, setDrop] = (0,
|
|
33023
|
-
const [said, setSaid] = (0,
|
|
33024
|
-
const
|
|
33025
|
-
const
|
|
33118
|
+
const [drop, setDrop] = (0, import_react16.useState)(null);
|
|
33119
|
+
const [said, setSaid] = (0, import_react16.useState)("");
|
|
33120
|
+
const [cur2, setCur] = (0, import_react16.useState)(null);
|
|
33121
|
+
const dragged = (0, import_react16.useRef)(null);
|
|
33122
|
+
const body = (0, import_react16.useRef)(null);
|
|
33026
33123
|
const chosen = new Set(sel.kind === "items" ? sel.ids : sel.kind === "cell" ? [sel.id] : []);
|
|
33124
|
+
const keys = sectionList(def).flatMap(({ key: key2 }) => {
|
|
33125
|
+
const out = [`band:${key2}`];
|
|
33126
|
+
const go = (l) => l.forEach((it) => {
|
|
33127
|
+
out.push(it.id);
|
|
33128
|
+
if (NESTING.has(it.type)) go(it.items || []);
|
|
33129
|
+
});
|
|
33130
|
+
go(secOf(def, key2)?.items || []);
|
|
33131
|
+
return out;
|
|
33132
|
+
});
|
|
33133
|
+
const stop = keys.includes(cur2) ? cur2 : keys.find((k) => chosen.has(k) || sel.kind === "section" && k === `band:${sel.section}`) || keys[0];
|
|
33134
|
+
const roving = (k) => ({ tabIndex: k === stop ? 0 : -1, onFocus: () => setCur(k) });
|
|
33135
|
+
const nav2 = (e) => {
|
|
33136
|
+
if (e.defaultPrevented || e.altKey || e.metaKey || e.ctrlKey || e.target.getAttribute("role") !== "option") return;
|
|
33137
|
+
const all = [...e.currentTarget.querySelectorAll("[role=option]")];
|
|
33138
|
+
const i2 = all.indexOf(e.target);
|
|
33139
|
+
const j = e.key === "ArrowDown" ? i2 + 1 : e.key === "ArrowUp" ? i2 - 1 : e.key === "Home" ? 0 : e.key === "End" ? all.length - 1 : null;
|
|
33140
|
+
if (j == null) return;
|
|
33141
|
+
e.preventDefault();
|
|
33142
|
+
all[Math.max(0, Math.min(all.length - 1, j))]?.focus();
|
|
33143
|
+
};
|
|
33027
33144
|
const pick = (e, id) => {
|
|
33028
33145
|
const st = useDesigner.getState();
|
|
33029
33146
|
if (e.shiftKey && st.sel.kind === "items") {
|
|
@@ -33135,30 +33252,32 @@ function Outline() {
|
|
|
33135
33252
|
};
|
|
33136
33253
|
const rows = (list2, parent, depth, section) => list2.map((it, i2) => {
|
|
33137
33254
|
const mark = drop && drop.id != null && drop.id === it.id ? ` drop-${drop.where}` : "";
|
|
33138
|
-
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("li", { children: [
|
|
33255
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("li", { role: "none", children: [
|
|
33139
33256
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: `trow outline-row${chosen.has(it.id) ? " sel" : ""}${mark}`, style: { paddingInlineStart: depth * 14 }, "data-outline": it.name, "data-outline-id": it.id, ...dragProps(it, i2, parent, section), children: [
|
|
33140
33257
|
!readOnly2 && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "grip", "aria-hidden": "true", children: "⠿" }),
|
|
33141
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("button", { type: "button", className: "linklike nm", onClick: (e) => pick(e, it.id), onKeyDown: (e) => onKey(e, it, list2, i2, parent), "aria-
|
|
33258
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("button", { type: "button", role: "option", className: "linklike nm", onClick: (e) => pick(e, it.id), onKeyDown: (e) => onKey(e, it, list2, i2, parent), "aria-selected": chosen.has(it.id), "aria-describedby": readOnly2 ? "outline-nav" : "outline-nav outline-keys", ...roving(it.id), children: it.name }),
|
|
33142
33259
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ty", children: T(`item_${it.type}`) === `item_${it.type}` ? ITEMS[it.type]?.label || it.type : T(`item_${it.type}`) }),
|
|
33143
33260
|
!readOnly2 && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { className: "act", style: { display: "inline-flex", gap: 2 }, children: [
|
|
33144
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("button", { type: "button", className: "btn sm ghost icon", disabled: i2 === 0, onClick: () => reorderItem(it.id, -1), title: T("outlineBackward"), "aria-label": `${T("outlineBackward")}: ${it.name}`, children: "↑" }),
|
|
33145
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("button", { type: "button", className: "btn sm ghost icon", disabled: i2 === list2.length - 1, onClick: () => reorderItem(it.id, 1), title: T("outlineForward"), "aria-label": `${T("outlineForward")}: ${it.name}`, children: "↓" }),
|
|
33146
|
-
parent && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("button", { type: "button", className: "btn sm ghost icon", onClick: () => moveOutOfParent(it.id), title: T("outlineMoveOut", { name: parent.name }), "aria-label": `${T("outlineMoveOut", { name: parent.name })}: ${it.name}`, children: "⇱" })
|
|
33261
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("button", { type: "button", className: "btn sm ghost icon", tabIndex: -1, disabled: i2 === 0, onClick: () => reorderItem(it.id, -1), title: T("outlineBackward"), "aria-label": `${T("outlineBackward")}: ${it.name}`, children: "↑" }),
|
|
33262
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("button", { type: "button", className: "btn sm ghost icon", tabIndex: -1, disabled: i2 === list2.length - 1, onClick: () => reorderItem(it.id, 1), title: T("outlineForward"), "aria-label": `${T("outlineForward")}: ${it.name}`, children: "↓" }),
|
|
33263
|
+
parent && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("button", { type: "button", className: "btn sm ghost icon", tabIndex: -1, onClick: () => moveOutOfParent(it.id), title: T("outlineMoveOut", { name: parent.name }), "aria-label": `${T("outlineMoveOut", { name: parent.name })}: ${it.name}`, children: "⇱" })
|
|
33147
33264
|
] })
|
|
33148
33265
|
] }),
|
|
33149
|
-
NESTING.has(it.type) && (it.items || []).length > 0 && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("ul", { className: "tree", children: rows(it.items, it, depth + 1, section) })
|
|
33266
|
+
NESTING.has(it.type) && (it.items || []).length > 0 && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("ul", { className: "tree", role: "none", children: rows(it.items, it, depth + 1, section) })
|
|
33150
33267
|
] }, it.id);
|
|
33151
33268
|
});
|
|
33152
33269
|
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "pane", "data-testid": "outline", children: [
|
|
33153
33270
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("h4", { children: T("outline") }),
|
|
33154
33271
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "pane-body", ref: body, children: [
|
|
33155
|
-
sectionList(def).map(({ key: key2, label }) => {
|
|
33272
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { role: "listbox", "aria-label": T("outline"), "aria-multiselectable": "true", onKeyDown: nav2, children: sectionList(def).map(({ key: key2, label }) => {
|
|
33156
33273
|
const items = secOf(def, key2)?.items || [];
|
|
33157
|
-
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: `outline-sec${drop?.band === key2 ? " drop-band" : ""}`, "data-outline-band": key2, ...bandDrop(key2), children: [
|
|
33158
|
-
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("button", { type: "button", className: `linklike outline-band${sel.kind === "section" && sel.section === key2 ? " sel" : ""}`, onClick: () => useDesigner.getState().select({ kind: "section", section: key2 }),
|
|
33159
|
-
|
|
33274
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { role: "group", "aria-label": label, className: `outline-sec${drop?.band === key2 ? " drop-band" : ""}`, "data-outline-band": key2, ...bandDrop(key2), children: [
|
|
33275
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("button", { type: "button", role: "option", "aria-selected": sel.kind === "section" && sel.section === key2, "aria-describedby": "outline-nav", className: `linklike outline-band${sel.kind === "section" && sel.section === key2 ? " sel" : ""}`, onClick: () => useDesigner.getState().select({ kind: "section", section: key2 }), ...roving(`band:${key2}`),
|
|
33276
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("b", { children: label }) }),
|
|
33277
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("ul", { className: "tree", role: "none", children: items.length ? rows(items, null, 1, key2) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("li", { className: "subtle", role: "none", children: T("outlineEmpty") }) })
|
|
33160
33278
|
] }, key2);
|
|
33161
|
-
}),
|
|
33279
|
+
}) }),
|
|
33280
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "sr-only", id: "outline-nav", children: T("b9_outlineKeys") }),
|
|
33162
33281
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "hint", children: T("outlineHint") }),
|
|
33163
33282
|
!readOnly2 && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "hint", id: "outline-keys", children: T("outlineKeys") }),
|
|
33164
33283
|
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "sr-only", role: "status", "aria-live": "polite", children: said })
|
|
@@ -33167,7 +33286,7 @@ function Outline() {
|
|
|
33167
33286
|
}
|
|
33168
33287
|
|
|
33169
33288
|
// src/theme/ThemeToggle.jsx
|
|
33170
|
-
var
|
|
33289
|
+
var import_react17 = __toESM(require_react(), 1);
|
|
33171
33290
|
|
|
33172
33291
|
// src/theme/theme.js
|
|
33173
33292
|
var THEME_KEY = "pw-theme";
|
|
@@ -33209,8 +33328,8 @@ function Icon2({ pref }) {
|
|
|
33209
33328
|
] });
|
|
33210
33329
|
}
|
|
33211
33330
|
function ThemeToggle({ className = "btn sm ghost icon" }) {
|
|
33212
|
-
const [pref, setPref] = (0,
|
|
33213
|
-
(0,
|
|
33331
|
+
const [pref, setPref] = (0, import_react17.useState)("system");
|
|
33332
|
+
(0, import_react17.useEffect)(() => {
|
|
33214
33333
|
setPref(readPreference());
|
|
33215
33334
|
const mq = window.matchMedia("(prefers-color-scheme: dark)");
|
|
33216
33335
|
const onChange = () => {
|
|
@@ -33228,7 +33347,7 @@ function ThemeToggle({ className = "btn sm ghost icon" }) {
|
|
|
33228
33347
|
}
|
|
33229
33348
|
|
|
33230
33349
|
// src/designer/ChartWizard.jsx
|
|
33231
|
-
var
|
|
33350
|
+
var import_react18 = __toESM(require_react(), 1);
|
|
33232
33351
|
var import_jsx_runtime16 = __toESM(require_jsx_runtime(), 1);
|
|
33233
33352
|
var TYPES = ["column", "bar", "line", "area", "pie", "donut", "scatter", "bubble", "radar", "funnel", "gauge", "treemap", "histogram", "boxplot", "waterfall", "gantt"];
|
|
33234
33353
|
var PER_ROW = /* @__PURE__ */ new Set(["scatter", "bubble"]);
|
|
@@ -33344,14 +33463,14 @@ function ChartWizard() {
|
|
|
33344
33463
|
const close = () => useDesigner.getState().setUi({ wizard: null });
|
|
33345
33464
|
const lang2 = useDesigner((s) => s.lang);
|
|
33346
33465
|
const tr = (k, v) => t(lang2, `cw_${k}`, v);
|
|
33347
|
-
const [c, setC] = (0,
|
|
33466
|
+
const [c, setC] = (0, import_react18.useState)(() => {
|
|
33348
33467
|
if (editing) return configFromChart(editing);
|
|
33349
33468
|
const score2 = (d) => ((d.fields || []).some((f) => f.type === "number") ? 1e6 : 0) + (sample?.dataSets?.[d.name]?.length || 0);
|
|
33350
33469
|
const ds2 = [...def.dataSets || []].sort((a, b) => score2(b) - score2(a))[0];
|
|
33351
33470
|
return { title: "", split: "", stacked: false, format: "N0", ...guess(ds2, sample?.dataSets?.[ds2?.name] || []) };
|
|
33352
33471
|
});
|
|
33353
33472
|
const set2 = (patch) => setC((x) => ({ ...x, ...patch, custom: false }));
|
|
33354
|
-
(0,
|
|
33473
|
+
(0, import_react18.useEffect)(() => {
|
|
33355
33474
|
if (!sample?.dataSets && !sample?.loading) loadSample();
|
|
33356
33475
|
}, []);
|
|
33357
33476
|
const ds = (def.dataSets || []).find((d) => d.name === c.dataSet);
|
|
@@ -33362,7 +33481,7 @@ function ChartWizard() {
|
|
|
33362
33481
|
const good = suggested(c, rows, fields);
|
|
33363
33482
|
const dateCategory = fields.find((f) => f.name === c.category)?.type === "date";
|
|
33364
33483
|
const monthish = fields.find((f) => f.name === c.category)?.type === "number" && /month/i.test(c.category) && rows.length > 0 && rows.every((r) => r[c.category] == null || Number.isInteger(r[c.category]) && r[c.category] >= 1 && r[c.category] <= 12);
|
|
33365
|
-
const compact = (0,
|
|
33484
|
+
const compact = (0, import_react18.useMemo)(() => {
|
|
33366
33485
|
if (!c.value || c.agg === "Count" || c.format === "P1") return null;
|
|
33367
33486
|
const per = /* @__PURE__ */ new Map();
|
|
33368
33487
|
for (const r of rows) {
|
|
@@ -33378,14 +33497,14 @@ function ChartWizard() {
|
|
|
33378
33497
|
const d = def.dataSets.find((x) => x.name === name2);
|
|
33379
33498
|
setC((x) => ({ ...x, split: "", ...guess(d, sample?.dataSets?.[name2] || []) }));
|
|
33380
33499
|
};
|
|
33381
|
-
(0,
|
|
33500
|
+
(0, import_react18.useEffect)(() => {
|
|
33382
33501
|
if (editing || !rows.length || c.touched) return;
|
|
33383
33502
|
setC((x) => ({ ...x, ...guess(ds, rows), touched: true }));
|
|
33384
33503
|
}, [rows.length]);
|
|
33385
|
-
const [thumbs, setThumbs] = (0,
|
|
33386
|
-
const [big, setBig] = (0,
|
|
33504
|
+
const [thumbs, setThumbs] = (0, import_react18.useState)({});
|
|
33505
|
+
const [big, setBig] = (0, import_react18.useState)(null);
|
|
33387
33506
|
const cfgKey = JSON.stringify({ ...c, touched: void 0 });
|
|
33388
|
-
(0,
|
|
33507
|
+
(0, import_react18.useEffect)(() => {
|
|
33389
33508
|
if (!sample?.dataSets || !c.dataSet) return;
|
|
33390
33509
|
let alive = true;
|
|
33391
33510
|
const t3 = setTimeout(async () => {
|
|
@@ -33573,7 +33692,7 @@ function rawText(raw) {
|
|
|
33573
33692
|
}
|
|
33574
33693
|
|
|
33575
33694
|
// src/designer/TableWizard.jsx
|
|
33576
|
-
var
|
|
33695
|
+
var import_react19 = __toESM(require_react(), 1);
|
|
33577
33696
|
var import_jsx_runtime17 = __toESM(require_jsx_runtime(), 1);
|
|
33578
33697
|
var LAYOUTS = [
|
|
33579
33698
|
{ id: "list", label: "List", when: "Every row, with totals" },
|
|
@@ -33586,12 +33705,13 @@ function TableWizard() {
|
|
|
33586
33705
|
const wiz = useDesigner((s) => s.tableWizard);
|
|
33587
33706
|
const def = useDesigner((s) => s.def);
|
|
33588
33707
|
const sample = useDesigner((s) => s.sample);
|
|
33708
|
+
const lang2 = useDesigner((s) => s.lang);
|
|
33589
33709
|
const close = () => useDesigner.getState().setUi({ tableWizard: null });
|
|
33590
33710
|
const parent = wiz?.parentId ? findItem(def, wiz.parentId)?.item : null;
|
|
33591
33711
|
const width = Math.max(120, Math.round((parent ? parent.w : bodyWidth(def, wiz?.section || "body")) - (wiz?.x || 0)));
|
|
33592
|
-
const [c, setC] = (0,
|
|
33712
|
+
const [c, setC] = (0, import_react19.useState)(() => ({ dataSet: wiz?.dataSet || def.dataSets?.[0]?.name, layout: wiz?.type === "matrix" ? "matrix" : "list", groupBy: "", fields: null, mRows: "", mCols: "", mValue: "" }));
|
|
33593
33713
|
const set2 = (patch) => setC((x) => ({ ...x, ...patch }));
|
|
33594
|
-
(0,
|
|
33714
|
+
(0, import_react19.useEffect)(() => {
|
|
33595
33715
|
if (!sample?.dataSets && !sample?.loading) loadSample();
|
|
33596
33716
|
}, []);
|
|
33597
33717
|
const ds = (def.dataSets || []).find((d) => d.name === c.dataSet);
|
|
@@ -33605,9 +33725,9 @@ function TableWizard() {
|
|
|
33605
33725
|
const groupBy2 = c.groupBy || groupGuess;
|
|
33606
33726
|
const mRows = c.mRows || groupBy2, mCols = c.mCols || text.find((f) => f.name !== mRows)?.name || "", mValue = c.mValue || nums[0]?.name || "";
|
|
33607
33727
|
const itemFor = (layout, w) => layout === "matrix" ? mRows && mCols ? matrixFor(ds, { rows: mRows, columns: mCols, value: mValue, agg: mValue ? "Sum" : "Count", width: w, sample: rows, currency: def.currency }) : null : tableFor(ds, { layout, groupBy: groupBy2, width: w, rows, fields: chosen, currency: def.currency });
|
|
33608
|
-
const [thumbs, setThumbs] = (0,
|
|
33728
|
+
const [thumbs, setThumbs] = (0, import_react19.useState)({});
|
|
33609
33729
|
const key2 = JSON.stringify([c, groupBy2, mRows, mCols, mValue, chosen]);
|
|
33610
|
-
(0,
|
|
33730
|
+
(0, import_react19.useEffect)(() => {
|
|
33611
33731
|
if (!ds || !sample?.dataSets) return;
|
|
33612
33732
|
let alive = true;
|
|
33613
33733
|
const t3 = setTimeout(async () => {
|
|
@@ -33652,7 +33772,7 @@ function TableWizard() {
|
|
|
33652
33772
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("button", { className: "btn ghost", onClick: () => {
|
|
33653
33773
|
useDesigner.getState().setUi({ tableWizard: null, pivotWizard: { section: wiz.section, x: wiz.x, y: wiz.y, parentId: wiz.parentId, dataSet: c.dataSet } });
|
|
33654
33774
|
}, "data-testid": "open-pivot-wizard", children: [
|
|
33655
|
-
t(
|
|
33775
|
+
t(lang2, "pivotWizard"),
|
|
33656
33776
|
"…"
|
|
33657
33777
|
] }),
|
|
33658
33778
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { className: "btn", onClick: close, children: "Cancel" }),
|
|
@@ -33665,7 +33785,7 @@ function TableWizard() {
|
|
|
33665
33785
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("section", { className: "cw-side", "aria-label": "Data for the table", children: [
|
|
33666
33786
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Field, { label: "Data set", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Select, { value: c.dataSet, options: (def.dataSets || []).map((d) => d.name), onChange: (v) => set2({ dataSet: v, fields: null, groupBy: "", mRows: "", mCols: "", mValue: "" }) }) }),
|
|
33667
33787
|
sample?.loading && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "hint", children: "Calling the API…" }),
|
|
33668
|
-
noSourceKey(def) && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "hint", role: "status", "data-testid": "no-source", children: t(
|
|
33788
|
+
noSourceKey(def) && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "hint", role: "status", "data-testid": "no-source", children: t(lang2, noSourceKey(def)) }),
|
|
33669
33789
|
sample?.error && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "err", children: sample.error }),
|
|
33670
33790
|
c.layout !== "matrix" && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
|
|
33671
33791
|
c.layout !== "list" && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Field, { label: "Group by", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Select, { value: groupBy2, options: text.map((f) => f.name), onChange: (v) => set2({ groupBy: v }) }) }),
|
|
@@ -33695,7 +33815,7 @@ function TableWizard() {
|
|
|
33695
33815
|
}
|
|
33696
33816
|
|
|
33697
33817
|
// src/designer/AskAi.jsx
|
|
33698
|
-
var
|
|
33818
|
+
var import_react20 = __toESM(require_react(), 1);
|
|
33699
33819
|
var import_jsx_runtime18 = __toESM(require_jsx_runtime(), 1);
|
|
33700
33820
|
var trim = (v, n = 200) => Array.isArray(v) ? v.slice(0, n).map((x) => trim(x, n)) : v && typeof v === "object" ? Object.fromEntries(Object.entries(v).map(([k, x]) => [k, trim(x, n)])) : v;
|
|
33701
33821
|
function changes(before, after) {
|
|
@@ -33711,9 +33831,9 @@ function changes(before, after) {
|
|
|
33711
33831
|
function AskAi({ onClose }) {
|
|
33712
33832
|
const def = useDesigner((s) => s.def);
|
|
33713
33833
|
const sample = useDesigner((s) => s.sample);
|
|
33714
|
-
const [prompt, setPrompt] = (0,
|
|
33715
|
-
const [st, setSt] = (0,
|
|
33716
|
-
(0,
|
|
33834
|
+
const [prompt, setPrompt] = (0, import_react20.useState)("");
|
|
33835
|
+
const [st, setSt] = (0, import_react20.useState)({ state: "idle" });
|
|
33836
|
+
(0, import_react20.useEffect)(() => {
|
|
33717
33837
|
if (!sample?.dataSets && !sample?.loading) loadSample();
|
|
33718
33838
|
}, []);
|
|
33719
33839
|
const ask = async () => {
|
|
@@ -33727,7 +33847,7 @@ function AskAi({ onClose }) {
|
|
|
33727
33847
|
let preview = null;
|
|
33728
33848
|
try {
|
|
33729
33849
|
const params = resolveParameters(out.definition, {}, { lenient: true });
|
|
33730
|
-
const model = await render(out.definition, { fontStore:
|
|
33850
|
+
const model = await render(out.definition, { fontStore: await loadFontStore(), parameters: params, sources: sources ? Object.fromEntries((out.definition.dataSources || []).map((s) => [s.name, sources[s.name] ?? (s.type === "json" ? s.data : [])])) : void 0, baseUrl: origin(), fetch: reportFetch(origin()) });
|
|
33731
33851
|
preview = { html: pageToSvg(model.pages[0], model.width, model.height), pages: model.pages.length };
|
|
33732
33852
|
} catch (e) {
|
|
33733
33853
|
preview = { error: e.message };
|
|
@@ -33798,7 +33918,7 @@ function AskAi({ onClose }) {
|
|
|
33798
33918
|
}
|
|
33799
33919
|
|
|
33800
33920
|
// src/designer/PivotWizard.jsx
|
|
33801
|
-
var
|
|
33921
|
+
var import_react21 = __toESM(require_react(), 1);
|
|
33802
33922
|
var import_jsx_runtime19 = __toESM(require_jsx_runtime(), 1);
|
|
33803
33923
|
var MIME_PF = "application/x-pw-pivot-field";
|
|
33804
33924
|
var AGGS2 = ["Sum", "Avg", "Count", "Min", "Max"];
|
|
@@ -33830,9 +33950,9 @@ function Thumb({ item }) {
|
|
|
33830
33950
|
const T = useT2();
|
|
33831
33951
|
const def = useDesigner((s) => s.def);
|
|
33832
33952
|
const sample = useDesigner((s) => s.sample);
|
|
33833
|
-
const [svg, setSvg] = (0,
|
|
33953
|
+
const [svg, setSvg] = (0, import_react21.useState)(null);
|
|
33834
33954
|
const key2 = JSON.stringify(item);
|
|
33835
|
-
(0,
|
|
33955
|
+
(0, import_react21.useEffect)(() => {
|
|
33836
33956
|
if (!item || !sample?.dataSets) return void 0;
|
|
33837
33957
|
let alive = true;
|
|
33838
33958
|
const t3 = setTimeout(() => {
|
|
@@ -33854,7 +33974,7 @@ function Thumb({ item }) {
|
|
|
33854
33974
|
function useData(name2) {
|
|
33855
33975
|
const def = useDesigner((s) => s.def);
|
|
33856
33976
|
const sample = useDesigner((s) => s.sample);
|
|
33857
|
-
(0,
|
|
33977
|
+
(0, import_react21.useEffect)(() => {
|
|
33858
33978
|
if (!sample?.dataSets && !sample?.loading) loadSample();
|
|
33859
33979
|
}, []);
|
|
33860
33980
|
const ds = (def.dataSets || []).find((d) => d.name === name2);
|
|
@@ -33869,10 +33989,10 @@ function placeOf(w, def) {
|
|
|
33869
33989
|
function PivotWizard() {
|
|
33870
33990
|
const T = useT2();
|
|
33871
33991
|
const w = useDesigner((s) => s.pivotWizard);
|
|
33872
|
-
const [dsName, setDs] = (0,
|
|
33992
|
+
const [dsName, setDs] = (0, import_react21.useState)(() => w?.dataSet || useDesigner.getState().def.dataSets?.[0]?.name);
|
|
33873
33993
|
const { def, ds, fields, rows } = useData(dsName);
|
|
33874
|
-
const [lay, setLay] = (0,
|
|
33875
|
-
const [totals, setTotals] = (0,
|
|
33994
|
+
const [lay, setLay] = (0, import_react21.useState)({ rows: [], columns: [], values: [] });
|
|
33995
|
+
const [totals, setTotals] = (0, import_react21.useState)(true);
|
|
33876
33996
|
const close = () => useDesigner.getState().setUi({ pivotWizard: null });
|
|
33877
33997
|
const width = Math.round(bodyWidth(def, w?.section || "body") - (w?.x || 0));
|
|
33878
33998
|
const add = (zone2, f) => setLay((l) => {
|
|
@@ -33993,13 +34113,13 @@ function InstantVisuals() {
|
|
|
33993
34113
|
const T = useT2();
|
|
33994
34114
|
const w = useDesigner((s) => s.instantVisuals);
|
|
33995
34115
|
const { def, ds, fields, rows } = useData(w?.dataSet);
|
|
33996
|
-
const [picked, setPickedRaw] = (0,
|
|
33997
|
-
const [touched, setTouched] = (0,
|
|
34116
|
+
const [picked, setPickedRaw] = (0, import_react21.useState)(() => instantPicks(ds?.fields || [], rows));
|
|
34117
|
+
const [touched, setTouched] = (0, import_react21.useState)(false);
|
|
33998
34118
|
const setPicked = (fn3) => {
|
|
33999
34119
|
setTouched(true);
|
|
34000
34120
|
setPickedRaw(fn3);
|
|
34001
34121
|
};
|
|
34002
|
-
(0,
|
|
34122
|
+
(0, import_react21.useEffect)(() => {
|
|
34003
34123
|
if (!touched) setPickedRaw(instantPicks(ds?.fields || [], rows));
|
|
34004
34124
|
}, [rows.length, ds]);
|
|
34005
34125
|
const close = () => useDesigner.getState().setUi({ instantVisuals: null });
|
|
@@ -34199,9 +34319,10 @@ var TOOLS = [
|
|
|
34199
34319
|
] }) }
|
|
34200
34320
|
];
|
|
34201
34321
|
function Toolbox({ T, hide = [] }) {
|
|
34322
|
+
const api = useDesignerStore();
|
|
34202
34323
|
const name2 = (type) => T(`item_${type}`) === `item_${type}` ? ITEMS[type].label : T(`item_${type}`);
|
|
34203
34324
|
const add = (type) => {
|
|
34204
|
-
const s =
|
|
34325
|
+
const s = api.getState();
|
|
34205
34326
|
const at2 = insertSpot(s.def, s.sel);
|
|
34206
34327
|
insertItem(type, at2.section, 0, at2.y, {}, at2.parentId);
|
|
34207
34328
|
};
|
|
@@ -34250,12 +34371,15 @@ var TbGroup = ({ label, children }) => /* @__PURE__ */ (0, import_jsx_runtime20.
|
|
|
34250
34371
|
] });
|
|
34251
34372
|
var QUICK = [["textbox", "text"], ["table", "table"], ["chart", "chart"], ["image", "image"]];
|
|
34252
34373
|
function LeftRail({ T, readOnly: readOnly2, embed }) {
|
|
34253
|
-
const body = (0,
|
|
34254
|
-
const [at2, setAt] = (0,
|
|
34374
|
+
const body = (0, import_react22.useRef)(null);
|
|
34375
|
+
const [at2, setAt] = (0, import_react22.useState)("tools");
|
|
34255
34376
|
const tabs = [!readOnly2 && ["tools", "b2_toolbox", "tools"], embed?.panels?.data !== false && ["data", "b2_data", "data"], ["outline", "b2_outline", "outline"]].filter(Boolean);
|
|
34256
34377
|
const go = (id) => {
|
|
34257
34378
|
const el = body.current?.querySelector(`[data-rail="${id}"]`);
|
|
34258
|
-
if (el)
|
|
34379
|
+
if (el) {
|
|
34380
|
+
body.current.scrollTo({ top: el.offsetTop - body.current.offsetTop, behavior: "smooth" });
|
|
34381
|
+
(el.querySelector('[role=listbox] [tabindex="0"]') || el.querySelector("button, input, select, textarea"))?.focus({ preventScroll: true });
|
|
34382
|
+
}
|
|
34259
34383
|
setAt(id);
|
|
34260
34384
|
};
|
|
34261
34385
|
const spy = () => {
|
|
@@ -34357,8 +34481,9 @@ var framed = () => {
|
|
|
34357
34481
|
}
|
|
34358
34482
|
};
|
|
34359
34483
|
function useAutosave(id, T, lang2, user) {
|
|
34360
|
-
const
|
|
34361
|
-
(0,
|
|
34484
|
+
const api = useDesignerStore();
|
|
34485
|
+
const [offer, setOffer] = (0, import_react22.useState)(null);
|
|
34486
|
+
(0, import_react22.useEffect)(() => {
|
|
34362
34487
|
if (!id || user == null || framed()) return void 0;
|
|
34363
34488
|
let store;
|
|
34364
34489
|
try {
|
|
@@ -34368,10 +34493,10 @@ function useAutosave(id, T, lang2, user) {
|
|
|
34368
34493
|
}
|
|
34369
34494
|
clearDrafts(store, user);
|
|
34370
34495
|
const d = readDraft(store, user, id);
|
|
34371
|
-
if (d && plain(mergeDraft(d.def,
|
|
34496
|
+
if (d && plain(mergeDraft(d.def, api.getState().def)) !== plain(api.getState().def)) setOffer(d);
|
|
34372
34497
|
else if (d) clearDraft(store, user, id);
|
|
34373
34498
|
const keep = () => {
|
|
34374
|
-
const s =
|
|
34499
|
+
const s = api.getState();
|
|
34375
34500
|
if (!s.saved && !s.readOnly) writeDraft(store, user, id, s.def, Date.now(), s.rev || null);
|
|
34376
34501
|
};
|
|
34377
34502
|
const t3 = setInterval(keep, AUTOSAVE_MS);
|
|
@@ -34380,7 +34505,7 @@ function useAutosave(id, T, lang2, user) {
|
|
|
34380
34505
|
};
|
|
34381
34506
|
window.addEventListener("pagehide", keep);
|
|
34382
34507
|
document.addEventListener("visibilitychange", hide);
|
|
34383
|
-
const unsub =
|
|
34508
|
+
const unsub = api.subscribe((s, prev) => {
|
|
34384
34509
|
if (s.saved && !prev.saved) clearDraft(store, user, id);
|
|
34385
34510
|
});
|
|
34386
34511
|
return () => {
|
|
@@ -34392,13 +34517,13 @@ function useAutosave(id, T, lang2, user) {
|
|
|
34392
34517
|
}, [id, user]);
|
|
34393
34518
|
if (!offer) return null;
|
|
34394
34519
|
const when = new Date(offer.at).toLocaleString(lang2 === "en" ? "en-IN" : lang2, { dateStyle: "medium", timeStyle: "short" });
|
|
34395
|
-
const stale = staleDraft(offer,
|
|
34520
|
+
const stale = staleDraft(offer, api.getState().rev);
|
|
34396
34521
|
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "draft-bar", role: "alert", "data-testid": "draft-offer", "data-stale": stale || void 0, children: [
|
|
34397
34522
|
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { children: T(stale ? "ux_draftStale" : "ux_draftFound", { when }) }),
|
|
34398
34523
|
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("button", { className: `btn sm${stale ? "" : " primary"}`, "data-testid": "draft-restore", onClick: () => {
|
|
34399
|
-
const d = mergeDraft(offer.def,
|
|
34400
|
-
|
|
34401
|
-
|
|
34524
|
+
const d = mergeDraft(offer.def, api.getState().def);
|
|
34525
|
+
api.getState().apply(() => JSON.parse(JSON.stringify(d)));
|
|
34526
|
+
api.getState().fixSelection();
|
|
34402
34527
|
setOffer(null);
|
|
34403
34528
|
}, children: T(stale ? "ux_draftRestoreAnyway" : "ux_draftRestore") }),
|
|
34404
34529
|
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("button", { className: "btn sm", "data-testid": "draft-discard", onClick: () => {
|
|
@@ -34411,12 +34536,13 @@ function useAutosave(id, T, lang2, user) {
|
|
|
34411
34536
|
] });
|
|
34412
34537
|
}
|
|
34413
34538
|
function ConflictBar({ T }) {
|
|
34539
|
+
const api = useDesignerStore();
|
|
34414
34540
|
const conflict = useDesigner((s) => s.conflict);
|
|
34415
34541
|
if (!conflict) return null;
|
|
34416
34542
|
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "draft-bar", role: "alert", "data-testid": "save-conflict", children: [
|
|
34417
34543
|
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { children: T("ux_conflict") }),
|
|
34418
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("button", { className: "btn sm", "data-testid": "conflict-mine", onClick: () =>
|
|
34419
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("button", { className: "btn sm", "data-testid": "conflict-theirs", onClick: () =>
|
|
34544
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("button", { className: "btn sm", "data-testid": "conflict-mine", onClick: () => api.getState().save({ overwrite: true }), children: T("ux_conflictMine") }),
|
|
34545
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("button", { className: "btn sm", "data-testid": "conflict-theirs", onClick: () => api.getState().takeTheirs(), children: T("ux_conflictTheirs") })
|
|
34420
34546
|
] });
|
|
34421
34547
|
}
|
|
34422
34548
|
var AL = (d) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("svg", { width: "16", height: "14", viewBox: "0 0 16 14", "aria-hidden": "true", children: d });
|
|
@@ -34466,7 +34592,7 @@ var ALIGN2 = [
|
|
|
34466
34592
|
];
|
|
34467
34593
|
function AlignBar({ T }) {
|
|
34468
34594
|
const sel = useDesigner((s) => s.sel);
|
|
34469
|
-
const [toPage, setToPage] = (0,
|
|
34595
|
+
const [toPage, setToPage] = (0, import_react22.useState)(false);
|
|
34470
34596
|
if (sel.kind !== "items" || !sel.ids.length) return null;
|
|
34471
34597
|
const n = sel.ids.length;
|
|
34472
34598
|
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { className: "align-bar", role: "toolbar", "aria-label": T("ux_alignBar"), "data-testid": "align-bar", children: [
|
|
@@ -34481,13 +34607,14 @@ function AlignBar({ T }) {
|
|
|
34481
34607
|
] });
|
|
34482
34608
|
}
|
|
34483
34609
|
function IssuesButton({ T }) {
|
|
34610
|
+
const api = useDesignerStore();
|
|
34484
34611
|
const issues = useDesignIssues();
|
|
34485
|
-
const [open, setOpen] = (0,
|
|
34486
|
-
(0,
|
|
34612
|
+
const [open, setOpen] = (0, import_react22.useState)(false);
|
|
34613
|
+
(0, import_react22.useEffect)(() => {
|
|
34487
34614
|
if (!issues.length) setOpen(false);
|
|
34488
34615
|
}, [issues.length]);
|
|
34489
|
-
const listRef = (0,
|
|
34490
|
-
(0,
|
|
34616
|
+
const listRef = (0, import_react22.useRef)(null);
|
|
34617
|
+
(0, import_react22.useLayoutEffect)(() => {
|
|
34491
34618
|
const el = listRef.current;
|
|
34492
34619
|
if (!el) return void 0;
|
|
34493
34620
|
const place = () => {
|
|
@@ -34504,7 +34631,7 @@ function IssuesButton({ T }) {
|
|
|
34504
34631
|
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { className: "issues-wrap", children: [
|
|
34505
34632
|
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("button", { type: "button", className: "btn sm issues-btn", "aria-expanded": open, onClick: () => setOpen((v) => !v), "data-testid": "issues", children: T("ux_issues", { n: issues.length }) }),
|
|
34506
34633
|
open && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("ul", { className: "issues-list", "data-testid": "issues-list", ref: listRef, children: issues.map((i2, k) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("button", { type: "button", className: "linklike", onClick: () => {
|
|
34507
|
-
if (i2.id)
|
|
34634
|
+
if (i2.id) api.getState().select({ kind: "items", ids: [i2.id] });
|
|
34508
34635
|
}, children: issueLine(T, i2) }) }, k)) })
|
|
34509
34636
|
] });
|
|
34510
34637
|
}
|
|
@@ -34528,9 +34655,10 @@ var SHORTCUTS = [
|
|
|
34528
34655
|
["?", "sc_help"]
|
|
34529
34656
|
];
|
|
34530
34657
|
function HistoryDialog({ id, onClose, T, lang: lang2 }) {
|
|
34531
|
-
const
|
|
34532
|
-
const [
|
|
34533
|
-
(0,
|
|
34658
|
+
const api = useDesignerStore();
|
|
34659
|
+
const [list2, setList] = (0, import_react22.useState)(null);
|
|
34660
|
+
const [err, setErr] = (0, import_react22.useState)(null);
|
|
34661
|
+
(0, import_react22.useEffect)(() => {
|
|
34534
34662
|
fetch(`/api/reports/${id}/versions`).then((r) => r.json()).then(setList).catch((e) => setErr(e.message));
|
|
34535
34663
|
}, [id]);
|
|
34536
34664
|
const restore = async (v) => {
|
|
@@ -34540,7 +34668,7 @@ function HistoryDialog({ id, onClose, T, lang: lang2 }) {
|
|
|
34540
34668
|
return;
|
|
34541
34669
|
}
|
|
34542
34670
|
const def = await res.json();
|
|
34543
|
-
|
|
34671
|
+
api.getState().init(id, def);
|
|
34544
34672
|
onClose();
|
|
34545
34673
|
};
|
|
34546
34674
|
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(Dialog, { title: T("versionHistory"), onClose, footer: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("button", { className: "btn", onClick: onClose, children: T("close") }), children: [
|
|
@@ -34562,18 +34690,48 @@ function HistoryDialog({ id, onClose, T, lang: lang2 }) {
|
|
|
34562
34690
|
] }, v.version))
|
|
34563
34691
|
] });
|
|
34564
34692
|
}
|
|
34565
|
-
function Designer({
|
|
34693
|
+
function Designer({ store: storeIn = null, ...props }) {
|
|
34694
|
+
const [store] = (0, import_react22.useState)(() => {
|
|
34695
|
+
const s = storeIn || newDesignerStore();
|
|
34696
|
+
activateStore(s);
|
|
34697
|
+
return s;
|
|
34698
|
+
});
|
|
34699
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DesignerStore.Provider, { value: store, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(DesignerIn, { ...props }) });
|
|
34700
|
+
}
|
|
34701
|
+
var ACTIVATE = [
|
|
34702
|
+
"onPointerDownCapture",
|
|
34703
|
+
"onMouseDownCapture",
|
|
34704
|
+
"onKeyDownCapture",
|
|
34705
|
+
"onFocusCapture",
|
|
34706
|
+
"onClickCapture",
|
|
34707
|
+
"onInputCapture",
|
|
34708
|
+
"onChangeCapture",
|
|
34709
|
+
"onDragStartCapture",
|
|
34710
|
+
"onDragOverCapture",
|
|
34711
|
+
"onDropCapture",
|
|
34712
|
+
"onPasteCapture",
|
|
34713
|
+
"onWheelCapture",
|
|
34714
|
+
"onContextMenuCapture",
|
|
34715
|
+
"onDoubleClickCapture",
|
|
34716
|
+
"onSubmitCapture"
|
|
34717
|
+
];
|
|
34718
|
+
function DesignerIn({ id, initial, rev = null, lang: langIn, embed = null, user = null, ai = false }) {
|
|
34719
|
+
const api = useDesignerStore();
|
|
34720
|
+
const activators = (0, import_react22.useMemo)(() => {
|
|
34721
|
+
const on = () => activateStore(api);
|
|
34722
|
+
return Object.fromEntries(ACTIVATE.map((k) => [k, on]));
|
|
34723
|
+
}, [api]);
|
|
34566
34724
|
const lang2 = pickLang(langIn);
|
|
34567
34725
|
const T = (k, v) => t(lang2, k, v);
|
|
34568
34726
|
const q2 = lang2 === "en" ? "" : `?lang=${encodeURIComponent(lang2)}`;
|
|
34569
|
-
const ready = (0,
|
|
34727
|
+
const ready = (0, import_react22.useRef)(false);
|
|
34570
34728
|
if (!ready.current && typeof window !== "undefined") {
|
|
34571
|
-
|
|
34572
|
-
|
|
34729
|
+
api.getState().init(id, initial);
|
|
34730
|
+
api.getState().setUi({ lang: lang2, embed, readOnly: !!embed?.readOnly, rev, conflict: null });
|
|
34573
34731
|
ready.current = true;
|
|
34574
34732
|
}
|
|
34575
34733
|
const readOnly2 = !!embed?.readOnly;
|
|
34576
|
-
const rootRef = (0,
|
|
34734
|
+
const rootRef = (0, import_react22.useRef)(null);
|
|
34577
34735
|
const def = useDesigner((s) => s.def);
|
|
34578
34736
|
const tab = useDesigner((s) => s.tab);
|
|
34579
34737
|
const saved = useDesigner((s) => s.saved);
|
|
@@ -34583,23 +34741,23 @@ function Designer({ id, initial, rev = null, lang: langIn, embed = null, user =
|
|
|
34583
34741
|
const snap = useDesigner((s) => s.snap);
|
|
34584
34742
|
const unit = useDesigner((s) => s.unit);
|
|
34585
34743
|
const fonts = useDesigner((s) => s.fonts);
|
|
34586
|
-
const fontCss = (0,
|
|
34587
|
-
(0,
|
|
34744
|
+
const fontCss = (0, import_react22.useMemo)(() => fontFaceCss(allFontKeys(), fontsBase().replace(/\/$/, "")), [fonts]);
|
|
34745
|
+
(0, import_react22.useEffect)(() => {
|
|
34588
34746
|
if (embed) declareDocumentStyles("pw-designer-fonts", fontCss);
|
|
34589
34747
|
}, [embed, fontCss]);
|
|
34590
|
-
(0,
|
|
34591
|
-
customFonts().then((list2) =>
|
|
34748
|
+
(0, import_react22.useEffect)(() => {
|
|
34749
|
+
customFonts().then((list2) => api.getState().setUi({ fonts: list2 }));
|
|
34592
34750
|
}, []);
|
|
34593
|
-
(0,
|
|
34751
|
+
(0, import_react22.useEffect)(() => {
|
|
34594
34752
|
const z = savedZoom();
|
|
34595
|
-
if (z != null)
|
|
34753
|
+
if (z != null) api.getState().setUi({ zoom: z });
|
|
34596
34754
|
}, []);
|
|
34597
34755
|
const canUndo = useDesigner((s) => s.past.length > 0);
|
|
34598
34756
|
const canRedo = useDesigner((s) => s.future.length > 0);
|
|
34599
|
-
const st =
|
|
34600
|
-
const [dialog, setDialog] = (0,
|
|
34601
|
-
const [showLeft, setShowLeft] = (0,
|
|
34602
|
-
const [showRight, setShowRight] = (0,
|
|
34757
|
+
const st = api.getState;
|
|
34758
|
+
const [dialog, setDialog] = (0, import_react22.useState)(null);
|
|
34759
|
+
const [showLeft, setShowLeft] = (0, import_react22.useState)(true);
|
|
34760
|
+
const [showRight, setShowRight] = (0, import_react22.useState)(true);
|
|
34603
34761
|
const selKind = useDesigner((s) => s.sel.kind);
|
|
34604
34762
|
const wizard = useDesigner((s) => s.wizard);
|
|
34605
34763
|
const tableWizard = useDesigner((s) => s.tableWizard);
|
|
@@ -34608,12 +34766,18 @@ function Designer({ id, initial, rev = null, lang: langIn, embed = null, user =
|
|
|
34608
34766
|
const cells = useDesigner((s) => s.cells);
|
|
34609
34767
|
const cellSize = useDesigner((s) => s.cellSize);
|
|
34610
34768
|
const dataKey = useDesigner((s) => `${(s.def?.dataSources || []).map((x) => x.name)}|${(s.def?.dataSets || []).map((x) => x.name)}`);
|
|
34611
|
-
(0,
|
|
34612
|
-
loadSample();
|
|
34769
|
+
(0, import_react22.useEffect)(() => {
|
|
34770
|
+
loadSample(api);
|
|
34613
34771
|
}, [dataKey]);
|
|
34614
|
-
(0,
|
|
34772
|
+
(0, import_react22.useEffect)(() => {
|
|
34773
|
+
let lastInside = false;
|
|
34774
|
+
const inside = (e) => (e.composedPath?.() || []).includes(rootRef.current);
|
|
34775
|
+
const onDown = (e) => {
|
|
34776
|
+
lastInside = inside(e);
|
|
34777
|
+
};
|
|
34778
|
+
const ours = (e) => inside(e) || lastInside && (e.target === document.body || e.target === document.documentElement);
|
|
34615
34779
|
const onKey = (e) => {
|
|
34616
|
-
if (embed && !(e
|
|
34780
|
+
if (embed && !ours(e)) return;
|
|
34617
34781
|
const mod = e.metaKey || e.ctrlKey;
|
|
34618
34782
|
if (mod && e.key.toLowerCase() === "s") {
|
|
34619
34783
|
e.preventDefault();
|
|
@@ -34632,7 +34796,7 @@ function Designer({ id, initial, rev = null, lang: langIn, embed = null, user =
|
|
|
34632
34796
|
st().save();
|
|
34633
34797
|
return;
|
|
34634
34798
|
}
|
|
34635
|
-
if (isTyping(e) || st().tab !== "design") return;
|
|
34799
|
+
if (isTyping(e) || st().tab !== "design" || e.defaultPrevented) return;
|
|
34636
34800
|
if (mod && e.key.toLowerCase() === "z") {
|
|
34637
34801
|
e.preventDefault();
|
|
34638
34802
|
e.shiftKey ? st().redo() : st().undo();
|
|
@@ -34655,11 +34819,7 @@ function Designer({ id, initial, rev = null, lang: langIn, embed = null, user =
|
|
|
34655
34819
|
}
|
|
34656
34820
|
return;
|
|
34657
34821
|
}
|
|
34658
|
-
if (mod && e.key.toLowerCase() === "v")
|
|
34659
|
-
e.preventDefault();
|
|
34660
|
-
pasteItems(st().sel.kind === "section" ? st().sel.section : "body");
|
|
34661
|
-
return;
|
|
34662
|
-
}
|
|
34822
|
+
if (mod && e.key.toLowerCase() === "v") return;
|
|
34663
34823
|
if (e.key === "Delete" || e.key === "Backspace") {
|
|
34664
34824
|
if (st().sel.kind === "items") {
|
|
34665
34825
|
e.preventDefault();
|
|
@@ -34691,10 +34851,24 @@ function Designer({ id, initial, rev = null, lang: langIn, embed = null, user =
|
|
|
34691
34851
|
e.returnValue = "";
|
|
34692
34852
|
}
|
|
34693
34853
|
};
|
|
34854
|
+
const onPaste = (e) => {
|
|
34855
|
+
if (embed && !ours(e) || isTyping(e) || st().tab !== "design") return;
|
|
34856
|
+
e.preventDefault();
|
|
34857
|
+
if (!pasteItems(st().sel.kind === "section" ? st().sel.section : "body", e.clipboardData?.getData("text/plain"))) {
|
|
34858
|
+
st().setUi({ saveError: t(lang2, "b9_nothingToPaste") });
|
|
34859
|
+
setTimeout(() => st().setUi({ saveError: null }), 3e3);
|
|
34860
|
+
}
|
|
34861
|
+
};
|
|
34694
34862
|
window.addEventListener("keydown", onKey);
|
|
34863
|
+
window.addEventListener("paste", onPaste);
|
|
34864
|
+
window.addEventListener("pointerdown", onDown, true);
|
|
34865
|
+
window.addEventListener("focusin", onDown, true);
|
|
34695
34866
|
if (!embed) window.addEventListener("beforeunload", onLeave);
|
|
34696
34867
|
return () => {
|
|
34697
34868
|
window.removeEventListener("keydown", onKey);
|
|
34869
|
+
window.removeEventListener("paste", onPaste);
|
|
34870
|
+
window.removeEventListener("pointerdown", onDown, true);
|
|
34871
|
+
window.removeEventListener("focusin", onDown, true);
|
|
34698
34872
|
window.removeEventListener("beforeunload", onLeave);
|
|
34699
34873
|
};
|
|
34700
34874
|
}, [st, embed]);
|
|
@@ -34713,17 +34887,17 @@ function Designer({ id, initial, rev = null, lang: langIn, embed = null, user =
|
|
|
34713
34887
|
const d = await embed.onOpen();
|
|
34714
34888
|
if (d && typeof d === "object") {
|
|
34715
34889
|
st().init(id, d);
|
|
34716
|
-
loadSample();
|
|
34890
|
+
loadSample(api);
|
|
34717
34891
|
}
|
|
34718
34892
|
};
|
|
34719
|
-
const importInput = (0,
|
|
34720
|
-
const [imported, setImported] = (0,
|
|
34893
|
+
const importInput = (0, import_react22.useRef)(null);
|
|
34894
|
+
const [imported, setImported] = (0, import_react22.useState)(null);
|
|
34721
34895
|
const importFile = async (file) => {
|
|
34722
34896
|
if (!file) return;
|
|
34723
34897
|
const r = readReportFile(file.name, await file.text());
|
|
34724
34898
|
if (r.definition) {
|
|
34725
34899
|
st().init(id, r.definition);
|
|
34726
|
-
loadSample();
|
|
34900
|
+
loadSample(api);
|
|
34727
34901
|
}
|
|
34728
34902
|
setImported({ name: file.name, ok: !!r.definition, warnings: r.warnings || [], error: r.error });
|
|
34729
34903
|
};
|
|
@@ -34737,7 +34911,7 @@ function Designer({ id, initial, rev = null, lang: langIn, embed = null, user =
|
|
|
34737
34911
|
] }),
|
|
34738
34912
|
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "hint", children: T("loadingDesigner") })
|
|
34739
34913
|
] }) });
|
|
34740
|
-
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "designer", "data-testid": "designer", dir: dirOf(lang2), lang: lang2, ref: rootRef, "data-readonly": readOnly2 || void 0, children: [
|
|
34914
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "designer", "data-testid": "designer", dir: dirOf(lang2), lang: lang2, ref: rootRef, "data-readonly": readOnly2 || void 0, ...activators, children: [
|
|
34741
34915
|
!embed && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("style", { children: fontCss }),
|
|
34742
34916
|
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("header", { className: "dtop dbar", children: [
|
|
34743
34917
|
embed ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { className: "brand", children: [
|
|
@@ -34844,7 +35018,7 @@ function Designer({ id, initial, rev = null, lang: langIn, embed = null, user =
|
|
|
34844
35018
|
imported.warnings.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("ul", { children: imported.warnings.map((w, i2) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("li", { children: w }, i2)) })
|
|
34845
35019
|
] }),
|
|
34846
35020
|
dialog === "keys" && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Dialog, { title: T("shortcuts"), onClose: () => setDialog(null), footer: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("button", { className: "btn", onClick: () => setDialog(null), children: T("close") }), children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "kbd-grid", children: SHORTCUTS.map(([k, d]) => /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
34847
|
-
|
|
35021
|
+
import_react22.Fragment, { children: [
|
|
34848
35022
|
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "kbd", children: k }),
|
|
34849
35023
|
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { children: T(d) })
|
|
34850
35024
|
] }, d)) }) }),
|
|
@@ -34926,6 +35100,7 @@ var CSS2 = true ? `/* Layout: a drafting table. Cool grey workspace, white paper
|
|
|
34926
35100
|
--ink: #16202a;
|
|
34927
35101
|
--muted: #5f6b77;
|
|
34928
35102
|
--faint: #64717e; /* 5:1 on panel (was #8e99a4, 2.9:1) */
|
|
35103
|
+
--faint-desk: #5a6672; /* small text on the desk: 4.85:1 on #e6eaee (--faint is 4.13:1 there) */
|
|
34929
35104
|
--line-strong: #848f9b; /* control borders, 3:1 */
|
|
34930
35105
|
--accent: #0e7490;
|
|
34931
35106
|
--accent-ink: #ffffff;
|
|
@@ -34979,6 +35154,7 @@ var CSS2 = true ? `/* Layout: a drafting table. Cool grey workspace, white paper
|
|
|
34979
35154
|
--ink: #e6edf3;
|
|
34980
35155
|
--muted: #a3afbb;
|
|
34981
35156
|
--faint: #8693a0;
|
|
35157
|
+
--faint-desk: #8693a0;
|
|
34982
35158
|
--accent: #3cbfd4;
|
|
34983
35159
|
--accent-ink: #03222a;
|
|
34984
35160
|
--accent-soft: #123a44;
|
|
@@ -35317,7 +35493,7 @@ a.cell-name:hover { color: var(--accent); }
|
|
|
35317
35493
|
.tbl .grip { position: absolute; left: -18px; top: -18px; width: 14px; height: 14px; border-radius: 3px; background: var(--panel-2); border: 1px solid var(--line); display: grid; place-items: center; cursor: move; font-size: var(--fs-2xs); color: var(--muted); }
|
|
35318
35494
|
.tbl.sel .grip { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); }
|
|
35319
35495
|
.tbl .row { position: relative; display: flex; }
|
|
35320
|
-
.tbl .row-tag { position: absolute; left: -18px; width: 14px; display: grid; place-items: center; font: var(--fs-2xs) var(--mono); color: var(--faint); height: 100%; }
|
|
35496
|
+
.tbl .row-tag { position: absolute; left: -18px; width: 14px; display: grid; place-items: center; font: var(--fs-2xs) var(--mono); color: var(--faint-desk); height: 100%; }
|
|
35321
35497
|
.tbl .cell { position: relative; overflow: hidden; display: flex; border-right: 1px dashed rgba(95,107,119,.3); border-bottom: 1px dashed rgba(95,107,119,.3); cursor: cell; }
|
|
35322
35498
|
.tbl .cell:first-child { border-left: 1px dashed rgba(95,107,119,.3); }
|
|
35323
35499
|
.tbl .row:first-child .cell { border-top: 1px dashed rgba(95,107,119,.3); }
|
|
@@ -35837,7 +36013,7 @@ input[type=checkbox], input[type=radio] { width: 16px; height: 16px; accent-colo
|
|
|
35837
36013
|
|
|
35838
36014
|
.pw-embed{display:block;font:var(--fw-regular) var(--fs-base)/var(--lh) var(--ui);color:var(--ink);background:var(--desk);border:1px solid var(--line);border-radius:8px;overflow:hidden}
|
|
35839
36015
|
` : "";
|
|
35840
|
-
var BLANK = { $schema: "pagewright/report@1", name: "
|
|
36016
|
+
var BLANK = { $schema: "pagewright/report@1", name: "Untitled report", page: { size: "A4", margins: [36, 36, 36, 36] }, dataSources: [], dataSets: [], sections: { body: { items: [] } } };
|
|
35841
36017
|
function mountDesigner(target, opts = {}) {
|
|
35842
36018
|
const el = typeof target === "string" ? document.querySelector(target) : target;
|
|
35843
36019
|
if (!el) throw new Error(`mountDesigner: no element for ${target}`);
|
|
@@ -35855,18 +36031,43 @@ function mountDesigner(target, opts = {}) {
|
|
|
35855
36031
|
);
|
|
35856
36032
|
box.style.height = opts.height || "760px";
|
|
35857
36033
|
const root = (0, import_client.createRoot)(box);
|
|
36034
|
+
const store = newDesignerStore();
|
|
35858
36035
|
const embed = { onSave: opts.onSave, onOpen: opts.onOpen, readOnly: !!opts.readOnly, toolbox: opts.toolbox, panels: opts.panels, dataSourceTemplates: opts.dataSourceTemplates, server: server2 };
|
|
35859
36036
|
const show = (definition) => loadLanguage(opts.lang).catch(() => {
|
|
35860
|
-
}).then(() => root.render((0,
|
|
36037
|
+
}).then(() => root.render((0, import_react23.createElement)(Designer, { id: opts.report, initial: definition, lang: opts.lang, embed, store })));
|
|
35861
36038
|
if (opts.definition || !opts.report) show(opts.definition || BLANK);
|
|
35862
36039
|
else fetch(`${server2}/api/reports/${encodeURIComponent(opts.report)}`).then((r) => r.ok ? r.json() : r.json().then((j) => Promise.reject(new Error(j.error || `HTTP ${r.status}`)))).then(show).catch((e) => {
|
|
35863
36040
|
box.innerHTML = `<div class="vmsg error">The report did not load: ${String(e.message).replace(/</g, "<")}</div>`;
|
|
35864
36041
|
});
|
|
36042
|
+
const onLeave = (e) => {
|
|
36043
|
+
e.preventDefault();
|
|
36044
|
+
e.returnValue = "";
|
|
36045
|
+
};
|
|
36046
|
+
let dirty = false;
|
|
36047
|
+
const unsub = store.subscribe((s) => {
|
|
36048
|
+
if (!s.saved === dirty) return;
|
|
36049
|
+
dirty = !s.saved;
|
|
36050
|
+
if (opts.warnOnLeave !== false) {
|
|
36051
|
+
if (dirty) window.addEventListener("beforeunload", onLeave);
|
|
36052
|
+
else window.removeEventListener("beforeunload", onLeave);
|
|
36053
|
+
}
|
|
36054
|
+
try {
|
|
36055
|
+
opts.onDirtyChange?.(dirty);
|
|
36056
|
+
} catch (e) {
|
|
36057
|
+
console.error(e);
|
|
36058
|
+
}
|
|
36059
|
+
});
|
|
35865
36060
|
return {
|
|
35866
|
-
unmount: () =>
|
|
36061
|
+
unmount: () => {
|
|
36062
|
+
unsub();
|
|
36063
|
+
window.removeEventListener("beforeunload", onLeave);
|
|
36064
|
+
root.unmount();
|
|
36065
|
+
},
|
|
36066
|
+
/** whether there are changes not saved yet */
|
|
36067
|
+
isDirty: () => !store.getState().saved,
|
|
35867
36068
|
/** the definition as it is now (a plain copy) */
|
|
35868
|
-
getDefinition: () => JSON.parse(JSON.stringify(
|
|
35869
|
-
save: () =>
|
|
36069
|
+
getDefinition: () => JSON.parse(JSON.stringify(store.getState().def)),
|
|
36070
|
+
save: () => store.getState().save()
|
|
35870
36071
|
};
|
|
35871
36072
|
}
|
|
35872
36073
|
export {
|