@nice-code/action 0.2.19 → 0.3.0

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.
@@ -1957,7 +1957,7 @@ class ActionDevtoolsCore {
1957
1957
  }
1958
1958
  }
1959
1959
  // src/devtools/browser/NiceActionDevtools.tsx
1960
- import { useEffect as useEffect3, useMemo as useMemo2, useRef as useRef2, useState as useState9 } from "react";
1960
+ import { useEffect as useEffect4, useMemo as useMemo3, useState as useState9 } from "react";
1961
1961
 
1962
1962
  // src/devtools/core/devtools_colors.ts
1963
1963
  var DEVTOOL_COLOR_SEMANTIC_ERROR = "#FF5C5C";
@@ -3310,6 +3310,8 @@ function Chip({
3310
3310
  onMouseEnter: hasTooltip ? (e) => setAnchor(e.currentTarget.getBoundingClientRect()) : undefined,
3311
3311
  onMouseLeave: hasTooltip ? () => setAnchor(null) : undefined,
3312
3312
  style: {
3313
+ display: "flex",
3314
+ alignItems: "center",
3313
3315
  color: resolvedColor,
3314
3316
  fontSize,
3315
3317
  background: DEVTOOL_LIST_BASE_BACKGROUND,
@@ -3334,11 +3336,13 @@ function Chip({
3334
3336
  // src/devtools/browser/components/Icon.tsx
3335
3337
  import { useState as useState4 } from "react";
3336
3338
  import { jsxDEV as jsxDEV8, Fragment as Fragment3 } from "react/jsx-dev-runtime";
3337
- var ICON_SIZE_PX = {
3338
- ["sm" /* sm */]: 13,
3339
- ["md" /* md */]: 16,
3340
- ["lg" /* lg */]: 18
3339
+ var ICON_SIZE_EM = {
3340
+ ["sm" /* sm */]: 1,
3341
+ ["md" /* md */]: 1.2,
3342
+ ["lg" /* lg */]: 1.6
3341
3343
  };
3344
+ var BASE_ICON_SIDE_LENGTH_EM = 1.5;
3345
+ var ICON_GAP_EM = 0.3;
3342
3346
  function Icon({
3343
3347
  icon: IconComponent,
3344
3348
  color,
@@ -3351,6 +3355,9 @@ function Icon({
3351
3355
  const hasTooltip = tooltip != null;
3352
3356
  const colorEntry = SEMANTIC_COLORS[color];
3353
3357
  const resolvedColor = subtle ? colorEntry.subtle?.color ?? colorEntry.color : colorEntry.color;
3358
+ const finalIcons = Array.isArray(IconComponent) ? IconComponent : [IconComponent];
3359
+ const fullIconWidthEm = (finalIcons.length - 1) * ICON_GAP_EM + finalIcons.length * BASE_ICON_SIDE_LENGTH_EM * getSizeValue(size);
3360
+ const iconSideLengthEm = `${BASE_ICON_SIDE_LENGTH_EM * getSizeValue(size)}em`;
3354
3361
  return /* @__PURE__ */ jsxDEV8(Fragment3, {
3355
3362
  children: [
3356
3363
  /* @__PURE__ */ jsxDEV8("div", {
@@ -3358,8 +3365,9 @@ function Icon({
3358
3365
  onMouseLeave: hasTooltip ? () => setAnchor(null) : undefined,
3359
3366
  style: {
3360
3367
  borderRadius: "0.4em",
3361
- height: `${1.65 * getSizeValue(size)}em`,
3362
- width: `${1.65 * getSizeValue(size)}em`,
3368
+ width: `${fullIconWidthEm}em`,
3369
+ height: iconSideLengthEm,
3370
+ padding: "0.15em",
3363
3371
  display: "flex",
3364
3372
  alignItems: "center",
3365
3373
  justifyContent: "center",
@@ -3369,9 +3377,12 @@ function Icon({
3369
3377
  cursor: hasTooltip ? "default" : undefined,
3370
3378
  ...style
3371
3379
  },
3372
- children: /* @__PURE__ */ jsxDEV8(IconComponent, {
3373
- size: ICON_SIZE_PX[size],
3374
- strokeWidth: 1.5
3380
+ children: /* @__PURE__ */ jsxDEV8("div", {
3381
+ style: { display: "flex", alignItems: "center", gap: `${ICON_GAP_EM}em` },
3382
+ children: finalIcons.map((Comp, i) => /* @__PURE__ */ jsxDEV8(Comp, {
3383
+ size: iconSideLengthEm,
3384
+ strokeWidth: 2.3
3385
+ }, `${Comp.name}-${i}`, false, undefined, this))
3375
3386
  }, undefined, false, undefined, this)
3376
3387
  }, undefined, false, undefined, this),
3377
3388
  anchor != null && hasTooltip && /* @__PURE__ */ jsxDEV8(Tooltip, {
@@ -3455,26 +3466,28 @@ function DomainChip({
3455
3466
  title: "Action Domain",
3456
3467
  align: "edge"
3457
3468
  },
3458
- style: { display: "flex", alignItems: "center", gap: "0.4em" },
3459
- children: [
3460
- /* @__PURE__ */ jsxDEV9("span", {
3461
- style: {
3462
- height: "1.2em",
3463
- width: "1.2em",
3464
- display: "flex",
3465
- alignItems: "center",
3466
- justifyContent: "center"
3467
- },
3468
- children: /* @__PURE__ */ jsxDEV9(Component, {
3469
- height: "1.2em",
3470
- width: "1.2em"
3469
+ children: /* @__PURE__ */ jsxDEV9("div", {
3470
+ style: { display: "flex", alignItems: "center", gap: "0.4em" },
3471
+ children: [
3472
+ /* @__PURE__ */ jsxDEV9("span", {
3473
+ style: {
3474
+ height: "1.2em",
3475
+ width: "1.2em",
3476
+ display: "flex",
3477
+ alignItems: "center",
3478
+ justifyContent: "center"
3479
+ },
3480
+ children: /* @__PURE__ */ jsxDEV9(Component, {
3481
+ height: "1.2em",
3482
+ width: "1.2em"
3483
+ }, undefined, false, undefined, this)
3484
+ }, undefined, false, undefined, this),
3485
+ /* @__PURE__ */ jsxDEV9("span", {
3486
+ children: domain
3471
3487
  }, undefined, false, undefined, this)
3472
- }, undefined, false, undefined, this),
3473
- /* @__PURE__ */ jsxDEV9("span", {
3474
- children: domain
3475
- }, undefined, false, undefined, this)
3476
- ]
3477
- }, undefined, true, undefined, this);
3488
+ ]
3489
+ }, undefined, true, undefined, this)
3490
+ }, undefined, false, undefined, this);
3478
3491
  }
3479
3492
 
3480
3493
  // src/devtools/browser/components/HandlerChips.tsx
@@ -4197,19 +4210,18 @@ function ActionDetailPanel({
4197
4210
  }, undefined, true, undefined, this);
4198
4211
  }
4199
4212
 
4213
+ // src/devtools/browser/components/action_list/ActionList.tsx
4214
+ import { useEffect as useEffect3, useMemo as useMemo2, useRef as useRef2 } from "react";
4215
+
4200
4216
  // src/devtools/browser/components/action_list/ActionEntryRow.tsx
4201
- import { Box, CircleX as CircleX2, Variable } from "lucide-react";
4202
- import { Fragment as Fragment7, useState as useState8 } from "react";
4203
- import { jsxDEV as jsxDEV17, Fragment as Fragment8 } from "react/jsx-dev-runtime";
4204
- function getLatestChipColor(status) {
4205
- if (status === "failed")
4206
- return "failed" /* failed */;
4207
- if (status === "action-error")
4208
- return "action_error" /* action_error */;
4209
- if (status === "aborted")
4210
- return "aborted" /* aborted */;
4211
- return "success" /* success */;
4212
- }
4217
+ import { Box as Box2, CircleX as CircleX3, Variable as Variable2 } from "lucide-react";
4218
+ import { Fragment as Fragment8, useState as useState8 } from "react";
4219
+
4220
+ // src/devtools/browser/components/action_list/ActionInputAndOutputChip.tsx
4221
+ import { Box, CircleX as CircleX2, Sprout, Variable } from "lucide-react";
4222
+
4223
+ // src/devtools/browser/components/action_list/IoTooltipContent.tsx
4224
+ import { jsxDEV as jsxDEV17, Fragment as Fragment7 } from "react/jsx-dev-runtime";
4213
4225
  var JSON_TOKEN_RE2 = /("(?:\\.|[^"\\])*")(\s*:)?|(-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)|(\btrue\b|\bfalse\b|\bnull\b|\bundefined\b)|([{}[\],])/g;
4214
4226
  function renderColoredJson2(text) {
4215
4227
  const nodes = [];
@@ -4281,6 +4293,84 @@ function IoTooltipContent({ value }) {
4281
4293
  children: renderColoredJson2(text)
4282
4294
  }, undefined, false, undefined, this);
4283
4295
  }
4296
+
4297
+ // src/devtools/browser/components/action_list/ActionInputAndOutputChip.tsx
4298
+ import { jsxDEV as jsxDEV18 } from "react/jsx-dev-runtime";
4299
+ var ActionInputAndOutputChip = ({
4300
+ entry,
4301
+ breakReasons,
4302
+ subtle,
4303
+ size
4304
+ }) => {
4305
+ const firstHop = entry.meta.routing[0];
4306
+ const localEnvId = firstHop != null ? firstHop.runtime.envId : null;
4307
+ const externalLabel = firstHop != null ? getExternalLabel(firstHop) : null;
4308
+ const firstHopIsLocal = firstHop != null && firstHop.handlerType === "local";
4309
+ const isLocal = localEnvId != null && (firstHopIsLocal || externalLabel == null);
4310
+ const color = isLocal ? "handler_local" /* handler_local */ : "handler_external" /* handler_external */;
4311
+ const isNewInput = breakReasons.includes("new_input" /* new_input */);
4312
+ const isNewOutput = breakReasons.includes("new_output" /* new_output */);
4313
+ const hasError = entry.error != null || entry.abortReason != null;
4314
+ return /* @__PURE__ */ jsxDEV18(Chip, {
4315
+ color,
4316
+ size,
4317
+ subtle,
4318
+ children: /* @__PURE__ */ jsxDEV18("div", {
4319
+ style: { display: "flex", alignItems: "center", gap: "0.4em" },
4320
+ children: [
4321
+ /* @__PURE__ */ jsxDEV18(Icon, {
4322
+ icon: isNewInput ? [Sprout, Variable] : Variable,
4323
+ color,
4324
+ subtle: subtle || entry.input === undefined,
4325
+ tooltip: {
4326
+ content: entry.input !== undefined ? /* @__PURE__ */ jsxDEV18(IoTooltipContent, {
4327
+ value: entry.input
4328
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV18("span", {
4329
+ style: { color: DEVTOOL_COLOR_TEXT_MUTED, fontSize: "10px" },
4330
+ children: "No input required or given"
4331
+ }, undefined, false, undefined, this),
4332
+ title: isNewInput ? "New Input" : "Input"
4333
+ }
4334
+ }, undefined, false, undefined, this),
4335
+ isLocal ? localEnvId : externalLabel,
4336
+ entry.status === "success" && entry.output !== undefined && /* @__PURE__ */ jsxDEV18(Icon, {
4337
+ icon: isNewOutput ? [Sprout, Box] : Box,
4338
+ color: !hasError ? color : "default" /* default */,
4339
+ tooltip: {
4340
+ content: /* @__PURE__ */ jsxDEV18(IoTooltipContent, {
4341
+ value: entry.output
4342
+ }, undefined, false, undefined, this),
4343
+ title: isNewOutput ? "New Output" : "Output"
4344
+ }
4345
+ }, undefined, false, undefined, this),
4346
+ (entry.error != null || entry.abortReason != null) && /* @__PURE__ */ jsxDEV18(Icon, {
4347
+ icon: CircleX2,
4348
+ color: entry.status === "aborted" ? "aborted" /* aborted */ : "error" /* error */,
4349
+ tooltip: {
4350
+ content: /* @__PURE__ */ jsxDEV18(ActionErrorDisplay, {
4351
+ entry,
4352
+ compact: true
4353
+ }, undefined, false, undefined, this),
4354
+ title: entry.status === "aborted" ? "Aborted" : "Error",
4355
+ maxWidth: 340
4356
+ }
4357
+ }, undefined, false, undefined, this)
4358
+ ]
4359
+ }, undefined, true, undefined, this)
4360
+ }, undefined, false, undefined, this);
4361
+ };
4362
+
4363
+ // src/devtools/browser/components/action_list/ActionEntryRow.tsx
4364
+ import { jsxDEV as jsxDEV19, Fragment as Fragment9 } from "react/jsx-dev-runtime";
4365
+ function getLatestChipColor(status) {
4366
+ if (status === "failed")
4367
+ return "failed" /* failed */;
4368
+ if (status === "action-error")
4369
+ return "action_error" /* action_error */;
4370
+ if (status === "aborted")
4371
+ return "aborted" /* aborted */;
4372
+ return "success" /* success */;
4373
+ }
4284
4374
  function GroupDotTooltip({
4285
4375
  entry,
4286
4376
  index,
@@ -4293,14 +4383,14 @@ function GroupDotTooltip({
4293
4383
  const deltaMs = refTime - entry.startTime;
4294
4384
  const relStr = index === 0 ? "latest run" : `−${formatRelativeAge(deltaMs)} from latest`;
4295
4385
  const durationStr = entry.endTime != null ? `${entry.endTime - entry.startTime}ms` : "running…";
4296
- return /* @__PURE__ */ jsxDEV17(Tooltip, {
4386
+ return /* @__PURE__ */ jsxDEV19(Tooltip, {
4297
4387
  anchor,
4298
4388
  config: {
4299
4389
  align: "center",
4300
4390
  maxWidth: 240,
4301
- content: /* @__PURE__ */ jsxDEV17(Fragment8, {
4391
+ content: /* @__PURE__ */ jsxDEV19(Fragment9, {
4302
4392
  children: [
4303
- /* @__PURE__ */ jsxDEV17("div", {
4393
+ /* @__PURE__ */ jsxDEV19("div", {
4304
4394
  style: { color: dotColor, marginBottom: "1px" },
4305
4395
  children: [
4306
4396
  symbol,
@@ -4310,15 +4400,15 @@ function GroupDotTooltip({
4310
4400
  total
4311
4401
  ]
4312
4402
  }, undefined, true, undefined, this),
4313
- /* @__PURE__ */ jsxDEV17("div", {
4403
+ /* @__PURE__ */ jsxDEV19("div", {
4314
4404
  style: { color: DEVTOOL_COLOR_TEXT_SECONDARY },
4315
4405
  children: formatTimestamp(entry.startTime)
4316
4406
  }, undefined, false, undefined, this),
4317
- /* @__PURE__ */ jsxDEV17("div", {
4407
+ /* @__PURE__ */ jsxDEV19("div", {
4318
4408
  style: { color: DEVTOOL_COLOR_TEXT_MUTED },
4319
4409
  children: durationStr
4320
4410
  }, undefined, false, undefined, this),
4321
- index > 0 && /* @__PURE__ */ jsxDEV17("div", {
4411
+ index > 0 && /* @__PURE__ */ jsxDEV19("div", {
4322
4412
  style: {
4323
4413
  color: DEVTOOL_COLOR_TEXT_MUTED,
4324
4414
  marginTop: "3px",
@@ -4343,9 +4433,9 @@ function GroupDot({
4343
4433
  const [anchor, setAnchor] = useState8(null);
4344
4434
  const dotColor = STATUS_COLOR[entry.status];
4345
4435
  const hovered = anchor != null;
4346
- return /* @__PURE__ */ jsxDEV17(Fragment8, {
4436
+ return /* @__PURE__ */ jsxDEV19(Fragment9, {
4347
4437
  children: [
4348
- /* @__PURE__ */ jsxDEV17("button", {
4438
+ /* @__PURE__ */ jsxDEV19("button", {
4349
4439
  "data-cuid": entry.cuid,
4350
4440
  onClick: (e) => {
4351
4441
  e.stopPropagation();
@@ -4367,7 +4457,7 @@ function GroupDot({
4367
4457
  transition: "transform 0.1s ease, opacity 0.1s ease, border-color 0.1s ease"
4368
4458
  }
4369
4459
  }, undefined, false, undefined, this),
4370
- hovered && anchor != null && /* @__PURE__ */ jsxDEV17(GroupDotTooltip, {
4460
+ hovered && anchor != null && /* @__PURE__ */ jsxDEV19(GroupDotTooltip, {
4371
4461
  entry,
4372
4462
  index,
4373
4463
  total,
@@ -4392,8 +4482,8 @@ function ActionEntryRow({
4392
4482
  }) {
4393
4483
  const timestamp = formatTimestamp(entry.startTime);
4394
4484
  const hasGroup = groupEntries != null && groupEntries.length > 1;
4395
- const hasBottomContent = childEntries != null && childEntries.length > 0 || (breakReasons?.some((r) => r !== "new input" && r !== "new output") ?? false) || entry.error != null || entry.abortReason != null;
4396
- return /* @__PURE__ */ jsxDEV17("div", {
4485
+ const hasBottomContent = childEntries != null && childEntries.length > 0 || (breakReasons?.some((r) => r !== "new_input" /* new_input */ && r !== "new_output" /* new_output */) ?? false) || entry.error != null || entry.abortReason != null;
4486
+ return /* @__PURE__ */ jsxDEV19("div", {
4397
4487
  "data-cuid": entry.cuid,
4398
4488
  onClick,
4399
4489
  style: {
@@ -4410,7 +4500,7 @@ function ActionEntryRow({
4410
4500
  margin: "2px 4px"
4411
4501
  },
4412
4502
  children: [
4413
- /* @__PURE__ */ jsxDEV17("div", {
4503
+ /* @__PURE__ */ jsxDEV19("div", {
4414
4504
  style: {
4415
4505
  position: "absolute",
4416
4506
  left: "2em",
@@ -4422,10 +4512,10 @@ function ActionEntryRow({
4422
4512
  zIndex: 0
4423
4513
  }
4424
4514
  }, undefined, false, undefined, this),
4425
- /* @__PURE__ */ jsxDEV17("div", {
4515
+ /* @__PURE__ */ jsxDEV19("div", {
4426
4516
  style: { display: "flex", alignItems: "center", gap: "8px" },
4427
4517
  children: [
4428
- /* @__PURE__ */ jsxDEV17("div", {
4518
+ /* @__PURE__ */ jsxDEV19("div", {
4429
4519
  style: {
4430
4520
  position: "relative",
4431
4521
  zIndex: 1,
@@ -4435,11 +4525,11 @@ function ActionEntryRow({
4435
4525
  alignItems: "center",
4436
4526
  justifyContent: "flex-start"
4437
4527
  },
4438
- children: isLatest ? /* @__PURE__ */ jsxDEV17(Chip, {
4528
+ children: isLatest ? /* @__PURE__ */ jsxDEV19(Chip, {
4439
4529
  size: "sm" /* sm */,
4440
4530
  color: getLatestChipColor(entry.status),
4441
4531
  children: "latest"
4442
- }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV17(Chip, {
4532
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV19(Chip, {
4443
4533
  size: "sm" /* sm */,
4444
4534
  color: getLatestChipColor(entry.status),
4445
4535
  children: [
@@ -4448,10 +4538,10 @@ function ActionEntryRow({
4448
4538
  ]
4449
4539
  }, undefined, true, undefined, this)
4450
4540
  }, undefined, false, undefined, this),
4451
- /* @__PURE__ */ jsxDEV17("div", {
4541
+ /* @__PURE__ */ jsxDEV19("div", {
4452
4542
  style: { flex: 1, minWidth: 0, display: "flex", alignItems: "center", gap: "0.5em" },
4453
4543
  children: [
4454
- /* @__PURE__ */ jsxDEV17("span", {
4544
+ /* @__PURE__ */ jsxDEV19("span", {
4455
4545
  style: {
4456
4546
  color: DEVTOOL_COLOR_TEXT_SECONDARY,
4457
4547
  fontSize: "1em",
@@ -4465,47 +4555,14 @@ function ActionEntryRow({
4465
4555
  },
4466
4556
  children: entry.actionId
4467
4557
  }, undefined, false, undefined, this),
4468
- /* @__PURE__ */ jsxDEV17(Icon, {
4469
- icon: Variable,
4470
- color: entry.input !== undefined ? "io_input" /* io_input */ : "default" /* default */,
4471
- subtle: entry.input === undefined,
4472
- tooltip: {
4473
- content: entry.input !== undefined ? /* @__PURE__ */ jsxDEV17(IoTooltipContent, {
4474
- value: entry.input
4475
- }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV17("span", {
4476
- style: { color: DEVTOOL_COLOR_TEXT_MUTED, fontSize: "10px" },
4477
- children: "No input required or given"
4478
- }, undefined, false, undefined, this),
4479
- title: "Input"
4480
- }
4481
- }, undefined, false, undefined, this),
4482
- /* @__PURE__ */ jsxDEV17(HandlerChips, {
4483
- entry,
4484
- size: "sm" /* sm */
4485
- }, undefined, false, undefined, this),
4486
- entry.status === "success" && entry.output !== undefined && /* @__PURE__ */ jsxDEV17(Icon, {
4487
- icon: Box,
4488
- color: "io_output" /* io_output */,
4489
- tooltip: { content: /* @__PURE__ */ jsxDEV17(IoTooltipContent, {
4490
- value: entry.output
4491
- }, undefined, false, undefined, this), title: "Output" }
4492
- }, undefined, false, undefined, this),
4493
- (entry.error != null || entry.abortReason != null) && /* @__PURE__ */ jsxDEV17(Icon, {
4494
- icon: CircleX2,
4495
- color: entry.status === "aborted" ? "aborted" /* aborted */ : "error" /* error */,
4496
- tooltip: {
4497
- content: /* @__PURE__ */ jsxDEV17(ActionErrorDisplay, {
4498
- entry,
4499
- compact: true
4500
- }, undefined, false, undefined, this),
4501
- title: entry.status === "aborted" ? "Aborted" : "Error",
4502
- maxWidth: 340
4503
- }
4558
+ /* @__PURE__ */ jsxDEV19(ActionInputAndOutputChip, {
4559
+ breakReasons,
4560
+ entry
4504
4561
  }, undefined, false, undefined, this),
4505
- /* @__PURE__ */ jsxDEV17("div", {
4562
+ /* @__PURE__ */ jsxDEV19("div", {
4506
4563
  style: { flex: 1 }
4507
4564
  }, undefined, false, undefined, this),
4508
- /* @__PURE__ */ jsxDEV17("span", {
4565
+ /* @__PURE__ */ jsxDEV19("span", {
4509
4566
  style: {
4510
4567
  color: DEVTOOL_COLOR_SEMANTIC_METADATA,
4511
4568
  fontSize: "10px",
@@ -4515,9 +4572,9 @@ function ActionEntryRow({
4515
4572
  },
4516
4573
  children: timestamp
4517
4574
  }, undefined, false, undefined, this),
4518
- /* @__PURE__ */ jsxDEV17("span", {
4575
+ /* @__PURE__ */ jsxDEV19("span", {
4519
4576
  style: { color: DEVTOOL_COLOR_SEMANTIC_WARNING, fontSize: "11px", flexShrink: 0 },
4520
- children: /* @__PURE__ */ jsxDEV17(DurationDisplay, {
4577
+ children: /* @__PURE__ */ jsxDEV19(DurationDisplay, {
4521
4578
  entry
4522
4579
  }, undefined, false, undefined, this)
4523
4580
  }, undefined, false, undefined, this)
@@ -4525,7 +4582,7 @@ function ActionEntryRow({
4525
4582
  }, undefined, true, undefined, this)
4526
4583
  ]
4527
4584
  }, undefined, true, undefined, this),
4528
- hasBottomContent && /* @__PURE__ */ jsxDEV17("div", {
4585
+ hasBottomContent && /* @__PURE__ */ jsxDEV19("div", {
4529
4586
  style: {
4530
4587
  display: "flex",
4531
4588
  flexWrap: "wrap",
@@ -4534,33 +4591,35 @@ function ActionEntryRow({
4534
4591
  paddingLeft: "4.5em"
4535
4592
  },
4536
4593
  children: [
4537
- childEntries?.map((child) => /* @__PURE__ */ jsxDEV17(Fragment7, {
4594
+ childEntries?.map((child) => /* @__PURE__ */ jsxDEV19(Fragment8, {
4538
4595
  children: [
4539
- /* @__PURE__ */ jsxDEV17(Icon, {
4540
- icon: Variable,
4596
+ /* @__PURE__ */ jsxDEV19(Icon, {
4597
+ size: "sm" /* sm */,
4598
+ icon: Variable2,
4541
4599
  color: "io_input" /* io_input */,
4542
4600
  subtle: true,
4543
4601
  tooltip: {
4544
- content: child.input !== undefined ? /* @__PURE__ */ jsxDEV17(IoTooltipContent, {
4602
+ content: child.input !== undefined ? /* @__PURE__ */ jsxDEV19(IoTooltipContent, {
4545
4603
  value: child.input
4546
- }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV17("span", {
4604
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV19("span", {
4547
4605
  style: { color: DEVTOOL_COLOR_TEXT_MUTED, fontSize: "10px" },
4548
4606
  children: "No input required or given"
4549
4607
  }, undefined, false, undefined, this),
4550
4608
  title: `Input · ${child.actionId}`
4551
4609
  }
4552
4610
  }, undefined, false, undefined, this),
4553
- /* @__PURE__ */ jsxDEV17(HandlerChips, {
4611
+ /* @__PURE__ */ jsxDEV19(HandlerChips, {
4554
4612
  entry: child,
4555
4613
  size: "sm" /* sm */,
4556
4614
  subtle: true
4557
4615
  }, undefined, false, undefined, this),
4558
- child.status === "success" && child.output !== undefined && /* @__PURE__ */ jsxDEV17(Icon, {
4559
- icon: Box,
4616
+ child.status === "success" && child.output !== undefined && /* @__PURE__ */ jsxDEV19(Icon, {
4617
+ size: "sm" /* sm */,
4618
+ icon: Box2,
4560
4619
  color: "io_output" /* io_output */,
4561
4620
  subtle: true,
4562
4621
  tooltip: {
4563
- content: /* @__PURE__ */ jsxDEV17(IoTooltipContent, {
4622
+ content: /* @__PURE__ */ jsxDEV19(IoTooltipContent, {
4564
4623
  value: child.output
4565
4624
  }, undefined, false, undefined, this),
4566
4625
  title: `Output · ${child.actionId}`
@@ -4568,17 +4627,17 @@ function ActionEntryRow({
4568
4627
  }, undefined, false, undefined, this)
4569
4628
  ]
4570
4629
  }, child.actionId, true, undefined, this)),
4571
- breakReasons?.filter((r) => r !== "new input" && r !== "new output").map((reason) => /* @__PURE__ */ jsxDEV17(Chip, {
4630
+ breakReasons?.filter((r) => r !== "new_input" /* new_input */ && r !== "new_output" /* new_output */).map((reason) => /* @__PURE__ */ jsxDEV19(Chip, {
4572
4631
  color: "default" /* default */,
4573
4632
  subtle: true,
4574
4633
  children: reason
4575
4634
  }, reason, false, undefined, this)),
4576
- (childEntries?.length ?? 0) > 0 && (entry.error != null || entry.abortReason != null) && /* @__PURE__ */ jsxDEV17(Icon, {
4577
- icon: CircleX2,
4635
+ (childEntries?.length ?? 0) > 0 && (entry.error != null || entry.abortReason != null) && /* @__PURE__ */ jsxDEV19(Icon, {
4636
+ icon: CircleX3,
4578
4637
  color: entry.status === "aborted" ? "aborted" /* aborted */ : "error" /* error */,
4579
4638
  subtle: true,
4580
4639
  tooltip: {
4581
- content: /* @__PURE__ */ jsxDEV17(ActionErrorDisplay, {
4640
+ content: /* @__PURE__ */ jsxDEV19(ActionErrorDisplay, {
4582
4641
  entry,
4583
4642
  compact: true
4584
4643
  }, undefined, false, undefined, this),
@@ -4588,7 +4647,7 @@ function ActionEntryRow({
4588
4647
  }, undefined, false, undefined, this)
4589
4648
  ]
4590
4649
  }, undefined, true, undefined, this),
4591
- hasGroup && /* @__PURE__ */ jsxDEV17("div", {
4650
+ hasGroup && /* @__PURE__ */ jsxDEV19("div", {
4592
4651
  style: {
4593
4652
  display: "flex",
4594
4653
  flexWrap: "wrap",
@@ -4597,7 +4656,7 @@ function ActionEntryRow({
4597
4656
  paddingLeft: "4.6em",
4598
4657
  paddingBottom: "2px"
4599
4658
  },
4600
- children: groupEntries.map((e, i) => /* @__PURE__ */ jsxDEV17(GroupDot, {
4659
+ children: groupEntries.map((e, i) => /* @__PURE__ */ jsxDEV19(GroupDot, {
4601
4660
  entry: e,
4602
4661
  index: i,
4603
4662
  total: groupEntries.length,
@@ -4610,8 +4669,124 @@ function ActionEntryRow({
4610
4669
  }, undefined, true, undefined, this);
4611
4670
  }
4612
4671
 
4672
+ // src/devtools/browser/components/action_list/ActionList.tsx
4673
+ import { jsxDEV as jsxDEV20 } from "react/jsx-dev-runtime";
4674
+ function getBreakReasons(current, previous) {
4675
+ const reasons = [];
4676
+ const inputChanged = current.inputHash != null && previous.inputHash != null ? current.inputHash !== previous.inputHash : safeStringify(current.input, 0) !== safeStringify(previous.input, 0);
4677
+ if (inputChanged)
4678
+ reasons.push("new_input" /* new_input */);
4679
+ const outputChanged = current.outputHash != null && previous.outputHash != null && current.outputHash !== previous.outputHash;
4680
+ if (outputChanged)
4681
+ reasons.push("new_output" /* new_output */);
4682
+ return reasons;
4683
+ }
4684
+ function getGroupChildEntries(group, childEntriesMap) {
4685
+ const seen = new Set;
4686
+ const result = [];
4687
+ for (const e of [group.representative, ...group.rest]) {
4688
+ for (const child of childEntriesMap.get(e.cuid) ?? []) {
4689
+ if (!seen.has(child.actionId)) {
4690
+ seen.add(child.actionId);
4691
+ result.push(child);
4692
+ }
4693
+ }
4694
+ }
4695
+ return result.length > 0 ? result.sort((a, b) => a.startTime - b.startTime) : undefined;
4696
+ }
4697
+ function getFlatItemKey(item) {
4698
+ const oldestCuid = item.group.rest[item.group.rest.length - 1]?.cuid ?? item.group.representative.cuid;
4699
+ return `g:${oldestCuid}`;
4700
+ }
4701
+ function ActionList({
4702
+ groups,
4703
+ selectedCuid,
4704
+ onGroupClick,
4705
+ onSubClick,
4706
+ childEntriesMap,
4707
+ style
4708
+ }) {
4709
+ const containerRef = useRef2(null);
4710
+ const latestTime = groups[0]?.representative.startTime;
4711
+ const flatItems = useMemo2(() => {
4712
+ return groups.map((group, gi) => {
4713
+ const prevGroup = groups[gi + 1];
4714
+ let breakReasons = [];
4715
+ if (prevGroup != null && prevGroup.representative.actionId === group.representative.actionId && prevGroup.representative.domain === group.representative.domain) {
4716
+ const reasons = getBreakReasons(group.representative, prevGroup.representative);
4717
+ if (reasons.length > 0)
4718
+ breakReasons = reasons;
4719
+ }
4720
+ return { group, groupIndex: gi, breakReasons };
4721
+ });
4722
+ }, [groups]);
4723
+ const prevSelectedRef = useRef2(selectedCuid);
4724
+ useEffect3(() => {
4725
+ if (selectedCuid === prevSelectedRef.current)
4726
+ return;
4727
+ prevSelectedRef.current = selectedCuid;
4728
+ if (selectedCuid == null)
4729
+ return;
4730
+ let repCuid = selectedCuid;
4731
+ for (const item of flatItems) {
4732
+ if (item.group.rest.some((e) => e.cuid === selectedCuid)) {
4733
+ repCuid = item.group.representative.cuid;
4734
+ break;
4735
+ }
4736
+ }
4737
+ containerRef.current?.querySelector(`[data-cuid="${repCuid}"]`)?.scrollIntoView({ block: "nearest" });
4738
+ }, [selectedCuid, flatItems]);
4739
+ if (groups.length === 0) {
4740
+ return /* @__PURE__ */ jsxDEV20("div", {
4741
+ style,
4742
+ children: /* @__PURE__ */ jsxDEV20("div", {
4743
+ style: { padding: "24px", textAlign: "center", color: DEVTOOL_COLOR_TEXT_MUTED },
4744
+ children: "No actions recorded yet"
4745
+ }, undefined, false, undefined, this)
4746
+ }, undefined, false, undefined, this);
4747
+ }
4748
+ return /* @__PURE__ */ jsxDEV20("div", {
4749
+ ref: containerRef,
4750
+ style,
4751
+ children: flatItems.map((item) => {
4752
+ const key = getFlatItemKey(item);
4753
+ const { group } = item;
4754
+ return /* @__PURE__ */ jsxDEV20("div", {
4755
+ style: {
4756
+ borderBottom: `1px solid ${DEVTOOL_LIST_GROUP_DIVIDER}`,
4757
+ position: "relative",
4758
+ overflow: "hidden"
4759
+ },
4760
+ children: [
4761
+ /* @__PURE__ */ jsxDEV20("div", {
4762
+ style: {
4763
+ position: "absolute",
4764
+ inset: 0,
4765
+ pointerEvents: "none",
4766
+ background: "linear-gradient(90deg, transparent 0%, rgba(148, 210, 255, 0.13) 50%, transparent 100%)",
4767
+ animation: "__nice-action-shine 0.65s ease-out forwards"
4768
+ }
4769
+ }, group.representative.cuid, false, undefined, this),
4770
+ /* @__PURE__ */ jsxDEV20(ActionEntryRow, {
4771
+ entry: group.representative,
4772
+ isSelected: selectedCuid === group.representative.cuid || group.rest.some((e) => e.cuid === selectedCuid),
4773
+ isLatest: item.groupIndex === 0,
4774
+ latestTime,
4775
+ childEntries: getGroupChildEntries(group, childEntriesMap),
4776
+ breakReasons: item.breakReasons,
4777
+ groupEntries: group.rest.length > 0 ? [group.representative, ...group.rest] : undefined,
4778
+ selectedGroupCuid: selectedCuid,
4779
+ onSelectGroupEntry: (cuid) => onSubClick(cuid, selectedCuid === cuid),
4780
+ onClick: () => onGroupClick(group)
4781
+ }, undefined, false, undefined, this)
4782
+ ]
4783
+ }, key, true, undefined, this);
4784
+ })
4785
+ }, undefined, false, undefined, this);
4786
+ }
4787
+
4613
4788
  // src/devtools/browser/components/PanelChrome.tsx
4614
- import { jsxDEV as jsxDEV18 } from "react/jsx-dev-runtime";
4789
+ import { jsxDEV as jsxDEV21 } from "react/jsx-dev-runtime";
4615
4790
  var DOCKED_SIZE_MIN = 140;
4616
4791
  var POSITION_GRID = [
4617
4792
  ["top-left", "dock-top", "top-right"],
@@ -4635,7 +4810,7 @@ function PanelHeader({
4635
4810
  onClose,
4636
4811
  onClear
4637
4812
  }) {
4638
- return /* @__PURE__ */ jsxDEV18("div", {
4813
+ return /* @__PURE__ */ jsxDEV21("div", {
4639
4814
  style: {
4640
4815
  display: "flex",
4641
4816
  alignItems: "center",
@@ -4646,18 +4821,18 @@ function PanelHeader({
4646
4821
  flexShrink: 0
4647
4822
  },
4648
4823
  children: [
4649
- /* @__PURE__ */ jsxDEV18("span", {
4824
+ /* @__PURE__ */ jsxDEV21("span", {
4650
4825
  style: { color: DEVTOOL_COLOR_SEMANTIC_SYSTEM, fontWeight: "bold", fontSize: "11px" },
4651
4826
  children: "⚡ nice-action devtools"
4652
4827
  }, undefined, false, undefined, this),
4653
- /* @__PURE__ */ jsxDEV18("div", {
4828
+ /* @__PURE__ */ jsxDEV21("div", {
4654
4829
  style: { display: "flex", gap: "10px", alignItems: "center" },
4655
4830
  children: [
4656
- /* @__PURE__ */ jsxDEV18(PositionPicker, {
4831
+ /* @__PURE__ */ jsxDEV21(PositionPicker, {
4657
4832
  position,
4658
4833
  onChange: onPositionChange
4659
4834
  }, undefined, false, undefined, this),
4660
- onClear != null && /* @__PURE__ */ jsxDEV18("button", {
4835
+ onClear != null && /* @__PURE__ */ jsxDEV21("button", {
4661
4836
  onClick: onClear,
4662
4837
  style: {
4663
4838
  background: "none",
@@ -4669,7 +4844,7 @@ function PanelHeader({
4669
4844
  },
4670
4845
  children: "clear"
4671
4846
  }, undefined, false, undefined, this),
4672
- /* @__PURE__ */ jsxDEV18("button", {
4847
+ /* @__PURE__ */ jsxDEV21("button", {
4673
4848
  onClick: onClose,
4674
4849
  style: {
4675
4850
  background: "none",
@@ -4691,18 +4866,18 @@ function PositionPicker({
4691
4866
  position,
4692
4867
  onChange
4693
4868
  }) {
4694
- return /* @__PURE__ */ jsxDEV18("div", {
4869
+ return /* @__PURE__ */ jsxDEV21("div", {
4695
4870
  title: "Move / dock panel",
4696
4871
  style: { display: "grid", gridTemplateColumns: "repeat(3, 9px)", gap: "2px", padding: "2px" },
4697
4872
  children: POSITION_GRID.flat().map((pos) => {
4698
4873
  if (pos == null)
4699
- return /* @__PURE__ */ jsxDEV18("div", {
4874
+ return /* @__PURE__ */ jsxDEV21("div", {
4700
4875
  style: { width: "9px", height: "9px" }
4701
4876
  }, "center-empty", false, undefined, this);
4702
4877
  const isDock = pos.startsWith("dock-");
4703
4878
  const isTopBottom = pos === "dock-top" || pos === "dock-bottom";
4704
4879
  const isActive = pos === position;
4705
- return /* @__PURE__ */ jsxDEV18("div", {
4880
+ return /* @__PURE__ */ jsxDEV21("div", {
4706
4881
  title: pos,
4707
4882
  onClick: () => onChange(pos),
4708
4883
  style: {
@@ -4713,7 +4888,7 @@ function PositionPicker({
4713
4888
  justifyContent: "center",
4714
4889
  cursor: "pointer"
4715
4890
  },
4716
- children: /* @__PURE__ */ jsxDEV18("div", {
4891
+ children: /* @__PURE__ */ jsxDEV21("div", {
4717
4892
  style: {
4718
4893
  width: isDock ? isTopBottom ? "9px" : "3px" : "7px",
4719
4894
  height: isDock ? isTopBottom ? "3px" : "9px" : "7px",
@@ -4749,7 +4924,7 @@ function ResizeHandle({
4749
4924
  window.addEventListener("mouseup", onUp);
4750
4925
  };
4751
4926
  const edgeStyle = dockSide === "bottom" ? { top: 0, left: 0, right: 0, height: "5px", cursor: "ns-resize" } : dockSide === "top" ? { bottom: 0, left: 0, right: 0, height: "5px", cursor: "ns-resize" } : dockSide === "right" ? { top: 0, bottom: 0, left: 0, width: "5px", cursor: "ew-resize" } : { top: 0, bottom: 0, right: 0, width: "5px", cursor: "ew-resize" };
4752
- return /* @__PURE__ */ jsxDEV18("div", {
4927
+ return /* @__PURE__ */ jsxDEV21("div", {
4753
4928
  onMouseDown,
4754
4929
  style: {
4755
4930
  position: "absolute",
@@ -4761,7 +4936,7 @@ function ResizeHandle({
4761
4936
  }
4762
4937
 
4763
4938
  // src/devtools/browser/NiceActionDevtools.tsx
4764
- import { jsxDEV as jsxDEV19, Fragment as Fragment9 } from "react/jsx-dev-runtime";
4939
+ import { jsxDEV as jsxDEV22, Fragment as Fragment10 } from "react/jsx-dev-runtime";
4765
4940
  if (typeof document !== "undefined" && !document.getElementById("__nice-action-devtools-styles")) {
4766
4941
  const style = document.createElement("style");
4767
4942
  style.id = "__nice-action-devtools-styles";
@@ -4854,7 +5029,7 @@ function groupEntries(entries) {
4854
5029
  }
4855
5030
  function NiceActionDevtools(props) {
4856
5031
  if (false) {}
4857
- return /* @__PURE__ */ jsxDEV19(NiceActionDevtools_Panel, {
5032
+ return /* @__PURE__ */ jsxDEV22(NiceActionDevtools_Panel, {
4858
5033
  ...props
4859
5034
  }, undefined, false, undefined, this);
4860
5035
  }
@@ -4866,13 +5041,13 @@ function NiceActionDevtools_Panel({
4866
5041
  const [prefs, setPrefsRaw] = useState9(() => readPrefs(defaultPosition, initialOpen));
4867
5042
  const [entries, setEntries] = useState9([]);
4868
5043
  const [selectedCuid, setSelectedCuid] = useState9(null);
4869
- useEffect3(() => core.subscribe(setEntries), [core]);
4870
- const groups = useMemo2(() => {
5044
+ useEffect4(() => core.subscribe(setEntries), [core]);
5045
+ const groups = useMemo3(() => {
4871
5046
  const byCuid = new Map(entries.map((e) => [e.cuid, e]));
4872
5047
  const roots = entries.filter((e) => e.status !== "running" && (e.parentCuid == null || !byCuid.has(e.parentCuid)));
4873
5048
  return groupEntries(roots);
4874
5049
  }, [entries]);
4875
- const childEntriesMap = useMemo2(() => {
5050
+ const childEntriesMap = useMemo3(() => {
4876
5051
  const map = new Map;
4877
5052
  for (const entry of entries) {
4878
5053
  if (entry.parentCuid == null)
@@ -4908,7 +5083,7 @@ function NiceActionDevtools_Panel({
4908
5083
  const dockedSize = isHorizDock ? dockedHeight : dockedWidth;
4909
5084
  const selectedEntry = selectedCuid != null ? entries.find((e) => e.cuid === selectedCuid) : null;
4910
5085
  const runningCount = entries.filter((e) => e.status === "running").length;
4911
- useEffect3(() => {
5086
+ useEffect4(() => {
4912
5087
  const sides = ["top", "bottom", "left", "right"];
4913
5088
  const clearAll = () => {
4914
5089
  sides.forEach((s) => {
@@ -4947,7 +5122,7 @@ function NiceActionDevtools_Panel({
4947
5122
  fontSize: "12px"
4948
5123
  };
4949
5124
  if (!isOpen) {
4950
- return /* @__PURE__ */ jsxDEV19("button", {
5125
+ return /* @__PURE__ */ jsxDEV22("button", {
4951
5126
  onClick: () => setPrefs({ isOpen: true }),
4952
5127
  style: {
4953
5128
  ...baseStyle,
@@ -4962,7 +5137,7 @@ function NiceActionDevtools_Panel({
4962
5137
  },
4963
5138
  children: [
4964
5139
  "⚡ actions",
4965
- runningCount > 0 && /* @__PURE__ */ jsxDEV19("span", {
5140
+ runningCount > 0 && /* @__PURE__ */ jsxDEV22("span", {
4966
5141
  style: {
4967
5142
  marginLeft: "6px",
4968
5143
  color: DEVTOOL_COLOR_SEMANTIC_SYSTEM,
@@ -5035,16 +5210,16 @@ function NiceActionDevtools_Panel({
5035
5210
  },
5036
5211
  childEntriesMap
5037
5212
  };
5038
- return /* @__PURE__ */ jsxDEV19("div", {
5213
+ return /* @__PURE__ */ jsxDEV22("div", {
5039
5214
  id: "__nice-action-devtools-panel",
5040
5215
  style: panelStyle,
5041
5216
  children: [
5042
- dockSide != null && /* @__PURE__ */ jsxDEV19(ResizeHandle, {
5217
+ dockSide != null && /* @__PURE__ */ jsxDEV22(ResizeHandle, {
5043
5218
  dockSide,
5044
5219
  dockedSize,
5045
5220
  onChange: (size) => setPrefs(isHorizDock ? { dockedHeight: size } : { dockedWidth: size })
5046
5221
  }, undefined, false, undefined, this),
5047
- /* @__PURE__ */ jsxDEV19(PanelHeader, {
5222
+ /* @__PURE__ */ jsxDEV22(PanelHeader, {
5048
5223
  position,
5049
5224
  onPositionChange: (p) => setPrefs({ position: p }),
5050
5225
  onClose: () => setPrefs({ isOpen: false }),
@@ -5053,17 +5228,17 @@ function NiceActionDevtools_Panel({
5053
5228
  setSelectedCuid(null);
5054
5229
  } : undefined
5055
5230
  }, undefined, false, undefined, this),
5056
- isHorizDock ? /* @__PURE__ */ jsxDEV19("div", {
5231
+ isHorizDock ? /* @__PURE__ */ jsxDEV22("div", {
5057
5232
  style: { flex: 1, display: "flex", overflow: "hidden" },
5058
5233
  children: [
5059
- /* @__PURE__ */ jsxDEV19("div", {
5234
+ /* @__PURE__ */ jsxDEV22("div", {
5060
5235
  style: { position: "relative", width: "340px", flexShrink: 0 },
5061
5236
  children: [
5062
- /* @__PURE__ */ jsxDEV19(ActionList, {
5237
+ /* @__PURE__ */ jsxDEV22(ActionList, {
5063
5238
  ...virtualListProps,
5064
5239
  style: { width: "100%", height: "100%", overflowY: "auto" }
5065
5240
  }, undefined, false, undefined, this),
5066
- /* @__PURE__ */ jsxDEV19("div", {
5241
+ /* @__PURE__ */ jsxDEV22("div", {
5067
5242
  style: {
5068
5243
  position: "absolute",
5069
5244
  top: 0,
@@ -5076,7 +5251,7 @@ function NiceActionDevtools_Panel({
5076
5251
  }, undefined, false, undefined, this)
5077
5252
  ]
5078
5253
  }, undefined, true, undefined, this),
5079
- /* @__PURE__ */ jsxDEV19("div", {
5254
+ /* @__PURE__ */ jsxDEV22("div", {
5080
5255
  style: {
5081
5256
  flex: 1,
5082
5257
  display: "flex",
@@ -5085,12 +5260,12 @@ function NiceActionDevtools_Panel({
5085
5260
  borderLeft: `1px solid ${DEVTOOL_PANEL_DIVIDER_BORDER}`,
5086
5261
  boxShadow: "inset 18px 0 36px -14px rgba(0,0,0,0.8)"
5087
5262
  },
5088
- children: selectedEntry != null ? /* @__PURE__ */ jsxDEV19(ActionDetailPanel, {
5263
+ children: selectedEntry != null ? /* @__PURE__ */ jsxDEV22(ActionDetailPanel, {
5089
5264
  entry: selectedEntry,
5090
5265
  parent: selectedEntryParent,
5091
5266
  childEntries: selectedEntryChildren,
5092
5267
  onSelectEntry: (cuid) => setSelectedCuid(cuid)
5093
- }, selectedEntry.cuid, false, undefined, this) : /* @__PURE__ */ jsxDEV19("div", {
5268
+ }, selectedEntry.cuid, false, undefined, this) : /* @__PURE__ */ jsxDEV22("div", {
5094
5269
  style: {
5095
5270
  padding: "24px",
5096
5271
  textAlign: "center",
@@ -5101,16 +5276,16 @@ function NiceActionDevtools_Panel({
5101
5276
  }, undefined, false, undefined, this)
5102
5277
  }, undefined, false, undefined, this)
5103
5278
  ]
5104
- }, undefined, true, undefined, this) : /* @__PURE__ */ jsxDEV19(Fragment9, {
5279
+ }, undefined, true, undefined, this) : /* @__PURE__ */ jsxDEV22(Fragment10, {
5105
5280
  children: [
5106
- /* @__PURE__ */ jsxDEV19("div", {
5281
+ /* @__PURE__ */ jsxDEV22("div", {
5107
5282
  style: { position: "relative", flex: 1, minHeight: "80px" },
5108
5283
  children: [
5109
- /* @__PURE__ */ jsxDEV19(ActionList, {
5284
+ /* @__PURE__ */ jsxDEV22(ActionList, {
5110
5285
  ...virtualListProps,
5111
5286
  style: { overflowY: "auto", height: "100%" }
5112
5287
  }, undefined, false, undefined, this),
5113
- selectedEntry != null && /* @__PURE__ */ jsxDEV19("div", {
5288
+ selectedEntry != null && /* @__PURE__ */ jsxDEV22("div", {
5114
5289
  style: {
5115
5290
  position: "absolute",
5116
5291
  bottom: 0,
@@ -5123,7 +5298,7 @@ function NiceActionDevtools_Panel({
5123
5298
  }, undefined, false, undefined, this)
5124
5299
  ]
5125
5300
  }, undefined, true, undefined, this),
5126
- selectedEntry != null && /* @__PURE__ */ jsxDEV19("div", {
5301
+ selectedEntry != null && /* @__PURE__ */ jsxDEV22("div", {
5127
5302
  style: {
5128
5303
  flexShrink: 0,
5129
5304
  maxHeight: "55%",
@@ -5133,7 +5308,7 @@ function NiceActionDevtools_Panel({
5133
5308
  borderTop: `1px solid ${DEVTOOL_PANEL_DIVIDER_BORDER}`,
5134
5309
  boxShadow: "inset 0 18px 36px -14px rgba(0,0,0,0.8)"
5135
5310
  },
5136
- children: /* @__PURE__ */ jsxDEV19(ActionDetailPanel, {
5311
+ children: /* @__PURE__ */ jsxDEV22(ActionDetailPanel, {
5137
5312
  entry: selectedEntry,
5138
5313
  parent: selectedEntryParent,
5139
5314
  childEntries: selectedEntryChildren,
@@ -5145,119 +5320,6 @@ function NiceActionDevtools_Panel({
5145
5320
  ]
5146
5321
  }, undefined, true, undefined, this);
5147
5322
  }
5148
- function getBreakReasons(current, previous) {
5149
- const reasons = [];
5150
- const inputChanged = current.inputHash != null && previous.inputHash != null ? current.inputHash !== previous.inputHash : safeStringify(current.input, 0) !== safeStringify(previous.input, 0);
5151
- if (inputChanged)
5152
- reasons.push("new input");
5153
- const outputChanged = current.outputHash != null && previous.outputHash != null && current.outputHash !== previous.outputHash;
5154
- if (outputChanged)
5155
- reasons.push("new output");
5156
- return reasons;
5157
- }
5158
- function getGroupChildEntries(group, childEntriesMap) {
5159
- const seen = new Set;
5160
- const result = [];
5161
- for (const e of [group.representative, ...group.rest]) {
5162
- for (const child of childEntriesMap.get(e.cuid) ?? []) {
5163
- if (!seen.has(child.actionId)) {
5164
- seen.add(child.actionId);
5165
- result.push(child);
5166
- }
5167
- }
5168
- }
5169
- return result.length > 0 ? result.sort((a, b) => a.startTime - b.startTime) : undefined;
5170
- }
5171
- function getFlatItemKey(item) {
5172
- const oldestCuid = item.group.rest[item.group.rest.length - 1]?.cuid ?? item.group.representative.cuid;
5173
- return `g:${oldestCuid}`;
5174
- }
5175
- function ActionList({
5176
- groups,
5177
- selectedCuid,
5178
- onGroupClick,
5179
- onSubClick,
5180
- childEntriesMap,
5181
- style
5182
- }) {
5183
- const containerRef = useRef2(null);
5184
- const latestTime = groups[0]?.representative.startTime;
5185
- const flatItems = useMemo2(() => {
5186
- return groups.map((group, gi) => {
5187
- const prevGroup = groups[gi + 1];
5188
- let breakReasons;
5189
- if (prevGroup != null && prevGroup.representative.actionId === group.representative.actionId && prevGroup.representative.domain === group.representative.domain) {
5190
- const reasons = getBreakReasons(group.representative, prevGroup.representative);
5191
- if (reasons.length > 0)
5192
- breakReasons = reasons;
5193
- }
5194
- return { group, groupIndex: gi, breakReasons };
5195
- });
5196
- }, [groups]);
5197
- const prevSelectedRef = useRef2(selectedCuid);
5198
- useEffect3(() => {
5199
- if (selectedCuid === prevSelectedRef.current)
5200
- return;
5201
- prevSelectedRef.current = selectedCuid;
5202
- if (selectedCuid == null)
5203
- return;
5204
- let repCuid = selectedCuid;
5205
- for (const item of flatItems) {
5206
- if (item.group.rest.some((e) => e.cuid === selectedCuid)) {
5207
- repCuid = item.group.representative.cuid;
5208
- break;
5209
- }
5210
- }
5211
- containerRef.current?.querySelector(`[data-cuid="${repCuid}"]`)?.scrollIntoView({ block: "nearest" });
5212
- }, [selectedCuid, flatItems]);
5213
- if (groups.length === 0) {
5214
- return /* @__PURE__ */ jsxDEV19("div", {
5215
- style,
5216
- children: /* @__PURE__ */ jsxDEV19("div", {
5217
- style: { padding: "24px", textAlign: "center", color: DEVTOOL_COLOR_TEXT_MUTED },
5218
- children: "No actions recorded yet"
5219
- }, undefined, false, undefined, this)
5220
- }, undefined, false, undefined, this);
5221
- }
5222
- return /* @__PURE__ */ jsxDEV19("div", {
5223
- ref: containerRef,
5224
- style,
5225
- children: flatItems.map((item) => {
5226
- const key = getFlatItemKey(item);
5227
- const { group } = item;
5228
- return /* @__PURE__ */ jsxDEV19("div", {
5229
- style: {
5230
- borderBottom: `1px solid ${DEVTOOL_LIST_GROUP_DIVIDER}`,
5231
- position: "relative",
5232
- overflow: "hidden"
5233
- },
5234
- children: [
5235
- /* @__PURE__ */ jsxDEV19("div", {
5236
- style: {
5237
- position: "absolute",
5238
- inset: 0,
5239
- pointerEvents: "none",
5240
- background: "linear-gradient(90deg, transparent 0%, rgba(148, 210, 255, 0.13) 50%, transparent 100%)",
5241
- animation: "__nice-action-shine 0.65s ease-out forwards"
5242
- }
5243
- }, group.representative.cuid, false, undefined, this),
5244
- /* @__PURE__ */ jsxDEV19(ActionEntryRow, {
5245
- entry: group.representative,
5246
- isSelected: selectedCuid === group.representative.cuid || group.rest.some((e) => e.cuid === selectedCuid),
5247
- isLatest: item.groupIndex === 0,
5248
- latestTime,
5249
- childEntries: getGroupChildEntries(group, childEntriesMap),
5250
- breakReasons: item.breakReasons,
5251
- groupEntries: group.rest.length > 0 ? [group.representative, ...group.rest] : undefined,
5252
- selectedGroupCuid: selectedCuid,
5253
- onSelectGroupEntry: (cuid) => onSubClick(cuid, selectedCuid === cuid),
5254
- onClick: () => onGroupClick(group)
5255
- }, undefined, false, undefined, this)
5256
- ]
5257
- }, key, true, undefined, this);
5258
- })
5259
- }, undefined, false, undefined, this);
5260
- }
5261
5323
  export {
5262
5324
  NiceActionDevtools,
5263
5325
  ActionDevtoolsCore
@@ -1,8 +1,12 @@
1
- import type { TDevtoolsPosition } from "../core/ActionDevtools.types";
1
+ import type { IDevtoolsActionEntry, TDevtoolsPosition } from "../core/ActionDevtools.types";
2
2
  import type { ActionDevtoolsCore } from "../core/ActionDevtoolsCore";
3
3
  export interface INiceActionDevtoolsProps {
4
4
  core: ActionDevtoolsCore;
5
5
  position?: TDevtoolsPosition;
6
6
  initialOpen?: boolean;
7
7
  }
8
+ export interface IEntryGroup {
9
+ representative: IDevtoolsActionEntry;
10
+ rest: IDevtoolsActionEntry[];
11
+ }
8
12
  export declare function NiceActionDevtools(props: INiceActionDevtoolsProps): import("react/jsx-runtime").JSX.Element | null;
@@ -4,7 +4,7 @@ import { type ESemanticThing } from "../../core/devtools_colors";
4
4
  import { ESize } from "../ui_util/size";
5
5
  import { type ITooltipConfig } from "./Tooltip";
6
6
  interface IIconProps {
7
- icon: LucideIcon;
7
+ icon: LucideIcon | LucideIcon[];
8
8
  color: ESemanticThing;
9
9
  size?: ESize;
10
10
  subtle?: boolean;
@@ -1,4 +1,5 @@
1
1
  import type { IDevtoolsActionEntry } from "../../../core/ActionDevtools.types";
2
+ import { EBreakGroupReason } from "./action_list.types";
2
3
  export declare function ActionEntryRow({ entry, isSelected, onClick, isLatest, latestTime, childEntries, breakReasons, groupEntries, selectedGroupCuid, onSelectGroupEntry, }: {
3
4
  entry: IDevtoolsActionEntry;
4
5
  isSelected: boolean;
@@ -6,7 +7,7 @@ export declare function ActionEntryRow({ entry, isSelected, onClick, isLatest, l
6
7
  isLatest?: boolean;
7
8
  latestTime?: number;
8
9
  childEntries?: IDevtoolsActionEntry[];
9
- breakReasons?: string[];
10
+ breakReasons: EBreakGroupReason[];
10
11
  groupEntries?: IDevtoolsActionEntry[];
11
12
  selectedGroupCuid?: string | null;
12
13
  onSelectGroupEntry?: (cuid: string) => void;
@@ -0,0 +1,11 @@
1
+ import type { IDevtoolsActionEntry } from "../../../core/ActionDevtools.types";
2
+ import { ESize } from "../../ui_util/size";
3
+ import { EBreakGroupReason } from "./action_list.types";
4
+ interface IActionInputAndOutputChipProps {
5
+ entry: IDevtoolsActionEntry;
6
+ breakReasons: EBreakGroupReason[];
7
+ subtle?: boolean;
8
+ size?: ESize;
9
+ }
10
+ export declare const ActionInputAndOutputChip: ({ entry, breakReasons, subtle, size, }: IActionInputAndOutputChipProps) => import("react/jsx-runtime").JSX.Element;
11
+ export {};
@@ -0,0 +1,10 @@
1
+ import type { IDevtoolsActionEntry } from "../../../server";
2
+ import type { IEntryGroup } from "../../NiceActionDevtools";
3
+ export declare function ActionList({ groups, selectedCuid, onGroupClick, onSubClick, childEntriesMap, style, }: {
4
+ groups: IEntryGroup[];
5
+ selectedCuid: string | null;
6
+ onGroupClick: (group: IEntryGroup) => void;
7
+ onSubClick: (cuid: string, isSelected: boolean) => void;
8
+ childEntriesMap: Map<string, IDevtoolsActionEntry[]>;
9
+ style?: React.CSSProperties;
10
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,6 @@
1
+ export declare const _IoTooltipContent: ({ value }: {
2
+ value: unknown;
3
+ }) => import("react/jsx-runtime").JSX.Element;
4
+ export declare function IoTooltipContent({ value }: {
5
+ value: unknown;
6
+ }): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,4 @@
1
+ export declare enum EBreakGroupReason {
2
+ new_input = "new_input",
3
+ new_output = "new_output"
4
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nice-code/action",
3
- "version": "0.2.19",
3
+ "version": "0.3.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "exports": {
@@ -44,9 +44,9 @@
44
44
  "build-types": "tsc --project tsconfig.build.json"
45
45
  },
46
46
  "dependencies": {
47
- "@nice-code/common-errors": "0.2.19",
48
- "@nice-code/error": "0.2.19",
49
- "@nice-code/util": "0.2.19",
47
+ "@nice-code/common-errors": "0.3.0",
48
+ "@nice-code/error": "0.3.0",
49
+ "@nice-code/util": "0.3.0",
50
50
  "@standard-schema/spec": "^1.1.0",
51
51
  "@tanstack/react-virtual": "^3.13.26",
52
52
  "http-status-codes": "^2.3.0",