@eintrek/erp-shell 0.1.75 → 0.1.77

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.
@@ -10,9 +10,9 @@
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, GuideSection, 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, openSectionGuide, setSectionGuideValues, useGuideEntry, usePageGuideEntry, usePageGuides, useSectionGuideValues, 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
16
  export { SectionGuideButton, type SectionGuideButtonProps } from "./section-button";
17
17
  export { THAI_MONTHS_SHORT, formatBaht, thaiMonth, thaiMonthYear } from "./format";
18
18
  export { GuideRuntime, type GuideMenu, type GuideRouting, type GuideRuntimeProps, } from "./guide-runtime";
@@ -29,11 +29,22 @@ export interface PageGuidesEntry {
29
29
  key: string;
30
30
  title: string;
31
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;
32
39
  }
33
40
  /** Called by the host: this page's guide, the listed count, the sections on screen, and how to open them. */
34
- export declare function publishPageGuides(next: PageGuidesEntry | null, openPage: (() => void) | null, openPages: (() => void) | null, openSection?: ((key: string) => void) | null): void;
35
- /** The "?" menu's items, in order (pure: the menu and its tests share it). "sections": one entry per section guide. */
36
- export type GuideMenuItem = "page" | "sections" | "missions" | "pages" | "help";
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";
37
48
  export declare function guideMenuItems(e: GuideEntry | null, p?: PageGuidesEntry): GuideMenuItem[];
38
49
  /**
39
50
  * Whether the "?" press opens a menu rather than the help dialog: a tour
@@ -69,6 +80,10 @@ export declare function usePageGuideEntry(): {
69
80
  * (`useSectionGuideValues`).
70
81
  */
71
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;
72
87
  type Values = Readonly<Record<string, unknown>>;
73
88
  /**
74
89
  * Sets (or with undefined, clears) a section guide's live values. The
@@ -100,6 +100,12 @@ export interface StepLayerProps {
100
100
  height: number;
101
101
  offsetTop: number;
102
102
  };
103
+ /**
104
+ * The app's content column (GuideConfig.contentRoot), already cut to the
105
+ * viewport: the bubble stays inside it (LIFF's 460 px column on a desktop).
106
+ * Shell ≥ 0.1.77. Omitted: the viewport.
107
+ */
108
+ bounds?: Rect | null;
103
109
  phone: boolean;
104
110
  showHand: boolean;
105
111
  bubble: BubbleModel;
@@ -191,7 +197,8 @@ export declare function PageOfferCard(p: {
191
197
  title: string;
192
198
  steps: number;
193
199
  onStart: () => void;
194
- onLater: () => void;
200
+ onLater: () => void; /** "คู่มือหน้านี้" by default; a flow's: "พาทำงาน". */
201
+ eyebrow?: string;
195
202
  }): import("react/jsx-runtime").JSX.Element;
196
203
  /** One page guide in the panel's "คู่มือแต่ละหน้า" list. */
