@eintrek/erp-shell 0.1.65 → 0.1.67

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.
@@ -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;
@@ -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,18 @@ 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
+ export interface ReplayPage {
76
+ mission: string;
77
+ /** The mission's abort anchors that were on the page at the start. */
78
+ anchors: string[];
79
+ /** An app dialog was open at the start. */
80
+ dialog: boolean;
66
81
  }
67
82
  /** What the machine may ask about the page. */
68
83
  export interface GuideEnv {
@@ -77,6 +92,8 @@ export interface GuideEnv {
77
92
  sidebarOpen: boolean;
78
93
  /** The current value of the step target's field. */
79
94
  targetValue: () => string;
95
+ /** An app dialog (not the tour's) is open. */
96
+ dialogOpen?: () => boolean;
80
97
  }
81
98
  export type GuideSignal = {
82
99
  kind: "api";
@@ -213,6 +230,16 @@ export declare function triggersOf(step: GuideStep): GuideTrigger[];
213
230
  export declare function stepKind(step: GuideStep): import("./types").GuideStepKind;
214
231
  /** The last checkpoint at or before `index` (a mission's first step always is one). */
215
232
  export declare function checkpointAtOrBefore(steps: GuideStep[], index: number): number;
233
+ /**
234
+ * A commit step with nothing to save: its button is not on the page, and what
235
+ * is saved is (GuideStep.nothingToSave).
236
+ */
237
+ export declare function nothingToSaveHolds(step: GuideStep, env: GuideEnv, ctx: GuideContext): boolean;
238
+ /**
239
+ * The step as it is shown: a commit step with nothing to save is a read step
240
+ * on what is saved, with its own title (ถัดไป moves on).
241
+ */
242
+ export declare function shownStep(step: GuideStep, nothingToSave: boolean): GuideStep;
216
243
  /** Whether the step's target (or the bridge's) is on screen. */
217
244
  export declare function stepTargetVisible(step: GuideStep, env: GuideEnv, ctx: GuideContext, bridge: boolean): boolean;
218
245
  /** The anchor the spotlight is on for the current step. */
@@ -228,6 +255,14 @@ export declare function spotlightTarget(step: GuideStep, ctx: GuideContext, brid
228
255
  export declare function stepHomeRoute(steps: GuideStep[], index: number): string | undefined;
229
256
  /** What puts the page back when a replay ends at this step (see GuideStep.abort). */
230
257
  export declare function abortActionsFor(mission: GuideMission, index: number): GuideAbortAction[];
258
+ /** Every anchor the mission's abort actions press. */
259
+ export declare function abortAnchorsOf(mission: GuideMission): string[];
260
+ /**
261
+ * What the replay may do to put the page back: not press what the user had
262
+ * open before it started, not Escape out of a dialog that was already open,
263
+ * and no app event while anything of theirs was open.
264
+ */
265
+ export declare function abortActionsLeft(actions: GuideAbortAction[], before: ReplayPage | null): GuideAbortAction[];
231
266
  /** Status of each mission as the panel shows it. */
232
267
  export type MissionView = "todo" | "next" | "active" | "skipped" | "done" | "already" | "locked" | "waiting";
233
268
  export declare function missionSettled(m: GuideMission, entry: MissionEntry | undefined, ctx: GuideContext): boolean;
@@ -180,6 +180,17 @@ export interface GuideStep {
180
180
  * or Escape to the open dialog. Overrides the mission's `abort`.
181
181
  */
182
182
  abort?: GuideAbortAction | GuideAbortAction[];
183
+ /**
184
+ * "commit" steps whose button only shows after a change (a save bar that
185
+ * appears once the form is edited). When `target` is not on the page but
186
+ * `nothingToSave.target` is (what is saved is on screen and nothing is
187
+ * changed), the step is a read step on that anchor, with ถัดไป, which moves
188
+ * on as if saved. The moment `target` shows (the user changed something)
189
+ * it is the commit step again. Name an anchor that only exists when the
190
+ * saved state is real, so a first run never passes without a save that
191
+ * was needed (shell ≥ 0.1.67).
192
+ */
193
+ nothingToSave?: GuideNothingToSave;
183
194
  /**
184
195
  * "commit" steps: what a refused save means. Return the key of the step to
185
196
  * go back to (a field) and/or the line to show. Default: stay, show the
@@ -190,10 +201,20 @@ export interface GuideStep {
190
201
  message?: string;
191
202
  } | void;
192
203
  }
204
+ /** A commit step's read form when there is nothing to save (GuideStep.nothingToSave). */
205
+ export interface GuideNothingToSave {
206
+ /** What is saved, on screen (the placed point's card, the saved list). */
207
+ target: GuideAnchorKey;
208
+ title: GuideText;
209
+ why?: GuideText;
210
+ /** Anchors the user may use meanwhile; a change there brings the save back. */
211
+ allow?: GuideAnchorKey[];
212
+ }
193
213
  /**
194
214
  * One thing the engine does to put the page back when a replay ends early.
195
215
  * Run in order, after the tour has let go of the page; an anchor that is not
196
- * on the page is passed over.
216
+ * on the page is passed over, and so is one that was already on the page
217
+ * when the replay started (the user's own open form: shell ≥ 0.1.67).
197
218
  */
198
219
  export type GuideAbortAction =
199
220
  /** Press this anchor (the form's ยกเลิก, a dialog's close). */
@@ -251,6 +272,9 @@ export interface GuideMission {
251
272
  * How to put the page back when a replay of this mission ends without
252
273
  * saving (a step's own `abort` wins). Default: Escape, and only from a step
253
274
  * that is not a checkpoint (inside the dialog or form the tour opened).
275
+ * Whatever was already open when the replay started is the user's and is
276
+ * left alone: an anchor on the page then is never pressed, and no Escape
277
+ * is sent when an app dialog was open (shell ≥ 0.1.67).
254
278
  */
255
279
  abort?: GuideAbortAction | GuideAbortAction[];
256
280
  steps: GuideStep[];
package/dist/index.d.ts CHANGED
@@ -33,7 +33,7 @@ export { HelpDialogHost, type HelpDialogHostProps } from "./help/help-dialog";
33
33
  export { openHelp, closeHelp, type HelpAppId } from "./help/help-store";
34
34
  export { describeBrowser, describeAttached, detectHelpApp, type HelpContext, } from "./help/help-context";
35
35
  export { SHELL_VERSION } from "./version";
36
- export type { GuideAbortAction, GuideAnchorKey, GuideApiFailure, GuideApiMatch, GuideAppId, GuideCaptureEvent, GuideConfig, GuideContext, GuideFacts, GuideGate, GuideMission, GuideOnMissing, GuideStep, GuideStepKind, GuideSuite, GuideText, GuideTrigger, } from "./guide/types";
36
+ export type { GuideAbortAction, GuideAnchorKey, GuideApiFailure, GuideApiMatch, GuideAppId, GuideCaptureEvent, GuideConfig, GuideContext, GuideFacts, GuideGate, GuideMission, GuideNothingToSave, GuideOnMissing, GuideStep, GuideStepKind, GuideSuite, GuideText, GuideTrigger, } from "./guide/types";
37
37
  export { API_EVENT as GUIDE_API_EVENT, GUIDE_EVENT_PREFIX, GUIDE_LAYER_ATTRIBUTE, emitGuideEvent, guideAnchor, reportApiEvent, type ApiEventDetail, type GuideAnchorProps, } from "./guide/events";
38
38
  export { openGuidePanel, useGuideEntry, type GuideEntry } from "./guide/guide-store";
39
39
  export { GuideHost, type GuideHostProps } from "./guide/guide-host";
package/dist/index.esm.js CHANGED
@@ -1956,7 +1956,7 @@ function platformApiBase(app) {
1956
1956
  * This package's version, attached to help messages so the back office can
1957
1957
  * tell which shell a report came from. Keep in step with package.json.
1958
1958
  */
1959
- const SHELL_VERSION = "0.1.65";
1959
+ const SHELL_VERSION = "0.1.67";
1960
1960
 
1961
1961
  const HELP_APP_LABEL = {
1962
1962
  platform: "แพลตฟอร์ม",
@@ -3813,6 +3813,7 @@ function initialGuideState(audience, progress) {
3813
3813
  chipPulse: 0,
3814
3814
  nudge: 0,
3815
3815
  gateDismissed: false,
3816
+ replayPage: null,
3816
3817
  };
3817
3818
  }
3818
3819
  function findMission(suite, key) {
@@ -3870,6 +3871,38 @@ function targetIdOf(step, ctx) {
3870
3871
  return safe(() => step.targetId(ctx), undefined);
3871
3872
  return step.targetId;
3872
3873
  }
3874
+ /**
3875
+ * A commit step with nothing to save: its button is not on the page, and what
3876
+ * is saved is (GuideStep.nothingToSave).
3877
+ */
3878
+ function nothingToSaveHolds(step, env, ctx) {
3879
+ const n = step.nothingToSave;
3880
+ if (!n || !step.target)
3881
+ return false;
3882
+ return !env.isVisible(step.target, targetIdOf(step, ctx)) && env.isVisible(n.target);
3883
+ }
3884
+ /**
3885
+ * The step as it is shown: a commit step with nothing to save is a read step
3886
+ * on what is saved, with its own title (ถัดไป moves on).
3887
+ */
3888
+ function shownStep(step, nothingToSave) {
3889
+ const n = step.nothingToSave;
3890
+ if (!nothingToSave || !n)
3891
+ return step;
3892
+ return {
3893
+ key: step.key,
3894
+ kind: "view",
3895
+ target: n.target,
3896
+ title: n.title,
3897
+ why: n.why,
3898
+ allow: n.allow,
3899
+ route: step.route,
3900
+ resumeUrl: step.resumeUrl,
3901
+ checkpoint: step.checkpoint,
3902
+ timeoutMs: step.timeoutMs,
3903
+ abort: step.abort,
3904
+ };
3905
+ }
3873
3906
  /** Whether the step's target (or the bridge's) is on screen. */
3874
3907
  function stepTargetVisible(step, env, ctx, bridge) {
3875
3908
  if (bridge)
@@ -3938,6 +3971,30 @@ function abortActionsFor(mission, index) {
3938
3971
  return [];
3939
3972
  return [{ escape: true }];
3940
3973
  }
3974
+ /** Every anchor the mission's abort actions press. */
3975
+ function abortAnchorsOf(mission) {
3976
+ const out = new Set();
3977
+ const add = (a) => {
3978
+ for (const x of a ? (Array.isArray(a) ? a : [a]) : [])
3979
+ if ("click" in x)
3980
+ out.add(x.click);
3981
+ };
3982
+ add(mission.abort);
3983
+ for (const st of mission.steps)
3984
+ add(st.abort);
3985
+ return Array.from(out);
3986
+ }
3987
+ /**
3988
+ * What the replay may do to put the page back: not press what the user had
3989
+ * open before it started, not Escape out of a dialog that was already open,
3990
+ * and no app event while anything of theirs was open.
3991
+ */
3992
+ function abortActionsLeft(actions, before) {
3993
+ if (!before)
3994
+ return actions;
3995
+ const busy = before.anchors.length > 0 || before.dialog;
3996
+ return actions.filter(a => "click" in a ? !before.anchors.includes(a.click) : "escape" in a ? !before.dialog : !busy);
3997
+ }
3941
3998
  function routeParamsFor(step, env) {
3942
3999
  if (!step.route)
3943
4000
  return {};
@@ -4076,7 +4133,7 @@ function announceStep(d, suite, env) {
4076
4133
  const mission = findMission(suite, s.mission);
4077
4134
  if (!mission)
4078
4135
  return;
4079
- const step = mission.steps[s.index];
4136
+ const step = shownStep(mission.steps[s.index], s.nothingToSave);
4080
4137
  const ctx = guideContext(env, d.state.progress.context, routeParamsFor(step, env));
4081
4138
  const title = s.bridge ? COPY.bridgeTitle : plainTitle(resolveText(step.title, ctx));
4082
4139
  const why = s.bridge ? COPY.bridgeWhy(suite.appName) : plainTitle(resolveText(step.why, ctx));
@@ -4144,6 +4201,7 @@ function enterStep(d, suite, env, mission, index, opts) {
4144
4201
  confirmExit: false,
4145
4202
  misses: 0,
4146
4203
  armed: hiddenAnchorShown(step, env),
4204
+ nothingToSave: !away && !bridge && nothingToSaveHolds(step, env, ctx),
4147
4205
  });
4148
4206
  if (!opts.replay) {
4149
4207
  const cp = checkpointAtOrBefore(steps, i);
@@ -4161,6 +4219,28 @@ function enterStep(d, suite, env, mission, index, opts) {
4161
4219
  markReadyIfVisible(d, suite, env);
4162
4220
  }
4163
4221
  }
4222
+ /**
4223
+ * The save button came (a change) or went (nothing left to save): show the
4224
+ * commit step's other form. A ready step whose new target is not there is
4225
+ * left to the target-lost path (back to the checkpoint).
4226
+ */
4227
+ function setNothingToSave(d, suite, env, on) {
4228
+ const s = d.state.screen;
4229
+ if (s.name !== "step" || s.nothingToSave === on)
4230
+ return;
4231
+ setScreen(d, { ...s, nothingToSave: on, error: null });
4232
+ if (s.phase !== "ready") {
4233
+ markReadyIfVisible(d, suite, env);
4234
+ return;
4235
+ }
4236
+ const mission = findMission(suite, s.mission);
4237
+ if (!mission)
4238
+ return;
4239
+ const step = shownStep(mission.steps[s.index], on);
4240
+ const ctx = guideContext(env, d.state.progress.context, routeParamsFor(step, env));
4241
+ if (stepTargetVisible(step, env, ctx, s.bridge))
4242
+ announceStep(d, suite, env);
4243
+ }
4164
4244
  function markReadyIfVisible(d, suite, env) {
4165
4245
  const s = d.state.screen;
4166
4246
  if (s.name !== "step" || s.phase !== "waiting")
@@ -4168,7 +4248,7 @@ function markReadyIfVisible(d, suite, env) {
4168
4248
  const mission = findMission(suite, s.mission);
4169
4249
  if (!mission)
4170
4250
  return;
4171
- const step = mission.steps[s.index];
4251
+ const step = shownStep(mission.steps[s.index], s.nothingToSave);
4172
4252
  const ctx = guideContext(env, d.state.progress.context, routeParamsFor(step, env));
4173
4253
  if (stepTargetVisible(step, env, ctx, s.bridge)) {
4174
4254
  setScreen(d, { ...s, phase: "ready" });
@@ -4290,6 +4370,17 @@ function startMission(d, suite, env, key, replay) {
4290
4370
  if (at > 0)
4291
4371
  index = checkpointAtOrBefore(mission.steps, at);
4292
4372
  }
4373
+ if (isReplay) {
4374
+ // What is open now is the user's: ending the replay leaves it alone.
4375
+ d.state = {
4376
+ ...d.state,
4377
+ replayPage: {
4378
+ mission: key,
4379
+ anchors: abortAnchorsOf(mission).filter(a => safe(() => env.isVisible(a), false)),
4380
+ dialog: safe(() => env.dialogOpen?.() === true, false),
4381
+ },
4382
+ };
4383
+ }
4293
4384
  enterStep(d, suite, env, mission, index, { replay: isReplay });
4294
4385
  // A replay never writes progress; only what starting it changed (the
4295
4386
  // welcome, first seen through a replay) is saved.
@@ -4350,7 +4441,8 @@ function pushAbort(d, suite, s) {
4350
4441
  const mission = findMission(suite, s.mission);
4351
4442
  if (!mission)
4352
4443
  return;
4353
- const actions = abortActionsFor(mission, s.index);
4444
+ const before = d.state.replayPage?.mission === s.mission ? d.state.replayPage : null;
4445
+ const actions = abortActionsLeft(abortActionsFor(mission, s.index), before);
4354
4446
  if (actions.length)
4355
4447
  d.effects.push({ type: "abort", actions });
4356
4448
  }
@@ -4443,7 +4535,12 @@ function reduceGuide(state, action, suite, env) {
4443
4535
  }
4444
4536
  if (s.confirmExit)
4445
4537
  break;
4446
- const kind = stepKind(step);
4538
+ const nts = !s.bridge && nothingToSaveHolds(step, env, ctx);
4539
+ if (nts !== s.nothingToSave) {
4540
+ setNothingToSave(d, suite, env, nts);
4541
+ break;
4542
+ }
4543
+ const kind = stepKind(shownStep(step, s.nothingToSave));
4447
4544
  const armed = s.armed || hiddenAnchorShown(step, env);
4448
4545
  if (kind !== "input" && kind !== "view") {
4449
4546
  const held = syncTriggerHolds(step, env, armed);
@@ -4452,7 +4549,7 @@ function reduceGuide(state, action, suite, env) {
4452
4549
  break;
4453
4550
  }
4454
4551
  }
4455
- if (!s.bridge && !stepTargetVisible(step, env, ctx, false) && offRoute(mission.steps, s.index, env)) {
4552
+ if (!s.bridge && !stepTargetVisible(shownStep(step, s.nothingToSave), env, ctx, false) && offRoute(mission.steps, s.index, env)) {
4456
4553
  // The target is missing because the page is another one.
4457
4554
  recoverOffRoute(d, suite, env, false);
4458
4555
  break;
@@ -4523,8 +4620,9 @@ function reduceGuide(state, action, suite, env) {
4523
4620
  if (!mission)
4524
4621
  break;
4525
4622
  const step = mission.steps[s.index];
4526
- const kind = stepKind(step);
4623
+ const kind = stepKind(shownStep(step, s.nothingToSave));
4527
4624
  if (kind === "view") {
4625
+ // A read step, or a commit step with nothing to save.
4528
4626
  advance(d, suite, env);
4529
4627
  break;
4530
4628
  }
@@ -4553,21 +4651,24 @@ function reduceGuide(state, action, suite, env) {
4553
4651
  const mission = findMission(suite, s.mission);
4554
4652
  if (!mission)
4555
4653
  break;
4556
- const step = mission.steps[s.index];
4557
- const ctx = guideContext(env, d.state.progress.context, routeParamsFor(step, env));
4558
- if (stepTargetVisible(step, env, ctx, s.bridge))
4654
+ const raw = mission.steps[s.index];
4655
+ const ctx = guideContext(env, d.state.progress.context, routeParamsFor(raw, env));
4656
+ // The save went with nothing left to save, or came back: the other form.
4657
+ setNothingToSave(d, suite, env, !s.bridge && nothingToSaveHolds(raw, env, ctx));
4658
+ const cur = d.state.screen;
4659
+ if (stepTargetVisible(shownStep(raw, cur.nothingToSave), env, ctx, cur.bridge))
4559
4660
  break;
4560
- if (!s.bridge && offRoute(mission.steps, s.index, env)) {
4661
+ if (!cur.bridge && offRoute(mission.steps, cur.index, env)) {
4561
4662
  recoverOffRoute(d, suite, env, false);
4562
4663
  break;
4563
4664
  }
4564
- const cp = checkpointAtOrBefore(mission.steps, s.index);
4565
- if (cp < s.index && !s.bridge) {
4665
+ const cp = checkpointAtOrBefore(mission.steps, cur.index);
4666
+ if (cp < cur.index && !cur.bridge) {
4566
4667
  // A dialog or a menu closed under the step: back to what opens it.
4567
- enterStep(d, suite, env, mission, cp, { replay: s.replay, noAutoPass: false });
4668
+ enterStep(d, suite, env, mission, cp, { replay: cur.replay, noAutoPass: false });
4568
4669
  }
4569
4670
  else {
4570
- setScreen(d, { ...s, phase: "waiting" });
4671
+ setScreen(d, { ...cur, phase: "waiting" });
4571
4672
  }
4572
4673
  break;
4573
4674
  }
@@ -5159,6 +5260,12 @@ function coveredByDialog(el) {
5159
5260
  }
5160
5261
  return false;
5161
5262
  }
5263
+ /** An app dialog (not the tour's) is open on the page. */
5264
+ function appDialogOpen() {
5265
+ if (!hasDocument())
5266
+ return false;
5267
+ return Array.from(document.querySelectorAll(OPEN_DIALOG_SELECTOR)).some(d => !inGuideLayer(d) && isPresent(d));
5268
+ }
5162
5269
  function openPoppers() {
5163
5270
  if (!hasDocument())
5164
5271
  return [];
@@ -6197,6 +6304,7 @@ function GuideHostInner({ config, organizationId, code }) {
6197
6304
  isVisible: (anchor, id) => anchorVisible(anchor, id),
6198
6305
  sidebarOpen: pg.sidebarOpen,
6199
6306
  targetValue: () => fieldValue(targetElRef.current),
6307
+ dialogOpen: () => appDialogOpen(),
6200
6308
  };
6201
6309
  }, [code]);
6202
6310
  /* ---------------- effects: save, announce, toast, navigate ---------------- */
@@ -6373,11 +6481,13 @@ function GuideHostInner({ config, organizationId, code }) {
6373
6481
  const mission = findMission(suite, screen.mission);
6374
6482
  if (!mission)
6375
6483
  return null;
6376
- const step = mission.steps[screen.index];
6377
- if (!step)
6484
+ const raw = mission.steps[screen.index];
6485
+ if (!raw)
6378
6486
  return null;
6487
+ // A commit step with nothing to save is shown as its read form.
6488
+ const step = shownStep(raw, screen.nothingToSave);
6379
6489
  const missionNo = suite.missions.indexOf(mission) + 1;
6380
- return { mission, step, missionNo };
6490
+ return { mission, step, raw, missionNo };
6381
6491
  }, [state, screen, suite]);
6382
6492
  const stepCtx = useMemo(() => {
6383
6493
  if (!state)
@@ -6393,7 +6503,7 @@ function GuideHostInner({ config, organizationId, code }) {
6393
6503
  : null;
6394
6504
  const targetKey = target ? `${target.anchor}|${target.id ?? ""}` : "";
6395
6505
  const phase = screen.name === "step" ? screen.phase : null;
6396
- const stepId = screen.name === "step" ? `${screen.mission}:${screen.index}:${screen.bridge ? "b" : ""}` : "";
6506
+ const stepId = screen.name === "step" ? `${screen.mission}:${screen.index}:${screen.bridge ? "b" : ""}${screen.nothingToSave ? "n" : ""}` : "";
6397
6507
  /* Measure every frame while a step is shown: the spotlight follows
6398
6508
  scrolling, dialogs animating in, the drawer sliding, the keyboard. */
6399
6509
  const [layout, setLayout] = useState({
@@ -6556,7 +6666,7 @@ function GuideHostInner({ config, organizationId, code }) {
6556
6666
  dispatchRef.current({ type: "signal", signal: { kind: "api", method: d.method, path: d.path, status: d.status, id: d.id, message: d.message } });
6557
6667
  };
6558
6668
  window.addEventListener(API_EVENT, onApi);
6559
- const names = triggersOf(stepInfo.step).flatMap(t => ("event" in t ? [t.event] : []));
6669
+ const names = triggersOf(stepInfo.raw).flatMap(t => ("event" in t ? [t.event] : []));
6560
6670
  const onApp = (name) => (e) => dispatchRef.current({ type: "signal", signal: { kind: "event", name, detail: e.detail ?? undefined } });
6561
6671
  const appHandlers = names.map(n => [GUIDE_EVENT_PREFIX + n, onApp(n)]);
6562
6672
  appHandlers.forEach(([n, h]) => window.addEventListener(n, h));
@@ -6788,21 +6898,18 @@ function GuideHostInner({ config, organizationId, code }) {
6788
6898
  useEffect(() => {
6789
6899
  const el = document.createElement("div");
6790
6900
  el.setAttribute(GUIDE_LAYER_ATTRIBUTE, "");
6791
- // A Radix modal (dialog, select, menu) hides everything outside it from
6792
- // screen readers with aria-hidden's hideOthers. It leaves [aria-live]
6793
- // elements and their insides alone, but walks into their ancestors and
6794
- // hides the siblings: with only the status line live, the bubble and its
6795
- // buttons were hidden. "off" announces nothing; it only makes the whole
6796
- // layer one of the kept elements.
6797
- el.setAttribute("aria-live", "off");
6798
6901
  document.body.appendChild(el);
6799
6902
  layerRef.current = el;
6800
6903
  setLayer(el);
6801
- // And should anything still hide the layer or a part of it (another
6802
- // library, a later hideOthers), take it off again. hideOthers marks what
6803
- // it hides with data-aria-hidden (the layer never sets that, or inert);
6804
- // aria-hidden goes only where it was just added, so the layer's own
6805
- // decorative aria-hidden stays.
6904
+ // A Radix modal (dialog, select, menu) hides everything outside it from
6905
+ // screen readers with aria-hidden's hideOthers. It keeps [aria-live]
6906
+ // elements but walks into their ancestors and hides the other children:
6907
+ // with the status line live, the bubble and its buttons were hidden.
6908
+ // Take off what it adds, at once. hideOthers marks what it hides with
6909
+ // data-aria-hidden (the layer never sets that, or inert); aria-hidden goes
6910
+ // only where it was just added, so the layer's own decorative aria-hidden
6911
+ // stays. (aria-live="off" on the layer would make hideOthers skip it, but
6912
+ // it changed what test tools match by text.)
6806
6913
  const obs = new MutationObserver(records => {
6807
6914
  for (const r of records) {
6808
6915
  const n = r.target;