@eintrek/erp-shell 0.1.72 → 0.1.73
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -0
- package/dist/chunks/{guide-runtime-B-3myqxe.esm.js → guide-runtime-C7Z00QwM.esm.js} +76 -6
- package/dist/chunks/guide-runtime-C7Z00QwM.esm.js.map +1 -0
- package/dist/chunks/{guide-runtime-DfnNdrjZ.cjs → guide-runtime-CLVSNkTN.cjs} +76 -5
- package/dist/chunks/guide-runtime-CLVSNkTN.cjs.map +1 -0
- package/dist/guide/core.d.ts +1 -1
- package/dist/guide/guide-store.d.ts +8 -0
- package/dist/guide/guide-styles.d.ts +1 -1
- package/dist/guide/guide-ui.d.ts +2 -0
- package/dist/guide/machine.d.ts +17 -0
- package/dist/guide/types.d.ts +8 -0
- package/dist/guide-core.cjs +2 -1
- package/dist/guide-core.cjs.map +1 -1
- package/dist/guide-core.esm.js +1 -1
- package/dist/index.cjs +4 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.esm.js +5 -5
- package/dist/index.esm.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
- package/dist/chunks/guide-runtime-B-3myqxe.esm.js.map +0 -1
- package/dist/chunks/guide-runtime-DfnNdrjZ.cjs.map +0 -1
|
@@ -357,6 +357,16 @@ function publishGuideEntry(next, openPanel) {
|
|
|
357
357
|
emit();
|
|
358
358
|
}
|
|
359
359
|
}
|
|
360
|
+
/**
|
|
361
|
+
* Whether the "?" menu offers "ไกด์เริ่มต้น": a tour whose missions are all
|
|
362
|
+
* hidden for this user (`visible`, e.g. Plannex without an employee record)
|
|
363
|
+
* has nothing to open, and "0/0" led to an empty panel. The entry itself
|
|
364
|
+
* stays published: apps wait on it before they load the facts that make
|
|
365
|
+
* missions visible.
|
|
366
|
+
*/
|
|
367
|
+
function guideMenuShown(e) {
|
|
368
|
+
return !!e && e.total > 0;
|
|
369
|
+
}
|
|
360
370
|
/** Opens the tour's quest panel, when this user has a tour here. */
|
|
361
371
|
function openGuidePanel() {
|
|
362
372
|
openPanelImpl?.();
|
|
@@ -823,6 +833,7 @@ function enterStep(d, suite, env, mission, index, opts) {
|
|
|
823
833
|
const where = placeRoute(steps, i);
|
|
824
834
|
const away = !!where && !matchRoute(where, env.pathname, env.search, env.code);
|
|
825
835
|
const bridge = !away && needsBridge(step, env, ctx);
|
|
836
|
+
const nts = !away && !bridge && nothingToSaveHolds(step, env, ctx);
|
|
826
837
|
setScreen(d, {
|
|
827
838
|
name: "step",
|
|
828
839
|
mission: mission.key,
|
|
@@ -834,7 +845,9 @@ function enterStep(d, suite, env, mission, index, opts) {
|
|
|
834
845
|
confirmExit: false,
|
|
835
846
|
misses: 0,
|
|
836
847
|
armed: hiddenAnchorShown(step, env),
|
|
837
|
-
nothingToSave:
|
|
848
|
+
nothingToSave: nts,
|
|
849
|
+
status: away || bridge ? null : stepStatus(shownStep(step, nts), ctx),
|
|
850
|
+
replayNext: !away && !bridge && opts.replay && replayCanGoOn(mission, i, env, d.state.progress.context, nts),
|
|
838
851
|
});
|
|
839
852
|
if (!opts.replay) {
|
|
840
853
|
const cp = checkpointAtOrBefore(steps, i);
|
|
@@ -877,6 +890,54 @@ function setNothingToSave(d, suite, env, on) {
|
|
|
877
890
|
if (stepTargetVisible(step, env, ctx, s.bridge))
|
|
878
891
|
announceStep(d, suite, env);
|
|
879
892
|
}
|
|
893
|
+
/** The step's status line (GuideStep.status): trimmed text, or null. */
|
|
894
|
+
function stepStatus(step, ctx) {
|
|
895
|
+
if (!step.status)
|
|
896
|
+
return null;
|
|
897
|
+
const text = safe(() => step.status(ctx), undefined);
|
|
898
|
+
return typeof text === "string" && text.trim() ? text.trim() : null;
|
|
899
|
+
}
|
|
900
|
+
/**
|
|
901
|
+
* In a replay, whether a "select" step may go on with ถัดไป: the next step
|
|
902
|
+
* this person sees has its target on the page already (or there is none).
|
|
903
|
+
* A pick that makes the next step's target (a save shown only once the
|
|
904
|
+
* right value is chosen) is still needed.
|
|
905
|
+
*/
|
|
906
|
+
function replayCanGoOn(mission, index, env, context, nothingToSave = false) {
|
|
907
|
+
if (stepKind(shownStep(mission.steps[index], nothingToSave)) !== "select")
|
|
908
|
+
return false;
|
|
909
|
+
for (let i = index + 1; i < mission.steps.length; i++) {
|
|
910
|
+
const next = mission.steps[i];
|
|
911
|
+
const ctx = guideContext(env, context, routeParamsFor(next, env));
|
|
912
|
+
if (next.requires && !safe(() => env.can(next.requires), true))
|
|
913
|
+
continue;
|
|
914
|
+
if (next.skipIf && safe(() => next.skipIf(ctx), false))
|
|
915
|
+
continue;
|
|
916
|
+
if (!next.target)
|
|
917
|
+
return true;
|
|
918
|
+
if (stepTargetVisible(next, env, ctx, false))
|
|
919
|
+
return true;
|
|
920
|
+
// A commit step with nothing to save is read on its saved state.
|
|
921
|
+
return nothingToSaveHolds(next, env, ctx);
|
|
922
|
+
}
|
|
923
|
+
return true;
|
|
924
|
+
}
|
|
925
|
+
/** Keep the status line and a replay's ถัดไป current (the page changed). */
|
|
926
|
+
function syncStatus(d, suite, env) {
|
|
927
|
+
const s = d.state.screen;
|
|
928
|
+
if (s.name !== "step")
|
|
929
|
+
return;
|
|
930
|
+
const mission = findMission(suite, s.mission);
|
|
931
|
+
if (!mission)
|
|
932
|
+
return;
|
|
933
|
+
const step = shownStep(mission.steps[s.index], s.nothingToSave);
|
|
934
|
+
const ctx = guideContext(env, d.state.progress.context, routeParamsFor(step, env));
|
|
935
|
+
const off = s.phase === "away" || s.bridge;
|
|
936
|
+
const status = off ? null : stepStatus(step, ctx);
|
|
937
|
+
const replayNext = !off && s.replay && replayCanGoOn(mission, s.index, env, d.state.progress.context, s.nothingToSave);
|
|
938
|
+
if (status !== s.status || replayNext !== s.replayNext)
|
|
939
|
+
setScreen(d, { ...s, status, replayNext });
|
|
940
|
+
}
|
|
880
941
|
function markReadyIfVisible(d, suite, env) {
|
|
881
942
|
const s = d.state.screen;
|
|
882
943
|
if (s.name !== "step" || s.phase !== "waiting")
|
|
@@ -1262,6 +1323,7 @@ function reduceGuide(state, action, suite, env) {
|
|
|
1262
1323
|
else if (!cur.bridge && needsBridge(step, env, ctx)) {
|
|
1263
1324
|
setScreen(d, { ...cur, bridge: true, phase: "waiting" });
|
|
1264
1325
|
}
|
|
1326
|
+
syncStatus(d, suite, env);
|
|
1265
1327
|
markReadyIfVisible(d, suite, env);
|
|
1266
1328
|
break;
|
|
1267
1329
|
}
|
|
@@ -1324,6 +1386,12 @@ function reduceGuide(state, action, suite, env) {
|
|
|
1324
1386
|
advance(d, suite, env);
|
|
1325
1387
|
break;
|
|
1326
1388
|
}
|
|
1389
|
+
if (kind === "select") {
|
|
1390
|
+
// A replay goes on without a pick when the next step is on the page.
|
|
1391
|
+
if (s.replay && replayCanGoOn(mission, s.index, env, d.state.progress.context, s.nothingToSave))
|
|
1392
|
+
advance(d, suite, env);
|
|
1393
|
+
break;
|
|
1394
|
+
}
|
|
1327
1395
|
if (kind !== "input")
|
|
1328
1396
|
break;
|
|
1329
1397
|
const ctx = guideContext(env, d.state.progress.context, routeParamsFor(step, env));
|
|
@@ -2330,6 +2398,7 @@ const GUIDE_CSS = `
|
|
|
2330
2398
|
.eg-b-t{margin:0;font-size:16px;font-weight:600;line-height:1.45}
|
|
2331
2399
|
.eg-b-w{margin:2px 0 0;font-size:13.5px;color:var(--eg-muted)}
|
|
2332
2400
|
.eg-bubble.eg-err .eg-b-t{color:var(--eg-danger)}
|
|
2401
|
+
.eg-b-s{margin:6px 0 0;font-size:13px;font-weight:600;color:var(--eg-danger)}
|
|
2333
2402
|
.eg-k{display:inline-block;background:var(--eg-tint);color:var(--eg-strong);border-radius:7px;padding:0 7px;font-weight:600}
|
|
2334
2403
|
.eg-b-f{display:flex;align-items:center;justify-content:space-between;margin-top:12px;gap:8px}
|
|
2335
2404
|
.eg-b-f .eg-btn{height:34px;padding:0 14px;font-size:13.5px}
|
|
@@ -2563,7 +2632,7 @@ function StepLayer(p) {
|
|
|
2563
2632
|
const showBubble = p.phase === "ready" && (!!spot || !p.hasTarget);
|
|
2564
2633
|
const gap = p.showHand ? 34 : 14;
|
|
2565
2634
|
const spotKey = spot ? `${spot.x}|${spot.y}|${spot.width}|${spot.height}` : "";
|
|
2566
|
-
const contentKey = `${p.bubble.title}|${p.bubble.why}|${p.bubble.error?.title ?? ""}|${p.bubble.showNext}`;
|
|
2635
|
+
const contentKey = `${p.bubble.title}|${p.bubble.why}|${p.bubble.error?.title ?? ""}|${p.bubble.status ?? ""}|${p.bubble.showNext}`;
|
|
2567
2636
|
// What the bubble sits beside: the target, with an open list over it (the
|
|
2568
2637
|
// list is what the person is choosing from now). What it must not cover:
|
|
2569
2638
|
// open lists, and the other anchors the step allows (a map step's
|
|
@@ -2686,7 +2755,7 @@ function BubbleBody(p) {
|
|
|
2686
2755
|
const b = p.bubble;
|
|
2687
2756
|
const title = b.error ? b.error.title : b.title;
|
|
2688
2757
|
const why = b.error ? (b.error.detail ?? "") : b.why;
|
|
2689
|
-
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", { className: "eg-b-top", children: [jsxRuntime.jsxs("span", { className: "eg-mis", children: ["\u0E20\u0E32\u0E23\u0E01\u0E34\u0E08 ", b.missionNo, " \u00B7 ", b.missionTitle, b.replay ? " (ทบทวน)" : ""] }), jsxRuntime.jsxs("span", { className: "eg-cnt", children: ["\u0E02\u0E31\u0E49\u0E19\u0E17\u0E35\u0E48 ", b.index + 1, "/", b.total] })] }), jsxRuntime.jsx("div", { className: "eg-pips", "aria-hidden": "true", children: Array.from({ length: b.total }, (_, i) => (jsxRuntime.jsx("i", { className: i < b.index ? "eg-d" : i === b.index ? "eg-c" : undefined }, i))) }), jsxRuntime.jsx("p", { className: "eg-b-t", id: BUBBLE_TITLE_ID, children: jsxRuntime.jsx(GuideTitle, { text: title }) }), jsxRuntime.jsx("p", { className: "eg-b-w", id: BUBBLE_WHY_ID, hidden: !why, children: jsxRuntime.jsx(GuideTitle, { text: why }) }), jsxRuntime.jsxs("div", { className: "eg-b-f", children: [jsxRuntime.jsx("button", { type: "button", className: "eg-exit", onClick: p.onExit, children: b.replay ? "จบการทบทวน" : "ออกจากไกด์" }), jsxRuntime.jsxs("span", { style: { display: "flex", gap: 6 }, children: [b.showEndWithoutSave ? (jsxRuntime.jsx("button", { type: "button", className: "eg-btn eg-ghost", onClick: p.onEndWithoutSave, children: "\u0E08\u0E1A\u0E42\u0E14\u0E22\u0E44\u0E21\u0E48\u0E1A\u0E31\u0E19\u0E17\u0E36\u0E01" })) : null, b.showNext ? (jsxRuntime.jsx("button", { type: "button", className: "eg-btn eg-primary", onClick: p.onNext, children: "\u0E16\u0E31\u0E14\u0E44\u0E1B" })) : null] })] })] }));
|
|
2758
|
+
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs("div", { className: "eg-b-top", children: [jsxRuntime.jsxs("span", { className: "eg-mis", children: ["\u0E20\u0E32\u0E23\u0E01\u0E34\u0E08 ", b.missionNo, " \u00B7 ", b.missionTitle, b.replay ? " (ทบทวน)" : ""] }), jsxRuntime.jsxs("span", { className: "eg-cnt", children: ["\u0E02\u0E31\u0E49\u0E19\u0E17\u0E35\u0E48 ", b.index + 1, "/", b.total] })] }), jsxRuntime.jsx("div", { className: "eg-pips", "aria-hidden": "true", children: Array.from({ length: b.total }, (_, i) => (jsxRuntime.jsx("i", { className: i < b.index ? "eg-d" : i === b.index ? "eg-c" : undefined }, i))) }), jsxRuntime.jsx("p", { className: "eg-b-t", id: BUBBLE_TITLE_ID, children: jsxRuntime.jsx(GuideTitle, { text: title }) }), jsxRuntime.jsx("p", { className: "eg-b-w", id: BUBBLE_WHY_ID, hidden: !why, children: jsxRuntime.jsx(GuideTitle, { text: why }) }), b.status && !b.error ? (jsxRuntime.jsx("p", { className: "eg-b-s", role: "status", "data-eg-status": "", children: b.status })) : null, jsxRuntime.jsxs("div", { className: "eg-b-f", children: [jsxRuntime.jsx("button", { type: "button", className: "eg-exit", onClick: p.onExit, children: b.replay ? "จบการทบทวน" : "ออกจากไกด์" }), jsxRuntime.jsxs("span", { style: { display: "flex", gap: 6 }, children: [b.showEndWithoutSave ? (jsxRuntime.jsx("button", { type: "button", className: "eg-btn eg-ghost", onClick: p.onEndWithoutSave, children: "\u0E08\u0E1A\u0E42\u0E14\u0E22\u0E44\u0E21\u0E48\u0E1A\u0E31\u0E19\u0E17\u0E36\u0E01" })) : null, b.showNext ? (jsxRuntime.jsx("button", { type: "button", className: "eg-btn eg-primary", onClick: p.onNext, children: "\u0E16\u0E31\u0E14\u0E44\u0E1B" })) : null] })] })] }));
|
|
2690
2759
|
}
|
|
2691
2760
|
/** The fingertip at ≈62% across and down the target; upside down near the bottom. */
|
|
2692
2761
|
function handPosition(spot, viewportHeight) {
|
|
@@ -3838,7 +3907,8 @@ function GuideRuntimeInner({ config, organizationId, code, routing, progress: pr
|
|
|
3838
3907
|
title: bridge ? "กดปุ่มเมนู" : resolveText(step.title, stepCtx),
|
|
3839
3908
|
why: bridge ? `เมนูทั้งหมดของ ${suite.appName} อยู่ในนี้` : resolveText(step.why, stepCtx),
|
|
3840
3909
|
error: screen.error,
|
|
3841
|
-
|
|
3910
|
+
status: bridge ? null : screen.status,
|
|
3911
|
+
showNext: !bridge && (kind === "input" || kind === "view" || (kind === "select" && screen.replay && screen.replayNext)),
|
|
3842
3912
|
showEndWithoutSave: !bridge && screen.replay && kind === "commit",
|
|
3843
3913
|
}, hasTarget: bridge || !!step.target, targetPressable: targetPressable(step, bridge), phase: screen.phase, confirmExit: screen.confirmExit, reopenHint: suite.reopenHint, nudge: state.nudge, moving: moving, onExit: () => dispatch({ type: "exit" }), onNext: () => dispatch({ type: "next" }), onEndWithoutSave: () => dispatch({ type: "endWithoutSave" }), onRetry: () => dispatch({ type: "retry" }), onGoResume: () => dispatch({ type: "goResume" }), onExitConfirm: () => dispatch({ type: "exitConfirm" }), onExitCancel: () => dispatch({ type: "exitCancel" }) }));
|
|
3844
3914
|
}
|
|
@@ -3900,6 +3970,7 @@ exports.apiCallDetail = apiCallDetail;
|
|
|
3900
3970
|
exports.emitGuideEvent = emitGuideEvent;
|
|
3901
3971
|
exports.fillRoute = fillRoute;
|
|
3902
3972
|
exports.guideAnchor = guideAnchor;
|
|
3973
|
+
exports.guideMenuShown = guideMenuShown;
|
|
3903
3974
|
exports.loadGuides = loadGuides;
|
|
3904
3975
|
exports.matchApiPath = matchApiPath;
|
|
3905
3976
|
exports.matchRoute = matchRoute;
|
|
@@ -3908,4 +3979,4 @@ exports.reportApiCall = reportApiCall;
|
|
|
3908
3979
|
exports.reportApiEvent = reportApiEvent;
|
|
3909
3980
|
exports.storeGuides = storeGuides;
|
|
3910
3981
|
exports.useGuideEntry = useGuideEntry;
|
|
3911
|
-
//# sourceMappingURL=guide-runtime-
|
|
3982
|
+
//# sourceMappingURL=guide-runtime-CLVSNkTN.cjs.map
|