@eintrek/erp-shell 0.1.66 → 0.1.68
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 +28 -2
- package/dist/chunks/guide-runtime-B2RjoQeb.cjs +3874 -0
- package/dist/chunks/guide-runtime-B2RjoQeb.cjs.map +1 -0
- package/dist/chunks/guide-runtime-BT7rN-5p.esm.js +3837 -0
- package/dist/chunks/guide-runtime-BT7rN-5p.esm.js.map +1 -0
- package/dist/guide/core.d.ts +19 -0
- package/dist/guide/dom.d.ts +2 -0
- package/dist/guide/events.d.ts +25 -0
- package/dist/guide/guide-runtime.d.ts +83 -0
- package/dist/guide/guide-styles.d.ts +7 -1
- package/dist/guide/machine.d.ts +68 -2
- package/dist/guide/patterns.d.ts +6 -2
- package/dist/guide/progress-client.d.ts +6 -5
- package/dist/guide/progress-sync.d.ts +68 -0
- package/dist/guide/types.d.ts +48 -3
- package/dist/guide-core.cjs +29 -0
- package/dist/guide-core.cjs.map +1 -0
- package/dist/guide-core.esm.js +7 -0
- package/dist/guide-core.esm.js.map +1 -0
- package/dist/{index.js → index.cjs} +129 -3431
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.esm.js +110 -3414
- package/dist/index.esm.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +46 -2
- package/dist/index.js.map +0 -1
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@eintrek/erp-shell/guide-core`: the guided-tour engine without the shell.
|
|
3
|
+
*
|
|
4
|
+
* For an app that does not use AppLayoutShell (erp-liff): no React Query,
|
|
5
|
+
* axios, zustand, next-auth, next-themes or sidebar behind it — only React,
|
|
6
|
+
* react-dom and @floating-ui/dom. The app mounts GuideRuntime with adapters
|
|
7
|
+
* (routing, isBusy, progress, menu, hidden). Authors:
|
|
8
|
+
* _claude-work/guides-r2/GUIDE-CORE.md and _claude-work/peoplx-guide/ENGINE-API.md.
|
|
9
|
+
*
|
|
10
|
+
* The main entry re-exports the same modules, so a tour defined against
|
|
11
|
+
* either entry is the same data, and the bus and the "?" entry are shared.
|
|
12
|
+
*/
|
|
13
|
+
export type { GuideAbortAction, GuideAnchorKey, GuideApiFailure, GuideApiMatch, GuideAppId, GuideCaptureEvent, GuideConfig, GuideContext, GuideFacts, GuideGate, GuideMission, GuideNothingToSave, GuideOnMissing, GuideStep, GuideStepKind, GuideSuite, GuideText, GuideTrigger, } from "./types";
|
|
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 { openGuidePanel, useGuideEntry, type GuideEntry } from "./guide-store";
|
|
16
|
+
export { GuideRuntime, type GuideMenu, type GuideRouting, type GuideRuntimeProps, } from "./guide-runtime";
|
|
17
|
+
export { GuideProgressConflict, loadGuides, storeGuides, type GuideProgressAdapter, type GuideProgressRequest, type GuideProgressResponse, } from "./progress-sync";
|
|
18
|
+
export type { GuideAudience, GuideMode } from "./progress";
|
|
19
|
+
export { matchApiPath, matchRoute, fillRoute } from "./patterns";
|
package/dist/guide/dom.d.ts
CHANGED
|
@@ -38,6 +38,8 @@ export declare const OPEN_DIALOG_SELECTOR = "[role=\"dialog\"][data-state=\"open
|
|
|
38
38
|
* behind it.
|
|
39
39
|
*/
|
|
40
40
|
export declare function coveredByDialog(el: Element | null): boolean;
|
|
41
|
+
/** An app dialog (not the tour's) is open on the page. */
|
|
42
|
+
export declare function appDialogOpen(): boolean;
|
|
41
43
|
export declare function openPoppers(): HTMLElement[];
|
|
42
44
|
export declare function inGuideLayer(node: EventTarget | null): boolean;
|
|
43
45
|
export declare function prefersReducedMotion(): boolean;
|
package/dist/guide/events.d.ts
CHANGED
|
@@ -22,3 +22,28 @@ export declare function emitGuideEvent(name: string, detail?: Record<string, str
|
|
|
22
22
|
export declare function apiEventDetail(responseOrError: unknown): ApiEventDetail | null;
|
|
23
23
|
/** Puts an axios answer (or error) on the bus. Safe to call with anything. */
|
|
24
24
|
export declare function reportApiEvent(responseOrError: unknown): void;
|
|
25
|
+
/** One answered request, from a client that is not axios (plain `fetch`). */
|
|
26
|
+
export interface ApiCallReport {
|
|
27
|
+
/** "POST"; any case. Default "GET". */
|
|
28
|
+
method?: string;
|
|
29
|
+
/** The request URL, absolute or relative (any query is dropped). */
|
|
30
|
+
url: string;
|
|
31
|
+
/** The base the URL is relative to, if any. */
|
|
32
|
+
baseURL?: string;
|
|
33
|
+
/** The HTTP status; 0 for a network failure. */
|
|
34
|
+
status: number;
|
|
35
|
+
/**
|
|
36
|
+
* The parsed response body, if at hand. Only the saved record's id (on a
|
|
37
|
+
* 2xx: `id` or `data.id`) and the server's message (otherwise) are read
|
|
38
|
+
* from it; the body itself never goes on the bus.
|
|
39
|
+
*/
|
|
40
|
+
data?: unknown;
|
|
41
|
+
}
|
|
42
|
+
/** The bus detail for a fetch-style report; null when it has no URL. */
|
|
43
|
+
export declare function apiCallDetail(call: ApiCallReport): ApiEventDetail | null;
|
|
44
|
+
/**
|
|
45
|
+
* Puts a request answered through plain `fetch` on the bus (`{ api }`
|
|
46
|
+
* triggers and `completeOn`). Call it once per answer, refusals and network
|
|
47
|
+
* failures (status 0) included. Safe to call with anything.
|
|
48
|
+
*/
|
|
49
|
+
export declare function reportApiCall(call: ApiCallReport): void;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GuideRuntime: runs an app's tour against the real page, with everything
|
|
3
|
+
* app-specific passed in as adapters — routing, "is the page loading",
|
|
4
|
+
* where progress is kept, the menu, when to stay hidden. It loads progress,
|
|
5
|
+
* decides who sees what from the answer, runs the state machine (machine.ts)
|
|
6
|
+
* and draws the layer (guide-ui.tsx) in a portal marked data-erp-guide-layer.
|
|
7
|
+
*
|
|
8
|
+
* Two hosts build the adapters: the shell's GuideHost (AppLayoutShell:
|
|
9
|
+
* Next router, React Query, the sidebar, platform-api through axios) and an
|
|
10
|
+
* app without the shell, through `@eintrek/erp-shell/guide-core` (erp-liff:
|
|
11
|
+
* its own fetch client and peoplx-api). No React Query, axios, zustand,
|
|
12
|
+
* next-auth, next-themes or Next import here.
|
|
13
|
+
*
|
|
14
|
+
* Fail open, always: an API error, an odd answer, a predicate or a render
|
|
15
|
+
* that throws — the tour does not show and the app is untouched.
|
|
16
|
+
*/
|
|
17
|
+
import * as React from "react";
|
|
18
|
+
import type { GuideConfig } from "./types";
|
|
19
|
+
import { type GuideProgressAdapter } from "./progress-sync";
|
|
20
|
+
/** Where the user is, and how the tour sends them somewhere (route triggers, resume, ทำต่อ). */
|
|
21
|
+
export interface GuideRouting {
|
|
22
|
+
/** The current path, without the query: Next's usePathname(). */
|
|
23
|
+
pathname: string;
|
|
24
|
+
/** The current query without "?": useSearchParams().toString(). */
|
|
25
|
+
search: string;
|
|
26
|
+
/** Go to an in-app path ("/me/leave"); absolute URLs are opened by the engine itself. */
|
|
27
|
+
navigate: (href: string) => void;
|
|
28
|
+
}
|
|
29
|
+
/** The app's navigation menu, for the phone's "กดปุ่มเมนู" step before a `nav.*` target. */
|
|
30
|
+
export interface GuideMenu {
|
|
31
|
+
/** The menu (sidebar or drawer) is open now. */
|
|
32
|
+
open: boolean;
|
|
33
|
+
}
|
|
34
|
+
export interface GuideRuntimeProps {
|
|
35
|
+
config: GuideConfig;
|
|
36
|
+
/** What progress is kept per: the organisation id. A change starts over. */
|
|
37
|
+
organizationId: string;
|
|
38
|
+
/**
|
|
39
|
+
* Fills `[code]` in routes and is the only value `[code]`/`[[code]]` may
|
|
40
|
+
* match. The org code in the URL; "" where the URL has none (LIFF `/me/…`).
|
|
41
|
+
*/
|
|
42
|
+
code: string;
|
|
43
|
+
routing: GuideRouting;
|
|
44
|
+
/** Where progress is read and saved (progress-sync.ts). */
|
|
45
|
+
progress: GuideProgressAdapter;
|
|
46
|
+
/**
|
|
47
|
+
* Whether the page is still loading data. A step waiting for its target
|
|
48
|
+
* counts only time when this is false; the welcome and a waiting
|
|
49
|
+
* celebration open after a moment of it being false. Polled. Default: never.
|
|
50
|
+
*/
|
|
51
|
+
isBusy?: () => boolean;
|
|
52
|
+
/** The app's menu; null or omitted: none (no menu step; do not target `nav.*`). */
|
|
53
|
+
menu?: GuideMenu | null;
|
|
54
|
+
/** True keeps the tour out of sight (sign-in, a picker, a gate of the app's). */
|
|
55
|
+
hidden?: boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Sets `--erp-guide-bottom-offset` on the layer: how far the chip and the
|
|
58
|
+
* bottom cards sit from the bottom (above a bottom nav), e.g.
|
|
59
|
+
* "calc(64px + env(safe-area-inset-bottom))". Default: the CSS variable as
|
|
60
|
+
* the page sets it, else 16px (22px beside the docked layout on desktop).
|
|
61
|
+
*/
|
|
62
|
+
bottomOffset?: string;
|
|
63
|
+
}
|
|
64
|
+
/** Hides the tour (and only the tour) after any error under it. */
|
|
65
|
+
export declare class GuideErrorBoundary extends React.Component<{
|
|
66
|
+
children: React.ReactNode;
|
|
67
|
+
}, {
|
|
68
|
+
failed: boolean;
|
|
69
|
+
}> {
|
|
70
|
+
state: {
|
|
71
|
+
failed: boolean;
|
|
72
|
+
};
|
|
73
|
+
static getDerivedStateFromError(): {
|
|
74
|
+
failed: boolean;
|
|
75
|
+
};
|
|
76
|
+
componentDidCatch(error: unknown): void;
|
|
77
|
+
render(): React.ReactNode;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Runs a tour with the app's adapters. Mount it once, above the pages (so a
|
|
81
|
+
* route change does not unmount it), only where the tour may run.
|
|
82
|
+
*/
|
|
83
|
+
export declare function GuideRuntime(props: GuideRuntimeProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -3,5 +3,11 @@
|
|
|
3
3
|
* its dist for Tailwind classes, which cannot carry keyframes; so the layer
|
|
4
4
|
* brings its own sheet, namespaced `eg-`, drawn from the theme's tokens
|
|
5
5
|
* (--primary carries each app's brand accent; light and dark follow).
|
|
6
|
+
*
|
|
7
|
+
* `--erp-guide-bottom-offset` (set by the app on :root/body, or through
|
|
8
|
+
* GuideRuntime's `bottomOffset`) lifts the chip, the bottom card, the toast
|
|
9
|
+
* and the desktop panel above a bottom nav. Unset, they sit where they did
|
|
10
|
+
* before 0.1.68: 16px from the bottom (+ the safe area) on a phone, 22px on
|
|
11
|
+
* desktop.
|
|
6
12
|
*/
|
|
7
|
-
export declare const GUIDE_CSS = "\n[data-erp-guide-layer]{position:fixed;inset:0;z-index:1000;pointer-events:none;font-family:inherit;color:var(--popover-foreground,#1c2634);\n --eg-scrim:rgba(12,20,34,.64);--eg-card:var(--popover,#fff);--eg-fg:var(--popover-foreground,#1c2634);\n --eg-muted:var(--muted-foreground,#6d7886);--eg-soft:var(--muted,#eef3f9);--eg-line:var(--border,#e8ecf1);\n --eg-primary:var(--primary,#3280dd);--eg-on-primary:var(--primary-foreground,#fff);\n --eg-tint:color-mix(in oklab,var(--eg-primary) 13%,var(--eg-card));--eg-strong:color-mix(in oklab,var(--eg-primary) 82%,#000);\n --eg-danger:var(--destructive,#d23b4b);--eg-ok:#1d9a5f;--eg-gold:#e6a417;\n --eg-shadow:0 18px 50px -12px rgba(16,32,64,.35),0 4px 12px rgba(16,32,64,.08);line-height:1.5;font-size:14px}\n[data-erp-guide-layer] *{box-sizing:border-box}\n[data-erp-guide-layer] button{font:inherit;color:inherit;cursor:pointer}\n.eg-i{pointer-events:auto}\n.eg-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}\n.eg-scrim-svg{position:fixed;inset:0;width:100%;height:100%;pointer-events:none;overflow:visible}\n.eg-scrim-svg .eg-scrim-fill{fill:var(--eg-scrim);pointer-events:none}\n.eg-scrim-svg .eg-scrim-hit{fill:transparent;pointer-events:all}\n.eg-scrim{position:fixed;inset:0;background:var(--eg-scrim);pointer-events:auto}\n.eg-scrim.eg-light{background:rgba(12,20,34,.45)}\n.eg-scrim.eg-faint{background:rgba(12,20,34,.35)}\n.eg-ring{position:fixed;border-radius:12px;pointer-events:none;box-shadow:0 0 0 3px #fff,0 0 0 6px var(--eg-primary)}\n.eg-ring.eg-move{transition:left .26s ease,top .26s ease,width .26s ease,height .26s ease}\n.eg-ring::after{content:\"\";position:absolute;inset:-6px;border-radius:15px;border:3px solid var(--eg-primary);animation:eg-pulse 1.6s ease-out infinite}\n.eg-ring.eg-flash::after{animation:eg-flash .5s ease 1}\n@keyframes eg-pulse{0%{opacity:.9;transform:scale(1)}100%{opacity:0;transform:scale(1.12)}}\n@keyframes eg-flash{0%,100%{opacity:1;transform:none}50%{opacity:.2}}\n.eg-hand{position:fixed;width:46px;height:46px;pointer-events:none;filter:drop-shadow(0 4px 6px rgba(0,0,0,.35));animation:eg-tap 1.1s ease-in-out infinite}\n.eg-hand svg{width:46px;height:46px;fill:#fff;stroke:#1c2634;stroke-width:1.4;stroke-linejoin:round;stroke-linecap:round}\n.eg-hand.eg-flip svg{transform:scaleY(-1)}\n@keyframes eg-tap{0%,100%{transform:translate(6px,8px)}50%{transform:translate(0,0)}}\n.eg-bubble{position:fixed;left:0;top:0;width:320px;background:var(--eg-card);color:var(--eg-fg);border-radius:14px;box-shadow:var(--eg-shadow);padding:14px 16px 12px;border-top:4px solid var(--eg-primary);outline:none;pointer-events:auto}\n.eg-bubble.eg-err{border-top-color:var(--eg-danger)}\n.eg-bubble.eg-nudge{animation:eg-nudge .38s ease}\n@keyframes eg-nudge{0%,100%{translate:0}20%{translate:-7px}40%{translate:6px}60%{translate:-4px}80%{translate:2px}}\n.eg-b-top{display:flex;justify-content:space-between;align-items:center;gap:8px;font-size:12px;color:var(--eg-muted)}\n.eg-b-top .eg-mis{font-weight:600;color:var(--eg-strong);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.eg-b-top .eg-cnt{white-space:nowrap;font-weight:600}\n.eg-pips{display:flex;gap:4px;margin:8px 0 10px}\n.eg-pips i{flex:1;height:4px;border-radius:2px;background:var(--eg-soft)}\n.eg-pips i.eg-d{background:var(--eg-primary)}\n.eg-pips i.eg-c{background:color-mix(in oklab,var(--eg-primary) 45%,var(--eg-card))}\n.eg-b-t{margin:0;font-size:16px;font-weight:600;line-height:1.45}\n.eg-b-w{margin:2px 0 0;font-size:13.5px;color:var(--eg-muted)}\n.eg-bubble.eg-err .eg-b-t{color:var(--eg-danger)}\n.eg-k{display:inline-block;background:var(--eg-tint);color:var(--eg-strong);border-radius:7px;padding:0 7px;font-weight:600}\n.eg-b-f{display:flex;align-items:center;justify-content:space-between;margin-top:12px;gap:8px}\n.eg-b-f .eg-btn{height:34px;padding:0 14px;font-size:13.5px}\n.eg-exit{border:0;background:none;color:var(--eg-muted);font-size:12.5px;padding:4px 0;text-decoration:underline;text-underline-offset:3px}\n.eg-exit:hover{color:var(--eg-fg)}\n.eg-arrow{position:absolute;width:14px;height:14px;background:var(--eg-card);transform:rotate(45deg);border-radius:2px}\n.eg-arrow.eg-top{background:var(--eg-primary)}\n.eg-bubble.eg-err .eg-arrow.eg-top{background:var(--eg-danger)}\n.eg-btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;height:40px;padding:0 16px;border-radius:10px;border:1px solid transparent;font-size:14px;font-weight:600;white-space:nowrap}\n.eg-btn:focus-visible,.eg-exit:focus-visible,.eg-chip:focus-visible,.eg-x:focus-visible{outline:2px solid var(--eg-primary);outline-offset:2px}\n.eg-primary{background:var(--eg-primary);color:var(--eg-on-primary)!important}\n.eg-primary:hover{background:var(--eg-strong)}\n.eg-primary[disabled]{opacity:.55;cursor:default}\n.eg-ghost{background:var(--eg-card);border-color:var(--eg-line)}\n.eg-ghost:hover{background:var(--eg-soft)}\n.eg-ghost[disabled]{opacity:.55;cursor:default}\n.eg-link{background:none;border:0;color:var(--eg-muted);font-weight:500;padding:0 6px;height:32px}\n.eg-link:hover{color:var(--eg-fg);text-decoration:underline}\n.eg-modal{position:fixed;left:50%;top:50%;transform:translate(-50%,-50%);width:min(440px,calc(100vw - 32px));max-height:calc(100vh - 32px);overflow:auto;background:var(--eg-card);color:var(--eg-fg);border-radius:20px;box-shadow:var(--eg-shadow);padding:28px 28px 22px;text-align:center;outline:none;pointer-events:auto}\n.eg-modal.eg-pop{animation:eg-pop .32s cubic-bezier(.2,.9,.3,1.3)}\n@keyframes eg-pop{from{opacity:0;transform:translate(-50%,-46%) scale(.94)}}\n.eg-modal h2{margin:6px 0 4px;font-size:22px;font-weight:700;letter-spacing:-.2px;line-height:1.3}\n.eg-modal .eg-sub{margin:0;color:var(--eg-muted);font-size:14.5px}\n.eg-eyebrow{margin:0;font-size:12.5px;font-weight:600;letter-spacing:.3px;color:var(--eg-strong)}\n.eg-actions{display:grid;gap:6px;margin-top:20px}\n.eg-actions .eg-btn{height:44px}\n.eg-badge{width:64px;height:64px;border-radius:18px;margin:0 auto 12px;display:grid;place-items:center;background:var(--eg-tint);color:var(--eg-strong)}\n.eg-badge svg.eg-ic{width:30px;height:30px}\n.eg-quests{list-style:none;padding:0;margin:18px 0 0;text-align:left;display:grid;gap:6px}\n.eg-quests li{display:flex;align-items:center;gap:12px;padding:9px 12px;border-radius:11px;background:var(--eg-soft);font-size:14px}\n.eg-quests li .eg-n{width:26px;height:26px;border-radius:50%;background:var(--eg-card);border:1.5px solid var(--eg-line);display:grid;place-items:center;font-size:12px;font-weight:700;color:var(--eg-muted);flex:none}\n.eg-quests li.eg-first{background:var(--eg-tint)}\n.eg-quests li.eg-first .eg-n{border-color:var(--eg-primary);color:var(--eg-strong)}\n.eg-quests li.eg-ok .eg-n{background:var(--eg-ok);border-color:var(--eg-ok);color:#fff}\n.eg-quests li .eg-n svg.eg-ic{width:15px;height:15px;stroke-width:3}\n.eg-quests li .eg-t{flex:1}\n.eg-quests li small{color:var(--eg-muted);font-size:12px;white-space:nowrap}\n.eg-modal.eg-confirm{text-align:left;width:min(380px,calc(100vw - 32px));padding:22px}\n.eg-modal.eg-confirm h2{font-size:18px;margin-top:0}\n.eg-modal.eg-confirm .eg-actions{grid-template-columns:1fr 1fr}\n.eg-medal{width:84px;height:84px;border-radius:50%;margin:4px auto 10px;display:grid;place-items:center;color:#fff;background:radial-gradient(circle at 35% 30%,#ffd666,var(--eg-gold));box-shadow:0 0 0 8px #fff4d6;animation:eg-stamp .5s cubic-bezier(.2,.9,.3,1.4) .1s both}\n.eg-medal svg.eg-ic{width:42px;height:42px;stroke-width:2.6}\n@keyframes eg-stamp{from{transform:scale(.3) rotate(-25deg);opacity:0}}\n.eg-prog{display:flex;align-items:center;gap:10px;margin-top:16px;font-size:13px;color:var(--eg-muted);font-weight:600}\n.eg-prog .eg-bar{flex:1;height:8px;border-radius:4px;background:var(--eg-soft);overflow:hidden}\n.eg-prog .eg-bar i{display:block;height:100%;background:var(--eg-primary);border-radius:4px;transition:width .9s cubic-bezier(.2,.8,.2,1) .35s}\n.eg-burst{position:absolute;left:50%;top:70px;width:0;height:0;pointer-events:none}\n.eg-burst span{position:absolute;width:8px;height:12px;border-radius:2px;opacity:0;animation:eg-conf 1.1s cubic-bezier(.15,.7,.3,1) forwards}\n@keyframes eg-conf{0%{opacity:1;transform:translate(0,0) rotate(0)}100%{opacity:0;transform:translate(var(--x),var(--y)) rotate(var(--r))}}\n.eg-card{position:fixed;left:50%;bottom:28px;transform:translateX(-50%);width:min(360px,calc(100vw - 32px));background:var(--eg-card);color:var(--eg-fg);border-radius:14px;box-shadow:var(--eg-shadow);padding:14px 16px;border-top:4px solid var(--eg-primary);pointer-events:auto;outline:none}\n.eg-card .eg-row{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-top:12px}\n.eg-loading{display:flex;align-items:center;gap:10px;font-weight:600}\n.eg-spin{width:18px;height:18px;border-radius:50%;border:2.5px solid var(--eg-soft);border-top-color:var(--eg-primary);animation:eg-spin .8s linear infinite;flex:none}\n@keyframes eg-spin{to{transform:rotate(360deg)}}\n.eg-chip{position:fixed;right:22px;bottom:22px;display:flex;align-items:center;gap:10px;height:48px;padding:0 18px 0 8px;border-radius:24px;border:1px solid var(--eg-line);background:var(--eg-card);color:var(--eg-fg);box-shadow:0 8px 24px -8px rgba(16,32,64,.3);font-weight:600;font-size:14px;pointer-events:auto}\n.eg-chip svg{width:34px;height:34px}\n.eg-chip.eg-hi{animation:eg-hi 1.2s ease 2}\n@keyframes eg-hi{50%{box-shadow:0 0 0 6px color-mix(in oklab,var(--eg-primary) 35%,transparent),0 8px 24px -8px rgba(16,32,64,.3)}}\n.eg-panel{position:fixed;right:22px;bottom:82px;width:360px;max-height:calc(100vh - 110px);overflow:auto;background:var(--eg-card);color:var(--eg-fg);border:1px solid var(--eg-line);border-radius:16px;box-shadow:var(--eg-shadow);outline:none;pointer-events:auto}\n.eg-panel-bd{display:none}\n.eg-q-h{display:flex;align-items:center;gap:10px;padding:16px 12px 4px 18px}\n.eg-q-h h2{margin:0;font-size:16px;font-weight:700;flex:1}\n.eg-q-h .eg-n{font-size:13px;color:var(--eg-muted);font-weight:600}\n.eg-x{width:34px;height:34px;border-radius:10px;border:0;background:none;display:grid;place-items:center;color:var(--eg-muted)}\n.eg-x:hover{background:var(--eg-soft)}\n.eg-x svg.eg-ic{width:18px;height:18px}\n.eg-panel .eg-prog{margin:6px 18px 8px}\n.eg-q-list{list-style:none;margin:0;padding:4px 10px 6px;display:grid;gap:2px}\n.eg-q-item{display:flex;align-items:center;gap:12px;padding:10px 8px;border-radius:11px}\n.eg-q-item.eg-next{background:var(--eg-tint)}\n.eg-q-item .eg-n{width:30px;height:30px;border-radius:50%;border:1.5px solid var(--eg-line);display:grid;place-items:center;font-size:12.5px;font-weight:700;color:var(--eg-muted);flex:none;background:var(--eg-card)}\n.eg-q-item.eg-next .eg-n{border-color:var(--eg-primary);color:var(--eg-strong)}\n.eg-q-item.eg-done .eg-n{background:var(--eg-ok);border-color:var(--eg-ok);color:#fff}\n.eg-q-item.eg-done .eg-n svg.eg-ic{width:16px;height:16px;stroke-width:3}\n.eg-q-item.eg-dim .eg-n{opacity:.55}\n.eg-q-item.eg-just .eg-n{animation:eg-stamp .55s cubic-bezier(.2,.9,.3,1.4) .2s both}\n.eg-q-item .eg-t{flex:1;min-width:0}\n.eg-q-item .eg-t b{display:block;font-size:14px;font-weight:600}\n.eg-q-item.eg-done .eg-t b{color:var(--eg-muted)}\n.eg-q-item .eg-t small{display:block;font-size:12px;color:var(--eg-muted)}\n.eg-q-item .eg-t small.eg-sk{color:#b06a00}\n.eg-q-item .eg-t small.eg-lock{color:var(--eg-fg);font-weight:500}\n.eg-q-item .eg-btn{height:32px;padding:0 12px;font-size:13px}\n.eg-q-acts{display:flex;flex-direction:column;align-items:flex-end;gap:2px}\n.eg-q-acts .eg-link{height:22px;font-size:12px;padding:0 2px}\n.eg-q-f{border-top:1px solid var(--eg-line);padding:8px 12px;display:flex;justify-content:flex-end}\n.eg-toast{position:fixed;left:50%;bottom:84px;transform:translateX(-50%);background:#1c2634;color:#fff;padding:10px 16px;border-radius:10px;font-size:13.5px;box-shadow:var(--eg-shadow);max-width:calc(100vw - 32px);pointer-events:none}\nsvg.eg-ic{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;flex:none}\n@media (max-width:767px){\n .eg-bubble{width:auto}\n .eg-arrow{display:none}\n .eg-modal{top:auto;bottom:12px;transform:translateX(-50%);width:calc(100vw - 24px);padding:24px 20px 18px}\n .eg-modal.eg-pop{animation:eg-up .3s cubic-bezier(.2,.9,.3,1.1)}\n .eg-modal .eg-actions .eg-btn{height:46px}\n .eg-chip{right:16px;bottom:calc(16px + env(safe-area-inset-bottom))}\n .eg-panel-bd{display:block;position:fixed;inset:0;background:rgba(15,23,42,.38);pointer-events:auto}\n .eg-panel{left:0;right:0;bottom:0;width:100%;max-height:85vh;border-radius:18px 18px 0 0;padding-bottom:env(safe-area-inset-bottom)}\n .eg-q-item{padding:12px 8px}\n .eg-card{bottom:calc(12px + env(safe-area-inset-bottom))}\n .eg-toast{bottom:calc(76px + env(safe-area-inset-bottom))}\n}\n@keyframes eg-up{from{opacity:0;transform:translate(-50%,30px)}}\n@media (prefers-reduced-motion:reduce){\n [data-erp-guide-layer] *,[data-erp-guide-layer] *::before,[data-erp-guide-layer] *::after{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important}\n .eg-ring::after{animation:none!important;opacity:1;transform:none}\n .eg-ring.eg-flash::after{animation:eg-flash .5s ease 1!important;animation-duration:.5s!important}\n .eg-hand{animation:none!important;transform:translate(4px,6px)}\n .eg-burst{display:none}\n .eg-bubble.eg-nudge{animation:none!important;border-top-color:var(--eg-danger)}\n}\n";
|
|
13
|
+
export declare const GUIDE_CSS = "\n[data-erp-guide-layer]{position:fixed;inset:0;z-index:1000;pointer-events:none;font-family:inherit;color:var(--popover-foreground,#1c2634);\n --eg-scrim:rgba(12,20,34,.64);--eg-card:var(--popover,#fff);--eg-fg:var(--popover-foreground,#1c2634);\n --eg-muted:var(--muted-foreground,#6d7886);--eg-soft:var(--muted,#eef3f9);--eg-line:var(--border,#e8ecf1);\n --eg-primary:var(--primary,#3280dd);--eg-on-primary:var(--primary-foreground,#fff);\n --eg-tint:color-mix(in oklab,var(--eg-primary) 13%,var(--eg-card));--eg-strong:color-mix(in oklab,var(--eg-primary) 82%,#000);\n --eg-danger:var(--destructive,#d23b4b);--eg-ok:#1d9a5f;--eg-gold:#e6a417;\n --eg-shadow:0 18px 50px -12px rgba(16,32,64,.35),0 4px 12px rgba(16,32,64,.08);line-height:1.5;font-size:14px}\n[data-erp-guide-layer] *{box-sizing:border-box}\n[data-erp-guide-layer] button{font:inherit;color:inherit;cursor:pointer}\n.eg-i{pointer-events:auto}\n.eg-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}\n.eg-scrim-svg{position:fixed;inset:0;width:100%;height:100%;pointer-events:none;overflow:visible}\n.eg-scrim-svg .eg-scrim-fill{fill:var(--eg-scrim);pointer-events:none}\n.eg-scrim-svg .eg-scrim-hit{fill:transparent;pointer-events:all}\n.eg-scrim{position:fixed;inset:0;background:var(--eg-scrim);pointer-events:auto}\n.eg-scrim.eg-light{background:rgba(12,20,34,.45)}\n.eg-scrim.eg-faint{background:rgba(12,20,34,.35)}\n.eg-ring{position:fixed;border-radius:12px;pointer-events:none;box-shadow:0 0 0 3px #fff,0 0 0 6px var(--eg-primary)}\n.eg-ring.eg-move{transition:left .26s ease,top .26s ease,width .26s ease,height .26s ease}\n.eg-ring::after{content:\"\";position:absolute;inset:-6px;border-radius:15px;border:3px solid var(--eg-primary);animation:eg-pulse 1.6s ease-out infinite}\n.eg-ring.eg-flash::after{animation:eg-flash .5s ease 1}\n@keyframes eg-pulse{0%{opacity:.9;transform:scale(1)}100%{opacity:0;transform:scale(1.12)}}\n@keyframes eg-flash{0%,100%{opacity:1;transform:none}50%{opacity:.2}}\n.eg-hand{position:fixed;width:46px;height:46px;pointer-events:none;filter:drop-shadow(0 4px 6px rgba(0,0,0,.35));animation:eg-tap 1.1s ease-in-out infinite}\n.eg-hand svg{width:46px;height:46px;fill:#fff;stroke:#1c2634;stroke-width:1.4;stroke-linejoin:round;stroke-linecap:round}\n.eg-hand.eg-flip svg{transform:scaleY(-1)}\n@keyframes eg-tap{0%,100%{transform:translate(6px,8px)}50%{transform:translate(0,0)}}\n.eg-bubble{position:fixed;left:0;top:0;width:320px;background:var(--eg-card);color:var(--eg-fg);border-radius:14px;box-shadow:var(--eg-shadow);padding:14px 16px 12px;border-top:4px solid var(--eg-primary);outline:none;pointer-events:auto}\n.eg-bubble.eg-err{border-top-color:var(--eg-danger)}\n.eg-bubble.eg-nudge{animation:eg-nudge .38s ease}\n@keyframes eg-nudge{0%,100%{translate:0}20%{translate:-7px}40%{translate:6px}60%{translate:-4px}80%{translate:2px}}\n.eg-b-top{display:flex;justify-content:space-between;align-items:center;gap:8px;font-size:12px;color:var(--eg-muted)}\n.eg-b-top .eg-mis{font-weight:600;color:var(--eg-strong);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.eg-b-top .eg-cnt{white-space:nowrap;font-weight:600}\n.eg-pips{display:flex;gap:4px;margin:8px 0 10px}\n.eg-pips i{flex:1;height:4px;border-radius:2px;background:var(--eg-soft)}\n.eg-pips i.eg-d{background:var(--eg-primary)}\n.eg-pips i.eg-c{background:color-mix(in oklab,var(--eg-primary) 45%,var(--eg-card))}\n.eg-b-t{margin:0;font-size:16px;font-weight:600;line-height:1.45}\n.eg-b-w{margin:2px 0 0;font-size:13.5px;color:var(--eg-muted)}\n.eg-bubble.eg-err .eg-b-t{color:var(--eg-danger)}\n.eg-k{display:inline-block;background:var(--eg-tint);color:var(--eg-strong);border-radius:7px;padding:0 7px;font-weight:600}\n.eg-b-f{display:flex;align-items:center;justify-content:space-between;margin-top:12px;gap:8px}\n.eg-b-f .eg-btn{height:34px;padding:0 14px;font-size:13.5px}\n.eg-exit{border:0;background:none;color:var(--eg-muted);font-size:12.5px;padding:4px 0;text-decoration:underline;text-underline-offset:3px}\n.eg-exit:hover{color:var(--eg-fg)}\n.eg-arrow{position:absolute;width:14px;height:14px;background:var(--eg-card);transform:rotate(45deg);border-radius:2px}\n.eg-arrow.eg-top{background:var(--eg-primary)}\n.eg-bubble.eg-err .eg-arrow.eg-top{background:var(--eg-danger)}\n.eg-btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;height:40px;padding:0 16px;border-radius:10px;border:1px solid transparent;font-size:14px;font-weight:600;white-space:nowrap}\n.eg-btn:focus-visible,.eg-exit:focus-visible,.eg-chip:focus-visible,.eg-x:focus-visible{outline:2px solid var(--eg-primary);outline-offset:2px}\n.eg-primary{background:var(--eg-primary);color:var(--eg-on-primary)!important}\n.eg-primary:hover{background:var(--eg-strong)}\n.eg-primary[disabled]{opacity:.55;cursor:default}\n.eg-ghost{background:var(--eg-card);border-color:var(--eg-line)}\n.eg-ghost:hover{background:var(--eg-soft)}\n.eg-ghost[disabled]{opacity:.55;cursor:default}\n.eg-link{background:none;border:0;color:var(--eg-muted);font-weight:500;padding:0 6px;height:32px}\n.eg-link:hover{color:var(--eg-fg);text-decoration:underline}\n.eg-modal{position:fixed;left:50%;top:50%;transform:translate(-50%,-50%);width:min(440px,calc(100vw - 32px));max-height:calc(100vh - 32px);overflow:auto;background:var(--eg-card);color:var(--eg-fg);border-radius:20px;box-shadow:var(--eg-shadow);padding:28px 28px 22px;text-align:center;outline:none;pointer-events:auto}\n.eg-modal.eg-pop{animation:eg-pop .32s cubic-bezier(.2,.9,.3,1.3)}\n@keyframes eg-pop{from{opacity:0;transform:translate(-50%,-46%) scale(.94)}}\n.eg-modal h2{margin:6px 0 4px;font-size:22px;font-weight:700;letter-spacing:-.2px;line-height:1.3}\n.eg-modal .eg-sub{margin:0;color:var(--eg-muted);font-size:14.5px}\n.eg-eyebrow{margin:0;font-size:12.5px;font-weight:600;letter-spacing:.3px;color:var(--eg-strong)}\n.eg-actions{display:grid;gap:6px;margin-top:20px}\n.eg-actions .eg-btn{height:44px}\n.eg-badge{width:64px;height:64px;border-radius:18px;margin:0 auto 12px;display:grid;place-items:center;background:var(--eg-tint);color:var(--eg-strong)}\n.eg-badge svg.eg-ic{width:30px;height:30px}\n.eg-quests{list-style:none;padding:0;margin:18px 0 0;text-align:left;display:grid;gap:6px}\n.eg-quests li{display:flex;align-items:center;gap:12px;padding:9px 12px;border-radius:11px;background:var(--eg-soft);font-size:14px}\n.eg-quests li .eg-n{width:26px;height:26px;border-radius:50%;background:var(--eg-card);border:1.5px solid var(--eg-line);display:grid;place-items:center;font-size:12px;font-weight:700;color:var(--eg-muted);flex:none}\n.eg-quests li.eg-first{background:var(--eg-tint)}\n.eg-quests li.eg-first .eg-n{border-color:var(--eg-primary);color:var(--eg-strong)}\n.eg-quests li.eg-ok .eg-n{background:var(--eg-ok);border-color:var(--eg-ok);color:#fff}\n.eg-quests li .eg-n svg.eg-ic{width:15px;height:15px;stroke-width:3}\n.eg-quests li .eg-t{flex:1}\n.eg-quests li small{color:var(--eg-muted);font-size:12px;white-space:nowrap}\n.eg-modal.eg-confirm{text-align:left;width:min(380px,calc(100vw - 32px));padding:22px}\n.eg-modal.eg-confirm h2{font-size:18px;margin-top:0}\n.eg-modal.eg-confirm .eg-actions{grid-template-columns:1fr 1fr}\n.eg-medal{width:84px;height:84px;border-radius:50%;margin:4px auto 10px;display:grid;place-items:center;color:#fff;background:radial-gradient(circle at 35% 30%,#ffd666,var(--eg-gold));box-shadow:0 0 0 8px #fff4d6;animation:eg-stamp .5s cubic-bezier(.2,.9,.3,1.4) .1s both}\n.eg-medal svg.eg-ic{width:42px;height:42px;stroke-width:2.6}\n@keyframes eg-stamp{from{transform:scale(.3) rotate(-25deg);opacity:0}}\n.eg-prog{display:flex;align-items:center;gap:10px;margin-top:16px;font-size:13px;color:var(--eg-muted);font-weight:600}\n.eg-prog .eg-bar{flex:1;height:8px;border-radius:4px;background:var(--eg-soft);overflow:hidden}\n.eg-prog .eg-bar i{display:block;height:100%;background:var(--eg-primary);border-radius:4px;transition:width .9s cubic-bezier(.2,.8,.2,1) .35s}\n.eg-burst{position:absolute;left:50%;top:70px;width:0;height:0;pointer-events:none}\n.eg-burst span{position:absolute;width:8px;height:12px;border-radius:2px;opacity:0;animation:eg-conf 1.1s cubic-bezier(.15,.7,.3,1) forwards}\n@keyframes eg-conf{0%{opacity:1;transform:translate(0,0) rotate(0)}100%{opacity:0;transform:translate(var(--x),var(--y)) rotate(var(--r))}}\n.eg-card{position:fixed;left:50%;bottom:calc(var(--erp-guide-bottom-offset,16px) + 12px);transform:translateX(-50%);width:min(360px,calc(100vw - 32px));background:var(--eg-card);color:var(--eg-fg);border-radius:14px;box-shadow:var(--eg-shadow);padding:14px 16px;border-top:4px solid var(--eg-primary);pointer-events:auto;outline:none}\n.eg-card .eg-row{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-top:12px}\n.eg-loading{display:flex;align-items:center;gap:10px;font-weight:600}\n.eg-spin{width:18px;height:18px;border-radius:50%;border:2.5px solid var(--eg-soft);border-top-color:var(--eg-primary);animation:eg-spin .8s linear infinite;flex:none}\n@keyframes eg-spin{to{transform:rotate(360deg)}}\n.eg-chip{position:fixed;right:22px;bottom:var(--erp-guide-bottom-offset,22px);display:flex;align-items:center;gap:10px;height:48px;padding:0 18px 0 8px;border-radius:24px;border:1px solid var(--eg-line);background:var(--eg-card);color:var(--eg-fg);box-shadow:0 8px 24px -8px rgba(16,32,64,.3);font-weight:600;font-size:14px;pointer-events:auto}\n.eg-chip svg{width:34px;height:34px}\n.eg-chip.eg-hi{animation:eg-hi 1.2s ease 2}\n@keyframes eg-hi{50%{box-shadow:0 0 0 6px color-mix(in oklab,var(--eg-primary) 35%,transparent),0 8px 24px -8px rgba(16,32,64,.3)}}\n.eg-panel{position:fixed;right:22px;bottom:calc(var(--erp-guide-bottom-offset,22px) + 60px);width:360px;max-height:calc(100vh - 110px);overflow:auto;background:var(--eg-card);color:var(--eg-fg);border:1px solid var(--eg-line);border-radius:16px;box-shadow:var(--eg-shadow);outline:none;pointer-events:auto}\n.eg-panel-bd{display:none}\n.eg-q-h{display:flex;align-items:center;gap:10px;padding:16px 12px 4px 18px}\n.eg-q-h h2{margin:0;font-size:16px;font-weight:700;flex:1}\n.eg-q-h .eg-n{font-size:13px;color:var(--eg-muted);font-weight:600}\n.eg-x{width:34px;height:34px;border-radius:10px;border:0;background:none;display:grid;place-items:center;color:var(--eg-muted)}\n.eg-x:hover{background:var(--eg-soft)}\n.eg-x svg.eg-ic{width:18px;height:18px}\n.eg-panel .eg-prog{margin:6px 18px 8px}\n.eg-q-list{list-style:none;margin:0;padding:4px 10px 6px;display:grid;gap:2px}\n.eg-q-item{display:flex;align-items:center;gap:12px;padding:10px 8px;border-radius:11px}\n.eg-q-item.eg-next{background:var(--eg-tint)}\n.eg-q-item .eg-n{width:30px;height:30px;border-radius:50%;border:1.5px solid var(--eg-line);display:grid;place-items:center;font-size:12.5px;font-weight:700;color:var(--eg-muted);flex:none;background:var(--eg-card)}\n.eg-q-item.eg-next .eg-n{border-color:var(--eg-primary);color:var(--eg-strong)}\n.eg-q-item.eg-done .eg-n{background:var(--eg-ok);border-color:var(--eg-ok);color:#fff}\n.eg-q-item.eg-done .eg-n svg.eg-ic{width:16px;height:16px;stroke-width:3}\n.eg-q-item.eg-dim .eg-n{opacity:.55}\n.eg-q-item.eg-just .eg-n{animation:eg-stamp .55s cubic-bezier(.2,.9,.3,1.4) .2s both}\n.eg-q-item .eg-t{flex:1;min-width:0}\n.eg-q-item .eg-t b{display:block;font-size:14px;font-weight:600}\n.eg-q-item.eg-done .eg-t b{color:var(--eg-muted)}\n.eg-q-item .eg-t small{display:block;font-size:12px;color:var(--eg-muted)}\n.eg-q-item .eg-t small.eg-sk{color:#b06a00}\n.eg-q-item .eg-t small.eg-lock{color:var(--eg-fg);font-weight:500}\n.eg-q-item .eg-btn{height:32px;padding:0 12px;font-size:13px}\n.eg-q-acts{display:flex;flex-direction:column;align-items:flex-end;gap:2px}\n.eg-q-acts .eg-link{height:22px;font-size:12px;padding:0 2px}\n.eg-q-f{border-top:1px solid var(--eg-line);padding:8px 12px;display:flex;justify-content:flex-end}\n.eg-toast{position:fixed;left:50%;bottom:calc(var(--erp-guide-bottom-offset,22px) + 62px);transform:translateX(-50%);background:#1c2634;color:#fff;padding:10px 16px;border-radius:10px;font-size:13.5px;box-shadow:var(--eg-shadow);max-width:calc(100vw - 32px);pointer-events:none}\nsvg.eg-ic{width:18px;height:18px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;flex:none}\n@media (max-width:767px){\n .eg-bubble{width:auto}\n .eg-arrow{display:none}\n .eg-modal{top:auto;bottom:12px;transform:translateX(-50%);width:calc(100vw - 24px);padding:24px 20px 18px}\n .eg-modal.eg-pop{animation:eg-up .3s cubic-bezier(.2,.9,.3,1.1)}\n .eg-modal .eg-actions .eg-btn{height:46px}\n .eg-chip{right:16px;bottom:var(--erp-guide-bottom-offset,calc(16px + env(safe-area-inset-bottom)))}\n .eg-panel-bd{display:block;position:fixed;inset:0;background:rgba(15,23,42,.38);pointer-events:auto}\n .eg-panel{left:0;right:0;bottom:0;width:100%;max-height:85vh;border-radius:18px 18px 0 0;padding-bottom:env(safe-area-inset-bottom)}\n .eg-q-item{padding:12px 8px}\n .eg-card{bottom:calc(var(--erp-guide-bottom-offset,calc(16px + env(safe-area-inset-bottom))) - 4px)}\n .eg-toast{bottom:calc(var(--erp-guide-bottom-offset,calc(16px + env(safe-area-inset-bottom))) + 60px)}\n}\n@keyframes eg-up{from{opacity:0;transform:translate(-50%,30px)}}\n@media (prefers-reduced-motion:reduce){\n [data-erp-guide-layer] *,[data-erp-guide-layer] *::before,[data-erp-guide-layer] *::after{animation-duration:.001ms!important;animation-iteration-count:1!important;transition-duration:.001ms!important}\n .eg-ring::after{animation:none!important;opacity:1;transform:none}\n .eg-ring.eg-flash::after{animation:eg-flash .5s ease 1!important;animation-duration:.5s!important}\n .eg-hand{animation:none!important;transform:translate(4px,6px)}\n .eg-burst{display:none}\n .eg-bubble.eg-nudge{animation:none!important;border-top-color:var(--eg-danger)}\n}\n";
|
package/dist/guide/machine.d.ts
CHANGED
|
@@ -44,6 +44,9 @@ export type GuideScreen = {
|
|
|
44
44
|
/** A `hidden` trigger's anchor has been seen on this step, so its
|
|
45
45
|
* going away counts. */
|
|
46
46
|
armed: boolean;
|
|
47
|
+
/** A commit step shown in its read form: nothing to save
|
|
48
|
+
* (GuideStep.nothingToSave). */
|
|
49
|
+
nothingToSave: boolean;
|
|
47
50
|
} | {
|
|
48
51
|
name: "celebrate";
|
|
49
52
|
mission: string;
|
|
@@ -63,6 +66,23 @@ export interface GuideState {
|
|
|
63
66
|
nudge: number;
|
|
64
67
|
/** The gate card was put away for this visit ("ไว้ทีหลัง"). */
|
|
65
68
|
gateDismissed: boolean;
|
|
69
|
+
/**
|
|
70
|
+
* What the user already had open when the current replay started: those
|
|
71
|
+
* are theirs, and ending the replay leaves them alone (see pushAbort).
|
|
72
|
+
*/
|
|
73
|
+
replayPage: ReplayPage | null;
|
|
74
|
+
/**
|
|
75
|
+
* Missions done outside the tour (`completeOn`) whose celebration waits for
|
|
76
|
+
* the next idle moment (never mid-step). Not saved: a reload drops it.
|
|
77
|
+
*/
|
|
78
|
+
pendingCelebrate: string[];
|
|
79
|
+
}
|
|
80
|
+
export interface ReplayPage {
|
|
81
|
+
mission: string;
|
|
82
|
+
/** The mission's abort anchors that were on the page at the start. */
|
|
83
|
+
anchors: string[];
|
|
84
|
+
/** An app dialog was open at the start. */
|
|
85
|
+
dialog: boolean;
|
|
66
86
|
}
|
|
67
87
|
/** What the machine may ask about the page. */
|
|
68
88
|
export interface GuideEnv {
|
|
@@ -77,6 +97,8 @@ export interface GuideEnv {
|
|
|
77
97
|
sidebarOpen: boolean;
|
|
78
98
|
/** The current value of the step target's field. */
|
|
79
99
|
targetValue: () => string;
|
|
100
|
+
/** An app dialog (not the tour's) is open. */
|
|
101
|
+
dialogOpen?: () => boolean;
|
|
80
102
|
}
|
|
81
103
|
export type GuideSignal = {
|
|
82
104
|
kind: "api";
|
|
@@ -166,6 +188,15 @@ export type GuideAction = {
|
|
|
166
188
|
} | {
|
|
167
189
|
type: "serverRow";
|
|
168
190
|
progress: GuideProgress;
|
|
191
|
+
}
|
|
192
|
+
/** An API answer or app event, whenever the host is mounted: `completeOn`. */
|
|
193
|
+
| {
|
|
194
|
+
type: "passive";
|
|
195
|
+
signal: GuideSignal;
|
|
196
|
+
}
|
|
197
|
+
/** The host is idle: show a waiting `completeOn` celebration. */
|
|
198
|
+
| {
|
|
199
|
+
type: "idleCelebrate";
|
|
169
200
|
};
|
|
170
201
|
export type GuideEffect = {
|
|
171
202
|
type: "save";
|
|
@@ -207,12 +238,32 @@ export declare const COPY: {
|
|
|
207
238
|
export declare const BRIDGE_TARGET = "shell.menu-toggle";
|
|
208
239
|
export declare function initialGuideState(audience: GuideAudience, progress: GuideProgress): GuideState;
|
|
209
240
|
export declare function findMission(suite: GuideSuite, key: string | null | undefined): GuideMission | undefined;
|
|
241
|
+
/**
|
|
242
|
+
* Whether the user has this mission (GuideMission.visible). Without the
|
|
243
|
+
* predicate, yes; with it, only `true` (undefined — not known yet — and a
|
|
244
|
+
* throw hide it).
|
|
245
|
+
*/
|
|
246
|
+
export declare function missionShown(m: GuideMission, ctx: GuideContext): boolean;
|
|
247
|
+
/** The missions this user has, in order: what the panel draws and n/N counts. */
|
|
248
|
+
export declare function shownMissions(suite: GuideSuite, ctx: GuideContext): GuideMission[];
|
|
249
|
+
/** The mission's number among the shown ones (1-based); its place in the suite when hidden. */
|
|
250
|
+
export declare function missionNumber(suite: GuideSuite, key: string, ctx: GuideContext): number;
|
|
210
251
|
export declare function guideContext(env: GuideEnv, data: Readonly<Record<string, string>>, params?: RouteParams): GuideContext;
|
|
211
252
|
export declare function resolveText(t: GuideText | undefined, ctx: GuideContext): string;
|
|
212
253
|
export declare function triggersOf(step: GuideStep): GuideTrigger[];
|
|
213
254
|
export declare function stepKind(step: GuideStep): import("./types").GuideStepKind;
|
|
214
255
|
/** The last checkpoint at or before `index` (a mission's first step always is one). */
|
|
215
256
|
export declare function checkpointAtOrBefore(steps: GuideStep[], index: number): number;
|
|
257
|
+
/**
|
|
258
|
+
* A commit step with nothing to save: its button is not on the page, and what
|
|
259
|
+
* is saved is (GuideStep.nothingToSave).
|
|
260
|
+
*/
|
|
261
|
+
export declare function nothingToSaveHolds(step: GuideStep, env: GuideEnv, ctx: GuideContext): boolean;
|
|
262
|
+
/**
|
|
263
|
+
* The step as it is shown: a commit step with nothing to save is a read step
|
|
264
|
+
* on what is saved, with its own title (ถัดไป moves on).
|
|
265
|
+
*/
|
|
266
|
+
export declare function shownStep(step: GuideStep, nothingToSave: boolean): GuideStep;
|
|
216
267
|
/** Whether the step's target (or the bridge's) is on screen. */
|
|
217
268
|
export declare function stepTargetVisible(step: GuideStep, env: GuideEnv, ctx: GuideContext, bridge: boolean): boolean;
|
|
218
269
|
/** The anchor the spotlight is on for the current step. */
|
|
@@ -228,9 +279,18 @@ export declare function spotlightTarget(step: GuideStep, ctx: GuideContext, brid
|
|
|
228
279
|
export declare function stepHomeRoute(steps: GuideStep[], index: number): string | undefined;
|
|
229
280
|
/** What puts the page back when a replay ends at this step (see GuideStep.abort). */
|
|
230
281
|
export declare function abortActionsFor(mission: GuideMission, index: number): GuideAbortAction[];
|
|
282
|
+
/** Every anchor the mission's abort actions press. */
|
|
283
|
+
export declare function abortAnchorsOf(mission: GuideMission): string[];
|
|
284
|
+
/**
|
|
285
|
+
* What the replay may do to put the page back: not press what the user had
|
|
286
|
+
* open before it started, not Escape out of a dialog that was already open,
|
|
287
|
+
* and no app event while anything of theirs was open.
|
|
288
|
+
*/
|
|
289
|
+
export declare function abortActionsLeft(actions: GuideAbortAction[], before: ReplayPage | null): GuideAbortAction[];
|
|
231
290
|
/** Status of each mission as the panel shows it. */
|
|
232
291
|
export type MissionView = "todo" | "next" | "active" | "skipped" | "done" | "already" | "locked" | "waiting";
|
|
233
292
|
export declare function missionSettled(m: GuideMission, entry: MissionEntry | undefined, ctx: GuideContext): boolean;
|
|
293
|
+
/** Settled missions among the shown ones (the n of n/N). */
|
|
234
294
|
export declare function settledCount(suite: GuideSuite, progress: GuideProgress, ctx: GuideContext): number;
|
|
235
295
|
export declare function gateState(suite: GuideSuite, ctx: GuideContext): boolean | undefined;
|
|
236
296
|
export declare function missionViews(suite: GuideSuite, progress: GuideProgress, ctx: GuideContext): Array<{
|
|
@@ -240,10 +300,16 @@ export declare function missionViews(suite: GuideSuite, progress: GuideProgress,
|
|
|
240
300
|
}>;
|
|
241
301
|
/** The mission the celebration offers next: the first one not settled and not locked. */
|
|
242
302
|
export declare function nextMissionKey(suite: GuideSuite, progress: GuideProgress, ctx: GuideContext): string | null;
|
|
243
|
-
/** Whether the welcome should open by itself. */
|
|
244
|
-
export declare function welcomeDue(state: GuideState, suite: GuideSuite): boolean;
|
|
303
|
+
/** Whether the welcome should open by itself (with `ctx`: only when a mission is shown). */
|
|
304
|
+
export declare function welcomeDue(state: GuideState, suite: GuideSuite, ctx?: GuideContext): boolean;
|
|
245
305
|
/** Whether the floating "ภารกิจ n/N" chip shows. */
|
|
246
306
|
export declare function chipVisible(state: GuideState, suite: GuideSuite, ctx: GuideContext): boolean;
|
|
247
307
|
/** "กด [บันทึก]" → "กด บันทึก" (for screen readers). */
|
|
248
308
|
export declare function plainTitle(t: string): string;
|
|
309
|
+
/** A mission's `completeOn` triggers, as a list. */
|
|
310
|
+
export declare function completeTriggersOf(mission: GuideMission): GuideTrigger[];
|
|
311
|
+
/** Every app event name a suite's `completeOn` listens for. */
|
|
312
|
+
export declare function passiveEventNames(suite: GuideSuite): string[];
|
|
313
|
+
/** Missions whose `completeOn` this signal meets ({ api } and { event } only). */
|
|
314
|
+
export declare function passiveMatches(suite: GuideSuite, sig: GuideSignal): GuideMission[];
|
|
249
315
|
export declare function reduceGuide(state: GuideState, action: GuideAction, suite: GuideSuite, env: GuideEnv): GuideResult;
|
package/dist/guide/patterns.d.ts
CHANGED
|
@@ -7,10 +7,14 @@ export type RouteParams = Record<string, string>;
|
|
|
7
7
|
/**
|
|
8
8
|
* Matches a Next-style page pattern ("/[code]/employee/[id]", optionally
|
|
9
9
|
* "?tab=job") against a path and query. `[code]`, when given, must be the
|
|
10
|
-
* organisation code.
|
|
10
|
+
* organisation code. `[[x]]` is a segment that may be absent. Returns the
|
|
11
|
+
* params, or null.
|
|
11
12
|
*/
|
|
12
13
|
export declare function matchRoute(pattern: string, pathname: string, search?: URLSearchParams | string | null, code?: string): RouteParams | null;
|
|
13
|
-
/**
|
|
14
|
+
/**
|
|
15
|
+
* Fills a page pattern's params ("/[code]/x/[id]" → "/O1/x/42"); null if one
|
|
16
|
+
* is missing. A `[[x]]` segment without a value is left out.
|
|
17
|
+
*/
|
|
14
18
|
export declare function fillRoute(pattern: string, params: Readonly<Record<string, string | undefined>>): string | null;
|
|
15
19
|
/**
|
|
16
20
|
* The path of a request, without origin, base URL query or hash:
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import type { GuideSuite } from "./types";
|
|
2
|
-
import {
|
|
2
|
+
import type { GuideProgress, GuidesAnswer } from "./progress";
|
|
3
|
+
import { type GuideProgressAdapter } from "./progress-sync";
|
|
4
|
+
/** platform-api's `…/organizations/:id/guides/me` as a progress adapter. */
|
|
5
|
+
export declare function platformGuideProgress(organizationId: string): GuideProgressAdapter;
|
|
3
6
|
/** GET …/guides/me?app=…; null (show nothing) on any failure or odd answer. */
|
|
4
7
|
export declare function fetchGuides(organizationId: string, suite: GuideSuite, signal?: AbortSignal): Promise<GuidesAnswer | null>;
|
|
5
8
|
/**
|
|
6
|
-
* PUT the whole state
|
|
7
|
-
*
|
|
8
|
-
* stored row, or null when it could not be saved (the tour goes on; the
|
|
9
|
-
* session copy keeps the place).
|
|
9
|
+
* PUT the whole state; on 409 merge and try once more (progress-sync.ts).
|
|
10
|
+
* Returns the stored row, or null when it could not be saved.
|
|
10
11
|
*/
|
|
11
12
|
export declare function saveGuides(organizationId: string, suite: GuideSuite, progress: GuideProgress): Promise<GuideProgress | null>;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loading and saving tour progress through an adapter, so the rules stay in
|
|
3
|
+
* one place whatever carries the request: platform-api through the shell's
|
|
4
|
+
* axios (GuideHost), or peoplx-api's `/public/line/me/guides` through LIFF's
|
|
5
|
+
* fetch client (guide-core). The adapter only moves bytes; parsing, the
|
|
6
|
+
* fail-open rule and the 409 merge are here.
|
|
7
|
+
*
|
|
8
|
+
* No runtime imports beyond sibling pure modules: the tests run it in Node.
|
|
9
|
+
*/
|
|
10
|
+
import type { GuideSuite } from "./types";
|
|
11
|
+
import { type GuideProgress, type GuidesAnswer } from "./progress";
|
|
12
|
+
/** What a progress call is about. */
|
|
13
|
+
export interface GuideProgressRequest {
|
|
14
|
+
/** The suite's app ("peoplx", "liff"). */
|
|
15
|
+
app: string;
|
|
16
|
+
/** The suite's key, the row on the server ("liff.first-run"). */
|
|
17
|
+
guideKey: string;
|
|
18
|
+
}
|
|
19
|
+
/** An HTTP answer as the adapter got it. */
|
|
20
|
+
export interface GuideProgressResponse {
|
|
21
|
+
/** The HTTP status. */
|
|
22
|
+
status: number;
|
|
23
|
+
/** The parsed JSON body (the API's envelope, or the row itself). */
|
|
24
|
+
data: unknown;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* How the engine reaches the progress API. Both calls carry the user's
|
|
28
|
+
* credentials and the organisation, as the app's own client does.
|
|
29
|
+
*
|
|
30
|
+
* - `fetchProgress` answers what `GET …/guides/me?app=` answers (API.md §3):
|
|
31
|
+
* the envelope `{ data: { app, mode, audience, guides } }` or its `data`.
|
|
32
|
+
* Throw, or return anything else, and the tour does not show.
|
|
33
|
+
* - `saveProgress` sends `body` as the whole row (API.md §4) and returns the
|
|
34
|
+
* status and parsed body — a 409 too, with its `current`, so the engine
|
|
35
|
+
* merges and retries. A client that throws on non-2xx may instead throw
|
|
36
|
+
* `new GuideProgressConflict(current)` (or anything with `status: 409` and
|
|
37
|
+
* `current`): it is read as the same 409. Throw anything else (or return
|
|
38
|
+
* another status) on any other failure: the tour goes on and the session
|
|
39
|
+
* copy keeps the place.
|
|
40
|
+
*/
|
|
41
|
+
export interface GuideProgressAdapter {
|
|
42
|
+
fetchProgress(req: GuideProgressRequest & {
|
|
43
|
+
signal?: AbortSignal;
|
|
44
|
+
}): Promise<unknown>;
|
|
45
|
+
saveProgress(req: GuideProgressRequest & {
|
|
46
|
+
body: Record<string, unknown>;
|
|
47
|
+
}): Promise<GuideProgressResponse>;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* A 409 from the progress API, for a client that throws on non-2xx: throw
|
|
51
|
+
* it from `saveProgress` with the answer's `current` (the stored row, or
|
|
52
|
+
* null) and the engine merges as if `{ status: 409, data: { current } }` had
|
|
53
|
+
* been returned.
|
|
54
|
+
*/
|
|
55
|
+
export declare class GuideProgressConflict extends Error {
|
|
56
|
+
readonly current: unknown;
|
|
57
|
+
readonly code: string;
|
|
58
|
+
readonly status = 409;
|
|
59
|
+
constructor(current: unknown, code?: string);
|
|
60
|
+
}
|
|
61
|
+
/** The GET, parsed for this suite; null (show nothing) on any failure or odd answer. */
|
|
62
|
+
export declare function loadGuides(adapter: GuideProgressAdapter, suite: GuideSuite, signal?: AbortSignal): Promise<GuidesAnswer | null>;
|
|
63
|
+
/**
|
|
64
|
+
* PUT the whole state. On 409 the server's row comes back: merge (keeping
|
|
65
|
+
* whatever is further along) and try once more with its rev. Returns the
|
|
66
|
+
* stored row, or null when it could not be saved.
|
|
67
|
+
*/
|
|
68
|
+
export declare function storeGuides(adapter: GuideProgressAdapter, suite: GuideSuite, progress: GuideProgress): Promise<GuideProgress | null>;
|
package/dist/guide/types.d.ts
CHANGED
|
@@ -10,7 +10,9 @@
|
|
|
10
10
|
* The full guide for tour authors is _claude-work/peoplx-guide/ENGINE-API.md.
|
|
11
11
|
*/
|
|
12
12
|
/** Which app a tour belongs to (the same ids as the help channel). */
|
|
13
|
-
export type GuideAppId = "platform" | "accounx" | "invenx" | "plannex" | "peoplx" | "sellx" | "carex"
|
|
13
|
+
export type GuideAppId = "platform" | "accounx" | "invenx" | "plannex" | "peoplx" | "sellx" | "carex"
|
|
14
|
+
/** The employee app inside LINE (erp-liff), through `guide-core`. */
|
|
15
|
+
| "liff";
|
|
14
16
|
/**
|
|
15
17
|
* A `data-guide` key, "<app>.<area>.<element>" — "peoplx.shift.edit".
|
|
16
18
|
* The shell's own: "nav.<menu item id>", "shell.menu-toggle", "shell.help".
|
|
@@ -48,7 +50,8 @@ export type GuideText = string | ((ctx: GuideContext) => string);
|
|
|
48
50
|
*/
|
|
49
51
|
export type GuideTrigger =
|
|
50
52
|
/** The page is this route. Next-style pattern; an optional `?k=v` must be
|
|
51
|
-
* in the query. `/[code]/setting?tab=department`
|
|
53
|
+
* in the query. `/[code]/setting?tab=department`. `[[x]]` is a segment
|
|
54
|
+
* that may be absent: `/me/[[org]]/attendance` (shell ≥ 0.1.68). */
|
|
52
55
|
{
|
|
53
56
|
route: string;
|
|
54
57
|
}
|
|
@@ -180,6 +183,17 @@ export interface GuideStep {
|
|
|
180
183
|
* or Escape to the open dialog. Overrides the mission's `abort`.
|
|
181
184
|
*/
|
|
182
185
|
abort?: GuideAbortAction | GuideAbortAction[];
|
|
186
|
+
/**
|
|
187
|
+
* "commit" steps whose button only shows after a change (a save bar that
|
|
188
|
+
* appears once the form is edited). When `target` is not on the page but
|
|
189
|
+
* `nothingToSave.target` is (what is saved is on screen and nothing is
|
|
190
|
+
* changed), the step is a read step on that anchor, with ถัดไป, which moves
|
|
191
|
+
* on as if saved. The moment `target` shows (the user changed something)
|
|
192
|
+
* it is the commit step again. Name an anchor that only exists when the
|
|
193
|
+
* saved state is real, so a first run never passes without a save that
|
|
194
|
+
* was needed (shell ≥ 0.1.67).
|
|
195
|
+
*/
|
|
196
|
+
nothingToSave?: GuideNothingToSave;
|
|
183
197
|
/**
|
|
184
198
|
* "commit" steps: what a refused save means. Return the key of the step to
|
|
185
199
|
* go back to (a field) and/or the line to show. Default: stay, show the
|
|
@@ -190,10 +204,20 @@ export interface GuideStep {
|
|
|
190
204
|
message?: string;
|
|
191
205
|
} | void;
|
|
192
206
|
}
|
|
207
|
+
/** A commit step's read form when there is nothing to save (GuideStep.nothingToSave). */
|
|
208
|
+
export interface GuideNothingToSave {
|
|
209
|
+
/** What is saved, on screen (the placed point's card, the saved list). */
|
|
210
|
+
target: GuideAnchorKey;
|
|
211
|
+
title: GuideText;
|
|
212
|
+
why?: GuideText;
|
|
213
|
+
/** Anchors the user may use meanwhile; a change there brings the save back. */
|
|
214
|
+
allow?: GuideAnchorKey[];
|
|
215
|
+
}
|
|
193
216
|
/**
|
|
194
217
|
* One thing the engine does to put the page back when a replay ends early.
|
|
195
218
|
* Run in order, after the tour has let go of the page; an anchor that is not
|
|
196
|
-
* on the page is passed over
|
|
219
|
+
* on the page is passed over, and so is one that was already on the page
|
|
220
|
+
* when the replay started (the user's own open form: shell ≥ 0.1.67).
|
|
197
221
|
*/
|
|
198
222
|
export type GuideAbortAction =
|
|
199
223
|
/** Press this anchor (the form's ยกเลิก, a dialog's close). */
|
|
@@ -242,6 +266,24 @@ export interface GuideMission {
|
|
|
242
266
|
* "ดูวิธีทำ" (a replay). undefined = not known yet.
|
|
243
267
|
*/
|
|
244
268
|
alreadyDone?: (ctx: GuideContext) => boolean | undefined;
|
|
269
|
+
/**
|
|
270
|
+
* Whether this user has the mission at all (a menu the org lacks, a plan
|
|
271
|
+
* without LINE). A hidden mission is not drawn in the panel or the welcome,
|
|
272
|
+
* does not count in n/N and is never "next". Without it the mission shows;
|
|
273
|
+
* with it, only `true` shows it: undefined (not known yet) and a throw hide
|
|
274
|
+
* it, so a mission the user may not have never flashes in. A hidden
|
|
275
|
+
* mission named in another's `after` does not lock it (shell ≥ 0.1.68).
|
|
276
|
+
*/
|
|
277
|
+
visible?: (ctx: GuideContext) => boolean | undefined;
|
|
278
|
+
/**
|
|
279
|
+
* Done without the tour: while the engine is mounted (not only inside a
|
|
280
|
+
* step), this `{ api }` or `{ event }` trigger marks the mission done with
|
|
281
|
+
* the ordinary save, and its celebration shows at the next idle moment,
|
|
282
|
+
* never in the middle of a step. Other trigger kinds are ignored here.
|
|
283
|
+
* E.g. the first real punch: `{ api: { method: "POST", path:
|
|
284
|
+
* "/public/line/me/attendance/punch" } }` (shell ≥ 0.1.68).
|
|
285
|
+
*/
|
|
286
|
+
completeOn?: GuideTrigger | GuideTrigger[];
|
|
245
287
|
/** The celebration. Title defaults to "<title>แล้ว". */
|
|
246
288
|
done?: {
|
|
247
289
|
title?: GuideText;
|
|
@@ -251,6 +293,9 @@ export interface GuideMission {
|
|
|
251
293
|
* How to put the page back when a replay of this mission ends without
|
|
252
294
|
* saving (a step's own `abort` wins). Default: Escape, and only from a step
|
|
253
295
|
* that is not a checkpoint (inside the dialog or form the tour opened).
|
|
296
|
+
* Whatever was already open when the replay started is the user's and is
|
|
297
|
+
* left alone: an anchor on the page then is never pressed, and no Escape
|
|
298
|
+
* is sent when an app dialog was open (shell ≥ 0.1.67).
|
|
254
299
|
*/
|
|
255
300
|
abort?: GuideAbortAction | GuideAbortAction[];
|
|
256
301
|
steps: GuideStep[];
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var guideRuntime = require('./chunks/guide-runtime-B2RjoQeb.cjs');
|
|
5
|
+
require('react/jsx-runtime');
|
|
6
|
+
require('react');
|
|
7
|
+
require('react-dom');
|
|
8
|
+
require('@floating-ui/dom');
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
exports.GUIDE_API_EVENT = guideRuntime.API_EVENT;
|
|
13
|
+
exports.GUIDE_EVENT_PREFIX = guideRuntime.GUIDE_EVENT_PREFIX;
|
|
14
|
+
exports.GUIDE_LAYER_ATTRIBUTE = guideRuntime.GUIDE_LAYER_ATTRIBUTE;
|
|
15
|
+
exports.GuideProgressConflict = guideRuntime.GuideProgressConflict;
|
|
16
|
+
exports.GuideRuntime = guideRuntime.GuideRuntime;
|
|
17
|
+
exports.apiCallDetail = guideRuntime.apiCallDetail;
|
|
18
|
+
exports.emitGuideEvent = guideRuntime.emitGuideEvent;
|
|
19
|
+
exports.fillRoute = guideRuntime.fillRoute;
|
|
20
|
+
exports.guideAnchor = guideRuntime.guideAnchor;
|
|
21
|
+
exports.loadGuides = guideRuntime.loadGuides;
|
|
22
|
+
exports.matchApiPath = guideRuntime.matchApiPath;
|
|
23
|
+
exports.matchRoute = guideRuntime.matchRoute;
|
|
24
|
+
exports.openGuidePanel = guideRuntime.openGuidePanel;
|
|
25
|
+
exports.reportApiCall = guideRuntime.reportApiCall;
|
|
26
|
+
exports.reportApiEvent = guideRuntime.reportApiEvent;
|
|
27
|
+
exports.storeGuides = guideRuntime.storeGuides;
|
|
28
|
+
exports.useGuideEntry = guideRuntime.useGuideEntry;
|
|
29
|
+
//# sourceMappingURL=guide-core.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guide-core.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -0,0 +1,7 @@
|
|
|
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, e as apiCallDetail, f as emitGuideEvent, g as fillRoute, h as guideAnchor, l as loadGuides, m as matchApiPath, i as matchRoute, o as openGuidePanel, r as reportApiCall, j as reportApiEvent, s as storeGuides, u as useGuideEntry } from './chunks/guide-runtime-BT7rN-5p.esm.js';
|
|
3
|
+
import 'react/jsx-runtime';
|
|
4
|
+
import 'react';
|
|
5
|
+
import 'react-dom';
|
|
6
|
+
import '@floating-ui/dom';
|
|
7
|
+
//# sourceMappingURL=guide-core.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guide-core.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;"}
|