opensteer 0.6.9 → 0.6.11

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.
@@ -324,7 +324,7 @@ function normalizeNonEmptyString(value) {
324
324
  // src/config.ts
325
325
  var DEFAULT_CONFIG = {
326
326
  browser: {
327
- headless: false,
327
+ headless: void 0,
328
328
  executablePath: void 0,
329
329
  slowMo: 0,
330
330
  mode: void 0,
@@ -14,7 +14,7 @@ import {
14
14
  resolveNamespaceDir,
15
15
  selectCloudCredential,
16
16
  withTokenQuery
17
- } from "./chunk-GTT3A3RU.js";
17
+ } from "./chunk-2ES46WCO.js";
18
18
  import {
19
19
  detectChromePaths,
20
20
  expandHome,
@@ -3077,6 +3077,58 @@ async function serializeFrameRecursive(frame, baseContext, frameKey) {
3077
3077
  };
3078
3078
  }
3079
3079
 
3080
+ // src/html/interactive-patterns.ts
3081
+ var NATIVE_INTERACTIVE_TAGS = /* @__PURE__ */ new Set([
3082
+ "a",
3083
+ "button",
3084
+ "input",
3085
+ "select",
3086
+ "textarea"
3087
+ ]);
3088
+ var INTERACTIVE_SELECTOR_PARTS = [
3089
+ "a[href]",
3090
+ "button",
3091
+ "input",
3092
+ "textarea",
3093
+ "select",
3094
+ '[role="button"]',
3095
+ '[role="link"]',
3096
+ '[role="menuitem"]',
3097
+ '[role="option"]',
3098
+ '[role="radio"]',
3099
+ '[role="checkbox"]',
3100
+ '[role="tab"]',
3101
+ '[contenteditable="true"]',
3102
+ "[onclick]",
3103
+ "[onmousedown]",
3104
+ "[onmouseup]"
3105
+ ];
3106
+ var INTERACTIVE_SELECTOR = INTERACTIVE_SELECTOR_PARTS.join(",");
3107
+ var INTERACTIVE_ROLE_TOKENS = [
3108
+ "button",
3109
+ "link",
3110
+ "menuitem",
3111
+ "option",
3112
+ "radio",
3113
+ "checkbox",
3114
+ "tab",
3115
+ "textbox",
3116
+ "combobox",
3117
+ "slider",
3118
+ "spinbutton",
3119
+ "search",
3120
+ "searchbox"
3121
+ ];
3122
+ var INTERACTIVE_ROLE_SET = new Set(
3123
+ INTERACTIVE_ROLE_TOKENS
3124
+ );
3125
+ var NON_NEGATIVE_TAB_INDEX_MIN = 0;
3126
+ function hasNonNegativeTabIndex(value) {
3127
+ if (value == null) return false;
3128
+ const parsed = Number.parseInt(value, 10);
3129
+ return Number.isFinite(parsed) && parsed >= NON_NEGATIVE_TAB_INDEX_MIN;
3130
+ }
3131
+
3080
3132
  // src/html/interactivity.ts
3081
3133
  var OPENSTEER_INTERACTIVE_ATTR = "data-opensteer-interactive";
3082
3134
  var OPENSTEER_HIDDEN_ATTR = "data-opensteer-hidden";
@@ -3091,42 +3143,12 @@ async function markInteractiveElements(page, {
3091
3143
  markAttribute: markAttribute2,
3092
3144
  skipIfAlreadyMarked: skipIfAlreadyMarked2,
3093
3145
  hiddenAttr,
3094
- scrollableAttr
3146
+ scrollableAttr,
3147
+ interactiveSelector,
3148
+ interactiveRoles,
3149
+ nonNegativeTabIndexMin
3095
3150
  }) => {
3096
- const interactiveSelector = [
3097
- "a[href]",
3098
- "button",
3099
- "input",
3100
- "textarea",
3101
- "select",
3102
- '[role="button"]',
3103
- '[role="link"]',
3104
- '[role="menuitem"]',
3105
- '[role="option"]',
3106
- '[role="radio"]',
3107
- '[role="checkbox"]',
3108
- '[role="tab"]',
3109
- '[contenteditable="true"]',
3110
- "[onclick]",
3111
- "[onmousedown]",
3112
- "[onmouseup]",
3113
- "[tabindex]"
3114
- ].join(",");
3115
- const interactiveRoles = /* @__PURE__ */ new Set([
3116
- "button",
3117
- "link",
3118
- "menuitem",
3119
- "option",
3120
- "radio",
3121
- "checkbox",
3122
- "tab",
3123
- "textbox",
3124
- "combobox",
3125
- "slider",
3126
- "spinbutton",
3127
- "search",
3128
- "searchbox"
3129
- ]);
3151
+ const interactiveRolesSet = new Set(interactiveRoles);
3130
3152
  function isExplicitlyHidden(el, style) {
3131
3153
  if (el.hasAttribute("hidden")) {
3132
3154
  return true;
@@ -3168,6 +3190,12 @@ async function markInteractiveElements(page, {
3168
3190
  }
3169
3191
  return !hasVisibleOutOfFlowChild(el);
3170
3192
  }
3193
+ function hasInteractiveTabIndex(el) {
3194
+ const value = el.getAttribute("tabindex");
3195
+ if (value == null) return false;
3196
+ const parsed = Number.parseInt(value, 10);
3197
+ return Number.isFinite(parsed) && parsed >= nonNegativeTabIndexMin;
3198
+ }
3171
3199
  const roots = [document];
3172
3200
  while (roots.length) {
3173
3201
  const root = roots.pop();
@@ -3193,11 +3221,13 @@ async function markInteractiveElements(page, {
3193
3221
  let interactive = false;
3194
3222
  if (el.matches(interactiveSelector)) {
3195
3223
  interactive = true;
3224
+ } else if (hasInteractiveTabIndex(el)) {
3225
+ interactive = true;
3196
3226
  } else if (style.cursor === "pointer") {
3197
3227
  interactive = true;
3198
3228
  } else {
3199
3229
  const role = (el.getAttribute("role") || "").toLowerCase();
3200
- if (interactiveRoles.has(role)) {
3230
+ if (interactiveRolesSet.has(role)) {
3201
3231
  interactive = true;
3202
3232
  }
3203
3233
  }
@@ -3242,7 +3272,10 @@ async function markInteractiveElements(page, {
3242
3272
  markAttribute,
3243
3273
  skipIfAlreadyMarked,
3244
3274
  hiddenAttr: OPENSTEER_HIDDEN_ATTR,
3245
- scrollableAttr: OPENSTEER_SCROLLABLE_ATTR
3275
+ scrollableAttr: OPENSTEER_SCROLLABLE_ATTR,
3276
+ interactiveSelector: INTERACTIVE_SELECTOR,
3277
+ interactiveRoles: INTERACTIVE_ROLE_TOKENS,
3278
+ nonNegativeTabIndexMin: NON_NEGATIVE_TAB_INDEX_MIN
3246
3279
  }
3247
3280
  );
3248
3281
  };
@@ -3329,7 +3362,7 @@ function isClickable($, el, context) {
3329
3362
  }
3330
3363
  const tag = (el[0]?.tagName || "").toLowerCase();
3331
3364
  if (!tag || ROOT_TAGS.has(tag)) return false;
3332
- if ((/* @__PURE__ */ new Set(["a", "button", "input", "select", "textarea"])).has(tag)) {
3365
+ if (NATIVE_INTERACTIVE_TAGS.has(tag)) {
3333
3366
  if (tag === "input") {
3334
3367
  const inputType = String(el.attr("type") || "").toLowerCase();
3335
3368
  if (inputType === "hidden") return false;
@@ -3343,26 +3376,11 @@ function isClickable($, el, context) {
3343
3376
  if (attrs["data-action"] !== void 0) return true;
3344
3377
  if (attrs["data-click"] !== void 0) return true;
3345
3378
  if (attrs["data-toggle"] !== void 0) return true;
3346
- if (attrs.tabindex !== void 0) {
3347
- const tabIndex = Number.parseInt(String(attrs.tabindex), 10);
3348
- if (!Number.isNaN(tabIndex) && tabIndex >= 0) return true;
3379
+ if (hasNonNegativeTabIndex(attrs.tabindex)) {
3380
+ return true;
3349
3381
  }
3350
3382
  const role = String(attrs.role || "").toLowerCase();
3351
- if ([
3352
- "button",
3353
- "link",
3354
- "menuitem",
3355
- "option",
3356
- "radio",
3357
- "checkbox",
3358
- "tab",
3359
- "textbox",
3360
- "combobox",
3361
- "slider",
3362
- "spinbutton",
3363
- "search",
3364
- "searchbox"
3365
- ].includes(role)) {
3383
+ if (INTERACTIVE_ROLE_SET.has(role)) {
3366
3384
  return true;
3367
3385
  }
3368
3386
  const className = String(attrs.class || "").toLowerCase();
@@ -5,7 +5,7 @@ import {
5
5
  resolveConfigWithEnv,
6
6
  selectCloudCredential,
7
7
  stripTrailingSlashes
8
- } from "./chunk-GTT3A3RU.js";
8
+ } from "./chunk-2ES46WCO.js";
9
9
 
10
10
  // src/cli/auth.ts
11
11
  import open from "open";
@@ -2,7 +2,7 @@ import {
2
2
  cloudAuthHeaders,
3
3
  normalizeCloudBaseUrl,
4
4
  parseCloudHttpError
5
- } from "./chunk-GTT3A3RU.js";
5
+ } from "./chunk-2ES46WCO.js";
6
6
 
7
7
  // src/cloud/browser-profile-client.ts
8
8
  var BrowserProfileClient = class {
package/dist/cli/auth.cjs CHANGED
@@ -238,7 +238,7 @@ function normalizeNonEmptyString(value) {
238
238
  // src/config.ts
239
239
  var DEFAULT_CONFIG = {
240
240
  browser: {
241
- headless: false,
241
+ headless: void 0,
242
242
  executablePath: void 0,
243
243
  slowMo: 0,
244
244
  mode: void 0,
package/dist/cli/auth.js CHANGED
@@ -4,8 +4,8 @@ import {
4
4
  isCloudModeEnabledForRootDir,
5
5
  parseOpensteerAuthArgs,
6
6
  runOpensteerAuthCli
7
- } from "../chunk-K7DQUSZG.js";
8
- import "../chunk-GTT3A3RU.js";
7
+ } from "../chunk-U724TBY6.js";
8
+ import "../chunk-2ES46WCO.js";
9
9
  export {
10
10
  ensureCloudCredentialsForCommand,
11
11
  ensureCloudCredentialsForOpenCommand,
@@ -753,7 +753,7 @@ function sanitizeNamespaceSegment(segment) {
753
753
  // src/config.ts
754
754
  var DEFAULT_CONFIG = {
755
755
  browser: {
756
- headless: false,
756
+ headless: void 0,
757
757
  executablePath: void 0,
758
758
  slowMo: 0,
759
759
  mode: void 0,
@@ -4446,6 +4446,58 @@ async function serializeFrameRecursive(frame, baseContext, frameKey) {
4446
4446
  };
4447
4447
  }
4448
4448
 
4449
+ // src/html/interactive-patterns.ts
4450
+ var NATIVE_INTERACTIVE_TAGS = /* @__PURE__ */ new Set([
4451
+ "a",
4452
+ "button",
4453
+ "input",
4454
+ "select",
4455
+ "textarea"
4456
+ ]);
4457
+ var INTERACTIVE_SELECTOR_PARTS = [
4458
+ "a[href]",
4459
+ "button",
4460
+ "input",
4461
+ "textarea",
4462
+ "select",
4463
+ '[role="button"]',
4464
+ '[role="link"]',
4465
+ '[role="menuitem"]',
4466
+ '[role="option"]',
4467
+ '[role="radio"]',
4468
+ '[role="checkbox"]',
4469
+ '[role="tab"]',
4470
+ '[contenteditable="true"]',
4471
+ "[onclick]",
4472
+ "[onmousedown]",
4473
+ "[onmouseup]"
4474
+ ];
4475
+ var INTERACTIVE_SELECTOR = INTERACTIVE_SELECTOR_PARTS.join(",");
4476
+ var INTERACTIVE_ROLE_TOKENS = [
4477
+ "button",
4478
+ "link",
4479
+ "menuitem",
4480
+ "option",
4481
+ "radio",
4482
+ "checkbox",
4483
+ "tab",
4484
+ "textbox",
4485
+ "combobox",
4486
+ "slider",
4487
+ "spinbutton",
4488
+ "search",
4489
+ "searchbox"
4490
+ ];
4491
+ var INTERACTIVE_ROLE_SET = new Set(
4492
+ INTERACTIVE_ROLE_TOKENS
4493
+ );
4494
+ var NON_NEGATIVE_TAB_INDEX_MIN = 0;
4495
+ function hasNonNegativeTabIndex(value) {
4496
+ if (value == null) return false;
4497
+ const parsed = Number.parseInt(value, 10);
4498
+ return Number.isFinite(parsed) && parsed >= NON_NEGATIVE_TAB_INDEX_MIN;
4499
+ }
4500
+
4449
4501
  // src/html/interactivity.ts
4450
4502
  var OPENSTEER_INTERACTIVE_ATTR = "data-opensteer-interactive";
4451
4503
  var OPENSTEER_HIDDEN_ATTR = "data-opensteer-hidden";
@@ -4460,42 +4512,12 @@ async function markInteractiveElements(page, {
4460
4512
  markAttribute: markAttribute2,
4461
4513
  skipIfAlreadyMarked: skipIfAlreadyMarked2,
4462
4514
  hiddenAttr,
4463
- scrollableAttr
4515
+ scrollableAttr,
4516
+ interactiveSelector,
4517
+ interactiveRoles,
4518
+ nonNegativeTabIndexMin
4464
4519
  }) => {
4465
- const interactiveSelector = [
4466
- "a[href]",
4467
- "button",
4468
- "input",
4469
- "textarea",
4470
- "select",
4471
- '[role="button"]',
4472
- '[role="link"]',
4473
- '[role="menuitem"]',
4474
- '[role="option"]',
4475
- '[role="radio"]',
4476
- '[role="checkbox"]',
4477
- '[role="tab"]',
4478
- '[contenteditable="true"]',
4479
- "[onclick]",
4480
- "[onmousedown]",
4481
- "[onmouseup]",
4482
- "[tabindex]"
4483
- ].join(",");
4484
- const interactiveRoles = /* @__PURE__ */ new Set([
4485
- "button",
4486
- "link",
4487
- "menuitem",
4488
- "option",
4489
- "radio",
4490
- "checkbox",
4491
- "tab",
4492
- "textbox",
4493
- "combobox",
4494
- "slider",
4495
- "spinbutton",
4496
- "search",
4497
- "searchbox"
4498
- ]);
4520
+ const interactiveRolesSet = new Set(interactiveRoles);
4499
4521
  function isExplicitlyHidden(el, style) {
4500
4522
  if (el.hasAttribute("hidden")) {
4501
4523
  return true;
@@ -4537,6 +4559,12 @@ async function markInteractiveElements(page, {
4537
4559
  }
4538
4560
  return !hasVisibleOutOfFlowChild(el);
4539
4561
  }
4562
+ function hasInteractiveTabIndex(el) {
4563
+ const value = el.getAttribute("tabindex");
4564
+ if (value == null) return false;
4565
+ const parsed = Number.parseInt(value, 10);
4566
+ return Number.isFinite(parsed) && parsed >= nonNegativeTabIndexMin;
4567
+ }
4540
4568
  const roots = [document];
4541
4569
  while (roots.length) {
4542
4570
  const root = roots.pop();
@@ -4562,11 +4590,13 @@ async function markInteractiveElements(page, {
4562
4590
  let interactive = false;
4563
4591
  if (el.matches(interactiveSelector)) {
4564
4592
  interactive = true;
4593
+ } else if (hasInteractiveTabIndex(el)) {
4594
+ interactive = true;
4565
4595
  } else if (style.cursor === "pointer") {
4566
4596
  interactive = true;
4567
4597
  } else {
4568
4598
  const role = (el.getAttribute("role") || "").toLowerCase();
4569
- if (interactiveRoles.has(role)) {
4599
+ if (interactiveRolesSet.has(role)) {
4570
4600
  interactive = true;
4571
4601
  }
4572
4602
  }
@@ -4611,7 +4641,10 @@ async function markInteractiveElements(page, {
4611
4641
  markAttribute,
4612
4642
  skipIfAlreadyMarked,
4613
4643
  hiddenAttr: OPENSTEER_HIDDEN_ATTR,
4614
- scrollableAttr: OPENSTEER_SCROLLABLE_ATTR
4644
+ scrollableAttr: OPENSTEER_SCROLLABLE_ATTR,
4645
+ interactiveSelector: INTERACTIVE_SELECTOR,
4646
+ interactiveRoles: INTERACTIVE_ROLE_TOKENS,
4647
+ nonNegativeTabIndexMin: NON_NEGATIVE_TAB_INDEX_MIN
4615
4648
  }
4616
4649
  );
4617
4650
  };
@@ -4698,7 +4731,7 @@ function isClickable($, el, context) {
4698
4731
  }
4699
4732
  const tag = (el[0]?.tagName || "").toLowerCase();
4700
4733
  if (!tag || ROOT_TAGS.has(tag)) return false;
4701
- if ((/* @__PURE__ */ new Set(["a", "button", "input", "select", "textarea"])).has(tag)) {
4734
+ if (NATIVE_INTERACTIVE_TAGS.has(tag)) {
4702
4735
  if (tag === "input") {
4703
4736
  const inputType = String(el.attr("type") || "").toLowerCase();
4704
4737
  if (inputType === "hidden") return false;
@@ -4712,26 +4745,11 @@ function isClickable($, el, context) {
4712
4745
  if (attrs["data-action"] !== void 0) return true;
4713
4746
  if (attrs["data-click"] !== void 0) return true;
4714
4747
  if (attrs["data-toggle"] !== void 0) return true;
4715
- if (attrs.tabindex !== void 0) {
4716
- const tabIndex = Number.parseInt(String(attrs.tabindex), 10);
4717
- if (!Number.isNaN(tabIndex) && tabIndex >= 0) return true;
4748
+ if (hasNonNegativeTabIndex(attrs.tabindex)) {
4749
+ return true;
4718
4750
  }
4719
4751
  const role = String(attrs.role || "").toLowerCase();
4720
- if ([
4721
- "button",
4722
- "link",
4723
- "menuitem",
4724
- "option",
4725
- "radio",
4726
- "checkbox",
4727
- "tab",
4728
- "textbox",
4729
- "combobox",
4730
- "slider",
4731
- "spinbutton",
4732
- "search",
4733
- "searchbox"
4734
- ].includes(role)) {
4752
+ if (INTERACTIVE_ROLE_SET.has(role)) {
4735
4753
  return true;
4736
4754
  }
4737
4755
  const className = String(attrs.class || "").toLowerCase();
@@ -1,16 +1,16 @@
1
1
  import {
2
2
  BrowserProfileClient
3
- } from "../chunk-A6LF44E3.js";
3
+ } from "../chunk-ZRCFF546.js";
4
4
  import {
5
5
  createKeychainStore,
6
6
  ensureCloudCredentialsForCommand
7
- } from "../chunk-K7DQUSZG.js";
7
+ } from "../chunk-U724TBY6.js";
8
8
  import {
9
9
  Opensteer
10
- } from "../chunk-I66RNYIW.js";
10
+ } from "../chunk-JZF2WC7U.js";
11
11
  import {
12
12
  resolveConfigWithEnv
13
- } from "../chunk-GTT3A3RU.js";
13
+ } from "../chunk-2ES46WCO.js";
14
14
  import {
15
15
  expandHome
16
16
  } from "../chunk-K5CL76MG.js";
@@ -1881,7 +1881,7 @@ function sanitizeNamespaceSegment(segment) {
1881
1881
  // src/config.ts
1882
1882
  var DEFAULT_CONFIG = {
1883
1883
  browser: {
1884
- headless: false,
1884
+ headless: void 0,
1885
1885
  executablePath: void 0,
1886
1886
  slowMo: 0,
1887
1887
  mode: void 0,
@@ -4439,6 +4439,58 @@ async function serializeFrameRecursive(frame, baseContext, frameKey) {
4439
4439
  };
4440
4440
  }
4441
4441
 
4442
+ // src/html/interactive-patterns.ts
4443
+ var NATIVE_INTERACTIVE_TAGS = /* @__PURE__ */ new Set([
4444
+ "a",
4445
+ "button",
4446
+ "input",
4447
+ "select",
4448
+ "textarea"
4449
+ ]);
4450
+ var INTERACTIVE_SELECTOR_PARTS = [
4451
+ "a[href]",
4452
+ "button",
4453
+ "input",
4454
+ "textarea",
4455
+ "select",
4456
+ '[role="button"]',
4457
+ '[role="link"]',
4458
+ '[role="menuitem"]',
4459
+ '[role="option"]',
4460
+ '[role="radio"]',
4461
+ '[role="checkbox"]',
4462
+ '[role="tab"]',
4463
+ '[contenteditable="true"]',
4464
+ "[onclick]",
4465
+ "[onmousedown]",
4466
+ "[onmouseup]"
4467
+ ];
4468
+ var INTERACTIVE_SELECTOR = INTERACTIVE_SELECTOR_PARTS.join(",");
4469
+ var INTERACTIVE_ROLE_TOKENS = [
4470
+ "button",
4471
+ "link",
4472
+ "menuitem",
4473
+ "option",
4474
+ "radio",
4475
+ "checkbox",
4476
+ "tab",
4477
+ "textbox",
4478
+ "combobox",
4479
+ "slider",
4480
+ "spinbutton",
4481
+ "search",
4482
+ "searchbox"
4483
+ ];
4484
+ var INTERACTIVE_ROLE_SET = new Set(
4485
+ INTERACTIVE_ROLE_TOKENS
4486
+ );
4487
+ var NON_NEGATIVE_TAB_INDEX_MIN = 0;
4488
+ function hasNonNegativeTabIndex(value) {
4489
+ if (value == null) return false;
4490
+ const parsed = Number.parseInt(value, 10);
4491
+ return Number.isFinite(parsed) && parsed >= NON_NEGATIVE_TAB_INDEX_MIN;
4492
+ }
4493
+
4442
4494
  // src/html/interactivity.ts
4443
4495
  var OPENSTEER_INTERACTIVE_ATTR = "data-opensteer-interactive";
4444
4496
  var OPENSTEER_HIDDEN_ATTR = "data-opensteer-hidden";
@@ -4453,42 +4505,12 @@ async function markInteractiveElements(page, {
4453
4505
  markAttribute: markAttribute2,
4454
4506
  skipIfAlreadyMarked: skipIfAlreadyMarked2,
4455
4507
  hiddenAttr,
4456
- scrollableAttr
4508
+ scrollableAttr,
4509
+ interactiveSelector,
4510
+ interactiveRoles,
4511
+ nonNegativeTabIndexMin
4457
4512
  }) => {
4458
- const interactiveSelector = [
4459
- "a[href]",
4460
- "button",
4461
- "input",
4462
- "textarea",
4463
- "select",
4464
- '[role="button"]',
4465
- '[role="link"]',
4466
- '[role="menuitem"]',
4467
- '[role="option"]',
4468
- '[role="radio"]',
4469
- '[role="checkbox"]',
4470
- '[role="tab"]',
4471
- '[contenteditable="true"]',
4472
- "[onclick]",
4473
- "[onmousedown]",
4474
- "[onmouseup]",
4475
- "[tabindex]"
4476
- ].join(",");
4477
- const interactiveRoles = /* @__PURE__ */ new Set([
4478
- "button",
4479
- "link",
4480
- "menuitem",
4481
- "option",
4482
- "radio",
4483
- "checkbox",
4484
- "tab",
4485
- "textbox",
4486
- "combobox",
4487
- "slider",
4488
- "spinbutton",
4489
- "search",
4490
- "searchbox"
4491
- ]);
4513
+ const interactiveRolesSet = new Set(interactiveRoles);
4492
4514
  function isExplicitlyHidden(el, style) {
4493
4515
  if (el.hasAttribute("hidden")) {
4494
4516
  return true;
@@ -4530,6 +4552,12 @@ async function markInteractiveElements(page, {
4530
4552
  }
4531
4553
  return !hasVisibleOutOfFlowChild(el);
4532
4554
  }
4555
+ function hasInteractiveTabIndex(el) {
4556
+ const value = el.getAttribute("tabindex");
4557
+ if (value == null) return false;
4558
+ const parsed = Number.parseInt(value, 10);
4559
+ return Number.isFinite(parsed) && parsed >= nonNegativeTabIndexMin;
4560
+ }
4533
4561
  const roots = [document];
4534
4562
  while (roots.length) {
4535
4563
  const root = roots.pop();
@@ -4555,11 +4583,13 @@ async function markInteractiveElements(page, {
4555
4583
  let interactive = false;
4556
4584
  if (el.matches(interactiveSelector)) {
4557
4585
  interactive = true;
4586
+ } else if (hasInteractiveTabIndex(el)) {
4587
+ interactive = true;
4558
4588
  } else if (style.cursor === "pointer") {
4559
4589
  interactive = true;
4560
4590
  } else {
4561
4591
  const role = (el.getAttribute("role") || "").toLowerCase();
4562
- if (interactiveRoles.has(role)) {
4592
+ if (interactiveRolesSet.has(role)) {
4563
4593
  interactive = true;
4564
4594
  }
4565
4595
  }
@@ -4604,7 +4634,10 @@ async function markInteractiveElements(page, {
4604
4634
  markAttribute,
4605
4635
  skipIfAlreadyMarked,
4606
4636
  hiddenAttr: OPENSTEER_HIDDEN_ATTR,
4607
- scrollableAttr: OPENSTEER_SCROLLABLE_ATTR
4637
+ scrollableAttr: OPENSTEER_SCROLLABLE_ATTR,
4638
+ interactiveSelector: INTERACTIVE_SELECTOR,
4639
+ interactiveRoles: INTERACTIVE_ROLE_TOKENS,
4640
+ nonNegativeTabIndexMin: NON_NEGATIVE_TAB_INDEX_MIN
4608
4641
  }
4609
4642
  );
4610
4643
  };
@@ -4691,7 +4724,7 @@ function isClickable($, el, context) {
4691
4724
  }
4692
4725
  const tag = (el[0]?.tagName || "").toLowerCase();
4693
4726
  if (!tag || ROOT_TAGS.has(tag)) return false;
4694
- if ((/* @__PURE__ */ new Set(["a", "button", "input", "select", "textarea"])).has(tag)) {
4727
+ if (NATIVE_INTERACTIVE_TAGS.has(tag)) {
4695
4728
  if (tag === "input") {
4696
4729
  const inputType = String(el.attr("type") || "").toLowerCase();
4697
4730
  if (inputType === "hidden") return false;
@@ -4705,26 +4738,11 @@ function isClickable($, el, context) {
4705
4738
  if (attrs["data-action"] !== void 0) return true;
4706
4739
  if (attrs["data-click"] !== void 0) return true;
4707
4740
  if (attrs["data-toggle"] !== void 0) return true;
4708
- if (attrs.tabindex !== void 0) {
4709
- const tabIndex = Number.parseInt(String(attrs.tabindex), 10);
4710
- if (!Number.isNaN(tabIndex) && tabIndex >= 0) return true;
4741
+ if (hasNonNegativeTabIndex(attrs.tabindex)) {
4742
+ return true;
4711
4743
  }
4712
4744
  const role = String(attrs.role || "").toLowerCase();
4713
- if ([
4714
- "button",
4715
- "link",
4716
- "menuitem",
4717
- "option",
4718
- "radio",
4719
- "checkbox",
4720
- "tab",
4721
- "textbox",
4722
- "combobox",
4723
- "slider",
4724
- "spinbutton",
4725
- "search",
4726
- "searchbox"
4727
- ].includes(role)) {
4745
+ if (INTERACTIVE_ROLE_SET.has(role)) {
4728
4746
  return true;
4729
4747
  }
4730
4748
  const className = String(attrs.class || "").toLowerCase();
@@ -1,11 +1,11 @@
1
1
  import {
2
2
  Opensteer
3
- } from "../chunk-I66RNYIW.js";
3
+ } from "../chunk-JZF2WC7U.js";
4
4
  import {
5
5
  normalizeError,
6
6
  resolveCloudSelection,
7
7
  resolveConfigWithEnv
8
- } from "../chunk-GTT3A3RU.js";
8
+ } from "../chunk-2ES46WCO.js";
9
9
  import "../chunk-K5CL76MG.js";
10
10
  import "../chunk-3H5RRIMZ.js";
11
11
 
package/dist/index.cjs CHANGED
@@ -1986,7 +1986,7 @@ function sanitizeNamespaceSegment(segment) {
1986
1986
  // src/config.ts
1987
1987
  var DEFAULT_CONFIG = {
1988
1988
  browser: {
1989
- headless: false,
1989
+ headless: void 0,
1990
1990
  executablePath: void 0,
1991
1991
  slowMo: 0,
1992
1992
  mode: void 0,
@@ -4544,6 +4544,58 @@ async function serializeFrameRecursive(frame, baseContext, frameKey) {
4544
4544
  };
4545
4545
  }
4546
4546
 
4547
+ // src/html/interactive-patterns.ts
4548
+ var NATIVE_INTERACTIVE_TAGS = /* @__PURE__ */ new Set([
4549
+ "a",
4550
+ "button",
4551
+ "input",
4552
+ "select",
4553
+ "textarea"
4554
+ ]);
4555
+ var INTERACTIVE_SELECTOR_PARTS = [
4556
+ "a[href]",
4557
+ "button",
4558
+ "input",
4559
+ "textarea",
4560
+ "select",
4561
+ '[role="button"]',
4562
+ '[role="link"]',
4563
+ '[role="menuitem"]',
4564
+ '[role="option"]',
4565
+ '[role="radio"]',
4566
+ '[role="checkbox"]',
4567
+ '[role="tab"]',
4568
+ '[contenteditable="true"]',
4569
+ "[onclick]",
4570
+ "[onmousedown]",
4571
+ "[onmouseup]"
4572
+ ];
4573
+ var INTERACTIVE_SELECTOR = INTERACTIVE_SELECTOR_PARTS.join(",");
4574
+ var INTERACTIVE_ROLE_TOKENS = [
4575
+ "button",
4576
+ "link",
4577
+ "menuitem",
4578
+ "option",
4579
+ "radio",
4580
+ "checkbox",
4581
+ "tab",
4582
+ "textbox",
4583
+ "combobox",
4584
+ "slider",
4585
+ "spinbutton",
4586
+ "search",
4587
+ "searchbox"
4588
+ ];
4589
+ var INTERACTIVE_ROLE_SET = new Set(
4590
+ INTERACTIVE_ROLE_TOKENS
4591
+ );
4592
+ var NON_NEGATIVE_TAB_INDEX_MIN = 0;
4593
+ function hasNonNegativeTabIndex(value) {
4594
+ if (value == null) return false;
4595
+ const parsed = Number.parseInt(value, 10);
4596
+ return Number.isFinite(parsed) && parsed >= NON_NEGATIVE_TAB_INDEX_MIN;
4597
+ }
4598
+
4547
4599
  // src/html/interactivity.ts
4548
4600
  var OPENSTEER_INTERACTIVE_ATTR = "data-opensteer-interactive";
4549
4601
  var OPENSTEER_HIDDEN_ATTR = "data-opensteer-hidden";
@@ -4558,42 +4610,12 @@ async function markInteractiveElements(page, {
4558
4610
  markAttribute: markAttribute2,
4559
4611
  skipIfAlreadyMarked: skipIfAlreadyMarked2,
4560
4612
  hiddenAttr,
4561
- scrollableAttr
4613
+ scrollableAttr,
4614
+ interactiveSelector,
4615
+ interactiveRoles,
4616
+ nonNegativeTabIndexMin
4562
4617
  }) => {
4563
- const interactiveSelector = [
4564
- "a[href]",
4565
- "button",
4566
- "input",
4567
- "textarea",
4568
- "select",
4569
- '[role="button"]',
4570
- '[role="link"]',
4571
- '[role="menuitem"]',
4572
- '[role="option"]',
4573
- '[role="radio"]',
4574
- '[role="checkbox"]',
4575
- '[role="tab"]',
4576
- '[contenteditable="true"]',
4577
- "[onclick]",
4578
- "[onmousedown]",
4579
- "[onmouseup]",
4580
- "[tabindex]"
4581
- ].join(",");
4582
- const interactiveRoles = /* @__PURE__ */ new Set([
4583
- "button",
4584
- "link",
4585
- "menuitem",
4586
- "option",
4587
- "radio",
4588
- "checkbox",
4589
- "tab",
4590
- "textbox",
4591
- "combobox",
4592
- "slider",
4593
- "spinbutton",
4594
- "search",
4595
- "searchbox"
4596
- ]);
4618
+ const interactiveRolesSet = new Set(interactiveRoles);
4597
4619
  function isExplicitlyHidden(el, style) {
4598
4620
  if (el.hasAttribute("hidden")) {
4599
4621
  return true;
@@ -4635,6 +4657,12 @@ async function markInteractiveElements(page, {
4635
4657
  }
4636
4658
  return !hasVisibleOutOfFlowChild(el);
4637
4659
  }
4660
+ function hasInteractiveTabIndex(el) {
4661
+ const value = el.getAttribute("tabindex");
4662
+ if (value == null) return false;
4663
+ const parsed = Number.parseInt(value, 10);
4664
+ return Number.isFinite(parsed) && parsed >= nonNegativeTabIndexMin;
4665
+ }
4638
4666
  const roots = [document];
4639
4667
  while (roots.length) {
4640
4668
  const root = roots.pop();
@@ -4660,11 +4688,13 @@ async function markInteractiveElements(page, {
4660
4688
  let interactive = false;
4661
4689
  if (el.matches(interactiveSelector)) {
4662
4690
  interactive = true;
4691
+ } else if (hasInteractiveTabIndex(el)) {
4692
+ interactive = true;
4663
4693
  } else if (style.cursor === "pointer") {
4664
4694
  interactive = true;
4665
4695
  } else {
4666
4696
  const role = (el.getAttribute("role") || "").toLowerCase();
4667
- if (interactiveRoles.has(role)) {
4697
+ if (interactiveRolesSet.has(role)) {
4668
4698
  interactive = true;
4669
4699
  }
4670
4700
  }
@@ -4709,7 +4739,10 @@ async function markInteractiveElements(page, {
4709
4739
  markAttribute,
4710
4740
  skipIfAlreadyMarked,
4711
4741
  hiddenAttr: OPENSTEER_HIDDEN_ATTR,
4712
- scrollableAttr: OPENSTEER_SCROLLABLE_ATTR
4742
+ scrollableAttr: OPENSTEER_SCROLLABLE_ATTR,
4743
+ interactiveSelector: INTERACTIVE_SELECTOR,
4744
+ interactiveRoles: INTERACTIVE_ROLE_TOKENS,
4745
+ nonNegativeTabIndexMin: NON_NEGATIVE_TAB_INDEX_MIN
4713
4746
  }
4714
4747
  );
4715
4748
  };
@@ -4796,7 +4829,7 @@ function isClickable($, el, context) {
4796
4829
  }
4797
4830
  const tag = (el[0]?.tagName || "").toLowerCase();
4798
4831
  if (!tag || ROOT_TAGS.has(tag)) return false;
4799
- if ((/* @__PURE__ */ new Set(["a", "button", "input", "select", "textarea"])).has(tag)) {
4832
+ if (NATIVE_INTERACTIVE_TAGS.has(tag)) {
4800
4833
  if (tag === "input") {
4801
4834
  const inputType = String(el.attr("type") || "").toLowerCase();
4802
4835
  if (inputType === "hidden") return false;
@@ -4810,26 +4843,11 @@ function isClickable($, el, context) {
4810
4843
  if (attrs["data-action"] !== void 0) return true;
4811
4844
  if (attrs["data-click"] !== void 0) return true;
4812
4845
  if (attrs["data-toggle"] !== void 0) return true;
4813
- if (attrs.tabindex !== void 0) {
4814
- const tabIndex = Number.parseInt(String(attrs.tabindex), 10);
4815
- if (!Number.isNaN(tabIndex) && tabIndex >= 0) return true;
4846
+ if (hasNonNegativeTabIndex(attrs.tabindex)) {
4847
+ return true;
4816
4848
  }
4817
4849
  const role = String(attrs.role || "").toLowerCase();
4818
- if ([
4819
- "button",
4820
- "link",
4821
- "menuitem",
4822
- "option",
4823
- "radio",
4824
- "checkbox",
4825
- "tab",
4826
- "textbox",
4827
- "combobox",
4828
- "slider",
4829
- "spinbutton",
4830
- "search",
4831
- "searchbox"
4832
- ].includes(role)) {
4850
+ if (INTERACTIVE_ROLE_SET.has(role)) {
4833
4851
  return true;
4834
4852
  }
4835
4853
  const className = String(attrs.class || "").toLowerCase();
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  BrowserProfileClient
3
- } from "./chunk-A6LF44E3.js";
3
+ } from "./chunk-ZRCFF546.js";
4
4
  import {
5
5
  ActionWsClient,
6
6
  BrowserPool,
@@ -80,7 +80,7 @@ import {
80
80
  switchTab,
81
81
  typeText,
82
82
  waitForVisualStability
83
- } from "./chunk-I66RNYIW.js";
83
+ } from "./chunk-JZF2WC7U.js";
84
84
  import {
85
85
  CloudCdpClient,
86
86
  CloudSessionClient,
@@ -98,7 +98,7 @@ import {
98
98
  isCloudSessionStatus,
99
99
  normalizeNamespace,
100
100
  resolveNamespaceDir
101
- } from "./chunk-GTT3A3RU.js";
101
+ } from "./chunk-2ES46WCO.js";
102
102
  import {
103
103
  detectChromePaths,
104
104
  expandHome,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opensteer",
3
- "version": "0.6.9",
3
+ "version": "0.6.11",
4
4
  "description": "Open-source browser automation SDK and CLI that lets AI agents build complex scrapers directly in your codebase.",
5
5
  "license": "MIT",
6
6
  "type": "module",