@timeax/service-builder 0.0.11 → 0.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -6918,27 +6918,62 @@ var Header = ({ menu = [] }) => {
6918
6918
  var header_default = Header;
6919
6919
 
6920
6920
  // src/components/ui/scroll-area.tsx
6921
- import * as React11 from "react";
6922
- import { jsx as jsx27 } from "react/jsx-runtime";
6923
- var ScrollArea = React11.forwardRef(function ScrollArea2({ className, children, ...props }, ref) {
6924
- return /* @__PURE__ */ jsx27("div", { "data-slot": "scroll-area", ref, className: cn("relative size-full overflow-auto", className), ...props, children });
6925
- });
6926
- var ScrollBar = React11.forwardRef(function ScrollBar2({ className, orientation = "vertical", ...props }, ref) {
6921
+ import "react";
6922
+ import { ScrollArea as ScrollAreaPrimitive } from "radix-ui";
6923
+ import { jsx as jsx27, jsxs as jsxs20 } from "react/jsx-runtime";
6924
+ function ScrollArea({
6925
+ className,
6926
+ children,
6927
+ ...props
6928
+ }) {
6929
+ return /* @__PURE__ */ jsxs20(
6930
+ ScrollAreaPrimitive.Root,
6931
+ {
6932
+ "data-slot": "scroll-area",
6933
+ className: cn("relative", className),
6934
+ ...props,
6935
+ children: [
6936
+ /* @__PURE__ */ jsx27(
6937
+ ScrollAreaPrimitive.Viewport,
6938
+ {
6939
+ "data-slot": "scroll-area-viewport",
6940
+ className: "size-full rounded-[inherit] transition-[color,box-shadow] outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1",
6941
+ children
6942
+ }
6943
+ ),
6944
+ /* @__PURE__ */ jsx27(ScrollBar, {}),
6945
+ /* @__PURE__ */ jsx27(ScrollAreaPrimitive.Corner, {})
6946
+ ]
6947
+ }
6948
+ );
6949
+ }
6950
+ function ScrollBar({
6951
+ className,
6952
+ orientation = "vertical",
6953
+ ...props
6954
+ }) {
6927
6955
  return /* @__PURE__ */ jsx27(
6928
- "div",
6956
+ ScrollAreaPrimitive.ScrollAreaScrollbar,
6929
6957
  {
6930
6958
  "data-slot": "scroll-area-scrollbar",
6931
- ref,
6932
- "aria-hidden": "true",
6959
+ orientation,
6933
6960
  className: cn(
6934
- "pointer-events-none absolute opacity-0",
6935
- orientation === "vertical" ? "right-0 top-0 h-full w-0" : "bottom-0 left-0 h-0 w-full",
6961
+ "flex touch-none p-px transition-colors select-none",
6962
+ orientation === "vertical" && "h-full w-2.5 border-l border-l-transparent",
6963
+ orientation === "horizontal" && "h-2.5 flex-col border-t border-t-transparent",
6936
6964
  className
6937
6965
  ),
6938
- ...props
6966
+ ...props,
6967
+ children: /* @__PURE__ */ jsx27(
6968
+ ScrollAreaPrimitive.ScrollAreaThumb,
6969
+ {
6970
+ "data-slot": "scroll-area-thumb",
6971
+ className: "relative flex-1 rounded-full bg-border"
6972
+ }
6973
+ )
6939
6974
  }
6940
6975
  );
6941
- });
6976
+ }
6942
6977
 
6943
6978
  // src/panels/left/assets/index.tsx
6944
6979
  import { useInputs } from "@timeax/digital-service-engine/react";
@@ -6946,7 +6981,7 @@ import { useWorkspace as useWorkspace8 } from "@timeax/digital-service-engine/wo
6946
6981
  import { useMemo as useMemo11, useState as useState12 } from "react";
6947
6982
  import { CiSearch } from "react-icons/ci";
6948
6983
  import { LuBox, LuShapes } from "react-icons/lu";
6949
- import { jsx as jsx28, jsxs as jsxs20 } from "react/jsx-runtime";
6984
+ import { jsx as jsx28, jsxs as jsxs21 } from "react/jsx-runtime";
6950
6985
  function toTitle(value) {
6951
6986
  return value.split(/[-_:]/g).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
6952
6987
  }
@@ -6978,8 +7013,8 @@ function AssetsPanel() {
6978
7013
  const filteredTemplates = lower ? templates2.filter(
6979
7014
  (item) => item.name.toLowerCase().includes(lower) || String(item.kind ?? "").toLowerCase().includes(lower)
6980
7015
  ) : templates2;
6981
- return /* @__PURE__ */ jsxs20("div", { className: "flex h-full min-h-0 flex-col rounded-2xl border border-slate-200/80 bg-white/90 p-3 shadow-sm dark:border-slate-800 dark:bg-slate-950/80", children: [
6982
- /* @__PURE__ */ jsxs20("label", { className: "relative", children: [
7016
+ return /* @__PURE__ */ jsxs21("div", { className: "flex h-full min-h-0 flex-col rounded-2xl border border-slate-200/80 bg-white/90 p-3 shadow-sm dark:border-slate-800 dark:bg-slate-950/80", children: [
7017
+ /* @__PURE__ */ jsxs21("label", { className: "relative", children: [
6983
7018
  /* @__PURE__ */ jsx28(CiSearch, { className: "pointer-events-none absolute top-1/2 left-3 -translate-y-1/2 text-slate-400" }),
6984
7019
  /* @__PURE__ */ jsx28(
6985
7020
  "input",
@@ -6991,13 +7026,13 @@ function AssetsPanel() {
6991
7026
  }
6992
7027
  )
6993
7028
  ] }),
6994
- /* @__PURE__ */ jsxs20(ScrollArea, { className: "mt-3 min-h-0 flex-1 pr-1", children: [
6995
- /* @__PURE__ */ jsxs20("section", { children: [
6996
- /* @__PURE__ */ jsxs20("h4", { className: "mb-2 flex items-center gap-2 text-xs font-semibold tracking-wide text-slate-500 uppercase dark:text-slate-400", children: [
7029
+ /* @__PURE__ */ jsxs21(ScrollArea, { className: "mt-3 min-h-0 flex-1 pr-1", children: [
7030
+ /* @__PURE__ */ jsxs21("section", { children: [
7031
+ /* @__PURE__ */ jsxs21("h4", { className: "mb-2 flex items-center gap-2 text-xs font-semibold tracking-wide text-slate-500 uppercase dark:text-slate-400", children: [
6997
7032
  /* @__PURE__ */ jsx28(LuShapes, {}),
6998
7033
  "Built-in Inputs"
6999
7034
  ] }),
7000
- /* @__PURE__ */ jsx28("div", { className: "grid grid-cols-2 gap-2", children: filteredBuiltins.length ? filteredBuiltins.map((item) => /* @__PURE__ */ jsxs20(
7035
+ /* @__PURE__ */ jsx28("div", { className: "grid grid-cols-2 gap-2", children: filteredBuiltins.length ? filteredBuiltins.map((item) => /* @__PURE__ */ jsxs21(
7001
7036
  "button",
7002
7037
  {
7003
7038
  type: "button",
@@ -7022,13 +7057,13 @@ function AssetsPanel() {
7022
7057
  item.key
7023
7058
  )) : /* @__PURE__ */ jsx28(EmptyState, { title: "No built-ins", description: "No registry input entries matched your search.", className: "min-h-36" }) })
7024
7059
  ] }),
7025
- /* @__PURE__ */ jsxs20("section", { className: "mt-5", children: [
7026
- /* @__PURE__ */ jsxs20("h4", { className: "mb-2 flex items-center gap-2 text-xs font-semibold tracking-wide text-slate-500 uppercase dark:text-slate-400", children: [
7060
+ /* @__PURE__ */ jsxs21("section", { className: "mt-5", children: [
7061
+ /* @__PURE__ */ jsxs21("h4", { className: "mb-2 flex items-center gap-2 text-xs font-semibold tracking-wide text-slate-500 uppercase dark:text-slate-400", children: [
7027
7062
  /* @__PURE__ */ jsx28(LuBox, {}),
7028
7063
  "Saved Templates"
7029
7064
  ] }),
7030
7065
  /* @__PURE__ */ jsx28(WorkspaceBootInlineNotice, { boot: ws.boot, sections: ["templates"], className: "mb-3" }),
7031
- /* @__PURE__ */ jsx28("div", { className: "grid grid-cols-2 gap-2", children: filteredTemplates.length ? filteredTemplates.map((item) => /* @__PURE__ */ jsxs20(
7066
+ /* @__PURE__ */ jsx28("div", { className: "grid grid-cols-2 gap-2", children: filteredTemplates.length ? filteredTemplates.map((item) => /* @__PURE__ */ jsxs21(
7032
7067
  "button",
7033
7068
  {
7034
7069
  type: "button",
@@ -8238,7 +8273,7 @@ import { VscChevronRight } from "react-icons/vsc";
8238
8273
 
8239
8274
  // src/components/sort-tree/node.tsx
8240
8275
  import * as React21 from "react";
8241
- import { jsx as jsx32, jsxs as jsxs21 } from "react/jsx-runtime";
8276
+ import { jsx as jsx32, jsxs as jsxs22 } from "react/jsx-runtime";
8242
8277
  function Node({ node, matched, isEditing, onCommit, onCancel }) {
8243
8278
  const spanRef = React21.useRef(null);
8244
8279
  React21.useEffect(() => {
@@ -8269,7 +8304,7 @@ function Node({ node, matched, isEditing, onCommit, onCancel }) {
8269
8304
  onCancel?.();
8270
8305
  }
8271
8306
  };
8272
- return /* @__PURE__ */ jsxs21("div", { className: "flex items-center gap-2 truncate " + (matched ? "rounded bg-yellow-200/50 px-1" : ""), children: [
8307
+ return /* @__PURE__ */ jsxs22("div", { className: "flex items-center gap-2 truncate " + (matched ? "rounded bg-yellow-200/50 px-1" : ""), children: [
8273
8308
  node.icon ? /* @__PURE__ */ jsx32("span", { className: "inline-flex items-center", children: node.icon }) : null,
8274
8309
  /* @__PURE__ */ jsx32(
8275
8310
  "span",
@@ -8287,7 +8322,7 @@ function Node({ node, matched, isEditing, onCommit, onCancel }) {
8287
8322
  }
8288
8323
 
8289
8324
  // src/components/sort-tree/node-row.tsx
8290
- import { jsx as jsx33, jsxs as jsxs22 } from "react/jsx-runtime";
8325
+ import { jsx as jsx33, jsxs as jsxs23 } from "react/jsx-runtime";
8291
8326
  function NodeRow({
8292
8327
  node,
8293
8328
  path,
@@ -8318,7 +8353,7 @@ function NodeRow({
8318
8353
  e.stopPropagation();
8319
8354
  callback?.(e);
8320
8355
  };
8321
- return /* @__PURE__ */ jsxs22(
8356
+ return /* @__PURE__ */ jsxs23(
8322
8357
  "div",
8323
8358
  {
8324
8359
  className: ["tree-row", rowClassName || "", isDragging ? "is-dragging" : ""].join(" "),
@@ -8332,7 +8367,7 @@ function NodeRow({
8332
8367
  children: [
8333
8368
  showBinding ? /* @__PURE__ */ jsx33("div", { className: "tree-rail", style: { width: pad }, children: binding.guides.map((g, i) => /* @__PURE__ */ jsx33("span", { className: "tree-col", "data-show": g ? "1" : "0", style: { width: indent } }, i)) }) : /* @__PURE__ */ jsx33("div", { style: { width: pad } }),
8334
8369
  showBinding && /* @__PURE__ */ jsx33("div", { className: "tree-elbow", style: { width: indent } }),
8335
- /* @__PURE__ */ jsx33("div", { className: "min-w-0 flex-1", children: isDragging ? /* @__PURE__ */ jsxs22(
8370
+ /* @__PURE__ */ jsx33("div", { className: "min-w-0 flex-1", children: isDragging ? /* @__PURE__ */ jsxs23(
8336
8371
  "div",
8337
8372
  {
8338
8373
  "aria-hidden": "true",
@@ -8404,7 +8439,7 @@ function NodeRow({
8404
8439
  }
8405
8440
 
8406
8441
  // src/components/sort-tree/internal/render-row.tsx
8407
- import { jsx as jsx34, jsxs as jsxs23 } from "react/jsx-runtime";
8442
+ import { jsx as jsx34, jsxs as jsxs24 } from "react/jsx-runtime";
8408
8443
  var ZONE_HEIGHT = 6;
8409
8444
  function useRenderRow(args) {
8410
8445
  const {
@@ -8495,7 +8530,7 @@ function useRenderRow(args) {
8495
8530
  // fallback
8496
8531
  },
8497
8532
  onMouseDown: (e) => onRowPointerDown(e, rIndex, r.node),
8498
- children: /* @__PURE__ */ jsxs23("div", { className: cn(skinClass, activeClassString), style: { borderRadius: "inherit" }, children: [
8533
+ children: /* @__PURE__ */ jsxs24("div", { className: cn(skinClass, activeClassString), style: { borderRadius: "inherit" }, children: [
8499
8534
  /* @__PURE__ */ jsx34(DropZone, { id: zoneId(r.path, "before"), height: ZONE_HEIGHT, onNativeDrop: handleExternalDrop, disabled: disableZones }),
8500
8535
  /* @__PURE__ */ jsx34(OnDroppableWrap, { id: zoneId(r.path, "on"), onNativeDrop: handleExternalDrop, disabled: disableZones, children: /* @__PURE__ */ jsx34(DraggableRow, { id: draggableId, disabled: disabledDrag, children: /* @__PURE__ */ jsx34(
8501
8536
  NodeRow,
@@ -8603,7 +8638,7 @@ function useRenderRow(args) {
8603
8638
  }
8604
8639
 
8605
8640
  // src/components/sort-tree/sort-tree.tsx
8606
- import { jsx as jsx35, jsxs as jsxs24 } from "react/jsx-runtime";
8641
+ import { jsx as jsx35, jsxs as jsxs25 } from "react/jsx-runtime";
8607
8642
  function SortTreeInner(props, ref) {
8608
8643
  const {
8609
8644
  data,
@@ -8896,7 +8931,7 @@ function SortTreeInner(props, ref) {
8896
8931
  loadChildren
8897
8932
  ]
8898
8933
  );
8899
- return /* @__PURE__ */ jsxs24(DndContext, { sensors, onDragStart: handleDragStart, onDragEnd: handleDragEnd, collisionDetection, children: [
8934
+ return /* @__PURE__ */ jsxs25(DndContext, { sensors, onDragStart: handleDragStart, onDragEnd: handleDragEnd, collisionDetection, children: [
8900
8935
  /* @__PURE__ */ jsx35("div", { className, style, tabIndex: 0, onKeyDown, children: height ? /* @__PURE__ */ jsx35(
8901
8936
  List,
8902
8937
  {
@@ -9252,7 +9287,7 @@ function applyFieldTreeReorder(detail, args) {
9252
9287
  }
9253
9288
 
9254
9289
  // src/panels/left/layers/index.tsx
9255
- import { jsx as jsx38, jsxs as jsxs25 } from "react/jsx-runtime";
9290
+ import { jsx as jsx38, jsxs as jsxs26 } from "react/jsx-runtime";
9256
9291
  function filterTree(nodes, query) {
9257
9292
  if (!query.trim()) return nodes;
9258
9293
  const lower = query.toLowerCase();
@@ -9338,7 +9373,7 @@ var Layers = () => {
9338
9373
  const handleFieldSearchBlur = () => {
9339
9374
  if (!fieldSearch.trim()) setIsFieldSearchOpen(false);
9340
9375
  };
9341
- return /* @__PURE__ */ jsxs25("div", { className: "flex h-full min-h-0 flex-1 flex-col overflow-hidden rounded-2xl border border-slate-200/80 bg-white/90 shadow-sm dark:border-slate-800 dark:bg-slate-950/80", children: [
9376
+ return /* @__PURE__ */ jsxs26("div", { className: "flex h-full min-h-0 flex-1 flex-col overflow-hidden rounded-2xl border border-slate-200/80 bg-white/90 shadow-sm dark:border-slate-800 dark:bg-slate-950/80", children: [
9342
9377
  /* @__PURE__ */ jsx38(
9343
9378
  Panel,
9344
9379
  {
@@ -9347,13 +9382,13 @@ var Layers = () => {
9347
9382
  minHeight: 180,
9348
9383
  maxHeight: 520,
9349
9384
  className: "flex min-h-45 flex-col rounded-none! border-b border-slate-200/80 bg-transparent dark:border-slate-800",
9350
- children: /* @__PURE__ */ jsxs25("section", { className: "flex min-h-0 flex-1 flex-col px-4 pt-4 pb-3", children: [
9351
- /* @__PURE__ */ jsxs25("div", { className: "flex items-start justify-between gap-3", children: [
9352
- /* @__PURE__ */ jsxs25("div", { className: "min-w-0", children: [
9385
+ children: /* @__PURE__ */ jsxs26("section", { className: "flex min-h-0 flex-1 flex-col px-4 pt-4 pb-3", children: [
9386
+ /* @__PURE__ */ jsxs26("div", { className: "flex items-start justify-between gap-3", children: [
9387
+ /* @__PURE__ */ jsxs26("div", { className: "min-w-0", children: [
9353
9388
  /* @__PURE__ */ jsx38("h3", { className: "text-sm font-semibold text-slate-900 dark:text-slate-100", children: "Tag hierarchy" }),
9354
9389
  /* @__PURE__ */ jsx38("p", { className: "mt-1 text-xs text-slate-500 dark:text-slate-400", children: "Structure the visible groups and inheritance tree." })
9355
9390
  ] }),
9356
- /* @__PURE__ */ jsxs25("div", { className: "flex items-center gap-1", children: [
9391
+ /* @__PURE__ */ jsxs26("div", { className: "flex items-center gap-1", children: [
9357
9392
  /* @__PURE__ */ jsx38(
9358
9393
  "button",
9359
9394
  {
@@ -9374,7 +9409,7 @@ var Layers = () => {
9374
9409
  )
9375
9410
  ] })
9376
9411
  ] }),
9377
- /* @__PURE__ */ jsxs25("div", { className: "mt-3 flex min-h-0 flex-1 flex-col gap-3", children: [
9412
+ /* @__PURE__ */ jsxs26("div", { className: "mt-3 flex min-h-0 flex-1 flex-col gap-3", children: [
9378
9413
  isTagSearchOpen || hasTagSearch ? /* @__PURE__ */ jsx38(
9379
9414
  PanelSearch,
9380
9415
  {
@@ -9433,13 +9468,13 @@ var Layers = () => {
9433
9468
  ] })
9434
9469
  }
9435
9470
  ),
9436
- /* @__PURE__ */ jsxs25("section", { className: "flex min-h-0 flex-1 flex-col px-4 pt-3 pb-4", children: [
9437
- /* @__PURE__ */ jsxs25("div", { className: "flex items-start justify-between gap-3", children: [
9438
- /* @__PURE__ */ jsxs25("div", { className: "min-w-0", children: [
9471
+ /* @__PURE__ */ jsxs26("section", { className: "flex min-h-0 flex-1 flex-col px-4 pt-3 pb-4", children: [
9472
+ /* @__PURE__ */ jsxs26("div", { className: "flex items-start justify-between gap-3", children: [
9473
+ /* @__PURE__ */ jsxs26("div", { className: "min-w-0", children: [
9439
9474
  /* @__PURE__ */ jsx38("h3", { className: "text-sm font-semibold text-slate-900 dark:text-slate-100", children: "Fields in view" }),
9440
9475
  /* @__PURE__ */ jsx38("p", { className: "mt-1 text-xs text-slate-500 dark:text-slate-400", children: `Under ${activeTagLabel}` })
9441
9476
  ] }),
9442
- /* @__PURE__ */ jsxs25("div", { className: "flex items-center gap-1", children: [
9477
+ /* @__PURE__ */ jsxs26("div", { className: "flex items-center gap-1", children: [
9443
9478
  /* @__PURE__ */ jsx38(
9444
9479
  "button",
9445
9480
  {
@@ -9481,7 +9516,7 @@ var Layers = () => {
9481
9516
  )
9482
9517
  ] })
9483
9518
  ] }),
9484
- /* @__PURE__ */ jsxs25("div", { className: "mt-3 flex min-h-0 flex-1 flex-col gap-3", children: [
9519
+ /* @__PURE__ */ jsxs26("div", { className: "mt-3 flex min-h-0 flex-1 flex-col gap-3", children: [
9485
9520
  isFieldSearchOpen || hasFieldSearch ? /* @__PURE__ */ jsx38(
9486
9521
  PanelSearch,
9487
9522
  {
@@ -9625,7 +9660,7 @@ function TabsContent({
9625
9660
  // src/panels/left/index.tsx
9626
9661
  import { CiGrid32 } from "react-icons/ci";
9627
9662
  import { MdOutlineLayers } from "react-icons/md";
9628
- import { jsx as jsx40, jsxs as jsxs26 } from "react/jsx-runtime";
9663
+ import { jsx as jsx40, jsxs as jsxs27 } from "react/jsx-runtime";
9629
9664
  var Left = ({ menu }) => {
9630
9665
  const tabClassName = cn(
9631
9666
  "rounded-xl! py-2! shadow-none!",
@@ -9639,15 +9674,15 @@ var Left = ({ menu }) => {
9639
9674
  edges: ["right"],
9640
9675
  maxWidth: 420,
9641
9676
  minWidth: 320,
9642
- children: /* @__PURE__ */ jsxs26("div", { className: "flex h-full flex-col", children: [
9677
+ children: /* @__PURE__ */ jsxs27("div", { className: "flex h-full flex-col", children: [
9643
9678
  /* @__PURE__ */ jsx40(header_default, { menu }),
9644
- /* @__PURE__ */ jsx40("div", { className: "flex min-h-0 flex-1 flex-col gap-2 py-2", children: /* @__PURE__ */ jsxs26(Tabs, { defaultValue: "layers", className: "flex min-h-0 flex-1 flex-col px-3", children: [
9645
- /* @__PURE__ */ jsxs26(TabsList, { className: "grid h-auto grid-cols-2 rounded-2xl bg-slate-100 p-1 dark:bg-slate-900", children: [
9646
- /* @__PURE__ */ jsx40(TabsTrigger, { className: tabClassName, value: "layers", children: /* @__PURE__ */ jsxs26("span", { className: "flex items-center gap-2", children: [
9679
+ /* @__PURE__ */ jsx40("div", { className: "flex min-h-0 flex-1 flex-col gap-2 py-2", children: /* @__PURE__ */ jsxs27(Tabs, { defaultValue: "layers", className: "flex min-h-0 flex-1 flex-col px-3", children: [
9680
+ /* @__PURE__ */ jsxs27(TabsList, { className: "grid h-auto grid-cols-2 rounded-2xl bg-slate-100 p-1 dark:bg-slate-900", children: [
9681
+ /* @__PURE__ */ jsx40(TabsTrigger, { className: tabClassName, value: "layers", children: /* @__PURE__ */ jsxs27("span", { className: "flex items-center gap-2", children: [
9647
9682
  /* @__PURE__ */ jsx40(MdOutlineLayers, {}),
9648
9683
  /* @__PURE__ */ jsx40("span", { children: "Layers" })
9649
9684
  ] }) }),
9650
- /* @__PURE__ */ jsx40(TabsTrigger, { className: tabClassName, value: "assets", children: /* @__PURE__ */ jsxs26("span", { className: "flex items-center gap-2", children: [
9685
+ /* @__PURE__ */ jsx40(TabsTrigger, { className: tabClassName, value: "assets", children: /* @__PURE__ */ jsxs27("span", { className: "flex items-center gap-2", children: [
9651
9686
  /* @__PURE__ */ jsx40(CiGrid32, {}),
9652
9687
  /* @__PURE__ */ jsx40("span", { children: "Assets" })
9653
9688
  ] }) })
@@ -9667,7 +9702,7 @@ import { useMemo as useMemo18 } from "react";
9667
9702
  import { GoChevronDown } from "react-icons/go";
9668
9703
  import { HiOutlineDotsHorizontal } from "react-icons/hi";
9669
9704
  import { PiUserPlusThin } from "react-icons/pi";
9670
- import { jsx as jsx41, jsxs as jsxs27 } from "react/jsx-runtime";
9705
+ import { jsx as jsx41, jsxs as jsxs28 } from "react/jsx-runtime";
9671
9706
  function getInitials(name) {
9672
9707
  const parts = name.trim().split(/\s+/).filter(Boolean);
9673
9708
  if (!parts.length) return "?";
@@ -9729,22 +9764,22 @@ var Users = ({ users, onViewUser, onSetMain, onToggleAdmin, onRemoveUser, onInvi
9729
9764
  return bScore - aScore || a.name.localeCompare(b.name);
9730
9765
  });
9731
9766
  }, [users]);
9732
- return /* @__PURE__ */ jsxs27(Popover, { children: [
9733
- /* @__PURE__ */ jsx41(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs27(
9767
+ return /* @__PURE__ */ jsxs28(Popover, { children: [
9768
+ /* @__PURE__ */ jsx41(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs28(
9734
9769
  "button",
9735
9770
  {
9736
9771
  type: "button",
9737
9772
  className: "flex items-center gap-2 rounded-xl border border-transparent px-1 py-1 transition hover:border-slate-200 hover:bg-white dark:hover:border-slate-800 dark:hover:bg-slate-950",
9738
9773
  children: [
9739
- /* @__PURE__ */ jsxs27("div", { className: "flex -space-x-2 *:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:ring-white dark:*:data-[slot=avatar]:ring-slate-950", children: [
9740
- visibleUsers.map((user) => /* @__PURE__ */ jsxs27("div", { className: "relative", children: [
9741
- /* @__PURE__ */ jsxs27(Avatar, { className: "h-8 w-8", children: [
9774
+ /* @__PURE__ */ jsxs28("div", { className: "flex -space-x-2 *:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:ring-white dark:*:data-[slot=avatar]:ring-slate-950", children: [
9775
+ visibleUsers.map((user) => /* @__PURE__ */ jsxs28("div", { className: "relative", children: [
9776
+ /* @__PURE__ */ jsxs28(Avatar, { className: "h-8 w-8", children: [
9742
9777
  /* @__PURE__ */ jsx41(AvatarImage, { src: user.avatar, alt: user.name }),
9743
9778
  /* @__PURE__ */ jsx41(AvatarFallback, { children: getInitials(user.name) })
9744
9779
  ] }),
9745
9780
  user.isOnline ? /* @__PURE__ */ jsx41("span", { className: "absolute right-0 bottom-0 h-2 w-2 rounded-full bg-emerald-500 ring-2 ring-white dark:ring-slate-950" }) : null
9746
9781
  ] }, user.id)),
9747
- extra > 0 ? /* @__PURE__ */ jsxs27("div", { className: "flex h-8 w-8 items-center justify-center rounded-full border border-dashed border-slate-300 bg-slate-100 text-xs font-medium text-slate-500 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-300", children: [
9782
+ extra > 0 ? /* @__PURE__ */ jsxs28("div", { className: "flex h-8 w-8 items-center justify-center rounded-full border border-dashed border-slate-300 bg-slate-100 text-xs font-medium text-slate-500 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-300", children: [
9748
9783
  "+",
9749
9784
  extra
9750
9785
  ] }) : null
@@ -9753,14 +9788,14 @@ var Users = ({ users, onViewUser, onSetMain, onToggleAdmin, onRemoveUser, onInvi
9753
9788
  ]
9754
9789
  }
9755
9790
  ) }),
9756
- /* @__PURE__ */ jsxs27(PopoverContent, { align: "start", className: "w-[380px] rounded-3xl border-slate-200 bg-white/98 p-0 shadow-2xl dark:border-slate-800 dark:bg-slate-950/98", children: [
9757
- /* @__PURE__ */ jsx41("div", { className: "border-b border-slate-200 px-4 py-4 dark:border-slate-800", children: /* @__PURE__ */ jsxs27("div", { className: "flex items-start justify-between gap-3", children: [
9758
- /* @__PURE__ */ jsxs27("div", { children: [
9791
+ /* @__PURE__ */ jsxs28(PopoverContent, { align: "start", className: "w-[380px] rounded-3xl border-slate-200 bg-white/98 p-0 shadow-2xl dark:border-slate-800 dark:bg-slate-950/98", children: [
9792
+ /* @__PURE__ */ jsx41("div", { className: "border-b border-slate-200 px-4 py-4 dark:border-slate-800", children: /* @__PURE__ */ jsxs28("div", { className: "flex items-start justify-between gap-3", children: [
9793
+ /* @__PURE__ */ jsxs28("div", { children: [
9759
9794
  /* @__PURE__ */ jsx41("div", { className: "text-[10px] font-semibold uppercase tracking-[0.18em] text-slate-400 dark:text-slate-500", children: "Collaborators" }),
9760
9795
  /* @__PURE__ */ jsx41("h3", { className: "mt-1 text-base font-semibold text-slate-900 dark:text-slate-100", children: "Branch authors" }),
9761
9796
  /* @__PURE__ */ jsx41("p", { className: "mt-1 text-sm text-slate-500 dark:text-slate-400", children: "Presence, roles, and access for the active branch." })
9762
9797
  ] }),
9763
- /* @__PURE__ */ jsxs27(
9798
+ /* @__PURE__ */ jsxs28(
9764
9799
  Button,
9765
9800
  {
9766
9801
  type: "button",
@@ -9782,9 +9817,9 @@ var Users = ({ users, onViewUser, onSetMain, onToggleAdmin, onRemoveUser, onInvi
9782
9817
  "div",
9783
9818
  {
9784
9819
  className: "rounded-2xl border border-slate-200/80 bg-slate-50/80 p-3 shadow-sm dark:border-slate-800 dark:bg-slate-900/70",
9785
- children: /* @__PURE__ */ jsxs27("div", { className: "flex items-start gap-3", children: [
9786
- /* @__PURE__ */ jsxs27("div", { className: "relative", children: [
9787
- /* @__PURE__ */ jsxs27(Avatar, { className: "h-11 w-11 border border-white shadow-sm dark:border-slate-950", children: [
9820
+ children: /* @__PURE__ */ jsxs28("div", { className: "flex items-start gap-3", children: [
9821
+ /* @__PURE__ */ jsxs28("div", { className: "relative", children: [
9822
+ /* @__PURE__ */ jsxs28(Avatar, { className: "h-11 w-11 border border-white shadow-sm dark:border-slate-950", children: [
9788
9823
  /* @__PURE__ */ jsx41(AvatarImage, { src: user.avatar, alt: user.name }),
9789
9824
  /* @__PURE__ */ jsx41(AvatarFallback, { children: getInitials(user.name) })
9790
9825
  ] }),
@@ -9798,9 +9833,9 @@ var Users = ({ users, onViewUser, onSetMain, onToggleAdmin, onRemoveUser, onInvi
9798
9833
  }
9799
9834
  )
9800
9835
  ] }),
9801
- /* @__PURE__ */ jsxs27("div", { className: "min-w-0 flex-1", children: [
9802
- /* @__PURE__ */ jsxs27("div", { className: "flex items-start justify-between gap-3", children: [
9803
- /* @__PURE__ */ jsxs27("div", { className: "min-w-0", children: [
9836
+ /* @__PURE__ */ jsxs28("div", { className: "min-w-0 flex-1", children: [
9837
+ /* @__PURE__ */ jsxs28("div", { className: "flex items-start justify-between gap-3", children: [
9838
+ /* @__PURE__ */ jsxs28("div", { className: "min-w-0", children: [
9804
9839
  /* @__PURE__ */ jsx41("div", { className: "truncate text-sm font-semibold text-slate-900 dark:text-slate-100", children: user.name }),
9805
9840
  /* @__PURE__ */ jsx41("div", { className: "mt-1 text-xs text-slate-500 dark:text-slate-400", children: statusLabel })
9806
9841
  ] }),
@@ -9826,7 +9861,7 @@ var Users = ({ users, onViewUser, onSetMain, onToggleAdmin, onRemoveUser, onInvi
9826
9861
  }
9827
9862
  )
9828
9863
  ] }),
9829
- /* @__PURE__ */ jsxs27("div", { className: "mt-3 flex flex-wrap gap-2", children: [
9864
+ /* @__PURE__ */ jsxs28("div", { className: "mt-3 flex flex-wrap gap-2", children: [
9830
9865
  (user.roles?.length ? user.roles : ["viewer"]).map((role) => /* @__PURE__ */ jsx41("span", { className: cn("rounded-full border px-2.5 py-1 text-[11px] font-semibold capitalize", roleClass(role)), children: formatRole(role) }, `${user.id}-${role}`)),
9831
9866
  /* @__PURE__ */ jsx41("span", { className: "rounded-full border border-slate-200 bg-white px-2.5 py-1 text-[11px] font-medium text-slate-500 dark:border-slate-700 dark:bg-slate-950 dark:text-slate-300", children: permissionsLabel })
9832
9867
  ] })
@@ -9846,7 +9881,7 @@ import { useCanvas as useCanvas6, useWorkspace as useWorkspace9 } from "@timeax/
9846
9881
  import { useMemo as useMemo19 } from "react";
9847
9882
  import { MdOutlinePlayArrow } from "react-icons/md";
9848
9883
  import { PiShareFatThin } from "react-icons/pi";
9849
- import { jsx as jsx42, jsxs as jsxs28 } from "react/jsx-runtime";
9884
+ import { jsx as jsx42, jsxs as jsxs29 } from "react/jsx-runtime";
9850
9885
  var Header2 = ({ onShare, onPlay }) => {
9851
9886
  const ws = useWorkspace9();
9852
9887
  const canvas = useCanvas6();
@@ -9881,8 +9916,8 @@ var Header2 = ({ onShare, onPlay }) => {
9881
9916
  const onShareClick = () => {
9882
9917
  onShare?.(ws.snapshot.data);
9883
9918
  };
9884
- return /* @__PURE__ */ jsxs28("div", { className: "flex items-center justify-between gap-3 border-b border-slate-200 px-3 py-3 dark:border-slate-800", children: [
9885
- /* @__PURE__ */ jsxs28("div", { className: "min-w-0 flex items-center gap-3", children: [
9919
+ return /* @__PURE__ */ jsxs29("div", { className: "flex items-center justify-between gap-3 border-b border-slate-200 px-3 py-3 dark:border-slate-800", children: [
9920
+ /* @__PURE__ */ jsxs29("div", { className: "min-w-0 flex items-center gap-3", children: [
9886
9921
  /* @__PURE__ */ jsx42(users_default, { users }),
9887
9922
  /* @__PURE__ */ jsx42(
9888
9923
  BuilderIconButton,
@@ -9944,7 +9979,7 @@ function CollapsibleContent2({
9944
9979
  import { InputField as InputField3 } from "@timeax/form-palette";
9945
9980
  import * as React28 from "react";
9946
9981
  import { createCache as createCache2, createIndexedDBDriver as createIndexedDBDriver2, createMemoryDriver as createMemoryDriver2 } from "@timeax/cache-store";
9947
- import { jsx as jsx44, jsxs as jsxs29 } from "react/jsx-runtime";
9982
+ import { jsx as jsx44, jsxs as jsxs30 } from "react/jsx-runtime";
9948
9983
  var OPEN_DB_NAME = "dgp-cache";
9949
9984
  var OPEN_STORE_NAME = "kv";
9950
9985
  var OPEN_NS = "comment-thread-open";
@@ -10027,7 +10062,7 @@ function PersonAvatar({
10027
10062
  sizeClass = "h-8 w-8",
10028
10063
  fallback
10029
10064
  }) {
10030
- return /* @__PURE__ */ jsxs29(Avatar, { className: sizeClass, children: [
10065
+ return /* @__PURE__ */ jsxs30(Avatar, { className: sizeClass, children: [
10031
10066
  person.avatar?.src ? /* @__PURE__ */ jsx44(AvatarImage, { src: person.avatar.src, alt: person.avatar.alt ?? `Avatar of ${person.name}` }) : null,
10032
10067
  /* @__PURE__ */ jsx44(AvatarFallback, { children: fallback ?? initials(person.name) })
10033
10068
  ] });
@@ -10039,7 +10074,7 @@ function ReplyInputRow({
10039
10074
  onSubmit,
10040
10075
  className
10041
10076
  }) {
10042
- return /* @__PURE__ */ jsxs29("div", { className: cx("flex items-center gap-3", className), children: [
10077
+ return /* @__PURE__ */ jsxs30("div", { className: cx("flex items-center gap-3", className), children: [
10043
10078
  /* @__PURE__ */ jsx44(PersonAvatar, { person: { name: you.name, avatar: you.avatar }, fallback: initials(you.name) }),
10044
10079
  /* @__PURE__ */ jsx44(
10045
10080
  InputField3,
@@ -10060,10 +10095,10 @@ function ReplyInputRow({
10060
10095
  }
10061
10096
  function CommentItem({ msg, identities, formatTime }) {
10062
10097
  const author = resolveAuthor(msg, identities);
10063
- return /* @__PURE__ */ jsxs29("div", { className: "flex items-start gap-3", children: [
10098
+ return /* @__PURE__ */ jsxs30("div", { className: "flex items-start gap-3", children: [
10064
10099
  /* @__PURE__ */ jsx44(PersonAvatar, { person: author }),
10065
- /* @__PURE__ */ jsxs29("div", { className: "flex-1", children: [
10066
- /* @__PURE__ */ jsxs29("div", { className: "flex items-center justify-between", children: [
10100
+ /* @__PURE__ */ jsxs30("div", { className: "flex-1", children: [
10101
+ /* @__PURE__ */ jsxs30("div", { className: "flex items-center justify-between", children: [
10067
10102
  /* @__PURE__ */ jsx44("p", { className: "text-sm font-semibold text-gray-800 dark:text-white", children: author.name }),
10068
10103
  /* @__PURE__ */ jsx44("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: formatTime(msg.createdAt) })
10069
10104
  ] }),
@@ -10085,7 +10120,7 @@ function CommentThreadView({ thread, identities, you, highlight, formatTime, onR
10085
10120
  };
10086
10121
  if (!main) return null;
10087
10122
  const [open, setOpen] = useThreadOpenState(thread.id, true);
10088
- return /* @__PURE__ */ jsxs29(
10123
+ return /* @__PURE__ */ jsxs30(
10089
10124
  "div",
10090
10125
  {
10091
10126
  className: cx(
@@ -10093,11 +10128,11 @@ function CommentThreadView({ thread, identities, you, highlight, formatTime, onR
10093
10128
  ),
10094
10129
  children: [
10095
10130
  isHighlighted ? /* @__PURE__ */ jsx44(ActiveDot, {}) : null,
10096
- /* @__PURE__ */ jsxs29(Collapsible, { open, onOpenChange: setOpen, children: [
10131
+ /* @__PURE__ */ jsxs30(Collapsible, { open, onOpenChange: setOpen, children: [
10097
10132
  /* @__PURE__ */ jsx44(CollapsibleTrigger2, { asChild: true, children: /* @__PURE__ */ jsx44("div", { className: "px-3 py-4", children: /* @__PURE__ */ jsx44(CommentItem, { msg: main, identities, formatTime: fmt }) }) }),
10098
- /* @__PURE__ */ jsx44(CollapsibleContent2, { children: /* @__PURE__ */ jsx44("div", { className: "border-t border-gray-200 bg-gray-50 p-4 pl-6 dark:border-gray-700 dark:bg-gray-800/50", children: /* @__PURE__ */ jsxs29("div", { className: "flex items-start gap-4", children: [
10133
+ /* @__PURE__ */ jsx44(CollapsibleContent2, { children: /* @__PURE__ */ jsx44("div", { className: "border-t border-gray-200 bg-gray-50 p-4 pl-6 dark:border-gray-700 dark:bg-gray-800/50", children: /* @__PURE__ */ jsxs30("div", { className: "flex items-start gap-4", children: [
10099
10134
  /* @__PURE__ */ jsx44("div", { className: "ml-1 w-px shrink-0 self-stretch bg-gray-300 dark:bg-gray-600" }),
10100
- /* @__PURE__ */ jsxs29("div", { className: "flex-1 space-y-4", children: [
10135
+ /* @__PURE__ */ jsxs30("div", { className: "flex-1 space-y-4", children: [
10101
10136
  replies.map((r) => /* @__PURE__ */ jsx44(CommentItem, { msg: r, identities, formatTime: fmt }, r.id)),
10102
10137
  /* @__PURE__ */ jsx44(ReplyInputRow, { id: thread.id, you, value, setValue, onSubmit: submit })
10103
10138
  ] })
@@ -10108,7 +10143,7 @@ function CommentThreadView({ thread, identities, you, highlight, formatTime, onR
10108
10143
  );
10109
10144
  }
10110
10145
  function ActiveDot() {
10111
- return /* @__PURE__ */ jsxs29("span", { className: "absolute -top-1.5 -left-1.5 flex h-3 w-3", children: [
10146
+ return /* @__PURE__ */ jsxs30("span", { className: "absolute -top-1.5 -left-1.5 flex h-3 w-3", children: [
10112
10147
  /* @__PURE__ */ jsx44("span", { className: "absolute inline-flex h-full w-full animate-ping rounded-full bg-primary opacity-75" }),
10113
10148
  /* @__PURE__ */ jsx44("span", { className: "relative inline-flex h-3 w-3 rounded-full bg-primary" })
10114
10149
  ] });
@@ -10119,7 +10154,7 @@ import { useWorkspace as useWorkspace10 } from "@timeax/digital-service-engine/w
10119
10154
  import { InputField as InputField4 } from "@timeax/form-palette";
10120
10155
  import { useMemo as useMemo21, useState as useState22 } from "react";
10121
10156
  import { MdOutlineSend } from "react-icons/md";
10122
- import { jsx as jsx45, jsxs as jsxs30 } from "react/jsx-runtime";
10157
+ import { jsx as jsx45, jsxs as jsxs31 } from "react/jsx-runtime";
10123
10158
  var Comments = () => {
10124
10159
  const ws = useWorkspace10();
10125
10160
  const [value, setValue] = useState22("");
@@ -10132,12 +10167,12 @@ var Comments = () => {
10132
10167
  (thread) => thread.messages.some((message) => `${message.authorName ?? ""} ${message.body}`.toLowerCase().includes(lower))
10133
10168
  );
10134
10169
  }, [ws.comments.threads.data, query]);
10135
- return /* @__PURE__ */ jsxs30("div", { className: "flex h-full min-h-0 flex-col overflow-hidden", children: [
10136
- /* @__PURE__ */ jsxs30("div", { className: "flex items-center justify-between px-4 pt-4", children: [
10170
+ return /* @__PURE__ */ jsxs31("div", { className: "flex h-full min-h-0 flex-col overflow-hidden", children: [
10171
+ /* @__PURE__ */ jsxs31("div", { className: "flex items-center justify-between px-4 pt-4", children: [
10137
10172
  /* @__PURE__ */ jsx45("div", { children: /* @__PURE__ */ jsx45("h3", { className: "text-sm font-semibold text-slate-900 dark:text-slate-100", children: "All comments" }) }),
10138
10173
  /* @__PURE__ */ jsx45("button", { className: "text-xs font-semibold text-blue-600 hover:underline dark:text-blue-300", children: "Mark as read" })
10139
10174
  ] }),
10140
- /* @__PURE__ */ jsxs30("div", { className: "px-4 pt-3", children: [
10175
+ /* @__PURE__ */ jsxs31("div", { className: "px-4 pt-3", children: [
10141
10176
  /* @__PURE__ */ jsx45(PanelSearch, { value: query, onChange: setQuery, placeholder: "Search comments or authors" }),
10142
10177
  /* @__PURE__ */ jsx45(WorkspaceBootInlineNotice, { boot: ws.boot, sections: ["comments"], className: "mt-3" })
10143
10178
  ] }),
@@ -10245,7 +10280,7 @@ function FieldLabel(props) {
10245
10280
  import * as React31 from "react";
10246
10281
  import { MdOutlineOpenInNew, MdOutlineRemoveCircleOutline } from "react-icons/md";
10247
10282
  import { TiWarning } from "react-icons/ti";
10248
- import { jsx as jsx48, jsxs as jsxs31 } from "react/jsx-runtime";
10283
+ import { jsx as jsx48, jsxs as jsxs32 } from "react/jsx-runtime";
10249
10284
  var SectionCtx = React31.createContext(null);
10250
10285
  function useSectionCtx() {
10251
10286
  const ctx = React31.useContext(SectionCtx);
@@ -10301,7 +10336,7 @@ var Section = Object.assign(SectionRoot, {
10301
10336
  });
10302
10337
  function buildSectionActionButton({ className, icon, tooltip, iconOnly = false, badge, children, ...props }, ref) {
10303
10338
  const derivedAriaLabel = props["aria-label"] ?? (typeof tooltip === "string" ? tooltip : typeof children === "string" ? children : typeof props.title === "string" ? props.title : void 0);
10304
- const button = /* @__PURE__ */ jsxs31(
10339
+ const button = /* @__PURE__ */ jsxs32(
10305
10340
  "button",
10306
10341
  {
10307
10342
  ref,
@@ -10323,7 +10358,7 @@ function buildSectionActionButton({ className, icon, tooltip, iconOnly = false,
10323
10358
  }
10324
10359
  );
10325
10360
  if (!tooltip) return button;
10326
- return /* @__PURE__ */ jsxs31(Tooltip, { children: [
10361
+ return /* @__PURE__ */ jsxs32(Tooltip, { children: [
10327
10362
  /* @__PURE__ */ jsx48(TooltipTrigger, { asChild: true, children: button }),
10328
10363
  /* @__PURE__ */ jsx48(TooltipContent, { side: "bottom", children: tooltip })
10329
10364
  ] });
@@ -10338,8 +10373,8 @@ function IncludesList({ className, children }) {
10338
10373
  return /* @__PURE__ */ jsx48("div", { className: cn("space-y-2", className), children });
10339
10374
  }
10340
10375
  function IncludesItem({ title, badge, actions, className }) {
10341
- return /* @__PURE__ */ jsxs31("div", { className: cn("flex items-center justify-between rounded-md p-2", "bg-gray-50 dark:bg-gray-800/50", className), children: [
10342
- /* @__PURE__ */ jsxs31("div", { className: "flex min-w-0 items-center gap-2", children: [
10376
+ return /* @__PURE__ */ jsxs32("div", { className: cn("flex items-center justify-between rounded-md p-2", "bg-gray-50 dark:bg-gray-800/50", className), children: [
10377
+ /* @__PURE__ */ jsxs32("div", { className: "flex min-w-0 items-center gap-2", children: [
10343
10378
  /* @__PURE__ */ jsx48("span", { className: "truncate text-sm text-gray-800 dark:text-gray-200", children: title }),
10344
10379
  badge
10345
10380
  ] }),
@@ -10352,8 +10387,8 @@ function IncludesItemMissing({
10352
10387
  className,
10353
10388
  icon
10354
10389
  }) {
10355
- return /* @__PURE__ */ jsxs31("div", { className: cn("flex items-center justify-between rounded-md p-2", "bg-red-50 dark:bg-red-900/20", className), children: [
10356
- /* @__PURE__ */ jsxs31("div", { className: "flex min-w-0 items-center gap-2", children: [
10390
+ return /* @__PURE__ */ jsxs32("div", { className: cn("flex items-center justify-between rounded-md p-2", "bg-red-50 dark:bg-red-900/20", className), children: [
10391
+ /* @__PURE__ */ jsxs32("div", { className: "flex min-w-0 items-center gap-2", children: [
10357
10392
  /* @__PURE__ */ jsx48("span", { className: "shrink-0 text-base text-red-500 dark:text-red-400", children: icon ?? /* @__PURE__ */ jsx48("span", { className: "material-symbols-outlined", children: /* @__PURE__ */ jsx48(TiWarning, {}) }) }),
10358
10393
  /* @__PURE__ */ jsx48("span", { className: "truncate text-sm text-red-700 dark:text-red-300", children: message })
10359
10394
  ] }),
@@ -10388,6 +10423,161 @@ function IncludesIconAction({ kind, onClick, disabled, title, icon, className })
10388
10423
  );
10389
10424
  }
10390
10425
 
10426
+ // src/builder/service-context.ts
10427
+ import { createBuilder } from "@timeax/digital-service-engine/core";
10428
+ function createDefaultServiceContext(props, preferredTagId) {
10429
+ const tagIds = (props?.filters ?? []).map((tag) => tag.id);
10430
+ return {
10431
+ selectedTagId: preferredTagId && tagIds.includes(preferredTagId) ? preferredTagId : tagIds[0] ?? null,
10432
+ selectedButtons: [],
10433
+ strictSafety: true,
10434
+ enforcePolicies: true
10435
+ };
10436
+ }
10437
+ function sanitizeServiceContext(snapshot, state) {
10438
+ const allowed = new Set(snapshot.buttonGroups.flatMap((group) => group.options.map((option) => option.id)));
10439
+ const selectedButtons = state.selectedButtons.filter((id) => allowed.has(id));
10440
+ if (selectedButtons.length === state.selectedButtons.length) return state;
10441
+ return { ...state, selectedButtons };
10442
+ }
10443
+ function buildServiceContextSnapshot(args) {
10444
+ const props = args.props ?? void 0;
10445
+ const serviceMap = args.services ?? {};
10446
+ const tags = (props?.filters ?? []).map((tag) => ({
10447
+ id: tag.id,
10448
+ label: tag.label,
10449
+ description: describeTag(tag)
10450
+ }));
10451
+ const selectedTag = (props?.filters ?? []).find((tag) => tag.id === args.state.selectedTagId) ?? null;
10452
+ if (!props || !selectedTag) {
10453
+ return {
10454
+ state: args.state,
10455
+ tags,
10456
+ selectedTag,
10457
+ buttonGroups: [],
10458
+ visibleFieldIds: [],
10459
+ usedServiceIds: []
10460
+ };
10461
+ }
10462
+ const sandbox = createBuilder({ serviceMap });
10463
+ sandbox.load(props);
10464
+ const visibleFieldIds = sandbox.visibleFields(selectedTag.id, args.state.selectedButtons);
10465
+ const buttonGroups = buildButtonGroups(props.fields ?? [], visibleFieldIds);
10466
+ const usedServiceIds = collectUsedServiceIds({
10467
+ props,
10468
+ tagId: selectedTag.id,
10469
+ visibleFieldIds,
10470
+ selectedButtons: args.state.selectedButtons
10471
+ });
10472
+ return {
10473
+ state: args.state,
10474
+ tags,
10475
+ selectedTag,
10476
+ buttonGroups,
10477
+ visibleFieldIds,
10478
+ usedServiceIds
10479
+ };
10480
+ }
10481
+ function buildServiceRowVM(args) {
10482
+ const service = args.services?.[args.summary.id] ?? null;
10483
+ const check = args.check;
10484
+ const searchText = [args.summary.name, args.summary.category, args.summary.platformId, String(args.summary.id)].filter(Boolean).join(" ").toLowerCase();
10485
+ const search = args.search?.trim().toLowerCase() ?? "";
10486
+ const matchesSearch = !search || searchText.includes(search);
10487
+ const isCompatible = !check || servicePassesCurrentFilter(check, args.state);
10488
+ const status = describeCheck(check, args.state);
10489
+ return {
10490
+ id: String(args.summary.id),
10491
+ summary: args.summary,
10492
+ service,
10493
+ check,
10494
+ matchesSearch,
10495
+ isCompatible,
10496
+ passesCurrentFilter: matchesSearch,
10497
+ statusTone: status.tone,
10498
+ statusLabel: status.label,
10499
+ reasonLabels: status.reasons,
10500
+ searchText
10501
+ };
10502
+ }
10503
+ function buildButtonGroups(fields, visibleFieldIds) {
10504
+ const visibleSet = new Set(visibleFieldIds);
10505
+ return fields.filter((field) => visibleSet.has(field.id)).map((field) => {
10506
+ const options = field.options?.length ? field.options.filter((option) => option.id).map((option) => ({
10507
+ id: String(option.id),
10508
+ label: option.label,
10509
+ description: `Option in ${field.label}`,
10510
+ fieldId: field.id,
10511
+ fieldLabel: field.label
10512
+ })) : field.button ? [
10513
+ {
10514
+ id: field.id,
10515
+ label: field.label,
10516
+ description: "Button field",
10517
+ fieldId: field.id,
10518
+ fieldLabel: field.label
10519
+ }
10520
+ ] : [];
10521
+ return {
10522
+ id: field.id,
10523
+ label: field.label,
10524
+ options
10525
+ };
10526
+ }).filter((group) => group.options.length > 0);
10527
+ }
10528
+ function collectUsedServiceIds(args) {
10529
+ const visibleSet = new Set(args.visibleFieldIds);
10530
+ const used = /* @__PURE__ */ new Set();
10531
+ const tag = args.props.filters?.find((item) => item.id === args.tagId);
10532
+ if (tag?.service_id != null) used.add(String(tag.service_id));
10533
+ for (const field of args.props.fields ?? []) {
10534
+ if (!visibleSet.has(field.id)) continue;
10535
+ if (field.service_id != null) {
10536
+ used.add(String(field.service_id));
10537
+ }
10538
+ for (const option of field.options ?? []) {
10539
+ if (option.service_id != null) {
10540
+ used.add(String(option.service_id));
10541
+ }
10542
+ }
10543
+ }
10544
+ return Array.from(used);
10545
+ }
10546
+ function describeTag(tag) {
10547
+ const constraints = Object.entries(tag.constraints ?? {}).filter(([, enabled]) => enabled).map(([key]) => key);
10548
+ return constraints.length ? constraints.join(", ") : "All visible services";
10549
+ }
10550
+ function servicePassesCurrentFilter(check, state) {
10551
+ const passesPolicies = state?.enforcePolicies === false ? true : check.passesPolicies;
10552
+ const safetyPass = check.fitsConstraints && check.passesRate && passesPolicies;
10553
+ return state?.strictSafety === false ? true : safetyPass;
10554
+ }
10555
+ function describeCheck(check, state) {
10556
+ if (!check) {
10557
+ return {
10558
+ tone: "default",
10559
+ label: "No context",
10560
+ reasons: []
10561
+ };
10562
+ }
10563
+ const reasons = [
10564
+ !check.fitsConstraints ? "Constraint mismatch" : null,
10565
+ !check.passesRate ? "Rate policy mismatch" : null,
10566
+ state?.enforcePolicies !== false && !check.passesPolicies ? "Policy blocked" : null,
10567
+ check.reasons.includes("missing_capability") ? "Missing capability" : null
10568
+ ].filter(Boolean);
10569
+ if (servicePassesCurrentFilter(check, state) && check.ok) {
10570
+ return { tone: "success", label: "Safe fit", reasons };
10571
+ }
10572
+ if (servicePassesCurrentFilter(check, state)) {
10573
+ return { tone: "warning", label: state?.enforcePolicies === false ? "Policy checks relaxed" : "Usable", reasons };
10574
+ }
10575
+ if (reasons.length) {
10576
+ return { tone: "danger", label: "Hidden by context", reasons };
10577
+ }
10578
+ return { tone: "default", label: "Available", reasons };
10579
+ }
10580
+
10391
10581
  // src/panels/right/components/renderif.tsx
10392
10582
  import "react";
10393
10583
  import { Fragment as Fragment8, jsx as jsx49 } from "react/jsx-runtime";
@@ -10416,29 +10606,32 @@ function RenderIf({ data, emptyMessage = null, children, when }) {
10416
10606
  // src/panels/right/partials/global/add-service.tsx
10417
10607
  import { useCanvas as useCanvas7, useWorkspace as useWorkspace11 } from "@timeax/digital-service-engine/workspace";
10418
10608
  import { InputField as InputField5 } from "@timeax/form-palette";
10419
- import { useMemo as useMemo23, useState as useState24 } from "react";
10609
+ import { useCallback as useCallback16, useEffect as useEffect17, useMemo as useMemo23, useState as useState24 } from "react";
10420
10610
  import { BsPlus } from "react-icons/bs";
10421
- import { Fragment as Fragment9, jsx as jsx50, jsxs as jsxs32 } from "react/jsx-runtime";
10611
+ import { FaFolderOpen } from "react-icons/fa";
10612
+ import { FiFilter } from "react-icons/fi";
10613
+ import { Fragment as Fragment9, jsx as jsx50, jsxs as jsxs33 } from "react/jsx-runtime";
10614
+ var UNGROUPED_TREE_VALUE = "__catalog_ungrouped__";
10422
10615
  function AddService({ className, data, disabled, disabledMessage, readOnly, readOnlyMessage, emptyMessage }) {
10423
10616
  const ws = useWorkspace11();
10424
10617
  const canvas = useCanvas7();
10425
- const services2 = useMemo23(() => ws.services.data ?? {}, [ws.services.data]);
10426
- const connectedService = data.raw.service_id != null ? services2[data.raw.service_id] : void 0;
10618
+ const servicesMap = useMemo23(() => ws.services.data ?? {}, [ws.services.data]);
10619
+ const connectedService = data.raw.service_id != null ? servicesMap[data.raw.service_id] : void 0;
10427
10620
  const isReadOnly = Boolean(disabled || readOnly);
10428
10621
  const helperMessage = readOnlyMessage ?? disabledMessage;
10429
- return /* @__PURE__ */ jsxs32(Section, { className, children: [
10430
- /* @__PURE__ */ jsxs32(Section.Header, { children: [
10622
+ return /* @__PURE__ */ jsxs33(Section, { className, children: [
10623
+ /* @__PURE__ */ jsxs33(Section.Header, { children: [
10431
10624
  /* @__PURE__ */ jsx50(Section.Title, { children: "Service" }),
10432
- /* @__PURE__ */ jsx50(Section.Actions, { children: !isReadOnly ? /* @__PURE__ */ jsx50(AddServicePopover, { data, services: Object.values(services2) }) : null })
10625
+ /* @__PURE__ */ jsx50(Section.Actions, { children: !isReadOnly ? /* @__PURE__ */ jsx50(AddServicePopover, { data, services: Object.values(servicesMap), servicesMap }) : null })
10433
10626
  ] }),
10434
- /* @__PURE__ */ jsxs32(Section.Content, { children: [
10627
+ /* @__PURE__ */ jsxs33(Section.Content, { children: [
10435
10628
  helperMessage ? /* @__PURE__ */ jsx50("p", { className: "mb-3 text-xs text-slate-500 dark:text-slate-400", children: helperMessage }) : null,
10436
10629
  /* @__PURE__ */ jsx50(RenderIf, { data: connectedService, emptyMessage: isReadOnly ? emptyMessage ?? null : emptyMessage ?? "None", children: (service) => /* @__PURE__ */ jsx50(Fragment9, { children: /* @__PURE__ */ jsx50(
10437
10630
  IncludesItem,
10438
10631
  {
10439
10632
  title: service.name ?? `Service ${service.id}`,
10440
10633
  className: "items-start!",
10441
- badge: /* @__PURE__ */ jsxs32("span", { className: "rounded-full bg-slate-200 px-2 py-0.5 text-[10px] font-semibold uppercase tracking-[0.16em] text-slate-600 dark:bg-slate-800 dark:text-slate-300", children: [
10634
+ badge: /* @__PURE__ */ jsxs33("span", { className: "rounded-full bg-slate-200 px-2 py-0.5 text-[10px] font-semibold tracking-[0.16em] text-slate-600 uppercase dark:bg-slate-800 dark:text-slate-300", children: [
10442
10635
  "#",
10443
10636
  service.id
10444
10637
  ] }),
@@ -10457,19 +10650,19 @@ function AddService({ className, data, disabled, disabledMessage, readOnly, read
10457
10650
  }
10458
10651
  function ServiceSummary({ service, nodeId, disabled }) {
10459
10652
  const canvas = useCanvas7();
10460
- return /* @__PURE__ */ jsxs32("div", { className: "mt-2 rounded-md bg-gray-50 p-3 text-sm dark:bg-gray-800/50", children: [
10461
- /* @__PURE__ */ jsxs32("div", { className: "space-y-1 text-xs text-gray-600 dark:text-gray-300", children: [
10462
- /* @__PURE__ */ jsxs32("p", { children: [
10653
+ return /* @__PURE__ */ jsxs33("div", { className: "mt-2 rounded-md bg-gray-50 p-3 text-sm dark:bg-gray-800/50", children: [
10654
+ /* @__PURE__ */ jsxs33("div", { className: "space-y-1 text-xs text-gray-600 dark:text-gray-300", children: [
10655
+ /* @__PURE__ */ jsxs33("p", { children: [
10463
10656
  /* @__PURE__ */ jsx50("span", { className: "font-medium text-gray-800 dark:text-gray-200", children: "Category:" }),
10464
10657
  " ",
10465
10658
  service.category ?? "Uncategorised"
10466
10659
  ] }),
10467
- /* @__PURE__ */ jsxs32("p", { children: [
10660
+ /* @__PURE__ */ jsxs33("p", { children: [
10468
10661
  /* @__PURE__ */ jsx50("span", { className: "font-medium text-gray-800 dark:text-gray-200", children: "Rate:" }),
10469
10662
  " ",
10470
10663
  service.rate
10471
10664
  ] }),
10472
- /* @__PURE__ */ jsxs32("p", { children: [
10665
+ /* @__PURE__ */ jsxs33("p", { children: [
10473
10666
  /* @__PURE__ */ jsx50("span", { className: "font-medium text-gray-800 dark:text-gray-200", children: "Range:" }),
10474
10667
  " ",
10475
10668
  service.min ?? 0,
@@ -10488,28 +10681,230 @@ function ServiceSummary({ service, nodeId, disabled }) {
10488
10681
  ) }) : null
10489
10682
  ] });
10490
10683
  }
10491
- function AddServicePopover({ data, services: services2 }) {
10684
+ function AddServicePopover({
10685
+ data,
10686
+ services: services2,
10687
+ servicesMap
10688
+ }) {
10689
+ const ws = useWorkspace11();
10492
10690
  const canvas = useCanvas7();
10493
10691
  const [open, setOpen] = useState24(false);
10692
+ const [filterOpen, setFilterOpen] = useState24(false);
10494
10693
  const [query, setQuery] = useState24("");
10495
10694
  const [selected, setSelected] = useState24("");
10695
+ const [contextFilterEnabled, setContextFilterEnabled] = useState24(false);
10696
+ const [catalogState, setCatalogState] = useState24(null);
10697
+ const policies2 = ws.policies.policies.data ?? [];
10698
+ const currentTagId = canvas.api.selection.currentTag?.();
10699
+ const preferredTagId = currentTagId != null ? String(currentTagId) : canvas.layers.tags[0]?.id != null ? String(canvas.layers.tags[0]?.id) : null;
10700
+ const selectedButtons = useMemo23(
10701
+ () => (canvas.api.selection.selectedButtons?.() ?? []).map((value) => String(value)),
10702
+ [canvas.api.selection, canvas.selectionInfo.ids, canvas.selectionInfo.optionIds]
10703
+ );
10704
+ const liveSelectionContext = useMemo23(
10705
+ () => ({
10706
+ selectedTagId: preferredTagId,
10707
+ selectedButtons,
10708
+ strictSafety: true,
10709
+ enforcePolicies: true
10710
+ }),
10711
+ [preferredTagId, selectedButtons]
10712
+ );
10713
+ const liveSnapshot = useMemo23(
10714
+ () => buildServiceContextSnapshot({ props: canvas.props, services: servicesMap, state: liveSelectionContext }),
10715
+ [canvas.props, liveSelectionContext, servicesMap]
10716
+ );
10717
+ useEffect17(() => {
10718
+ const editor = canvas.api.editor;
10719
+ const ensured = editor.getCatalog?.() ?? editor.ensureCatalog?.();
10720
+ if (ensured) setCatalogState(ensured);
10721
+ const offCatalogChange = canvas.api.on("catalog:change", ({ catalog }) => {
10722
+ const next = catalog ?? editor.getCatalog?.() ?? editor.ensureCatalog?.();
10723
+ setCatalogState(next ?? null);
10724
+ });
10725
+ const offCatalogActiveChange = canvas.api.on("catalog:active-change", () => {
10726
+ const next = editor.getCatalog?.() ?? editor.ensureCatalog?.();
10727
+ setCatalogState(next ?? null);
10728
+ });
10729
+ return () => {
10730
+ offCatalogChange?.();
10731
+ offCatalogActiveChange?.();
10732
+ };
10733
+ }, [canvas.api]);
10734
+ const catalogMode = catalogState?.viewMode === "grouped" ? "catalog" : "all";
10735
+ const catalogGroups = useMemo23(
10736
+ () => (catalogState?.nodes ?? []).filter((node) => node.kind === "group").sort((a, b) => (a.order ?? 0) - (b.order ?? 0) || a.label.localeCompare(b.label)),
10737
+ [catalogState]
10738
+ );
10739
+ const selectedCatalogGroupId = catalogGroups.some((node) => node.id === catalogState?.activeNodeId) ? String(catalogState?.activeNodeId) : null;
10740
+ const groupedServiceIds = useMemo23(() => {
10741
+ const ids = /* @__PURE__ */ new Set();
10742
+ for (const group of catalogGroups) {
10743
+ for (const serviceId of group.serviceIds) ids.add(String(serviceId));
10744
+ }
10745
+ return ids;
10746
+ }, [catalogGroups]);
10747
+ const allowedCatalogIds = useMemo23(() => {
10748
+ if (catalogMode !== "catalog") return null;
10749
+ if (!selectedCatalogGroupId) {
10750
+ const ids = /* @__PURE__ */ new Set();
10751
+ for (const service of services2) {
10752
+ const id = String(service.id);
10753
+ if (!groupedServiceIds.has(id)) ids.add(id);
10754
+ }
10755
+ return ids;
10756
+ }
10757
+ const selectedGroup = catalogGroups.find((group) => group.id === selectedCatalogGroupId);
10758
+ if (!selectedGroup) {
10759
+ const ids = /* @__PURE__ */ new Set();
10760
+ for (const service of services2) {
10761
+ const id = String(service.id);
10762
+ if (!groupedServiceIds.has(id)) ids.add(id);
10763
+ }
10764
+ return ids;
10765
+ }
10766
+ return new Set(selectedGroup.serviceIds.map((id) => String(id)));
10767
+ }, [catalogGroups, catalogMode, groupedServiceIds, selectedCatalogGroupId, services2]);
10768
+ const compatibleIds = useMemo23(() => {
10769
+ if (!contextFilterEnabled) return null;
10770
+ if (!liveSnapshot.selectedTag) return null;
10771
+ const checks = canvas.api.editor.filterServicesForVisibleGroup?.(
10772
+ services2.map((service) => service.id),
10773
+ {
10774
+ tagId: liveSnapshot.selectedTag.id,
10775
+ selectedButtons: liveSnapshot.state.selectedButtons,
10776
+ usedServiceIds: liveSnapshot.usedServiceIds,
10777
+ effectiveConstraints: liveSnapshot.selectedTag.constraints,
10778
+ policies: policies2
10779
+ }
10780
+ );
10781
+ if (!Array.isArray(checks)) return null;
10782
+ const ids = /* @__PURE__ */ new Set();
10783
+ for (const check of checks) {
10784
+ if (check?.fitsConstraints && check?.passesRate && check?.passesPolicies) {
10785
+ ids.add(String(check.id));
10786
+ }
10787
+ }
10788
+ return ids;
10789
+ }, [canvas.api.editor, contextFilterEnabled, liveSnapshot, policies2, services2]);
10790
+ const setCatalogMode = useCallback16(
10791
+ (mode) => {
10792
+ const editor = canvas.api.editor;
10793
+ editor.ensureCatalog?.();
10794
+ editor.setCatalogViewMode?.(mode === "catalog" ? "grouped" : "all");
10795
+ },
10796
+ [canvas.api.editor]
10797
+ );
10798
+ const filterActive = contextFilterEnabled || catalogMode === "catalog";
10496
10799
  const options = useMemo23(() => {
10497
10800
  const lower = query.trim().toLowerCase();
10498
10801
  return services2.filter((service) => {
10499
10802
  if (!lower) return true;
10500
10803
  return `${service.name ?? ""} ${service.category ?? ""} ${String(service.id)}`.toLowerCase().includes(lower);
10501
- }).map((service) => ({
10804
+ }).filter((service) => allowedCatalogIds ? allowedCatalogIds.has(String(service.id)) : true).filter((service) => compatibleIds ? compatibleIds.has(String(service.id)) : true).map((service) => ({
10502
10805
  label: service.name ?? `Service ${service.id}`,
10503
10806
  value: String(service.id),
10504
10807
  description: service.category,
10505
10808
  service
10506
10809
  }));
10507
- }, [services2, query]);
10508
- return /* @__PURE__ */ jsxs32(Popover, { open, onOpenChange: setOpen, children: [
10810
+ }, [allowedCatalogIds, compatibleIds, services2, query]);
10811
+ useEffect17(() => {
10812
+ if (selected && !options.some((option) => option.value === selected)) {
10813
+ setSelected("");
10814
+ }
10815
+ }, [options, selected]);
10816
+ const treeValue = selectedCatalogGroupId ?? (catalogMode === "catalog" ? UNGROUPED_TREE_VALUE : void 0);
10817
+ const treeOptions = buildCatalogGroupTreeOptions(catalogGroups);
10818
+ const selectedCatalogGroup = catalogGroups.find((group) => group.id === selectedCatalogGroupId) ?? null;
10819
+ return /* @__PURE__ */ jsxs33(Popover, { open, onOpenChange: setOpen, children: [
10509
10820
  /* @__PURE__ */ jsx50(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx50(SectionActionTriggerButton, { icon: /* @__PURE__ */ jsx50(BsPlus, {}), children: "Add" }) }),
10510
- /* @__PURE__ */ jsx50(PopoverContent, { className: "w-96", children: /* @__PURE__ */ jsxs32("div", { className: "flex flex-col gap-3", children: [
10511
- /* @__PURE__ */ jsx50(InputField5, { variant: "text", value: query, onChange: (e) => setQuery(e.value ?? ""), placeholder: "Search services..." }),
10512
- /* @__PURE__ */ jsx50(ScrollArea, { className: "h-72 pr-1", children: /* @__PURE__ */ jsx50("div", { className: "space-y-2 pr-2", children: options.length ? options.map((option) => /* @__PURE__ */ jsxs32(
10821
+ /* @__PURE__ */ jsx50(PopoverContent, { className: "w-96", children: /* @__PURE__ */ jsxs33("div", { className: "flex flex-col gap-3", children: [
10822
+ /* @__PURE__ */ jsx50(
10823
+ InputField5,
10824
+ {
10825
+ variant: "text",
10826
+ value: query,
10827
+ onChange: (e) => setQuery(e.value ?? ""),
10828
+ placeholder: "Search services...",
10829
+ extendBoxToControls: true,
10830
+ joinControls: true,
10831
+ trailingControl: /* @__PURE__ */ jsxs33(Popover, { open: filterOpen, onOpenChange: setFilterOpen, children: [
10832
+ /* @__PURE__ */ jsx50(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx50(
10833
+ "button",
10834
+ {
10835
+ type: "button",
10836
+ "aria-label": "Service list filter",
10837
+ className: `flex h-full w-8 cursor-pointer items-center justify-center text-sm transition ${filterActive ? "text-blue-700 dark:text-blue-200" : "text-slate-600 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-900"}`,
10838
+ children: /* @__PURE__ */ jsx50(FiFilter, {})
10839
+ }
10840
+ ) }),
10841
+ /* @__PURE__ */ jsxs33(PopoverContent, { align: "end", sideOffset: 8, collisionPadding: 12, className: "w-80 space-y-3 rounded-xl", children: [
10842
+ /* @__PURE__ */ jsxs33("div", { children: [
10843
+ /* @__PURE__ */ jsx50("div", { className: "text-sm font-semibold text-slate-900 dark:text-slate-100", children: "Service filters" }),
10844
+ /* @__PURE__ */ jsx50("p", { className: "mt-1 text-xs text-slate-500 dark:text-slate-400", children: "Combine catalog grouping with current context compatibility." })
10845
+ ] }),
10846
+ /* @__PURE__ */ jsxs33("div", { className: "space-y-2 rounded-lg border border-slate-200 p-3 dark:border-slate-800", children: [
10847
+ /* @__PURE__ */ jsx50("div", { className: "text-xs font-semibold tracking-[0.16em] text-slate-500 uppercase dark:text-slate-400", children: "Catalog scope" }),
10848
+ /* @__PURE__ */ jsx50(
10849
+ InputField5,
10850
+ {
10851
+ variant: "radio",
10852
+ value: catalogMode,
10853
+ options: [
10854
+ { key: "all", label: "All services" },
10855
+ { key: "catalog", label: "Catalog group" }
10856
+ ],
10857
+ onChange: (event) => setCatalogMode(event.value)
10858
+ }
10859
+ ),
10860
+ /* @__PURE__ */ jsx50(
10861
+ InputField5,
10862
+ {
10863
+ variant: "treeselect",
10864
+ mode: "button",
10865
+ label: "Select group",
10866
+ className: "w-fit!",
10867
+ disabled: catalogMode !== "catalog",
10868
+ multiple: false,
10869
+ value: treeValue,
10870
+ options: [{ key: UNGROUPED_TREE_VALUE, label: "Ungrouped" }, ...treeOptions],
10871
+ searchable: true,
10872
+ clearable: true,
10873
+ onChange: (event) => {
10874
+ const next = event.value == null ? null : String(event.value);
10875
+ canvas.api.editor.setActiveCatalogNode?.(
10876
+ next === UNGROUPED_TREE_VALUE || next == null ? void 0 : next
10877
+ );
10878
+ },
10879
+ button: /* @__PURE__ */ jsx50(FaFolderOpen, {})
10880
+ }
10881
+ ),
10882
+ catalogMode === "catalog" ? /* @__PURE__ */ jsxs33("div", { className: "text-xs text-slate-500 dark:text-slate-400", children: [
10883
+ "Showing ",
10884
+ selectedCatalogGroup?.label ?? "Ungrouped",
10885
+ " services."
10886
+ ] }) : null
10887
+ ] }),
10888
+ /* @__PURE__ */ jsxs33("label", { className: "flex items-start justify-between gap-3 rounded-lg border border-slate-200 p-3 text-sm text-slate-900 dark:border-slate-800 dark:text-slate-100", children: [
10889
+ /* @__PURE__ */ jsxs33("span", { className: "min-w-0", children: [
10890
+ /* @__PURE__ */ jsx50("span", { className: "block font-medium", children: "Current context" }),
10891
+ /* @__PURE__ */ jsx50("span", { className: "mt-1 block text-xs text-slate-500 dark:text-slate-400", children: "Filter services based on the current visible-group context." })
10892
+ ] }),
10893
+ /* @__PURE__ */ jsx50(
10894
+ "input",
10895
+ {
10896
+ "aria-label": "Current context",
10897
+ type: "checkbox",
10898
+ checked: contextFilterEnabled,
10899
+ onChange: (event) => setContextFilterEnabled(event.target.checked)
10900
+ }
10901
+ )
10902
+ ] })
10903
+ ] })
10904
+ ] })
10905
+ }
10906
+ ),
10907
+ /* @__PURE__ */ jsx50(ScrollArea, { className: "h-72 pr-1", children: /* @__PURE__ */ jsx50("div", { className: "space-y-2 pr-2", children: options.length ? options.map((option) => /* @__PURE__ */ jsxs33(
10513
10908
  "button",
10514
10909
  {
10515
10910
  type: "button",
@@ -10517,7 +10912,7 @@ function AddServicePopover({ data, services: services2 }) {
10517
10912
  className: `w-full rounded-md border px-3 py-2 text-left transition ${selected === option.value ? "border-blue-300 bg-blue-50 dark:border-blue-500/40 dark:bg-blue-500/10" : "border-slate-200 hover:border-slate-300 hover:bg-slate-50 dark:border-slate-700 dark:hover:border-slate-600 dark:hover:bg-slate-900"}`,
10518
10913
  children: [
10519
10914
  /* @__PURE__ */ jsx50("div", { className: "text-sm font-medium text-slate-900 dark:text-slate-100", children: option.label }),
10520
- /* @__PURE__ */ jsxs32("div", { className: "mt-1 text-xs text-slate-500 dark:text-slate-400", children: [
10915
+ /* @__PURE__ */ jsxs33("div", { className: "mt-1 text-xs text-slate-500 dark:text-slate-400", children: [
10521
10916
  option.description ?? "Uncategorised",
10522
10917
  " \u2022 Rate ",
10523
10918
  option.service.rate
@@ -10534,7 +10929,6 @@ function AddServicePopover({ data, services: services2 }) {
10534
10929
  canvas.api.editor.setService(data.id, { service_id: Number(selected) });
10535
10930
  setOpen(false);
10536
10931
  setSelected("");
10537
- setQuery("");
10538
10932
  },
10539
10933
  type: "button",
10540
10934
  size: "sm",
@@ -10544,13 +10938,24 @@ function AddServicePopover({ data, services: services2 }) {
10544
10938
  ] }) })
10545
10939
  ] });
10546
10940
  }
10941
+ function buildCatalogGroupTreeOptions(groups, parentId = null) {
10942
+ return groups.filter((group) => (group.parentId ?? null) === parentId).sort((a, b) => (a.order ?? 0) - (b.order ?? 0) || a.label.localeCompare(b.label)).map((group) => {
10943
+ const children = buildCatalogGroupTreeOptions(groups, group.id);
10944
+ return {
10945
+ key: group.id,
10946
+ label: group.label,
10947
+ description: `${group.serviceIds.length} service${group.serviceIds.length === 1 ? "" : "s"}`,
10948
+ children: children.length ? children : void 0
10949
+ };
10950
+ });
10951
+ }
10547
10952
  var add_service_default = AddService;
10548
10953
 
10549
10954
  // src/panels/right/partials/properties/field-properties.tsx
10550
10955
  import { resolveInputDescriptor, useInputs as useInputs2 } from "@timeax/digital-service-engine/react";
10551
10956
  import { useCanvas as useCanvas12 } from "@timeax/digital-service-engine/workspace";
10552
10957
  import { InputField as InputField11 } from "@timeax/form-palette";
10553
- import { useEffect as useEffect17, useMemo as useMemo28, useState as useState28 } from "react";
10958
+ import { useEffect as useEffect18, useMemo as useMemo28, useState as useState28 } from "react";
10554
10959
 
10555
10960
  // src/panels/right/partials/properties/components/descriptor-settings.tsx
10556
10961
  import { InputField as InputField6 } from "@timeax/form-palette";
@@ -10599,7 +11004,7 @@ function buildQuantityRule(valueBy, base = {}) {
10599
11004
  }
10600
11005
 
10601
11006
  // src/panels/right/partials/properties/components/descriptor-settings.tsx
10602
- import { jsx as jsx51, jsxs as jsxs33 } from "react/jsx-runtime";
11007
+ import { jsx as jsx51, jsxs as jsxs34 } from "react/jsx-runtime";
10603
11008
  var RESERVED_DESCRIPTOR_KEYS = /* @__PURE__ */ new Set([
10604
11009
  "options",
10605
11010
  "label",
@@ -10751,7 +11156,7 @@ function FieldDescription({
10751
11156
  onReset
10752
11157
  }) {
10753
11158
  if (!description && !canReset) return null;
10754
- return /* @__PURE__ */ jsxs33("div", { className: "flex items-start justify-between gap-3", children: [
11159
+ return /* @__PURE__ */ jsxs34("div", { className: "flex items-start justify-between gap-3", children: [
10755
11160
  /* @__PURE__ */ jsx51("p", { className: "text-xs text-slate-500 dark:text-slate-400", children: description }),
10756
11161
  canReset ? /* @__PURE__ */ jsx51(Button, { type: "button", variant: "ghost", size: "sm", className: "h-7 px-2 text-xs", onClick: onReset, children: "Reset" }) : null
10757
11162
  ] });
@@ -10760,7 +11165,7 @@ function DescriptorPrimitiveField({ schema, value, hasOverride, onSet, onClear,
10760
11165
  switch (schema.type) {
10761
11166
  case "string": {
10762
11167
  const options = schema.enum?.map((item) => ({ label: item, value: item }));
10763
- return /* @__PURE__ */ jsxs33("div", { className: "space-y-2", children: [
11168
+ return /* @__PURE__ */ jsxs34("div", { className: "space-y-2", children: [
10764
11169
  /* @__PURE__ */ jsx51(FieldDescription, { description: schema.description, canReset: hasOverride, onReset: () => onClear(path) }),
10765
11170
  /* @__PURE__ */ jsx51(
10766
11171
  InputField6,
@@ -10783,7 +11188,7 @@ function DescriptorPrimitiveField({ schema, value, hasOverride, onSet, onClear,
10783
11188
  ] });
10784
11189
  }
10785
11190
  case "number":
10786
- return /* @__PURE__ */ jsxs33("div", { className: "space-y-2", children: [
11191
+ return /* @__PURE__ */ jsxs34("div", { className: "space-y-2", children: [
10787
11192
  /* @__PURE__ */ jsx51(FieldDescription, { description: schema.description, canReset: hasOverride, onReset: () => onClear(path) }),
10788
11193
  /* @__PURE__ */ jsx51(
10789
11194
  InputField6,
@@ -10804,7 +11209,7 @@ function DescriptorPrimitiveField({ schema, value, hasOverride, onSet, onClear,
10804
11209
  )
10805
11210
  ] });
10806
11211
  case "boolean":
10807
- return /* @__PURE__ */ jsxs33("div", { className: "space-y-2", children: [
11212
+ return /* @__PURE__ */ jsxs34("div", { className: "space-y-2", children: [
10808
11213
  /* @__PURE__ */ jsx51(FieldDescription, { description: schema.description, canReset: hasOverride, onReset: () => onClear(path) }),
10809
11214
  /* @__PURE__ */ jsx51(
10810
11215
  InputField6,
@@ -10822,7 +11227,7 @@ function DescriptorPrimitiveField({ schema, value, hasOverride, onSet, onClear,
10822
11227
  value: item.value,
10823
11228
  description: item.description
10824
11229
  }));
10825
- return /* @__PURE__ */ jsxs33("div", { className: "space-y-2", children: [
11230
+ return /* @__PURE__ */ jsxs34("div", { className: "space-y-2", children: [
10826
11231
  /* @__PURE__ */ jsx51(FieldDescription, { description: schema.description, canReset: hasOverride, onReset: () => onClear(path) }),
10827
11232
  /* @__PURE__ */ jsx51(
10828
11233
  InputField6,
@@ -10891,15 +11296,15 @@ function DescriptorObjectField({ schema, value, hasOverride, onSet, onClear, pat
10891
11296
  setActiveShapes((current) => ({ ...current, [nextKey]: draftShape }));
10892
11297
  setDraftKey("");
10893
11298
  };
10894
- return /* @__PURE__ */ jsx51("div", { className: "rounded-xl border border-slate-200/80 p-3 dark:border-slate-800", children: /* @__PURE__ */ jsxs33("div", { className: "space-y-2", children: [
10895
- /* @__PURE__ */ jsxs33("div", { className: "flex items-start justify-between gap-3", children: [
10896
- /* @__PURE__ */ jsxs33("div", { children: [
11299
+ return /* @__PURE__ */ jsx51("div", { className: "rounded-xl border border-slate-200/80 p-3 dark:border-slate-800", children: /* @__PURE__ */ jsxs34("div", { className: "space-y-2", children: [
11300
+ /* @__PURE__ */ jsxs34("div", { className: "flex items-start justify-between gap-3", children: [
11301
+ /* @__PURE__ */ jsxs34("div", { children: [
10897
11302
  /* @__PURE__ */ jsx51("h4", { className: "text-sm font-semibold text-slate-900 dark:text-slate-100", children: schema.label }),
10898
11303
  /* @__PURE__ */ jsx51("p", { className: "mt-1 text-xs text-slate-500 dark:text-slate-400", children: schema.description })
10899
11304
  ] }),
10900
11305
  allowClear && hasOverride ? /* @__PURE__ */ jsx51(Button, { type: "button", variant: "ghost", size: "sm", className: "h-7 px-2 text-xs", onClick: () => onClear(path), children: "Reset" }) : null
10901
11306
  ] }),
10902
- /* @__PURE__ */ jsxs33("div", { className: "space-y-4", children: [
11307
+ /* @__PURE__ */ jsxs34("div", { className: "space-y-4", children: [
10903
11308
  orderedEntries.map(([key, childSchema]) => /* @__PURE__ */ jsx51(
10904
11309
  DescriptorNodeField,
10905
11310
  {
@@ -10916,8 +11321,8 @@ function DescriptorObjectField({ schema, value, hasOverride, onSet, onClear, pat
10916
11321
  const shapeKey = activeShapes[key] ?? inferShapeKey(schema.shape, objectValue[key]);
10917
11322
  const shapeSchema = (shapeKey && schema.shape?.[shapeKey]) ?? shapeEntries[0]?.[1];
10918
11323
  if (!shapeSchema) return null;
10919
- return /* @__PURE__ */ jsxs33("div", { className: "space-y-3 rounded-lg border border-dashed border-slate-200 p-3 dark:border-slate-700", children: [
10920
- /* @__PURE__ */ jsxs33("div", { className: "grid gap-3 md:grid-cols-[minmax(0,1fr)_180px_auto]", children: [
11324
+ return /* @__PURE__ */ jsxs34("div", { className: "space-y-3 rounded-lg border border-dashed border-slate-200 p-3 dark:border-slate-700", children: [
11325
+ /* @__PURE__ */ jsxs34("div", { className: "grid gap-3 md:grid-cols-[minmax(0,1fr)_180px_auto]", children: [
10921
11326
  /* @__PURE__ */ jsx51(
10922
11327
  InputField6,
10923
11328
  {
@@ -10949,7 +11354,7 @@ function DescriptorObjectField({ schema, value, hasOverride, onSet, onClear, pat
10949
11354
  });
10950
11355
  }
10951
11356
  }
10952
- ) : /* @__PURE__ */ jsxs33("div", { className: "flex items-end text-xs text-slate-500 dark:text-slate-400", children: [
11357
+ ) : /* @__PURE__ */ jsxs34("div", { className: "flex items-end text-xs text-slate-500 dark:text-slate-400", children: [
10953
11358
  "Shape: ",
10954
11359
  shapeKey ?? shapeEntries[0]?.[0] ?? "Custom"
10955
11360
  ] }),
@@ -10983,7 +11388,7 @@ function DescriptorObjectField({ schema, value, hasOverride, onSet, onClear, pat
10983
11388
  )
10984
11389
  ] }, key);
10985
11390
  }),
10986
- schema.editable && shapeEntries.length ? /* @__PURE__ */ jsxs33("div", { className: "grid gap-3 rounded-lg border border-dashed border-slate-200 p-3 md:grid-cols-[minmax(0,1fr)_180px_auto] dark:border-slate-700", children: [
11391
+ schema.editable && shapeEntries.length ? /* @__PURE__ */ jsxs34("div", { className: "grid gap-3 rounded-lg border border-dashed border-slate-200 p-3 md:grid-cols-[minmax(0,1fr)_180px_auto] dark:border-slate-700", children: [
10987
11392
  /* @__PURE__ */ jsx51(
10988
11393
  InputField6,
10989
11394
  {
@@ -11031,15 +11436,15 @@ function DescriptorArrayField({ schema, value, hasOverride, onSet, onClear, path
11031
11436
  setActiveShapes((current) => ({ ...current, [nextIndex]: draftShape }));
11032
11437
  }
11033
11438
  };
11034
- return /* @__PURE__ */ jsx51("div", { className: "rounded-xl border border-slate-200/80 p-3 dark:border-slate-800", children: /* @__PURE__ */ jsxs33("div", { className: "space-y-2", children: [
11035
- /* @__PURE__ */ jsxs33("div", { className: "flex items-start justify-between gap-3", children: [
11036
- /* @__PURE__ */ jsxs33("div", { children: [
11439
+ return /* @__PURE__ */ jsx51("div", { className: "rounded-xl border border-slate-200/80 p-3 dark:border-slate-800", children: /* @__PURE__ */ jsxs34("div", { className: "space-y-2", children: [
11440
+ /* @__PURE__ */ jsxs34("div", { className: "flex items-start justify-between gap-3", children: [
11441
+ /* @__PURE__ */ jsxs34("div", { children: [
11037
11442
  /* @__PURE__ */ jsx51("h4", { className: "text-sm font-semibold text-slate-900 dark:text-slate-100", children: schema.label }),
11038
11443
  /* @__PURE__ */ jsx51("p", { className: "mt-1 text-xs text-slate-500 dark:text-slate-400", children: schema.description })
11039
11444
  ] }),
11040
11445
  allowClear && hasOverride ? /* @__PURE__ */ jsx51(Button, { type: "button", variant: "ghost", size: "sm", className: "h-7 px-2 text-xs", onClick: () => onClear(path), children: "Reset" }) : null
11041
11446
  ] }),
11042
- /* @__PURE__ */ jsxs33("div", { className: "space-y-4", children: [
11447
+ /* @__PURE__ */ jsxs34("div", { className: "space-y-4", children: [
11043
11448
  schema.items ? schema.items.map((childSchema, index) => /* @__PURE__ */ jsx51(
11044
11449
  DescriptorNodeField,
11045
11450
  {
@@ -11056,9 +11461,9 @@ function DescriptorArrayField({ schema, value, hasOverride, onSet, onClear, path
11056
11461
  const shapeKey = activeShapes[index] ?? inferShapeKey(schema.shape, item);
11057
11462
  const itemSchema = schema.item ?? (shapeKey ? schema.shape?.[shapeKey] : void 0) ?? shapeEntries[0]?.[1];
11058
11463
  if (!itemSchema) return null;
11059
- return /* @__PURE__ */ jsxs33("div", { className: "space-y-3 rounded-lg border border-dashed border-slate-200 p-3 dark:border-slate-700", children: [
11060
- /* @__PURE__ */ jsxs33("div", { className: "grid gap-3 md:grid-cols-[minmax(0,1fr)_180px_auto]", children: [
11061
- /* @__PURE__ */ jsxs33("div", { className: "flex items-end text-xs text-slate-500 dark:text-slate-400", children: [
11464
+ return /* @__PURE__ */ jsxs34("div", { className: "space-y-3 rounded-lg border border-dashed border-slate-200 p-3 dark:border-slate-700", children: [
11465
+ /* @__PURE__ */ jsxs34("div", { className: "grid gap-3 md:grid-cols-[minmax(0,1fr)_180px_auto]", children: [
11466
+ /* @__PURE__ */ jsxs34("div", { className: "flex items-end text-xs text-slate-500 dark:text-slate-400", children: [
11062
11467
  formatLabel(schema.label),
11063
11468
  " item ",
11064
11469
  index + 1
@@ -11112,8 +11517,8 @@ function DescriptorArrayField({ schema, value, hasOverride, onSet, onClear, path
11112
11517
  )
11113
11518
  ] }, `${path.join(".")}:${index}`);
11114
11519
  }),
11115
- !schema.items && (schema.editable ?? true) ? /* @__PURE__ */ jsxs33("div", { className: "grid gap-3 rounded-lg border border-dashed border-slate-200 p-3 md:grid-cols-[minmax(0,1fr)_180px_auto] dark:border-slate-700", children: [
11116
- /* @__PURE__ */ jsxs33("div", { className: "flex items-end text-xs text-slate-500 dark:text-slate-400", children: [
11520
+ !schema.items && (schema.editable ?? true) ? /* @__PURE__ */ jsxs34("div", { className: "grid gap-3 rounded-lg border border-dashed border-slate-200 p-3 md:grid-cols-[minmax(0,1fr)_180px_auto] dark:border-slate-700", children: [
11521
+ /* @__PURE__ */ jsxs34("div", { className: "flex items-end text-xs text-slate-500 dark:text-slate-400", children: [
11117
11522
  "Add another ",
11118
11523
  schema.label.toLowerCase()
11119
11524
  ] }),
@@ -11188,7 +11593,7 @@ import { InputField as InputField7 } from "@timeax/form-palette";
11188
11593
  import { useMemo as useMemo25 } from "react";
11189
11594
  import { BsPlus as BsPlus2 } from "react-icons/bs";
11190
11595
  import { MdDeleteOutline } from "react-icons/md";
11191
- import { jsx as jsx52, jsxs as jsxs34 } from "react/jsx-runtime";
11596
+ import { jsx as jsx52, jsxs as jsxs35 } from "react/jsx-runtime";
11192
11597
  var ruleOptions = [
11193
11598
  { label: "Value", value: "value" },
11194
11599
  { label: "Length", value: "length" },
@@ -11248,10 +11653,10 @@ function QuantitySection({ node }) {
11248
11653
  const hasQuantityDefault = capabilities.quantity.canEditDefault && quantityDefault !== void 0;
11249
11654
  const canAddRule = capabilities.quantity.canEditRule && !hasFieldRule;
11250
11655
  const canAddDefault = capabilities.quantity.canEditDefault && !hasQuantityDefault;
11251
- return /* @__PURE__ */ jsxs34(Section, { children: [
11252
- /* @__PURE__ */ jsxs34(Section.Header, { children: [
11656
+ return /* @__PURE__ */ jsxs35(Section, { children: [
11657
+ /* @__PURE__ */ jsxs35(Section.Header, { children: [
11253
11658
  /* @__PURE__ */ jsx52(Section.Title, { children: "Quantity" }),
11254
- canAddRule || canAddDefault || hasFieldRule || hasQuantityDefault ? /* @__PURE__ */ jsxs34(Section.Actions, { children: [
11659
+ canAddRule || canAddDefault || hasFieldRule || hasQuantityDefault ? /* @__PURE__ */ jsxs35(Section.Actions, { children: [
11255
11660
  canAddRule ? /* @__PURE__ */ jsx52(
11256
11661
  SectionActionButton,
11257
11662
  {
@@ -11297,9 +11702,9 @@ function QuantitySection({ node }) {
11297
11702
  ) : null
11298
11703
  ] }) : null
11299
11704
  ] }),
11300
- /* @__PURE__ */ jsx52(Section.Content, { children: node.kind === "field" ? /* @__PURE__ */ jsxs34("div", { className: "space-y-4", children: [
11301
- hasFieldRule ? /* @__PURE__ */ jsxs34("div", { className: "space-y-3 rounded-xl border border-slate-200 p-3 dark:border-slate-800", children: [
11302
- /* @__PURE__ */ jsxs34("div", { className: "space-y-2", children: [
11705
+ /* @__PURE__ */ jsx52(Section.Content, { children: node.kind === "field" ? /* @__PURE__ */ jsxs35("div", { className: "space-y-4", children: [
11706
+ hasFieldRule ? /* @__PURE__ */ jsxs35("div", { className: "space-y-3 rounded-xl border border-slate-200 p-3 dark:border-slate-800", children: [
11707
+ /* @__PURE__ */ jsxs35("div", { className: "space-y-2", children: [
11303
11708
  /* @__PURE__ */ jsx52("div", { className: "grid grid-cols-3 gap-2 rounded-lg bg-slate-100 p-1 dark:bg-slate-900", children: ruleOptions.map((option) => {
11304
11709
  const active = fieldRule?.valueBy === option.value;
11305
11710
  return /* @__PURE__ */ jsx52(
@@ -11328,7 +11733,7 @@ function QuantitySection({ node }) {
11328
11733
  onChange: (e) => updateRule({ code: String(e.value ?? "") })
11329
11734
  }
11330
11735
  ) : null,
11331
- /* @__PURE__ */ jsxs34("div", { className: "grid grid-cols-1 gap-3 sm:grid-cols-2", children: [
11736
+ /* @__PURE__ */ jsxs35("div", { className: "grid grid-cols-1 gap-3 sm:grid-cols-2", children: [
11332
11737
  /* @__PURE__ */ jsx52(
11333
11738
  InputField7,
11334
11739
  {
@@ -11381,7 +11786,7 @@ function QuantitySection({ node }) {
11381
11786
  )
11382
11787
  ] })
11383
11788
  ] }) : null,
11384
- capabilities.quantity.canEditDefault ? hasQuantityDefault ? /* @__PURE__ */ jsxs34("div", { className: "space-y-2 rounded-xl border border-slate-200 p-3 dark:border-slate-800", children: [
11789
+ capabilities.quantity.canEditDefault ? hasQuantityDefault ? /* @__PURE__ */ jsxs35("div", { className: "space-y-2 rounded-xl border border-slate-200 p-3 dark:border-slate-800", children: [
11385
11790
  /* @__PURE__ */ jsx52(
11386
11791
  InputField7,
11387
11792
  {
@@ -11394,7 +11799,7 @@ function QuantitySection({ node }) {
11394
11799
  ),
11395
11800
  capabilities.quantity.defaultHelp ? /* @__PURE__ */ jsx52("p", { className: "text-xs text-slate-500 dark:text-slate-400", children: capabilities.quantity.defaultHelp }) : null
11396
11801
  ] }) : null : null
11397
- ] }) : hasQuantityDefault ? /* @__PURE__ */ jsxs34("div", { className: "space-y-2", children: [
11802
+ ] }) : hasQuantityDefault ? /* @__PURE__ */ jsxs35("div", { className: "space-y-2", children: [
11398
11803
  /* @__PURE__ */ jsx52(
11399
11804
  InputField7,
11400
11805
  {
@@ -11416,7 +11821,7 @@ import { useCanvas as useCanvas9 } from "@timeax/digital-service-engine/workspac
11416
11821
  import { InputField as InputField8 } from "@timeax/form-palette";
11417
11822
  import { BsPencil, BsPlus as BsPlus3 } from "react-icons/bs";
11418
11823
  import { MdDeleteOutline as MdDeleteOutline2 } from "react-icons/md";
11419
- import { Fragment as Fragment10, jsx as jsx53, jsxs as jsxs35 } from "react/jsx-runtime";
11824
+ import { Fragment as Fragment10, jsx as jsx53, jsxs as jsxs36 } from "react/jsx-runtime";
11420
11825
  var utilityModes = [
11421
11826
  { label: "Flat", value: "flat" },
11422
11827
  { label: "Per quantity", value: "per_quantity" },
@@ -11468,10 +11873,10 @@ function UtilitySection({ node }) {
11468
11873
  canvas.api.editor.updateOption(node.id, { meta: nextMeta });
11469
11874
  });
11470
11875
  };
11471
- return /* @__PURE__ */ jsxs35(Section, { children: [
11472
- /* @__PURE__ */ jsxs35(Section.Header, { children: [
11876
+ return /* @__PURE__ */ jsxs36(Section, { children: [
11877
+ /* @__PURE__ */ jsxs36(Section.Header, { children: [
11473
11878
  /* @__PURE__ */ jsx53(Section.Title, { children: "Utility" }),
11474
- /* @__PURE__ */ jsxs35(Section.Actions, { children: [
11879
+ /* @__PURE__ */ jsxs36(Section.Actions, { children: [
11475
11880
  !hasStoredUtility && !isActiveUtility ? /* @__PURE__ */ jsx53(
11476
11881
  SectionActionButton,
11477
11882
  {
@@ -11504,10 +11909,10 @@ function UtilitySection({ node }) {
11504
11909
  ) : null
11505
11910
  ] })
11506
11911
  ] }),
11507
- /* @__PURE__ */ jsx53(Section.Content, { children: hasUtilityConfiguration ? /* @__PURE__ */ jsxs35("div", { className: "space-y-3", children: [
11912
+ /* @__PURE__ */ jsx53(Section.Content, { children: hasUtilityConfiguration ? /* @__PURE__ */ jsxs36("div", { className: "space-y-3", children: [
11508
11913
  !hasStoredUtility ? /* @__PURE__ */ jsx53("p", { className: "text-xs text-slate-500 dark:text-slate-400", children: "This node is marked as utility-priced, but its utility marker is missing. Fill in the values below to repair it." }) : null,
11509
11914
  hasStoredUtility && !isActiveUtility ? /* @__PURE__ */ jsx53("p", { className: "text-xs text-slate-500 dark:text-slate-400", children: "This node still has utility marker values stored, but its pricing role is base. Activate utility to apply these charges, or clear the marker." }) : null,
11510
- /* @__PURE__ */ jsxs35(Fragment10, { children: [
11915
+ /* @__PURE__ */ jsxs36(Fragment10, { children: [
11511
11916
  /* @__PURE__ */ jsx53(
11512
11917
  InputField8,
11513
11918
  {
@@ -11586,7 +11991,7 @@ import { InputField as InputField9 } from "@timeax/form-palette";
11586
11991
  import { useMemo as useMemo26 } from "react";
11587
11992
  import { BsPlus as BsPlus4 } from "react-icons/bs";
11588
11993
  import { MdDeleteOutline as MdDeleteOutline3 } from "react-icons/md";
11589
- import { jsx as jsx54, jsxs as jsxs36 } from "react/jsx-runtime";
11994
+ import { jsx as jsx54, jsxs as jsxs37 } from "react/jsx-runtime";
11590
11995
  var opOptions = [
11591
11996
  { label: "Equals", value: "eq" },
11592
11997
  { label: "Not equal", value: "neq" },
@@ -11659,7 +12064,7 @@ function TypedScalarEditor({
11659
12064
  onChange
11660
12065
  }) {
11661
12066
  const scalarType = inferScalarType(value);
11662
- return /* @__PURE__ */ jsx54("div", { className: "space-y-3 rounded-lg border border-slate-200/80 p-3 dark:border-slate-800", children: /* @__PURE__ */ jsxs36("div", { className: "grid gap-3 md:grid-cols-[160px_minmax(0,1fr)]", children: [
12067
+ return /* @__PURE__ */ jsx54("div", { className: "space-y-3 rounded-lg border border-slate-200/80 p-3 dark:border-slate-800", children: /* @__PURE__ */ jsxs37("div", { className: "grid gap-3 md:grid-cols-[160px_minmax(0,1fr)]", children: [
11663
12068
  /* @__PURE__ */ jsx54(
11664
12069
  InputField9,
11665
12070
  {
@@ -11705,17 +12110,17 @@ function TypedScalarListEditor({
11705
12110
  onChange
11706
12111
  }) {
11707
12112
  const items = (values ?? []).filter((value) => ["string", "number", "boolean"].includes(typeof value));
11708
- return /* @__PURE__ */ jsxs36("div", { className: "space-y-3 rounded-lg border border-slate-200/80 p-3 dark:border-slate-800", children: [
11709
- /* @__PURE__ */ jsxs36("div", { className: "flex items-center justify-between gap-3", children: [
11710
- /* @__PURE__ */ jsxs36("div", { children: [
12113
+ return /* @__PURE__ */ jsxs37("div", { className: "space-y-3 rounded-lg border border-slate-200/80 p-3 dark:border-slate-800", children: [
12114
+ /* @__PURE__ */ jsxs37("div", { className: "flex items-center justify-between gap-3", children: [
12115
+ /* @__PURE__ */ jsxs37("div", { children: [
11711
12116
  /* @__PURE__ */ jsx54("h4", { className: "text-sm font-semibold text-slate-900 dark:text-slate-100", children: "Allowed values" }),
11712
12117
  /* @__PURE__ */ jsx54("p", { className: "mt-1 text-xs text-slate-500 dark:text-slate-400", children: "Rule values are checked in the order shown here." })
11713
12118
  ] }),
11714
12119
  /* @__PURE__ */ jsx54(Button, { type: "button", variant: "outline", size: "sm", onClick: () => onChange([...items, ""]), children: "Add value" })
11715
12120
  ] }),
11716
- items.length ? /* @__PURE__ */ jsx54("div", { className: "space-y-3", children: items.map((item, index) => /* @__PURE__ */ jsxs36("div", { className: "space-y-3 rounded-lg border border-dashed border-slate-200 p-3 dark:border-slate-700", children: [
11717
- /* @__PURE__ */ jsxs36("div", { className: "flex items-center justify-between gap-3", children: [
11718
- /* @__PURE__ */ jsxs36("div", { className: "text-xs font-medium tracking-[0.16em] text-slate-500 uppercase dark:text-slate-400", children: [
12121
+ items.length ? /* @__PURE__ */ jsx54("div", { className: "space-y-3", children: items.map((item, index) => /* @__PURE__ */ jsxs37("div", { className: "space-y-3 rounded-lg border border-dashed border-slate-200 p-3 dark:border-slate-700", children: [
12122
+ /* @__PURE__ */ jsxs37("div", { className: "flex items-center justify-between gap-3", children: [
12123
+ /* @__PURE__ */ jsxs37("div", { className: "text-xs font-medium tracking-[0.16em] text-slate-500 uppercase dark:text-slate-400", children: [
11719
12124
  "Value ",
11720
12125
  index + 1
11721
12126
  ] }),
@@ -11749,10 +12154,10 @@ function ValidationRuleCard({
11749
12154
  onRemove
11750
12155
  }) {
11751
12156
  const valueBy = rule.valueBy ?? "value";
11752
- return /* @__PURE__ */ jsxs36("div", { className: "space-y-4 rounded-xl border border-slate-200 p-4 dark:border-slate-800", children: [
11753
- /* @__PURE__ */ jsxs36("div", { className: "flex items-start justify-between gap-3", children: [
11754
- /* @__PURE__ */ jsxs36("div", { children: [
11755
- /* @__PURE__ */ jsxs36("div", { className: "text-xs font-medium tracking-[0.16em] text-slate-500 uppercase dark:text-slate-400", children: [
12157
+ return /* @__PURE__ */ jsxs37("div", { className: "space-y-4 rounded-xl border border-slate-200 p-4 dark:border-slate-800", children: [
12158
+ /* @__PURE__ */ jsxs37("div", { className: "flex items-start justify-between gap-3", children: [
12159
+ /* @__PURE__ */ jsxs37("div", { children: [
12160
+ /* @__PURE__ */ jsxs37("div", { className: "text-xs font-medium tracking-[0.16em] text-slate-500 uppercase dark:text-slate-400", children: [
11756
12161
  "Rule ",
11757
12162
  index + 1
11758
12163
  ] }),
@@ -11769,7 +12174,7 @@ function ValidationRuleCard({
11769
12174
  }
11770
12175
  )
11771
12176
  ] }),
11772
- /* @__PURE__ */ jsxs36("div", { className: "grid gap-3 md:grid-cols-2", children: [
12177
+ /* @__PURE__ */ jsxs37("div", { className: "grid gap-3 md:grid-cols-2", children: [
11773
12178
  /* @__PURE__ */ jsx54(
11774
12179
  InputField9,
11775
12180
  {
@@ -11829,7 +12234,7 @@ function ValidationRuleCard({
11829
12234
  )
11830
12235
  }
11831
12236
  ) : null,
11832
- rule.op === "between" ? /* @__PURE__ */ jsxs36("div", { className: "grid gap-3 md:grid-cols-2", children: [
12237
+ rule.op === "between" ? /* @__PURE__ */ jsxs37("div", { className: "grid gap-3 md:grid-cols-2", children: [
11833
12238
  /* @__PURE__ */ jsx54(
11834
12239
  InputField9,
11835
12240
  {
@@ -11873,7 +12278,7 @@ function ValidationRuleCard({
11873
12278
  )
11874
12279
  }
11875
12280
  ) : null,
11876
- rule.op === "match" ? /* @__PURE__ */ jsxs36("div", { className: "grid gap-3 md:grid-cols-2", children: [
12281
+ rule.op === "match" ? /* @__PURE__ */ jsxs37("div", { className: "grid gap-3 md:grid-cols-2", children: [
11877
12282
  /* @__PURE__ */ jsx54(
11878
12283
  InputField9,
11879
12284
  {
@@ -11947,10 +12352,10 @@ function ValidationSection({ node }) {
11947
12352
  const removeRuleAt = (index) => {
11948
12353
  persistRules(rules.filter((_, ruleIndex) => ruleIndex !== index));
11949
12354
  };
11950
- return /* @__PURE__ */ jsxs36(Section, { children: [
11951
- /* @__PURE__ */ jsxs36(Section.Header, { children: [
12355
+ return /* @__PURE__ */ jsxs37(Section, { children: [
12356
+ /* @__PURE__ */ jsxs37(Section.Header, { children: [
11952
12357
  /* @__PURE__ */ jsx54(Section.Title, { children: "Validation" }),
11953
- /* @__PURE__ */ jsxs36(Section.Actions, { children: [
12358
+ /* @__PURE__ */ jsxs37(Section.Actions, { children: [
11954
12359
  !rules.length ? /* @__PURE__ */ jsx54(SectionActionButton, { icon: /* @__PURE__ */ jsx54(BsPlus4, {}), iconOnly: true, tooltip: "Add validation", "aria-label": "Add validation", onClick: addRule }) : null,
11955
12360
  rules.length ? /* @__PURE__ */ jsx54(
11956
12361
  SectionActionButton,
@@ -11964,7 +12369,7 @@ function ValidationSection({ node }) {
11964
12369
  ) : null
11965
12370
  ] })
11966
12371
  ] }),
11967
- /* @__PURE__ */ jsx54(Section.Content, { children: rules.length ? /* @__PURE__ */ jsxs36("div", { className: "space-y-4", children: [
12372
+ /* @__PURE__ */ jsx54(Section.Content, { children: rules.length ? /* @__PURE__ */ jsxs37("div", { className: "space-y-4", children: [
11968
12373
  rules.map((rule, index) => /* @__PURE__ */ jsx54(
11969
12374
  ValidationRuleCard,
11970
12375
  {
@@ -11976,7 +12381,7 @@ function ValidationSection({ node }) {
11976
12381
  `${index}-${rule.op}-${rule.valueBy ?? "value"}`
11977
12382
  )),
11978
12383
  /* @__PURE__ */ jsx54(Button, { type: "button", variant: "outline", size: "sm", onClick: addRule, children: "Add another rule" })
11979
- ] }) : /* @__PURE__ */ jsxs36("div", { className: "space-y-3 rounded-xl border border-dashed border-slate-200 p-4 dark:border-slate-800", children: [
12384
+ ] }) : /* @__PURE__ */ jsxs37("div", { className: "space-y-3 rounded-xl border border-dashed border-slate-200 p-4 dark:border-slate-800", children: [
11980
12385
  /* @__PURE__ */ jsx54("p", { className: "text-sm font-medium text-slate-900 dark:text-slate-100", children: "No validation rules yet" }),
11981
12386
  /* @__PURE__ */ jsx54("p", { className: "text-xs text-slate-500 dark:text-slate-400", children: "Add ordered rules to validate this field value, its length, or an eval-derived subject. The first failing rule supplies the field message." }),
11982
12387
  /* @__PURE__ */ jsx54(Button, { type: "button", variant: "outline", size: "sm", onClick: addRule, children: "Add validation" })
@@ -11994,12 +12399,12 @@ import { useMemo as useMemo27, useState as useState27 } from "react";
11994
12399
  import { InputField as InputField10 } from "@timeax/form-palette";
11995
12400
  import { useState as useState26 } from "react";
11996
12401
  import { BsPlus as BsPlus5 } from "react-icons/bs";
11997
- import { jsx as jsx55, jsxs as jsxs37 } from "react/jsx-runtime";
12402
+ import { jsx as jsx55, jsxs as jsxs38 } from "react/jsx-runtime";
11998
12403
  function AddIncludesPopover({ open, onOpenChange, onSelect, options }) {
11999
12404
  const [value, setValue] = useState26();
12000
- return /* @__PURE__ */ jsxs37(Popover, { open, onOpenChange, children: [
12405
+ return /* @__PURE__ */ jsxs38(Popover, { open, onOpenChange, children: [
12001
12406
  /* @__PURE__ */ jsx55(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx55(SectionActionTriggerButton, { icon: /* @__PURE__ */ jsx55(BsPlus5, {}), children: "Add" }) }),
12002
- /* @__PURE__ */ jsx55(PopoverContent, { children: /* @__PURE__ */ jsxs37("div", { className: "flex flex-col gap-2", children: [
12407
+ /* @__PURE__ */ jsx55(PopoverContent, { children: /* @__PURE__ */ jsxs38("div", { className: "flex flex-col gap-2", children: [
12003
12408
  /* @__PURE__ */ jsx55(
12004
12409
  InputField10,
12005
12410
  {
@@ -12030,7 +12435,7 @@ function AddIncludesPopover({ open, onOpenChange, onSelect, options }) {
12030
12435
  }
12031
12436
 
12032
12437
  // src/panels/right/partials/properties/components/Union.tsx
12033
- import { jsx as jsx56, jsxs as jsxs38 } from "react/jsx-runtime";
12438
+ import { jsx as jsx56, jsxs as jsxs39 } from "react/jsx-runtime";
12034
12439
  function IncExcludeSection({ node, mode, capability }) {
12035
12440
  const canvas = useCanvas11();
12036
12441
  const [open, setOpen] = useState27(false);
@@ -12066,8 +12471,8 @@ function IncExcludeSection({ node, mode, capability }) {
12066
12471
  }));
12067
12472
  }, [canvas.props.fields, node]);
12068
12473
  const name = mode.slice(0, -1);
12069
- return /* @__PURE__ */ jsxs38(Section, { children: [
12070
- /* @__PURE__ */ jsxs38(Section.Header, { children: [
12474
+ return /* @__PURE__ */ jsxs39(Section, { children: [
12475
+ /* @__PURE__ */ jsxs39(Section.Header, { children: [
12071
12476
  /* @__PURE__ */ jsx56(Section.Title, { children: mode == "includes" ? "Includes" : "Excludes" }),
12072
12477
  /* @__PURE__ */ jsx56(Section.Actions, { children: canEdit ? /* @__PURE__ */ jsx56(
12073
12478
  AddIncludesPopover,
@@ -12079,7 +12484,7 @@ function IncExcludeSection({ node, mode, capability }) {
12079
12484
  }
12080
12485
  ) : null })
12081
12486
  ] }),
12082
- /* @__PURE__ */ jsxs38(Section.Content, { children: [
12487
+ /* @__PURE__ */ jsxs39(Section.Content, { children: [
12083
12488
  helperMessage ? /* @__PURE__ */ jsx56("p", { className: "mb-3 text-xs text-slate-500 dark:text-slate-400", children: helperMessage }) : null,
12084
12489
  /* @__PURE__ */ jsx56(RenderIf, { data: (node[mode]?.size ?? 0) > 0, emptyMessage: "None", children: /* @__PURE__ */ jsx56(IncludesList, { children: Array.from(node[mode] ?? []).map((id) => {
12085
12490
  const field = fields[id];
@@ -12111,7 +12516,7 @@ function IncExcludeSection({ node, mode, capability }) {
12111
12516
  }
12112
12517
 
12113
12518
  // src/panels/right/partials/properties/field-properties.tsx
12114
- import { Fragment as Fragment11, jsx as jsx57, jsxs as jsxs39 } from "react/jsx-runtime";
12519
+ import { Fragment as Fragment11, jsx as jsx57, jsxs as jsxs40 } from "react/jsx-runtime";
12115
12520
  var getVariant = (node) => {
12116
12521
  const variant = node.raw.meta?.variant;
12117
12522
  return typeof variant === "string" && variant.trim() ? variant.trim() : void 0;
@@ -12140,13 +12545,13 @@ function FieldProperties({ className, node }) {
12140
12545
  const descriptor = useMemo28(() => resolveInputDescriptor(registry, currentType, currentVariant), [currentType, currentVariant, registry]);
12141
12546
  const descriptorUi = descriptor?.ui ?? {};
12142
12547
  const descriptorKeySet = useMemo28(() => new Set(getDescriptorUiKeys(descriptorUi)), [descriptorUi]);
12143
- useEffect17(() => {
12548
+ useEffect18(() => {
12144
12549
  setNameDraft(nameValue);
12145
12550
  }, [node.id, nameValue]);
12146
- useEffect17(() => {
12551
+ useEffect18(() => {
12147
12552
  setPlaceholderDraft(placeholderValue);
12148
12553
  }, [node.id, placeholderValue]);
12149
- useEffect17(() => {
12554
+ useEffect18(() => {
12150
12555
  setHelpTextDraft(helpTextValue);
12151
12556
  }, [node.id, helpTextValue]);
12152
12557
  const fieldTypeOptions = useMemo28(() => {
@@ -12203,12 +12608,12 @@ function FieldProperties({ className, node }) {
12203
12608
  const nextVariant = String(rawVariant ?? "default");
12204
12609
  applyDescriptorTransition(currentType, nextVariant === "default" ? void 0 : nextVariant);
12205
12610
  };
12206
- return /* @__PURE__ */ jsx57("div", { className, children: /* @__PURE__ */ jsxs39("div", { className: "space-y-4", children: [
12207
- /* @__PURE__ */ jsxs39(Section, { children: [
12611
+ return /* @__PURE__ */ jsx57("div", { className, children: /* @__PURE__ */ jsxs40("div", { className: "space-y-4", children: [
12612
+ /* @__PURE__ */ jsxs40(Section, { children: [
12208
12613
  /* @__PURE__ */ jsx57(Section.Header, { children: /* @__PURE__ */ jsx57(Section.Title, { children: "Field identity" }) }),
12209
- /* @__PURE__ */ jsxs39(Section.Content, { children: [
12614
+ /* @__PURE__ */ jsxs40(Section.Content, { children: [
12210
12615
  /* @__PURE__ */ jsx57("p", { className: "mb-3 text-xs text-slate-500 dark:text-slate-400", children: "Core field metadata used by the service engine and preview form." }),
12211
- /* @__PURE__ */ jsxs39("div", { className: "space-y-3", children: [
12616
+ /* @__PURE__ */ jsxs40("div", { className: "space-y-3", children: [
12212
12617
  /* @__PURE__ */ jsx57(
12213
12618
  InputField11,
12214
12619
  {
@@ -12264,11 +12669,11 @@ function FieldProperties({ className, node }) {
12264
12669
  ] })
12265
12670
  ] }),
12266
12671
  /* @__PURE__ */ jsx57(Separator2, {}),
12267
- /* @__PURE__ */ jsxs39(Section, { children: [
12672
+ /* @__PURE__ */ jsxs40(Section, { children: [
12268
12673
  /* @__PURE__ */ jsx57(Section.Header, { children: /* @__PURE__ */ jsx57(Section.Title, { children: "Defaults and help" }) }),
12269
- /* @__PURE__ */ jsxs39(Section.Content, { children: [
12674
+ /* @__PURE__ */ jsxs40(Section.Content, { children: [
12270
12675
  /* @__PURE__ */ jsx57("p", { className: "mb-3 text-xs text-slate-500 dark:text-slate-400", children: "Preview-oriented defaults passed to the form palette." }),
12271
- /* @__PURE__ */ jsxs39("div", { className: "space-y-3", children: [
12676
+ /* @__PURE__ */ jsxs40("div", { className: "space-y-3", children: [
12272
12677
  /* @__PURE__ */ jsx57(
12273
12678
  InputField11,
12274
12679
  {
@@ -12293,11 +12698,11 @@ function FieldProperties({ className, node }) {
12293
12698
  ] })
12294
12699
  ] }),
12295
12700
  /* @__PURE__ */ jsx57(Separator2, {}),
12296
- /* @__PURE__ */ jsxs39(Section, { defaultOpen: false, children: [
12701
+ /* @__PURE__ */ jsxs40(Section, { defaultOpen: false, children: [
12297
12702
  /* @__PURE__ */ jsx57(Section.Header, { children: /* @__PURE__ */ jsx57(Section.Title, { children: "Input appearance and behavior" }) }),
12298
- /* @__PURE__ */ jsxs39(Section.Content, { children: [
12703
+ /* @__PURE__ */ jsxs40(Section.Content, { children: [
12299
12704
  /* @__PURE__ */ jsx57("p", { className: "mb-3 text-xs text-slate-500 dark:text-slate-400", children: "Descriptor-owned runtime props. The schema comes from the input registry and overrides are stored in field defaults." }),
12300
- descriptor ? /* @__PURE__ */ jsx57(DescriptorSettings, { schema: descriptorUi, defaults, onChange: updateDefaults }) : /* @__PURE__ */ jsxs39("p", { className: "text-xs text-slate-500 dark:text-slate-400", children: [
12705
+ descriptor ? /* @__PURE__ */ jsx57(DescriptorSettings, { schema: descriptorUi, defaults, onChange: updateDefaults }) : /* @__PURE__ */ jsxs40("p", { className: "text-xs text-slate-500 dark:text-slate-400", children: [
12301
12706
  "No input descriptor was found for this field type",
12302
12707
  currentVariant ? ` / ${currentVariant}` : "",
12303
12708
  "."
@@ -12311,9 +12716,9 @@ function FieldProperties({ className, node }) {
12311
12716
  /* @__PURE__ */ jsx57(Separator2, {}),
12312
12717
  /* @__PURE__ */ jsx57(utility_section_default, { node }),
12313
12718
  /* @__PURE__ */ jsx57(Separator2, {}),
12314
- /* @__PURE__ */ jsxs39(Section, { children: [
12719
+ /* @__PURE__ */ jsxs40(Section, { children: [
12315
12720
  /* @__PURE__ */ jsx57(Section.Header, { children: /* @__PURE__ */ jsx57(Section.Title, { children: "Binding summary" }) }),
12316
- /* @__PURE__ */ jsxs39(Section.Content, { children: [
12721
+ /* @__PURE__ */ jsxs40(Section.Content, { children: [
12317
12722
  /* @__PURE__ */ jsx57("p", { className: "mb-3 text-xs text-slate-500 dark:text-slate-400", children: "Where this field appears and how it behaves in the active branch." }),
12318
12723
  /* @__PURE__ */ jsx57(
12319
12724
  PropertyList,
@@ -12328,12 +12733,12 @@ function FieldProperties({ className, node }) {
12328
12733
  ] })
12329
12734
  ] }),
12330
12735
  /* @__PURE__ */ jsx57(Separator2, {}),
12331
- options.length ? /* @__PURE__ */ jsxs39(Fragment11, { children: [
12332
- /* @__PURE__ */ jsxs39(Section, { children: [
12736
+ options.length ? /* @__PURE__ */ jsxs40(Fragment11, { children: [
12737
+ /* @__PURE__ */ jsxs40(Section, { children: [
12333
12738
  /* @__PURE__ */ jsx57(Section.Header, { children: /* @__PURE__ */ jsx57(Section.Title, { children: "Options" }) }),
12334
- /* @__PURE__ */ jsxs39(Section.Content, { children: [
12739
+ /* @__PURE__ */ jsxs40(Section.Content, { children: [
12335
12740
  /* @__PURE__ */ jsx57("p", { className: "mb-3 text-xs text-slate-500 dark:text-slate-400", children: "Current option labels available on this field." }),
12336
- /* @__PURE__ */ jsx57("div", { className: "space-y-2", children: options.map((option) => /* @__PURE__ */ jsxs39(
12741
+ /* @__PURE__ */ jsx57("div", { className: "space-y-2", children: options.map((option) => /* @__PURE__ */ jsxs40(
12337
12742
  "div",
12338
12743
  {
12339
12744
  className: "flex items-center justify-between rounded-xl bg-slate-50 px-3 py-2 text-sm dark:bg-slate-900",
@@ -12356,11 +12761,11 @@ function FieldProperties({ className, node }) {
12356
12761
  ] }),
12357
12762
  /* @__PURE__ */ jsx57(Separator2, {})
12358
12763
  ] }) : null,
12359
- capabilities.triggerMappings.canEdit ? /* @__PURE__ */ jsxs39(Fragment11, { children: [
12764
+ capabilities.triggerMappings.canEdit ? /* @__PURE__ */ jsxs40(Fragment11, { children: [
12360
12765
  /* @__PURE__ */ jsx57(IncExcludeSection, { node, mode: "includes", capability: capabilities.triggerMappings }),
12361
12766
  /* @__PURE__ */ jsx57(Separator2, {}),
12362
12767
  /* @__PURE__ */ jsx57(IncExcludeSection, { node, mode: "excludes", capability: capabilities.triggerMappings })
12363
- ] }) : /* @__PURE__ */ jsxs39(Section, { children: [
12768
+ ] }) : /* @__PURE__ */ jsxs40(Section, { children: [
12364
12769
  /* @__PURE__ */ jsx57(Section.Header, { children: /* @__PURE__ */ jsx57(Section.Title, { children: "Trigger mappings" }) }),
12365
12770
  /* @__PURE__ */ jsx57(Section.Content, { children: /* @__PURE__ */ jsx57("p", { className: "text-xs text-slate-500 dark:text-slate-400", children: capabilities.triggerMappings.message }) })
12366
12771
  ] }),
@@ -12373,18 +12778,18 @@ var field_properties_default = FieldProperties;
12373
12778
  // src/panels/right/partials/properties/option-properties.tsx
12374
12779
  import { useCanvas as useCanvas13 } from "@timeax/digital-service-engine/workspace";
12375
12780
  import { InputField as InputField12 } from "@timeax/form-palette";
12376
- import { jsx as jsx58, jsxs as jsxs40 } from "react/jsx-runtime";
12781
+ import { jsx as jsx58, jsxs as jsxs41 } from "react/jsx-runtime";
12377
12782
  function OptionProperties({ className, node }) {
12378
12783
  const canvas = useCanvas13();
12379
12784
  const capabilities = getOptionPropertyCapabilities(node);
12380
12785
  const field = node.field();
12381
12786
  const options = field.raw.options ?? [];
12382
- return /* @__PURE__ */ jsx58("div", { className, children: /* @__PURE__ */ jsxs40("div", { className: "space-y-4", children: [
12383
- /* @__PURE__ */ jsxs40(Section, { children: [
12787
+ return /* @__PURE__ */ jsx58("div", { className, children: /* @__PURE__ */ jsxs41("div", { className: "space-y-4", children: [
12788
+ /* @__PURE__ */ jsxs41(Section, { children: [
12384
12789
  /* @__PURE__ */ jsx58(Section.Header, { children: /* @__PURE__ */ jsx58(Section.Title, { children: "Option identity" }) }),
12385
- /* @__PURE__ */ jsxs40(Section.Content, { children: [
12790
+ /* @__PURE__ */ jsxs41(Section.Content, { children: [
12386
12791
  /* @__PURE__ */ jsx58("p", { className: "mb-3 text-xs text-slate-500 dark:text-slate-400", children: "Edit the currently focused option node." }),
12387
- /* @__PURE__ */ jsxs40("div", { className: "space-y-3", children: [
12792
+ /* @__PURE__ */ jsxs41("div", { className: "space-y-3", children: [
12388
12793
  /* @__PURE__ */ jsx58(
12389
12794
  InputField12,
12390
12795
  {
@@ -12422,9 +12827,9 @@ function OptionProperties({ className, node }) {
12422
12827
  /* @__PURE__ */ jsx58(Separator2, {}),
12423
12828
  /* @__PURE__ */ jsx58(utility_section_default, { node }),
12424
12829
  /* @__PURE__ */ jsx58(Separator2, {}),
12425
- /* @__PURE__ */ jsxs40(Section, { children: [
12830
+ /* @__PURE__ */ jsxs41(Section, { children: [
12426
12831
  /* @__PURE__ */ jsx58(Section.Header, { children: /* @__PURE__ */ jsx58(Section.Title, { children: "Option mapping" }) }),
12427
- /* @__PURE__ */ jsxs40(Section.Content, { children: [
12832
+ /* @__PURE__ */ jsxs41(Section.Content, { children: [
12428
12833
  /* @__PURE__ */ jsx58("p", { className: "mb-3 text-xs text-slate-500 dark:text-slate-400", children: "How this option participates in visible field mappings." }),
12429
12834
  /* @__PURE__ */ jsx58(
12430
12835
  PropertyList,
@@ -12463,11 +12868,11 @@ import { TiDelete } from "react-icons/ti";
12463
12868
  import { Form, InputField as InputField13 } from "@timeax/form-palette";
12464
12869
  import "react";
12465
12870
  import { BsPlus as BsPlus6 } from "react-icons/bs";
12466
- import { jsx as jsx59, jsxs as jsxs41 } from "react/jsx-runtime";
12871
+ import { jsx as jsx59, jsxs as jsxs42 } from "react/jsx-runtime";
12467
12872
  function AddConstraintsPopover({ open, onOpenChange, constraints, allConstraints, onSubmit }) {
12468
- return /* @__PURE__ */ jsxs41(Popover, { open, onOpenChange, children: [
12873
+ return /* @__PURE__ */ jsxs42(Popover, { open, onOpenChange, children: [
12469
12874
  /* @__PURE__ */ jsx59(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx59(SectionActionTriggerButton, { icon: /* @__PURE__ */ jsx59(BsPlus6, {}), children: "Add" }) }),
12470
- /* @__PURE__ */ jsx59(PopoverContent, { children: /* @__PURE__ */ jsx59(RenderIf, { data: allConstraints, children: /* @__PURE__ */ jsxs41(
12875
+ /* @__PURE__ */ jsx59(PopoverContent, { children: /* @__PURE__ */ jsx59(RenderIf, { data: allConstraints, children: /* @__PURE__ */ jsxs42(
12471
12876
  Form,
12472
12877
  {
12473
12878
  wrapped: true,
@@ -12498,20 +12903,20 @@ function AddConstraintsPopover({ open, onOpenChange, constraints, allConstraints
12498
12903
 
12499
12904
  // src/panels/right/partials/properties/tag/ConstraintOriginPopover.tsx
12500
12905
  import "react";
12501
- import { jsx as jsx60, jsxs as jsxs42 } from "react/jsx-runtime";
12906
+ import { jsx as jsx60, jsxs as jsxs43 } from "react/jsx-runtime";
12502
12907
  function ConstraintOriginPopover({ constraint, onClearSelf, onClearSubtree }) {
12503
- return /* @__PURE__ */ jsxs42(Popover, { children: [
12908
+ return /* @__PURE__ */ jsxs43(Popover, { children: [
12504
12909
  /* @__PURE__ */ jsx60(PopoverTrigger, { className: "flex items-center gap-1", children: "Owner" }),
12505
- /* @__PURE__ */ jsx60(PopoverContent, { className: "w-fit p-0", children: /* @__PURE__ */ jsxs42("div", { className: "max-w-[320px] p-3 text-sm", children: [
12910
+ /* @__PURE__ */ jsx60(PopoverContent, { className: "w-fit p-0", children: /* @__PURE__ */ jsxs43("div", { className: "max-w-[320px] p-3 text-sm", children: [
12506
12911
  /* @__PURE__ */ jsx60("div", { className: "font-medium", children: "Clear constraint?" }),
12507
- /* @__PURE__ */ jsxs42("div", { className: "mt-1 text-muted-foreground", children: [
12912
+ /* @__PURE__ */ jsxs43("div", { className: "mt-1 text-muted-foreground", children: [
12508
12913
  "You're about to clear ",
12509
12914
  /* @__PURE__ */ jsx60("span", { className: "font-medium", children: constraint }),
12510
12915
  " on this tag. Descendants may inherit a different value (or none) after this change."
12511
12916
  ] }),
12512
- /* @__PURE__ */ jsxs42("div", { className: "mt-3 space-y-2", children: [
12917
+ /* @__PURE__ */ jsxs43("div", { className: "mt-3 space-y-2", children: [
12513
12918
  /* @__PURE__ */ jsx60("div", { className: "text-muted-foreground", children: "Do you want to also clear it for the whole subtree (\xE2\u20AC\u0153shake the tree\xE2\u20AC\x9D)?" }),
12514
- /* @__PURE__ */ jsxs42("div", { className: "flex items-center justify-end gap-2", children: [
12919
+ /* @__PURE__ */ jsxs43("div", { className: "flex items-center justify-end gap-2", children: [
12515
12920
  /* @__PURE__ */ jsx60(
12516
12921
  "button",
12517
12922
  {
@@ -12539,24 +12944,24 @@ function ConstraintOriginPopover({ constraint, onClearSelf, onClearSubtree }) {
12539
12944
  // src/panels/right/partials/properties/tag/ConstraintOverridePopover.tsx
12540
12945
  import { AlertTriangle } from "lucide-react";
12541
12946
  import "react";
12542
- import { jsx as jsx61, jsxs as jsxs43 } from "react/jsx-runtime";
12947
+ import { jsx as jsx61, jsxs as jsxs44 } from "react/jsx-runtime";
12543
12948
  function ConstraintOverridePopover({ constraint, onClear }) {
12544
- return /* @__PURE__ */ jsxs43(Popover, { children: [
12545
- /* @__PURE__ */ jsxs43(PopoverTrigger, { className: "flex items-center gap-1", children: [
12949
+ return /* @__PURE__ */ jsxs44(Popover, { children: [
12950
+ /* @__PURE__ */ jsxs44(PopoverTrigger, { className: "flex items-center gap-1", children: [
12546
12951
  /* @__PURE__ */ jsx61(AlertTriangle, { className: "size-3 text-yellow-400" }),
12547
12952
  "Overridden"
12548
12953
  ] }),
12549
- /* @__PURE__ */ jsx61(PopoverContent, { className: "w-fit p-0", children: /* @__PURE__ */ jsxs43("div", { className: "max-w-[320px] p-3 text-sm", children: [
12954
+ /* @__PURE__ */ jsx61(PopoverContent, { className: "w-fit p-0", children: /* @__PURE__ */ jsxs44("div", { className: "max-w-[320px] p-3 text-sm", children: [
12550
12955
  /* @__PURE__ */ jsx61("div", { className: "font-medium", children: "Constraint override detected" }),
12551
- /* @__PURE__ */ jsxs43("div", { className: "mt-1 text-muted-foreground", children: [
12956
+ /* @__PURE__ */ jsxs44("div", { className: "mt-1 text-muted-foreground", children: [
12552
12957
  "This tag tries to set ",
12553
12958
  /* @__PURE__ */ jsx61("span", { className: "font-medium", children: constraint }),
12554
12959
  ", but an ancestor tag already decided it. Overrides don't apply \xE2\u20AC\u201D the ancestor value wins."
12555
12960
  ] }),
12556
- /* @__PURE__ */ jsxs43("div", { className: "mt-3 space-y-1", children: [
12961
+ /* @__PURE__ */ jsxs44("div", { className: "mt-3 space-y-1", children: [
12557
12962
  /* @__PURE__ */ jsx61("div", { className: "font-medium", children: "How to fix" }),
12558
- /* @__PURE__ */ jsxs43("ul", { className: "list-disc pl-4 text-muted-foreground", children: [
12559
- /* @__PURE__ */ jsxs43("li", { children: [
12963
+ /* @__PURE__ */ jsxs44("ul", { className: "list-disc pl-4 text-muted-foreground", children: [
12964
+ /* @__PURE__ */ jsxs44("li", { children: [
12560
12965
  "Click ",
12561
12966
  /* @__PURE__ */ jsx61("span", { className: "font-medium", children: "Origin" }),
12562
12967
  " to jump to the ancestor that set the rule, then make the value match there (or remove it)."
@@ -12578,14 +12983,14 @@ function ConstraintOverridePopover({ constraint, onClear }) {
12578
12983
  }
12579
12984
 
12580
12985
  // src/panels/right/partials/properties/tag/TagConstraintsSection.tsx
12581
- import { Fragment as Fragment12, jsx as jsx62, jsxs as jsxs44 } from "react/jsx-runtime";
12986
+ import { Fragment as Fragment12, jsx as jsx62, jsxs as jsxs45 } from "react/jsx-runtime";
12582
12987
  function TagConstraintsSection({ node }) {
12583
12988
  const constraints = Object.keys(node.raw.constraints ?? {});
12584
12989
  const canvas = useCanvas14();
12585
12990
  const [open, setOpen] = useState29(false);
12586
12991
  const allConstraints = useMemo29(() => canvas.api.getConstraints() ?? [], [canvas.props]);
12587
- return /* @__PURE__ */ jsx62(Fragment12, { children: /* @__PURE__ */ jsxs44(Section, { children: [
12588
- /* @__PURE__ */ jsxs44(Section.Header, { children: [
12992
+ return /* @__PURE__ */ jsx62(Fragment12, { children: /* @__PURE__ */ jsxs45(Section, { children: [
12993
+ /* @__PURE__ */ jsxs45(Section.Header, { children: [
12589
12994
  /* @__PURE__ */ jsx62(Section.Title, { children: "Constraints" }),
12590
12995
  /* @__PURE__ */ jsx62(Section.Actions, { children: /* @__PURE__ */ jsx62(
12591
12996
  AddConstraintsPopover,
@@ -12680,10 +13085,10 @@ function TagExcludesSection({ node }) {
12680
13085
  }
12681
13086
 
12682
13087
  // src/panels/right/partials/properties/tag.tsx
12683
- import { Fragment as Fragment13, jsx as jsx65, jsxs as jsxs45 } from "react/jsx-runtime";
13088
+ import { Fragment as Fragment13, jsx as jsx65, jsxs as jsxs46 } from "react/jsx-runtime";
12684
13089
  function TagProperties({ node }) {
12685
13090
  const capabilities = getTagPropertyCapabilities();
12686
- return /* @__PURE__ */ jsxs45(Fragment13, { children: [
13091
+ return /* @__PURE__ */ jsxs46(Fragment13, { children: [
12687
13092
  /* @__PURE__ */ jsx65(TagConstraintsSection, { node }),
12688
13093
  /* @__PURE__ */ jsx65(Separator2, {}),
12689
13094
  /* @__PURE__ */ jsx65(quantity_section_default, { node }),
@@ -12702,7 +13107,7 @@ import { InputField as InputField15 } from "@timeax/form-palette";
12702
13107
  import { useMemo as useMemo30, useState as useState30 } from "react";
12703
13108
  import { AiOutlineLoading3Quarters } from "react-icons/ai";
12704
13109
  import { MdOutlineContentCopy } from "react-icons/md";
12705
- import { jsx as jsx66, jsxs as jsxs46 } from "react/jsx-runtime";
13110
+ import { jsx as jsx66, jsxs as jsxs47 } from "react/jsx-runtime";
12706
13111
  var kinds = {
12707
13112
  tag: TagProperties,
12708
13113
  option: option_properties_default,
@@ -12720,20 +13125,20 @@ var Properties = () => {
12720
13125
  if (!Kind) {
12721
13126
  return /* @__PURE__ */ jsx66("div", { className: "p-4", children: /* @__PURE__ */ jsx66(EmptyState, { title: "No active node selected", description: "Pick a tag, field, or option from the layers panel or canvas to inspect its core settings." }) });
12722
13127
  }
12723
- return /* @__PURE__ */ jsx66("div", { className: "flex h-full flex-col overflow-hidden", children: /* @__PURE__ */ jsx66(ScrollArea, { className: "min-h-0 flex-1", children: /* @__PURE__ */ jsxs46("div", { className: "flex flex-col gap-4 px-4 py-4", children: [
13128
+ return /* @__PURE__ */ jsx66("div", { className: "flex h-full flex-col overflow-hidden", children: /* @__PURE__ */ jsx66(ScrollArea, { className: "min-h-0 flex-1", children: /* @__PURE__ */ jsxs47("div", { className: "flex flex-col gap-4 px-4 py-4", children: [
12724
13129
  /* @__PURE__ */ jsx66(WorkspaceBootInlineNotice, { boot: ws.boot, sections: ["snapshotBody", "policies"] }),
12725
- /* @__PURE__ */ jsxs46(Section, { children: [
13130
+ /* @__PURE__ */ jsxs47(Section, { children: [
12726
13131
  /* @__PURE__ */ jsx66(Section.Header, { children: /* @__PURE__ */ jsx66(Section.Title, { children: "Selection overview" }) }),
12727
- /* @__PURE__ */ jsxs46(Section.Content, { children: [
13132
+ /* @__PURE__ */ jsxs47(Section.Content, { children: [
12728
13133
  /* @__PURE__ */ jsx66("p", { className: "mb-3 text-xs text-slate-500 dark:text-slate-400", children: "The inspector stays synced with the active canvas and layers selection." }),
12729
- /* @__PURE__ */ jsxs46("div", { className: "flex items-start justify-between gap-3", children: [
12730
- /* @__PURE__ */ jsxs46("div", { children: [
13134
+ /* @__PURE__ */ jsxs47("div", { className: "flex items-start justify-between gap-3", children: [
13135
+ /* @__PURE__ */ jsxs47("div", { children: [
12731
13136
  /* @__PURE__ */ jsx66("div", { className: "text-sm font-semibold capitalize text-slate-900 dark:text-slate-100", children: node.kind }),
12732
13137
  /* @__PURE__ */ jsx66("p", { className: "mt-1 text-xs text-slate-500 dark:text-slate-400", children: getNodeSummary(node) })
12733
13138
  ] }),
12734
13139
  /* @__PURE__ */ jsx66(SelectionBadge, { active: true, selected: true })
12735
13140
  ] }),
12736
- /* @__PURE__ */ jsxs46("div", { className: "mt-3 space-y-3", children: [
13141
+ /* @__PURE__ */ jsxs47("div", { className: "mt-3 space-y-3", children: [
12737
13142
  /* @__PURE__ */ jsx66(
12738
13143
  InputField15,
12739
13144
  {
@@ -12790,7 +13195,7 @@ var Properties = () => {
12790
13195
 
12791
13196
  // src/panels/right/components/wireframe-tags-widget.tsx
12792
13197
  import { IoClose } from "react-icons/io5";
12793
- import { Fragment as Fragment14, jsx as jsx67, jsxs as jsxs47 } from "react/jsx-runtime";
13198
+ import { Fragment as Fragment14, jsx as jsx67, jsxs as jsxs48 } from "react/jsx-runtime";
12794
13199
  function noticeToneClass(notice) {
12795
13200
  const color = (notice.color ?? "").toLowerCase();
12796
13201
  if (color.includes("red") || color.includes("rose") || color.includes("danger")) {
@@ -12823,7 +13228,7 @@ function WireframeTagsWidget({
12823
13228
  onTagDragOver,
12824
13229
  onTagDrop
12825
13230
  }) {
12826
- return /* @__PURE__ */ jsxs47("div", { className: "flex flex-wrap items-center gap-2", children: [
13231
+ return /* @__PURE__ */ jsxs48("div", { className: "flex flex-wrap items-center gap-2", children: [
12827
13232
  /* @__PURE__ */ jsx67(
12828
13233
  "small",
12829
13234
  {
@@ -12833,8 +13238,8 @@ function WireframeTagsWidget({
12833
13238
  children: "Tags:"
12834
13239
  }
12835
13240
  ),
12836
- /* @__PURE__ */ jsx67("div", { className: "flex flex-wrap items-center gap-1.5", children: visibleTag ? /* @__PURE__ */ jsxs47(Fragment14, { children: [
12837
- parents.map((item) => /* @__PURE__ */ jsxs47(
13241
+ /* @__PURE__ */ jsx67("div", { className: "flex flex-wrap items-center gap-1.5", children: visibleTag ? /* @__PURE__ */ jsxs48(Fragment14, { children: [
13242
+ parents.map((item) => /* @__PURE__ */ jsxs48(
12838
13243
  "button",
12839
13244
  {
12840
13245
  type: "button",
@@ -12858,7 +13263,7 @@ function WireframeTagsWidget({
12858
13263
  },
12859
13264
  item.id
12860
13265
  )),
12861
- /* @__PURE__ */ jsxs47(
13266
+ /* @__PURE__ */ jsxs48(
12862
13267
  "button",
12863
13268
  {
12864
13269
  type: "button",
@@ -12881,7 +13286,7 @@ function WireframeTagsWidget({
12881
13286
  }
12882
13287
  ),
12883
13288
  children.map((item) => {
12884
- return /* @__PURE__ */ jsxs47(
13289
+ return /* @__PURE__ */ jsxs48(
12885
13290
  "button",
12886
13291
  {
12887
13292
  type: "button",
@@ -12906,7 +13311,7 @@ function WireframeTagsWidget({
12906
13311
  );
12907
13312
  })
12908
13313
  ] }) : children.length ? children.map((item) => {
12909
- return /* @__PURE__ */ jsxs47(
13314
+ return /* @__PURE__ */ jsxs48(
12910
13315
  "button",
12911
13316
  {
12912
13317
  type: "button",
@@ -12930,8 +13335,8 @@ var wireframe_tags_widget_default = WireframeTagsWidget;
12930
13335
  // src/panels/right/tabs/wireframe.tsx
12931
13336
  import { useOrderFlow, Wrapper } from "@timeax/digital-service-engine/react";
12932
13337
  import { useCanvas as useCanvas16, useWorkspace as useWorkspace13 } from "@timeax/digital-service-engine/workspace";
12933
- import { useCallback as useCallback16, useMemo as useMemo31 } from "react";
12934
- import { jsx as jsx68, jsxs as jsxs48 } from "react/jsx-runtime";
13338
+ import { useCallback as useCallback17, useMemo as useMemo31 } from "react";
13339
+ import { jsx as jsx68, jsxs as jsxs49 } from "react/jsx-runtime";
12935
13340
  var CHECKBOX_SINGLE_EXTRA_PROPS = Object.freeze({ single: true });
12936
13341
  function Wireframe() {
12937
13342
  const canvas = useCanvas16();
@@ -12991,15 +13396,15 @@ function Wireframe() {
12991
13396
  }
12992
13397
  return map;
12993
13398
  }, [canvas.props, canvas.selectionInfo, canvas.activeId]);
12994
- const select = useCallback16(
13399
+ const select = useCallback17(
12995
13400
  (id) => {
12996
13401
  canvas.setActive(id);
12997
13402
  canvas.api.select([id]);
12998
13403
  },
12999
13404
  [canvas.api, canvas.setActive]
13000
13405
  );
13001
- return /* @__PURE__ */ jsxs48("div", { className: "flex h-full min-h-0 flex-col", children: [
13002
- /* @__PURE__ */ jsx68("div", { className: "min-h-0 flex-1 overflow-auto p-4", children: /* @__PURE__ */ jsx68("div", { className: "mx-auto max-w-md", children: /* @__PURE__ */ jsxs48("div", { className: "flex flex-col gap-4", children: [
13406
+ return /* @__PURE__ */ jsxs49("div", { className: "flex h-full min-h-0 flex-col", children: [
13407
+ /* @__PURE__ */ jsx68("div", { className: "min-h-0 flex-1 overflow-auto p-4", children: /* @__PURE__ */ jsx68("div", { className: "mx-auto max-w-md", children: /* @__PURE__ */ jsxs49("div", { className: "flex flex-col gap-4", children: [
13003
13408
  /* @__PURE__ */ jsx68(WorkspaceBootInlineNotice, { boot: ws.boot, sections: ["snapshotBody", "policies"] }),
13004
13409
  /* @__PURE__ */ jsx68(
13005
13410
  wireframe_tags_widget_default,
@@ -13095,7 +13500,7 @@ var wireframe_default = Wireframe;
13095
13500
  // src/panels/right/index.tsx
13096
13501
  import { OrderFlowProvider, useInputs as useInputs3 } from "@timeax/digital-service-engine/react";
13097
13502
  import { useCanvas as useCanvas17 } from "@timeax/digital-service-engine/workspace";
13098
- import { jsx as jsx69, jsxs as jsxs49 } from "react/jsx-runtime";
13503
+ import { jsx as jsx69, jsxs as jsxs50 } from "react/jsx-runtime";
13099
13504
  var RightPanel = ({ onShare, onPlay }) => {
13100
13505
  const tabClassName = cn(
13101
13506
  "m-0! rounded-none! border-t-0! border-r-0! border-b-2! border-l-0! border-transparent! py-2.5! shadow-none!",
@@ -13112,10 +13517,10 @@ var RightPanel = ({ onShare, onPlay }) => {
13112
13517
  maxWidth: 420,
13113
13518
  minWidth: 320,
13114
13519
  className: "flex h-dvh max-h-dvh w-100 flex-col rounded-none! border-l border-slate-200 bg-[linear-gradient(180deg,rgba(255,255,255,0.98),rgba(248,250,252,0.98))] dark:border-slate-800 dark:bg-[linear-gradient(180deg,rgba(2,6,23,0.98),rgba(15,23,42,0.98))]",
13115
- children: /* @__PURE__ */ jsxs49("div", { className: "flex h-full flex-col", children: [
13520
+ children: /* @__PURE__ */ jsxs50("div", { className: "flex h-full flex-col", children: [
13116
13521
  /* @__PURE__ */ jsx69(header_default2, { onShare, onPlay }),
13117
- /* @__PURE__ */ jsxs49(Tabs, { className: "grow gap-0 overflow-hidden", defaultValue: "wireframe", children: [
13118
- /* @__PURE__ */ jsxs49(TabsList, { className: "grid h-fit w-full grid-cols-3 rounded-none! border-b border-slate-200 bg-transparent p-0 dark:border-slate-800", children: [
13522
+ /* @__PURE__ */ jsxs50(Tabs, { className: "grow gap-0 overflow-hidden", defaultValue: "wireframe", children: [
13523
+ /* @__PURE__ */ jsxs50(TabsList, { className: "grid h-fit w-full grid-cols-3 rounded-none! border-b border-slate-200 bg-transparent p-0 dark:border-slate-800", children: [
13119
13524
  /* @__PURE__ */ jsx69(TabsTrigger, { className: tabClassName, value: "comments", children: "Comments" }),
13120
13525
  /* @__PURE__ */ jsx69(TabsTrigger, { className: tabClassName, value: "properties", children: "Properties" }),
13121
13526
  /* @__PURE__ */ jsx69(TabsTrigger, { className: tabClassName, value: "wireframe", children: "Wireframe" })
@@ -13130,168 +13535,13 @@ var RightPanel = ({ onShare, onPlay }) => {
13130
13535
  };
13131
13536
  var right_default = RightPanel;
13132
13537
 
13133
- // src/builder/service-context.ts
13134
- import { createBuilder } from "@timeax/digital-service-engine/core";
13135
- function createDefaultServiceContext(props, preferredTagId) {
13136
- const tagIds = (props?.filters ?? []).map((tag) => tag.id);
13137
- return {
13138
- selectedTagId: preferredTagId && tagIds.includes(preferredTagId) ? preferredTagId : tagIds[0] ?? null,
13139
- selectedButtons: [],
13140
- strictSafety: true,
13141
- enforcePolicies: true
13142
- };
13143
- }
13144
- function sanitizeServiceContext(snapshot, state) {
13145
- const allowed = new Set(snapshot.buttonGroups.flatMap((group) => group.options.map((option) => option.id)));
13146
- const selectedButtons = state.selectedButtons.filter((id) => allowed.has(id));
13147
- if (selectedButtons.length === state.selectedButtons.length) return state;
13148
- return { ...state, selectedButtons };
13149
- }
13150
- function buildServiceContextSnapshot(args) {
13151
- const props = args.props ?? void 0;
13152
- const serviceMap = args.services ?? {};
13153
- const tags = (props?.filters ?? []).map((tag) => ({
13154
- id: tag.id,
13155
- label: tag.label,
13156
- description: describeTag(tag)
13157
- }));
13158
- const selectedTag = (props?.filters ?? []).find((tag) => tag.id === args.state.selectedTagId) ?? null;
13159
- if (!props || !selectedTag) {
13160
- return {
13161
- state: args.state,
13162
- tags,
13163
- selectedTag,
13164
- buttonGroups: [],
13165
- visibleFieldIds: [],
13166
- usedServiceIds: []
13167
- };
13168
- }
13169
- const sandbox = createBuilder({ serviceMap });
13170
- sandbox.load(props);
13171
- const visibleFieldIds = sandbox.visibleFields(selectedTag.id, args.state.selectedButtons);
13172
- const buttonGroups = buildButtonGroups(props.fields ?? [], visibleFieldIds);
13173
- const usedServiceIds = collectUsedServiceIds({
13174
- props,
13175
- tagId: selectedTag.id,
13176
- visibleFieldIds,
13177
- selectedButtons: args.state.selectedButtons
13178
- });
13179
- return {
13180
- state: args.state,
13181
- tags,
13182
- selectedTag,
13183
- buttonGroups,
13184
- visibleFieldIds,
13185
- usedServiceIds
13186
- };
13187
- }
13188
- function buildServiceRowVM(args) {
13189
- const service = args.services?.[args.summary.id] ?? null;
13190
- const check = args.check;
13191
- const searchText = [args.summary.name, args.summary.category, args.summary.platformId, String(args.summary.id)].filter(Boolean).join(" ").toLowerCase();
13192
- const search = args.search?.trim().toLowerCase() ?? "";
13193
- const matchesSearch = !search || searchText.includes(search);
13194
- const isCompatible = !check || servicePassesCurrentFilter(check, args.state);
13195
- const status = describeCheck(check, args.state);
13196
- return {
13197
- id: String(args.summary.id),
13198
- summary: args.summary,
13199
- service,
13200
- check,
13201
- matchesSearch,
13202
- isCompatible,
13203
- passesCurrentFilter: matchesSearch,
13204
- statusTone: status.tone,
13205
- statusLabel: status.label,
13206
- reasonLabels: status.reasons,
13207
- searchText
13208
- };
13209
- }
13210
- function buildButtonGroups(fields, visibleFieldIds) {
13211
- const visibleSet = new Set(visibleFieldIds);
13212
- return fields.filter((field) => visibleSet.has(field.id)).map((field) => {
13213
- const options = field.options?.length ? field.options.filter((option) => option.id).map((option) => ({
13214
- id: String(option.id),
13215
- label: option.label,
13216
- description: `Option in ${field.label}`,
13217
- fieldId: field.id,
13218
- fieldLabel: field.label
13219
- })) : field.button ? [
13220
- {
13221
- id: field.id,
13222
- label: field.label,
13223
- description: "Button field",
13224
- fieldId: field.id,
13225
- fieldLabel: field.label
13226
- }
13227
- ] : [];
13228
- return {
13229
- id: field.id,
13230
- label: field.label,
13231
- options
13232
- };
13233
- }).filter((group) => group.options.length > 0);
13234
- }
13235
- function collectUsedServiceIds(args) {
13236
- const visibleSet = new Set(args.visibleFieldIds);
13237
- const used = /* @__PURE__ */ new Set();
13238
- const tag = args.props.filters?.find((item) => item.id === args.tagId);
13239
- if (tag?.service_id != null) used.add(String(tag.service_id));
13240
- for (const field of args.props.fields ?? []) {
13241
- if (!visibleSet.has(field.id)) continue;
13242
- if (field.service_id != null) {
13243
- used.add(String(field.service_id));
13244
- }
13245
- for (const option of field.options ?? []) {
13246
- if (option.service_id != null) {
13247
- used.add(String(option.service_id));
13248
- }
13249
- }
13250
- }
13251
- return Array.from(used);
13252
- }
13253
- function describeTag(tag) {
13254
- const constraints = Object.entries(tag.constraints ?? {}).filter(([, enabled]) => enabled).map(([key]) => key);
13255
- return constraints.length ? constraints.join(", ") : "All visible services";
13256
- }
13257
- function servicePassesCurrentFilter(check, state) {
13258
- const passesPolicies = state?.enforcePolicies === false ? true : check.passesPolicies;
13259
- const safetyPass = check.fitsConstraints && check.passesRate && passesPolicies;
13260
- return state?.strictSafety === false ? true : safetyPass;
13261
- }
13262
- function describeCheck(check, state) {
13263
- if (!check) {
13264
- return {
13265
- tone: "default",
13266
- label: "No context",
13267
- reasons: []
13268
- };
13269
- }
13270
- const reasons = [
13271
- !check.fitsConstraints ? "Constraint mismatch" : null,
13272
- !check.passesRate ? "Rate policy mismatch" : null,
13273
- state?.enforcePolicies !== false && !check.passesPolicies ? "Policy blocked" : null,
13274
- check.reasons.includes("missing_capability") ? "Missing capability" : null
13275
- ].filter(Boolean);
13276
- if (servicePassesCurrentFilter(check, state) && check.ok) {
13277
- return { tone: "success", label: "Safe fit", reasons };
13278
- }
13279
- if (servicePassesCurrentFilter(check, state)) {
13280
- return { tone: "warning", label: state?.enforcePolicies === false ? "Policy checks relaxed" : "Usable", reasons };
13281
- }
13282
- if (reasons.length) {
13283
- return { tone: "danger", label: "Hidden by context", reasons };
13284
- }
13285
- return { tone: "default", label: "Available", reasons };
13286
- }
13287
-
13288
13538
  // src/workspace/fallback-editor-modal.tsx
13289
13539
  import { useCanvas as useCanvas18, useWorkspace as useWorkspace14 } from "@timeax/digital-service-engine/workspace";
13290
13540
  import cloneDeep2 from "lodash/cloneDeep";
13291
- import { Suspense, lazy, createContext as createContext4, useCallback as useCallback17, useContext as useContext4, useEffect as useEffect18, useMemo as useMemo32, useState as useState31 } from "react";
13541
+ import { Suspense, lazy, createContext as createContext4, useCallback as useCallback18, useContext as useContext4, useEffect as useEffect19, useMemo as useMemo32, useState as useState31 } from "react";
13292
13542
  import { createPortal as createPortal3 } from "react-dom";
13293
13543
  import { FiX as FiX3 } from "react-icons/fi";
13294
- import { jsx as jsx70, jsxs as jsxs50 } from "react/jsx-runtime";
13544
+ import { jsx as jsx70, jsxs as jsxs51 } from "react/jsx-runtime";
13295
13545
  var LazyFallbackEditor = lazy(async () => {
13296
13546
  const mod = await import("@timeax/digital-service-engine/react");
13297
13547
  return { default: mod.FallbackEditor };
@@ -13311,11 +13561,11 @@ function FallbackEditorModalProvider({ children }) {
13311
13561
  const [launch, setLaunch] = useState31(null);
13312
13562
  const [sessionId, setSessionId] = useState31(0);
13313
13563
  const [surfaceError, setSurfaceError] = useState31(null);
13314
- const close = useCallback17(() => {
13564
+ const close = useCallback18(() => {
13315
13565
  setLaunch(null);
13316
13566
  setSurfaceError(null);
13317
13567
  }, []);
13318
- const openForNode = useCallback17((input) => {
13568
+ const openForNode = useCallback18((input) => {
13319
13569
  setSurfaceError(null);
13320
13570
  setSessionId((current) => current + 1);
13321
13571
  setLaunch({
@@ -13326,7 +13576,7 @@ function FallbackEditorModalProvider({ children }) {
13326
13576
  nodeLabel: input.nodeLabel ?? input.nodeId
13327
13577
  });
13328
13578
  }, []);
13329
- const openForService = useCallback17((input) => {
13579
+ const openForService = useCallback18((input) => {
13330
13580
  setSurfaceError(null);
13331
13581
  setSessionId((current) => current + 1);
13332
13582
  setLaunch({
@@ -13335,7 +13585,7 @@ function FallbackEditorModalProvider({ children }) {
13335
13585
  serviceName: input.serviceName
13336
13586
  });
13337
13587
  }, []);
13338
- const persistProps = useCallback17(
13588
+ const persistProps = useCallback18(
13339
13589
  (label, mutate) => {
13340
13590
  const editorAny = canvas.api.editor;
13341
13591
  if (typeof editorAny.transact !== "function" || typeof editorAny.replaceProps !== "function") {
@@ -13349,7 +13599,7 @@ function FallbackEditorModalProvider({ children }) {
13349
13599
  },
13350
13600
  [canvas.api.builder, canvas.api.editor, canvas.props]
13351
13601
  );
13352
- const handleSave = useCallback17(
13602
+ const handleSave = useCallback18(
13353
13603
  async (nextFallbacks) => {
13354
13604
  setSurfaceError(null);
13355
13605
  try {
@@ -13366,7 +13616,7 @@ function FallbackEditorModalProvider({ children }) {
13366
13616
  },
13367
13617
  [close, persistProps]
13368
13618
  );
13369
- const handleSettingsChange = useCallback17(
13619
+ const handleSettingsChange = useCallback18(
13370
13620
  async (nextSettings) => {
13371
13621
  setSurfaceError(null);
13372
13622
  try {
@@ -13401,7 +13651,7 @@ function FallbackEditorModalProvider({ children }) {
13401
13651
  () => canvas.props?.fallbackSettings ?? {},
13402
13652
  [canvas.props]
13403
13653
  );
13404
- useEffect18(() => {
13654
+ useEffect19(() => {
13405
13655
  if (!launch) return;
13406
13656
  const onKeyDown = (event) => {
13407
13657
  if (event.key === "Escape") close();
@@ -13418,7 +13668,7 @@ function FallbackEditorModalProvider({ children }) {
13418
13668
  }),
13419
13669
  [close, launch, openForNode, openForService]
13420
13670
  );
13421
- return /* @__PURE__ */ jsxs50(FallbackEditorModalContext.Provider, { value, children: [
13671
+ return /* @__PURE__ */ jsxs51(FallbackEditorModalContext.Provider, { value, children: [
13422
13672
  children,
13423
13673
  typeof document !== "undefined" && launch ? createPortal3(
13424
13674
  /* @__PURE__ */ jsx70(
@@ -13428,15 +13678,15 @@ function FallbackEditorModalProvider({ children }) {
13428
13678
  onMouseDown: (event) => {
13429
13679
  if (event.target === event.currentTarget) close();
13430
13680
  },
13431
- children: /* @__PURE__ */ jsxs50(
13681
+ children: /* @__PURE__ */ jsxs51(
13432
13682
  "div",
13433
13683
  {
13434
13684
  className: cn(
13435
13685
  "flex h-[min(90vh,56rem)] w-[min(96vw,88rem)] flex-col overflow-hidden rounded-[28px] border border-slate-200 bg-white shadow-2xl dark:border-slate-800 dark:bg-slate-950"
13436
13686
  ),
13437
13687
  children: [
13438
- /* @__PURE__ */ jsxs50("div", { className: "flex items-start justify-between gap-4 border-b border-slate-200 px-6 py-4 dark:border-slate-800", children: [
13439
- /* @__PURE__ */ jsxs50("div", { className: "min-w-0", children: [
13688
+ /* @__PURE__ */ jsxs51("div", { className: "flex items-start justify-between gap-4 border-b border-slate-200 px-6 py-4 dark:border-slate-800", children: [
13689
+ /* @__PURE__ */ jsxs51("div", { className: "min-w-0", children: [
13440
13690
  /* @__PURE__ */ jsx70("h2", { className: "text-lg font-semibold text-slate-900 dark:text-slate-100", children: launchTitle }),
13441
13691
  /* @__PURE__ */ jsx70("p", { className: "mt-1 text-sm text-slate-500 dark:text-slate-400", children: launchDescription })
13442
13692
  ] }),
@@ -13479,7 +13729,7 @@ function useFallbackEditorModal() {
13479
13729
 
13480
13730
  // src/workspace/bottom-panel/index.tsx
13481
13731
  import { useCanvas as useCanvas21, useWorkspace as useWorkspace15 } from "@timeax/digital-service-engine/workspace";
13482
- import { useCallback as useCallback18, useEffect as useEffect21, useMemo as useMemo34, useRef as useRef11, useState as useState34 } from "react";
13732
+ import { useCallback as useCallback19, useEffect as useEffect22, useMemo as useMemo34, useRef as useRef11, useState as useState34 } from "react";
13483
13733
  import { FiEye as FiEye3, FiEyeOff as FiEyeOff2, FiSearch, FiTerminal as FiTerminal2, FiX as FiX5 } from "react-icons/fi";
13484
13734
  import { LuGripHorizontal, LuLayers3 } from "react-icons/lu";
13485
13735
  import { MdOutlineSync } from "react-icons/md";
@@ -13690,7 +13940,7 @@ function toNodeChip(canvas, id) {
13690
13940
  }
13691
13941
 
13692
13942
  // src/workspace/bottom-panel/console-tab.tsx
13693
- import { Fragment as Fragment15, jsx as jsx72, jsxs as jsxs51 } from "react/jsx-runtime";
13943
+ import { Fragment as Fragment15, jsx as jsx72, jsxs as jsxs52 } from "react/jsx-runtime";
13694
13944
  function ConsoleTab({
13695
13945
  errors,
13696
13946
  notices,
@@ -13719,20 +13969,20 @@ function ConsoleTab({
13719
13969
  ];
13720
13970
  const activeIntro = introState[subTab];
13721
13971
  const introCopy = getConsoleIntroCopy(subTab);
13722
- return /* @__PURE__ */ jsxs51("div", { className: "space-y-4", children: [
13723
- !activeIntro.closed ? /* @__PURE__ */ jsx72("div", { className: "rounded-2xl border border-sky-200/80 bg-sky-50/70 p-3 dark:border-sky-500/20 dark:bg-sky-500/10", children: /* @__PURE__ */ jsxs51("div", { className: "flex items-start justify-between gap-3", children: [
13724
- /* @__PURE__ */ jsxs51("div", { className: "min-w-0", children: [
13972
+ return /* @__PURE__ */ jsxs52("div", { className: "space-y-4", children: [
13973
+ !activeIntro.closed ? /* @__PURE__ */ jsx72("div", { className: "rounded-2xl border border-sky-200/80 bg-sky-50/70 p-3 dark:border-sky-500/20 dark:bg-sky-500/10", children: /* @__PURE__ */ jsxs52("div", { className: "flex items-start justify-between gap-3", children: [
13974
+ /* @__PURE__ */ jsxs52("div", { className: "min-w-0", children: [
13725
13975
  /* @__PURE__ */ jsx72("p", { className: "text-sm font-semibold text-slate-900 dark:text-slate-100", children: introCopy.title }),
13726
- !activeIntro.minimized ? /* @__PURE__ */ jsxs51(Fragment15, { children: [
13976
+ !activeIntro.minimized ? /* @__PURE__ */ jsxs52(Fragment15, { children: [
13727
13977
  /* @__PURE__ */ jsx72("p", { className: "mt-1 text-xs text-slate-600 dark:text-slate-300", children: introCopy.description }),
13728
- /* @__PURE__ */ jsxs51("div", { className: "mt-2 flex flex-wrap items-center gap-2 text-[11px] text-slate-500 dark:text-slate-400", children: [
13978
+ /* @__PURE__ */ jsxs52("div", { className: "mt-2 flex flex-wrap items-center gap-2 text-[11px] text-slate-500 dark:text-slate-400", children: [
13729
13979
  /* @__PURE__ */ jsx72("span", { className: "rounded-full bg-white/80 px-2 py-0.5 dark:bg-slate-900/70", children: validating ? "Validating..." : "Console idle" }),
13730
13980
  /* @__PURE__ */ jsx72("span", { className: "rounded-full bg-white/80 px-2 py-0.5 dark:bg-slate-900/70", children: shortcutLabel }),
13731
13981
  /* @__PURE__ */ jsx72("span", { className: "rounded-full bg-white/80 px-2 py-0.5 dark:bg-slate-900/70", children: "Press Escape to close" })
13732
13982
  ] })
13733
13983
  ] }) : null
13734
13984
  ] }),
13735
- /* @__PURE__ */ jsxs51("div", { className: "flex items-center gap-2 text-xs", children: [
13985
+ /* @__PURE__ */ jsxs52("div", { className: "flex items-center gap-2 text-xs", children: [
13736
13986
  /* @__PURE__ */ jsx72(
13737
13987
  "button",
13738
13988
  {
@@ -13753,9 +14003,9 @@ function ConsoleTab({
13753
14003
  )
13754
14004
  ] })
13755
14005
  ] }) }) : null,
13756
- /* @__PURE__ */ jsxs51("div", { className: "rounded-2xl border border-slate-200 bg-white/70 p-3 dark:border-slate-800 dark:bg-slate-950/40", children: [
13757
- /* @__PURE__ */ jsxs51("div", { className: "flex flex-wrap items-center justify-between gap-2", children: [
13758
- /* @__PURE__ */ jsx72("div", { className: "flex flex-wrap items-center gap-2", children: subTabs.map((tab) => /* @__PURE__ */ jsxs51(
14006
+ /* @__PURE__ */ jsxs52("div", { className: "rounded-2xl border border-slate-200 bg-white/70 p-3 dark:border-slate-800 dark:bg-slate-950/40", children: [
14007
+ /* @__PURE__ */ jsxs52("div", { className: "flex flex-wrap items-center justify-between gap-2", children: [
14008
+ /* @__PURE__ */ jsx72("div", { className: "flex flex-wrap items-center gap-2", children: subTabs.map((tab) => /* @__PURE__ */ jsxs52(
13759
14009
  "button",
13760
14010
  {
13761
14011
  type: "button",
@@ -13771,12 +14021,12 @@ function ConsoleTab({
13771
14021
  },
13772
14022
  tab.id
13773
14023
  )) }),
13774
- subTab === "logs" && logRows.length ? /* @__PURE__ */ jsxs51(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => errors.clear("logs"), className: "h-8 rounded-xl px-3 text-xs", children: [
14024
+ subTab === "logs" && logRows.length ? /* @__PURE__ */ jsxs52(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => errors.clear("logs"), className: "h-8 rounded-xl px-3 text-xs", children: [
13775
14025
  /* @__PURE__ */ jsx72(FiTrash2, {}),
13776
14026
  "Clear logs"
13777
14027
  ] }) : null
13778
14028
  ] }),
13779
- /* @__PURE__ */ jsxs51("div", { className: "mt-3 flex flex-wrap items-center gap-2", children: [
14029
+ /* @__PURE__ */ jsxs52("div", { className: "mt-3 flex flex-wrap items-center gap-2", children: [
13780
14030
  /* @__PURE__ */ jsx72("span", { className: "text-[11px] font-semibold tracking-[0.16em] text-slate-500 uppercase dark:text-slate-400", children: "Scope" }),
13781
14031
  /* @__PURE__ */ jsx72(
13782
14032
  "button",
@@ -13802,7 +14052,7 @@ function ConsoleTab({
13802
14052
  children: "Active node"
13803
14053
  }
13804
14054
  ),
13805
- subTab !== "logs" ? /* @__PURE__ */ jsxs51(Fragment15, { children: [
14055
+ subTab !== "logs" ? /* @__PURE__ */ jsxs52(Fragment15, { children: [
13806
14056
  /* @__PURE__ */ jsx72("span", { className: "ml-2 text-[11px] font-semibold tracking-[0.16em] text-slate-500 uppercase dark:text-slate-400", children: "Severity" }),
13807
14057
  ["all", "error", "warning", "info"].map((option) => /* @__PURE__ */ jsx72(
13808
14058
  "button",
@@ -13848,20 +14098,20 @@ function NoticeCard({ notice, onNodeClick }) {
13848
14098
  const canvas = useCanvas20();
13849
14099
  const targetNodeId = notice.target.scope === "node" ? notice.target.node_id : null;
13850
14100
  const targetChip = notice.target.scope === "node" ? toNodeChip(canvas, notice.target.node_id) : "Global notice";
13851
- return /* @__PURE__ */ jsx72("div", { className: "rounded-2xl border border-slate-200 bg-white p-4 shadow-sm dark:border-slate-800 dark:bg-slate-950/90", children: /* @__PURE__ */ jsxs51("div", { className: "flex items-start gap-3", children: [
14101
+ return /* @__PURE__ */ jsx72("div", { className: "rounded-2xl border border-slate-200 bg-white p-4 shadow-sm dark:border-slate-800 dark:bg-slate-950/90", children: /* @__PURE__ */ jsxs52("div", { className: "flex items-start gap-3", children: [
13852
14102
  /* @__PURE__ */ jsx72("div", { className: "mt-0.5", children: iconForSeverity(notice.severity) }),
13853
- /* @__PURE__ */ jsxs51("div", { className: "min-w-0 flex-1 space-y-2", children: [
13854
- /* @__PURE__ */ jsxs51("div", { className: "flex flex-wrap items-center gap-2", children: [
14103
+ /* @__PURE__ */ jsxs52("div", { className: "min-w-0 flex-1 space-y-2", children: [
14104
+ /* @__PURE__ */ jsxs52("div", { className: "flex flex-wrap items-center gap-2", children: [
13855
14105
  /* @__PURE__ */ jsx72("span", { className: severityBadgeClassName(notice.severity), children: notice.kind }),
13856
14106
  /* @__PURE__ */ jsx72("span", { className: "rounded-full bg-slate-100 px-2.5 py-1 text-[10px] font-semibold tracking-[0.16em] text-slate-600 uppercase dark:bg-slate-900 dark:text-slate-300", children: notice.type }),
13857
14107
  /* @__PURE__ */ jsx72("span", { className: "text-sm font-semibold text-slate-900 dark:text-slate-100", children: notice.title })
13858
14108
  ] }),
13859
14109
  notice.description ? /* @__PURE__ */ jsx72("p", { className: "text-sm text-slate-600 dark:text-slate-300", children: notice.description }) : null,
13860
- notice.reason ? /* @__PURE__ */ jsxs51("p", { className: "text-xs text-slate-500 dark:text-slate-400", children: [
14110
+ notice.reason ? /* @__PURE__ */ jsxs52("p", { className: "text-xs text-slate-500 dark:text-slate-400", children: [
13861
14111
  "Reason: ",
13862
14112
  notice.reason
13863
14113
  ] }) : null,
13864
- /* @__PURE__ */ jsxs51("div", { className: "flex flex-wrap items-center gap-2 text-xs text-slate-500 dark:text-slate-400", children: [
14114
+ /* @__PURE__ */ jsxs52("div", { className: "flex flex-wrap items-center gap-2 text-xs text-slate-500 dark:text-slate-400", children: [
13865
14115
  notice.target.scope === "node" ? /* @__PURE__ */ jsx72(
13866
14116
  "button",
13867
14117
  {
@@ -13872,11 +14122,11 @@ function NoticeCard({ notice, onNodeClick }) {
13872
14122
  }
13873
14123
  ) : /* @__PURE__ */ jsx72("span", { className: "rounded-full bg-slate-100 px-2.5 py-1 text-xs text-slate-700 dark:bg-slate-900 dark:text-slate-300", children: targetChip }),
13874
14124
  notice.marked_at ? /* @__PURE__ */ jsx72("span", { children: new Date(notice.marked_at).toLocaleString() }) : null,
13875
- notice.icon ? /* @__PURE__ */ jsxs51("span", { children: [
14125
+ notice.icon ? /* @__PURE__ */ jsxs52("span", { children: [
13876
14126
  "Icon: ",
13877
14127
  notice.icon
13878
14128
  ] }) : null,
13879
- notice.color ? /* @__PURE__ */ jsxs51("span", { children: [
14129
+ notice.color ? /* @__PURE__ */ jsxs52("span", { children: [
13880
14130
  "Color: ",
13881
14131
  notice.color
13882
14132
  ] }) : null
@@ -13892,10 +14142,10 @@ function ValidationCard({ row, onNodeClick }) {
13892
14142
  {
13893
14143
  className: "rounded-2xl border border-slate-200 bg-white p-4 shadow-sm dark:border-slate-800 dark:bg-slate-950/90",
13894
14144
  onClick: () => scope.length && canvas.api.setHighlighted(scope),
13895
- children: /* @__PURE__ */ jsxs51("div", { className: "flex items-start gap-3", children: [
14145
+ children: /* @__PURE__ */ jsxs52("div", { className: "flex items-start gap-3", children: [
13896
14146
  /* @__PURE__ */ jsx72("div", { className: "mt-0.5", children: iconForSeverity(row.severity) }),
13897
- /* @__PURE__ */ jsxs51("div", { className: "min-w-0 flex-1", children: [
13898
- /* @__PURE__ */ jsxs51("div", { className: "flex flex-wrap items-center gap-2", children: [
14147
+ /* @__PURE__ */ jsxs52("div", { className: "min-w-0 flex-1", children: [
14148
+ /* @__PURE__ */ jsxs52("div", { className: "flex flex-wrap items-center gap-2", children: [
13899
14149
  /* @__PURE__ */ jsx72("span", { className: severityBadgeClassName(row.severity), children: row.code.replaceAll("_", " ") }),
13900
14150
  /* @__PURE__ */ jsx72("span", { className: "text-sm font-semibold text-slate-900 dark:text-slate-100", children: row.message })
13901
14151
  ] }),
@@ -13914,16 +14164,16 @@ function ValidationCard({ row, onNodeClick }) {
13914
14164
  );
13915
14165
  }
13916
14166
  function LogCard({ row, onRemove }) {
13917
- return /* @__PURE__ */ jsx72("div", { className: "rounded-2xl border border-slate-200 bg-white p-4 shadow-sm dark:border-slate-800 dark:bg-slate-950/90", children: /* @__PURE__ */ jsxs51("div", { className: "flex items-start gap-3", children: [
14167
+ return /* @__PURE__ */ jsx72("div", { className: "rounded-2xl border border-slate-200 bg-white p-4 shadow-sm dark:border-slate-800 dark:bg-slate-950/90", children: /* @__PURE__ */ jsxs52("div", { className: "flex items-start gap-3", children: [
13918
14168
  /* @__PURE__ */ jsx72("div", { className: "mt-0.5", children: /* @__PURE__ */ jsx72(FiInfo2, { className: "text-lg text-sky-500" }) }),
13919
- /* @__PURE__ */ jsxs51("div", { className: "min-w-0 flex-1", children: [
13920
- /* @__PURE__ */ jsxs51("div", { className: "flex flex-wrap items-center gap-2", children: [
14169
+ /* @__PURE__ */ jsxs52("div", { className: "min-w-0 flex-1", children: [
14170
+ /* @__PURE__ */ jsxs52("div", { className: "flex flex-wrap items-center gap-2", children: [
13921
14171
  /* @__PURE__ */ jsx72("span", { className: "rounded-full bg-sky-100 px-2.5 py-1 text-[10px] font-semibold tracking-[0.16em] text-sky-700 uppercase dark:bg-sky-500/15 dark:text-sky-200", children: row.code ?? "log" }),
13922
14172
  /* @__PURE__ */ jsx72("span", { className: "text-sm font-semibold text-slate-900 dark:text-slate-100", children: row.message })
13923
14173
  ] }),
13924
- /* @__PURE__ */ jsxs51("div", { className: "mt-3 flex items-center justify-between gap-3 text-xs text-slate-500 dark:text-slate-400", children: [
14174
+ /* @__PURE__ */ jsxs52("div", { className: "mt-3 flex items-center justify-between gap-3 text-xs text-slate-500 dark:text-slate-400", children: [
13925
14175
  /* @__PURE__ */ jsx72("span", { children: new Date(row.createdAt).toLocaleTimeString() }),
13926
- /* @__PURE__ */ jsxs51(Button, { type: "button", variant: "ghost", size: "sm", onClick: onRemove, className: "h-7 rounded-xl px-2 text-xs", children: [
14176
+ /* @__PURE__ */ jsxs52(Button, { type: "button", variant: "ghost", size: "sm", onClick: onRemove, className: "h-7 rounded-xl px-2 text-xs", children: [
13927
14177
  /* @__PURE__ */ jsx72(FiX4, {}),
13928
14178
  "Dismiss"
13929
14179
  ] })
@@ -13934,7 +14184,7 @@ function LogCard({ row, onRemove }) {
13934
14184
 
13935
14185
  // src/workspace/bottom-panel/service-picker-dialog.tsx
13936
14186
  import { InputField as InputField16 } from "@timeax/form-palette";
13937
- import { useEffect as useEffect19, useMemo as useMemo33, useState as useState32 } from "react";
14187
+ import { useEffect as useEffect20, useMemo as useMemo33, useState as useState32 } from "react";
13938
14188
  import { createPortal as createPortal4 } from "react-dom";
13939
14189
 
13940
14190
  // src/workspace/bottom-panel/service-picker.ts
@@ -14052,7 +14302,7 @@ function isScalar(value) {
14052
14302
  }
14053
14303
 
14054
14304
  // src/workspace/bottom-panel/service-picker-dialog.tsx
14055
- import { jsx as jsx73, jsxs as jsxs52 } from "react/jsx-runtime";
14305
+ import { jsx as jsx73, jsxs as jsxs53 } from "react/jsx-runtime";
14056
14306
  function ServicePickerDialog({
14057
14307
  open,
14058
14308
  groupLabel,
@@ -14065,12 +14315,12 @@ function ServicePickerDialog({
14065
14315
  }) {
14066
14316
  const [filters, setFilters] = useState32(() => createDefaultServicePickerFilters());
14067
14317
  const [selectedIds, setSelectedIds] = useState32(/* @__PURE__ */ new Set());
14068
- useEffect19(() => {
14318
+ useEffect20(() => {
14069
14319
  if (!open) return;
14070
14320
  setFilters(createDefaultServicePickerFilters());
14071
14321
  setSelectedIds(/* @__PURE__ */ new Set());
14072
14322
  }, [open]);
14073
- useEffect19(() => {
14323
+ useEffect20(() => {
14074
14324
  if (!open) return;
14075
14325
  const onKeyDown = (event) => {
14076
14326
  if (event.key === "Escape") onOpenChange(false);
@@ -14098,7 +14348,7 @@ function ServicePickerDialog({
14098
14348
  const selectedCount = selectedIds.size;
14099
14349
  const canConfirm = selectedCount > 0;
14100
14350
  return createPortal4(
14101
- /* @__PURE__ */ jsx73("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-slate-950/45 p-4", children: /* @__PURE__ */ jsxs52(
14351
+ /* @__PURE__ */ jsx73("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-slate-950/45 p-4", children: /* @__PURE__ */ jsxs53(
14102
14352
  "div",
14103
14353
  {
14104
14354
  role: "dialog",
@@ -14106,15 +14356,15 @@ function ServicePickerDialog({
14106
14356
  "aria-label": "Service picker",
14107
14357
  className: "flex h-[min(80vh,42rem)] w-[min(72rem,calc(100vw-2rem))] flex-col overflow-hidden rounded-3xl border border-slate-200 bg-white shadow-2xl dark:border-slate-800 dark:bg-slate-950",
14108
14358
  children: [
14109
- /* @__PURE__ */ jsx73("div", { className: "border-b border-slate-200 px-5 py-4 dark:border-slate-800", children: /* @__PURE__ */ jsxs52("div", { className: "flex items-start justify-between gap-4", children: [
14110
- /* @__PURE__ */ jsxs52("div", { children: [
14359
+ /* @__PURE__ */ jsx73("div", { className: "border-b border-slate-200 px-5 py-4 dark:border-slate-800", children: /* @__PURE__ */ jsxs53("div", { className: "flex items-start justify-between gap-4", children: [
14360
+ /* @__PURE__ */ jsxs53("div", { children: [
14111
14361
  /* @__PURE__ */ jsx73("h3", { className: "text-lg font-semibold text-slate-900 dark:text-slate-100", children: "Assign services to group" }),
14112
14362
  /* @__PURE__ */ jsx73("p", { className: "mt-1 text-sm text-slate-500 dark:text-slate-400", children: groupLabel ? `Pick one or more services to append into ${groupLabel}.` : "Pick one or more services to append into the selected catalog group." })
14113
14363
  ] }),
14114
14364
  /* @__PURE__ */ jsx73(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => onOpenChange(false), className: "rounded-xl", children: "Close" })
14115
14365
  ] }) }),
14116
- /* @__PURE__ */ jsxs52("div", { className: "grid h-full min-h-0 flex-1 overflow-hidden md:grid-cols-[18rem_minmax(0,1fr)]", children: [
14117
- /* @__PURE__ */ jsx73("div", { className: "min-h-0 border-r border-slate-200 dark:border-slate-800", children: /* @__PURE__ */ jsx73(ScrollArea, { className: "h-full min-h-0", children: /* @__PURE__ */ jsxs52("div", { className: "space-y-4 p-4", children: [
14366
+ /* @__PURE__ */ jsxs53("div", { className: "grid h-full min-h-0 flex-1 overflow-hidden md:grid-cols-[18rem_minmax(0,1fr)]", children: [
14367
+ /* @__PURE__ */ jsx73("div", { className: "min-h-0 border-r border-slate-200 dark:border-slate-800", children: /* @__PURE__ */ jsx73(ScrollArea, { className: "h-full min-h-0", children: /* @__PURE__ */ jsxs53("div", { className: "space-y-4 p-4", children: [
14118
14368
  /* @__PURE__ */ jsx73(FilterField, { label: "Search", children: /* @__PURE__ */ jsx73(
14119
14369
  InputField16,
14120
14370
  {
@@ -14165,7 +14415,7 @@ function ServicePickerDialog({
14165
14415
  }))
14166
14416
  }
14167
14417
  ) }),
14168
- /* @__PURE__ */ jsxs52("div", { className: "grid grid-cols-2 gap-2", children: [
14418
+ /* @__PURE__ */ jsxs53("div", { className: "grid grid-cols-2 gap-2", children: [
14169
14419
  /* @__PURE__ */ jsx73(FilterField, { label: "Min rate", children: /* @__PURE__ */ jsx73(
14170
14420
  InputField16,
14171
14421
  {
@@ -14189,7 +14439,7 @@ function ServicePickerDialog({
14189
14439
  }
14190
14440
  ) })
14191
14441
  ] }),
14192
- /* @__PURE__ */ jsx73(FilterField, { label: "Name keyword", children: /* @__PURE__ */ jsxs52("div", { className: "space-y-2", children: [
14442
+ /* @__PURE__ */ jsx73(FilterField, { label: "Name keyword", children: /* @__PURE__ */ jsxs53("div", { className: "space-y-2", children: [
14193
14443
  /* @__PURE__ */ jsx73(
14194
14444
  InputField16,
14195
14445
  {
@@ -14260,8 +14510,8 @@ function ServicePickerDialog({
14260
14510
  }
14261
14511
  ) })
14262
14512
  ] }) }) }),
14263
- /* @__PURE__ */ jsxs52("div", { className: "flex min-h-0 flex-col overflow-hidden", children: [
14264
- /* @__PURE__ */ jsxs52("div", { className: "border-b border-slate-200 px-4 py-3 text-sm text-slate-500 dark:border-slate-800 dark:text-slate-400", children: [
14513
+ /* @__PURE__ */ jsxs53("div", { className: "flex min-h-0 flex-col overflow-hidden", children: [
14514
+ /* @__PURE__ */ jsxs53("div", { className: "border-b border-slate-200 px-4 py-3 text-sm text-slate-500 dark:border-slate-800 dark:text-slate-400", children: [
14265
14515
  filteredServices.length,
14266
14516
  " service",
14267
14517
  filteredServices.length === 1 ? "" : "s",
@@ -14271,7 +14521,7 @@ function ServicePickerDialog({
14271
14521
  const id = String(service.id);
14272
14522
  const selected = selectedIds.has(id);
14273
14523
  const alreadyAssigned = existingGroupServiceIds.has(id);
14274
- return /* @__PURE__ */ jsxs52(
14524
+ return /* @__PURE__ */ jsxs53(
14275
14525
  "label",
14276
14526
  {
14277
14527
  className: cn(
@@ -14293,12 +14543,12 @@ function ServicePickerDialog({
14293
14543
  })
14294
14544
  }
14295
14545
  ),
14296
- /* @__PURE__ */ jsxs52("div", { className: "min-w-0 flex-1", children: [
14297
- /* @__PURE__ */ jsxs52("div", { className: "flex items-center justify-between gap-3", children: [
14298
- /* @__PURE__ */ jsxs52("div", { className: "min-w-0", children: [
14546
+ /* @__PURE__ */ jsxs53("div", { className: "min-w-0 flex-1", children: [
14547
+ /* @__PURE__ */ jsxs53("div", { className: "flex items-center justify-between gap-3", children: [
14548
+ /* @__PURE__ */ jsxs53("div", { className: "min-w-0", children: [
14299
14549
  /* @__PURE__ */ jsx73("div", { className: "truncate text-sm font-semibold text-slate-900 dark:text-slate-100", children: service.name }),
14300
- /* @__PURE__ */ jsxs52("div", { className: "mt-1 flex flex-wrap gap-2 text-xs text-slate-500 dark:text-slate-400", children: [
14301
- /* @__PURE__ */ jsxs52("span", { children: [
14550
+ /* @__PURE__ */ jsxs53("div", { className: "mt-1 flex flex-wrap gap-2 text-xs text-slate-500 dark:text-slate-400", children: [
14551
+ /* @__PURE__ */ jsxs53("span", { children: [
14302
14552
  "#",
14303
14553
  service.id
14304
14554
  ] }),
@@ -14308,8 +14558,8 @@ function ServicePickerDialog({
14308
14558
  ] }),
14309
14559
  alreadyAssigned ? /* @__PURE__ */ jsx73("span", { className: "rounded-full bg-emerald-50 px-2.5 py-1 text-[11px] text-emerald-700 dark:bg-emerald-500/10 dark:text-emerald-200", children: "Already in group" }) : null
14310
14560
  ] }),
14311
- /* @__PURE__ */ jsxs52("div", { className: "mt-3 flex flex-wrap gap-2", children: [
14312
- service.rate != null ? /* @__PURE__ */ jsxs52("span", { className: "rounded-full bg-slate-100 px-2.5 py-1 text-[11px] text-slate-600 dark:bg-slate-900 dark:text-slate-300", children: [
14561
+ /* @__PURE__ */ jsxs53("div", { className: "mt-3 flex flex-wrap gap-2", children: [
14562
+ service.rate != null ? /* @__PURE__ */ jsxs53("span", { className: "rounded-full bg-slate-100 px-2.5 py-1 text-[11px] text-slate-600 dark:bg-slate-900 dark:text-slate-300", children: [
14313
14563
  "Rate ",
14314
14564
  service.rate
14315
14565
  ] }) : null,
@@ -14323,14 +14573,14 @@ function ServicePickerDialog({
14323
14573
  }) : /* @__PURE__ */ jsx73("div", { className: "rounded-2xl border border-dashed border-slate-300 px-4 py-10 text-center text-sm text-slate-500 dark:border-slate-700 dark:text-slate-400", children: "No services match the current filters." }) }) })
14324
14574
  ] })
14325
14575
  ] }),
14326
- /* @__PURE__ */ jsxs52("div", { className: "flex items-center justify-between gap-3 border-t border-slate-200 px-5 py-4 dark:border-slate-800", children: [
14327
- /* @__PURE__ */ jsxs52("div", { className: "text-sm text-slate-500 dark:text-slate-400", children: [
14576
+ /* @__PURE__ */ jsxs53("div", { className: "flex items-center justify-between gap-3 border-t border-slate-200 px-5 py-4 dark:border-slate-800", children: [
14577
+ /* @__PURE__ */ jsxs53("div", { className: "text-sm text-slate-500 dark:text-slate-400", children: [
14328
14578
  selectedCount,
14329
14579
  " service",
14330
14580
  selectedCount === 1 ? "" : "s",
14331
14581
  " selected"
14332
14582
  ] }),
14333
- /* @__PURE__ */ jsxs52("div", { className: "flex items-center gap-2", children: [
14583
+ /* @__PURE__ */ jsxs53("div", { className: "flex items-center gap-2", children: [
14334
14584
  /* @__PURE__ */ jsx73(Button, { type: "button", variant: "outline", onClick: () => onOpenChange(false), className: "rounded-xl", children: "Cancel" }),
14335
14585
  /* @__PURE__ */ jsx73(
14336
14586
  Button,
@@ -14354,7 +14604,7 @@ function ServicePickerDialog({
14354
14604
  );
14355
14605
  }
14356
14606
  function FilterField({ label, children }) {
14357
- return /* @__PURE__ */ jsxs52("label", { className: "block space-y-1.5", children: [
14607
+ return /* @__PURE__ */ jsxs53("label", { className: "block space-y-1.5", children: [
14358
14608
  /* @__PURE__ */ jsx73("span", { className: "text-[11px] font-semibold uppercase tracking-[0.16em] text-slate-500 dark:text-slate-400", children: label }),
14359
14609
  children
14360
14610
  ] });
@@ -14405,12 +14655,12 @@ function ResizableHandle({
14405
14655
 
14406
14656
  // src/workspace/bottom-panel/services-split-pane.tsx
14407
14657
  import { InputField as InputField17 } from "@timeax/form-palette";
14408
- import { useEffect as useEffect20, useState as useState33 } from "react";
14409
- import { FaFolderOpen } from "react-icons/fa";
14410
- import { FiEdit2, FiFilter, FiFolderPlus, FiPlus as FiPlus2, FiTrash2 as FiTrash22 } from "react-icons/fi";
14658
+ import { useEffect as useEffect21, useState as useState33 } from "react";
14659
+ import { FaFolderOpen as FaFolderOpen2 } from "react-icons/fa";
14660
+ import { FiEdit2, FiFilter as FiFilter2, FiFolderPlus, FiPlus as FiPlus2, FiTrash2 as FiTrash22 } from "react-icons/fi";
14411
14661
 
14412
14662
  // src/workspace/bottom-panel/service-detail-card.tsx
14413
- import { jsx as jsx75, jsxs as jsxs53 } from "react/jsx-runtime";
14663
+ import { jsx as jsx75, jsxs as jsxs54 } from "react/jsx-runtime";
14414
14664
  function ServiceDetailCard({
14415
14665
  mode,
14416
14666
  row,
@@ -14421,16 +14671,16 @@ function ServiceDetailCard({
14421
14671
  }) {
14422
14672
  const summary = row.summary;
14423
14673
  const service = row.service;
14424
- return /* @__PURE__ */ jsxs53("div", { className: "space-y-5", children: [
14425
- /* @__PURE__ */ jsxs53("div", { className: "rounded-3xl border border-slate-200 bg-slate-50/80 p-5 dark:border-slate-800 dark:bg-slate-900/40", children: [
14426
- /* @__PURE__ */ jsxs53("div", { className: "flex flex-wrap items-start justify-between gap-4", children: [
14427
- /* @__PURE__ */ jsxs53("div", { className: "min-w-0", children: [
14428
- /* @__PURE__ */ jsxs53("div", { className: "flex items-center gap-2", children: [
14674
+ return /* @__PURE__ */ jsxs54("div", { className: "space-y-5", children: [
14675
+ /* @__PURE__ */ jsxs54("div", { className: "rounded-3xl border border-slate-200 bg-slate-50/80 p-5 dark:border-slate-800 dark:bg-slate-900/40", children: [
14676
+ /* @__PURE__ */ jsxs54("div", { className: "flex flex-wrap items-start justify-between gap-4", children: [
14677
+ /* @__PURE__ */ jsxs54("div", { className: "min-w-0", children: [
14678
+ /* @__PURE__ */ jsxs54("div", { className: "flex items-center gap-2", children: [
14429
14679
  /* @__PURE__ */ jsx75(StatusDot, { tone: row.statusTone, className: "mt-0.5" }),
14430
14680
  /* @__PURE__ */ jsx75("h5", { className: "truncate text-lg font-semibold text-slate-900 dark:text-slate-100", children: summary.name })
14431
14681
  ] }),
14432
- /* @__PURE__ */ jsxs53("div", { className: "mt-2 flex flex-wrap gap-2 text-xs text-slate-500 dark:text-slate-400", children: [
14433
- /* @__PURE__ */ jsxs53("span", { children: [
14682
+ /* @__PURE__ */ jsxs54("div", { className: "mt-2 flex flex-wrap gap-2 text-xs text-slate-500 dark:text-slate-400", children: [
14683
+ /* @__PURE__ */ jsxs54("span", { children: [
14434
14684
  "#",
14435
14685
  summary.id
14436
14686
  ] }),
@@ -14438,7 +14688,7 @@ function ServiceDetailCard({
14438
14688
  summary.platformId ? /* @__PURE__ */ jsx75("span", { children: summary.platformId }) : null
14439
14689
  ] })
14440
14690
  ] }),
14441
- /* @__PURE__ */ jsxs53("div", { className: "flex items-center gap-2", children: [
14691
+ /* @__PURE__ */ jsxs54("div", { className: "flex items-center gap-2", children: [
14442
14692
  mode === "active" && onOpenFallbackQuickAdd ? /* @__PURE__ */ jsx75(
14443
14693
  "button",
14444
14694
  {
@@ -14460,14 +14710,14 @@ function ServiceDetailCard({
14460
14710
  /* @__PURE__ */ jsx75("span", { className: statusBadgeClassName(row.statusTone), children: row.statusLabel })
14461
14711
  ] })
14462
14712
  ] }),
14463
- /* @__PURE__ */ jsxs53("div", { className: "mt-4 grid gap-3 sm:grid-cols-2", children: [
14713
+ /* @__PURE__ */ jsxs54("div", { className: "mt-4 grid gap-3 sm:grid-cols-2", children: [
14464
14714
  /* @__PURE__ */ jsx75(DetailMetric, { label: "Rate", value: summary.rate != null ? String(summary.rate) : "Not set" }),
14465
14715
  /* @__PURE__ */ jsx75(DetailMetric, { label: "Estimate", value: summary.estimate ?? "No estimate" }),
14466
14716
  /* @__PURE__ */ jsx75(DetailMetric, { label: "Min", value: summary.min != null ? String(summary.min) : "0" }),
14467
14717
  /* @__PURE__ */ jsx75(DetailMetric, { label: "Max", value: summary.max != null ? String(summary.max) : "Unlimited" })
14468
14718
  ] })
14469
14719
  ] }),
14470
- mode !== "active" ? /* @__PURE__ */ jsxs53("section", { className: "space-y-3", children: [
14720
+ mode !== "active" ? /* @__PURE__ */ jsxs54("section", { className: "space-y-3", children: [
14471
14721
  /* @__PURE__ */ jsx75(
14472
14722
  SectionTitle2,
14473
14723
  {
@@ -14475,8 +14725,8 @@ function ServiceDetailCard({
14475
14725
  description: mode === "catalog" ? "This summary shows how the service fits the current visible-group context while browsing catalog groups." : "This summary shows how the service fits the current visible-group context."
14476
14726
  }
14477
14727
  ),
14478
- /* @__PURE__ */ jsxs53("div", { className: "rounded-2xl border border-slate-200 bg-white p-4 dark:border-slate-800 dark:bg-slate-950/80", children: [
14479
- /* @__PURE__ */ jsxs53("div", { className: "flex flex-wrap gap-2", children: [
14728
+ /* @__PURE__ */ jsxs54("div", { className: "rounded-2xl border border-slate-200 bg-white p-4 dark:border-slate-800 dark:bg-slate-950/80", children: [
14729
+ /* @__PURE__ */ jsxs54("div", { className: "flex flex-wrap gap-2", children: [
14480
14730
  /* @__PURE__ */ jsx75(FilterChip, { label: row.check?.fitsConstraints ? "Constraints fit" : "Constraint mismatch", tone: row.check?.fitsConstraints ? "success" : "danger" }),
14481
14731
  /* @__PURE__ */ jsx75(FilterChip, { label: row.check?.passesRate ? "Rate ok" : "Rate blocked", tone: row.check?.passesRate ? "success" : "warning" }),
14482
14732
  /* @__PURE__ */ jsx75(
@@ -14490,14 +14740,14 @@ function ServiceDetailCard({
14490
14740
  row.reasonLabels.length ? /* @__PURE__ */ jsx75("div", { className: "mt-3 flex flex-wrap gap-2", children: row.reasonLabels.map((reason) => /* @__PURE__ */ jsx75("span", { className: "rounded-full bg-amber-50 px-2.5 py-1 text-xs text-amber-700 dark:bg-amber-500/10 dark:text-amber-200", children: reason }, `${row.id}:${reason}`)) }) : /* @__PURE__ */ jsx75("p", { className: "mt-3 text-sm text-slate-500 dark:text-slate-400", children: "This service is a clean fit for the current visible-group and selected-trigger context." })
14491
14741
  ] })
14492
14742
  ] }) : null,
14493
- /* @__PURE__ */ jsxs53("section", { className: "space-y-3", children: [
14743
+ /* @__PURE__ */ jsxs54("section", { className: "space-y-3", children: [
14494
14744
  /* @__PURE__ */ jsx75(SectionTitle2, { title: "Capabilities", description: "Flags and pricing hints attached to this service." }),
14495
- /* @__PURE__ */ jsx75("div", { className: "rounded-2xl border border-slate-200 bg-white p-4 dark:border-slate-800 dark:bg-slate-950/80", children: summary.flags.length || service?.meta ? /* @__PURE__ */ jsxs53("div", { className: "flex flex-wrap gap-2", children: [
14745
+ /* @__PURE__ */ jsx75("div", { className: "rounded-2xl border border-slate-200 bg-white p-4 dark:border-slate-800 dark:bg-slate-950/80", children: summary.flags.length || service?.meta ? /* @__PURE__ */ jsxs54("div", { className: "flex flex-wrap gap-2", children: [
14496
14746
  summary.flags.map((flag) => /* @__PURE__ */ jsx75("span", { className: "rounded-full bg-emerald-50 px-2.5 py-1 text-xs text-emerald-700 dark:bg-emerald-500/10 dark:text-emerald-200", children: flag }, flag)),
14497
14747
  Object.keys(service?.meta ?? {}).slice(0, 3).map((key) => /* @__PURE__ */ jsx75("span", { className: "rounded-full bg-slate-100 px-2.5 py-1 text-xs text-slate-600 dark:bg-slate-900 dark:text-slate-300", children: key }, key))
14498
14748
  ] }) : /* @__PURE__ */ jsx75("p", { className: "text-sm text-slate-500 dark:text-slate-400", children: "No capability flags were published for this service." }) })
14499
14749
  ] }),
14500
- /* @__PURE__ */ jsxs53("section", { className: "space-y-3", children: [
14750
+ /* @__PURE__ */ jsxs54("section", { className: "space-y-3", children: [
14501
14751
  /* @__PURE__ */ jsx75(SectionTitle2, { title: "Bindings", description: "Nodes currently connected to this service. Click any node to jump back into the canvas." }),
14502
14752
  /* @__PURE__ */ jsx75("div", { className: "rounded-2xl border border-slate-200 bg-white p-4 dark:border-slate-800 dark:bg-slate-950/80", children: summary.attachedNodeIds.length ? /* @__PURE__ */ jsx75("div", { className: "flex flex-wrap gap-2", children: summary.attachedNodeIds.map((nodeId, index) => /* @__PURE__ */ jsx75(
14503
14753
  "button",
@@ -14513,13 +14763,13 @@ function ServiceDetailCard({
14513
14763
  ] });
14514
14764
  }
14515
14765
  function SectionTitle2({ title, description }) {
14516
- return /* @__PURE__ */ jsxs53("div", { children: [
14766
+ return /* @__PURE__ */ jsxs54("div", { children: [
14517
14767
  /* @__PURE__ */ jsx75("p", { className: "text-sm font-semibold text-slate-900 dark:text-slate-100", children: title }),
14518
14768
  /* @__PURE__ */ jsx75("p", { className: "mt-1 text-xs text-slate-500 dark:text-slate-400", children: description })
14519
14769
  ] });
14520
14770
  }
14521
14771
  function DetailMetric({ label, value }) {
14522
- return /* @__PURE__ */ jsxs53("div", { className: "rounded-2xl bg-white px-4 py-3 dark:bg-slate-950", children: [
14772
+ return /* @__PURE__ */ jsxs54("div", { className: "rounded-2xl bg-white px-4 py-3 dark:bg-slate-950", children: [
14523
14773
  /* @__PURE__ */ jsx75("p", { className: "text-[11px] font-semibold uppercase tracking-[0.16em] text-slate-400 dark:text-slate-500", children: label }),
14524
14774
  /* @__PURE__ */ jsx75("p", { className: "mt-2 text-sm font-semibold text-slate-900 dark:text-slate-100", children: value })
14525
14775
  ] });
@@ -14529,22 +14779,22 @@ function FilterChip({ label, tone = "default" }) {
14529
14779
  }
14530
14780
 
14531
14781
  // src/workspace/bottom-panel/services-split-pane.tsx
14532
- import { jsx as jsx76, jsxs as jsxs54 } from "react/jsx-runtime";
14533
- var UNGROUPED_TREE_VALUE = "__catalog_ungrouped__";
14782
+ import { jsx as jsx76, jsxs as jsxs55 } from "react/jsx-runtime";
14783
+ var UNGROUPED_TREE_VALUE2 = "__catalog_ungrouped__";
14534
14784
  function ServicesSplitPane(props) {
14535
14785
  const emptyTitle = props.mode === "active" ? "No active services yet" : "No services match this view";
14536
14786
  const emptyDescription = props.mode === "active" ? "Connect a service to a tag, field, or option and it will appear here with its bindings." : props.mode === "catalog" ? "Select a catalog group or create one to organize source services for faster assignment." : "Try changing the search or toggles to bring more services into view.";
14537
- return /* @__PURE__ */ jsx76("div", { className: "min-h-90 p-4", children: /* @__PURE__ */ jsxs54(ResizablePanelGroup, { direction: "horizontal", className: "min-h-90", children: [
14538
- /* @__PURE__ */ jsx76(ResizablePanel, { defaultSize: 44, minSize: 30, children: /* @__PURE__ */ jsxs54("section", { className: "flex h-full min-h-0 flex-col overflow-hidden", children: [
14539
- /* @__PURE__ */ jsxs54("div", { className: "space-y-3 border-b border-slate-100 pr-4 dark:border-slate-800", children: [
14540
- /* @__PURE__ */ jsxs54("div", { className: "flex items-center justify-between gap-3", children: [
14787
+ return /* @__PURE__ */ jsx76("div", { className: "min-h-90 p-4", children: /* @__PURE__ */ jsxs55(ResizablePanelGroup, { direction: "horizontal", className: "min-h-90", children: [
14788
+ /* @__PURE__ */ jsx76(ResizablePanel, { defaultSize: 44, minSize: 30, children: /* @__PURE__ */ jsxs55("section", { className: "flex h-full min-h-0 flex-col overflow-hidden", children: [
14789
+ /* @__PURE__ */ jsxs55("div", { className: "space-y-3 border-b border-slate-100 pr-4 dark:border-slate-800", children: [
14790
+ /* @__PURE__ */ jsxs55("div", { className: "flex items-center justify-between gap-3", children: [
14541
14791
  /* @__PURE__ */ jsx76("div", { children: /* @__PURE__ */ jsx76("h4", { className: "mt-1 text-base font-semibold text-slate-900 dark:text-slate-100", children: props.mode === "active" ? "Attached services" : props.mode === "catalog" ? "Catalog workspace" : "All services" }) }),
14542
- /* @__PURE__ */ jsxs54("div", { className: "flex items-center gap-2", children: [
14792
+ /* @__PURE__ */ jsxs55("div", { className: "flex items-center gap-2", children: [
14543
14793
  props.mode === "catalog" ? /* @__PURE__ */ jsx76("span", { className: "rounded-full bg-blue-50 px-2.5 py-1 text-[10px] font-semibold tracking-[0.16em] text-blue-700 uppercase dark:bg-blue-500/10 dark:text-blue-200", children: props.selectedCatalogGroupLabel ?? "Ungrouped" }) : null,
14544
14794
  /* @__PURE__ */ jsx76("span", { className: "rounded-full bg-slate-100 px-2.5 py-1 text-[10px] font-semibold tracking-[0.16em] text-slate-600 uppercase dark:bg-slate-900 dark:text-slate-300", children: props.rows.length })
14545
14795
  ] })
14546
14796
  ] }),
14547
- props.mode === "all" && props.appliedSnapshot?.selectedTag ? /* @__PURE__ */ jsxs54("div", { className: "flex flex-wrap gap-2 pb-3", children: [
14797
+ props.mode === "all" && props.appliedSnapshot?.selectedTag ? /* @__PURE__ */ jsxs55("div", { className: "flex flex-wrap gap-2 pb-3", children: [
14548
14798
  /* @__PURE__ */ jsx76(FilterChip2, { label: `Context tag: ${props.appliedSnapshot.selectedTag.label}` }),
14549
14799
  /* @__PURE__ */ jsx76(
14550
14800
  FilterChip2,
@@ -14581,7 +14831,7 @@ function ServicesSplitPane(props) {
14581
14831
  }
14582
14832
  ) }) : null
14583
14833
  ] }),
14584
- /* @__PURE__ */ jsx76(ScrollArea, { className: "h-[calc(var(--bottom-panel-height)-15rem)] max-h-[calc(var(--bottom-panel-height)-15rem)] min-h-0 flex-1", children: /* @__PURE__ */ jsx76("div", { className: "space-y-2 p-3 pl-0", children: props.rows.length === 0 ? /* @__PURE__ */ jsx76(EmptyState, { title: emptyTitle, description: emptyDescription }) : props.rows.map((row) => /* @__PURE__ */ jsxs54(
14834
+ /* @__PURE__ */ jsx76(ScrollArea, { className: "h-[calc(var(--bottom-panel-height)-14.5rem)] max-h-[calc(var(--bottom-panel-height)-14.5rem)] min-h-0 flex-1", children: /* @__PURE__ */ jsx76("div", { className: "space-y-2 p-3 pl-0", children: props.rows.length === 0 ? /* @__PURE__ */ jsx76(EmptyState, { title: emptyTitle, description: emptyDescription }) : props.rows.map((row) => /* @__PURE__ */ jsxs55(
14585
14835
  "button",
14586
14836
  {
14587
14837
  type: "button",
@@ -14594,14 +14844,14 @@ function ServicesSplitPane(props) {
14594
14844
  props.selectedRowId === row.id ? "border-blue-300 bg-blue-50 shadow-sm dark:border-blue-500/40 dark:bg-blue-500/10" : "border-slate-200 bg-white hover:border-slate-300 hover:bg-slate-50 dark:border-slate-800 dark:bg-slate-950/60 dark:hover:border-slate-700"
14595
14845
  ),
14596
14846
  children: [
14597
- /* @__PURE__ */ jsxs54("div", { className: "flex items-start justify-between gap-3", children: [
14598
- /* @__PURE__ */ jsxs54("div", { className: "min-w-0", children: [
14599
- /* @__PURE__ */ jsxs54("div", { className: "flex items-center gap-2", children: [
14847
+ /* @__PURE__ */ jsxs55("div", { className: "flex items-start justify-between gap-3", children: [
14848
+ /* @__PURE__ */ jsxs55("div", { className: "min-w-0", children: [
14849
+ /* @__PURE__ */ jsxs55("div", { className: "flex items-center gap-2", children: [
14600
14850
  /* @__PURE__ */ jsx76(StatusDot, { tone: row.statusTone }),
14601
14851
  /* @__PURE__ */ jsx76("span", { className: "truncate text-sm font-semibold text-slate-900 dark:text-slate-100", children: row.summary.name })
14602
14852
  ] }),
14603
- /* @__PURE__ */ jsxs54("div", { className: "mt-1 flex flex-wrap items-center gap-2 text-xs text-slate-500 dark:text-slate-400", children: [
14604
- /* @__PURE__ */ jsxs54("span", { children: [
14853
+ /* @__PURE__ */ jsxs55("div", { className: "mt-1 flex flex-wrap items-center gap-2 text-xs text-slate-500 dark:text-slate-400", children: [
14854
+ /* @__PURE__ */ jsxs55("span", { children: [
14605
14855
  "#",
14606
14856
  row.summary.id
14607
14857
  ] }),
@@ -14611,13 +14861,13 @@ function ServicesSplitPane(props) {
14611
14861
  ] }),
14612
14862
  /* @__PURE__ */ jsx76("span", { className: statusBadgeClassName(row.statusTone), children: row.statusLabel })
14613
14863
  ] }),
14614
- /* @__PURE__ */ jsxs54("div", { className: "mt-3 flex flex-wrap items-center gap-2", children: [
14615
- /* @__PURE__ */ jsxs54("span", { className: "rounded-full bg-slate-100 px-2.5 py-1 text-[11px] text-slate-600 dark:bg-slate-900 dark:text-slate-300", children: [
14864
+ /* @__PURE__ */ jsxs55("div", { className: "mt-3 flex flex-wrap items-center gap-2", children: [
14865
+ /* @__PURE__ */ jsxs55("span", { className: "rounded-full bg-slate-100 px-2.5 py-1 text-[11px] text-slate-600 dark:bg-slate-900 dark:text-slate-300", children: [
14616
14866
  row.summary.attachmentCount,
14617
14867
  " node",
14618
14868
  row.summary.attachmentCount === 1 ? "" : "s"
14619
14869
  ] }),
14620
- row.summary.rate != null ? /* @__PURE__ */ jsxs54("span", { className: "rounded-full bg-slate-100 px-2.5 py-1 text-[11px] text-slate-600 dark:bg-slate-900 dark:text-slate-300", children: [
14870
+ row.summary.rate != null ? /* @__PURE__ */ jsxs55("span", { className: "rounded-full bg-slate-100 px-2.5 py-1 text-[11px] text-slate-600 dark:bg-slate-900 dark:text-slate-300", children: [
14621
14871
  "Rate ",
14622
14872
  row.summary.rate
14623
14873
  ] }) : null,
@@ -14636,13 +14886,13 @@ function ServicesSplitPane(props) {
14636
14886
  )) }) })
14637
14887
  ] }) }),
14638
14888
  /* @__PURE__ */ jsx76(ResizableHandle, { withHandle: true }),
14639
- /* @__PURE__ */ jsx76(ResizablePanel, { defaultSize: 56, minSize: 36, children: /* @__PURE__ */ jsxs54("section", { className: "flex h-full min-h-0 flex-col overflow-hidden", children: [
14640
- /* @__PURE__ */ jsxs54("div", { className: "border-b border-slate-100 px-4 dark:border-slate-800", children: [
14889
+ /* @__PURE__ */ jsx76(ResizablePanel, { defaultSize: 56, minSize: 36, children: /* @__PURE__ */ jsxs55("section", { className: "flex h-full min-h-0 flex-col overflow-hidden", children: [
14890
+ /* @__PURE__ */ jsxs55("div", { className: "border-b border-slate-100 px-4 dark:border-slate-800", children: [
14641
14891
  /* @__PURE__ */ jsx76("p", { className: "text-xs font-semibold tracking-[0.18em] text-slate-400 uppercase dark:text-slate-500", children: "Service detail" }),
14642
14892
  /* @__PURE__ */ jsx76("h4", { className: "mt-1 text-base font-semibold text-slate-900 dark:text-slate-100", children: props.detailRow ? props.detailRow.summary.name : "Select a service" }),
14643
14893
  /* @__PURE__ */ jsx76("p", { className: "mt-1 text-sm text-slate-500 dark:text-slate-400", children: props.mode === "active" ? "Highlight connected nodes, inspect usage, and jump back into the canvas." : props.mode === "catalog" ? "Inspect compatibility, pricing, and bindings while browsing manual catalog groups." : "Inspect compatibility, pricing, and bindings before assigning the service to a node." })
14644
14894
  ] }),
14645
- /* @__PURE__ */ jsx76(ScrollArea, { className: "h-[calc(var(--bottom-panel-height)-15rem)] min-h-0 flex-1", children: /* @__PURE__ */ jsx76("div", { className: "p-5", children: props.detailRow ? /* @__PURE__ */ jsx76(
14895
+ /* @__PURE__ */ jsx76(ScrollArea, { className: "h-[calc(var(--bottom-panel-height)-14.5rem)] max-h-[calc(var(--bottom-panel-height)-14.5rem)] min-h-0 flex-1", children: /* @__PURE__ */ jsx76("div", { className: "p-5", children: props.detailRow ? /* @__PURE__ */ jsx76(
14646
14896
  ServiceDetailCard,
14647
14897
  {
14648
14898
  mode: props.mode,
@@ -14674,7 +14924,7 @@ function CatalogContextPopover({
14674
14924
  onDraftContextChange
14675
14925
  }) {
14676
14926
  const context = draftContext;
14677
- return /* @__PURE__ */ jsxs54(Popover, { open, onOpenChange, children: [
14927
+ return /* @__PURE__ */ jsxs55(Popover, { open, onOpenChange, children: [
14678
14928
  /* @__PURE__ */ jsx76(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx76(
14679
14929
  "button",
14680
14930
  {
@@ -14684,10 +14934,10 @@ function CatalogContextPopover({
14684
14934
  "inline-flex h-9 w-9 items-center justify-center rounded-xl border text-sm transition",
14685
14935
  compatibleOnly ? "border-blue-200 bg-blue-50 text-blue-700 dark:border-blue-500/30 dark:bg-blue-500/10 dark:text-blue-200" : "border-slate-200 bg-white text-slate-600 hover:bg-slate-100 dark:border-slate-800 dark:bg-slate-950 dark:text-slate-300 dark:hover:bg-slate-900"
14686
14936
  ),
14687
- children: /* @__PURE__ */ jsx76(FiFilter, {})
14937
+ children: /* @__PURE__ */ jsx76(FiFilter2, {})
14688
14938
  }
14689
14939
  ) }),
14690
- /* @__PURE__ */ jsxs54(
14940
+ /* @__PURE__ */ jsxs55(
14691
14941
  PopoverContent,
14692
14942
  {
14693
14943
  align: "end",
@@ -14695,30 +14945,30 @@ function CatalogContextPopover({
14695
14945
  collisionPadding: 16,
14696
14946
  className: "max-h-[min(32rem,var(--radix-popover-content-available-height))] w-[min(24rem,calc(100vw-2rem))] overflow-hidden rounded-2xl p-0",
14697
14947
  children: [
14698
- /* @__PURE__ */ jsxs54("div", { className: "border-b border-slate-200 px-4 py-3 dark:border-slate-800", children: [
14948
+ /* @__PURE__ */ jsxs55("div", { className: "border-b border-slate-200 px-4 py-3 dark:border-slate-800", children: [
14699
14949
  /* @__PURE__ */ jsx76("div", { className: "text-sm font-semibold text-slate-900 dark:text-slate-100", children: "Catalog context" }),
14700
14950
  /* @__PURE__ */ jsx76("p", { className: "mt-1 text-xs text-slate-500 dark:text-slate-400", children: "Control compatibility checks here, or link them to the current workspace context." })
14701
14951
  ] }),
14702
- /* @__PURE__ */ jsx76(ScrollArea, { className: "h-[calc(var(--radix-popover-content-available-height)-4.5rem)] max-h-[calc(var(--radix-popover-content-available-height)-4.5rem)]", children: /* @__PURE__ */ jsxs54("div", { className: "space-y-4 p-4", children: [
14703
- /* @__PURE__ */ jsxs54("label", { className: "flex items-start justify-between gap-3 text-sm text-slate-900 dark:text-slate-100", children: [
14704
- /* @__PURE__ */ jsxs54("span", { className: "min-w-0", children: [
14952
+ /* @__PURE__ */ jsx76(ScrollArea, { className: "h-[calc(var(--radix-popover-content-available-height)-4.5rem)] max-h-[calc(var(--radix-popover-content-available-height)-4.5rem)]", children: /* @__PURE__ */ jsxs55("div", { className: "space-y-4 p-4", children: [
14953
+ /* @__PURE__ */ jsxs55("label", { className: "flex items-start justify-between gap-3 text-sm text-slate-900 dark:text-slate-100", children: [
14954
+ /* @__PURE__ */ jsxs55("span", { className: "min-w-0", children: [
14705
14955
  /* @__PURE__ */ jsx76("span", { className: "block font-medium", children: "Compatible only" }),
14706
14956
  /* @__PURE__ */ jsx76("span", { className: "mt-1 block text-xs text-slate-500 dark:text-slate-400", children: "Show only services that fit this catalog context safely." })
14707
14957
  ] }),
14708
14958
  /* @__PURE__ */ jsx76("input", { type: "checkbox", checked: compatibleOnly, onChange: (event) => onCompatibleOnlyChange(event.target.checked) })
14709
14959
  ] }),
14710
- /* @__PURE__ */ jsxs54("label", { className: "flex items-start justify-between gap-3 text-sm text-slate-900 dark:text-slate-100", children: [
14711
- /* @__PURE__ */ jsxs54("span", { className: "min-w-0", children: [
14960
+ /* @__PURE__ */ jsxs55("label", { className: "flex items-start justify-between gap-3 text-sm text-slate-900 dark:text-slate-100", children: [
14961
+ /* @__PURE__ */ jsxs55("span", { className: "min-w-0", children: [
14712
14962
  /* @__PURE__ */ jsx76("span", { className: "block font-medium", children: "Link to current context" }),
14713
14963
  /* @__PURE__ */ jsx76("span", { className: "mt-1 block text-xs text-slate-500 dark:text-slate-400", children: "Mirror the current canvas tag and selected buttons while linked." })
14714
14964
  ] }),
14715
14965
  /* @__PURE__ */ jsx76("input", { type: "checkbox", checked: contextLinked, onChange: (event) => onContextLinkedChange(event.target.checked) })
14716
14966
  ] }),
14717
- /* @__PURE__ */ jsxs54("div", { className: "space-y-2 rounded-2xl border border-slate-200 bg-slate-50/70 p-3 dark:border-slate-800 dark:bg-slate-900/40", children: [
14967
+ /* @__PURE__ */ jsxs55("div", { className: "space-y-2 rounded-2xl border border-slate-200 bg-slate-50/70 p-3 dark:border-slate-800 dark:bg-slate-900/40", children: [
14718
14968
  /* @__PURE__ */ jsx76("div", { className: "text-xs font-semibold tracking-[0.16em] text-slate-500 uppercase dark:text-slate-400", children: "Tags" }),
14719
14969
  /* @__PURE__ */ jsx76("div", { className: "space-y-2", children: (draftSnapshot?.tags ?? []).map((tag) => {
14720
14970
  const selected = context?.selectedTagId === tag.id;
14721
- return /* @__PURE__ */ jsxs54("label", { className: "flex items-start gap-3 text-sm text-slate-900 dark:text-slate-100", children: [
14971
+ return /* @__PURE__ */ jsxs55("label", { className: "flex items-start gap-3 text-sm text-slate-900 dark:text-slate-100", children: [
14722
14972
  /* @__PURE__ */ jsx76(
14723
14973
  "input",
14724
14974
  {
@@ -14737,20 +14987,20 @@ function CatalogContextPopover({
14737
14987
  })
14738
14988
  }
14739
14989
  ),
14740
- /* @__PURE__ */ jsxs54("span", { className: "min-w-0", children: [
14990
+ /* @__PURE__ */ jsxs55("span", { className: "min-w-0", children: [
14741
14991
  /* @__PURE__ */ jsx76("span", { className: "block font-medium", children: tag.label }),
14742
14992
  tag.description ? /* @__PURE__ */ jsx76("span", { className: "block text-xs text-slate-500 dark:text-slate-400", children: tag.description }) : null
14743
14993
  ] })
14744
14994
  ] }, tag.id);
14745
14995
  }) })
14746
14996
  ] }),
14747
- /* @__PURE__ */ jsxs54("div", { className: "space-y-2 rounded-2xl border border-slate-200 bg-slate-50/70 p-3 dark:border-slate-800 dark:bg-slate-900/40", children: [
14997
+ /* @__PURE__ */ jsxs55("div", { className: "space-y-2 rounded-2xl border border-slate-200 bg-slate-50/70 p-3 dark:border-slate-800 dark:bg-slate-900/40", children: [
14748
14998
  /* @__PURE__ */ jsx76("div", { className: "text-xs font-semibold tracking-[0.16em] text-slate-500 uppercase dark:text-slate-400", children: "Selected buttons" }),
14749
- draftSnapshot?.buttonGroups?.length ? /* @__PURE__ */ jsx76("div", { className: "space-y-3", children: draftSnapshot.buttonGroups.map((group) => /* @__PURE__ */ jsxs54("div", { className: "space-y-2", children: [
14999
+ draftSnapshot?.buttonGroups?.length ? /* @__PURE__ */ jsx76("div", { className: "space-y-3", children: draftSnapshot.buttonGroups.map((group) => /* @__PURE__ */ jsxs55("div", { className: "space-y-2", children: [
14750
15000
  /* @__PURE__ */ jsx76("div", { className: "text-sm font-medium text-slate-900 dark:text-slate-100", children: group.label }),
14751
15001
  /* @__PURE__ */ jsx76("div", { className: "space-y-1", children: group.options.map((option) => {
14752
15002
  const checked = context?.selectedButtons.includes(option.id) ?? false;
14753
- return /* @__PURE__ */ jsxs54(
15003
+ return /* @__PURE__ */ jsxs55(
14754
15004
  "label",
14755
15005
  {
14756
15006
  className: "flex items-start gap-3 text-sm text-slate-900 dark:text-slate-100",
@@ -14772,7 +15022,7 @@ function CatalogContextPopover({
14772
15022
  })
14773
15023
  }
14774
15024
  ),
14775
- /* @__PURE__ */ jsxs54("span", { className: "min-w-0", children: [
15025
+ /* @__PURE__ */ jsxs55("span", { className: "min-w-0", children: [
14776
15026
  /* @__PURE__ */ jsx76("span", { className: "block", children: option.label }),
14777
15027
  option.description ? /* @__PURE__ */ jsx76("span", { className: "block text-xs text-slate-500 dark:text-slate-400", children: option.description }) : null
14778
15028
  ] })
@@ -14783,9 +15033,9 @@ function CatalogContextPopover({
14783
15033
  }) })
14784
15034
  ] }, group.id)) }) : /* @__PURE__ */ jsx76("div", { className: "text-sm text-slate-500 dark:text-slate-400", children: "No visible trigger options for the selected tag." })
14785
15035
  ] }),
14786
- /* @__PURE__ */ jsxs54("div", { className: "space-y-2 rounded-2xl border border-slate-200 bg-slate-50/70 p-3 dark:border-slate-800 dark:bg-slate-900/40", children: [
15036
+ /* @__PURE__ */ jsxs55("div", { className: "space-y-2 rounded-2xl border border-slate-200 bg-slate-50/70 p-3 dark:border-slate-800 dark:bg-slate-900/40", children: [
14787
15037
  /* @__PURE__ */ jsx76("div", { className: "text-xs font-semibold tracking-[0.16em] text-slate-500 uppercase dark:text-slate-400", children: "Safety" }),
14788
- /* @__PURE__ */ jsxs54("label", { className: "flex items-center justify-between gap-3 text-sm text-slate-900 dark:text-slate-100", children: [
15038
+ /* @__PURE__ */ jsxs55("label", { className: "flex items-center justify-between gap-3 text-sm text-slate-900 dark:text-slate-100", children: [
14789
15039
  /* @__PURE__ */ jsx76("span", { children: "Strict safety" }),
14790
15040
  /* @__PURE__ */ jsx76(
14791
15041
  "input",
@@ -14800,7 +15050,7 @@ function CatalogContextPopover({
14800
15050
  }
14801
15051
  )
14802
15052
  ] }),
14803
- /* @__PURE__ */ jsxs54("label", { className: "flex items-center justify-between gap-3 text-sm text-slate-900 dark:text-slate-100", children: [
15053
+ /* @__PURE__ */ jsxs55("label", { className: "flex items-center justify-between gap-3 text-sm text-slate-900 dark:text-slate-100", children: [
14804
15054
  /* @__PURE__ */ jsx76("span", { children: "Enforce policies" }),
14805
15055
  /* @__PURE__ */ jsx76(
14806
15056
  "input",
@@ -14834,10 +15084,10 @@ function CatalogToolbar({
14834
15084
  onDeleteGroup,
14835
15085
  onAssignServices
14836
15086
  }) {
14837
- const treeValue = selectedGroupId ?? (ungroupedSelected ? UNGROUPED_TREE_VALUE : void 0);
14838
- const treeOptions = buildCatalogGroupTreeOptions(groups);
14839
- return /* @__PURE__ */ jsxs54("div", { className: "flex items-center justify-between gap-3", children: [
14840
- /* @__PURE__ */ jsxs54("div", { className: "flex flex-wrap items-center gap-2", children: [
15087
+ const treeValue = selectedGroupId ?? (ungroupedSelected ? UNGROUPED_TREE_VALUE2 : void 0);
15088
+ const treeOptions = buildCatalogGroupTreeOptions2(groups);
15089
+ return /* @__PURE__ */ jsxs55("div", { className: "flex items-center justify-between gap-3", children: [
15090
+ /* @__PURE__ */ jsxs55("div", { className: "flex flex-wrap items-center gap-2", children: [
14841
15091
  /* @__PURE__ */ jsx76(
14842
15092
  GroupInputPopoverButton,
14843
15093
  {
@@ -14893,14 +15143,14 @@ function CatalogToolbar({
14893
15143
  className: "w-fit!",
14894
15144
  multiple: false,
14895
15145
  value: treeValue,
14896
- options: [{ key: UNGROUPED_TREE_VALUE, label: "Ungrouped" }, ...treeOptions],
15146
+ options: [{ key: UNGROUPED_TREE_VALUE2, label: "Ungrouped" }, ...treeOptions],
14897
15147
  searchable: true,
14898
15148
  clearable: true,
14899
15149
  onChange: (event) => {
14900
15150
  const next = event.value == null ? null : String(event.value);
14901
- onSelectGroup(next === UNGROUPED_TREE_VALUE ? null : next);
15151
+ onSelectGroup(next === UNGROUPED_TREE_VALUE2 ? null : next);
14902
15152
  },
14903
- button: /* @__PURE__ */ jsx76(FaFolderOpen, {})
15153
+ button: /* @__PURE__ */ jsx76(FaFolderOpen2, {})
14904
15154
  }
14905
15155
  )
14906
15156
  ] });
@@ -14916,10 +15166,10 @@ function GroupInputPopoverButton({
14916
15166
  }) {
14917
15167
  const [open, setOpen] = useState33(false);
14918
15168
  const [value, setValue] = useState33(initialValue);
14919
- useEffect20(() => {
15169
+ useEffect21(() => {
14920
15170
  if (open) setValue(initialValue);
14921
15171
  }, [initialValue, open]);
14922
- return /* @__PURE__ */ jsxs54(Popover, { open, onOpenChange: setOpen, children: [
15172
+ return /* @__PURE__ */ jsxs55(Popover, { open, onOpenChange: setOpen, children: [
14923
15173
  /* @__PURE__ */ jsx76(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx76(
14924
15174
  "button",
14925
15175
  {
@@ -14934,8 +15184,8 @@ function GroupInputPopoverButton({
14934
15184
  children: icon
14935
15185
  }
14936
15186
  ) }),
14937
- /* @__PURE__ */ jsx76(PopoverContent, { align: "start", side: "bottom", sideOffset: 8, collisionPadding: 16, className: "w-80 rounded-2xl", children: /* @__PURE__ */ jsxs54("div", { className: "space-y-3", children: [
14938
- /* @__PURE__ */ jsxs54("div", { children: [
15187
+ /* @__PURE__ */ jsx76(PopoverContent, { align: "start", side: "bottom", sideOffset: 8, collisionPadding: 16, className: "w-80 rounded-2xl", children: /* @__PURE__ */ jsxs55("div", { className: "space-y-3", children: [
15188
+ /* @__PURE__ */ jsxs55("div", { children: [
14939
15189
  /* @__PURE__ */ jsx76("div", { className: "text-sm font-semibold text-slate-900 dark:text-slate-100", children: title }),
14940
15190
  /* @__PURE__ */ jsx76("p", { className: "mt-1 text-xs text-slate-500 dark:text-slate-400", children: "Names are editor-side catalog labels only." })
14941
15191
  ] }),
@@ -14950,7 +15200,7 @@ function GroupInputPopoverButton({
14950
15200
  autoComplete: "off"
14951
15201
  }
14952
15202
  ),
14953
- /* @__PURE__ */ jsxs54("div", { className: "flex justify-end gap-2", children: [
15203
+ /* @__PURE__ */ jsxs55("div", { className: "flex justify-end gap-2", children: [
14954
15204
  /* @__PURE__ */ jsx76(Button, { type: "button", variant: "outline", size: "sm", onClick: () => setOpen(false), className: "rounded-xl", children: "Cancel" }),
14955
15205
  /* @__PURE__ */ jsx76(
14956
15206
  Button,
@@ -14982,7 +15232,7 @@ function ConfirmPopoverButton({
14982
15232
  onConfirm
14983
15233
  }) {
14984
15234
  const [open, setOpen] = useState33(false);
14985
- return /* @__PURE__ */ jsxs54(Popover, { open, onOpenChange: setOpen, children: [
15235
+ return /* @__PURE__ */ jsxs55(Popover, { open, onOpenChange: setOpen, children: [
14986
15236
  /* @__PURE__ */ jsx76(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx76(
14987
15237
  "button",
14988
15238
  {
@@ -14997,12 +15247,12 @@ function ConfirmPopoverButton({
14997
15247
  children: icon
14998
15248
  }
14999
15249
  ) }),
15000
- /* @__PURE__ */ jsx76(PopoverContent, { align: "start", side: "bottom", sideOffset: 8, collisionPadding: 16, className: "w-80 rounded-2xl", children: /* @__PURE__ */ jsxs54("div", { className: "space-y-3", children: [
15001
- /* @__PURE__ */ jsxs54("div", { children: [
15250
+ /* @__PURE__ */ jsx76(PopoverContent, { align: "start", side: "bottom", sideOffset: 8, collisionPadding: 16, className: "w-80 rounded-2xl", children: /* @__PURE__ */ jsxs55("div", { className: "space-y-3", children: [
15251
+ /* @__PURE__ */ jsxs55("div", { children: [
15002
15252
  /* @__PURE__ */ jsx76("div", { className: "text-sm font-semibold text-slate-900 dark:text-slate-100", children: title }),
15003
15253
  /* @__PURE__ */ jsx76("p", { className: "mt-1 text-xs text-slate-500 dark:text-slate-400", children: description })
15004
15254
  ] }),
15005
- /* @__PURE__ */ jsxs54("div", { className: "flex justify-end gap-2", children: [
15255
+ /* @__PURE__ */ jsxs55("div", { className: "flex justify-end gap-2", children: [
15006
15256
  /* @__PURE__ */ jsx76(Button, { type: "button", variant: "outline", size: "sm", onClick: () => setOpen(false), className: "rounded-xl", children: "Cancel" }),
15007
15257
  /* @__PURE__ */ jsx76(
15008
15258
  Button,
@@ -15027,7 +15277,7 @@ function ToolbarIconButton({
15027
15277
  disabled = false,
15028
15278
  onClick
15029
15279
  }) {
15030
- return /* @__PURE__ */ jsxs54(Tooltip, { children: [
15280
+ return /* @__PURE__ */ jsxs55(Tooltip, { children: [
15031
15281
  /* @__PURE__ */ jsx76(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx76(
15032
15282
  "button",
15033
15283
  {
@@ -15048,9 +15298,9 @@ function ToolbarIconButton({
15048
15298
  function FilterChip2({ label, tone = "default" }) {
15049
15299
  return /* @__PURE__ */ jsx76("span", { className: cn("rounded-full px-2.5 py-1 text-[11px] font-medium", filterChipClassName(tone)), children: label });
15050
15300
  }
15051
- function buildCatalogGroupTreeOptions(groups, parentId = null) {
15301
+ function buildCatalogGroupTreeOptions2(groups, parentId = null) {
15052
15302
  return groups.filter((group) => (group.parentId ?? null) === parentId).sort((a, b) => (a.order ?? 0) - (b.order ?? 0) || a.label.localeCompare(b.label)).map((group) => {
15053
- const children = buildCatalogGroupTreeOptions(groups, group.id);
15303
+ const children = buildCatalogGroupTreeOptions2(groups, group.id);
15054
15304
  return {
15055
15305
  key: group.id,
15056
15306
  label: group.label,
@@ -15061,7 +15311,7 @@ function buildCatalogGroupTreeOptions(groups, parentId = null) {
15061
15311
  }
15062
15312
 
15063
15313
  // src/workspace/bottom-panel/index.tsx
15064
- import { Fragment as Fragment16, jsx as jsx77, jsxs as jsxs55 } from "react/jsx-runtime";
15314
+ import { Fragment as Fragment16, jsx as jsx77, jsxs as jsxs56 } from "react/jsx-runtime";
15065
15315
  var DRAG_MIME = "application/x-service-builder-service";
15066
15316
  function BottomConsolePanel({ controller, errors, activeServices, allServices, onServiceDragStateChange }) {
15067
15317
  const canvas = useCanvas21();
@@ -15156,25 +15406,25 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
15156
15406
  ).filter((row) => row.matchesSearch).filter((row) => !compatibleOnly || row.isCompatible).filter((row) => !hideActiveServices || !hiddenServiceIds.has(row.id)),
15157
15407
  [allChecksById, allSearch, allServices, compatibleOnly, effectiveCatalogContext, hiddenServiceIds, hideActiveServices, servicesMap]
15158
15408
  );
15159
- useEffect21(() => {
15409
+ useEffect22(() => {
15160
15410
  const next = createDefaultServiceContext(canvas.props, preferredTagId);
15161
15411
  setCatalogContextDraft((current) => {
15162
15412
  if (contextLinked) return current;
15163
15413
  return current.selectedTagId ? current : next;
15164
15414
  });
15165
15415
  }, [canvas.props, contextLinked, preferredTagId]);
15166
- useEffect21(() => {
15416
+ useEffect22(() => {
15167
15417
  if (!contextLinked) return;
15168
15418
  setCatalogContextDraft(liveSelectionContext);
15169
15419
  }, [contextLinked, liveSelectionContext]);
15170
- useEffect21(() => {
15420
+ useEffect22(() => {
15171
15421
  if (contextLinked) return;
15172
15422
  const next = sanitizeServiceContext(draftSnapshot, catalogContextDraft);
15173
15423
  if (JSON.stringify(next) !== JSON.stringify(catalogContextDraft)) {
15174
15424
  setCatalogContextDraft(next);
15175
15425
  }
15176
15426
  }, [catalogContextDraft, contextLinked, draftSnapshot]);
15177
- useEffect21(() => {
15427
+ useEffect22(() => {
15178
15428
  const editor = canvas.api.editor;
15179
15429
  const ensured = editor.getCatalog?.() ?? editor.ensureCatalog?.();
15180
15430
  console.log(ensured);
@@ -15221,24 +15471,24 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
15221
15471
  return ids;
15222
15472
  }, [canvas.activeId, canvas.selectionInfo.ids]);
15223
15473
  const consoleIssueCount = errors.validation.length + errors.logs.length + notices.length;
15224
- useEffect21(() => {
15474
+ useEffect22(() => {
15225
15475
  setSelectedActiveServiceId((current) => ensureSelectedRow(current, activeRows));
15226
15476
  }, [activeRows]);
15227
- useEffect21(() => {
15477
+ useEffect22(() => {
15228
15478
  if (catalogState?.selectedServiceId == null) return;
15229
15479
  setSelectedAllServiceId(String(catalogState.selectedServiceId));
15230
15480
  }, [catalogState?.selectedServiceId]);
15231
- useEffect21(() => {
15481
+ useEffect22(() => {
15232
15482
  setSelectedAllServiceId((current) => ensureSelectedRow(current, visibleAllRows));
15233
15483
  }, [visibleAllRows]);
15234
- useEffect21(() => {
15484
+ useEffect22(() => {
15235
15485
  const desiredIds = controller.isOpen && controller.activeTab === "activeServices" && selectedActiveServiceId ? activeRows.find((row) => row.id === selectedActiveServiceId)?.summary.attachedNodeIds ?? [] : [];
15236
15486
  if (!sameIds(lastHighlightedIdsRef.current, desiredIds)) {
15237
15487
  canvas.api.setHighlighted(desiredIds);
15238
15488
  lastHighlightedIdsRef.current = [...desiredIds];
15239
15489
  }
15240
15490
  }, [activeRows, canvas.api, controller.activeTab, controller.isOpen, selectedActiveServiceId]);
15241
- useEffect21(() => {
15491
+ useEffect22(() => {
15242
15492
  return () => {
15243
15493
  if (lastHighlightedIdsRef.current.length) {
15244
15494
  canvas.api.setHighlighted([]);
@@ -15246,10 +15496,10 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
15246
15496
  }
15247
15497
  };
15248
15498
  }, [canvas.api]);
15249
- useEffect21(() => {
15499
+ useEffect22(() => {
15250
15500
  if (searchOpen) searchInputRef.current?.focus();
15251
15501
  }, [searchOpen]);
15252
- useEffect21(() => {
15502
+ useEffect22(() => {
15253
15503
  setPanelPosition((current) => {
15254
15504
  const resolved = resolvePanelPosition(current, panelRef.current, panelContainerRef.current);
15255
15505
  persistPanelPosition(resolved);
@@ -15271,7 +15521,7 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
15271
15521
  }
15272
15522
  event.preventDefault();
15273
15523
  };
15274
- useEffect21(() => {
15524
+ useEffect22(() => {
15275
15525
  if (!draggingPanel) return;
15276
15526
  const onPointerMove = (event) => {
15277
15527
  const start = dragStartRef.current;
@@ -15299,7 +15549,7 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
15299
15549
  window.removeEventListener("pointercancel", onPointerUp);
15300
15550
  };
15301
15551
  }, [draggingPanel, panelPosition]);
15302
- const setCatalogMode = useCallback18(
15552
+ const setCatalogMode = useCallback19(
15303
15553
  (mode) => {
15304
15554
  const editor = canvas.api.editor;
15305
15555
  editor.ensureCatalog?.();
@@ -15307,27 +15557,27 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
15307
15557
  },
15308
15558
  [canvas.api.editor]
15309
15559
  );
15310
- const handleSelectCatalogService = useCallback18(
15560
+ const handleSelectCatalogService = useCallback19(
15311
15561
  (id) => {
15312
15562
  setSelectedAllServiceId(id);
15313
15563
  canvas.api.editor.setSelectedCatalogService?.(id ?? void 0);
15314
15564
  },
15315
15565
  [canvas.api.editor]
15316
15566
  );
15317
- const handleSelectCatalogGroup = useCallback18(
15567
+ const handleSelectCatalogGroup = useCallback19(
15318
15568
  (groupId) => {
15319
15569
  canvas.api.editor.setActiveCatalogNode?.(groupId ?? void 0);
15320
15570
  },
15321
15571
  [canvas.api.editor]
15322
15572
  );
15323
- const handleCreateRootGroup = useCallback18(
15573
+ const handleCreateRootGroup = useCallback19(
15324
15574
  (label) => {
15325
15575
  if (!label.trim()) return;
15326
15576
  canvas.api.editor.createCatalogGroup?.({ label: label.trim() });
15327
15577
  },
15328
15578
  [canvas.api.editor]
15329
15579
  );
15330
- const handleCreateChildGroup = useCallback18(
15580
+ const handleCreateChildGroup = useCallback19(
15331
15581
  (label) => {
15332
15582
  if (!selectedCatalogGroupId) return;
15333
15583
  const editor = canvas.api.editor;
@@ -15336,7 +15586,7 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
15336
15586
  },
15337
15587
  [canvas.api.editor, selectedCatalogGroupId]
15338
15588
  );
15339
- const handleRenameGroup = useCallback18(
15589
+ const handleRenameGroup = useCallback19(
15340
15590
  (label) => {
15341
15591
  if (!selectedCatalogGroupId) return;
15342
15592
  const group = catalogGroups.find((item) => item.id === selectedCatalogGroupId);
@@ -15346,15 +15596,15 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
15346
15596
  },
15347
15597
  [canvas.api.editor, catalogGroups, selectedCatalogGroupId]
15348
15598
  );
15349
- const handleDeleteGroup = useCallback18(() => {
15599
+ const handleDeleteGroup = useCallback19(() => {
15350
15600
  if (!selectedCatalogGroupId) return;
15351
15601
  canvas.api.editor.removeCatalogNode?.(selectedCatalogGroupId, { cascade: true });
15352
15602
  }, [canvas.api.editor, selectedCatalogGroupId]);
15353
- const handleAssignServices = useCallback18(() => {
15603
+ const handleAssignServices = useCallback19(() => {
15354
15604
  if (!selectedCatalogGroupId) return;
15355
15605
  setServicePickerOpen(true);
15356
15606
  }, [selectedCatalogGroupId]);
15357
- const handleConfirmAssignServices = useCallback18(
15607
+ const handleConfirmAssignServices = useCallback19(
15358
15608
  (serviceIds) => {
15359
15609
  if (!selectedCatalogGroupId || !serviceIds.length) return;
15360
15610
  canvas.api.editor.assignServicesToCatalogGroup?.(selectedCatalogGroupId, serviceIds, "append");
@@ -15395,7 +15645,7 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
15395
15645
  }
15396
15646
  ) });
15397
15647
  }, [controller.activeTab, activeSearch, allSearch, setActiveSearch, setAllSearch]);
15398
- return /* @__PURE__ */ jsxs55("div", { ref: panelContainerRef, className: "pointer-events-none absolute inset-0", children: [
15648
+ return /* @__PURE__ */ jsxs56("div", { ref: panelContainerRef, className: "pointer-events-none absolute inset-0", children: [
15399
15649
  /* @__PURE__ */ jsx77(
15400
15650
  ServicePickerDialog,
15401
15651
  {
@@ -15409,7 +15659,7 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
15409
15659
  onConfirm: handleConfirmAssignServices
15410
15660
  }
15411
15661
  ),
15412
- /* @__PURE__ */ jsxs55(
15662
+ /* @__PURE__ */ jsxs56(
15413
15663
  Panel,
15414
15664
  {
15415
15665
  ref: panelRef,
@@ -15440,8 +15690,8 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
15440
15690
  ["--bottom-panel-height"]: controller.height + "px"
15441
15691
  },
15442
15692
  children: [
15443
- /* @__PURE__ */ jsxs55("div", { className: "flex items-center justify-between gap-3 border-b border-slate-200/80 px-3 py-2 dark:border-slate-800/80", children: [
15444
- /* @__PURE__ */ jsx77("div", { className: "flex min-w-0 items-center gap-1", children: tabs.map((tab) => /* @__PURE__ */ jsxs55(
15693
+ /* @__PURE__ */ jsxs56("div", { className: "flex items-center justify-between gap-3 border-b border-slate-200/80 px-3 py-2 dark:border-slate-800/80", children: [
15694
+ /* @__PURE__ */ jsx77("div", { className: "flex min-w-0 items-center gap-1", children: tabs.map((tab) => /* @__PURE__ */ jsxs56(
15445
15695
  "button",
15446
15696
  {
15447
15697
  type: "button",
@@ -15467,8 +15717,8 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
15467
15717
  },
15468
15718
  tab.id
15469
15719
  )) }),
15470
- /* @__PURE__ */ jsxs55("div", { className: "flex items-center gap-1", children: [
15471
- /* @__PURE__ */ jsxs55(
15720
+ /* @__PURE__ */ jsxs56("div", { className: "flex items-center gap-1", children: [
15721
+ /* @__PURE__ */ jsxs56(
15472
15722
  "button",
15473
15723
  {
15474
15724
  type: "button",
@@ -15483,7 +15733,7 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
15483
15733
  ]
15484
15734
  }
15485
15735
  ),
15486
- /* @__PURE__ */ jsxs55("div", { className: "hidden items-center gap-2 rounded-xl border border-slate-200/80 px-2 py-1 text-xs text-slate-500 md:flex dark:border-slate-800 dark:text-slate-400", children: [
15736
+ /* @__PURE__ */ jsxs56("div", { className: "hidden items-center gap-2 rounded-xl border border-slate-200/80 px-2 py-1 text-xs text-slate-500 md:flex dark:border-slate-800 dark:text-slate-400", children: [
15487
15737
  /* @__PURE__ */ jsx77(LuGripHorizontal, {}),
15488
15738
  /* @__PURE__ */ jsx77("span", { children: "Resize from top or side edges" })
15489
15739
  ] }),
@@ -15500,13 +15750,13 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
15500
15750
  )
15501
15751
  ] })
15502
15752
  ] }),
15503
- /* @__PURE__ */ jsxs55("div", { className: "flex min-h-0 flex-1 flex-col bg-slate-50/70 dark:bg-slate-950/40", children: [
15504
- controller.activeTab !== "console" ? /* @__PURE__ */ jsxs55("div", { className: "flex items-center justify-between gap-3 border-b border-slate-200/70 px-4 py-3 dark:border-slate-800/70", children: [
15505
- /* @__PURE__ */ jsxs55("div", { className: "min-w-0", children: [
15753
+ /* @__PURE__ */ jsxs56("div", { className: "flex min-h-0 flex-1 flex-col bg-slate-50/70 dark:bg-slate-950/40", children: [
15754
+ controller.activeTab !== "console" ? /* @__PURE__ */ jsxs56("div", { className: "flex items-center justify-between gap-3 border-b border-slate-200/70 px-4 py-3 dark:border-slate-800/70", children: [
15755
+ /* @__PURE__ */ jsxs56("div", { className: "min-w-0", children: [
15506
15756
  /* @__PURE__ */ jsx77("p", { className: "text-sm font-semibold text-slate-900 dark:text-slate-100", children: controller.activeTab === "activeServices" ? "Connected services" : "Service catalog" }),
15507
15757
  /* @__PURE__ */ jsx77("p", { className: "mt-1 text-xs text-slate-500 dark:text-slate-400", children: controller.activeTab === "activeServices" ? "Bound services can be highlighted back onto the canvas from here." : catalogPanelMode === "catalog" ? "Browse source services through manual editor-side catalog groups while keeping detail and compatibility visible." : "Browse every source service, filter by current visible-group compatibility, and drag it onto nodes." })
15508
15758
  ] }),
15509
- /* @__PURE__ */ jsx77("div", { className: "flex items-center gap-3", children: /* @__PURE__ */ jsxs55("div", { className: "relative flex items-center gap-2", children: [
15759
+ /* @__PURE__ */ jsx77("div", { className: "flex items-center gap-3", children: /* @__PURE__ */ jsxs56("div", { className: "relative flex items-center gap-2", children: [
15510
15760
  searchOpen ? Search : null,
15511
15761
  /* @__PURE__ */ jsx77(
15512
15762
  HeaderIconButton,
@@ -15517,7 +15767,7 @@ function BottomConsolePanel({ controller, errors, activeServices, allServices, o
15517
15767
  children: /* @__PURE__ */ jsx77(FiSearch, {})
15518
15768
  }
15519
15769
  ),
15520
- controller.activeTab === "allServices" ? /* @__PURE__ */ jsxs55(Fragment16, { children: [
15770
+ controller.activeTab === "allServices" ? /* @__PURE__ */ jsxs56(Fragment16, { children: [
15521
15771
  /* @__PURE__ */ jsx77(
15522
15772
  CatalogContextPopover,
15523
15773
  {
@@ -15645,7 +15895,7 @@ function HeaderIconButton({
15645
15895
  active = false,
15646
15896
  onClick
15647
15897
  }) {
15648
- return /* @__PURE__ */ jsxs55(Tooltip, { children: [
15898
+ return /* @__PURE__ */ jsxs56(Tooltip, { children: [
15649
15899
  /* @__PURE__ */ jsx77(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx77(
15650
15900
  "button",
15651
15901
  {
@@ -15663,7 +15913,7 @@ function HeaderIconButton({
15663
15913
  ] });
15664
15914
  }
15665
15915
  function CatalogModeSwitch({ mode, onChange }) {
15666
- return /* @__PURE__ */ jsxs55("div", { className: "inline-flex items-center rounded-xl border border-slate-200 bg-white p-1 dark:border-slate-800 dark:bg-slate-950", children: [
15916
+ return /* @__PURE__ */ jsxs56("div", { className: "inline-flex items-center rounded-xl border border-slate-200 bg-white p-1 dark:border-slate-800 dark:bg-slate-950", children: [
15667
15917
  /* @__PURE__ */ jsx77(
15668
15918
  "button",
15669
15919
  {
@@ -16319,7 +16569,7 @@ var workspaceBackend = createMemoryWorkspaceBackend({
16319
16569
  });
16320
16570
 
16321
16571
  // src/index.tsx
16322
- import { Fragment as Fragment17, jsx as jsx78, jsxs as jsxs56 } from "react/jsx-runtime";
16572
+ import { Fragment as Fragment17, jsx as jsx78, jsxs as jsxs57 } from "react/jsx-runtime";
16323
16573
  var inputRegistry = createInputRegistry();
16324
16574
  registerEntries(inputRegistry);
16325
16575
  function WorkspaceLayout({ onShare, onPlay, menu }) {
@@ -16329,9 +16579,9 @@ function WorkspaceLayout({ onShare, onPlay, menu }) {
16329
16579
  const bottomPanel = useBottomConsolePanel();
16330
16580
  const [draggingServiceId, setDraggingServiceId] = useState35(null);
16331
16581
  const serviceSummary = useMemo35(() => buildServiceSummaries(canvas, ws), [canvas.props, canvas.selectionInfo, canvas.activeId, ws.services.data]);
16332
- return /* @__PURE__ */ jsx78(FallbackQuickAddProvider, { children: /* @__PURE__ */ jsx78(NodeContextMenuProvider, { children: /* @__PURE__ */ jsx78(FallbackEditorModalProvider, { children: /* @__PURE__ */ jsxs56("div", { className: "relative flex h-screen flex-col overflow-hidden *:font-display", children: [
16582
+ return /* @__PURE__ */ jsx78(FallbackQuickAddProvider, { children: /* @__PURE__ */ jsx78(NodeContextMenuProvider, { children: /* @__PURE__ */ jsx78(FallbackEditorModalProvider, { children: /* @__PURE__ */ jsxs57("div", { className: "relative flex h-screen flex-col overflow-hidden *:font-display", children: [
16333
16583
  /* @__PURE__ */ jsx78("div", { className: "pointer-events-none absolute top-4 left-1/2 z-30 w-full max-w-2xl -translate-x-1/2 px-4", children: /* @__PURE__ */ jsx78("div", { className: "pointer-events-auto", children: /* @__PURE__ */ jsx78(WorkspaceBootStatusSurface, { boot: ws.boot }) }) }),
16334
- /* @__PURE__ */ jsxs56("div", { className: "flex grow overflow-hidden", children: [
16584
+ /* @__PURE__ */ jsxs57("div", { className: "flex grow overflow-hidden", children: [
16335
16585
  /* @__PURE__ */ jsx78(left_default, { menu }),
16336
16586
  /* @__PURE__ */ jsx78(
16337
16587
  CanvasPanel,
@@ -16432,7 +16682,7 @@ var Styles = `
16432
16682
 
16433
16683
  `;
16434
16684
  function ServiceBuilder({ backend, actor, onShare, onPlay, menu }) {
16435
- return /* @__PURE__ */ jsxs56(Fragment17, { children: [
16685
+ return /* @__PURE__ */ jsxs57(Fragment17, { children: [
16436
16686
  /* @__PURE__ */ jsx78("style", { children: Styles }),
16437
16687
  /* @__PURE__ */ jsx78(InputsProvider, { initialRegistry: inputRegistry, children: /* @__PURE__ */ jsx78(Workspace, { backend, actor, children: () => /* @__PURE__ */ jsx78(WorkspaceLayout, { onShare, onPlay, menu }) }) })
16438
16688
  ] });