@eintrek/erp-shell 0.1.74 → 0.1.76
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 +50 -0
- package/dist/chunks/{guide-runtime-YS2nUhwS.cjs → format-BVoVc7Yk.cjs} +1012 -71
- package/dist/chunks/format-BVoVc7Yk.cjs.map +1 -0
- package/dist/chunks/{guide-runtime-Dl8V1iy9.esm.js → format-BWUKNKxg.esm.js} +1004 -73
- package/dist/chunks/format-BWUKNKxg.esm.js.map +1 -0
- package/dist/guide/core.d.ts +4 -2
- package/dist/guide/format.d.ts +26 -0
- package/dist/guide/guide-store.d.ts +52 -4
- package/dist/guide/guide-ui.d.ts +16 -2
- package/dist/guide/machine.d.ts +86 -10
- package/dist/guide/pages.d.ts +52 -1
- package/dist/guide/progress-sync.d.ts +3 -2
- package/dist/guide/progress.d.ts +8 -4
- package/dist/guide/section-button.d.ts +12 -0
- package/dist/guide/types.d.ts +100 -0
- package/dist/guide-core.cjs +34 -24
- package/dist/guide-core.cjs.map +1 -1
- package/dist/guide-core.esm.js +1 -1
- package/dist/help/help-button.d.ts +5 -2
- package/dist/index.cjs +53 -36
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.esm.js +15 -8
- 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-Dl8V1iy9.esm.js.map +0 -1
- package/dist/chunks/guide-runtime-YS2nUhwS.cjs.map +0 -1
package/dist/guide/core.d.ts
CHANGED
|
@@ -10,9 +10,11 @@
|
|
|
10
10
|
* The main entry re-exports the same modules, so a tour defined against
|
|
11
11
|
* either entry is the same data, and the bus and the "?" entry are shared.
|
|
12
12
|
*/
|
|
13
|
-
export type { GuideAbortAction, GuideAnchorKey, GuideApiFailure, GuideApiMatch, GuideAppId, GuideCaptureEvent, GuideConfig, GuideContext, GuideFacts, GuideGate, GuideMission, GuideNothingToSave, GuideOnMissing, GuidePage, GuideStep, GuideStepKind, GuideSuite, GuideText, GuideTrigger, } from "./types";
|
|
13
|
+
export type { GuideAbortAction, GuideAnchorKey, GuideApiFailure, GuideApiMatch, GuideAppId, GuideCaptureEvent, GuideConfig, GuideContext, GuideFacts, GuideFlow, GuideGate, GuideMission, GuideNothingToSave, GuideOnMissing, GuidePage, GuideSection, GuideStep, GuideStepKind, GuideSuite, GuideText, GuideTrigger, } from "./types";
|
|
14
14
|
export { API_EVENT as GUIDE_API_EVENT, GUIDE_EVENT_PREFIX, GUIDE_LAYER_ATTRIBUTE, apiCallDetail, emitGuideEvent, guideAnchor, reportApiCall, reportApiEvent, type ApiCallReport, type ApiEventDetail, type GuideAnchorProps, } from "./events";
|
|
15
|
-
export { guideMenuItems, guideMenuShown, openGuidePanel, openPageGuide, openPagesPanel, useGuideEntry, usePageGuideEntry, usePageGuides, type GuideEntry, type GuideMenuItem, type PageGuidesEntry, } from "./guide-store";
|
|
15
|
+
export { guideMenuItems, guideMenuShown, openGuidePanel, openPageGuide, openPagesPanel, openSectionGuide, openFlow, openFlowsPanel, setSectionGuideValues, useGuideEntry, usePageGuideEntry, usePageGuides, useSectionGuideValues, type GuideEntry, type GuideMenuItem, type PageGuidesEntry, } from "./guide-store";
|
|
16
|
+
export { SectionGuideButton, type SectionGuideButtonProps } from "./section-button";
|
|
17
|
+
export { THAI_MONTHS_SHORT, formatBaht, thaiMonth, thaiMonthYear } from "./format";
|
|
16
18
|
export { GuideRuntime, type GuideMenu, type GuideRouting, type GuideRuntimeProps, } from "./guide-runtime";
|
|
17
19
|
export { GuideProgressConflict, loadGuides, storeGuides, type GuideProgressAdapter, type GuideProgressRequest, type GuideProgressResponse, } from "./progress-sync";
|
|
18
20
|
export type { GuideAudience, GuideMode, PagesMode } from "./progress";
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Small formatters for section guides' copy (shell 0.1.75): the app passes
|
|
3
|
+
* its own computed numbers, and the copy says them the way the page does —
|
|
4
|
+
* "ม.ค. รับ 500,000 − จ่าย 320,000 = คงเหลือ 180,000".
|
|
5
|
+
*
|
|
6
|
+
* Pure: the tests run it in Node.
|
|
7
|
+
*/
|
|
8
|
+
export declare const THAI_MONTHS_SHORT: readonly ["ม.ค.", "ก.พ.", "มี.ค.", "เม.ย.", "พ.ค.", "มิ.ย.", "ก.ค.", "ส.ค.", "ก.ย.", "ต.ค.", "พ.ย.", "ธ.ค."];
|
|
9
|
+
/**
|
|
10
|
+
* A baht amount with thousands separators, no currency sign: 500000 →
|
|
11
|
+
* "500,000"; 1234.5 → "1,234.50"; -320000 → "-320,000". Whole amounts
|
|
12
|
+
* have no decimals unless `decimals` says so; others have two. Not a
|
|
13
|
+
* finite number → "" (a step whose value is missing is skipped anyway).
|
|
14
|
+
*/
|
|
15
|
+
export declare function formatBaht(n: unknown, opts?: {
|
|
16
|
+
decimals?: number;
|
|
17
|
+
}): string;
|
|
18
|
+
/** "2026-01" (or a Date, or 1) → "ม.ค."; "" when it is not a month. */
|
|
19
|
+
export declare function thaiMonth(m: unknown): string;
|
|
20
|
+
/**
|
|
21
|
+
* "2026-01" → "ม.ค. 69" (the Buddhist year's last two digits), or with
|
|
22
|
+
* `{ year: "full" }` "ม.ค. 2569"; just the month when no year is known.
|
|
23
|
+
*/
|
|
24
|
+
export declare function thaiMonthYear(m: unknown, opts?: {
|
|
25
|
+
year?: "short" | "full";
|
|
26
|
+
}): string;
|
|
@@ -21,11 +21,30 @@ export interface PageGuidesEntry {
|
|
|
21
21
|
} | null;
|
|
22
22
|
/** Page guides with an `href` this person has (the panel's list). */
|
|
23
23
|
listed: number;
|
|
24
|
+
/**
|
|
25
|
+
* Section guides on screen here that this person has ("อธิบายส่วนนี้ ·
|
|
26
|
+
* <title>"), in the suite's order. Shell ≥ 0.1.75.
|
|
27
|
+
*/
|
|
28
|
+
sections?: ReadonlyArray<{
|
|
29
|
+
key: string;
|
|
30
|
+
title: string;
|
|
31
|
+
}>;
|
|
32
|
+
/** Flows that start on this page ("พาทำ · <title>"). Shell ≥ 0.1.76. */
|
|
33
|
+
flows?: ReadonlyArray<{
|
|
34
|
+
key: string;
|
|
35
|
+
title: string;
|
|
36
|
+
}>;
|
|
37
|
+
/** Flows this person has (the panel's "พาทำงาน" list). Shell ≥ 0.1.76. */
|
|
38
|
+
flowsListed?: number;
|
|
24
39
|
}
|
|
25
|
-
/** Called by the host: this page's guide
|
|
26
|
-
export declare function publishPageGuides(next: PageGuidesEntry | null, openPage: (() => void) | null, openPages: (() => void) | null): void;
|
|
27
|
-
/**
|
|
28
|
-
|
|
40
|
+
/** Called by the host: this page's guide, the listed count, the sections on screen, and how to open them. */
|
|
41
|
+
export declare function publishPageGuides(next: PageGuidesEntry | null, openPage: (() => void) | null, openPages: (() => void) | null, openSection?: ((key: string) => void) | null, openFlow?: ((key: string) => void) | null, openFlows?: (() => void) | null): void;
|
|
42
|
+
/**
|
|
43
|
+
* The "?" menu's items, in order (pure: the menu and its tests share it).
|
|
44
|
+
* "sections": one entry per section guide; "flowsHere": one "พาทำ · <title>"
|
|
45
|
+
* per flow starting here; "flows": "พาทำงาน" (the panel's flows).
|
|
46
|
+
*/
|
|
47
|
+
export type GuideMenuItem = "page" | "sections" | "flowsHere" | "missions" | "pages" | "flows" | "help";
|
|
29
48
|
export declare function guideMenuItems(e: GuideEntry | null, p?: PageGuidesEntry): GuideMenuItem[];
|
|
30
49
|
/**
|
|
31
50
|
* Whether the "?" press opens a menu rather than the help dialog: a tour
|
|
@@ -55,3 +74,32 @@ export declare function usePageGuideEntry(): {
|
|
|
55
74
|
title: string;
|
|
56
75
|
open: () => void;
|
|
57
76
|
} | null;
|
|
77
|
+
/**
|
|
78
|
+
* Opens a section guide ("อธิบายส่วนนี้"), when it is on screen here for this
|
|
79
|
+
* person. The values it shows are the ones the app last rendered
|
|
80
|
+
* (`useSectionGuideValues`).
|
|
81
|
+
*/
|
|
82
|
+
export declare function openSectionGuide(key: string): void;
|
|
83
|
+
/** Starts a flow that starts on this page ("พาทำ · <title>"). */
|
|
84
|
+
export declare function openFlow(key: string): void;
|
|
85
|
+
/** Opens the panel on the flows alone ("พาทำงาน"). */
|
|
86
|
+
export declare function openFlowsPanel(): void;
|
|
87
|
+
type Values = Readonly<Record<string, unknown>>;
|
|
88
|
+
/**
|
|
89
|
+
* Sets (or with undefined, clears) a section guide's live values. The
|
|
90
|
+
* engine reads the latest whenever it draws a step, so a page that
|
|
91
|
+
* re-renders mid-guide never leaves an old number on screen.
|
|
92
|
+
*/
|
|
93
|
+
export declare function setSectionGuideValues(key: string, values: Values | undefined): void;
|
|
94
|
+
/** A section guide's live values now (empty when the app has given none). */
|
|
95
|
+
export declare function getSectionGuideValues(key: string | null | undefined): Values;
|
|
96
|
+
/** Re-renders when any section guide's values change (the engine's own use). */
|
|
97
|
+
export declare function useSectionValuesVersion(): number;
|
|
98
|
+
/**
|
|
99
|
+
* Hands a section guide the numbers its copy uses, from the component that
|
|
100
|
+
* computes them: `useSectionGuideValues("cash-flow", { month: "ม.ค.", cashIn,
|
|
101
|
+
* … })`. Call it on every render (the latest wins); they go when the
|
|
102
|
+
* component unmounts. undefined values: nothing.
|
|
103
|
+
*/
|
|
104
|
+
export declare function useSectionGuideValues(key: string, values: Values | undefined): void;
|
|
105
|
+
export {};
|
package/dist/guide/guide-ui.d.ts
CHANGED
|
@@ -191,7 +191,8 @@ export declare function PageOfferCard(p: {
|
|
|
191
191
|
title: string;
|
|
192
192
|
steps: number;
|
|
193
193
|
onStart: () => void;
|
|
194
|
-
onLater: () => void;
|
|
194
|
+
onLater: () => void; /** "คู่มือหน้านี้" by default; a flow's: "พาทำงาน". */
|
|
195
|
+
eyebrow?: string;
|
|
195
196
|
}): import("react/jsx-runtime").JSX.Element;
|
|
196
197
|
/** One page guide in the panel's "คู่มือแต่ละหน้า" list. */
|
|
197
198
|
export interface PageItem {
|
|
@@ -200,6 +201,14 @@ export interface PageItem {
|
|
|
200
201
|
/** This person has ended this version (ดูแล้ว); otherwise ใหม่. */
|
|
201
202
|
seen: boolean;
|
|
202
203
|
}
|
|
204
|
+
/** One flow in the panel's "พาทำงาน" list. Shell ≥ 0.1.76. */
|
|
205
|
+
export interface FlowItem {
|
|
206
|
+
key: string;
|
|
207
|
+
title: string;
|
|
208
|
+
minutes?: number;
|
|
209
|
+
/** This person has finished this version (ทำแล้ว). */
|
|
210
|
+
done: boolean;
|
|
211
|
+
}
|
|
203
212
|
export declare function QuestChip({ done, total, pulse, onOpen }: {
|
|
204
213
|
done: number;
|
|
205
214
|
total: number;
|
|
@@ -236,9 +245,14 @@ export declare function QuestPanel(p: {
|
|
|
236
245
|
* (shell ≥ 0.1.74). Omitted or empty: no section.
|
|
237
246
|
*/
|
|
238
247
|
pages?: PageItem[];
|
|
239
|
-
/** false:
|
|
248
|
+
/** false: no missions (none for this person, "คู่มือทุกหน้า" or "พาทำงาน"). */
|
|
240
249
|
showMissions?: boolean;
|
|
241
250
|
onOpenPage?: (key: string) => void;
|
|
251
|
+
/** The "พาทำงาน" section: the flows this person has (shell ≥ 0.1.76). */
|
|
252
|
+
flows?: FlowItem[];
|
|
253
|
+
onOpenFlow?: (key: string) => void;
|
|
254
|
+
/** Without missions: one list alone ("คู่มือทุกหน้า" → pages, "พาทำงาน" → flows). */
|
|
255
|
+
only?: "pages" | "flows";
|
|
242
256
|
}): import("react/jsx-runtime").JSX.Element;
|
|
243
257
|
export declare function GuideToast({ text }: {
|
|
244
258
|
text: string;
|
package/dist/guide/machine.d.ts
CHANGED
|
@@ -58,11 +58,16 @@ export type GuideScreen = {
|
|
|
58
58
|
replayNext: boolean;
|
|
59
59
|
/** A page guide's step: the page key (the mission is `page:<key>`). Shell ≥ 0.1.74. */
|
|
60
60
|
page?: string;
|
|
61
|
+
/** A section guide's step: the section key (the mission is `section:<key>`). Shell ≥ 0.1.75. */
|
|
62
|
+
section?: string;
|
|
63
|
+
/** A flow's step: the flow key (the mission is `flow:<key>`). Shell ≥ 0.1.76. */
|
|
64
|
+
flow?: string;
|
|
61
65
|
}
|
|
62
66
|
/** The first-visit offer of this page's guide: a small card, not modal. */
|
|
63
67
|
| {
|
|
64
68
|
name: "pageOffer";
|
|
65
|
-
page: string;
|
|
69
|
+
page: string; /** The offer is a flow's (`page` is the flow key). Shell ≥ 0.1.76. */
|
|
70
|
+
flow?: boolean;
|
|
66
71
|
} | {
|
|
67
72
|
name: "celebrate";
|
|
68
73
|
mission: string;
|
|
@@ -98,24 +103,43 @@ export interface GuideState {
|
|
|
98
103
|
pagesMode: PagesMode;
|
|
99
104
|
/** Page rows by page key, as the server holds them (or as just written). */
|
|
100
105
|
pages: Record<string, PageRow>;
|
|
106
|
+
/** Section rows by section key (`<app>.section.<key>`). Shell ≥ 0.1.75. */
|
|
107
|
+
sections: Record<string, PageRow>;
|
|
108
|
+
/** Flow rows by flow key (`<app>.flow.<key>`). Shell ≥ 0.1.76. */
|
|
109
|
+
flows: Record<string, PageRow>;
|
|
101
110
|
/**
|
|
102
|
-
* The page guide being played: `write` when its row is still
|
|
103
|
-
* written (the offer was taken, or this person has never ended this
|
|
104
|
-
* version); a replay
|
|
111
|
+
* The page or section guide being played: `write` when its row is still
|
|
112
|
+
* to be written (the offer was taken, or this person has never ended this
|
|
113
|
+
* version); a replay of a recorded one writes nothing.
|
|
105
114
|
*/
|
|
106
115
|
pageRun: {
|
|
107
116
|
key: string;
|
|
108
117
|
write: boolean;
|
|
118
|
+
kind?: ReadKind;
|
|
119
|
+
/** A flow's: the tour's captured ids before it started, put back at its end. */
|
|
120
|
+
context?: Record<string, string>;
|
|
121
|
+
} | null;
|
|
122
|
+
/** What the panel shows: everything, the page guides alone ("คู่มือทุกหน้า"), or the flows alone ("พาทำงาน"). */
|
|
123
|
+
panelSection: "all" | "pages" | "flows";
|
|
124
|
+
/**
|
|
125
|
+
* Steps of the mission being played that passed by themselves (a click
|
|
126
|
+
* whose outcome already held): not counted in "ขั้นที่ x/y". Shell ≥ 0.1.75.
|
|
127
|
+
*/
|
|
128
|
+
autoPassed: {
|
|
129
|
+
mission: string;
|
|
130
|
+
steps: number[];
|
|
109
131
|
} | null;
|
|
110
|
-
/** What the panel shows: everything, or the page guides alone ("คู่มือทุกหน้า"). */
|
|
111
|
-
panelSection: "all" | "pages";
|
|
112
132
|
}
|
|
113
133
|
/** The page-guide part of the state, from the progress answer. */
|
|
114
134
|
export interface GuidePagesInit {
|
|
115
135
|
pageAudience: GuideAudience;
|
|
116
136
|
pagesMode: PagesMode;
|
|
117
137
|
pages: Record<string, PageRow>;
|
|
138
|
+
sections?: Record<string, PageRow>;
|
|
139
|
+
flows?: Record<string, PageRow>;
|
|
118
140
|
}
|
|
141
|
+
/** A guide with its own row: a page guide, a section guide or a flow. */
|
|
142
|
+
export type ReadKind = "page" | "section" | "flow";
|
|
119
143
|
export interface ReplayPage {
|
|
120
144
|
mission: string;
|
|
121
145
|
/** The mission's abort anchors that were on the page at the start. */
|
|
@@ -138,6 +162,8 @@ export interface GuideEnv {
|
|
|
138
162
|
targetValue: () => string;
|
|
139
163
|
/** An app dialog (not the tour's) is open. */
|
|
140
164
|
dialogOpen?: () => boolean;
|
|
165
|
+
/** The running (or opening) section guide's live values (GuideContext.values). */
|
|
166
|
+
values?: Readonly<Record<string, unknown>>;
|
|
141
167
|
}
|
|
142
168
|
export type GuideSignal = {
|
|
143
169
|
kind: "api";
|
|
@@ -221,7 +247,7 @@ export type GuideAction = {
|
|
|
221
247
|
type: "dismissComplete";
|
|
222
248
|
} | {
|
|
223
249
|
type: "openPanel";
|
|
224
|
-
section?: "all" | "pages";
|
|
250
|
+
section?: "all" | "pages" | "flows";
|
|
225
251
|
} | {
|
|
226
252
|
type: "closePanel";
|
|
227
253
|
} | {
|
|
@@ -242,10 +268,11 @@ export type GuideAction = {
|
|
|
242
268
|
| {
|
|
243
269
|
type: "idleCelebrate";
|
|
244
270
|
}
|
|
245
|
-
/** The host found this page's guide
|
|
271
|
+
/** The host found this page's guide (or, with `flow`, a flow) due: show the offer card. */
|
|
246
272
|
| {
|
|
247
273
|
type: "pageOffer";
|
|
248
274
|
page: string;
|
|
275
|
+
flow?: boolean;
|
|
249
276
|
}
|
|
250
277
|
/** The offer's [เริ่ม]. */
|
|
251
278
|
| {
|
|
@@ -269,6 +296,25 @@ export type GuideAction = {
|
|
|
269
296
|
type: "pageRow";
|
|
270
297
|
key: string;
|
|
271
298
|
row: PageRow;
|
|
299
|
+
kind?: ReadKind;
|
|
300
|
+
}
|
|
301
|
+
/** "อธิบายส่วนนี้": a section guide on screen here (its button, or "?"). */
|
|
302
|
+
| {
|
|
303
|
+
type: "startSection";
|
|
304
|
+
section: string;
|
|
305
|
+
}
|
|
306
|
+
/** "พาทำ · <title>", or the panel's "พาทำงาน" (once on its start page). */
|
|
307
|
+
| {
|
|
308
|
+
type: "startFlow";
|
|
309
|
+
flow: string;
|
|
310
|
+
}
|
|
311
|
+
/** After a refresh, in the same session: back into a flow at its checkpoint. */
|
|
312
|
+
| {
|
|
313
|
+
type: "resumeFlow";
|
|
314
|
+
flow: string;
|
|
315
|
+
step: string;
|
|
316
|
+
context: Record<string, string>;
|
|
317
|
+
write: boolean;
|
|
272
318
|
};
|
|
273
319
|
export type GuideEffect = {
|
|
274
320
|
type: "save";
|
|
@@ -291,12 +337,13 @@ export type GuideEffect = {
|
|
|
291
337
|
type: "abort";
|
|
292
338
|
actions: GuideAbortAction[];
|
|
293
339
|
}
|
|
294
|
-
/** Write a page guide's row, once: `<app>.page.<key>`. */
|
|
340
|
+
/** Write a page (or section) guide's row, once: `<app>.page.<key>` / `<app>.section.<key>`. */
|
|
295
341
|
| {
|
|
296
342
|
type: "savePage";
|
|
297
343
|
key: string;
|
|
298
344
|
version: number;
|
|
299
345
|
status: "completed" | "skipped";
|
|
346
|
+
kind?: ReadKind;
|
|
300
347
|
};
|
|
301
348
|
export interface GuideResult {
|
|
302
349
|
state: GuideState;
|
|
@@ -312,6 +359,8 @@ export declare const COPY: {
|
|
|
312
359
|
readonly hiddenToast: "ซ่อนแล้ว";
|
|
313
360
|
readonly aborted: "ไกด์ไปต่อไม่ได้ ลองอีกครั้งภายหลัง";
|
|
314
361
|
readonly pageDone: "จบคู่มือหน้านี้";
|
|
362
|
+
readonly sectionDone: "จบคำอธิบายส่วนนี้";
|
|
363
|
+
readonly flowDone: "พาทำงานเสร็จแล้ว";
|
|
315
364
|
readonly bridgeTitle: "กดปุ่มเมนู";
|
|
316
365
|
readonly bridgeWhy: (app: string) => string;
|
|
317
366
|
};
|
|
@@ -389,10 +438,14 @@ export declare function chipVisible(state: GuideState, suite: GuideSuite, ctx: G
|
|
|
389
438
|
* whose `requires` they lack or whose `skipIf` holds is left out (the step on
|
|
390
439
|
* screen always counts).
|
|
391
440
|
*/
|
|
392
|
-
export declare function stepPosition(mission: GuideMission, index: number, env: GuideEnv, context: Readonly<Record<string, string
|
|
441
|
+
export declare function stepPosition(mission: GuideMission, index: number, env: GuideEnv, context: Readonly<Record<string, string>>, autoPassed?: readonly number[]): {
|
|
393
442
|
no: number;
|
|
394
443
|
total: number;
|
|
395
444
|
};
|
|
445
|
+
/** A step entered now would pass at once: a click or select step whose route or visible outcome holds. */
|
|
446
|
+
export declare function wouldAutoPass(step: GuideStep, env: GuideEnv): boolean;
|
|
447
|
+
/** The steps of this mission that passed by themselves in this run. */
|
|
448
|
+
export declare function autoPassedOf(state: GuideState, mission: string): readonly number[];
|
|
396
449
|
/** "กด [บันทึก]" → "กด บันทึก" (for screen readers). */
|
|
397
450
|
export declare function plainTitle(t: string): string;
|
|
398
451
|
/** The step's status line (GuideStep.status): trimmed text, or null. */
|
|
@@ -428,6 +481,29 @@ export declare function firstStepReady(suite: GuideSuite, pageKey: string, env:
|
|
|
428
481
|
* route, a moment of nothing loading, the primary tab, not hidden.
|
|
429
482
|
*/
|
|
430
483
|
export declare function pageOfferDue(state: GuideState, suite: GuideSuite, env: GuideEnv): string | null;
|
|
484
|
+
/** The section guide's row says this person has ended this version of it. */
|
|
485
|
+
export declare function sectionRecorded(state: GuideState, section: {
|
|
486
|
+
key: string;
|
|
487
|
+
version: number;
|
|
488
|
+
}): boolean;
|
|
489
|
+
/** The flow's row says this person has ended this version of it. */
|
|
490
|
+
export declare function flowRecorded(state: GuideState, flow: {
|
|
491
|
+
key: string;
|
|
492
|
+
version: number;
|
|
493
|
+
}): boolean;
|
|
494
|
+
/** The flows this person has that start on this page ("พาทำ · <title>"). */
|
|
495
|
+
export declare function flowsAvailable(suite: GuideSuite, env: GuideEnv): string[];
|
|
496
|
+
/**
|
|
497
|
+
* The flow to offer now, or null: only in "offer" mode, only a flow that
|
|
498
|
+
* says `offer: true`, on its start page, with no row of this version, when
|
|
499
|
+
* nothing else is up and this page's own guide is not due (it comes first:
|
|
500
|
+
* no guide here, offer: false, or already recorded), its first step's
|
|
501
|
+
* target on screen, no app dialog open. The host adds the welcome and the
|
|
502
|
+
* idle wait, as for the page guide's offer.
|
|
503
|
+
*/
|
|
504
|
+
export declare function flowOfferDue(state: GuideState, suite: GuideSuite, env: GuideEnv): string | null;
|
|
505
|
+
/** The section guides on screen here that this person has (the "?" entries, the buttons). */
|
|
506
|
+
export declare function sectionsAvailable(suite: GuideSuite, env: GuideEnv): string[];
|
|
431
507
|
/** The step before this one that this person sees, or -1. */
|
|
432
508
|
export declare function previousShownIndex(mission: GuideMission, index: number, env: GuideEnv, context: Readonly<Record<string, string>>): number;
|
|
433
509
|
/**
|
package/dist/guide/pages.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* A page guide runs through the missions' machinery as a synthetic mission
|
|
7
7
|
* `page:<key>` in replay mode, so nothing it does writes tour progress.
|
|
8
8
|
*/
|
|
9
|
-
import type { GuideContext, GuideMission, GuidePage, GuideSuite } from "./types";
|
|
9
|
+
import type { GuideContext, GuideFlow, GuideMission, GuidePage, GuideSection, GuideSuite } from "./types";
|
|
10
10
|
/** The synthetic mission key of a page guide: `page:<key>`. */
|
|
11
11
|
export declare const PAGE_PREFIX = "page:";
|
|
12
12
|
export declare function isPageMissionKey(key: string | null | undefined): boolean;
|
|
@@ -54,3 +54,54 @@ export declare function pageShown(page: GuidePage, ctx: GuideContext): boolean;
|
|
|
54
54
|
export declare function currentPage(suite: GuideSuite, where: PageWhere, ctx: GuideContext): GuidePage | null;
|
|
55
55
|
/** The page guides this person has, for the panel's list (those with an `href`). */
|
|
56
56
|
export declare function listedPages(suite: GuideSuite, ctx: GuideContext): GuidePage[];
|
|
57
|
+
/** The synthetic mission key of a section guide: `section:<key>`. */
|
|
58
|
+
export declare const SECTION_PREFIX = "section:";
|
|
59
|
+
export declare function isSectionMissionKey(key: string | null | undefined): boolean;
|
|
60
|
+
export declare function sectionKeyOf(missionKey: string | null | undefined): string | undefined;
|
|
61
|
+
/** Why a section guide cannot run, or null when it can. */
|
|
62
|
+
export declare function sectionProblem(app: string, section: GuideSection): string | null;
|
|
63
|
+
/** The suite's section guides that can run (as validPages: the rest dropped, with a warning in development). */
|
|
64
|
+
export declare function validSections(suite: GuideSuite): GuideSection[];
|
|
65
|
+
export declare function findSection(suite: GuideSuite, key: string | null | undefined): GuideSection | undefined;
|
|
66
|
+
/** A live value is missing: undefined, null, "" or a number that is not finite. */
|
|
67
|
+
export declare function valueMissing(v: unknown): boolean;
|
|
68
|
+
/**
|
|
69
|
+
* The section guide as a mission the machine plays: `section:<key>`, read
|
|
70
|
+
* steps only, checkpoints unless they say otherwise. A step is skipped while
|
|
71
|
+
* a value it `needs` is missing, or when its title comes out empty.
|
|
72
|
+
*/
|
|
73
|
+
export declare function sectionMission(section: GuideSection): GuideMission;
|
|
74
|
+
/** Whether the section guide applies here: one of its routes matches and its root is on screen. */
|
|
75
|
+
export declare function sectionApplies(section: GuideSection, where: PageWhere): boolean;
|
|
76
|
+
/** Whether this person has the section guide: `visible` (only true) and `requires`. */
|
|
77
|
+
export declare function sectionShown(section: GuideSection, ctx: GuideContext): boolean;
|
|
78
|
+
/** The section guides on screen here that this person has, in the suite's order. */
|
|
79
|
+
export declare function sectionsHere(suite: GuideSuite, where: PageWhere, ctx: GuideContext): GuideSection[];
|
|
80
|
+
/** The synthetic mission key of a flow: `flow:<key>`. */
|
|
81
|
+
export declare const FLOW_PREFIX = "flow:";
|
|
82
|
+
export declare function isFlowMissionKey(key: string | null | undefined): boolean;
|
|
83
|
+
export declare function flowKeyOf(missionKey: string | null | undefined): string | undefined;
|
|
84
|
+
/** Why a flow cannot run, or null when it can. */
|
|
85
|
+
export declare function flowProblem(app: string, flow: GuideFlow): string | null;
|
|
86
|
+
/** The suite's flows that can run (as validPages: the rest dropped, with a warning in development). */
|
|
87
|
+
export declare function validFlows(suite: GuideSuite): GuideFlow[];
|
|
88
|
+
export declare function findFlow(suite: GuideSuite, key: string | null | undefined): GuideFlow | undefined;
|
|
89
|
+
/** The flow as a mission the machine plays (in replay mode): `flow:<key>`, its steps as authored. */
|
|
90
|
+
export declare function flowMission(flow: GuideFlow): GuideMission;
|
|
91
|
+
/**
|
|
92
|
+
* The flow's chain: its start routes, every step's `route` and route
|
|
93
|
+
* trigger, and its `transit` routes. Leaving all of them ends the flow.
|
|
94
|
+
*/
|
|
95
|
+
export declare function flowChain(flow: GuideFlow): string[];
|
|
96
|
+
/** Whether the person is on one of the flow's pages. */
|
|
97
|
+
export declare function inFlowChain(flow: GuideFlow, where: Pick<PageWhere, "code" | "pathname">): boolean;
|
|
98
|
+
/** Whether the person is on the flow's start page. */
|
|
99
|
+
export declare function onFlowStart(flow: GuideFlow, where: Pick<PageWhere, "code" | "pathname" | "search">): boolean;
|
|
100
|
+
/** Whether this person has the flow: `visible` (only true) and `requires`. */
|
|
101
|
+
export declare function flowShown(flow: GuideFlow, ctx: GuideContext): boolean;
|
|
102
|
+
/** The flows this person has (the panel's "พาทำงาน" list), in the suite's order. */
|
|
103
|
+
export declare function shownFlows(suite: GuideSuite, ctx: GuideContext): GuideFlow[];
|
|
104
|
+
/** The flows this person has that start on this page ("พาทำ · <title>"). */
|
|
105
|
+
export declare function flowsHere(suite: GuideSuite, where: PageWhere, ctx: GuideContext): GuideFlow[];
|
|
106
|
+
/** Where the panel sends the person to start a flow, or null when it needs an id it does not have. */
|
|
107
|
+
export declare function flowHref(flow: GuideFlow, ctx: GuideContext): string | null;
|
|
@@ -67,10 +67,11 @@ export declare function loadGuides(adapter: GuideProgressAdapter, suite: GuideSu
|
|
|
67
67
|
*/
|
|
68
68
|
export declare function storeGuides(adapter: GuideProgressAdapter, suite: GuideSuite, progress: GuideProgress): Promise<GuideProgress | null>;
|
|
69
69
|
/**
|
|
70
|
-
* Writes a page guide's row (`<app>.page.<key>`)
|
|
70
|
+
* Writes a page guide's row (`<app>.page.<key>`), or a section guide's
|
|
71
|
+
* (`<app>.section.<key>`, kind "section"), once: the minimal body,
|
|
71
72
|
* with the same 409 handling as the tour's row. Another tab that already
|
|
72
73
|
* recorded this version wins (its row is returned, nothing is sent again);
|
|
73
74
|
* an older version's row is replaced with its rev; a newer one stops. Returns
|
|
74
75
|
* the stored row, or null when it could not be saved.
|
|
75
76
|
*/
|
|
76
|
-
export declare function storePageRow(adapter: GuideProgressAdapter, app: string, key: string, version: number, status: "completed" | "skipped", rev: number): Promise<PageRow | null>;
|
|
77
|
+
export declare function storePageRow(adapter: GuideProgressAdapter, app: string, key: string, version: number, status: "completed" | "skipped", rev: number, kind?: "page" | "section" | "flow"): Promise<PageRow | null>;
|
package/dist/guide/progress.d.ts
CHANGED
|
@@ -55,6 +55,10 @@ export interface GuidesAnswer {
|
|
|
55
55
|
pageAudience: GuideAudience;
|
|
56
56
|
/** Page rows by page key (the part after `<app>.page.`). */
|
|
57
57
|
pages: Record<string, PageRow>;
|
|
58
|
+
/** Section rows by section key (the part after `<app>.section.`). Shell ≥ 0.1.75. */
|
|
59
|
+
sections: Record<string, PageRow>;
|
|
60
|
+
/** Flow rows by flow key (the part after `<app>.flow.`). Shell ≥ 0.1.76. */
|
|
61
|
+
flows: Record<string, PageRow>;
|
|
58
62
|
/** The suite's row; a fresh one when the user has none or an older version. */
|
|
59
63
|
progress: GuideProgress;
|
|
60
64
|
/** The server holds a newer version than this app's tour: do not run. */
|
|
@@ -72,10 +76,10 @@ export declare function parseGuidesAnswer(payload: unknown, suite: {
|
|
|
72
76
|
version: number;
|
|
73
77
|
app: string;
|
|
74
78
|
}): GuidesAnswer | null;
|
|
75
|
-
/** The row key of a page guide
|
|
76
|
-
export declare function pageRowKey(app: string, key: string): string;
|
|
77
|
-
/** Page rows among the list's rows, by
|
|
78
|
-
export declare function parsePageRows(rows: unknown[], app: string): Record<string, PageRow>;
|
|
79
|
+
/** The row key of a page guide `<app>.page.<key>`, a section guide `<app>.section.<key>`, or a flow `<app>.flow.<key>`. */
|
|
80
|
+
export declare function pageRowKey(app: string, key: string, kind?: "page" | "section" | "flow"): string;
|
|
81
|
+
/** Page (or section) rows among the list's rows, by key. Off-shape rows are left out. */
|
|
82
|
+
export declare function parsePageRows(rows: unknown[], app: string, kind?: "page" | "section" | "flow"): Record<string, PageRow>;
|
|
79
83
|
/** One page row (a list entry, a PUT answer, a 409's `current`); null when off-shape. */
|
|
80
84
|
export declare function parsePageRow(raw: unknown): PageRow | null;
|
|
81
85
|
/**
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface SectionGuideButtonProps {
|
|
2
|
+
/** The GuideSection's key. */
|
|
3
|
+
guideKey: string;
|
|
4
|
+
/**
|
|
5
|
+
* The numbers the guide's copy uses (`ctx.values`), from this render.
|
|
6
|
+
* Optional: the section may call `useSectionGuideValues` itself instead.
|
|
7
|
+
*/
|
|
8
|
+
values?: Readonly<Record<string, unknown>>;
|
|
9
|
+
/** Replaces the default look (a 22px round icon button in the text colour). */
|
|
10
|
+
className?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function SectionGuideButton({ guideKey, values, className }: SectionGuideButtonProps): import("react/jsx-runtime").JSX.Element | null;
|
package/dist/guide/types.d.ts
CHANGED
|
@@ -41,6 +41,12 @@ export interface GuideContext {
|
|
|
41
41
|
can: (policyKey: string) => boolean;
|
|
42
42
|
/** Whether an anchor is on screen now. */
|
|
43
43
|
visible: (anchor: GuideAnchorKey) => boolean;
|
|
44
|
+
/**
|
|
45
|
+
* A section guide's live values, as the app last rendered them
|
|
46
|
+
* (`useSectionGuideValues` / `SectionGuideButton values`); empty
|
|
47
|
+
* elsewhere. Shell ≥ 0.1.75.
|
|
48
|
+
*/
|
|
49
|
+
values?: Readonly<Record<string, unknown>>;
|
|
44
50
|
}
|
|
45
51
|
/** Text that may depend on the context. */
|
|
46
52
|
export type GuideText = string | ((ctx: GuideContext) => string);
|
|
@@ -171,6 +177,12 @@ export interface GuideStep {
|
|
|
171
177
|
status?: (ctx: GuideContext) => string | null | undefined;
|
|
172
178
|
/** Skip the step (silently) when true. Runs every time it is entered. */
|
|
173
179
|
skipIf?: (ctx: GuideContext) => boolean;
|
|
180
|
+
/**
|
|
181
|
+
* Section guides: the live values this step's copy uses
|
|
182
|
+
* (`ctx.values`). The step is skipped while any is missing (undefined,
|
|
183
|
+
* null, "" or a number that is not finite). Shell ≥ 0.1.75.
|
|
184
|
+
*/
|
|
185
|
+
needs?: string[];
|
|
174
186
|
/** A policy key the step needs (checked with `guides.can`); skipped when
|
|
175
187
|
* the user lacks it. */
|
|
176
188
|
requires?: string;
|
|
@@ -378,6 +390,90 @@ export interface GuidePage {
|
|
|
378
390
|
*/
|
|
379
391
|
steps: GuideStep[];
|
|
380
392
|
}
|
|
393
|
+
/**
|
|
394
|
+
* A section guide ("อธิบายส่วนนี้", shell ≥ 0.1.75): explains one section of
|
|
395
|
+
* a page — a number-heavy card or table — row by row, with the formula and
|
|
396
|
+
* this record's own numbers. Read-only ("view" steps only; a step may point
|
|
397
|
+
* at a row or cell inside the section with `targetId`), never offered by
|
|
398
|
+
* itself: it opens from the section's `SectionGuideButton` or from "?" →
|
|
399
|
+
* "อธิบายส่วนนี้ · <title>". Same switch and audience as page guides
|
|
400
|
+
* (`guides.<app>.pages` not off); one row per section guide per person,
|
|
401
|
+
* `<app>.section.<key>`, written once. Authors:
|
|
402
|
+
* _claude-work/guides-r4/GUIDE-PAGES.md §10.
|
|
403
|
+
*/
|
|
404
|
+
export interface GuideSection {
|
|
405
|
+
/** Stable, [a-z0-9-]: the row key is `${suite.app}.section.${key}` (≤ 64 characters). */
|
|
406
|
+
key: string;
|
|
407
|
+
version: number;
|
|
408
|
+
/** The page(s) the section is on, as GuidePage.route. */
|
|
409
|
+
route: string | string[];
|
|
410
|
+
/** The section's root: the guide is there only while it is on screen. */
|
|
411
|
+
anchor: GuideAnchorKey;
|
|
412
|
+
/** "สรุปกระแสเงินสด": the "?" entry and the bubble's heading. ≤ 40 characters. */
|
|
413
|
+
title: string;
|
|
414
|
+
/** Only `true` shows it (as GuideMission.visible). */
|
|
415
|
+
visible?: (ctx: GuideContext) => boolean | undefined;
|
|
416
|
+
/** A policy key the section needs (checked with `guides.can`). */
|
|
417
|
+
requires?: string;
|
|
418
|
+
/**
|
|
419
|
+
* "view" steps (the default here), about 12 at most; titles ≤ 40 and whys
|
|
420
|
+
* ≤ 90 characters (the app's tests check). Copy may be a function of
|
|
421
|
+
* `ctx.values`; list what it uses in `needs`, and a step whose value is
|
|
422
|
+
* missing is skipped (so is one whose title comes out empty).
|
|
423
|
+
*/
|
|
424
|
+
steps: GuideStep[];
|
|
425
|
+
}
|
|
426
|
+
/**
|
|
427
|
+
* A workflow guide ("พาทำงาน", shell ≥ 0.1.76): walks one job across pages —
|
|
428
|
+
* "เปิดใบขอซื้อจากบรรทัดงบ" — and stops before anything irreversible. Not a
|
|
429
|
+
* mission: never in "ไกด์เริ่มต้น n/N" or the welcome. Same switch and
|
|
430
|
+
* audience as page guides (`guides.<app>.pages` not off; every member,
|
|
431
|
+
* filtered by `visible` / `requires`). Listed under "?" → "พาทำงาน" and,
|
|
432
|
+
* on its start page, "พาทำ · <title>". One row per flow per person,
|
|
433
|
+
* `<app>.flow.<key>`, written once at the end (completed or skipped).
|
|
434
|
+
* Authors: _claude-work/guides-r4/GUIDE-PAGES.md §11.
|
|
435
|
+
*/
|
|
436
|
+
export interface GuideFlow {
|
|
437
|
+
/** Stable, [a-z0-9-]: the row key is `${suite.app}.flow.${key}` (≤ 64 characters). */
|
|
438
|
+
key: string;
|
|
439
|
+
/** Raise it to offer this flow again (only when `offer: true`). */
|
|
440
|
+
version: number;
|
|
441
|
+
/** "เปิดใบขอซื้อจากบรรทัดงบ": the "?" entries, the panel, the bubble. ≤ 30 characters. */
|
|
442
|
+
title: string;
|
|
443
|
+
/** Rough minutes, for "ประมาณ n นาที" in the panel. */
|
|
444
|
+
minutes?: number;
|
|
445
|
+
/** Only `true` shows it (as GuideMission.visible). */
|
|
446
|
+
visible?: (ctx: GuideContext) => boolean | undefined;
|
|
447
|
+
/** A policy key the flow needs (checked with `guides.can`). */
|
|
448
|
+
requires?: string;
|
|
449
|
+
/** Where it starts: "พาทำ · <title>" is in "?" there, and the offer (if any) only there. */
|
|
450
|
+
startRoute: string | string[];
|
|
451
|
+
/**
|
|
452
|
+
* Where the panel's "พาทำงาน" list sends the person to start it, when
|
|
453
|
+
* `startRoute` needs an id (`[code]` is filled in). Default: the first
|
|
454
|
+
* `startRoute` when it has no other params.
|
|
455
|
+
*/
|
|
456
|
+
href?: GuideText;
|
|
457
|
+
/**
|
|
458
|
+
* Pages the flow may pass through without ending (a redirect, a picker
|
|
459
|
+
* page), besides `startRoute` and its steps' routes.
|
|
460
|
+
*/
|
|
461
|
+
transit?: string[];
|
|
462
|
+
/** true: offered once on its start page in `offer` mode, after the missions and the page guide's offer. Default false. */
|
|
463
|
+
offer?: boolean;
|
|
464
|
+
/**
|
|
465
|
+
* true: the flow may save something harmless and reversible ("commit",
|
|
466
|
+
* "input" and "select" steps). Every commit step must name its `abort`.
|
|
467
|
+
* Default false: "view" and "click" steps only.
|
|
468
|
+
*/
|
|
469
|
+
allowCommit?: boolean;
|
|
470
|
+
/**
|
|
471
|
+
* Steps as a mission's: `route`, checkpoints and resume across pages. The
|
|
472
|
+
* last step on an irreversible button is a "view" step (the app's
|
|
473
|
+
* deny-list test checks).
|
|
474
|
+
*/
|
|
475
|
+
steps: GuideStep[];
|
|
476
|
+
}
|
|
381
477
|
/** One app's whole tour: the welcome, the missions, the finish. */
|
|
382
478
|
export interface GuideSuite {
|
|
383
479
|
/** Progress key on the server, "<app>.<name>": "peoplx.first-run". */
|
|
@@ -423,6 +519,10 @@ export interface GuideSuite {
|
|
|
423
519
|
missions: GuideMission[];
|
|
424
520
|
/** Page guides ("คู่มือหน้านี้"), shell ≥ 0.1.74. */
|
|
425
521
|
pages?: GuidePage[];
|
|
522
|
+
/** Section guides ("อธิบายส่วนนี้"), shell ≥ 0.1.75. */
|
|
523
|
+
sections?: GuideSection[];
|
|
524
|
+
/** Workflow guides ("พาทำงาน"), shell ≥ 0.1.76. */
|
|
525
|
+
flows?: GuideFlow[];
|
|
426
526
|
}
|
|
427
527
|
/** AppLayoutShell's `guides` prop. */
|
|
428
528
|
export interface GuideConfig {
|