197
204
  export interface PageItem {
@@ -200,6 +207,14 @@ export interface PageItem {
200
207
  /** This person has ended this version (ดูแล้ว); otherwise ใหม่. */
201
208
  seen: boolean;
202
209
  }
210
+ /** One flow in the panel's "พาทำงาน" list. Shell ≥ 0.1.76. */
211
+ export interface FlowItem {
212
+ key: string;
213
+ title: string;
214
+ minutes?: number;
215
+ /** This person has finished this version (ทำแล้ว). */
216
+ done: boolean;
217
+ }
203
218
  export declare function QuestChip({ done, total, pulse, onOpen }: {
204
219
  done: number;
205
220
  total: number;
@@ -236,9 +251,14 @@ export declare function QuestPanel(p: {
236
251
  * (shell ≥ 0.1.74). Omitted or empty: no section.
237
252
  */
238
253
  pages?: PageItem[];
239
- /** false: the page guides alone (no missions for this person, or "คู่มือทุกหน้า"). */
254
+ /** false: no missions (none for this person, "คู่มือทุกหน้า" or "พาทำงาน"). */
240
255
  showMissions?: boolean;
241
256
  onOpenPage?: (key: string) => void;
257
+ /** The "พาทำงาน" section: the flows this person has (shell ≥ 0.1.76). */
258
+ flows?: FlowItem[];
259
+ onOpenFlow?: (key: string) => void;
260
+ /** Without missions: one list alone ("คู่มือทุกหน้า" → pages, "พาทำงาน" → flows). */
261
+ only?: "pages" | "flows";
242
262
  }): import("react/jsx-runtime").JSX.Element;
243
263
  export declare function GuideToast({ text }: {
244
264
  text: string;
@@ -60,11 +60,19 @@ export type GuideScreen = {
60
60
  page?: string;
61
61
  /** A section guide's step: the section key (the mission is `section:<key>`). Shell ≥ 0.1.75. */
62
62
  section?: string;
63
+ /** A flow's step: the flow key (the mission is `flow:<key>`). Shell ≥ 0.1.76. */
64
+ flow?: string;
65
+ /** "ขั้นที่ no/total" as shown (GuideState.counter): never going down. Shell ≥ 0.1.77. */
66
+ pos?: {
67
+ no: number;
68
+ total: number;
69
+ };
63
70
  }
64
71
  /** The first-visit offer of this page's guide: a small card, not modal. */
65
72
  | {
66
73
  name: "pageOffer";
67
- page: string;
74
+ page: string; /** The offer is a flow's (`page` is the flow key). Shell ≥ 0.1.76. */
75
+ flow?: boolean;
68
76
  } | {
69
77
  name: "celebrate";
70
78
  mission: string;
@@ -102,6 +110,8 @@ export interface GuideState {
102
110
  pages: Record<string, PageRow>;
103
111
  /** Section rows by section key (`<app>.section.<key>`). Shell ≥ 0.1.75. */
104
112
  sections: Record<string, PageRow>;
113
+ /** Flow rows by flow key (`<app>.flow.<key>`). Shell ≥ 0.1.76. */
114
+ flows: Record<string, PageRow>;
105
115
  /**
106
116
  * The page or section guide being played: `write` when its row is still
107
117
  * to be written (the offer was taken, or this person has never ended this
@@ -111,9 +121,11 @@ export interface GuideState {
111
121
  key: string;
112
122
  write: boolean;
113
123
  kind?: ReadKind;
124
+ /** A flow's: the tour's captured ids before it started, put back at its end. */
125
+ context?: Record<string, string>;
114
126
  } | null;
115
- /** What the panel shows: everything, or the page guides alone ("คู่มือทุกหน้า"). */
116
- panelSection: "all" | "pages";
127
+ /** What the panel shows: everything, the page guides alone ("คู่มือทุกหน้า"), or the flows alone ("พาทำงาน"). */
128
+ panelSection: "all" | "pages" | "flows";
117
129
  /**
118
130
  * Steps of the mission being played that passed by themselves (a click
119
131
  * whose outcome already held): not counted in "ขั้นที่ x/y". Shell ≥ 0.1.75.
@@ -122,6 +134,18 @@ export interface GuideState {
122
134
  mission: string;
123
135
  steps: number[];
124
136
  } | null;
137
+ /**
138
+ * The counter of the run being played (shell ≥ 0.1.77): the steps shown so
139
+ * far, and the total as last worked out and on which page. The total is
140
+ * worked out when a step is entered on a page it was not worked out on,
141
+ * and never goes down.
142
+ */
143
+ counter: {
144
+ mission: string;
145
+ shown: number[];
146
+ total: number;
147
+ path: string;
148
+ } | null;
125
149
  }
126
150
  /** The page-guide part of the state, from the progress answer. */
127
151
  export interface GuidePagesInit {
@@ -129,9 +153,10 @@ export interface GuidePagesInit {
129
153
  pagesMode: PagesMode;
130
154
  pages: Record<string, PageRow>;
131
155
  sections?: Record<string, PageRow>;
156
+ flows?: Record<string, PageRow>;
132
157
  }
133
- /** A read-only guide: a page guide or a section guide. */
134
- export type ReadKind = "page" | "section";
158
+ /** A guide with its own row: a page guide, a section guide or a flow. */
159
+ export type ReadKind = "page" | "section" | "flow";
135
160
  export interface ReplayPage {
136
161
  mission: string;
137
162
  /** The mission's abort anchors that were on the page at the start. */
@@ -239,7 +264,7 @@ export type GuideAction = {
239
264
  type: "dismissComplete";
240
265
  } | {
241
266
  type: "openPanel";
242
- section?: "all" | "pages";
267
+ section?: "all" | "pages" | "flows";
243
268
  } | {
244
269
  type: "closePanel";
245
270
  } | {
@@ -260,10 +285,11 @@ export type GuideAction = {
260
285
  | {
261
286
  type: "idleCelebrate";
262
287
  }
263
- /** The host found this page's guide due (pageOfferDue): show the offer card. */
288
+ /** The host found this page's guide (or, with `flow`, a flow) due: show the offer card. */
264
289
  | {
265
290
  type: "pageOffer";
266
291
  page: string;
292
+ flow?: boolean;
267
293
  }
268
294
  /** The offer's [เริ่ม]. */
269
295
  | {
@@ -293,6 +319,19 @@ export type GuideAction = {
293
319
  | {
294
320
  type: "startSection";
295
321
  section: string;
322
+ }
323
+ /** "พาทำ · <title>", or the panel's "พาทำงาน" (once on its start page). */
324
+ | {
325
+ type: "startFlow";
326
+ flow: string;
327
+ }
328
+ /** After a refresh, in the same session: back into a flow at its checkpoint. */
329
+ | {
330
+ type: "resumeFlow";
331
+ flow: string;
332
+ step: string;
333
+ context: Record<string, string>;
334
+ write: boolean;
296
335
  };
297
336
  export type GuideEffect = {
298
337
  type: "save";
@@ -338,6 +377,7 @@ export declare const COPY: {
338
377
  readonly aborted: "ไกด์ไปต่อไม่ได้ ลองอีกครั้งภายหลัง";
339
378
  readonly pageDone: "จบคู่มือหน้านี้";
340
379
  readonly sectionDone: "จบคำอธิบายส่วนนี้";
380
+ readonly flowDone: "พาทำงานเสร็จแล้ว";
341
381
  readonly bridgeTitle: "กดปุ่มเมนู";
342
382
  readonly bridgeWhy: (app: string) => string;
343
383
  };
@@ -419,6 +459,14 @@ export declare function stepPosition(mission: GuideMission, index: number, env:
419
459
  no: number;
420
460
  total: number;
421
461
  };
462
+ /**
463
+ * The steps after `index` this person will see, as far as can be known from
464
+ * here: on this page, everything is read (requires, skipIf, a click whose
465
+ * outcome already holds); on another page, a step whose showing depends on
466
+ * what is on that page (`skipIf`, `onMissing: "skip"`) is not counted until
467
+ * its page is reached.
468
+ */
469
+ export declare function stepsAhead(mission: GuideMission, index: number, env: GuideEnv, context: Readonly<Record<string, string>>): number;
422
470
  /** A step entered now would pass at once: a click or select step whose route or visible outcome holds. */
423
471
  export declare function wouldAutoPass(step: GuideStep, env: GuideEnv): boolean;
424
472
  /** The steps of this mission that passed by themselves in this run. */
@@ -458,11 +506,35 @@ export declare function firstStepReady(suite: GuideSuite, pageKey: string, env:
458
506
  * route, a moment of nothing loading, the primary tab, not hidden.
459
507
  */
460
508
  export declare function pageOfferDue(state: GuideState, suite: GuideSuite, env: GuideEnv): string | null;
509
+ /**
510
+ * Whether a row may be written now: none of this version yet, or — once —
511
+ * a skipped one that the person has now finished (skipped → completed,
512
+ * shell ≥ 0.1.77). A completed row is final; skipped again changes nothing.
513
+ */
514
+ export declare function rowWritable(row: PageRow | undefined, version: number, status: "completed" | "skipped"): boolean;
515
+ /** Whether a run should keep its row to write at its end: no row yet, or only a skipped one. */
516
+ export declare function rowStillDue(row: PageRow | undefined, version: number): boolean;
461
517
  /** The section guide's row says this person has ended this version of it. */
462
518
  export declare function sectionRecorded(state: GuideState, section: {
463
519
  key: string;
464
520
  version: number;
465
521
  }): boolean;
522
+ /** The flow's row says this person has ended this version of it. */
523
+ export declare function flowRecorded(state: GuideState, flow: {
524
+ key: string;
525
+ version: number;
526
+ }): boolean;
527
+ /** The flows this person has that start on this page ("พาทำ · <title>"). */
528
+ export declare function flowsAvailable(suite: GuideSuite, env: GuideEnv): string[];
529
+ /**
530
+ * The flow to offer now, or null: only in "offer" mode, only a flow that
531
+ * says `offer: true`, on its start page, with no row of this version, when
532
+ * nothing else is up and this page's own guide is not due (it comes first:
533
+ * no guide here, offer: false, or already recorded), its first step's
534
+ * target on screen, no app dialog open. The host adds the welcome and the
535
+ * idle wait, as for the page guide's offer.
536
+ */
537
+ export declare function flowOfferDue(state: GuideState, suite: GuideSuite, env: GuideEnv): string | null;
466
538
  /** The section guides on screen here that this person has (the "?" entries, the buttons). */
467
539
  export declare function sectionsAvailable(suite: GuideSuite, env: GuideEnv): string[];
468
540
  /** The step before this one that this person sees, or -1. */
@@ -478,4 +550,10 @@ export declare function backTarget(mission: GuideMission, index: number, env: Gu
478
550
  index: number;
479
551
  close: boolean;
480
552
  } | null;
553
+ /**
554
+ * A flow's next step (the next one this person sees) when the person is on
555
+ * its page and no longer on the current step's: they moved on by
556
+ * themselves. -1 otherwise (still on this step's page, or elsewhere).
557
+ */
558
+ export declare function flowStepArrivedAt(mission: GuideMission, index: number, env: GuideEnv, context: Readonly<Record<string, string>>): number;
481
559
  export declare function reduceGuide(state: GuideState, action: GuideAction, suite: GuideSuite, env: GuideEnv): GuideResult;
@@ -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, GuideSection, 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;
@@ -77,3 +77,31 @@ export declare function sectionApplies(section: GuideSection, where: PageWhere):
77
77
  export declare function sectionShown(section: GuideSection, ctx: GuideContext): boolean;
78
78
  /** The section guides on screen here that this person has, in the suite's order. */
79
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;
@@ -74,4 +74,4 @@ export declare function storeGuides(adapter: GuideProgressAdapter, suite: GuideS
74
74
  * an older version's row is replaced with its rev; a newer one stops. Returns
75
75
  * the stored row, or null when it could not be saved.
76
76
  */
77
- export declare function storePageRow(adapter: GuideProgressAdapter, app: string, key: string, version: number, status: "completed" | "skipped", rev: number, kind?: "page" | "section"): 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>;
@@ -57,6 +57,8 @@ export interface GuidesAnswer {
57
57
  pages: Record<string, PageRow>;
58
58
  /** Section rows by section key (the part after `<app>.section.`). Shell ≥ 0.1.75. */
59
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>;
60
62
  /** The suite's row; a fresh one when the user has none or an older version. */
61
63
  progress: GuideProgress;
62
64
  /** The server holds a newer version than this app's tour: do not run. */
@@ -74,10 +76,10 @@ export declare function parseGuidesAnswer(payload: unknown, suite: {
74
76
  version: number;
75
77
  app: string;
76
78
  }): GuidesAnswer | null;
77
- /** The row key of a page guide, `<app>.page.<key>`, or a section guide, `<app>.section.<key>`. */
78
- export declare function pageRowKey(app: string, key: string, kind?: "page" | "section"): string;
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;
79
81
  /** Page (or section) rows among the list's rows, by key. Off-shape rows are left out. */
80
- export declare function parsePageRows(rows: unknown[], app: string, kind?: "page" | "section"): Record<string, PageRow>;
82
+ export declare function parsePageRows(rows: unknown[], app: string, kind?: "page" | "section" | "flow"): Record<string, PageRow>;
81
83
  /** One page row (a list entry, a PUT answer, a 409's `current`); null when off-shape. */
82
84
  export declare function parsePageRow(raw: unknown): PageRow | null;
83
85
  /**
@@ -423,6 +423,57 @@ export interface GuideSection {
423
423
  */
424
424
  steps: GuideStep[];
425
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
+ }
426
477
  /** One app's whole tour: the welcome, the missions, the finish. */
427
478
  export interface GuideSuite {
428
479
  /** Progress key on the server, "<app>.<name>": "peoplx.first-run". */
@@ -470,6 +521,8 @@ export interface GuideSuite {
470
521
  pages?: GuidePage[];
471
522
  /** Section guides ("อธิบายส่วนนี้"), shell ≥ 0.1.75. */
472
523
  sections?: GuideSection[];
524
+ /** Workflow guides ("พาทำงาน"), shell ≥ 0.1.76. */
525
+ flows?: GuideFlow[];
473
526
  }
474
527
  /** AppLayoutShell's `guides` prop. */
475
528
  export interface GuideConfig {
@@ -489,4 +542,10 @@ export interface GuideConfig {
489
542
  * `module.accounting` is known). Shell ≥ 0.1.74.
490
543
  */
491
544
  pagesReady?: boolean;
545
+ /**
546
+ * A selector for the app's content column (LIFF's centred 460 px
547
+ * `MobileShell` on a desktop): bubbles stay inside it. Omitted: the
548
+ * viewport. Shell ≥ 0.1.77.
549
+ */
550
+ contentRoot?: string;
492
551
  }
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
  'use strict';
3
3
 
4
- var format = require('./chunks/format-CVazK0hP.cjs');
4
+ var format = require('./chunks/format-DQLPHq7h.cjs');
5
5
  require('react/jsx-runtime');
6
6
  require('react');
7
7
  require('react-dom');
@@ -26,6 +26,8 @@ exports.guideMenuShown = format.guideMenuShown;
26
26
  exports.loadGuides = format.loadGuides;
27
27
  exports.matchApiPath = format.matchApiPath;
28
28
  exports.matchRoute = format.matchRoute;
29
+ exports.openFlow = format.openFlow;
30
+ exports.openFlowsPanel = format.openFlowsPanel;
29
31
  exports.openGuidePanel = format.openGuidePanel;
30
32
  exports.openPageGuide = format.openPageGuide;
31
33
  exports.openPagesPanel = format.openPagesPanel;
@@ -1 +1 @@
1
- {"version":3,"file":"guide-core.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"guide-core.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,5 +1,5 @@
1
1
  'use client';
2
- export { A as GUIDE_API_EVENT, G as GUIDE_EVENT_PREFIX, a as GUIDE_LAYER_ATTRIBUTE, c as GuideProgressConflict, d as GuideRuntime, S as SectionGuideButton, T as THAI_MONTHS_SHORT, e as apiCallDetail, f as emitGuideEvent, g as fillRoute, h as formatBaht, i as guideAnchor, j as guideMenuItems, k as guideMenuShown, l as loadGuides, m as matchApiPath, n as matchRoute, o as openGuidePanel, p as openPageGuide, q as openPagesPanel, r as openSectionGuide, s as reportApiCall, t as reportApiEvent, u as setSectionGuideValues, v as storeGuides, w as thaiMonth, x as thaiMonthYear, y as useGuideEntry, z as usePageGuideEntry, B as usePageGuides, C as useSectionGuideValues } from './chunks/format-DCTuLpBU.esm.js';
2
+ export { A as GUIDE_API_EVENT, G as GUIDE_EVENT_PREFIX, a as GUIDE_LAYER_ATTRIBUTE, c as GuideProgressConflict, d as GuideRuntime, S as SectionGuideButton, T as THAI_MONTHS_SHORT, e as apiCallDetail, f as emitGuideEvent, g as fillRoute, h as formatBaht, i as guideAnchor, j as guideMenuItems, k as guideMenuShown, l as loadGuides, m as matchApiPath, n as matchRoute, o as openFlow, p as openFlowsPanel, q as openGuidePanel, r as openPageGuide, s as openPagesPanel, t as openSectionGuide, u as reportApiCall, v as reportApiEvent, w as setSectionGuideValues, x as storeGuides, y as thaiMonth, z as thaiMonthYear, B as useGuideEntry, C as usePageGuideEntry, D as usePageGuides, E as useSectionGuideValues } from './chunks/format-ILrTMV4G.esm.js';
3
3
  import 'react/jsx-runtime';
4
4
  import 'react';
5
5
  import 'react-dom';
@@ -7,8 +7,10 @@ export interface HelpButtonProps {
7
7
  *
8
8
  * When this user has something to open here, it opens a small menu:
9
9
  * "คู่มือหน้านี้" (this page's guide), "อธิบายส่วนนี้ · <title>" for each
10
- * section guide on screen, "ไกด์เริ่มต้น n/N" (the quest
11
- * panel), "คู่มือทุกหน้า" (the panel's page guides) and "ติดต่อทีมช่วยเหลือ"
10
+ * section guide on screen, "พาทำ · <title>" for each flow starting here,
11
+ * "ไกด์เริ่มต้น n/N" (the quest
12
+ * panel), "คู่มือทุกหน้า" (the panel's page guides), "พาทำงาน" (the panel's
13
+ * flows) and "ติดต่อทีมช่วยเหลือ"
12
14
  * (the help dialog), each only when it has something. Otherwise one press
13
15
  * opens the help dialog, as before.
14
16
  */
package/dist/index.cjs CHANGED
@@ -14,7 +14,7 @@ var Link = require('next/link');
14
14
  var reactDom = require('react-dom');
15
15
  var nextThemes = require('next-themes');
16
16
  var axios = require('axios');
17
- var format = require('./chunks/format-CVazK0hP.cjs');
17
+ var format = require('./chunks/format-DQLPHq7h.cjs');
18
18
  var reactQueryDevtools = require('@tanstack/react-query-devtools');
19
19
  require('@floating-ui/dom');
20
20
 
@@ -1740,7 +1740,7 @@ function platformApiBase(app) {
1740
1740
  * This package's version, attached to help messages so the back office can
1741
1741
  * tell which shell a report came from. Keep in step with package.json.
1742
1742
  */
1743
- const SHELL_VERSION = "0.1.75";
1743
+ const SHELL_VERSION = "0.1.77";
1744
1744
 
1745
1745
  const HELP_APP_LABEL = {
1746
1746
  platform: "แพลตฟอร์ม",
@@ -2574,8 +2574,10 @@ const BUTTON_CLASS = "grid size-[34px] shrink-0 place-items-center rounded-lg te
2574
2574
  *
2575
2575
  * When this user has something to open here, it opens a small menu:
2576
2576
  * "คู่มือหน้านี้" (this page's guide), "อธิบายส่วนนี้ · <title>" for each
2577
- * section guide on screen, "ไกด์เริ่มต้น n/N" (the quest
2578
- * panel), "คู่มือทุกหน้า" (the panel's page guides) and "ติดต่อทีมช่วยเหลือ"
2577
+ * section guide on screen, "พาทำ · <title>" for each flow starting here,
2578
+ * "ไกด์เริ่มต้น n/N" (the quest
2579
+ * panel), "คู่มือทุกหน้า" (the panel's page guides), "พาทำงาน" (the panel's
2580
+ * flows) and "ติดต่อทีมช่วยเหลือ"
2579
2581
  * (the help dialog), each only when it has something. Otherwise one press
2580
2582
  * opens the help dialog, as before.
2581
2583
  */
@@ -2601,7 +2603,9 @@ function HelpButton({ className }) {
2601
2603
  }
2602
2604
  }, children: [items.includes("page") ? (jsxRuntime.jsxs(erpTheme.DropdownMenuItem, { onSelect: toTour(format.openPageGuide), className: "gap-2.5", children: [jsxRuntime.jsx(lucideReact.BookOpen, { className: "size-4" }), jsxRuntime.jsx("span", { className: "flex-1", children: "\u0E04\u0E39\u0E48\u0E21\u0E37\u0E2D\u0E2B\u0E19\u0E49\u0E32\u0E19\u0E35\u0E49" })] })) : null, items.includes("sections")
2603
2605
  ? (pages.sections ?? []).map(sec => (jsxRuntime.jsxs(erpTheme.DropdownMenuItem, { onSelect: toTour(() => format.openSectionGuide(sec.key)), className: "gap-2.5", children: [jsxRuntime.jsx(lucideReact.Info, { className: "size-4" }), jsxRuntime.jsxs("span", { className: "flex-1", children: ["\u0E2D\u0E18\u0E34\u0E1A\u0E32\u0E22\u0E2A\u0E48\u0E27\u0E19\u0E19\u0E35\u0E49 \u00B7 ", sec.title] })] }, sec.key)))
2604
- : null, items.includes("missions") && guide ? (jsxRuntime.jsxs(erpTheme.DropdownMenuItem, { onSelect: toTour(format.openGuidePanel), className: "gap-2.5", children: [jsxRuntime.jsx(lucideReact.Flag, { className: "size-4" }), jsxRuntime.jsx("span", { className: "flex-1", children: "\u0E44\u0E01\u0E14\u0E4C\u0E40\u0E23\u0E34\u0E48\u0E21\u0E15\u0E49\u0E19" }), jsxRuntime.jsxs("span", { className: "text-xs font-semibold text-primary tabular-nums", children: [guide.done, "/", guide.total] })] })) : null, items.includes("pages") ? (jsxRuntime.jsxs(erpTheme.DropdownMenuItem, { onSelect: toTour(format.openPagesPanel), className: "gap-2.5", children: [jsxRuntime.jsx(lucideReact.Library, { className: "size-4" }), jsxRuntime.jsx("span", { className: "flex-1", children: "\u0E04\u0E39\u0E48\u0E21\u0E37\u0E2D\u0E17\u0E38\u0E01\u0E2B\u0E19\u0E49\u0E32" })] })) : null, jsxRuntime.jsxs(erpTheme.DropdownMenuItem, { onSelect: () => setTimeout(openHelp, 0), className: "gap-2.5", children: [jsxRuntime.jsx(lucideReact.MessageCircle, { className: "size-4" }), jsxRuntime.jsx("span", { className: "flex-1", children: "\u0E15\u0E34\u0E14\u0E15\u0E48\u0E2D\u0E17\u0E35\u0E21\u0E0A\u0E48\u0E27\u0E22\u0E40\u0E2B\u0E25\u0E37\u0E2D" })] })] })] }));
2606
+ : null, items.includes("flowsHere")
2607
+ ? (pages.flows ?? []).map(f => (jsxRuntime.jsxs(erpTheme.DropdownMenuItem, { onSelect: toTour(() => format.openFlow(f.key)), className: "gap-2.5", children: [jsxRuntime.jsx(lucideReact.Route, { className: "size-4" }), jsxRuntime.jsxs("span", { className: "flex-1", children: ["\u0E1E\u0E32\u0E17\u0E33 \u00B7 ", f.title] })] }, f.key)))
2608
+ : null, items.includes("missions") && guide ? (jsxRuntime.jsxs(erpTheme.DropdownMenuItem, { onSelect: toTour(format.openGuidePanel), className: "gap-2.5", children: [jsxRuntime.jsx(lucideReact.Flag, { className: "size-4" }), jsxRuntime.jsx("span", { className: "flex-1", children: "\u0E44\u0E01\u0E14\u0E4C\u0E40\u0E23\u0E34\u0E48\u0E21\u0E15\u0E49\u0E19" }), jsxRuntime.jsxs("span", { className: "text-xs font-semibold text-primary tabular-nums", children: [guide.done, "/", guide.total] })] })) : null, items.includes("pages") ? (jsxRuntime.jsxs(erpTheme.DropdownMenuItem, { onSelect: toTour(format.openPagesPanel), className: "gap-2.5", children: [jsxRuntime.jsx(lucideReact.Library, { className: "size-4" }), jsxRuntime.jsx("span", { className: "flex-1", children: "\u0E04\u0E39\u0E48\u0E21\u0E37\u0E2D\u0E17\u0E38\u0E01\u0E2B\u0E19\u0E49\u0E32" })] })) : null, items.includes("flows") ? (jsxRuntime.jsxs(erpTheme.DropdownMenuItem, { onSelect: toTour(format.openFlowsPanel), className: "gap-2.5", children: [jsxRuntime.jsx(lucideReact.Route, { className: "size-4" }), jsxRuntime.jsx("span", { className: "flex-1", children: "\u0E1E\u0E32\u0E17\u0E33\u0E07\u0E32\u0E19" })] })) : null, jsxRuntime.jsxs(erpTheme.DropdownMenuItem, { onSelect: () => setTimeout(openHelp, 0), className: "gap-2.5", children: [jsxRuntime.jsx(lucideReact.MessageCircle, { className: "size-4" }), jsxRuntime.jsx("span", { className: "flex-1", children: "\u0E15\u0E34\u0E14\u0E15\u0E48\u0E2D\u0E17\u0E35\u0E21\u0E0A\u0E48\u0E27\u0E22\u0E40\u0E2B\u0E25\u0E37\u0E2D" })] })] })] }));
2605
2609
  }
2606
2610
 
2607
2611
  const hasPaginationShape = (payload) => {
@@ -4457,6 +4461,8 @@ exports.formatBaht = format.formatBaht;
4457
4461
  exports.guideAnchor = format.guideAnchor;
4458
4462
  exports.guideMenuItems = format.guideMenuItems;
4459
4463
  exports.guideMenuShown = format.guideMenuShown;
4464
+ exports.openFlow = format.openFlow;
4465
+ exports.openFlowsPanel = format.openFlowsPanel;
4460
4466
  exports.openGuidePanel = format.openGuidePanel;
4461
4467
  exports.openPageGuide = format.openPageGuide;
4462
4468
  exports.openPagesPanel = format.openPagesPanel;