@codemem/server 0.28.1 → 0.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/static/app.js CHANGED
@@ -2106,8 +2106,8 @@
2106
2106
  var useLayoutEffect2 = globalThis?.document ? _$2 : () => {};
2107
2107
  //#endregion
2108
2108
  //#region ../../node_modules/.pnpm/@radix-ui+react-portal@1.1.9_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@radix-ui/react-portal/dist/index.mjs
2109
- var PORTAL_NAME$5 = "Portal";
2110
- var Portal$4 = D((props, forwardedRef) => {
2109
+ var PORTAL_NAME$6 = "Portal";
2110
+ var Portal$5 = D((props, forwardedRef) => {
2111
2111
  const { container: containerProp, ...portalProps } = props;
2112
2112
  const [mounted, setMounted] = d$2(false);
2113
2113
  useLayoutEffect2(() => setMounted(true), []);
@@ -2117,7 +2117,7 @@
2117
2117
  ref: forwardedRef
2118
2118
  }), container) : null;
2119
2119
  });
2120
- Portal$4.displayName = PORTAL_NAME$5;
2120
+ Portal$5.displayName = PORTAL_NAME$6;
2121
2121
  //#endregion
2122
2122
  //#region ../../node_modules/.pnpm/@radix-ui+react-presence@1.1.5_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@radix-ui/react-presence/dist/index.mjs
2123
2123
  function useStateMachine(initialState, machine) {
@@ -2686,7 +2686,7 @@
2686
2686
  const timer = window.setTimeout(() => setIsAnnounced(true), 1e3);
2687
2687
  return () => window.clearTimeout(timer);
2688
2688
  }, []);
2689
- return isAnnounced ? null : /* @__PURE__ */ u(Portal$4, {
2689
+ return isAnnounced ? null : /* @__PURE__ */ u(Portal$5, {
2690
2690
  asChild: true,
2691
2691
  children: /* @__PURE__ */ u(VisuallyHidden, {
2692
2692
  ...announceProps,
@@ -2733,10 +2733,10 @@
2733
2733
  });
2734
2734
  });
2735
2735
  ToastAction.displayName = ACTION_NAME;
2736
- var CLOSE_NAME$1 = "ToastClose";
2736
+ var CLOSE_NAME$2 = "ToastClose";
2737
2737
  var ToastClose = D((props, forwardedRef) => {
2738
2738
  const { __scopeToast, ...closeProps } = props;
2739
- const interactiveContext = useToastInteractiveContext(CLOSE_NAME$1, __scopeToast);
2739
+ const interactiveContext = useToastInteractiveContext(CLOSE_NAME$2, __scopeToast);
2740
2740
  return /* @__PURE__ */ u(ToastAnnounceExclude, {
2741
2741
  asChild: true,
2742
2742
  children: /* @__PURE__ */ u(Primitive.button, {
@@ -2747,7 +2747,7 @@
2747
2747
  })
2748
2748
  });
2749
2749
  });
2750
- ToastClose.displayName = CLOSE_NAME$1;
2750
+ ToastClose.displayName = CLOSE_NAME$2;
2751
2751
  var ToastAnnounceExclude = D((props, forwardedRef) => {
2752
2752
  const { __scopeToast, altText, ...announceExcludeProps } = props;
2753
2753
  return /* @__PURE__ */ u(Primitive.div, {
@@ -2825,7 +2825,7 @@
2825
2825
  }
2826
2826
  var Provider$1 = ToastProvider;
2827
2827
  var Viewport$1 = ToastViewport;
2828
- var Root2$5 = Toast;
2828
+ var Root2$6 = Toast;
2829
2829
  var Description = ToastDescription;
2830
2830
  var Close = ToastClose;
2831
2831
  //#endregion
@@ -2862,7 +2862,7 @@
2862
2862
  return /* @__PURE__ */ u(Provider$1, {
2863
2863
  duration: 8e3,
2864
2864
  swipeDirection: "right",
2865
- children: [items.map((item) => /* @__PURE__ */ u(Root2$5, {
2865
+ children: [items.map((item) => /* @__PURE__ */ u(Root2$6, {
2866
2866
  className: `toast-root toast-${item.variant}`,
2867
2867
  duration: item.durationMs,
2868
2868
  onOpenChange: (open) => {
@@ -3062,6 +3062,19 @@
3062
3062
  if (!resp.ok) throw new Error(payloadError(payload) || text || "request failed");
3063
3063
  return payload;
3064
3064
  }
3065
+ async function moveMemoryProject(memoryId, project) {
3066
+ const resp = await fetch("/api/memories/project", {
3067
+ method: "POST",
3068
+ headers: { "Content-Type": "application/json" },
3069
+ body: JSON.stringify({
3070
+ memory_id: memoryId,
3071
+ project
3072
+ })
3073
+ });
3074
+ const { text, payload } = await readJsonPayload(resp);
3075
+ if (!resp.ok) throw new Error(payloadError(payload) || text || "request failed");
3076
+ return payload;
3077
+ }
3065
3078
  async function forgetMemory(memoryId) {
3066
3079
  const resp = await fetch("/api/memories/forget", {
3067
3080
  method: "POST",
@@ -3213,6 +3226,26 @@
3213
3226
  if (!resp.ok) throw new Error(detail || payloadError(payload) || text || "request failed");
3214
3227
  return payload;
3215
3228
  }
3229
+ async function loadCoordinatorGroupPreferences(groupId) {
3230
+ const resp = await fetch(`/api/coordinator/admin/groups/${encodeURIComponent(groupId)}/preferences`);
3231
+ const { text, payload } = await readJsonPayload(resp);
3232
+ if (!resp.ok) throw new Error(payloadError(payload) || text || "request failed");
3233
+ const prefs = payload?.preferences;
3234
+ if (!prefs) throw new Error("response missing preferences");
3235
+ return prefs;
3236
+ }
3237
+ async function saveCoordinatorGroupPreferences(groupId, input) {
3238
+ const resp = await fetch(`/api/coordinator/admin/groups/${encodeURIComponent(groupId)}/preferences`, {
3239
+ method: "PUT",
3240
+ headers: { "Content-Type": "application/json" },
3241
+ body: JSON.stringify(input)
3242
+ });
3243
+ const { text, payload } = await readJsonPayload(resp);
3244
+ if (!resp.ok) throw new Error(payloadError(payload) || text || "request failed");
3245
+ const prefs = payload?.preferences;
3246
+ if (!prefs) throw new Error("response missing preferences");
3247
+ return prefs;
3248
+ }
3216
3249
  async function createActor(displayName) {
3217
3250
  const resp = await fetch("/api/sync/actors", {
3218
3251
  method: "POST",
@@ -3379,6 +3412,7 @@
3379
3412
  lastSyncCoordinator: null,
3380
3413
  lastCoordinatorAdminStatus: null,
3381
3414
  coordinatorAdminTargetGroup: "",
3415
+ knownProjects: [],
3382
3416
  lastCoordinatorAdminGroups: [],
3383
3417
  lastCoordinatorAdminJoinRequests: [],
3384
3418
  lastCoordinatorAdminDevices: [],
@@ -3412,9 +3446,18 @@
3412
3446
  function resolveAccessibleTab(tab, status) {
3413
3447
  return getVisibleTabs(status).includes(tab) ? tab : "sync";
3414
3448
  }
3449
+ /**
3450
+ * Parse `window.location.hash` into its top-level tab segment. Hashes with
3451
+ * sub-view segments (e.g. `#sync/diagnostics`) return their leading tab
3452
+ * (`sync`); sub-view state is owned per-tab.
3453
+ */
3454
+ function parseTabFromHash(hash = window.location.hash) {
3455
+ const first = hash.replace(/^#/, "").split("/")[0];
3456
+ return ALL_TAB_IDS.includes(first) ? first : null;
3457
+ }
3415
3458
  function getActiveTab() {
3416
- const hash = window.location.hash.replace("#", "");
3417
- if (ALL_TAB_IDS.includes(hash)) return resolveAccessibleTab(hash, state.lastCoordinatorAdminStatus);
3459
+ const fromHash = parseTabFromHash();
3460
+ if (fromHash) return resolveAccessibleTab(fromHash, state.lastCoordinatorAdminStatus);
3418
3461
  const saved = localStorage.getItem(TAB_KEY);
3419
3462
  if (saved && ALL_TAB_IDS.includes(saved)) return resolveAccessibleTab(saved, state.lastCoordinatorAdminStatus);
3420
3463
  return "feed";
@@ -3422,8 +3465,8 @@
3422
3465
  function setActiveTab(tab) {
3423
3466
  const nextTab = resolveAccessibleTab(tab, state.lastCoordinatorAdminStatus);
3424
3467
  state.activeTab = nextTab;
3425
- window.location.hash = nextTab;
3426
3468
  localStorage.setItem(TAB_KEY, nextTab);
3469
+ if (parseTabFromHash() !== nextTab) window.location.hash = nextTab;
3427
3470
  }
3428
3471
  function getFeedTypeFilter() {
3429
3472
  const saved = localStorage.getItem(FEED_FILTER_KEY) || "all";
@@ -3776,10 +3819,10 @@
3776
3819
  });
3777
3820
  });
3778
3821
  TabsList.displayName = TAB_LIST_NAME;
3779
- var TRIGGER_NAME$5 = "TabsTrigger";
3822
+ var TRIGGER_NAME$6 = "TabsTrigger";
3780
3823
  var TabsTrigger = D((props, forwardedRef) => {
3781
3824
  const { __scopeTabs, value, disabled = false, ...triggerProps } = props;
3782
- const context = useTabsContext(TRIGGER_NAME$5, __scopeTabs);
3825
+ const context = useTabsContext(TRIGGER_NAME$6, __scopeTabs);
3783
3826
  const rovingFocusGroupScope = useRovingFocusGroupScope$2(__scopeTabs);
3784
3827
  const triggerId = makeTriggerId(context.baseId, value);
3785
3828
  const contentId = makeContentId(context.baseId, value);
@@ -3814,11 +3857,11 @@
3814
3857
  })
3815
3858
  });
3816
3859
  });
3817
- TabsTrigger.displayName = TRIGGER_NAME$5;
3818
- var CONTENT_NAME$7 = "TabsContent";
3860
+ TabsTrigger.displayName = TRIGGER_NAME$6;
3861
+ var CONTENT_NAME$8 = "TabsContent";
3819
3862
  var TabsContent = D((props, forwardedRef) => {
3820
3863
  const { __scopeTabs, value, forceMount, children, ...contentProps } = props;
3821
- const context = useTabsContext(CONTENT_NAME$7, __scopeTabs);
3864
+ const context = useTabsContext(CONTENT_NAME$8, __scopeTabs);
3822
3865
  const triggerId = makeTriggerId(context.baseId, value);
3823
3866
  const contentId = makeContentId(context.baseId, value);
3824
3867
  const isSelected = value === context.value;
@@ -3847,27 +3890,27 @@
3847
3890
  })
3848
3891
  });
3849
3892
  });
3850
- TabsContent.displayName = CONTENT_NAME$7;
3893
+ TabsContent.displayName = CONTENT_NAME$8;
3851
3894
  function makeTriggerId(baseId, value) {
3852
3895
  return `${baseId}-trigger-${value}`;
3853
3896
  }
3854
3897
  function makeContentId(baseId, value) {
3855
3898
  return `${baseId}-content-${value}`;
3856
3899
  }
3857
- var Root2$4 = Tabs;
3900
+ var Root2$5 = Tabs;
3858
3901
  var List = TabsList;
3859
- var Trigger$4 = TabsTrigger;
3902
+ var Trigger$5 = TabsTrigger;
3860
3903
  var Content$3 = TabsContent;
3861
3904
  //#endregion
3862
3905
  //#region src/components/primitives/radix-tabs.tsx
3863
3906
  function RadixTabs({ ariaLabel, children, listClassName, onValueChange, tabs, triggerClassName, value }) {
3864
- return /* @__PURE__ */ u(Root2$4, {
3907
+ return /* @__PURE__ */ u(Root2$5, {
3865
3908
  onValueChange,
3866
3909
  value,
3867
3910
  children: [/* @__PURE__ */ u(List, {
3868
3911
  "aria-label": ariaLabel,
3869
3912
  className: listClassName,
3870
- children: tabs.map((tab) => /* @__PURE__ */ u(Trigger$4, {
3913
+ children: tabs.map((tab) => /* @__PURE__ */ u(Trigger$5, {
3871
3914
  className: triggerClassName,
3872
3915
  disabled: tab.disabled,
3873
3916
  value: tab.value,
@@ -3908,7 +3951,10 @@
3908
3951
  deviceActionPendingId: "",
3909
3952
  deviceActionPendingKind: "",
3910
3953
  groupRenameDrafts: /* @__PURE__ */ new Map(),
3911
- deviceRenameDrafts: /* @__PURE__ */ new Map()
3954
+ deviceRenameDrafts: /* @__PURE__ */ new Map(),
3955
+ groupPreferencesOpen: /* @__PURE__ */ new Set(),
3956
+ groupPreferencesDrafts: /* @__PURE__ */ new Map(),
3957
+ availableProjects: []
3912
3958
  };
3913
3959
  //#endregion
3914
3960
  //#region src/tabs/coordinator-admin/components/devices-panel.ts
@@ -3918,7 +3964,7 @@
3918
3964
  return _$3(RadixTabsContent, {
3919
3965
  className: "coordinator-admin-panel",
3920
3966
  value: "devices"
3921
- }, _$3("h3", null, "Enrolled devices"), _$3("p", { class: "peer-submeta" }, summary.readiness === "ready" ? "Rename, disable, re-enable, or remove enrolled devices from the operator surface without confusing this with direct sync state." : "Finish setup first. Device administration stays disabled until coordinator admin is ready."), !items.length ? _$3("div", { class: "peer-meta" }, summary.readiness === "ready" ? "No enrolled devices found for the active coordinator group." : "Device administration will appear here once setup is complete.") : _$3("div", { class: "coordinator-admin-request-list" }, items.map((item) => {
3967
+ }, _$3("h3", null, "Enrolled devices"), _$3("p", { class: "peer-submeta" }, summary.readiness === "ready" ? "Rename, disable, re-enable, or remove enrolled devices from the operator surface without confusing this with direct sync state." : "Finish setup first. Device administration stays disabled until coordinator admin is ready."), !items.length ? _$3("div", { class: "peer-meta" }, summary.readiness === "ready" ? "No enrolled devices found for the active coordinator group." : "Device administration will appear here once setup is complete.") : _$3("div", { class: "peer-list" }, items.map((item) => {
3922
3968
  const deviceId = String(item.device_id || "").trim();
3923
3969
  const groupId = String(item.group_id || state.lastCoordinatorAdminStatus?.active_group || "").trim();
3924
3970
  const displayName = String(item.display_name || deviceId || "Unnamed device");
@@ -3926,7 +3972,7 @@
3926
3972
  const draft = coordinatorAdminState.deviceRenameDrafts.get(deviceId) ?? String(item.display_name || "");
3927
3973
  const enabled = item.enabled !== false && item.enabled !== 0;
3928
3974
  return _$3("div", {
3929
- class: "peer-card",
3975
+ class: "peer-card peer-card--padded",
3930
3976
  key: deviceId || String(item.fingerprint || "unknown")
3931
3977
  }, _$3("div", { class: "peer-title" }, _$3("strong", null, draft || displayName)), _$3("div", { class: "peer-meta" }, `Device: ${deviceId || "unknown"}`), groupId ? _$3("div", { class: "peer-submeta" }, `Group: ${groupId}`) : null, _$3("div", { class: "peer-submeta" }, enabled ? "Enabled" : "Disabled"), _$3("div", { class: "coordinator-admin-form-grid" }, _$3("label", { class: "coordinator-admin-field" }, _$3("span", null, "Display name"), _$3(TextInput, {
3932
3978
  class: "peer-scope-input",
@@ -3960,337 +4006,121 @@
3960
4006
  })));
3961
4007
  }
3962
4008
  //#endregion
3963
- //#region ../../node_modules/.pnpm/@radix-ui+react-use-previous@1.1.1_react@19.2.4/node_modules/@radix-ui/react-use-previous/dist/index.mjs
3964
- function usePrevious(value) {
3965
- const ref = A$1({
3966
- value,
3967
- previous: value
3968
- });
3969
- return T$1(() => {
3970
- if (ref.current.value !== value) {
3971
- ref.current.previous = ref.current.value;
3972
- ref.current.value = value;
3973
- }
3974
- return ref.current.previous;
3975
- }, [value]);
3976
- }
3977
- //#endregion
3978
- //#region ../../node_modules/.pnpm/@radix-ui+react-use-size@1.1.1_react@19.2.4/node_modules/@radix-ui/react-use-size/dist/index.mjs
3979
- function useSize(element) {
3980
- const [size, setSize] = d$2(void 0);
3981
- useLayoutEffect2(() => {
3982
- if (element) {
3983
- setSize({
3984
- width: element.offsetWidth,
3985
- height: element.offsetHeight
3986
- });
3987
- const resizeObserver = new ResizeObserver((entries) => {
3988
- if (!Array.isArray(entries)) return;
3989
- if (!entries.length) return;
3990
- const entry = entries[0];
3991
- let width;
3992
- let height;
3993
- if ("borderBoxSize" in entry) {
3994
- const borderSizeEntry = entry["borderBoxSize"];
3995
- const borderSize = Array.isArray(borderSizeEntry) ? borderSizeEntry[0] : borderSizeEntry;
3996
- width = borderSize["inlineSize"];
3997
- height = borderSize["blockSize"];
3998
- } else {
3999
- width = element.offsetWidth;
4000
- height = element.offsetHeight;
4001
- }
4002
- setSize({
4003
- width,
4004
- height
4005
- });
4006
- });
4007
- resizeObserver.observe(element, { box: "border-box" });
4008
- return () => resizeObserver.unobserve(element);
4009
- } else setSize(void 0);
4010
- }, [element]);
4011
- return size;
4012
- }
4013
- //#endregion
4014
- //#region ../../node_modules/.pnpm/@radix-ui+react-switch@1.2.6_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@radix-ui/react-switch/dist/index.mjs
4015
- var SWITCH_NAME = "Switch";
4016
- var [createSwitchContext, createSwitchScope] = createContextScope(SWITCH_NAME);
4017
- var [SwitchProvider, useSwitchContext] = createSwitchContext(SWITCH_NAME);
4018
- var Switch = D((props, forwardedRef) => {
4019
- const { __scopeSwitch, name, checked: checkedProp, defaultChecked, required, disabled, value = "on", onCheckedChange, form, ...switchProps } = props;
4020
- const [button, setButton] = d$2(null);
4021
- const composedRefs = useComposedRefs(forwardedRef, (node) => setButton(node));
4022
- const hasConsumerStoppedPropagationRef = A$1(false);
4023
- const isFormControl = button ? form || !!button.closest("form") : true;
4024
- const [checked, setChecked] = useControllableState({
4025
- prop: checkedProp,
4026
- defaultProp: defaultChecked ?? false,
4027
- onChange: onCheckedChange,
4028
- caller: SWITCH_NAME
4009
+ //#region ../../node_modules/.pnpm/@radix-ui+react-collapsible@1.1.12_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@radix-ui/react-collapsible/dist/index.mjs
4010
+ var COLLAPSIBLE_NAME = "Collapsible";
4011
+ var [createCollapsibleContext, createCollapsibleScope] = createContextScope(COLLAPSIBLE_NAME);
4012
+ var [CollapsibleProvider, useCollapsibleContext] = createCollapsibleContext(COLLAPSIBLE_NAME);
4013
+ var Collapsible = D((props, forwardedRef) => {
4014
+ const { __scopeCollapsible, open: openProp, defaultOpen, disabled, onOpenChange, ...collapsibleProps } = props;
4015
+ const [open, setOpen] = useControllableState({
4016
+ prop: openProp,
4017
+ defaultProp: defaultOpen ?? false,
4018
+ onChange: onOpenChange,
4019
+ caller: COLLAPSIBLE_NAME
4029
4020
  });
4030
- return /* @__PURE__ */ u(SwitchProvider, {
4031
- scope: __scopeSwitch,
4032
- checked,
4021
+ return /* @__PURE__ */ u(CollapsibleProvider, {
4022
+ scope: __scopeCollapsible,
4033
4023
  disabled,
4034
- children: [/* @__PURE__ */ u(Primitive.button, {
4035
- type: "button",
4036
- role: "switch",
4037
- "aria-checked": checked,
4038
- "aria-required": required,
4039
- "data-state": getState$3(checked),
4024
+ contentId: useId(),
4025
+ open,
4026
+ onOpenToggle: q$2(() => setOpen((prevOpen) => !prevOpen), [setOpen]),
4027
+ children: /* @__PURE__ */ u(Primitive.div, {
4028
+ "data-state": getState$4(open),
4040
4029
  "data-disabled": disabled ? "" : void 0,
4041
- disabled,
4042
- value,
4043
- ...switchProps,
4044
- ref: composedRefs,
4045
- onClick: composeEventHandlers(props.onClick, (event) => {
4046
- setChecked((prevChecked) => !prevChecked);
4047
- if (isFormControl) {
4048
- hasConsumerStoppedPropagationRef.current = event.isPropagationStopped();
4049
- if (!hasConsumerStoppedPropagationRef.current) event.stopPropagation();
4050
- }
4051
- })
4052
- }), isFormControl && /* @__PURE__ */ u(SwitchBubbleInput, {
4053
- control: button,
4054
- bubbles: !hasConsumerStoppedPropagationRef.current,
4055
- name,
4056
- value,
4057
- checked,
4058
- required,
4059
- disabled,
4060
- form,
4061
- style: { transform: "translateX(-100%)" }
4062
- })]
4030
+ ...collapsibleProps,
4031
+ ref: forwardedRef
4032
+ })
4063
4033
  });
4064
4034
  });
4065
- Switch.displayName = SWITCH_NAME;
4066
- var THUMB_NAME = "SwitchThumb";
4067
- var SwitchThumb = D((props, forwardedRef) => {
4068
- const { __scopeSwitch, ...thumbProps } = props;
4069
- const context = useSwitchContext(THUMB_NAME, __scopeSwitch);
4070
- return /* @__PURE__ */ u(Primitive.span, {
4071
- "data-state": getState$3(context.checked),
4035
+ Collapsible.displayName = COLLAPSIBLE_NAME;
4036
+ var TRIGGER_NAME$5 = "CollapsibleTrigger";
4037
+ var CollapsibleTrigger = D((props, forwardedRef) => {
4038
+ const { __scopeCollapsible, ...triggerProps } = props;
4039
+ const context = useCollapsibleContext(TRIGGER_NAME$5, __scopeCollapsible);
4040
+ return /* @__PURE__ */ u(Primitive.button, {
4041
+ type: "button",
4042
+ "aria-controls": context.contentId,
4043
+ "aria-expanded": context.open || false,
4044
+ "data-state": getState$4(context.open),
4072
4045
  "data-disabled": context.disabled ? "" : void 0,
4073
- ...thumbProps,
4074
- ref: forwardedRef
4046
+ disabled: context.disabled,
4047
+ ...triggerProps,
4048
+ ref: forwardedRef,
4049
+ onClick: composeEventHandlers(props.onClick, context.onOpenToggle)
4075
4050
  });
4076
4051
  });
4077
- SwitchThumb.displayName = THUMB_NAME;
4078
- var BUBBLE_INPUT_NAME$2 = "SwitchBubbleInput";
4079
- var SwitchBubbleInput = D(({ __scopeSwitch, control, checked, bubbles = true, ...props }, forwardedRef) => {
4052
+ CollapsibleTrigger.displayName = TRIGGER_NAME$5;
4053
+ var CONTENT_NAME$7 = "CollapsibleContent";
4054
+ var CollapsibleContent = D((props, forwardedRef) => {
4055
+ const { forceMount, ...contentProps } = props;
4056
+ const context = useCollapsibleContext(CONTENT_NAME$7, props.__scopeCollapsible);
4057
+ return /* @__PURE__ */ u(Presence, {
4058
+ present: forceMount || context.open,
4059
+ children: ({ present }) => /* @__PURE__ */ u(CollapsibleContentImpl, {
4060
+ ...contentProps,
4061
+ ref: forwardedRef,
4062
+ present
4063
+ })
4064
+ });
4065
+ });
4066
+ CollapsibleContent.displayName = CONTENT_NAME$7;
4067
+ var CollapsibleContentImpl = D((props, forwardedRef) => {
4068
+ const { __scopeCollapsible, present, children, ...contentProps } = props;
4069
+ const context = useCollapsibleContext(CONTENT_NAME$7, __scopeCollapsible);
4070
+ const [isPresent, setIsPresent] = d$2(present);
4080
4071
  const ref = A$1(null);
4081
- const composedRefs = useComposedRefs(ref, forwardedRef);
4082
- const prevChecked = usePrevious(checked);
4083
- const controlSize = useSize(control);
4072
+ const composedRefs = useComposedRefs(forwardedRef, ref);
4073
+ const heightRef = A$1(0);
4074
+ const height = heightRef.current;
4075
+ const widthRef = A$1(0);
4076
+ const width = widthRef.current;
4077
+ const isOpen = context.open || isPresent;
4078
+ const isMountAnimationPreventedRef = A$1(isOpen);
4079
+ const originalStylesRef = A$1(void 0);
4084
4080
  y$2(() => {
4085
- const input = ref.current;
4086
- if (!input) return;
4087
- const inputProto = window.HTMLInputElement.prototype;
4088
- const setChecked = Object.getOwnPropertyDescriptor(inputProto, "checked").set;
4089
- if (prevChecked !== checked && setChecked) {
4090
- const event = new Event("click", { bubbles });
4091
- setChecked.call(input, checked);
4092
- input.dispatchEvent(event);
4081
+ const rAF = requestAnimationFrame(() => isMountAnimationPreventedRef.current = false);
4082
+ return () => cancelAnimationFrame(rAF);
4083
+ }, []);
4084
+ useLayoutEffect2(() => {
4085
+ const node = ref.current;
4086
+ if (node) {
4087
+ originalStylesRef.current = originalStylesRef.current || {
4088
+ transitionDuration: node.style.transitionDuration,
4089
+ animationName: node.style.animationName
4090
+ };
4091
+ node.style.transitionDuration = "0s";
4092
+ node.style.animationName = "none";
4093
+ const rect = node.getBoundingClientRect();
4094
+ heightRef.current = rect.height;
4095
+ widthRef.current = rect.width;
4096
+ if (!isMountAnimationPreventedRef.current) {
4097
+ node.style.transitionDuration = originalStylesRef.current.transitionDuration;
4098
+ node.style.animationName = originalStylesRef.current.animationName;
4099
+ }
4100
+ setIsPresent(present);
4093
4101
  }
4094
- }, [
4095
- prevChecked,
4096
- checked,
4097
- bubbles
4098
- ]);
4099
- return /* @__PURE__ */ u("input", {
4100
- type: "checkbox",
4101
- "aria-hidden": true,
4102
- defaultChecked: checked,
4103
- ...props,
4104
- tabIndex: -1,
4102
+ }, [context.open, present]);
4103
+ return /* @__PURE__ */ u(Primitive.div, {
4104
+ "data-state": getState$4(context.open),
4105
+ "data-disabled": context.disabled ? "" : void 0,
4106
+ id: context.contentId,
4107
+ hidden: !isOpen,
4108
+ ...contentProps,
4105
4109
  ref: composedRefs,
4106
4110
  style: {
4107
- ...props.style,
4108
- ...controlSize,
4109
- position: "absolute",
4110
- pointerEvents: "none",
4111
- opacity: 0,
4112
- margin: 0
4113
- }
4111
+ [`--radix-collapsible-content-height`]: height ? `${height}px` : void 0,
4112
+ [`--radix-collapsible-content-width`]: width ? `${width}px` : void 0,
4113
+ ...props.style
4114
+ },
4115
+ children: isOpen && children
4114
4116
  });
4115
4117
  });
4116
- SwitchBubbleInput.displayName = BUBBLE_INPUT_NAME$2;
4117
- function getState$3(checked) {
4118
- return checked ? "checked" : "unchecked";
4119
- }
4120
- var Root$3 = Switch;
4121
- var Thumb = SwitchThumb;
4122
- //#endregion
4123
- //#region src/components/primitives/radix-switch.tsx
4124
- function RadixSwitch({ "aria-labelledby": ariaLabelledBy, checked, className, disabled = false, id, name, onCheckedChange, thumbClassName }) {
4125
- return /* @__PURE__ */ u(Root$3, {
4126
- "aria-labelledby": ariaLabelledBy,
4127
- checked,
4128
- className,
4129
- disabled,
4130
- id,
4131
- name,
4132
- onCheckedChange,
4133
- children: /* @__PURE__ */ u(Thumb, { className: thumbClassName })
4134
- });
4135
- }
4136
- //#endregion
4137
- //#region src/tabs/coordinator-admin/data/target-group.ts
4138
- function adminTargetStorageKey(coordinatorUrl) {
4139
- return `${ADMIN_TARGET_GROUP_KEY}:${String(coordinatorUrl || "").trim()}`;
4140
- }
4141
- function readStoredAdminTargetGroup(coordinatorUrl) {
4142
- try {
4143
- return localStorage.getItem(adminTargetStorageKey(coordinatorUrl)) || "";
4144
- } catch {
4145
- return "";
4146
- }
4147
- }
4148
- function writeStoredAdminTargetGroup(coordinatorUrl, groupId) {
4149
- try {
4150
- localStorage.setItem(adminTargetStorageKey(coordinatorUrl), groupId);
4151
- } catch {}
4152
- }
4153
- function currentAdminTargetGroup() {
4154
- return String(state.coordinatorAdminTargetGroup || "").trim();
4155
- }
4156
- function setAdminTargetGroup(groupId) {
4157
- state.coordinatorAdminTargetGroup = groupId;
4158
- writeStoredAdminTargetGroup(state.lastCoordinatorAdminStatus?.coordinator_url || null, groupId);
4159
- }
4160
- function availableCoordinatorGroups() {
4161
- return (Array.isArray(state.lastCoordinatorAdminGroups) ? state.lastCoordinatorAdminGroups : []).map((group) => ({
4162
- archived_at: group.archived_at ?? null,
4163
- display_name: group.display_name ?? null,
4164
- group_id: String(group.group_id || "").trim()
4165
- })).filter((group) => group.group_id);
4166
- }
4167
- function reconcileGroupRenameDrafts() {
4168
- const next = /* @__PURE__ */ new Map();
4169
- for (const group of availableCoordinatorGroups()) next.set(group.group_id, group.display_name || group.group_id);
4170
- coordinatorAdminState.groupRenameDrafts.clear();
4171
- for (const [groupId, name] of next.entries()) coordinatorAdminState.groupRenameDrafts.set(groupId, name);
4172
- }
4173
- function currentAdminTargetGroupRecord() {
4174
- const target = currentAdminTargetGroup();
4175
- return availableCoordinatorGroups().find((group) => group.group_id === target) || null;
4176
- }
4177
- function resolveAdminTargetGroup() {
4178
- const status = state.lastCoordinatorAdminStatus;
4179
- const groups = availableCoordinatorGroups();
4180
- const configured = String(status?.active_group || "").trim();
4181
- const stored = readStoredAdminTargetGroup(status?.coordinator_url || null);
4182
- const current = currentAdminTargetGroup();
4183
- const availableIds = new Set(groups.map((group) => group.group_id));
4184
- const candidate = current || stored || configured || groups[0]?.group_id || "";
4185
- const resolved = candidate && (availableIds.size === 0 || availableIds.has(candidate)) ? candidate : configured || groups[0]?.group_id || "";
4186
- setAdminTargetGroup(resolved);
4187
- return resolved;
4188
- }
4189
- function reconcileDeviceRenameDrafts() {
4190
- const next = /* @__PURE__ */ new Map();
4191
- const items = Array.isArray(state.lastCoordinatorAdminDevices) ? state.lastCoordinatorAdminDevices : [];
4192
- for (const item of items) {
4193
- const deviceId = String(item.device_id || "").trim();
4194
- if (!deviceId) continue;
4195
- next.set(deviceId, String(item.display_name || ""));
4196
- }
4197
- coordinatorAdminState.deviceRenameDrafts.clear();
4198
- for (const [deviceId, name] of next.entries()) coordinatorAdminState.deviceRenameDrafts.set(deviceId, name);
4199
- }
4200
- //#endregion
4201
- //#region src/tabs/coordinator-admin/components/groups-panel.ts
4202
- function renderGroupsPanel(deps) {
4203
- const { summary, createGroup, runGroup, renderShell, reloadData } = deps;
4204
- const configuredGroup = String(state.lastCoordinatorAdminStatus?.active_group || "").trim();
4205
- const selectedGroup = currentAdminTargetGroup();
4206
- const groups = availableCoordinatorGroups();
4207
- const activeGroups = groups.filter((group) => !group.archived_at);
4208
- const archivedGroups = groups.filter((group) => group.archived_at);
4209
- const visibleGroups = coordinatorAdminState.showArchivedGroups ? groups : activeGroups;
4210
- const targetExists = selectedGroup ? groups.some((group) => group.group_id === selectedGroup) : false;
4211
- const countParts = [`${activeGroups.length} active`];
4212
- if (archivedGroups.length) countParts.push(`${archivedGroups.length} archived`);
4213
- return _$3(RadixTabsContent, {
4214
- className: "coordinator-admin-panel",
4215
- value: "groups"
4216
- }, _$3("h3", null, "Groups"), _$3("p", { class: "peer-submeta" }, selectedGroup ? `Managing ${selectedGroup}${configuredGroup && configuredGroup !== selectedGroup ? ` · this node uses ${configuredGroup} for discovery` : ""}` : configuredGroup ? `This node uses ${configuredGroup} for discovery. Select a group below to manage it.` : "No group selected yet. Create one or select an existing group to manage."), groups.length ? _$3("p", { class: "peer-submeta" }, countParts.join(" · ")) : null, !targetExists && selectedGroup ? _$3("div", { class: "peer-meta coordinator-admin-inline-warning" }, `The selected admin target group (${selectedGroup}) is configured locally but does not exist in the coordinator yet. Create it below or switch to another group once one exists.`) : null, _$3("div", { class: "coordinator-admin-form-grid" }, _$3("label", { class: "coordinator-admin-field" }, _$3("span", null, "New group id"), _$3(TextInput, {
4217
- class: "peer-scope-input",
4218
- disabled: summary.readiness !== "ready" || coordinatorAdminState.groupActionPendingKind === "create",
4219
- onInput: (event) => {
4220
- coordinatorAdminState.createGroupId = String(event.currentTarget.value || "");
4221
- },
4222
- placeholder: "team-alpha",
4223
- type: "text",
4224
- value: coordinatorAdminState.createGroupId
4225
- })), _$3("label", { class: "coordinator-admin-field" }, _$3("span", null, "Display name"), _$3(TextInput, {
4226
- class: "peer-scope-input",
4227
- disabled: summary.readiness !== "ready" || coordinatorAdminState.groupActionPendingKind === "create",
4228
- onInput: (event) => {
4229
- coordinatorAdminState.createGroupDisplayName = String(event.currentTarget.value || "");
4230
- },
4231
- placeholder: "Team Alpha",
4232
- type: "text",
4233
- value: coordinatorAdminState.createGroupDisplayName
4234
- }))), _$3("div", { class: "section-actions coordinator-admin-groups-toolbar" }, _$3("div", { class: "coordinator-admin-primary-actions" }, _$3("button", {
4235
- class: "settings-button",
4236
- disabled: summary.readiness !== "ready" || coordinatorAdminState.groupActionPendingKind === "create",
4237
- onClick: () => createGroup(),
4238
- type: "button"
4239
- }, coordinatorAdminState.groupActionPendingKind === "create" ? "Creating…" : "Create group")), _$3("div", { class: "coordinator-admin-secondary-actions" }, _$3("label", { class: "coordinator-admin-inline-filter" }, _$3("span", {
4240
- class: "section-meta",
4241
- id: "coordinatorAdminShowArchivedLabel"
4242
- }, "Show archived"), _$3(RadixSwitch, {
4243
- "aria-labelledby": "coordinatorAdminShowArchivedLabel",
4244
- checked: coordinatorAdminState.showArchivedGroups,
4245
- className: "coordinator-admin-switch",
4246
- disabled: summary.readiness !== "ready",
4247
- onCheckedChange: (checked) => {
4248
- coordinatorAdminState.showArchivedGroups = checked;
4249
- renderShell();
4250
- },
4251
- thumbClassName: "coordinator-admin-switch-thumb"
4252
- })))), !visibleGroups.length ? _$3("div", { class: "peer-meta coordinator-admin-empty-state" }, summary.readiness === "ready" ? coordinatorAdminState.showArchivedGroups ? "No coordinator groups are available yet." : "No active groups yet. Create one to get started." : "Group browsing will appear here once setup is complete.") : _$3("div", { class: "coordinator-admin-request-list" }, visibleGroups.map((group) => {
4253
- const selected = group.group_id === selectedGroup;
4254
- const pending = coordinatorAdminState.groupActionPendingId === group.group_id;
4255
- const archived = Boolean(group.archived_at);
4256
- const draftName = coordinatorAdminState.groupRenameDrafts.get(group.group_id) ?? group.display_name ?? group.group_id;
4257
- return _$3("div", {
4258
- class: "peer-card",
4259
- key: group.group_id
4260
- }, _$3("div", { class: "peer-title" }, _$3("strong", null, draftName)), _$3("div", { class: "peer-meta" }, `Group ID: ${group.group_id}`), _$3("div", { class: "peer-submeta" }, archived ? "Archived" : "Active"), configuredGroup === group.group_id ? _$3("div", { class: "peer-submeta" }, "This node is configured to use this group for coordinator-backed discovery.") : null, _$3("label", { class: "coordinator-admin-field" }, _$3("span", null, "Display name"), _$3(TextInput, {
4261
- class: "peer-scope-input",
4262
- disabled: summary.readiness !== "ready" || pending,
4263
- onInput: (event) => {
4264
- coordinatorAdminState.groupRenameDrafts.set(group.group_id, String(event.currentTarget.value || ""));
4265
- },
4266
- type: "text",
4267
- value: draftName
4268
- })), _$3("div", { class: "peer-actions" }, _$3("button", {
4269
- class: "settings-button",
4270
- disabled: summary.readiness !== "ready" || selected,
4271
- onClick: () => {
4272
- setAdminTargetGroup(group.group_id);
4273
- reloadData();
4274
- },
4275
- type: "button"
4276
- }, selected ? "Managing" : "Manage"), _$3("button", {
4277
- class: "settings-button",
4278
- disabled: summary.readiness !== "ready" || pending,
4279
- onClick: () => runGroup(group.group_id, draftName, "rename"),
4280
- type: "button"
4281
- }, pending && coordinatorAdminState.groupActionPendingKind === "rename" ? "Renaming…" : "Rename"), _$3("button", {
4282
- class: archived ? "settings-button" : "settings-button danger",
4283
- disabled: summary.readiness !== "ready" || pending,
4284
- onClick: () => runGroup(group.group_id, group.display_name || group.group_id, archived ? "unarchive" : "archive"),
4285
- type: "button"
4286
- }, pending && coordinatorAdminState.groupActionPendingKind === (archived ? "unarchive" : "archive") ? archived ? "Restoring…" : "Archiving…" : archived ? "Unarchive" : "Archive")));
4287
- })));
4288
- }
4289
- //#endregion
4290
- //#region ../../node_modules/.pnpm/@radix-ui+number@1.1.1/node_modules/@radix-ui/number/dist/index.mjs
4291
- function clamp$1(value, [min, max]) {
4292
- return Math.min(max, Math.max(min, value));
4118
+ function getState$4(open) {
4119
+ return open ? "open" : "closed";
4293
4120
  }
4121
+ var Root$3 = Collapsible;
4122
+ var Trigger$4 = CollapsibleTrigger;
4123
+ var Content$2 = CollapsibleContent;
4294
4124
  //#endregion
4295
4125
  //#region ../../node_modules/.pnpm/@radix-ui+react-focus-guards@1.1.3_react@19.2.4/node_modules/@radix-ui/react-focus-guards/dist/index.mjs
4296
4126
  var count = 0;
@@ -4531,7 +4361,7 @@
4531
4361
  bottom: "top",
4532
4362
  top: "bottom"
4533
4363
  };
4534
- function clamp(start, value, end) {
4364
+ function clamp$1(start, value, end) {
4535
4365
  return max(start, min(value, end));
4536
4366
  }
4537
4367
  function evaluate(value, param) {
@@ -4841,7 +4671,7 @@
4841
4671
  const min$1 = minPadding;
4842
4672
  const max = clientSize - arrowDimensions[length] - maxPadding;
4843
4673
  const center = clientSize / 2 - arrowDimensions[length] / 2 + centerToReference;
4844
- const offset = clamp(min$1, center, max);
4674
+ const offset = clamp$1(min$1, center, max);
4845
4675
  const shouldAddOffset = !middlewareData.arrow && getAlignment(placement) != null && center !== offset && rects.reference[length] / 2 - (center < min$1 ? minPadding : maxPadding) - arrowDimensions[length] / 2 < 0;
4846
4676
  const alignmentOffset = shouldAddOffset ? center < min$1 ? center - min$1 : center - max : 0;
4847
4677
  return {
@@ -5067,14 +4897,14 @@
5067
4897
  const maxSide = mainAxis === "y" ? "bottom" : "right";
5068
4898
  const min = mainAxisCoord + overflow[minSide];
5069
4899
  const max = mainAxisCoord - overflow[maxSide];
5070
- mainAxisCoord = clamp(min, mainAxisCoord, max);
4900
+ mainAxisCoord = clamp$1(min, mainAxisCoord, max);
5071
4901
  }
5072
4902
  if (checkCrossAxis) {
5073
4903
  const minSide = crossAxis === "y" ? "top" : "left";
5074
4904
  const maxSide = crossAxis === "y" ? "bottom" : "right";
5075
4905
  const min = crossAxisCoord + overflow[minSide];
5076
4906
  const max = crossAxisCoord - overflow[maxSide];
5077
- crossAxisCoord = clamp(min, crossAxisCoord, max);
4907
+ crossAxisCoord = clamp$1(min, crossAxisCoord, max);
5078
4908
  }
5079
4909
  const limitedCoords = limiter.fn({
5080
4910
  ...state,
@@ -6176,6 +6006,42 @@
6176
6006
  Arrow$1.displayName = NAME;
6177
6007
  var Root$2 = Arrow$1;
6178
6008
  //#endregion
6009
+ //#region ../../node_modules/.pnpm/@radix-ui+react-use-size@1.1.1_react@19.2.4/node_modules/@radix-ui/react-use-size/dist/index.mjs
6010
+ function useSize(element) {
6011
+ const [size, setSize] = d$2(void 0);
6012
+ useLayoutEffect2(() => {
6013
+ if (element) {
6014
+ setSize({
6015
+ width: element.offsetWidth,
6016
+ height: element.offsetHeight
6017
+ });
6018
+ const resizeObserver = new ResizeObserver((entries) => {
6019
+ if (!Array.isArray(entries)) return;
6020
+ if (!entries.length) return;
6021
+ const entry = entries[0];
6022
+ let width;
6023
+ let height;
6024
+ if ("borderBoxSize" in entry) {
6025
+ const borderSizeEntry = entry["borderBoxSize"];
6026
+ const borderSize = Array.isArray(borderSizeEntry) ? borderSizeEntry[0] : borderSizeEntry;
6027
+ width = borderSize["inlineSize"];
6028
+ height = borderSize["blockSize"];
6029
+ } else {
6030
+ width = element.offsetWidth;
6031
+ height = element.offsetHeight;
6032
+ }
6033
+ setSize({
6034
+ width,
6035
+ height
6036
+ });
6037
+ });
6038
+ resizeObserver.observe(element, { box: "border-box" });
6039
+ return () => resizeObserver.unobserve(element);
6040
+ } else setSize(void 0);
6041
+ }, [element]);
6042
+ return size;
6043
+ }
6044
+ //#endregion
6179
6045
  //#region ../../node_modules/.pnpm/@radix-ui+react-popper@1.2.8_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@radix-ui/react-popper/dist/index.mjs
6180
6046
  var POPPER_NAME = "Popper";
6181
6047
  var [createPopperContext, createPopperScope] = createContextScope(POPPER_NAME);
@@ -6191,10 +6057,10 @@
6191
6057
  });
6192
6058
  };
6193
6059
  Popper.displayName = POPPER_NAME;
6194
- var ANCHOR_NAME$1 = "PopperAnchor";
6060
+ var ANCHOR_NAME$2 = "PopperAnchor";
6195
6061
  var PopperAnchor = D((props, forwardedRef) => {
6196
6062
  const { __scopePopper, virtualRef, ...anchorProps } = props;
6197
- const context = usePopperContext(ANCHOR_NAME$1, __scopePopper);
6063
+ const context = usePopperContext(ANCHOR_NAME$2, __scopePopper);
6198
6064
  const ref = A$1(null);
6199
6065
  const composedRefs = useComposedRefs(forwardedRef, ref);
6200
6066
  const anchorRef = A$1(null);
@@ -6208,7 +6074,7 @@
6208
6074
  ref: composedRefs
6209
6075
  });
6210
6076
  });
6211
- PopperAnchor.displayName = ANCHOR_NAME$1;
6077
+ PopperAnchor.displayName = ANCHOR_NAME$2;
6212
6078
  var CONTENT_NAME$6 = "PopperContent";
6213
6079
  var [PopperContentProvider, useContentContext] = createPopperContext(CONTENT_NAME$6);
6214
6080
  var PopperContent = D((props, forwardedRef) => {
@@ -6327,7 +6193,7 @@
6327
6193
  });
6328
6194
  });
6329
6195
  PopperContent.displayName = CONTENT_NAME$6;
6330
- var ARROW_NAME$4 = "PopperArrow";
6196
+ var ARROW_NAME$5 = "PopperArrow";
6331
6197
  var OPPOSITE_SIDE = {
6332
6198
  top: "bottom",
6333
6199
  right: "left",
@@ -6336,7 +6202,7 @@
6336
6202
  };
6337
6203
  var PopperArrow = D(function PopperArrow2(props, forwardedRef) {
6338
6204
  const { __scopePopper, ...arrowProps } = props;
6339
- const contentContext = useContentContext(ARROW_NAME$4, __scopePopper);
6205
+ const contentContext = useContentContext(ARROW_NAME$5, __scopePopper);
6340
6206
  const baseSide = OPPOSITE_SIDE[contentContext.placedSide];
6341
6207
  return /* @__PURE__ */ u("span", {
6342
6208
  ref: contentContext.onArrowChange,
@@ -6369,7 +6235,7 @@
6369
6235
  })
6370
6236
  });
6371
6237
  });
6372
- PopperArrow.displayName = ARROW_NAME$4;
6238
+ PopperArrow.displayName = ARROW_NAME$5;
6373
6239
  function isNotNull(value) {
6374
6240
  return value !== null;
6375
6241
  }
@@ -6414,9 +6280,9 @@
6414
6280
  const [side, align = "center"] = placement.split("-");
6415
6281
  return [side, align];
6416
6282
  }
6417
- var Root2$3 = Popper;
6283
+ var Root2$4 = Popper;
6418
6284
  var Anchor = PopperAnchor;
6419
- var Content$2 = PopperContent;
6285
+ var Content$1 = PopperContent;
6420
6286
  var Arrow = PopperArrow;
6421
6287
  //#endregion
6422
6288
  //#region ../../node_modules/.pnpm/aria-hidden@1.2.6/node_modules/aria-hidden/dist/es2015/index.js
@@ -7225,17 +7091,919 @@
7225
7091
  return shadowParent;
7226
7092
  }
7227
7093
  //#endregion
7228
- //#region ../../node_modules/.pnpm/react-remove-scroll@2.7.2_react@19.2.4/node_modules/react-remove-scroll/dist/es2015/sidecar.js
7229
- var sidecar_default = exportSidecar(effectCar, RemoveScrollSideCar);
7230
- //#endregion
7231
- //#region ../../node_modules/.pnpm/react-remove-scroll@2.7.2_react@19.2.4/node_modules/react-remove-scroll/dist/es2015/Combination.js
7232
- var ReactRemoveScroll = D(function(props, ref) {
7233
- return _$3(RemoveScroll, __assign({}, props, {
7234
- ref,
7235
- sideCar: sidecar_default
7236
- }));
7237
- });
7238
- ReactRemoveScroll.classNames = RemoveScroll.classNames;
7094
+ //#region ../../node_modules/.pnpm/react-remove-scroll@2.7.2_react@19.2.4/node_modules/react-remove-scroll/dist/es2015/sidecar.js
7095
+ var sidecar_default = exportSidecar(effectCar, RemoveScrollSideCar);
7096
+ //#endregion
7097
+ //#region ../../node_modules/.pnpm/react-remove-scroll@2.7.2_react@19.2.4/node_modules/react-remove-scroll/dist/es2015/Combination.js
7098
+ var ReactRemoveScroll = D(function(props, ref) {
7099
+ return _$3(RemoveScroll, __assign({}, props, {
7100
+ ref,
7101
+ sideCar: sidecar_default
7102
+ }));
7103
+ });
7104
+ ReactRemoveScroll.classNames = RemoveScroll.classNames;
7105
+ //#endregion
7106
+ //#region ../../node_modules/.pnpm/@radix-ui+react-popover@1.1.15_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@radix-ui/react-popover/dist/index.mjs
7107
+ var POPOVER_NAME = "Popover";
7108
+ var [createPopoverContext, createPopoverScope] = createContextScope(POPOVER_NAME, [createPopperScope]);
7109
+ var usePopperScope$3 = createPopperScope();
7110
+ var [PopoverProvider, usePopoverContext] = createPopoverContext(POPOVER_NAME);
7111
+ var Popover = (props) => {
7112
+ const { __scopePopover, children, open: openProp, defaultOpen, onOpenChange, modal = false } = props;
7113
+ const popperScope = usePopperScope$3(__scopePopover);
7114
+ const triggerRef = A$1(null);
7115
+ const [hasCustomAnchor, setHasCustomAnchor] = d$2(false);
7116
+ const [open, setOpen] = useControllableState({
7117
+ prop: openProp,
7118
+ defaultProp: defaultOpen ?? false,
7119
+ onChange: onOpenChange,
7120
+ caller: POPOVER_NAME
7121
+ });
7122
+ return /* @__PURE__ */ u(Root2$4, {
7123
+ ...popperScope,
7124
+ children: /* @__PURE__ */ u(PopoverProvider, {
7125
+ scope: __scopePopover,
7126
+ contentId: useId(),
7127
+ triggerRef,
7128
+ open,
7129
+ onOpenChange: setOpen,
7130
+ onOpenToggle: q$2(() => setOpen((prevOpen) => !prevOpen), [setOpen]),
7131
+ hasCustomAnchor,
7132
+ onCustomAnchorAdd: q$2(() => setHasCustomAnchor(true), []),
7133
+ onCustomAnchorRemove: q$2(() => setHasCustomAnchor(false), []),
7134
+ modal,
7135
+ children
7136
+ })
7137
+ });
7138
+ };
7139
+ Popover.displayName = POPOVER_NAME;
7140
+ var ANCHOR_NAME$1 = "PopoverAnchor";
7141
+ var PopoverAnchor = D((props, forwardedRef) => {
7142
+ const { __scopePopover, ...anchorProps } = props;
7143
+ const context = usePopoverContext(ANCHOR_NAME$1, __scopePopover);
7144
+ const popperScope = usePopperScope$3(__scopePopover);
7145
+ const { onCustomAnchorAdd, onCustomAnchorRemove } = context;
7146
+ y$2(() => {
7147
+ onCustomAnchorAdd();
7148
+ return () => onCustomAnchorRemove();
7149
+ }, [onCustomAnchorAdd, onCustomAnchorRemove]);
7150
+ return /* @__PURE__ */ u(Anchor, {
7151
+ ...popperScope,
7152
+ ...anchorProps,
7153
+ ref: forwardedRef
7154
+ });
7155
+ });
7156
+ PopoverAnchor.displayName = ANCHOR_NAME$1;
7157
+ var TRIGGER_NAME$4 = "PopoverTrigger";
7158
+ var PopoverTrigger = D((props, forwardedRef) => {
7159
+ const { __scopePopover, ...triggerProps } = props;
7160
+ const context = usePopoverContext(TRIGGER_NAME$4, __scopePopover);
7161
+ const popperScope = usePopperScope$3(__scopePopover);
7162
+ const composedTriggerRef = useComposedRefs(forwardedRef, context.triggerRef);
7163
+ const trigger = /* @__PURE__ */ u(Primitive.button, {
7164
+ type: "button",
7165
+ "aria-haspopup": "dialog",
7166
+ "aria-expanded": context.open,
7167
+ "aria-controls": context.contentId,
7168
+ "data-state": getState$3(context.open),
7169
+ ...triggerProps,
7170
+ ref: composedTriggerRef,
7171
+ onClick: composeEventHandlers(props.onClick, context.onOpenToggle)
7172
+ });
7173
+ return context.hasCustomAnchor ? trigger : /* @__PURE__ */ u(Anchor, {
7174
+ asChild: true,
7175
+ ...popperScope,
7176
+ children: trigger
7177
+ });
7178
+ });
7179
+ PopoverTrigger.displayName = TRIGGER_NAME$4;
7180
+ var PORTAL_NAME$5 = "PopoverPortal";
7181
+ var [PortalProvider$3, usePortalContext$3] = createPopoverContext(PORTAL_NAME$5, { forceMount: void 0 });
7182
+ var PopoverPortal = (props) => {
7183
+ const { __scopePopover, forceMount, children, container } = props;
7184
+ const context = usePopoverContext(PORTAL_NAME$5, __scopePopover);
7185
+ return /* @__PURE__ */ u(PortalProvider$3, {
7186
+ scope: __scopePopover,
7187
+ forceMount,
7188
+ children: /* @__PURE__ */ u(Presence, {
7189
+ present: forceMount || context.open,
7190
+ children: /* @__PURE__ */ u(Portal$5, {
7191
+ asChild: true,
7192
+ container,
7193
+ children
7194
+ })
7195
+ })
7196
+ });
7197
+ };
7198
+ PopoverPortal.displayName = PORTAL_NAME$5;
7199
+ var CONTENT_NAME$5 = "PopoverContent";
7200
+ var PopoverContent = D((props, forwardedRef) => {
7201
+ const portalContext = usePortalContext$3(CONTENT_NAME$5, props.__scopePopover);
7202
+ const { forceMount = portalContext.forceMount, ...contentProps } = props;
7203
+ const context = usePopoverContext(CONTENT_NAME$5, props.__scopePopover);
7204
+ return /* @__PURE__ */ u(Presence, {
7205
+ present: forceMount || context.open,
7206
+ children: context.modal ? /* @__PURE__ */ u(PopoverContentModal, {
7207
+ ...contentProps,
7208
+ ref: forwardedRef
7209
+ }) : /* @__PURE__ */ u(PopoverContentNonModal, {
7210
+ ...contentProps,
7211
+ ref: forwardedRef
7212
+ })
7213
+ });
7214
+ });
7215
+ PopoverContent.displayName = CONTENT_NAME$5;
7216
+ var Slot$3 = /* @__PURE__ */ createSlot("PopoverContent.RemoveScroll");
7217
+ var PopoverContentModal = D((props, forwardedRef) => {
7218
+ const context = usePopoverContext(CONTENT_NAME$5, props.__scopePopover);
7219
+ const contentRef = A$1(null);
7220
+ const composedRefs = useComposedRefs(forwardedRef, contentRef);
7221
+ const isRightClickOutsideRef = A$1(false);
7222
+ y$2(() => {
7223
+ const content = contentRef.current;
7224
+ if (content) return hideOthers(content);
7225
+ }, []);
7226
+ return /* @__PURE__ */ u(ReactRemoveScroll, {
7227
+ as: Slot$3,
7228
+ allowPinchZoom: true,
7229
+ children: /* @__PURE__ */ u(PopoverContentImpl, {
7230
+ ...props,
7231
+ ref: composedRefs,
7232
+ trapFocus: context.open,
7233
+ disableOutsidePointerEvents: true,
7234
+ onCloseAutoFocus: composeEventHandlers(props.onCloseAutoFocus, (event) => {
7235
+ event.preventDefault();
7236
+ if (!isRightClickOutsideRef.current) context.triggerRef.current?.focus();
7237
+ }),
7238
+ onPointerDownOutside: composeEventHandlers(props.onPointerDownOutside, (event) => {
7239
+ const originalEvent = event.detail.originalEvent;
7240
+ const ctrlLeftClick = originalEvent.button === 0 && originalEvent.ctrlKey === true;
7241
+ isRightClickOutsideRef.current = originalEvent.button === 2 || ctrlLeftClick;
7242
+ }, { checkForDefaultPrevented: false }),
7243
+ onFocusOutside: composeEventHandlers(props.onFocusOutside, (event) => event.preventDefault(), { checkForDefaultPrevented: false })
7244
+ })
7245
+ });
7246
+ });
7247
+ var PopoverContentNonModal = D((props, forwardedRef) => {
7248
+ const context = usePopoverContext(CONTENT_NAME$5, props.__scopePopover);
7249
+ const hasInteractedOutsideRef = A$1(false);
7250
+ const hasPointerDownOutsideRef = A$1(false);
7251
+ return /* @__PURE__ */ u(PopoverContentImpl, {
7252
+ ...props,
7253
+ ref: forwardedRef,
7254
+ trapFocus: false,
7255
+ disableOutsidePointerEvents: false,
7256
+ onCloseAutoFocus: (event) => {
7257
+ props.onCloseAutoFocus?.(event);
7258
+ if (!event.defaultPrevented) {
7259
+ if (!hasInteractedOutsideRef.current) context.triggerRef.current?.focus();
7260
+ event.preventDefault();
7261
+ }
7262
+ hasInteractedOutsideRef.current = false;
7263
+ hasPointerDownOutsideRef.current = false;
7264
+ },
7265
+ onInteractOutside: (event) => {
7266
+ props.onInteractOutside?.(event);
7267
+ if (!event.defaultPrevented) {
7268
+ hasInteractedOutsideRef.current = true;
7269
+ if (event.detail.originalEvent.type === "pointerdown") hasPointerDownOutsideRef.current = true;
7270
+ }
7271
+ const target = event.target;
7272
+ if (context.triggerRef.current?.contains(target)) event.preventDefault();
7273
+ if (event.detail.originalEvent.type === "focusin" && hasPointerDownOutsideRef.current) event.preventDefault();
7274
+ }
7275
+ });
7276
+ });
7277
+ var PopoverContentImpl = D((props, forwardedRef) => {
7278
+ const { __scopePopover, trapFocus, onOpenAutoFocus, onCloseAutoFocus, disableOutsidePointerEvents, onEscapeKeyDown, onPointerDownOutside, onFocusOutside, onInteractOutside, ...contentProps } = props;
7279
+ const context = usePopoverContext(CONTENT_NAME$5, __scopePopover);
7280
+ const popperScope = usePopperScope$3(__scopePopover);
7281
+ useFocusGuards();
7282
+ return /* @__PURE__ */ u(FocusScope, {
7283
+ asChild: true,
7284
+ loop: true,
7285
+ trapped: trapFocus,
7286
+ onMountAutoFocus: onOpenAutoFocus,
7287
+ onUnmountAutoFocus: onCloseAutoFocus,
7288
+ children: /* @__PURE__ */ u(DismissableLayer, {
7289
+ asChild: true,
7290
+ disableOutsidePointerEvents,
7291
+ onInteractOutside,
7292
+ onEscapeKeyDown,
7293
+ onPointerDownOutside,
7294
+ onFocusOutside,
7295
+ onDismiss: () => context.onOpenChange(false),
7296
+ children: /* @__PURE__ */ u(Content$1, {
7297
+ "data-state": getState$3(context.open),
7298
+ role: "dialog",
7299
+ id: context.contentId,
7300
+ ...popperScope,
7301
+ ...contentProps,
7302
+ ref: forwardedRef,
7303
+ style: {
7304
+ ...contentProps.style,
7305
+ "--radix-popover-content-transform-origin": "var(--radix-popper-transform-origin)",
7306
+ "--radix-popover-content-available-width": "var(--radix-popper-available-width)",
7307
+ "--radix-popover-content-available-height": "var(--radix-popper-available-height)",
7308
+ "--radix-popover-trigger-width": "var(--radix-popper-anchor-width)",
7309
+ "--radix-popover-trigger-height": "var(--radix-popper-anchor-height)"
7310
+ }
7311
+ })
7312
+ })
7313
+ });
7314
+ });
7315
+ var CLOSE_NAME$1 = "PopoverClose";
7316
+ var PopoverClose = D((props, forwardedRef) => {
7317
+ const { __scopePopover, ...closeProps } = props;
7318
+ const context = usePopoverContext(CLOSE_NAME$1, __scopePopover);
7319
+ return /* @__PURE__ */ u(Primitive.button, {
7320
+ type: "button",
7321
+ ...closeProps,
7322
+ ref: forwardedRef,
7323
+ onClick: composeEventHandlers(props.onClick, () => context.onOpenChange(false))
7324
+ });
7325
+ });
7326
+ PopoverClose.displayName = CLOSE_NAME$1;
7327
+ var ARROW_NAME$4 = "PopoverArrow";
7328
+ var PopoverArrow = D((props, forwardedRef) => {
7329
+ const { __scopePopover, ...arrowProps } = props;
7330
+ return /* @__PURE__ */ u(Arrow, {
7331
+ ...usePopperScope$3(__scopePopover),
7332
+ ...arrowProps,
7333
+ ref: forwardedRef
7334
+ });
7335
+ });
7336
+ PopoverArrow.displayName = ARROW_NAME$4;
7337
+ function getState$3(open) {
7338
+ return open ? "open" : "closed";
7339
+ }
7340
+ var Root2$3 = Popover;
7341
+ var Anchor2$1 = PopoverAnchor;
7342
+ var Trigger$3 = PopoverTrigger;
7343
+ var Portal$4 = PopoverPortal;
7344
+ var Content2$4 = PopoverContent;
7345
+ //#endregion
7346
+ //#region src/components/primitives/project-scope-picker.tsx
7347
+ function normalize$1(value) {
7348
+ return value.trim();
7349
+ }
7350
+ function ProjectScopePicker({ values, onValuesChange, availableProjects, placeholder, emptyLabel, disabled, "aria-labelledby": ariaLabelledby }) {
7351
+ const [open, setOpen] = d$2(false);
7352
+ const [query, setQuery] = d$2("");
7353
+ const [activeIndex, setActiveIndex] = d$2(0);
7354
+ const inputRef = A$1(null);
7355
+ const allKnown = T$1(() => {
7356
+ const seen = /* @__PURE__ */ new Set();
7357
+ const out = [];
7358
+ for (const item of [...availableProjects, ...values]) {
7359
+ const trimmed = normalize$1(item);
7360
+ if (!trimmed || seen.has(trimmed)) continue;
7361
+ seen.add(trimmed);
7362
+ out.push(trimmed);
7363
+ }
7364
+ return out.sort((a, b) => a.localeCompare(b));
7365
+ }, [availableProjects, values]);
7366
+ const trimmedQuery = normalize$1(query);
7367
+ const loweredQuery = trimmedQuery.toLowerCase();
7368
+ const filtered = T$1(() => {
7369
+ if (!loweredQuery) return allKnown;
7370
+ return allKnown.filter((project) => project.toLowerCase().includes(loweredQuery));
7371
+ }, [allKnown, loweredQuery]);
7372
+ const exactMatchExists = trimmedQuery ? allKnown.some((project) => project.toLowerCase() === loweredQuery) : false;
7373
+ const showCreateRow = Boolean(trimmedQuery) && !exactMatchExists;
7374
+ const rowCount = filtered.length + (showCreateRow ? 1 : 0);
7375
+ y$2(() => {
7376
+ if (activeIndex >= rowCount) setActiveIndex(Math.max(0, rowCount - 1));
7377
+ }, [rowCount, activeIndex]);
7378
+ y$2(() => {
7379
+ if (!open) return;
7380
+ const raf = requestAnimationFrame(() => inputRef.current?.focus());
7381
+ return () => cancelAnimationFrame(raf);
7382
+ }, [open]);
7383
+ const toggleProject = (project) => {
7384
+ if (values.includes(project)) onValuesChange(values.filter((value) => value !== project));
7385
+ else onValuesChange(Array.from(new Set([...values, project])));
7386
+ };
7387
+ const createProject = (project) => {
7388
+ const trimmed = normalize$1(project);
7389
+ if (!trimmed) return;
7390
+ onValuesChange(Array.from(new Set([...values, trimmed])));
7391
+ setQuery("");
7392
+ setActiveIndex(0);
7393
+ };
7394
+ const activateRow = (index) => {
7395
+ if (index < filtered.length) {
7396
+ const project = filtered[index];
7397
+ if (project) toggleProject(project);
7398
+ return;
7399
+ }
7400
+ if (showCreateRow) createProject(trimmedQuery);
7401
+ };
7402
+ const handleSearchKeyDown = (event) => {
7403
+ if (event.key === "ArrowDown") {
7404
+ event.preventDefault();
7405
+ setActiveIndex((prev) => Math.min(rowCount - 1, prev + 1));
7406
+ return;
7407
+ }
7408
+ if (event.key === "ArrowUp") {
7409
+ event.preventDefault();
7410
+ setActiveIndex((prev) => Math.max(0, prev - 1));
7411
+ return;
7412
+ }
7413
+ if (event.key === "Enter") {
7414
+ event.preventDefault();
7415
+ activateRow(activeIndex);
7416
+ return;
7417
+ }
7418
+ };
7419
+ const removeValue = (value) => {
7420
+ onValuesChange(values.filter((existing) => existing !== value));
7421
+ };
7422
+ return /* @__PURE__ */ u("div", {
7423
+ class: "project-scope-picker",
7424
+ children: [/* @__PURE__ */ u("ul", {
7425
+ "aria-labelledby": ariaLabelledby,
7426
+ class: "project-scope-picker-selected",
7427
+ children: values.length === 0 ? /* @__PURE__ */ u("li", {
7428
+ class: "project-scope-picker-selected-empty",
7429
+ children: emptyLabel || "No projects selected."
7430
+ }) : values.map((value) => /* @__PURE__ */ u("li", {
7431
+ class: "project-scope-picker-selected-chip",
7432
+ children: [/* @__PURE__ */ u("span", { children: value }), !disabled ? /* @__PURE__ */ u("button", {
7433
+ "aria-label": `Remove ${value}`,
7434
+ class: "project-scope-picker-selected-remove",
7435
+ onClick: () => removeValue(value),
7436
+ type: "button",
7437
+ children: "×"
7438
+ }) : null]
7439
+ }, value))
7440
+ }), /* @__PURE__ */ u(Root2$3, {
7441
+ onOpenChange: (next) => {
7442
+ setOpen(next);
7443
+ if (!next) {
7444
+ setQuery("");
7445
+ setActiveIndex(0);
7446
+ }
7447
+ },
7448
+ open,
7449
+ children: [/* @__PURE__ */ u(Trigger$3, {
7450
+ asChild: true,
7451
+ children: /* @__PURE__ */ u("button", {
7452
+ class: "project-scope-picker-trigger settings-button",
7453
+ disabled,
7454
+ type: "button",
7455
+ children: [/* @__PURE__ */ u("span", {
7456
+ "aria-hidden": "true",
7457
+ children: "+"
7458
+ }), /* @__PURE__ */ u("span", { children: placeholder || "Add project" })]
7459
+ })
7460
+ }), /* @__PURE__ */ u(Portal$4, { children: /* @__PURE__ */ u(Content2$4, {
7461
+ align: "start",
7462
+ class: "project-scope-picker-popover",
7463
+ sideOffset: 6,
7464
+ children: [/* @__PURE__ */ u("input", {
7465
+ "aria-label": "Search projects",
7466
+ class: "project-scope-picker-search",
7467
+ onInput: (event) => {
7468
+ setQuery(event.currentTarget.value);
7469
+ setActiveIndex(0);
7470
+ },
7471
+ onKeyDown: handleSearchKeyDown,
7472
+ placeholder: "Search or create…",
7473
+ ref: inputRef,
7474
+ type: "text",
7475
+ value: query
7476
+ }), /* @__PURE__ */ u("div", {
7477
+ class: "project-scope-picker-results",
7478
+ role: "listbox",
7479
+ children: [
7480
+ filtered.length === 0 && !showCreateRow ? /* @__PURE__ */ u("div", {
7481
+ class: "project-scope-picker-empty-row",
7482
+ children: "No projects yet. Type a name to create one."
7483
+ }) : null,
7484
+ filtered.map((project, index) => {
7485
+ const selected = values.includes(project);
7486
+ return /* @__PURE__ */ u("button", {
7487
+ "aria-selected": selected,
7488
+ class: index === activeIndex ? "project-scope-picker-row project-scope-picker-row--active" : "project-scope-picker-row",
7489
+ onClick: () => {
7490
+ setActiveIndex(index);
7491
+ toggleProject(project);
7492
+ },
7493
+ onMouseEnter: () => setActiveIndex(index),
7494
+ role: "option",
7495
+ type: "button",
7496
+ children: [/* @__PURE__ */ u("span", {
7497
+ class: "project-scope-picker-row-check",
7498
+ "aria-hidden": "true",
7499
+ children: selected ? "✓" : ""
7500
+ }), /* @__PURE__ */ u("span", {
7501
+ class: "project-scope-picker-row-label",
7502
+ children: project
7503
+ })]
7504
+ }, project);
7505
+ }),
7506
+ showCreateRow ? /* @__PURE__ */ u("button", {
7507
+ "aria-selected": false,
7508
+ class: activeIndex === filtered.length ? "project-scope-picker-row project-scope-picker-row--create project-scope-picker-row--active" : "project-scope-picker-row project-scope-picker-row--create",
7509
+ onClick: () => createProject(trimmedQuery),
7510
+ onMouseEnter: () => setActiveIndex(filtered.length),
7511
+ role: "option",
7512
+ type: "button",
7513
+ children: [/* @__PURE__ */ u("span", {
7514
+ class: "project-scope-picker-row-check",
7515
+ "aria-hidden": "true",
7516
+ children: "+"
7517
+ }), /* @__PURE__ */ u("span", {
7518
+ class: "project-scope-picker-row-label",
7519
+ children: `Create "${trimmedQuery}"`
7520
+ })]
7521
+ }) : null
7522
+ ]
7523
+ })]
7524
+ }) })]
7525
+ })]
7526
+ });
7527
+ }
7528
+ //#endregion
7529
+ //#region ../../node_modules/.pnpm/@radix-ui+react-use-previous@1.1.1_react@19.2.4/node_modules/@radix-ui/react-use-previous/dist/index.mjs
7530
+ function usePrevious(value) {
7531
+ const ref = A$1({
7532
+ value,
7533
+ previous: value
7534
+ });
7535
+ return T$1(() => {
7536
+ if (ref.current.value !== value) {
7537
+ ref.current.previous = ref.current.value;
7538
+ ref.current.value = value;
7539
+ }
7540
+ return ref.current.previous;
7541
+ }, [value]);
7542
+ }
7543
+ //#endregion
7544
+ //#region ../../node_modules/.pnpm/@radix-ui+react-switch@1.2.6_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@radix-ui/react-switch/dist/index.mjs
7545
+ var SWITCH_NAME = "Switch";
7546
+ var [createSwitchContext, createSwitchScope] = createContextScope(SWITCH_NAME);
7547
+ var [SwitchProvider, useSwitchContext] = createSwitchContext(SWITCH_NAME);
7548
+ var Switch = D((props, forwardedRef) => {
7549
+ const { __scopeSwitch, name, checked: checkedProp, defaultChecked, required, disabled, value = "on", onCheckedChange, form, ...switchProps } = props;
7550
+ const [button, setButton] = d$2(null);
7551
+ const composedRefs = useComposedRefs(forwardedRef, (node) => setButton(node));
7552
+ const hasConsumerStoppedPropagationRef = A$1(false);
7553
+ const isFormControl = button ? form || !!button.closest("form") : true;
7554
+ const [checked, setChecked] = useControllableState({
7555
+ prop: checkedProp,
7556
+ defaultProp: defaultChecked ?? false,
7557
+ onChange: onCheckedChange,
7558
+ caller: SWITCH_NAME
7559
+ });
7560
+ return /* @__PURE__ */ u(SwitchProvider, {
7561
+ scope: __scopeSwitch,
7562
+ checked,
7563
+ disabled,
7564
+ children: [/* @__PURE__ */ u(Primitive.button, {
7565
+ type: "button",
7566
+ role: "switch",
7567
+ "aria-checked": checked,
7568
+ "aria-required": required,
7569
+ "data-state": getState$2(checked),
7570
+ "data-disabled": disabled ? "" : void 0,
7571
+ disabled,
7572
+ value,
7573
+ ...switchProps,
7574
+ ref: composedRefs,
7575
+ onClick: composeEventHandlers(props.onClick, (event) => {
7576
+ setChecked((prevChecked) => !prevChecked);
7577
+ if (isFormControl) {
7578
+ hasConsumerStoppedPropagationRef.current = event.isPropagationStopped();
7579
+ if (!hasConsumerStoppedPropagationRef.current) event.stopPropagation();
7580
+ }
7581
+ })
7582
+ }), isFormControl && /* @__PURE__ */ u(SwitchBubbleInput, {
7583
+ control: button,
7584
+ bubbles: !hasConsumerStoppedPropagationRef.current,
7585
+ name,
7586
+ value,
7587
+ checked,
7588
+ required,
7589
+ disabled,
7590
+ form,
7591
+ style: { transform: "translateX(-100%)" }
7592
+ })]
7593
+ });
7594
+ });
7595
+ Switch.displayName = SWITCH_NAME;
7596
+ var THUMB_NAME = "SwitchThumb";
7597
+ var SwitchThumb = D((props, forwardedRef) => {
7598
+ const { __scopeSwitch, ...thumbProps } = props;
7599
+ const context = useSwitchContext(THUMB_NAME, __scopeSwitch);
7600
+ return /* @__PURE__ */ u(Primitive.span, {
7601
+ "data-state": getState$2(context.checked),
7602
+ "data-disabled": context.disabled ? "" : void 0,
7603
+ ...thumbProps,
7604
+ ref: forwardedRef
7605
+ });
7606
+ });
7607
+ SwitchThumb.displayName = THUMB_NAME;
7608
+ var BUBBLE_INPUT_NAME$2 = "SwitchBubbleInput";
7609
+ var SwitchBubbleInput = D(({ __scopeSwitch, control, checked, bubbles = true, ...props }, forwardedRef) => {
7610
+ const ref = A$1(null);
7611
+ const composedRefs = useComposedRefs(ref, forwardedRef);
7612
+ const prevChecked = usePrevious(checked);
7613
+ const controlSize = useSize(control);
7614
+ y$2(() => {
7615
+ const input = ref.current;
7616
+ if (!input) return;
7617
+ const inputProto = window.HTMLInputElement.prototype;
7618
+ const setChecked = Object.getOwnPropertyDescriptor(inputProto, "checked").set;
7619
+ if (prevChecked !== checked && setChecked) {
7620
+ const event = new Event("click", { bubbles });
7621
+ setChecked.call(input, checked);
7622
+ input.dispatchEvent(event);
7623
+ }
7624
+ }, [
7625
+ prevChecked,
7626
+ checked,
7627
+ bubbles
7628
+ ]);
7629
+ return /* @__PURE__ */ u("input", {
7630
+ type: "checkbox",
7631
+ "aria-hidden": true,
7632
+ defaultChecked: checked,
7633
+ ...props,
7634
+ tabIndex: -1,
7635
+ ref: composedRefs,
7636
+ style: {
7637
+ ...props.style,
7638
+ ...controlSize,
7639
+ position: "absolute",
7640
+ pointerEvents: "none",
7641
+ opacity: 0,
7642
+ margin: 0
7643
+ }
7644
+ });
7645
+ });
7646
+ SwitchBubbleInput.displayName = BUBBLE_INPUT_NAME$2;
7647
+ function getState$2(checked) {
7648
+ return checked ? "checked" : "unchecked";
7649
+ }
7650
+ var Root$1 = Switch;
7651
+ var Thumb = SwitchThumb;
7652
+ //#endregion
7653
+ //#region src/components/primitives/radix-switch.tsx
7654
+ function RadixSwitch({ "aria-labelledby": ariaLabelledBy, checked, className, disabled = false, id, name, onCheckedChange, thumbClassName }) {
7655
+ return /* @__PURE__ */ u(Root$1, {
7656
+ "aria-labelledby": ariaLabelledBy,
7657
+ checked,
7658
+ className,
7659
+ disabled,
7660
+ id,
7661
+ name,
7662
+ onCheckedChange,
7663
+ children: /* @__PURE__ */ u(Thumb, { className: thumbClassName })
7664
+ });
7665
+ }
7666
+ //#endregion
7667
+ //#region src/lib/notice.ts
7668
+ /**
7669
+ * Legacy signature kept for callsite stability. Now delegates to the Radix
7670
+ * Toast host (mounted once at app boot). Historically rendered via a static
7671
+ * #globalNotice div; that markup is gone — ToastHost owns the UI.
7672
+ */
7673
+ function showGlobalNotice(message, type = "success") {
7674
+ pushToast(message, type);
7675
+ }
7676
+ //#endregion
7677
+ //#region src/tabs/coordinator-admin/data/target-group.ts
7678
+ function adminTargetStorageKey(coordinatorUrl) {
7679
+ return `${ADMIN_TARGET_GROUP_KEY}:${String(coordinatorUrl || "").trim()}`;
7680
+ }
7681
+ function readStoredAdminTargetGroup(coordinatorUrl) {
7682
+ try {
7683
+ return localStorage.getItem(adminTargetStorageKey(coordinatorUrl)) || "";
7684
+ } catch {
7685
+ return "";
7686
+ }
7687
+ }
7688
+ function writeStoredAdminTargetGroup(coordinatorUrl, groupId) {
7689
+ try {
7690
+ localStorage.setItem(adminTargetStorageKey(coordinatorUrl), groupId);
7691
+ } catch {}
7692
+ }
7693
+ function currentAdminTargetGroup() {
7694
+ return String(state.coordinatorAdminTargetGroup || "").trim();
7695
+ }
7696
+ function setAdminTargetGroup(groupId) {
7697
+ state.coordinatorAdminTargetGroup = groupId;
7698
+ writeStoredAdminTargetGroup(state.lastCoordinatorAdminStatus?.coordinator_url || null, groupId);
7699
+ }
7700
+ function availableCoordinatorGroups() {
7701
+ return (Array.isArray(state.lastCoordinatorAdminGroups) ? state.lastCoordinatorAdminGroups : []).map((group) => ({
7702
+ archived_at: group.archived_at ?? null,
7703
+ display_name: group.display_name ?? null,
7704
+ group_id: String(group.group_id || "").trim()
7705
+ })).filter((group) => group.group_id);
7706
+ }
7707
+ function reconcileGroupRenameDrafts() {
7708
+ const next = /* @__PURE__ */ new Map();
7709
+ for (const group of availableCoordinatorGroups()) next.set(group.group_id, group.display_name || group.group_id);
7710
+ coordinatorAdminState.groupRenameDrafts.clear();
7711
+ for (const [groupId, name] of next.entries()) coordinatorAdminState.groupRenameDrafts.set(groupId, name);
7712
+ }
7713
+ function currentAdminTargetGroupRecord() {
7714
+ const target = currentAdminTargetGroup();
7715
+ return availableCoordinatorGroups().find((group) => group.group_id === target) || null;
7716
+ }
7717
+ function resolveAdminTargetGroup() {
7718
+ const status = state.lastCoordinatorAdminStatus;
7719
+ const groups = availableCoordinatorGroups();
7720
+ const configured = String(status?.active_group || "").trim();
7721
+ const stored = readStoredAdminTargetGroup(status?.coordinator_url || null);
7722
+ const current = currentAdminTargetGroup();
7723
+ const availableIds = new Set(groups.map((group) => group.group_id));
7724
+ const candidate = current || stored || configured || groups[0]?.group_id || "";
7725
+ const resolved = candidate && (availableIds.size === 0 || availableIds.has(candidate)) ? candidate : configured || groups[0]?.group_id || "";
7726
+ setAdminTargetGroup(resolved);
7727
+ return resolved;
7728
+ }
7729
+ function reconcileDeviceRenameDrafts() {
7730
+ const next = /* @__PURE__ */ new Map();
7731
+ const items = Array.isArray(state.lastCoordinatorAdminDevices) ? state.lastCoordinatorAdminDevices : [];
7732
+ for (const item of items) {
7733
+ const deviceId = String(item.device_id || "").trim();
7734
+ if (!deviceId) continue;
7735
+ next.set(deviceId, String(item.display_name || ""));
7736
+ }
7737
+ coordinatorAdminState.deviceRenameDrafts.clear();
7738
+ for (const [deviceId, name] of next.entries()) coordinatorAdminState.deviceRenameDrafts.set(deviceId, name);
7739
+ }
7740
+ //#endregion
7741
+ //#region src/tabs/coordinator-admin/components/groups-panel.ts
7742
+ function ChevronRightIcon$1() {
7743
+ return _$3("svg", {
7744
+ "aria-hidden": "true",
7745
+ fill: "none",
7746
+ stroke: "currentColor",
7747
+ "stroke-linecap": "round",
7748
+ "stroke-linejoin": "round",
7749
+ "stroke-width": "2",
7750
+ viewBox: "0 0 24 24",
7751
+ xmlns: "http://www.w3.org/2000/svg"
7752
+ }, _$3("title", null, "Chevron"), _$3("path", { d: "m9 18 6-6-6-6" }));
7753
+ }
7754
+ function emptyDraft() {
7755
+ return {
7756
+ projects_include: [],
7757
+ projects_exclude: [],
7758
+ auto_seed_scope: true,
7759
+ loaded: false,
7760
+ saving: false,
7761
+ error: ""
7762
+ };
7763
+ }
7764
+ async function openGroupPreferences(groupId, renderShell) {
7765
+ const draft = emptyDraft();
7766
+ coordinatorAdminState.groupPreferencesDrafts.set(groupId, draft);
7767
+ coordinatorAdminState.groupPreferencesOpen.add(groupId);
7768
+ renderShell();
7769
+ try {
7770
+ const prefs = await loadCoordinatorGroupPreferences(groupId);
7771
+ coordinatorAdminState.groupPreferencesDrafts.set(groupId, {
7772
+ projects_include: Array.isArray(prefs.projects_include) ? [...prefs.projects_include] : [],
7773
+ projects_exclude: Array.isArray(prefs.projects_exclude) ? [...prefs.projects_exclude] : [],
7774
+ auto_seed_scope: prefs.auto_seed_scope,
7775
+ loaded: true,
7776
+ saving: false,
7777
+ error: ""
7778
+ });
7779
+ } catch (error) {
7780
+ coordinatorAdminState.groupPreferencesDrafts.set(groupId, {
7781
+ ...draft,
7782
+ loaded: true,
7783
+ error: error instanceof Error ? error.message : "Failed to load preferences."
7784
+ });
7785
+ }
7786
+ renderShell();
7787
+ }
7788
+ function closeGroupPreferences(groupId, renderShell) {
7789
+ coordinatorAdminState.groupPreferencesOpen.delete(groupId);
7790
+ coordinatorAdminState.groupPreferencesDrafts.delete(groupId);
7791
+ renderShell();
7792
+ }
7793
+ async function saveGroupPreferences(groupId, renderShell) {
7794
+ const initial = coordinatorAdminState.groupPreferencesDrafts.get(groupId);
7795
+ if (!initial) return;
7796
+ if (initial.saving) return;
7797
+ const payload = {
7798
+ projects_include: initial.projects_include.length > 0 ? [...initial.projects_include] : null,
7799
+ projects_exclude: initial.projects_exclude.length > 0 ? [...initial.projects_exclude] : null,
7800
+ auto_seed_scope: initial.auto_seed_scope
7801
+ };
7802
+ coordinatorAdminState.groupPreferencesDrafts.set(groupId, {
7803
+ ...initial,
7804
+ saving: true,
7805
+ error: ""
7806
+ });
7807
+ renderShell();
7808
+ try {
7809
+ await saveCoordinatorGroupPreferences(groupId, payload);
7810
+ showGlobalNotice("Group scope defaults saved. New peers enrolled through this team will use these defaults.");
7811
+ closeGroupPreferences(groupId, renderShell);
7812
+ } catch (error) {
7813
+ const latest = coordinatorAdminState.groupPreferencesDrafts.get(groupId);
7814
+ if (!latest) return;
7815
+ coordinatorAdminState.groupPreferencesDrafts.set(groupId, {
7816
+ ...latest,
7817
+ saving: false,
7818
+ error: error instanceof Error ? error.message : "Failed to save preferences."
7819
+ });
7820
+ renderShell();
7821
+ }
7822
+ }
7823
+ function renderGroupPreferencesEditor(groupId, renderShell, ready) {
7824
+ const draft = coordinatorAdminState.groupPreferencesDrafts.get(groupId);
7825
+ if (!draft) return null;
7826
+ if (!draft.loaded) return _$3("div", { class: "peer-submeta" }, "Loading scope defaults…");
7827
+ const autoSeedLabelId = `coord-admin-scope-autoseed-${groupId}`;
7828
+ const includeLabelId = `coord-admin-scope-include-${groupId}`;
7829
+ const excludeLabelId = `coord-admin-scope-exclude-${groupId}`;
7830
+ const fieldsDisabled = !ready || draft.saving || !draft.auto_seed_scope;
7831
+ return _$3(k$3, null, _$3("h4", { class: "coordinator-admin-drawer-title" }, "Scope defaults"), _$3("div", { class: "peer-submeta" }, "When enabled, new peers enrolled through this team start with the project filters below. Existing peers are unchanged."), _$3("label", { class: "coordinator-admin-inline-filter" }, _$3("span", {
7832
+ class: "section-meta",
7833
+ id: autoSeedLabelId
7834
+ }, "Auto-seed scope on new peers"), _$3(RadixSwitch, {
7835
+ "aria-labelledby": autoSeedLabelId,
7836
+ checked: draft.auto_seed_scope,
7837
+ className: "coordinator-admin-switch",
7838
+ disabled: !ready || draft.saving,
7839
+ onCheckedChange: (checked) => {
7840
+ const current = coordinatorAdminState.groupPreferencesDrafts.get(groupId) ?? draft;
7841
+ coordinatorAdminState.groupPreferencesDrafts.set(groupId, {
7842
+ ...current,
7843
+ auto_seed_scope: checked
7844
+ });
7845
+ renderShell();
7846
+ },
7847
+ thumbClassName: "coordinator-admin-switch-thumb"
7848
+ })), _$3("div", { class: "coordinator-admin-field" }, _$3("span", { id: includeLabelId }, "Include projects"), _$3(ProjectScopePicker, {
7849
+ "aria-labelledby": includeLabelId,
7850
+ availableProjects: coordinatorAdminState.availableProjects,
7851
+ disabled: fieldsDisabled,
7852
+ emptyLabel: "All projects allowed.",
7853
+ onValuesChange: (next) => {
7854
+ const current = coordinatorAdminState.groupPreferencesDrafts.get(groupId) ?? draft;
7855
+ coordinatorAdminState.groupPreferencesDrafts.set(groupId, {
7856
+ ...current,
7857
+ projects_include: next
7858
+ });
7859
+ renderShell();
7860
+ },
7861
+ placeholder: "Add project",
7862
+ values: draft.projects_include
7863
+ }), _$3("span", { class: "peer-submeta" }, "Leave empty to allow every project. Type to search or create a new name.")), _$3("div", { class: "coordinator-admin-field" }, _$3("span", { id: excludeLabelId }, "Exclude projects"), _$3(ProjectScopePicker, {
7864
+ "aria-labelledby": excludeLabelId,
7865
+ availableProjects: coordinatorAdminState.availableProjects,
7866
+ disabled: fieldsDisabled,
7867
+ emptyLabel: "Nothing excluded.",
7868
+ onValuesChange: (next) => {
7869
+ const current = coordinatorAdminState.groupPreferencesDrafts.get(groupId) ?? draft;
7870
+ coordinatorAdminState.groupPreferencesDrafts.set(groupId, {
7871
+ ...current,
7872
+ projects_exclude: next
7873
+ });
7874
+ renderShell();
7875
+ },
7876
+ placeholder: "Add project",
7877
+ values: draft.projects_exclude
7878
+ })), draft.error ? _$3("div", { class: "peer-submeta coordinator-admin-error" }, draft.error) : null, _$3("div", { class: "peer-actions" }, _$3("button", {
7879
+ class: "settings-button",
7880
+ disabled: !ready || draft.saving,
7881
+ onClick: () => void saveGroupPreferences(groupId, renderShell),
7882
+ type: "button"
7883
+ }, draft.saving ? "Saving…" : "Save defaults"), _$3("button", {
7884
+ class: "settings-button",
7885
+ disabled: draft.saving,
7886
+ onClick: () => closeGroupPreferences(groupId, renderShell),
7887
+ type: "button"
7888
+ }, "Cancel")));
7889
+ }
7890
+ function renderGroupsPanel(deps) {
7891
+ const { summary, createGroup, runGroup, renderShell, reloadData } = deps;
7892
+ const configuredGroup = String(state.lastCoordinatorAdminStatus?.active_group || "").trim();
7893
+ const selectedGroup = currentAdminTargetGroup();
7894
+ const groups = availableCoordinatorGroups();
7895
+ const activeGroups = groups.filter((group) => !group.archived_at);
7896
+ const archivedGroups = groups.filter((group) => group.archived_at);
7897
+ const visibleGroups = coordinatorAdminState.showArchivedGroups ? groups : activeGroups;
7898
+ const targetExists = selectedGroup ? groups.some((group) => group.group_id === selectedGroup) : false;
7899
+ const countParts = [`${activeGroups.length} active`];
7900
+ if (archivedGroups.length) countParts.push(`${archivedGroups.length} archived`);
7901
+ return _$3(RadixTabsContent, {
7902
+ className: "coordinator-admin-panel",
7903
+ value: "groups"
7904
+ }, _$3("h3", null, "Groups"), _$3("p", { class: "peer-submeta" }, selectedGroup ? `Managing ${selectedGroup}${configuredGroup && configuredGroup !== selectedGroup ? ` · this node uses ${configuredGroup} for discovery` : ""}` : configuredGroup ? `This node uses ${configuredGroup} for discovery. Select a group below to manage it.` : "No group selected yet. Create one or select an existing group to manage."), groups.length ? _$3("p", { class: "peer-submeta" }, countParts.join(" · ")) : null, !targetExists && selectedGroup ? _$3("div", { class: "peer-meta coordinator-admin-inline-warning" }, `The selected admin target group (${selectedGroup}) is configured locally but does not exist in the coordinator yet. Create it below or switch to another group once one exists.`) : null, _$3("div", { class: "coordinator-admin-form-grid" }, _$3("label", { class: "coordinator-admin-field" }, _$3("span", null, "New group id"), _$3(TextInput, {
7905
+ class: "peer-scope-input",
7906
+ disabled: summary.readiness !== "ready" || coordinatorAdminState.groupActionPendingKind === "create",
7907
+ onInput: (event) => {
7908
+ coordinatorAdminState.createGroupId = String(event.currentTarget.value || "");
7909
+ },
7910
+ placeholder: "team-alpha",
7911
+ type: "text",
7912
+ value: coordinatorAdminState.createGroupId
7913
+ })), _$3("label", { class: "coordinator-admin-field" }, _$3("span", null, "Display name"), _$3(TextInput, {
7914
+ class: "peer-scope-input",
7915
+ disabled: summary.readiness !== "ready" || coordinatorAdminState.groupActionPendingKind === "create",
7916
+ onInput: (event) => {
7917
+ coordinatorAdminState.createGroupDisplayName = String(event.currentTarget.value || "");
7918
+ },
7919
+ placeholder: "Team Alpha",
7920
+ type: "text",
7921
+ value: coordinatorAdminState.createGroupDisplayName
7922
+ }))), _$3("div", { class: "section-actions coordinator-admin-groups-toolbar" }, _$3("div", { class: "coordinator-admin-primary-actions" }, _$3("button", {
7923
+ class: "settings-button",
7924
+ disabled: summary.readiness !== "ready" || coordinatorAdminState.groupActionPendingKind === "create",
7925
+ onClick: () => createGroup(),
7926
+ type: "button"
7927
+ }, coordinatorAdminState.groupActionPendingKind === "create" ? "Creating…" : "Create group")), _$3("div", { class: "coordinator-admin-secondary-actions" }, _$3("label", { class: "coordinator-admin-inline-filter" }, _$3("span", {
7928
+ class: "section-meta",
7929
+ id: "coordinatorAdminShowArchivedLabel"
7930
+ }, "Show archived"), _$3(RadixSwitch, {
7931
+ "aria-labelledby": "coordinatorAdminShowArchivedLabel",
7932
+ checked: coordinatorAdminState.showArchivedGroups,
7933
+ className: "coordinator-admin-switch",
7934
+ disabled: summary.readiness !== "ready",
7935
+ onCheckedChange: (checked) => {
7936
+ coordinatorAdminState.showArchivedGroups = checked;
7937
+ renderShell();
7938
+ },
7939
+ thumbClassName: "coordinator-admin-switch-thumb"
7940
+ })))), !visibleGroups.length ? _$3("div", { class: "peer-meta coordinator-admin-empty-state" }, summary.readiness === "ready" ? coordinatorAdminState.showArchivedGroups ? "No coordinator groups are available yet." : "No active groups yet. Create one to get started." : "Group browsing will appear here once setup is complete.") : _$3("div", { class: "peer-list" }, visibleGroups.map((group) => {
7941
+ const selected = group.group_id === selectedGroup;
7942
+ const pending = coordinatorAdminState.groupActionPendingId === group.group_id;
7943
+ const archived = Boolean(group.archived_at);
7944
+ const draftName = coordinatorAdminState.groupRenameDrafts.get(group.group_id) ?? group.display_name ?? group.group_id;
7945
+ const scopeOpen = coordinatorAdminState.groupPreferencesOpen.has(group.group_id);
7946
+ return _$3("div", {
7947
+ class: "peer-card peer-card--padded",
7948
+ key: group.group_id
7949
+ }, _$3("div", { class: "peer-title" }, _$3("strong", null, draftName)), _$3("div", { class: "peer-meta" }, `Group ID: ${group.group_id}`), _$3("div", { class: "peer-submeta" }, archived ? "Archived" : "Active"), configuredGroup === group.group_id ? _$3("div", { class: "peer-submeta" }, "This node is configured to use this group for coordinator-backed discovery.") : null, _$3("label", { class: "coordinator-admin-field" }, _$3("span", null, "Display name"), _$3(TextInput, {
7950
+ class: "peer-scope-input",
7951
+ disabled: summary.readiness !== "ready" || pending,
7952
+ onInput: (event) => {
7953
+ coordinatorAdminState.groupRenameDrafts.set(group.group_id, String(event.currentTarget.value || ""));
7954
+ },
7955
+ type: "text",
7956
+ value: draftName
7957
+ })), _$3("div", { class: "peer-actions" }, _$3("button", {
7958
+ class: "settings-button",
7959
+ disabled: summary.readiness !== "ready" || selected,
7960
+ onClick: () => {
7961
+ setAdminTargetGroup(group.group_id);
7962
+ reloadData();
7963
+ },
7964
+ type: "button"
7965
+ }, selected ? "Managing" : "Manage"), _$3("button", {
7966
+ class: "settings-button",
7967
+ disabled: summary.readiness !== "ready" || pending,
7968
+ onClick: () => runGroup(group.group_id, draftName, "rename"),
7969
+ type: "button"
7970
+ }, pending && coordinatorAdminState.groupActionPendingKind === "rename" ? "Renaming…" : "Rename"), _$3("button", {
7971
+ "aria-expanded": scopeOpen,
7972
+ "aria-controls": `coord-admin-scope-drawer-${group.group_id}`,
7973
+ class: "settings-button coordinator-admin-scope-trigger",
7974
+ "data-state": scopeOpen ? "open" : "closed",
7975
+ disabled: summary.readiness !== "ready" || pending,
7976
+ onClick: () => {
7977
+ if (scopeOpen) closeGroupPreferences(group.group_id, renderShell);
7978
+ else openGroupPreferences(group.group_id, renderShell);
7979
+ },
7980
+ type: "button"
7981
+ }, _$3("span", null, "Scope defaults"), _$3("span", {
7982
+ "aria-hidden": "true",
7983
+ class: "device-row-chevron"
7984
+ }, _$3(ChevronRightIcon$1, null))), _$3("button", {
7985
+ class: archived ? "settings-button" : "settings-button danger",
7986
+ disabled: summary.readiness !== "ready" || pending,
7987
+ onClick: () => runGroup(group.group_id, group.display_name || group.group_id, archived ? "unarchive" : "archive"),
7988
+ type: "button"
7989
+ }, pending && coordinatorAdminState.groupActionPendingKind === (archived ? "unarchive" : "archive") ? archived ? "Restoring…" : "Archiving…" : archived ? "Unarchive" : "Archive")), _$3(Root$3, {
7990
+ open: scopeOpen,
7991
+ onOpenChange: (open) => {
7992
+ if (open) openGroupPreferences(group.group_id, renderShell);
7993
+ else closeGroupPreferences(group.group_id, renderShell);
7994
+ }
7995
+ }, _$3(Content$2, {
7996
+ "aria-label": `Scope defaults for ${draftName}`,
7997
+ class: "coordinator-admin-group-preferences",
7998
+ id: `coord-admin-scope-drawer-${group.group_id}`
7999
+ }, scopeOpen ? renderGroupPreferencesEditor(group.group_id, renderShell, summary.readiness === "ready") : null)));
8000
+ })));
8001
+ }
8002
+ //#endregion
8003
+ //#region ../../node_modules/.pnpm/@radix-ui+number@1.1.1/node_modules/@radix-ui/number/dist/index.mjs
8004
+ function clamp(value, [min, max]) {
8005
+ return Math.min(max, Math.max(min, value));
8006
+ }
7239
8007
  //#endregion
7240
8008
  //#region ../../node_modules/.pnpm/@radix-ui+react-select@2.2.6_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@radix-ui/react-select/dist/index.mjs
7241
8009
  var OPEN_KEYS = [
@@ -7274,7 +8042,7 @@
7274
8042
  const isFormControl = trigger ? form || !!trigger.closest("form") : true;
7275
8043
  const [nativeOptionsSet, setNativeOptionsSet] = d$2(/* @__PURE__ */ new Set());
7276
8044
  const nativeSelectKey = Array.from(nativeOptionsSet).map((option) => option.props.value).join(";");
7277
- return /* @__PURE__ */ u(Root2$3, {
8045
+ return /* @__PURE__ */ u(Root2$4, {
7278
8046
  ...popperScope,
7279
8047
  children: /* @__PURE__ */ u(SelectProvider, {
7280
8048
  required,
@@ -7325,11 +8093,11 @@
7325
8093
  });
7326
8094
  };
7327
8095
  Select.displayName = SELECT_NAME;
7328
- var TRIGGER_NAME$4 = "SelectTrigger";
8096
+ var TRIGGER_NAME$3 = "SelectTrigger";
7329
8097
  var SelectTrigger = D((props, forwardedRef) => {
7330
8098
  const { __scopeSelect, disabled = false, ...triggerProps } = props;
7331
8099
  const popperScope = usePopperScope$2(__scopeSelect);
7332
- const context = useSelectContext(TRIGGER_NAME$4, __scopeSelect);
8100
+ const context = useSelectContext(TRIGGER_NAME$3, __scopeSelect);
7333
8101
  const isDisabled = context.disabled || disabled;
7334
8102
  const composedRefs = useComposedRefs(forwardedRef, context.onTriggerChange);
7335
8103
  const getItems = useCollection$1(__scopeSelect);
@@ -7391,7 +8159,7 @@
7391
8159
  })
7392
8160
  });
7393
8161
  });
7394
- SelectTrigger.displayName = TRIGGER_NAME$4;
8162
+ SelectTrigger.displayName = TRIGGER_NAME$3;
7395
8163
  var VALUE_NAME = "SelectValue";
7396
8164
  var SelectValue = D((props, forwardedRef) => {
7397
8165
  const { __scopeSelect, className, style, children, placeholder = "", ...valueProps } = props;
@@ -7423,15 +8191,15 @@
7423
8191
  SelectIcon.displayName = ICON_NAME;
7424
8192
  var PORTAL_NAME$4 = "SelectPortal";
7425
8193
  var SelectPortal = (props) => {
7426
- return /* @__PURE__ */ u(Portal$4, {
8194
+ return /* @__PURE__ */ u(Portal$5, {
7427
8195
  asChild: true,
7428
8196
  ...props
7429
8197
  });
7430
8198
  };
7431
8199
  SelectPortal.displayName = PORTAL_NAME$4;
7432
- var CONTENT_NAME$5 = "SelectContent";
8200
+ var CONTENT_NAME$4 = "SelectContent";
7433
8201
  var SelectContent = D((props, forwardedRef) => {
7434
- const context = useSelectContext(CONTENT_NAME$5, props.__scopeSelect);
8202
+ const context = useSelectContext(CONTENT_NAME$4, props.__scopeSelect);
7435
8203
  const [fragment, setFragment] = d$2();
7436
8204
  useLayoutEffect2(() => {
7437
8205
  setFragment(new DocumentFragment());
@@ -7451,14 +8219,14 @@
7451
8219
  ref: forwardedRef
7452
8220
  });
7453
8221
  });
7454
- SelectContent.displayName = CONTENT_NAME$5;
8222
+ SelectContent.displayName = CONTENT_NAME$4;
7455
8223
  var CONTENT_MARGIN = 10;
7456
- var [SelectContentProvider, useSelectContentContext] = createSelectContext(CONTENT_NAME$5);
8224
+ var [SelectContentProvider, useSelectContentContext] = createSelectContext(CONTENT_NAME$4);
7457
8225
  var CONTENT_IMPL_NAME = "SelectContentImpl";
7458
8226
  var Slot$2 = /* @__PURE__ */ createSlot("SelectContent.RemoveScroll");
7459
8227
  var SelectContentImpl = D((props, forwardedRef) => {
7460
8228
  const { __scopeSelect, position = "item-aligned", onCloseAutoFocus, onEscapeKeyDown, onPointerDownOutside, side, sideOffset, align, alignOffset, arrowPadding, collisionBoundary, collisionPadding, sticky, hideWhenDetached, avoidCollisions, ...contentProps } = props;
7461
- const context = useSelectContext(CONTENT_NAME$5, __scopeSelect);
8229
+ const context = useSelectContext(CONTENT_NAME$4, __scopeSelect);
7462
8230
  const [content, setContent] = d$2(null);
7463
8231
  const [viewport, setViewport] = d$2(null);
7464
8232
  const composedRefs = useComposedRefs(forwardedRef, (node) => setContent(node));
@@ -7648,8 +8416,8 @@
7648
8416
  var ITEM_ALIGNED_POSITION_NAME = "SelectItemAlignedPosition";
7649
8417
  var SelectItemAlignedPosition = D((props, forwardedRef) => {
7650
8418
  const { __scopeSelect, onPlaced, ...popperProps } = props;
7651
- const context = useSelectContext(CONTENT_NAME$5, __scopeSelect);
7652
- const contentContext = useSelectContentContext(CONTENT_NAME$5, __scopeSelect);
8419
+ const context = useSelectContext(CONTENT_NAME$4, __scopeSelect);
8420
+ const contentContext = useSelectContentContext(CONTENT_NAME$4, __scopeSelect);
7653
8421
  const [contentWrapper, setContentWrapper] = d$2(null);
7654
8422
  const [content, setContent] = d$2(null);
7655
8423
  const composedRefs = useComposedRefs(forwardedRef, (node) => setContent(node));
@@ -7670,7 +8438,7 @@
7670
8438
  const minContentWidth = triggerRect.width + leftDelta;
7671
8439
  const contentWidth = Math.max(minContentWidth, contentRect.width);
7672
8440
  const rightEdge = window.innerWidth - CONTENT_MARGIN;
7673
- const clampedLeft = clamp$1(left, [CONTENT_MARGIN, Math.max(CONTENT_MARGIN, rightEdge - contentWidth)]);
8441
+ const clampedLeft = clamp(left, [CONTENT_MARGIN, Math.max(CONTENT_MARGIN, rightEdge - contentWidth)]);
7674
8442
  contentWrapper.style.minWidth = minContentWidth + "px";
7675
8443
  contentWrapper.style.left = clampedLeft + "px";
7676
8444
  } else {
@@ -7680,7 +8448,7 @@
7680
8448
  const minContentWidth = triggerRect.width + rightDelta;
7681
8449
  const contentWidth = Math.max(minContentWidth, contentRect.width);
7682
8450
  const leftEdge = window.innerWidth - CONTENT_MARGIN;
7683
- const clampedRight = clamp$1(right, [CONTENT_MARGIN, Math.max(CONTENT_MARGIN, leftEdge - contentWidth)]);
8451
+ const clampedRight = clamp(right, [CONTENT_MARGIN, Math.max(CONTENT_MARGIN, leftEdge - contentWidth)]);
7684
8452
  contentWrapper.style.minWidth = minContentWidth + "px";
7685
8453
  contentWrapper.style.right = clampedRight + "px";
7686
8454
  }
@@ -7774,7 +8542,7 @@
7774
8542
  var POPPER_POSITION_NAME = "SelectPopperPosition";
7775
8543
  var SelectPopperPosition = D((props, forwardedRef) => {
7776
8544
  const { __scopeSelect, align = "start", collisionPadding = CONTENT_MARGIN, ...popperProps } = props;
7777
- return /* @__PURE__ */ u(Content$2, {
8545
+ return /* @__PURE__ */ u(Content$1, {
7778
8546
  ...usePopperScope$2(__scopeSelect),
7779
8547
  ...popperProps,
7780
8548
  ref: forwardedRef,
@@ -7792,7 +8560,7 @@
7792
8560
  });
7793
8561
  });
7794
8562
  SelectPopperPosition.displayName = POPPER_POSITION_NAME;
7795
- var [SelectViewportProvider, useSelectViewportContext] = createSelectContext(CONTENT_NAME$5, {});
8563
+ var [SelectViewportProvider, useSelectViewportContext] = createSelectContext(CONTENT_NAME$4, {});
7796
8564
  var VIEWPORT_NAME = "SelectViewport";
7797
8565
  var SelectViewport = D((props, forwardedRef) => {
7798
8566
  const { __scopeSelect, nonce, ...viewportProps } = props;
@@ -8173,7 +8941,7 @@
8173
8941
  return array.map((_, index) => array[(startIndex + index) % array.length]);
8174
8942
  }
8175
8943
  var Root2$2 = Select;
8176
- var Trigger$3 = SelectTrigger;
8944
+ var Trigger$2 = SelectTrigger;
8177
8945
  var Value = SelectValue;
8178
8946
  var Icon = SelectIcon;
8179
8947
  var Portal$3 = SelectPortal;
@@ -8224,7 +8992,7 @@
8224
8992
  disabled,
8225
8993
  onValueChange: (nextValue) => onValueChange(decodeValue(nextValue)),
8226
8994
  value: value ? encodeValue(value) : void 0,
8227
- children: [/* @__PURE__ */ u(Trigger$3, {
8995
+ children: [/* @__PURE__ */ u(Trigger$2, {
8228
8996
  "aria-label": ariaLabel,
8229
8997
  className: triggerClassName ?? className,
8230
8998
  "data-value": value,
@@ -8333,13 +9101,13 @@
8333
9101
  return _$3(RadixTabsContent, {
8334
9102
  className: "coordinator-admin-panel",
8335
9103
  value: "join-requests"
8336
- }, _$3("h3", null, "Pending join requests"), _$3("p", { class: "peer-submeta" }, summary.readiness === "ready" ? "Approve or deny teammate join requests from the dedicated operator surface instead of burying them in Sync." : "Finish setup first. Join request review stays disabled until coordinator admin is ready."), !items.length ? _$3("div", { class: "peer-meta" }, summary.readiness === "ready" ? "No pending join requests right now." : "Join request review will appear here once setup is complete.") : _$3("div", { class: "coordinator-admin-request-list" }, items.map((item) => {
9104
+ }, _$3("h3", null, "Pending join requests"), _$3("p", { class: "peer-submeta" }, summary.readiness === "ready" ? "Approve or deny teammate join requests from the dedicated operator surface instead of burying them in Sync." : "Finish setup first. Join request review stays disabled until coordinator admin is ready."), !items.length ? _$3("div", { class: "peer-meta" }, summary.readiness === "ready" ? "No pending join requests right now." : "Join request review will appear here once setup is complete.") : _$3("div", { class: "peer-list" }, items.map((item) => {
8337
9105
  const requestId = String(item.request_id || "").trim();
8338
9106
  const deviceId = String(item.device_id || "unknown-device");
8339
9107
  const displayName = String(item.display_name || deviceId);
8340
9108
  const pending = coordinatorAdminState.joinReviewPendingId === requestId;
8341
9109
  return _$3("div", {
8342
- class: "peer-card",
9110
+ class: "peer-card peer-card--padded",
8343
9111
  key: requestId || deviceId
8344
9112
  }, _$3("div", { class: "peer-title" }, _$3("strong", null, displayName)), _$3("div", { class: "peer-meta" }, `Device: ${deviceId}`), _$3("div", { class: "peer-actions" }, _$3("button", {
8345
9113
  class: "settings-button",
@@ -8355,16 +9123,6 @@
8355
9123
  })));
8356
9124
  }
8357
9125
  //#endregion
8358
- //#region src/lib/notice.ts
8359
- /**
8360
- * Legacy signature kept for callsite stability. Now delegates to the Radix
8361
- * Toast host (mounted once at app boot). Historically rendered via a static
8362
- * #globalNotice div; that markup is gone — ToastHost owns the UI.
8363
- */
8364
- function showGlobalNotice(message, type = "success") {
8365
- pushToast(message, type);
8366
- }
8367
- //#endregion
8368
9126
  //#region ../../node_modules/.pnpm/@radix-ui+react-dialog@1.1.15_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@radix-ui/react-dialog/dist/index.mjs
8369
9127
  var DIALOG_NAME = "Dialog";
8370
9128
  var [createDialogContext, createDialogScope] = createContextScope(DIALOG_NAME);
@@ -8394,23 +9152,23 @@
8394
9152
  });
8395
9153
  };
8396
9154
  Dialog.displayName = DIALOG_NAME;
8397
- var TRIGGER_NAME$3 = "DialogTrigger";
9155
+ var TRIGGER_NAME$2 = "DialogTrigger";
8398
9156
  var DialogTrigger = D((props, forwardedRef) => {
8399
9157
  const { __scopeDialog, ...triggerProps } = props;
8400
- const context = useDialogContext(TRIGGER_NAME$3, __scopeDialog);
9158
+ const context = useDialogContext(TRIGGER_NAME$2, __scopeDialog);
8401
9159
  const composedTriggerRef = useComposedRefs(forwardedRef, context.triggerRef);
8402
9160
  return /* @__PURE__ */ u(Primitive.button, {
8403
9161
  type: "button",
8404
9162
  "aria-haspopup": "dialog",
8405
9163
  "aria-expanded": context.open,
8406
9164
  "aria-controls": context.contentId,
8407
- "data-state": getState$2(context.open),
9165
+ "data-state": getState$1(context.open),
8408
9166
  ...triggerProps,
8409
9167
  ref: composedTriggerRef,
8410
9168
  onClick: composeEventHandlers(props.onClick, context.onOpenToggle)
8411
9169
  });
8412
9170
  });
8413
- DialogTrigger.displayName = TRIGGER_NAME$3;
9171
+ DialogTrigger.displayName = TRIGGER_NAME$2;
8414
9172
  var PORTAL_NAME$3 = "DialogPortal";
8415
9173
  var [PortalProvider$2, usePortalContext$2] = createDialogContext(PORTAL_NAME$3, { forceMount: void 0 });
8416
9174
  var DialogPortal = (props) => {
@@ -8421,7 +9179,7 @@
8421
9179
  forceMount,
8422
9180
  children: L.map(children, (child) => /* @__PURE__ */ u(Presence, {
8423
9181
  present: forceMount || context.open,
8424
- children: /* @__PURE__ */ u(Portal$4, {
9182
+ children: /* @__PURE__ */ u(Portal$5, {
8425
9183
  asChild: true,
8426
9184
  container,
8427
9185
  children: child
@@ -8453,7 +9211,7 @@
8453
9211
  allowPinchZoom: true,
8454
9212
  shards: [context.contentRef],
8455
9213
  children: /* @__PURE__ */ u(Primitive.div, {
8456
- "data-state": getState$2(context.open),
9214
+ "data-state": getState$1(context.open),
8457
9215
  ...overlayProps,
8458
9216
  ref: forwardedRef,
8459
9217
  style: {
@@ -8463,11 +9221,11 @@
8463
9221
  })
8464
9222
  });
8465
9223
  });
8466
- var CONTENT_NAME$4 = "DialogContent";
9224
+ var CONTENT_NAME$3 = "DialogContent";
8467
9225
  var DialogContent = D((props, forwardedRef) => {
8468
- const portalContext = usePortalContext$2(CONTENT_NAME$4, props.__scopeDialog);
9226
+ const portalContext = usePortalContext$2(CONTENT_NAME$3, props.__scopeDialog);
8469
9227
  const { forceMount = portalContext.forceMount, ...contentProps } = props;
8470
- const context = useDialogContext(CONTENT_NAME$4, props.__scopeDialog);
9228
+ const context = useDialogContext(CONTENT_NAME$3, props.__scopeDialog);
8471
9229
  return /* @__PURE__ */ u(Presence, {
8472
9230
  present: forceMount || context.open,
8473
9231
  children: context.modal ? /* @__PURE__ */ u(DialogContentModal, {
@@ -8479,9 +9237,9 @@
8479
9237
  })
8480
9238
  });
8481
9239
  });
8482
- DialogContent.displayName = CONTENT_NAME$4;
9240
+ DialogContent.displayName = CONTENT_NAME$3;
8483
9241
  var DialogContentModal = D((props, forwardedRef) => {
8484
- const context = useDialogContext(CONTENT_NAME$4, props.__scopeDialog);
9242
+ const context = useDialogContext(CONTENT_NAME$3, props.__scopeDialog);
8485
9243
  const contentRef = A$1(null);
8486
9244
  const composedRefs = useComposedRefs(forwardedRef, context.contentRef, contentRef);
8487
9245
  y$2(() => {
@@ -8506,7 +9264,7 @@
8506
9264
  });
8507
9265
  });
8508
9266
  var DialogContentNonModal = D((props, forwardedRef) => {
8509
- const context = useDialogContext(CONTENT_NAME$4, props.__scopeDialog);
9267
+ const context = useDialogContext(CONTENT_NAME$3, props.__scopeDialog);
8510
9268
  const hasInteractedOutsideRef = A$1(false);
8511
9269
  const hasPointerDownOutsideRef = A$1(false);
8512
9270
  return /* @__PURE__ */ u(DialogContentImpl, {
@@ -8537,7 +9295,7 @@
8537
9295
  });
8538
9296
  var DialogContentImpl = D((props, forwardedRef) => {
8539
9297
  const { __scopeDialog, trapFocus, onOpenAutoFocus, onCloseAutoFocus, ...contentProps } = props;
8540
- const context = useDialogContext(CONTENT_NAME$4, __scopeDialog);
9298
+ const context = useDialogContext(CONTENT_NAME$3, __scopeDialog);
8541
9299
  const contentRef = A$1(null);
8542
9300
  const composedRefs = useComposedRefs(forwardedRef, contentRef);
8543
9301
  useFocusGuards();
@@ -8552,7 +9310,7 @@
8552
9310
  id: context.contentId,
8553
9311
  "aria-describedby": context.descriptionId,
8554
9312
  "aria-labelledby": context.titleId,
8555
- "data-state": getState$2(context.open),
9313
+ "data-state": getState$1(context.open),
8556
9314
  ...contentProps,
8557
9315
  ref: composedRefs,
8558
9316
  onDismiss: () => context.onOpenChange(false)
@@ -8596,12 +9354,12 @@
8596
9354
  });
8597
9355
  });
8598
9356
  DialogClose.displayName = CLOSE_NAME;
8599
- function getState$2(open) {
9357
+ function getState$1(open) {
8600
9358
  return open ? "open" : "closed";
8601
9359
  }
8602
9360
  var TITLE_WARNING_NAME = "DialogTitleWarning";
8603
9361
  var [WarningProvider, useWarningContext] = createContext2(TITLE_WARNING_NAME, {
8604
- contentName: CONTENT_NAME$4,
9362
+ contentName: CONTENT_NAME$3,
8605
9363
  titleName: TITLE_NAME,
8606
9364
  docsSlug: "dialog"
8607
9365
  });
@@ -8634,14 +9392,14 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
8634
9392
  ]);
8635
9393
  return null;
8636
9394
  };
8637
- var Root$1 = Dialog;
9395
+ var Root = Dialog;
8638
9396
  var Portal$2 = DialogPortal;
8639
9397
  var Overlay = DialogOverlay;
8640
- var Content$1 = DialogContent;
9398
+ var Content = DialogContent;
8641
9399
  //#endregion
8642
9400
  //#region src/components/primitives/radix-dialog.tsx
8643
9401
  function RadixDialog({ ariaDescribedby, ariaLabelledby, children, contentClassName, contentId, modal = true, onCloseAutoFocus, onEscapeKeyDown, onInteractOutside, onOpenAutoFocus, onOpenChange, open, overlayClassName, overlayId, slotId }) {
8644
- return /* @__PURE__ */ u(Root$1, {
9402
+ return /* @__PURE__ */ u(Root, {
8645
9403
  modal,
8646
9404
  open,
8647
9405
  onOpenChange,
@@ -8651,7 +9409,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
8651
9409
  className: overlayClassName,
8652
9410
  id: overlayId
8653
9411
  })
8654
- }), /* @__PURE__ */ u(Content$1, {
9412
+ }), /* @__PURE__ */ u(Content, {
8655
9413
  "aria-describedby": ariaDescribedby,
8656
9414
  "aria-labelledby": ariaLabelledby,
8657
9415
  asChild: true,
@@ -8715,6 +9473,125 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
8715
9473
  return tone === "danger" ? "sync-dialog-confirm danger" : "sync-dialog-confirm";
8716
9474
  }
8717
9475
  //#endregion
9476
+ //#region src/components/primitives/autocomplete-input.tsx
9477
+ var AutocompleteInput = D(function AutocompleteInput({ value, onValueChange, suggestions, onSubmit, maxSuggestions = 20, onKeyDown, onFocus, onBlur, className, ...inputProps }, externalRef) {
9478
+ const inputRef = A$1(null);
9479
+ F$2(externalRef, () => inputRef.current, []);
9480
+ const [open, setOpen] = d$2(false);
9481
+ const [activeIndex, setActiveIndex] = d$2(-1);
9482
+ const filtered = T$1(() => {
9483
+ const q = value.trim().toLowerCase();
9484
+ return (q ? suggestions.filter((s) => s.toLowerCase().includes(q)) : suggestions).slice(0, maxSuggestions);
9485
+ }, [
9486
+ value,
9487
+ suggestions,
9488
+ maxSuggestions
9489
+ ]);
9490
+ y$2(() => {
9491
+ if (activeIndex >= filtered.length) setActiveIndex(filtered.length - 1);
9492
+ }, [filtered.length, activeIndex]);
9493
+ const shouldOpen = open && filtered.length > 0;
9494
+ const commit = (selection) => {
9495
+ onValueChange(selection);
9496
+ setOpen(false);
9497
+ setActiveIndex(-1);
9498
+ inputRef.current?.focus();
9499
+ };
9500
+ const handleKeyDown = (event) => {
9501
+ if (event.key === "ArrowDown") {
9502
+ event.preventDefault();
9503
+ setOpen(true);
9504
+ setActiveIndex((i) => filtered.length === 0 ? -1 : Math.min(i + 1, filtered.length - 1));
9505
+ return;
9506
+ }
9507
+ if (event.key === "ArrowUp") {
9508
+ event.preventDefault();
9509
+ if (!open) setOpen(true);
9510
+ setActiveIndex((i) => Math.max(i - 1, -1));
9511
+ return;
9512
+ }
9513
+ if (event.key === "Escape" && shouldOpen) {
9514
+ event.preventDefault();
9515
+ setOpen(false);
9516
+ setActiveIndex(-1);
9517
+ return;
9518
+ }
9519
+ if ((event.key === "Tab" || event.key === "Enter") && activeIndex >= 0) {
9520
+ const pick = filtered[activeIndex];
9521
+ if (pick) {
9522
+ event.preventDefault();
9523
+ commit(pick);
9524
+ return;
9525
+ }
9526
+ }
9527
+ if (event.key === "Enter" && onSubmit) {
9528
+ event.preventDefault();
9529
+ onSubmit();
9530
+ return;
9531
+ }
9532
+ onKeyDown?.(event);
9533
+ };
9534
+ return /* @__PURE__ */ u(Root2$3, {
9535
+ open: shouldOpen,
9536
+ onOpenChange: setOpen,
9537
+ children: [/* @__PURE__ */ u(Anchor2$1, {
9538
+ asChild: true,
9539
+ children: /* @__PURE__ */ u("input", {
9540
+ ...inputProps,
9541
+ ref: inputRef,
9542
+ className,
9543
+ value,
9544
+ onInput: (event) => {
9545
+ onValueChange(event.currentTarget.value);
9546
+ setOpen(true);
9547
+ setActiveIndex(-1);
9548
+ },
9549
+ onFocus: (event) => {
9550
+ onFocus?.(event);
9551
+ },
9552
+ onBlur: (event) => {
9553
+ window.setTimeout(() => setOpen(false), 120);
9554
+ onBlur?.(event);
9555
+ },
9556
+ onKeyDown: handleKeyDown,
9557
+ role: "combobox",
9558
+ "aria-autocomplete": "list",
9559
+ "aria-expanded": shouldOpen,
9560
+ "aria-controls": "autocompleteListbox",
9561
+ "aria-activedescendant": activeIndex >= 0 ? `autocomplete-option-${activeIndex}` : void 0
9562
+ })
9563
+ }), /* @__PURE__ */ u(Portal$4, { children: /* @__PURE__ */ u(Content2$4, {
9564
+ align: "start",
9565
+ className: "autocomplete-popover",
9566
+ onOpenAutoFocus: (event) => event.preventDefault(),
9567
+ onCloseAutoFocus: (event) => event.preventDefault(),
9568
+ sideOffset: 4,
9569
+ style: { width: "var(--radix-popover-trigger-width)" },
9570
+ children: /* @__PURE__ */ u("div", {
9571
+ className: "autocomplete-listbox",
9572
+ id: "autocompleteListbox",
9573
+ role: "listbox",
9574
+ children: filtered.map((suggestion, index) => {
9575
+ const active = index === activeIndex;
9576
+ return /* @__PURE__ */ u("div", {
9577
+ "aria-selected": active,
9578
+ className: active ? "autocomplete-option active" : "autocomplete-option",
9579
+ id: `autocomplete-option-${index}`,
9580
+ onMouseDown: (event) => {
9581
+ event.preventDefault();
9582
+ commit(suggestion);
9583
+ },
9584
+ onMouseEnter: () => setActiveIndex(index),
9585
+ role: "option",
9586
+ tabIndex: -1,
9587
+ children: suggestion
9588
+ }, suggestion);
9589
+ })
9590
+ })
9591
+ }) })]
9592
+ });
9593
+ });
9594
+ //#endregion
8718
9595
  //#region src/components/primitives/dialog-close-button.tsx
8719
9596
  function DialogCloseButton({ ariaLabel, className = "modal-close-button", onClick, label = "Close" }) {
8720
9597
  return /* @__PURE__ */ u("button", {
@@ -8751,7 +9628,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
8751
9628
  type: "button",
8752
9629
  role: "radio",
8753
9630
  "aria-checked": checked,
8754
- "data-state": getState$1(checked),
9631
+ "data-state": getState(checked),
8755
9632
  "data-disabled": disabled ? "" : void 0,
8756
9633
  disabled,
8757
9634
  value,
@@ -8785,7 +9662,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
8785
9662
  return /* @__PURE__ */ u(Presence, {
8786
9663
  present: forceMount || context.checked,
8787
9664
  children: /* @__PURE__ */ u(Primitive.span, {
8788
- "data-state": getState$1(context.checked),
9665
+ "data-state": getState(context.checked),
8789
9666
  "data-disabled": context.disabled ? "" : void 0,
8790
9667
  ...indicatorProps,
8791
9668
  ref: forwardedRef
@@ -8832,7 +9709,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
8832
9709
  });
8833
9710
  });
8834
9711
  RadioBubbleInput.displayName = BUBBLE_INPUT_NAME;
8835
- function getState$1(checked) {
9712
+ function getState(checked) {
8836
9713
  return checked ? "checked" : "unchecked";
8837
9714
  }
8838
9715
  var ARROW_KEYS = [
@@ -9148,7 +10025,20 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
9148
10025
  }) : null,
9149
10026
  request.kind === "input" ? /* @__PURE__ */ u("div", {
9150
10027
  className: "field",
9151
- children: [/* @__PURE__ */ u(TextInput, {
10028
+ children: [request.suggestions?.length ? /* @__PURE__ */ u(AutocompleteInput, {
10029
+ "aria-describedby": errorText ? `${descriptionId} ${inputErrorId}` : descriptionId,
10030
+ autoFocus: true,
10031
+ className: errorText ? "sync-dialog-input sync-field-error" : "sync-dialog-input",
10032
+ "data-sync-primary-action": "true",
10033
+ onSubmit: submit,
10034
+ onValueChange: (value) => {
10035
+ setInputValue(value);
10036
+ if (errorText) setErrorText(null);
10037
+ },
10038
+ placeholder: request.placeholder,
10039
+ suggestions: request.suggestions,
10040
+ value: inputValue
10041
+ }) : /* @__PURE__ */ u(TextInput, {
9152
10042
  "aria-describedby": errorText ? `${descriptionId} ${inputErrorId}` : descriptionId,
9153
10043
  autoFocus: true,
9154
10044
  className: errorText ? "sync-dialog-input sync-field-error" : "sync-dialog-input",
@@ -9218,6 +10108,10 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
9218
10108
  if (nextOpen) return;
9219
10109
  resolveCurrentDialog(request?.kind === "confirm" ? false : null);
9220
10110
  };
10111
+ const handleInteractOutside = (event) => {
10112
+ const originalTarget = (event.detail?.originalEvent)?.target;
10113
+ if (originalTarget instanceof Element && originalTarget.closest(".autocomplete-popover")) event.preventDefault();
10114
+ };
9221
10115
  const handleOpenAutoFocus = (event) => {
9222
10116
  const legacyPrimary = document.querySelector("#syncDialog [data-sync-primary-action=\"true\"]");
9223
10117
  if (request?.kind === "input" && legacyPrimary) {
@@ -9236,6 +10130,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
9236
10130
  ariaLabelledby: titleId,
9237
10131
  contentClassName: "modal",
9238
10132
  contentId: "syncDialog",
10133
+ onInteractOutside: handleInteractOutside,
9239
10134
  onOpenAutoFocus: handleOpenAutoFocus,
9240
10135
  onOpenChange: handleOpenChange,
9241
10136
  open,
@@ -9602,6 +10497,11 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
9602
10497
  state.lastCoordinatorAdminDevices = [];
9603
10498
  coordinatorAdminState.deviceRenameDrafts.clear();
9604
10499
  }
10500
+ try {
10501
+ coordinatorAdminState.availableProjects = await loadProjects$1();
10502
+ } catch {
10503
+ coordinatorAdminState.availableProjects = [];
10504
+ }
9605
10505
  } else {
9606
10506
  state.lastCoordinatorAdminGroups = [];
9607
10507
  coordinatorAdminState.groupRenameDrafts.clear();
@@ -9977,7 +10877,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
9977
10877
  }
9978
10878
  };
9979
10879
  }, []);
9980
- return /* @__PURE__ */ u(Root2$3, {
10880
+ return /* @__PURE__ */ u(Root2$4, {
9981
10881
  ...popperScope,
9982
10882
  children: /* @__PURE__ */ u(TooltipContextProvider, {
9983
10883
  scope: __scopeTooltip,
@@ -10009,11 +10909,11 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
10009
10909
  });
10010
10910
  };
10011
10911
  Tooltip$1.displayName = TOOLTIP_NAME;
10012
- var TRIGGER_NAME$2 = "TooltipTrigger";
10912
+ var TRIGGER_NAME$1 = "TooltipTrigger";
10013
10913
  var TooltipTrigger = D((props, forwardedRef) => {
10014
10914
  const { __scopeTooltip, ...triggerProps } = props;
10015
- const context = useTooltipContext(TRIGGER_NAME$2, __scopeTooltip);
10016
- const providerContext = useTooltipProviderContext(TRIGGER_NAME$2, __scopeTooltip);
10915
+ const context = useTooltipContext(TRIGGER_NAME$1, __scopeTooltip);
10916
+ const providerContext = useTooltipProviderContext(TRIGGER_NAME$1, __scopeTooltip);
10017
10917
  const popperScope = usePopperScope$1(__scopeTooltip);
10018
10918
  const composedRefs = useComposedRefs(forwardedRef, A$1(null), context.onTriggerChange);
10019
10919
  const isPointerDownRef = A$1(false);
@@ -10054,7 +10954,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
10054
10954
  })
10055
10955
  });
10056
10956
  });
10057
- TooltipTrigger.displayName = TRIGGER_NAME$2;
10957
+ TooltipTrigger.displayName = TRIGGER_NAME$1;
10058
10958
  var PORTAL_NAME$2 = "TooltipPortal";
10059
10959
  var [PortalProvider$1, usePortalContext$1] = createTooltipContext(PORTAL_NAME$2, { forceMount: void 0 });
10060
10960
  var TooltipPortal = (props) => {
@@ -10065,7 +10965,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
10065
10965
  forceMount,
10066
10966
  children: /* @__PURE__ */ u(Presence, {
10067
10967
  present: forceMount || context.open,
10068
- children: /* @__PURE__ */ u(Portal$4, {
10968
+ children: /* @__PURE__ */ u(Portal$5, {
10069
10969
  asChild: true,
10070
10970
  container,
10071
10971
  children
@@ -10074,11 +10974,11 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
10074
10974
  });
10075
10975
  };
10076
10976
  TooltipPortal.displayName = PORTAL_NAME$2;
10077
- var CONTENT_NAME$3 = "TooltipContent";
10977
+ var CONTENT_NAME$2 = "TooltipContent";
10078
10978
  var TooltipContent = D((props, forwardedRef) => {
10079
- const portalContext = usePortalContext$1(CONTENT_NAME$3, props.__scopeTooltip);
10979
+ const portalContext = usePortalContext$1(CONTENT_NAME$2, props.__scopeTooltip);
10080
10980
  const { forceMount = portalContext.forceMount, side = "top", ...contentProps } = props;
10081
- const context = useTooltipContext(CONTENT_NAME$3, props.__scopeTooltip);
10981
+ const context = useTooltipContext(CONTENT_NAME$2, props.__scopeTooltip);
10082
10982
  return /* @__PURE__ */ u(Presence, {
10083
10983
  present: forceMount || context.open,
10084
10984
  children: context.disableHoverableContent ? /* @__PURE__ */ u(TooltipContentImpl, {
@@ -10093,8 +10993,8 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
10093
10993
  });
10094
10994
  });
10095
10995
  var TooltipContentHoverable = D((props, forwardedRef) => {
10096
- const context = useTooltipContext(CONTENT_NAME$3, props.__scopeTooltip);
10097
- const providerContext = useTooltipProviderContext(CONTENT_NAME$3, props.__scopeTooltip);
10996
+ const context = useTooltipContext(CONTENT_NAME$2, props.__scopeTooltip);
10997
+ const providerContext = useTooltipProviderContext(CONTENT_NAME$2, props.__scopeTooltip);
10098
10998
  const ref = A$1(null);
10099
10999
  const composedRefs = useComposedRefs(forwardedRef, ref);
10100
11000
  const [pointerGraceArea, setPointerGraceArea] = d$2(null);
@@ -10171,7 +11071,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
10171
11071
  var Slottable = /* @__PURE__ */ createSlottable("TooltipContent");
10172
11072
  var TooltipContentImpl = D((props, forwardedRef) => {
10173
11073
  const { __scopeTooltip, children, "aria-label": ariaLabel, onEscapeKeyDown, onPointerDownOutside, ...contentProps } = props;
10174
- const context = useTooltipContext(CONTENT_NAME$3, __scopeTooltip);
11074
+ const context = useTooltipContext(CONTENT_NAME$2, __scopeTooltip);
10175
11075
  const popperScope = usePopperScope$1(__scopeTooltip);
10176
11076
  const { onClose } = context;
10177
11077
  y$2(() => {
@@ -10194,7 +11094,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
10194
11094
  onPointerDownOutside,
10195
11095
  onFocusOutside: (event) => event.preventDefault(),
10196
11096
  onDismiss: onClose,
10197
- children: /* @__PURE__ */ u(Content$2, {
11097
+ children: /* @__PURE__ */ u(Content$1, {
10198
11098
  "data-state": context.stateAttribute,
10199
11099
  ...popperScope,
10200
11100
  ...contentProps,
@@ -10219,7 +11119,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
10219
11119
  })
10220
11120
  });
10221
11121
  });
10222
- TooltipContent.displayName = CONTENT_NAME$3;
11122
+ TooltipContent.displayName = CONTENT_NAME$2;
10223
11123
  var ARROW_NAME$2 = "TooltipArrow";
10224
11124
  var TooltipArrow = D((props, forwardedRef) => {
10225
11125
  const { __scopeTooltip, ...arrowProps } = props;
@@ -10363,7 +11263,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
10363
11263
  }
10364
11264
  var Provider = TooltipProvider$1;
10365
11265
  var Root3$1 = Tooltip$1;
10366
- var Trigger$2 = TooltipTrigger;
11266
+ var Trigger$1 = TooltipTrigger;
10367
11267
  var Portal$1 = TooltipPortal;
10368
11268
  var Content2$2 = TooltipContent;
10369
11269
  var Arrow2$1 = TooltipArrow;
@@ -10396,7 +11296,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
10396
11296
  */
10397
11297
  function Tooltip({ children, label, side = "top", align = "center", sideOffset = 6, asChild = true, disabled = false }) {
10398
11298
  if (disabled) return /* @__PURE__ */ u(k$3, { children });
10399
- return /* @__PURE__ */ u(Root3$1, { children: [/* @__PURE__ */ u(Trigger$2, {
11299
+ return /* @__PURE__ */ u(Root3$1, { children: [/* @__PURE__ */ u(Trigger$1, {
10400
11300
  asChild,
10401
11301
  children
10402
11302
  }), /* @__PURE__ */ u(Portal$1, { children: /* @__PURE__ */ u(Content2$2, {
@@ -10941,7 +11841,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
10941
11841
  document.removeEventListener("pointermove", handlePointer, { capture: true });
10942
11842
  };
10943
11843
  }, []);
10944
- return /* @__PURE__ */ u(Root2$3, {
11844
+ return /* @__PURE__ */ u(Root2$4, {
10945
11845
  ...popperScope,
10946
11846
  children: /* @__PURE__ */ u(MenuProvider, {
10947
11847
  scope: __scopeMenu,
@@ -10981,7 +11881,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
10981
11881
  forceMount,
10982
11882
  children: /* @__PURE__ */ u(Presence, {
10983
11883
  present: forceMount || context.open,
10984
- children: /* @__PURE__ */ u(Portal$4, {
11884
+ children: /* @__PURE__ */ u(Portal$5, {
10985
11885
  asChild: true,
10986
11886
  container,
10987
11887
  children
@@ -10990,13 +11890,13 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
10990
11890
  });
10991
11891
  };
10992
11892
  MenuPortal.displayName = PORTAL_NAME$1;
10993
- var CONTENT_NAME$2 = "MenuContent";
10994
- var [MenuContentProvider, useMenuContentContext] = createMenuContext(CONTENT_NAME$2);
11893
+ var CONTENT_NAME$1 = "MenuContent";
11894
+ var [MenuContentProvider, useMenuContentContext] = createMenuContext(CONTENT_NAME$1);
10995
11895
  var MenuContent = D((props, forwardedRef) => {
10996
- const portalContext = usePortalContext(CONTENT_NAME$2, props.__scopeMenu);
11896
+ const portalContext = usePortalContext(CONTENT_NAME$1, props.__scopeMenu);
10997
11897
  const { forceMount = portalContext.forceMount, ...contentProps } = props;
10998
- const context = useMenuContext(CONTENT_NAME$2, props.__scopeMenu);
10999
- const rootContext = useMenuRootContext(CONTENT_NAME$2, props.__scopeMenu);
11898
+ const context = useMenuContext(CONTENT_NAME$1, props.__scopeMenu);
11899
+ const rootContext = useMenuRootContext(CONTENT_NAME$1, props.__scopeMenu);
11000
11900
  return /* @__PURE__ */ u(Collection.Provider, {
11001
11901
  scope: props.__scopeMenu,
11002
11902
  children: /* @__PURE__ */ u(Presence, {
@@ -11015,7 +11915,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
11015
11915
  });
11016
11916
  });
11017
11917
  var MenuRootContentModal = D((props, forwardedRef) => {
11018
- const context = useMenuContext(CONTENT_NAME$2, props.__scopeMenu);
11918
+ const context = useMenuContext(CONTENT_NAME$1, props.__scopeMenu);
11019
11919
  const ref = A$1(null);
11020
11920
  const composedRefs = useComposedRefs(forwardedRef, ref);
11021
11921
  y$2(() => {
@@ -11033,7 +11933,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
11033
11933
  });
11034
11934
  });
11035
11935
  var MenuRootContentNonModal = D((props, forwardedRef) => {
11036
- const context = useMenuContext(CONTENT_NAME$2, props.__scopeMenu);
11936
+ const context = useMenuContext(CONTENT_NAME$1, props.__scopeMenu);
11037
11937
  return /* @__PURE__ */ u(MenuContentImpl, {
11038
11938
  ...props,
11039
11939
  ref: forwardedRef,
@@ -11046,8 +11946,8 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
11046
11946
  var Slot = /* @__PURE__ */ createSlot("MenuContent.ScrollLock");
11047
11947
  var MenuContentImpl = D((props, forwardedRef) => {
11048
11948
  const { __scopeMenu, loop = false, trapFocus, onOpenAutoFocus, onCloseAutoFocus, disableOutsidePointerEvents, onEntryFocus, onEscapeKeyDown, onPointerDownOutside, onFocusOutside, onInteractOutside, onDismiss, disableOutsideScroll, ...contentProps } = props;
11049
- const context = useMenuContext(CONTENT_NAME$2, __scopeMenu);
11050
- const rootContext = useMenuRootContext(CONTENT_NAME$2, __scopeMenu);
11949
+ const context = useMenuContext(CONTENT_NAME$1, __scopeMenu);
11950
+ const rootContext = useMenuRootContext(CONTENT_NAME$1, __scopeMenu);
11051
11951
  const popperScope = usePopperScope(__scopeMenu);
11052
11952
  const rovingFocusGroupScope = useRovingFocusGroupScope(__scopeMenu);
11053
11953
  const getItems = useCollection(__scopeMenu);
@@ -11134,7 +12034,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
11134
12034
  if (!rootContext.isUsingKeyboardRef.current) event.preventDefault();
11135
12035
  }),
11136
12036
  preventScrollOnEntryFocus: true,
11137
- children: /* @__PURE__ */ u(Content$2, {
12037
+ children: /* @__PURE__ */ u(Content$1, {
11138
12038
  role: "menu",
11139
12039
  "aria-orientation": "vertical",
11140
12040
  "data-state": getOpenState(context.open),
@@ -11184,7 +12084,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
11184
12084
  })
11185
12085
  });
11186
12086
  });
11187
- MenuContent.displayName = CONTENT_NAME$2;
12087
+ MenuContent.displayName = CONTENT_NAME$1;
11188
12088
  var GROUP_NAME$1 = "MenuGroup";
11189
12089
  var MenuGroup = D((props, forwardedRef) => {
11190
12090
  const { __scopeMenu, ...groupProps } = props;
@@ -11394,7 +12294,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
11394
12294
  if (parentMenuContext.open === false) handleOpenChange(false);
11395
12295
  return () => handleOpenChange(false);
11396
12296
  }, [parentMenuContext.open, handleOpenChange]);
11397
- return /* @__PURE__ */ u(Root2$3, {
12297
+ return /* @__PURE__ */ u(Root2$4, {
11398
12298
  ...popperScope,
11399
12299
  children: /* @__PURE__ */ u(MenuProvider, {
11400
12300
  scope: __scopeMenu,
@@ -11520,10 +12420,10 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
11520
12420
  MenuSubTrigger.displayName = SUB_TRIGGER_NAME$1;
11521
12421
  var SUB_CONTENT_NAME$1 = "MenuSubContent";
11522
12422
  var MenuSubContent = D((props, forwardedRef) => {
11523
- const portalContext = usePortalContext(CONTENT_NAME$2, props.__scopeMenu);
12423
+ const portalContext = usePortalContext(CONTENT_NAME$1, props.__scopeMenu);
11524
12424
  const { forceMount = portalContext.forceMount, ...subContentProps } = props;
11525
- const context = useMenuContext(CONTENT_NAME$2, props.__scopeMenu);
11526
- const rootContext = useMenuRootContext(CONTENT_NAME$2, props.__scopeMenu);
12425
+ const context = useMenuContext(CONTENT_NAME$1, props.__scopeMenu);
12426
+ const rootContext = useMenuRootContext(CONTENT_NAME$1, props.__scopeMenu);
11527
12427
  const subContext = useMenuSubContext(SUB_CONTENT_NAME$1, props.__scopeMenu);
11528
12428
  const ref = A$1(null);
11529
12429
  const composedRefs = useComposedRefs(forwardedRef, ref);
@@ -11673,10 +12573,10 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
11673
12573
  });
11674
12574
  };
11675
12575
  DropdownMenu.displayName = DROPDOWN_MENU_NAME;
11676
- var TRIGGER_NAME$1 = "DropdownMenuTrigger";
12576
+ var TRIGGER_NAME = "DropdownMenuTrigger";
11677
12577
  var DropdownMenuTrigger = D((props, forwardedRef) => {
11678
12578
  const { __scopeDropdownMenu, disabled = false, ...triggerProps } = props;
11679
- const context = useDropdownMenuContext(TRIGGER_NAME$1, __scopeDropdownMenu);
12579
+ const context = useDropdownMenuContext(TRIGGER_NAME, __scopeDropdownMenu);
11680
12580
  return /* @__PURE__ */ u(Anchor2, {
11681
12581
  asChild: true,
11682
12582
  ...useMenuScope(__scopeDropdownMenu),
@@ -11710,7 +12610,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
11710
12610
  })
11711
12611
  });
11712
12612
  });
11713
- DropdownMenuTrigger.displayName = TRIGGER_NAME$1;
12613
+ DropdownMenuTrigger.displayName = TRIGGER_NAME;
11714
12614
  var PORTAL_NAME = "DropdownMenuPortal";
11715
12615
  var DropdownMenuPortal = (props) => {
11716
12616
  const { __scopeDropdownMenu, ...portalProps } = props;
@@ -11720,10 +12620,10 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
11720
12620
  });
11721
12621
  };
11722
12622
  DropdownMenuPortal.displayName = PORTAL_NAME;
11723
- var CONTENT_NAME$1 = "DropdownMenuContent";
12623
+ var CONTENT_NAME = "DropdownMenuContent";
11724
12624
  var DropdownMenuContent = D((props, forwardedRef) => {
11725
12625
  const { __scopeDropdownMenu, ...contentProps } = props;
11726
- const context = useDropdownMenuContext(CONTENT_NAME$1, __scopeDropdownMenu);
12626
+ const context = useDropdownMenuContext(CONTENT_NAME, __scopeDropdownMenu);
11727
12627
  const menuScope = useMenuScope(__scopeDropdownMenu);
11728
12628
  const hasInteractedOutsideRef = A$1(false);
11729
12629
  return /* @__PURE__ */ u(Content2$1, {
@@ -11753,7 +12653,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
11753
12653
  }
11754
12654
  });
11755
12655
  });
11756
- DropdownMenuContent.displayName = CONTENT_NAME$1;
12656
+ DropdownMenuContent.displayName = CONTENT_NAME;
11757
12657
  var GROUP_NAME = "DropdownMenuGroup";
11758
12658
  var DropdownMenuGroup = D((props, forwardedRef) => {
11759
12659
  const { __scopeDropdownMenu, ...groupProps } = props;
@@ -11873,14 +12773,14 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
11873
12773
  });
11874
12774
  DropdownMenuSubContent.displayName = SUB_CONTENT_NAME;
11875
12775
  var Root2 = DropdownMenu;
11876
- var Trigger$1 = DropdownMenuTrigger;
12776
+ var Trigger = DropdownMenuTrigger;
11877
12777
  var Portal2 = DropdownMenuPortal;
11878
12778
  var Content2 = DropdownMenuContent;
11879
12779
  var Item2 = DropdownMenuItem;
11880
12780
  //#endregion
11881
12781
  //#region src/tabs/feed/components/FeedItemMenu.tsx
11882
- function FeedItemMenu({ disabled, onForget, title }) {
11883
- return _$3(Root2, null, _$3(Trigger$1, { asChild: true }, _$3("button", {
12782
+ function FeedItemMenu({ assignProjectDisabled, disabled, onAssignProject, onForget, title }) {
12783
+ return _$3(Root2, null, _$3(Trigger, { asChild: true }, _$3("button", {
11884
12784
  "aria-label": `Actions for ${title}`,
11885
12785
  className: "feed-menu-trigger",
11886
12786
  type: "button"
@@ -11890,6 +12790,10 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
11890
12790
  side: "bottom",
11891
12791
  sideOffset: 4
11892
12792
  }, _$3(Item2, {
12793
+ className: "feed-menu-item",
12794
+ disabled: assignProjectDisabled,
12795
+ onSelect: () => onAssignProject()
12796
+ }, assignProjectDisabled ? "Moving…" : "Assign to project…"), _$3(Item2, {
11893
12797
  className: "feed-menu-item danger",
11894
12798
  disabled,
11895
12799
  onSelect: () => onForget()
@@ -11966,6 +12870,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
11966
12870
  const [selectedVisibility, setSelectedVisibility] = d$2(visibility === "shared" ? "shared" : "private");
11967
12871
  const [savingVisibility, setSavingVisibility] = d$2(false);
11968
12872
  const [deletingMemory, setDeletingMemory] = d$2(false);
12873
+ const [movingProject, setMovingProject] = d$2(false);
11969
12874
  const summarySections = summaryObj ? renderSummarySections(summaryObj) : [];
11970
12875
  y$2(() => {
11971
12876
  if (!observationData) return;
@@ -12026,6 +12931,47 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
12026
12931
  setSavingVisibility(false);
12027
12932
  }
12028
12933
  }
12934
+ async function moveProject() {
12935
+ const currentProject = String(item.project || "").trim();
12936
+ const initialValue = currentProject;
12937
+ const titleText = String(displayTitle || "this memory").trim();
12938
+ const truncatedTitle = titleText.length > 80 ? `${titleText.slice(0, 79).trimEnd()}…` : titleText;
12939
+ const description = currentProject ? `Move "${truncatedTitle}" from "${currentProject}" to another project. Pick an existing project or type a new name. Every memory in the same session will be reassigned together.` : `Assign a project to "${truncatedTitle}". Pick an existing project or type a new name. Every memory in the same session will be reassigned together.`;
12940
+ let suggestions = [];
12941
+ try {
12942
+ suggestions = (await loadProjects$1()).filter((p) => p && p !== currentProject);
12943
+ } catch {}
12944
+ const nextProject = await openSyncInputDialog({
12945
+ title: "Assign to project",
12946
+ description,
12947
+ initialValue,
12948
+ placeholder: "Pick one or type a new project name",
12949
+ suggestions,
12950
+ confirmLabel: "Move",
12951
+ cancelLabel: "Cancel",
12952
+ validate: (value) => {
12953
+ const trimmed = value.trim();
12954
+ if (!trimmed) return "Enter a project name.";
12955
+ if (trimmed === currentProject) return "Already assigned to this project.";
12956
+ return null;
12957
+ }
12958
+ });
12959
+ if (nextProject == null) return;
12960
+ const target = nextProject.trim();
12961
+ if (!target || target === currentProject) return;
12962
+ setMovingProject(true);
12963
+ try {
12964
+ const result = await moveMemoryProject(memoryId, target);
12965
+ const count = Number(result.moved_memory_count || 1);
12966
+ showGlobalNotice(count > 1 ? `Moved ${count} memories from this session to "${result.project}".` : `Moved to "${result.project}".`);
12967
+ await onReload();
12968
+ onViewRefresh();
12969
+ } catch (error) {
12970
+ showGlobalNotice(error instanceof Error ? error.message : "Failed to move memory.", "warning");
12971
+ } finally {
12972
+ setMovingProject(false);
12973
+ }
12974
+ }
12029
12975
  async function forgetMemory$1() {
12030
12976
  const titleText = String(displayTitle || "this memory").trim();
12031
12977
  if (!await openSyncConfirmDialog({
@@ -12071,7 +13017,9 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
12071
13017
  label: formatDate(createdAtRaw),
12072
13018
  side: "left"
12073
13019
  }, _$3("div", { className: "small feed-age" }, relative)), Boolean(item.owned_by_self) && memoryId > 0 ? _$3(FeedItemMenu, {
13020
+ assignProjectDisabled: movingProject,
12074
13021
  disabled: deletingMemory,
13022
+ onAssignProject: () => void moveProject(),
12075
13023
  onForget: () => void forgetMemory$1(),
12076
13024
  title: String(displayTitle || "memory")
12077
13025
  }) : null)), _$3("div", { className: "feed-provenance" }, _$3(ProvenanceChip, {
@@ -12677,15 +13625,17 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
12677
13625
  const pct = total && total > 0 ? ` (${Math.round(100 * current / total)}%)` : "";
12678
13626
  const progress = total && total > 0 ? `${current.toLocaleString()}/${total.toLocaleString()} ${unit}${pct}` : `${current.toLocaleString()} ${unit}`;
12679
13627
  const isFailed = job.status === "failed";
12680
- const detail = isFailed ? String(job.error || "unknown error").trim() : void 0;
13628
+ const isCompleted = job.status === "completed";
13629
+ const value = isFailed ? "Failed" : isCompleted ? "Complete" : progress;
13630
+ const detail = isFailed ? String(job.error || "unknown error").trim() : isCompleted ? progress : void 0;
12681
13631
  return buildHealthCard({
12682
13632
  key: String(job.kind || job.title || "background-maintenance"),
12683
13633
  label: String(job.title || job.kind || "Background maintenance"),
12684
- value: isFailed ? "Failed" : progress,
13634
+ value,
12685
13635
  detail,
12686
- icon: isFailed ? "alert-triangle" : "loader",
13636
+ icon: isFailed ? "alert-triangle" : isCompleted ? "check-circle" : "loader",
12687
13637
  className: isFailed ? "status-attention" : void 0,
12688
- title: isFailed ? `Error: ${job.error || "unknown"}` : `${String(job.title || "Maintenance")} in progress`
13638
+ title: isFailed ? `Error: ${job.error || "unknown"}` : isCompleted ? `${String(job.title || "Maintenance")} finished` : `${String(job.title || "Maintenance")} in progress`
12689
13639
  });
12690
13640
  });
12691
13641
  renderHealthCards(healthGrid, [
@@ -15053,22 +16003,16 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
15053
16003
  function isRecord(value) {
15054
16004
  return typeof value === "object" && value !== null;
15055
16005
  }
16006
+ function noPairingCommand(payloadText, hintText) {
16007
+ state.pairingCommandRaw = "";
16008
+ return {
16009
+ payloadText,
16010
+ hintText
16011
+ };
16012
+ }
15056
16013
  function pairingView(payload) {
15057
- if (!isRecord(payload)) {
15058
- state.pairingCommandRaw = "";
15059
- return {
15060
- payloadText: "Pairing not available",
15061
- hintText: "Enable sync and retry."
15062
- };
15063
- }
16014
+ if (!isRecord(payload)) return noPairingCommand("Pairing not available", "Enable sync and retry.");
15064
16015
  const pairingPayload = payload;
15065
- if (pairingPayload.redacted) {
15066
- state.pairingCommandRaw = "";
15067
- return {
15068
- payloadText: "Pairing payload hidden",
15069
- hintText: "Diagnostics are required to view the pairing payload."
15070
- };
15071
- }
15072
16016
  const safePayload = {
15073
16017
  ...pairingPayload,
15074
16018
  addresses: Array.isArray(pairingPayload.addresses) ? pairingPayload.addresses : []
@@ -15182,122 +16126,6 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
15182
16126
  if (hintMount) renderIntoSyncMount(hintMount, /* @__PURE__ */ u(PairingText, { text: view.hintText }));
15183
16127
  }
15184
16128
  //#endregion
15185
- //#region ../../node_modules/.pnpm/@radix-ui+react-collapsible@1.1.12_react-dom@19.2.4_react@19.2.4__react@19.2.4/node_modules/@radix-ui/react-collapsible/dist/index.mjs
15186
- var COLLAPSIBLE_NAME = "Collapsible";
15187
- var [createCollapsibleContext, createCollapsibleScope] = createContextScope(COLLAPSIBLE_NAME);
15188
- var [CollapsibleProvider, useCollapsibleContext] = createCollapsibleContext(COLLAPSIBLE_NAME);
15189
- var Collapsible = D((props, forwardedRef) => {
15190
- const { __scopeCollapsible, open: openProp, defaultOpen, disabled, onOpenChange, ...collapsibleProps } = props;
15191
- const [open, setOpen] = useControllableState({
15192
- prop: openProp,
15193
- defaultProp: defaultOpen ?? false,
15194
- onChange: onOpenChange,
15195
- caller: COLLAPSIBLE_NAME
15196
- });
15197
- return /* @__PURE__ */ u(CollapsibleProvider, {
15198
- scope: __scopeCollapsible,
15199
- disabled,
15200
- contentId: useId(),
15201
- open,
15202
- onOpenToggle: q$2(() => setOpen((prevOpen) => !prevOpen), [setOpen]),
15203
- children: /* @__PURE__ */ u(Primitive.div, {
15204
- "data-state": getState(open),
15205
- "data-disabled": disabled ? "" : void 0,
15206
- ...collapsibleProps,
15207
- ref: forwardedRef
15208
- })
15209
- });
15210
- });
15211
- Collapsible.displayName = COLLAPSIBLE_NAME;
15212
- var TRIGGER_NAME = "CollapsibleTrigger";
15213
- var CollapsibleTrigger = D((props, forwardedRef) => {
15214
- const { __scopeCollapsible, ...triggerProps } = props;
15215
- const context = useCollapsibleContext(TRIGGER_NAME, __scopeCollapsible);
15216
- return /* @__PURE__ */ u(Primitive.button, {
15217
- type: "button",
15218
- "aria-controls": context.contentId,
15219
- "aria-expanded": context.open || false,
15220
- "data-state": getState(context.open),
15221
- "data-disabled": context.disabled ? "" : void 0,
15222
- disabled: context.disabled,
15223
- ...triggerProps,
15224
- ref: forwardedRef,
15225
- onClick: composeEventHandlers(props.onClick, context.onOpenToggle)
15226
- });
15227
- });
15228
- CollapsibleTrigger.displayName = TRIGGER_NAME;
15229
- var CONTENT_NAME = "CollapsibleContent";
15230
- var CollapsibleContent = D((props, forwardedRef) => {
15231
- const { forceMount, ...contentProps } = props;
15232
- const context = useCollapsibleContext(CONTENT_NAME, props.__scopeCollapsible);
15233
- return /* @__PURE__ */ u(Presence, {
15234
- present: forceMount || context.open,
15235
- children: ({ present }) => /* @__PURE__ */ u(CollapsibleContentImpl, {
15236
- ...contentProps,
15237
- ref: forwardedRef,
15238
- present
15239
- })
15240
- });
15241
- });
15242
- CollapsibleContent.displayName = CONTENT_NAME;
15243
- var CollapsibleContentImpl = D((props, forwardedRef) => {
15244
- const { __scopeCollapsible, present, children, ...contentProps } = props;
15245
- const context = useCollapsibleContext(CONTENT_NAME, __scopeCollapsible);
15246
- const [isPresent, setIsPresent] = d$2(present);
15247
- const ref = A$1(null);
15248
- const composedRefs = useComposedRefs(forwardedRef, ref);
15249
- const heightRef = A$1(0);
15250
- const height = heightRef.current;
15251
- const widthRef = A$1(0);
15252
- const width = widthRef.current;
15253
- const isOpen = context.open || isPresent;
15254
- const isMountAnimationPreventedRef = A$1(isOpen);
15255
- const originalStylesRef = A$1(void 0);
15256
- y$2(() => {
15257
- const rAF = requestAnimationFrame(() => isMountAnimationPreventedRef.current = false);
15258
- return () => cancelAnimationFrame(rAF);
15259
- }, []);
15260
- useLayoutEffect2(() => {
15261
- const node = ref.current;
15262
- if (node) {
15263
- originalStylesRef.current = originalStylesRef.current || {
15264
- transitionDuration: node.style.transitionDuration,
15265
- animationName: node.style.animationName
15266
- };
15267
- node.style.transitionDuration = "0s";
15268
- node.style.animationName = "none";
15269
- const rect = node.getBoundingClientRect();
15270
- heightRef.current = rect.height;
15271
- widthRef.current = rect.width;
15272
- if (!isMountAnimationPreventedRef.current) {
15273
- node.style.transitionDuration = originalStylesRef.current.transitionDuration;
15274
- node.style.animationName = originalStylesRef.current.animationName;
15275
- }
15276
- setIsPresent(present);
15277
- }
15278
- }, [context.open, present]);
15279
- return /* @__PURE__ */ u(Primitive.div, {
15280
- "data-state": getState(context.open),
15281
- "data-disabled": context.disabled ? "" : void 0,
15282
- id: context.contentId,
15283
- hidden: !isOpen,
15284
- ...contentProps,
15285
- ref: composedRefs,
15286
- style: {
15287
- [`--radix-collapsible-content-height`]: height ? `${height}px` : void 0,
15288
- [`--radix-collapsible-content-width`]: width ? `${width}px` : void 0,
15289
- ...props.style
15290
- },
15291
- children: isOpen && children
15292
- });
15293
- });
15294
- function getState(open) {
15295
- return open ? "open" : "closed";
15296
- }
15297
- var Root = Collapsible;
15298
- var Trigger = CollapsibleTrigger;
15299
- var Content = CollapsibleContent;
15300
- //#endregion
15301
16129
  //#region src/tabs/sync/components/sync-disclosure.tsx
15302
16130
  function SyncDisclosure({ open, onOpenChange, triggerId, triggerClassName, closedLabel, openLabel, contentId, contentClassName, contentHost = null, children }) {
15303
16131
  const triggerRef = A$1(null);
@@ -15325,7 +16153,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
15325
16153
  (contentRef.current?.querySelector("button:not([disabled]), input:not([disabled]), textarea:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex=\"-1\"])"))?.focus();
15326
16154
  });
15327
16155
  }, [open]);
15328
- const content = /* @__PURE__ */ u(Content, {
16156
+ const content = /* @__PURE__ */ u(Content$2, {
15329
16157
  forceMount: true,
15330
16158
  asChild: true,
15331
16159
  children: /* @__PURE__ */ u("div", {
@@ -15336,10 +16164,10 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
15336
16164
  children
15337
16165
  })
15338
16166
  });
15339
- return /* @__PURE__ */ u(Root, {
16167
+ return /* @__PURE__ */ u(Root$3, {
15340
16168
  open,
15341
16169
  onOpenChange,
15342
- children: [/* @__PURE__ */ u(Trigger, {
16170
+ children: [/* @__PURE__ */ u(Trigger$4, {
15343
16171
  asChild: true,
15344
16172
  children: /* @__PURE__ */ u("button", {
15345
16173
  ref: triggerRef,
@@ -15812,12 +16640,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
15812
16640
  title: trustSummary?.state === "needs-repairing" ? `${name} needs re-pairing` : `${name} needs review`,
15813
16641
  summary: detail
15814
16642
  }));
15815
- } else if (device.peer && peerStatus === "offline") attentionItems.push(createRepairItem({
15816
- id: device.deviceId,
15817
- name,
15818
- title: `${name} is offline`,
15819
- summary: "This device is offline or unreachable right now. Retry later, or review the local record if it should have been available."
15820
- }));
16643
+ }
15821
16644
  if (device.peer && trustSummary?.state === "trusted-by-you") attentionItems.push(createReviewItem({
15822
16645
  id: device.deviceId,
15823
16646
  key: "other-device-trust",
@@ -15883,6 +16706,10 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
15883
16706
  function setTeamInvitePanelOpen(v) {
15884
16707
  teamInvitePanelOpen = v;
15885
16708
  }
16709
+ var teamJoinPanelOpen = false;
16710
+ function setTeamJoinPanelOpen(v) {
16711
+ teamJoinPanelOpen = v;
16712
+ }
15886
16713
  var openPeerScopeEditors = /* @__PURE__ */ new Set();
15887
16714
  var pendingPeerScopeReviewIds = /* @__PURE__ */ new Set();
15888
16715
  var freshPeerScopeReviewIds = /* @__PURE__ */ new Set();
@@ -15958,9 +16785,6 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
15958
16785
  const unique = Array.from(new Set(addresses.filter(Boolean)));
15959
16786
  return typeof unique[0] === "string" ? unique[0] : "";
15960
16787
  }
15961
- function parseScopeList(value) {
15962
- return value.split(",").map((item) => item.trim()).filter(Boolean);
15963
- }
15964
16788
  function actorLabel(actor) {
15965
16789
  if (!actor || typeof actor !== "object") return "Unknown person";
15966
16790
  const displayName = String(actor.display_name || "").trim();
@@ -16006,53 +16830,203 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
16006
16830
  if (!targetActorId || !target) return "Choose which person should keep these devices.";
16007
16831
  return `Merge into ${actorDisplayLabel(target)}. Assigned devices move now; existing memories keep their current provenance.`;
16008
16832
  }
16009
- function createChipEditor(initialValues, placeholder, emptyLabel) {
16833
+ function createChipEditor(initialValues, placeholder, emptyLabel, availableProjects = []) {
16010
16834
  let values = [...initialValues];
16011
- const container = el("div", "peer-scope-editor");
16012
- const chips = el("div", "peer-scope-chips");
16013
- const input = el("input", "peer-scope-input");
16014
- input.placeholder = placeholder;
16015
- const syncChips = () => {
16016
- chips.textContent = "";
16835
+ let query = "";
16836
+ let activeIndex = 0;
16837
+ let popoverOpen = false;
16838
+ const container = el("div", "project-scope-picker");
16839
+ const selectedList = el("ul", "project-scope-picker-selected");
16840
+ const trigger = el("button", "project-scope-picker-trigger settings-button");
16841
+ trigger.type = "button";
16842
+ const triggerLabel = el("span", null, placeholder || "Add project");
16843
+ const triggerPlus = el("span", null, "+");
16844
+ triggerPlus.setAttribute("aria-hidden", "true");
16845
+ trigger.append(triggerPlus, triggerLabel);
16846
+ trigger.setAttribute("aria-haspopup", "listbox");
16847
+ trigger.setAttribute("aria-expanded", "false");
16848
+ const popover = el("div", "project-scope-picker-popover project-scope-picker-popover--inline");
16849
+ popover.hidden = true;
16850
+ const search = el("input", "project-scope-picker-search");
16851
+ search.type = "text";
16852
+ search.placeholder = "Search or create…";
16853
+ search.setAttribute("aria-label", "Search projects");
16854
+ const results = el("div", "project-scope-picker-results");
16855
+ results.setAttribute("role", "listbox");
16856
+ popover.append(search, results);
16857
+ const knownPool = () => {
16858
+ const seen = /* @__PURE__ */ new Set();
16859
+ const out = [];
16860
+ for (const item of [...availableProjects, ...values]) {
16861
+ const trimmed = item.trim();
16862
+ if (!trimmed || seen.has(trimmed)) continue;
16863
+ seen.add(trimmed);
16864
+ out.push(trimmed);
16865
+ }
16866
+ return out.sort((a, b) => a.localeCompare(b));
16867
+ };
16868
+ const filteredRows = () => {
16869
+ const all = knownPool();
16870
+ const q = query.trim().toLowerCase();
16871
+ if (!q) return all;
16872
+ return all.filter((project) => project.toLowerCase().includes(q));
16873
+ };
16874
+ const shouldShowCreateRow = () => {
16875
+ const q = query.trim();
16876
+ if (!q) return false;
16877
+ return !knownPool().some((project) => project.toLowerCase() === q.toLowerCase());
16878
+ };
16879
+ const toggleValue = (project) => {
16880
+ if (values.includes(project)) values = values.filter((value) => value !== project);
16881
+ else values = Array.from(new Set([...values, project]));
16882
+ renderSelected();
16883
+ renderResults();
16884
+ };
16885
+ const createFromQuery = () => {
16886
+ const trimmed = query.trim();
16887
+ if (!trimmed) return;
16888
+ values = Array.from(new Set([...values, trimmed]));
16889
+ query = "";
16890
+ search.value = "";
16891
+ activeIndex = 0;
16892
+ renderSelected();
16893
+ renderResults();
16894
+ };
16895
+ const activateRow = (index) => {
16896
+ const rows = filteredRows();
16897
+ if (index < rows.length) {
16898
+ const project = rows[index];
16899
+ if (project) toggleValue(project);
16900
+ return;
16901
+ }
16902
+ if (shouldShowCreateRow()) createFromQuery();
16903
+ };
16904
+ const renderSelected = () => {
16905
+ selectedList.textContent = "";
16017
16906
  if (!values.length) {
16018
- chips.appendChild(el("span", "peer-scope-chip empty", emptyLabel));
16907
+ const note = el("li", "project-scope-picker-selected-empty", emptyLabel);
16908
+ selectedList.appendChild(note);
16019
16909
  return;
16020
16910
  }
16021
- values.forEach((value, index) => {
16022
- const chip = el("span", "peer-scope-chip");
16911
+ values.forEach((value) => {
16912
+ const chip = el("li", "project-scope-picker-selected-chip");
16023
16913
  const label = el("span", null, value);
16024
- const remove = el("button", "peer-scope-chip-remove", "x");
16914
+ const remove = el("button", "project-scope-picker-selected-remove", "×");
16025
16915
  remove.type = "button";
16026
16916
  remove.setAttribute("aria-label", `Remove ${value}`);
16027
16917
  remove.addEventListener("click", () => {
16028
- values = values.filter((_, currentIndex) => currentIndex !== index);
16029
- syncChips();
16918
+ values = values.filter((existing) => existing !== value);
16919
+ renderSelected();
16920
+ renderResults();
16030
16921
  });
16031
16922
  chip.append(label, remove);
16032
- chips.appendChild(chip);
16923
+ selectedList.appendChild(chip);
16924
+ });
16925
+ };
16926
+ const renderResults = () => {
16927
+ results.textContent = "";
16928
+ const rows = filteredRows();
16929
+ const withCreate = shouldShowCreateRow();
16930
+ const rowCount = rows.length + (withCreate ? 1 : 0);
16931
+ if (activeIndex >= rowCount) activeIndex = Math.max(0, rowCount - 1);
16932
+ if (!rows.length && !withCreate) {
16933
+ const empty = el("div", "project-scope-picker-empty-row", "No projects yet. Type a name to create one.");
16934
+ results.appendChild(empty);
16935
+ return;
16936
+ }
16937
+ rows.forEach((project, index) => {
16938
+ const selected = values.includes(project);
16939
+ const row = el("button", index === activeIndex ? "project-scope-picker-row project-scope-picker-row--active" : "project-scope-picker-row");
16940
+ row.type = "button";
16941
+ row.setAttribute("role", "option");
16942
+ row.setAttribute("aria-selected", selected ? "true" : "false");
16943
+ const check = el("span", "project-scope-picker-row-check", selected ? "✓" : "");
16944
+ check.setAttribute("aria-hidden", "true");
16945
+ const labelEl = el("span", "project-scope-picker-row-label", project);
16946
+ row.append(check, labelEl);
16947
+ row.addEventListener("click", () => {
16948
+ activeIndex = index;
16949
+ toggleValue(project);
16950
+ });
16951
+ row.addEventListener("mouseenter", () => {
16952
+ activeIndex = index;
16953
+ renderResults();
16954
+ });
16955
+ results.appendChild(row);
16033
16956
  });
16957
+ if (withCreate) {
16958
+ const index = rows.length;
16959
+ const row = el("button", index === activeIndex ? "project-scope-picker-row project-scope-picker-row--create project-scope-picker-row--active" : "project-scope-picker-row project-scope-picker-row--create");
16960
+ row.type = "button";
16961
+ row.setAttribute("role", "option");
16962
+ const check = el("span", "project-scope-picker-row-check", "+");
16963
+ check.setAttribute("aria-hidden", "true");
16964
+ const labelEl = el("span", "project-scope-picker-row-label", `Create "${query.trim()}"`);
16965
+ row.append(check, labelEl);
16966
+ row.addEventListener("click", () => createFromQuery());
16967
+ row.addEventListener("mouseenter", () => {
16968
+ activeIndex = index;
16969
+ renderResults();
16970
+ });
16971
+ results.appendChild(row);
16972
+ }
16034
16973
  };
16035
- const commitInput = () => {
16036
- const incoming = parseScopeList(input.value);
16037
- if (incoming.length) {
16038
- values = Array.from(new Set([...values, ...incoming]));
16039
- input.value = "";
16040
- syncChips();
16974
+ const setOpen = (next) => {
16975
+ popoverOpen = next;
16976
+ popover.hidden = !next;
16977
+ trigger.setAttribute("aria-expanded", next ? "true" : "false");
16978
+ if (next) {
16979
+ query = "";
16980
+ search.value = "";
16981
+ activeIndex = 0;
16982
+ renderResults();
16983
+ requestAnimationFrame(() => search.focus());
16041
16984
  }
16042
16985
  };
16043
- input.addEventListener("keydown", (event) => {
16044
- if (event.key === "Enter" || event.key === ",") {
16986
+ trigger.addEventListener("click", (event) => {
16987
+ event.stopPropagation();
16988
+ setOpen(!popoverOpen);
16989
+ });
16990
+ search.addEventListener("input", () => {
16991
+ query = search.value;
16992
+ activeIndex = 0;
16993
+ renderResults();
16994
+ });
16995
+ search.addEventListener("keydown", (event) => {
16996
+ const rowCount = filteredRows().length + (shouldShowCreateRow() ? 1 : 0);
16997
+ if (event.key === "ArrowDown") {
16998
+ event.preventDefault();
16999
+ activeIndex = Math.min(rowCount - 1, activeIndex + 1);
17000
+ renderResults();
17001
+ return;
17002
+ }
17003
+ if (event.key === "ArrowUp") {
16045
17004
  event.preventDefault();
16046
- commitInput();
17005
+ activeIndex = Math.max(0, activeIndex - 1);
17006
+ renderResults();
17007
+ return;
17008
+ }
17009
+ if (event.key === "Enter") {
17010
+ event.preventDefault();
17011
+ activateRow(activeIndex);
17012
+ return;
16047
17013
  }
16048
- if (event.key === "Backspace" && !input.value && values.length) {
16049
- values = values.slice(0, -1);
16050
- syncChips();
17014
+ if (event.key === "Escape") {
17015
+ event.preventDefault();
17016
+ setOpen(false);
16051
17017
  }
16052
17018
  });
16053
- input.addEventListener("blur", commitInput);
16054
- syncChips();
16055
- container.append(chips, input);
17019
+ const onDocumentClick = (event) => {
17020
+ if (!popoverOpen) return;
17021
+ const target = event.target;
17022
+ if (!target) return;
17023
+ if (container.contains(target)) return;
17024
+ setOpen(false);
17025
+ };
17026
+ document.addEventListener("click", onDocumentClick);
17027
+ container.append(selectedList, trigger, popover);
17028
+ renderSelected();
17029
+ renderResults();
16056
17030
  return {
16057
17031
  element: container,
16058
17032
  values: () => [...values]
@@ -16096,9 +17070,13 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
16096
17070
  const peerLabel = String(matchedPeer?.name || "").trim() || (peerId ? peerId.slice(0, 8) : "unknown");
16097
17071
  const isError = attempt.status === "error";
16098
17072
  const detailParts = [];
16099
- if (isError && attempt.error) detailParts.push(String(attempt.error));
17073
+ const redact = isSyncRedactionEnabled();
17074
+ if (isError && attempt.error) {
17075
+ const errText = String(attempt.error);
17076
+ detailParts.push(redact ? redactIpOctets(errText) : errText);
17077
+ }
16100
17078
  if (!isError && (attempt.ops_in || attempt.ops_out)) detailParts.push(`${attempt.ops_in ?? 0} in · ${attempt.ops_out ?? 0} out`);
16101
- if (!isSyncRedactionEnabled() && attempt.address) detailParts.push(attempt.address);
17079
+ if (!redact && attempt.address) detailParts.push(attempt.address);
16102
17080
  return {
16103
17081
  status: attempt.status || "unknown",
16104
17082
  peerLabel,
@@ -16303,7 +17281,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
16303
17281
  });
16304
17282
  const pairingCopy = document.getElementById("pairingCopy");
16305
17283
  if (pairingCopy) pairingCopy.onclick = async () => {
16306
- const text = state.pairingCommandRaw || document.getElementById("pairingPayload")?.textContent || "";
17284
+ const text = state.pairingCommandRaw;
16307
17285
  if (text) await copyToClipboard(text, pairingCopy);
16308
17286
  };
16309
17287
  }
@@ -16313,6 +17291,8 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
16313
17291
  const pairingHint = document.getElementById("pairingHint");
16314
17292
  if (!pairingPayloadEl) return;
16315
17293
  renderPairingView(pairingPayloadEl, pairingHint, pairingView(state.pairingPayloadRaw));
17294
+ const pairingCopy = document.getElementById("pairingCopy");
17295
+ if (pairingCopy) pairingCopy.disabled = !state.pairingCommandRaw;
16316
17296
  }
16317
17297
  function renderRedactControl() {
16318
17298
  const mount = document.getElementById(SYNC_REDACT_MOUNT_ID);
@@ -16630,6 +17610,24 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
16630
17610
  renderIntoSyncMount(input.meta, /* @__PURE__ */ u(LegacyClaimMeta, { devices }));
16631
17611
  }
16632
17612
  //#endregion
17613
+ //#region src/components/primitives/presence-pip.tsx
17614
+ var DEFAULT_LABEL = {
17615
+ online: "Online",
17616
+ offline: "Offline",
17617
+ degraded: "Degraded",
17618
+ attention: "Action required",
17619
+ syncing: "Syncing",
17620
+ unknown: "Status unknown"
17621
+ };
17622
+ function PresencePip({ state, size = 8, "aria-label": ariaLabel }) {
17623
+ return /* @__PURE__ */ u("span", {
17624
+ "aria-label": ariaLabel ?? DEFAULT_LABEL[state],
17625
+ className: `presence-pip presence-pip--${state}`,
17626
+ role: "img",
17627
+ style: `--presence-pip-size: ${size}px`
17628
+ });
17629
+ }
17630
+ //#endregion
16633
17631
  //#region src/tabs/sync/peer-scope-collapsible.tsx
16634
17632
  function PeerScopeCollapsible({ contentHost, initialOpen, onOpenChange, children }) {
16635
17633
  const [open, setOpen] = d$2(initialOpen);
@@ -16646,17 +17644,17 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
16646
17644
  (contentRef.current?.querySelector("button:not([disabled]), input:not([disabled]), textarea:not([disabled]), select:not([disabled]), [tabindex]:not([tabindex=\"-1\"])"))?.focus();
16647
17645
  });
16648
17646
  }, [open]);
16649
- return /* @__PURE__ */ u(Root, {
17647
+ return /* @__PURE__ */ u(Root$3, {
16650
17648
  open,
16651
17649
  onOpenChange: setOpen,
16652
- children: [/* @__PURE__ */ u(Trigger, {
17650
+ children: [/* @__PURE__ */ u(Trigger$4, {
16653
17651
  asChild: true,
16654
17652
  children: /* @__PURE__ */ u("button", {
16655
17653
  type: "button",
16656
17654
  className: "settings-button",
16657
17655
  children: open ? "Hide sharing scope" : "Show sharing scope"
16658
17656
  })
16659
- }), contentHost ? $$1(/* @__PURE__ */ u(Content, {
17657
+ }), contentHost ? $$1(/* @__PURE__ */ u(Content$2, {
16660
17658
  forceMount: true,
16661
17659
  ref: contentRef,
16662
17660
  className: `peer-scope-editor-wrap${open ? "" : " collapsed"}`,
@@ -16683,6 +17681,46 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
16683
17681
  }
16684
17682
  //#endregion
16685
17683
  //#region src/tabs/sync/components/sync-peers.tsx
17684
+ function ChevronRightIcon() {
17685
+ return /* @__PURE__ */ u("svg", {
17686
+ "aria-hidden": "true",
17687
+ fill: "none",
17688
+ stroke: "currentColor",
17689
+ "stroke-linecap": "round",
17690
+ "stroke-linejoin": "round",
17691
+ "stroke-width": "2",
17692
+ viewBox: "0 0 24 24",
17693
+ xmlns: "http://www.w3.org/2000/svg",
17694
+ children: [/* @__PURE__ */ u("title", { children: "Chevron" }), /* @__PURE__ */ u("path", { d: "m9 18 6-6-6-6" })]
17695
+ });
17696
+ }
17697
+ function presenceForPeer(peer) {
17698
+ switch (derivePeerUiStatus(peer)) {
17699
+ case "connected": return "online";
17700
+ case "offline": return "offline";
17701
+ case "needs-repair": return "attention";
17702
+ default: return "unknown";
17703
+ }
17704
+ }
17705
+ var expandedPeerId = null;
17706
+ var expandTickCounter = 0;
17707
+ var expandListeners = /* @__PURE__ */ new Set();
17708
+ function setExpandedPeer(peerId) {
17709
+ if (expandedPeerId === peerId) return;
17710
+ expandedPeerId = peerId;
17711
+ expandTickCounter += 1;
17712
+ for (const listener of expandListeners) listener(expandTickCounter);
17713
+ }
17714
+ function useExpandedPeer() {
17715
+ const [, setTick] = d$2(0);
17716
+ y$2(() => {
17717
+ expandListeners.add(setTick);
17718
+ return () => {
17719
+ expandListeners.delete(setTick);
17720
+ };
17721
+ }, []);
17722
+ return expandedPeerId;
17723
+ }
16686
17724
  var DIRECTION_GLYPH = {
16687
17725
  bidirectional: {
16688
17726
  glyph: "↕",
@@ -16724,9 +17762,6 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
16724
17762
  const scope = peer.project_scope || {};
16725
17763
  const includeList = listText(scope.include);
16726
17764
  const excludeList = listText(scope.exclude);
16727
- listText(scope.effective_include);
16728
- listText(scope.effective_exclude);
16729
- Boolean(scope.inherits_global);
16730
17765
  const primaryAddress = pickPrimaryAddress(peer.addresses);
16731
17766
  const peerAddresses = Array.isArray(peer.addresses) ? Array.from(new Set(peer.addresses.filter(Boolean).map((value) => String(value)))) : [];
16732
17767
  const addressLine = peerAddresses.length ? peerAddresses.map((address) => isSyncRedactionEnabled() ? redactAddress(address) : address).join(" · ") : "No addresses";
@@ -16767,8 +17802,16 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
16767
17802
  state.lastSyncPeers,
16768
17803
  state.lastSyncViewModel
16769
17804
  ]);
16770
- const includeEditor = T$1(() => createChipEditor(includeList, "Add included project", "All projects"), [peerId, includeList.join("|")]);
16771
- const excludeEditor = T$1(() => createChipEditor(excludeList, "Add excluded project", "No exclusions"), [peerId, excludeList.join("|")]);
17805
+ const includeEditor = T$1(() => createChipEditor(includeList, "Add project", "All projects", state.knownProjects), [
17806
+ peerId,
17807
+ includeList.join("|"),
17808
+ state.knownProjects.join("|")
17809
+ ]);
17810
+ const excludeEditor = T$1(() => createChipEditor(excludeList, "Add project", "No exclusions", state.knownProjects), [
17811
+ peerId,
17812
+ excludeList.join("|"),
17813
+ state.knownProjects.join("|")
17814
+ ]);
16772
17815
  y$2(() => {
16773
17816
  setRenameValue(displayName);
16774
17817
  setFeedback(state.syncPeerFeedbackById.get(peerId) ?? null);
@@ -16910,171 +17953,214 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
16910
17953
  setResetScopeBusy(false);
16911
17954
  }
16912
17955
  }
16913
- return /* @__PURE__ */ u("div", {
16914
- ref: cardRef,
16915
- className: "peer-card",
16916
- "data-peer-device-id": peerId || void 0,
16917
- children: [/* @__PURE__ */ u("div", {
16918
- className: "peer-title",
16919
- children: [/* @__PURE__ */ u("div", { children: [
16920
- /* @__PURE__ */ u("strong", {
16921
- title: peerId || void 0,
16922
- children: displayName
16923
- }),
16924
- directionHint ? /* @__PURE__ */ u("span", {
16925
- "aria-label": directionHint.label,
16926
- className: "peer-direction",
16927
- role: "img",
16928
- title: directionHint.label,
16929
- children: directionHint.glyph
16930
- }) : null,
16931
- /* @__PURE__ */ u("div", {
16932
- className: "peer-meta",
16933
- children: [/* @__PURE__ */ u("span", {
16934
- className: `badge ${trustSummary.isWarning ? "badge-offline" : "badge-online"}`,
16935
- children: trustSummary.badgeLabel
16936
- }), pendingScopeReview ? /* @__PURE__ */ u("span", {
16937
- className: "badge actor-badge",
16938
- children: "Needs scope review"
16939
- }) : null]
16940
- })
16941
- ] }), /* @__PURE__ */ u("div", {
16942
- className: "peer-actions",
16943
- children: [
16944
- /* @__PURE__ */ u("button", {
16945
- type: "button",
16946
- className: "settings-button",
16947
- disabled: !primaryAddress || syncBusy,
16948
- onClick: () => void sync(),
16949
- children: syncBusy ? "Syncing…" : "Sync now"
16950
- }),
16951
- /* @__PURE__ */ u("div", {
16952
- className: "sync-labeled-field",
16953
- children: [/* @__PURE__ */ u("label", {
16954
- className: "sync-labeled-field-caption",
16955
- htmlFor: `device-name-${peerId || "unknown"}`,
16956
- children: "Device name"
16957
- }), /* @__PURE__ */ u(TextInput, {
16958
- "aria-label": `Friendly name for ${displayName}`,
16959
- className: "peer-scope-input",
16960
- "data-device-name-input": peerId || void 0,
16961
- disabled: renameBusy,
16962
- id: `device-name-${peerId || "unknown"}`,
16963
- placeholder: "Friendly device name",
16964
- type: "text",
16965
- value: renameValue,
16966
- onInput: (event) => setRenameValue(event.currentTarget.value)
16967
- })]
16968
- }),
16969
- /* @__PURE__ */ u("button", {
16970
- type: "button",
16971
- className: "settings-button",
16972
- disabled: renameBusy,
16973
- onClick: () => void rename(),
16974
- children: renameLabel
16975
- }),
16976
- /* @__PURE__ */ u("button", {
16977
- type: "button",
16978
- className: "settings-button danger",
16979
- disabled: removeBusy,
16980
- onClick: () => void remove(),
16981
- children: removeLabel
16982
- })
16983
- ]
16984
- })]
16985
- }), /* @__PURE__ */ u("div", {
16986
- className: "peer-scope",
16987
- children: [
16988
- scopeReviewRequested ? /* @__PURE__ */ u("div", {
16989
- className: "peer-meta",
16990
- children: "Review this device's sharing rules now if the defaults are too broad."
16991
- }) : pendingScopeReview ? /* @__PURE__ */ u("div", {
16992
- className: "peer-meta",
16993
- children: "Sharing rule review is still pending for this device."
16994
- }) : null,
16995
- /* @__PURE__ */ u("div", {
16996
- className: "peer-scope-summary",
16997
- children: "Device details"
16998
- }),
16999
- /* @__PURE__ */ u("div", {
17000
- className: "peer-addresses",
17001
- children: addressLine
17002
- }),
17003
- /* @__PURE__ */ u("div", {
17004
- className: "peer-meta",
17005
- children: [lastSyncAt ? `Sync: ${formatTimestamp(lastSyncAt)}` : "Sync: never", lastPingAt ? `Ping: ${formatTimestamp(lastPingAt)}` : "Ping: never"].join(" · ")
17006
- }),
17007
- /* @__PURE__ */ u("div", {
17008
- className: "peer-scope-summary",
17009
- children: "Who this device belongs to"
17010
- }),
17011
- /* @__PURE__ */ u("div", {
17012
- className: "peer-meta",
17013
- children: assignmentSummary
17014
- }),
17015
- /* @__PURE__ */ u("div", {
17016
- className: "peer-actor-row",
17017
- children: [/* @__PURE__ */ u("div", {
17018
- className: "sync-radix-select-host sync-actor-select-host",
17019
- children: /* @__PURE__ */ u(RadixSelect, {
17020
- ariaLabel: `Assigned person for ${displayName}`,
17021
- contentClassName: "sync-radix-select-content sync-actor-select-content",
17022
- disabled: applyActorBusy,
17023
- itemClassName: "sync-radix-select-item",
17024
- onValueChange: setSelectedActorId,
17025
- options: actorSelectOptions,
17026
- placeholder: "No person assigned yet",
17027
- triggerClassName: "sync-radix-select-trigger sync-actor-select",
17028
- value: selectedActorId,
17029
- viewportClassName: "sync-radix-select-viewport"
17956
+ const isExpanded = useExpandedPeer() === peerId && peerId !== "";
17957
+ const drawerId = `device-drawer-${peerId || "unknown"}`;
17958
+ const presenceState = presenceForPeer(peer);
17959
+ const syncMetaText = lastSyncAt ? `Sync: ${formatTimestamp(lastSyncAt)}` : "Sync: never";
17960
+ const toggleLabel = `${isExpanded ? "Collapse" : "Expand"} device ${displayName}`;
17961
+ const handleOpenChange = (open) => {
17962
+ if (open) setExpandedPeer(peerId);
17963
+ else if (expandedPeerId === peerId) setExpandedPeer(null);
17964
+ };
17965
+ return /* @__PURE__ */ u(Root$3, {
17966
+ asChild: true,
17967
+ open: isExpanded,
17968
+ onOpenChange: handleOpenChange,
17969
+ children: /* @__PURE__ */ u("div", {
17970
+ ref: cardRef,
17971
+ className: "peer-card",
17972
+ "data-peer-device-id": peerId || void 0,
17973
+ children: [/* @__PURE__ */ u(Trigger$4, {
17974
+ asChild: true,
17975
+ children: /* @__PURE__ */ u("button", {
17976
+ "aria-label": toggleLabel,
17977
+ className: "device-row-head device-row-head--trigger",
17978
+ type: "button",
17979
+ children: [
17980
+ /* @__PURE__ */ u(PresencePip, { state: presenceState }),
17981
+ /* @__PURE__ */ u("span", {
17982
+ className: "device-row-name",
17983
+ title: peerId || void 0,
17984
+ children: displayName
17985
+ }),
17986
+ directionHint ? /* @__PURE__ */ u("span", {
17987
+ "aria-label": directionHint.label,
17988
+ className: "peer-direction",
17989
+ role: "img",
17990
+ title: directionHint.label,
17991
+ children: directionHint.glyph
17992
+ }) : null,
17993
+ /* @__PURE__ */ u("span", {
17994
+ className: "device-row-chips",
17995
+ children: [
17996
+ /* @__PURE__ */ u("span", {
17997
+ className: `badge ${trustSummary.isWarning ? "badge-offline" : "badge-online"}`,
17998
+ children: trustSummary.badgeLabel
17999
+ }),
18000
+ pendingScopeReview ? /* @__PURE__ */ u("span", {
18001
+ className: "badge actor-badge",
18002
+ children: "Needs scope review"
18003
+ }) : null,
18004
+ peer.discovered_via_group_id ? /* @__PURE__ */ u("span", {
18005
+ className: "badge actor-badge",
18006
+ title: `Discovered through coordinator group ${peer.discovered_via_group_id}`,
18007
+ children: `via ${peer.discovered_via_group_id}`
18008
+ }) : null
18009
+ ]
18010
+ }),
18011
+ /* @__PURE__ */ u("span", {
18012
+ className: "device-row-meta",
18013
+ children: syncMetaText
18014
+ }),
18015
+ /* @__PURE__ */ u("span", {
18016
+ "aria-hidden": "true",
18017
+ className: "device-row-chevron",
18018
+ children: /* @__PURE__ */ u(ChevronRightIcon, {})
17030
18019
  })
17031
- }), /* @__PURE__ */ u("button", {
17032
- type: "button",
17033
- className: "settings-button",
17034
- disabled: applyActorBusy,
17035
- onClick: () => void savePerson(),
17036
- children: applyActorLabel
17037
- })]
17038
- }),
17039
- /* @__PURE__ */ u("div", {
17040
- className: "peer-scope-summary",
17041
- children: "Advanced sharing scope"
17042
- }),
17043
- /* @__PURE__ */ u("div", {
17044
- className: "peer-meta",
17045
- children: "Review or tighten what this device can share when you need more than the global defaults."
17046
- }),
17047
- /* @__PURE__ */ u(PeerScopeCollapsible, {
17048
- contentHost: scopeHost,
17049
- initialOpen: scopeEditorOpen,
17050
- onOpenChange: (open) => {
17051
- if (open) openPeerScopeEditors.add(peerId);
17052
- else openPeerScopeEditors.delete(peerId);
17053
- },
17054
- children: /* @__PURE__ */ u("div", { children: [/* @__PURE__ */ u("div", {
17055
- className: "peer-scope-row",
17056
- children: [/* @__PURE__ */ u(ExistingElementSlot$1, { element: includeEditor.element }), /* @__PURE__ */ u(ExistingElementSlot$1, { element: excludeEditor.element })]
17057
- }), /* @__PURE__ */ u("div", {
17058
- className: "peer-scope-actions",
17059
- children: [/* @__PURE__ */ u("button", {
18020
+ ]
18021
+ })
18022
+ }), /* @__PURE__ */ u(Content$2, {
18023
+ "aria-label": `Device actions for ${displayName}`,
18024
+ className: "device-row-drawer",
18025
+ id: drawerId,
18026
+ children: [/* @__PURE__ */ u("div", {
18027
+ className: "peer-actions",
18028
+ children: [
18029
+ /* @__PURE__ */ u("button", {
17060
18030
  type: "button",
17061
18031
  className: "settings-button",
17062
- disabled: saveScopeBusy,
17063
- onClick: () => void saveScope(),
17064
- children: saveScopeLabel
17065
- }), /* @__PURE__ */ u("button", {
18032
+ disabled: !primaryAddress || syncBusy,
18033
+ onClick: () => void sync(),
18034
+ children: syncBusy ? "Syncing…" : "Sync now"
18035
+ }),
18036
+ /* @__PURE__ */ u("div", {
18037
+ className: "sync-labeled-field",
18038
+ children: [/* @__PURE__ */ u("label", {
18039
+ className: "sync-labeled-field-caption",
18040
+ htmlFor: `device-name-${peerId || "unknown"}`,
18041
+ children: "Device name"
18042
+ }), /* @__PURE__ */ u(TextInput, {
18043
+ "aria-label": `Friendly name for ${displayName}`,
18044
+ className: "peer-scope-input",
18045
+ "data-device-name-input": peerId || void 0,
18046
+ disabled: renameBusy,
18047
+ id: `device-name-${peerId || "unknown"}`,
18048
+ placeholder: "Friendly device name",
18049
+ type: "text",
18050
+ value: renameValue,
18051
+ onInput: (event) => setRenameValue(event.currentTarget.value)
18052
+ })]
18053
+ }),
18054
+ /* @__PURE__ */ u("button", {
17066
18055
  type: "button",
17067
18056
  className: "settings-button",
17068
- disabled: resetScopeBusy,
17069
- onClick: () => void resetScope(),
17070
- children: resetScopeLabel
17071
- })]
17072
- })] })
17073
- }),
17074
- /* @__PURE__ */ u(SyncInlineFeedback, { feedback }),
17075
- /* @__PURE__ */ u("div", { ref: setScopeHost })
17076
- ]
17077
- })]
18057
+ disabled: renameBusy,
18058
+ onClick: () => void rename(),
18059
+ children: renameLabel
18060
+ }),
18061
+ /* @__PURE__ */ u("button", {
18062
+ type: "button",
18063
+ className: "settings-button danger",
18064
+ disabled: removeBusy,
18065
+ onClick: () => void remove(),
18066
+ children: removeLabel
18067
+ })
18068
+ ]
18069
+ }), /* @__PURE__ */ u("div", {
18070
+ className: "peer-scope",
18071
+ children: [
18072
+ scopeReviewRequested ? /* @__PURE__ */ u("div", {
18073
+ className: "peer-meta",
18074
+ children: "Review this device's sharing rules now if the defaults are too broad."
18075
+ }) : pendingScopeReview ? /* @__PURE__ */ u("div", {
18076
+ className: "peer-meta",
18077
+ children: "Sharing rule review is still pending for this device."
18078
+ }) : null,
18079
+ /* @__PURE__ */ u("div", {
18080
+ className: "peer-scope-summary",
18081
+ children: "Device details"
18082
+ }),
18083
+ /* @__PURE__ */ u("div", {
18084
+ className: "peer-addresses",
18085
+ children: addressLine
18086
+ }),
18087
+ /* @__PURE__ */ u("div", {
18088
+ className: "peer-meta",
18089
+ children: [lastSyncAt ? `Sync: ${formatTimestamp(lastSyncAt)}` : "Sync: never", lastPingAt ? `Ping: ${formatTimestamp(lastPingAt)}` : "Ping: never"].join(" · ")
18090
+ }),
18091
+ /* @__PURE__ */ u("div", {
18092
+ className: "peer-scope-summary",
18093
+ children: "Who this device belongs to"
18094
+ }),
18095
+ /* @__PURE__ */ u("div", {
18096
+ className: "peer-meta",
18097
+ children: assignmentSummary
18098
+ }),
18099
+ /* @__PURE__ */ u("div", {
18100
+ className: "peer-actor-row",
18101
+ children: [/* @__PURE__ */ u("div", {
18102
+ className: "sync-radix-select-host sync-actor-select-host",
18103
+ children: /* @__PURE__ */ u(RadixSelect, {
18104
+ ariaLabel: `Assigned person for ${displayName}`,
18105
+ contentClassName: "sync-radix-select-content sync-actor-select-content",
18106
+ disabled: applyActorBusy,
18107
+ itemClassName: "sync-radix-select-item",
18108
+ onValueChange: setSelectedActorId,
18109
+ options: actorSelectOptions,
18110
+ placeholder: "No person assigned yet",
18111
+ triggerClassName: "sync-radix-select-trigger sync-actor-select",
18112
+ value: selectedActorId,
18113
+ viewportClassName: "sync-radix-select-viewport"
18114
+ })
18115
+ }), /* @__PURE__ */ u("button", {
18116
+ type: "button",
18117
+ className: "settings-button",
18118
+ disabled: applyActorBusy,
18119
+ onClick: () => void savePerson(),
18120
+ children: applyActorLabel
18121
+ })]
18122
+ }),
18123
+ /* @__PURE__ */ u("div", {
18124
+ className: "peer-scope-summary",
18125
+ children: "Advanced sharing scope"
18126
+ }),
18127
+ /* @__PURE__ */ u("div", {
18128
+ className: "peer-meta",
18129
+ children: "Review or tighten what this device can share when you need more than the global defaults."
18130
+ }),
18131
+ /* @__PURE__ */ u(PeerScopeCollapsible, {
18132
+ contentHost: scopeHost,
18133
+ initialOpen: scopeEditorOpen,
18134
+ onOpenChange: (open) => {
18135
+ if (open) openPeerScopeEditors.add(peerId);
18136
+ else openPeerScopeEditors.delete(peerId);
18137
+ },
18138
+ children: /* @__PURE__ */ u("div", { children: [/* @__PURE__ */ u("div", {
18139
+ className: "peer-scope-row",
18140
+ children: [/* @__PURE__ */ u(ExistingElementSlot$1, { element: includeEditor.element }), /* @__PURE__ */ u(ExistingElementSlot$1, { element: excludeEditor.element })]
18141
+ }), /* @__PURE__ */ u("div", {
18142
+ className: "peer-scope-actions",
18143
+ children: [/* @__PURE__ */ u("button", {
18144
+ type: "button",
18145
+ className: "settings-button",
18146
+ disabled: saveScopeBusy,
18147
+ onClick: () => void saveScope(),
18148
+ children: saveScopeLabel
18149
+ }), /* @__PURE__ */ u("button", {
18150
+ type: "button",
18151
+ className: "settings-button",
18152
+ disabled: resetScopeBusy,
18153
+ onClick: () => void resetScope(),
18154
+ children: resetScopeLabel
18155
+ })]
18156
+ })] })
18157
+ }),
18158
+ /* @__PURE__ */ u(SyncInlineFeedback, { feedback }),
18159
+ /* @__PURE__ */ u("div", { ref: setScopeHost })
18160
+ ]
18161
+ })]
18162
+ })]
18163
+ })
17078
18164
  });
17079
18165
  }
17080
18166
  function SyncPeersList(props) {
@@ -17082,8 +18168,8 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
17082
18168
  const syncStatus = state.lastSyncStatus;
17083
18169
  const syncDisabled = syncStatus?.daemon_state === "disabled" || syncStatus?.enabled === false;
17084
18170
  if (!props.peers.length) return /* @__PURE__ */ u(k$3, { children: [/* @__PURE__ */ u(SyncInlineFeedback, { feedback: sectionFeedback }), /* @__PURE__ */ u(SyncEmptyState, {
17085
- detail: syncDisabled ? "Turn on sync in Settings → Device Sync first, then use Show pairing command under Connect another device to connect another device." : "Use Show pairing command under Connect another device, run the command on the other device, then come back here to name it and decide who it belongs to.",
17086
- title: "No devices connected here yet."
18171
+ detail: syncDisabled ? "Turn on sync in Settings → Device Sync first. Then use Invite a teammate or Paste an invite above to connect another device." : "Use Invite a teammate above to share a join code, or Paste an invite to enroll this device on an existing team.",
18172
+ title: "No teammates yet"
17087
18173
  })] });
17088
18174
  return /* @__PURE__ */ u(k$3, { children: [/* @__PURE__ */ u(SyncInlineFeedback, { feedback: sectionFeedback }), props.peers.map((peer) => {
17089
18175
  const peerId = String(peer.peer_device_id || peer.name || "unknown-peer");
@@ -17378,6 +18464,31 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
17378
18464
  });
17379
18465
  }
17380
18466
  //#endregion
18467
+ //#region src/tabs/sync/sync-view-controller.ts
18468
+ function getSyncSubView() {
18469
+ return window.location.hash.replace(/^#/, "") === "sync/diagnostics" ? "diagnostics" : "main";
18470
+ }
18471
+ function applySyncSubView(view = getSyncSubView()) {
18472
+ const main = document.getElementById("syncMainView");
18473
+ const diag = document.getElementById("syncDiagnosticsView");
18474
+ if (!main || !diag) return;
18475
+ if (view === "diagnostics") {
18476
+ main.hidden = true;
18477
+ diag.hidden = false;
18478
+ } else {
18479
+ main.hidden = false;
18480
+ diag.hidden = true;
18481
+ }
18482
+ }
18483
+ var listenerAttached = false;
18484
+ function ensureSyncSubViewListener() {
18485
+ if (listenerAttached) return;
18486
+ listenerAttached = true;
18487
+ window.addEventListener("hashchange", () => {
18488
+ applySyncSubView();
18489
+ });
18490
+ }
18491
+ //#endregion
17381
18492
  //#region src/tabs/sync/team-sync/data/state.ts
17382
18493
  var teamSyncState = {
17383
18494
  invitePolicy: "auto_admit",
@@ -17529,16 +18640,24 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
17529
18640
  if (!syncJoinButton || !syncJoinInvite) return;
17530
18641
  const inviteValue = syncJoinInvite.value.trim();
17531
18642
  if (!inviteValue) {
17532
- markFieldError(syncJoinInvite, "Paste a team invite to join.");
18643
+ markFieldError(syncJoinInvite, "Paste a team invite or pairing payload.");
17533
18644
  return;
17534
18645
  }
17535
18646
  clearFieldError(syncJoinInvite);
17536
18647
  syncJoinButton.disabled = true;
17537
- syncJoinButton.textContent = "Joining…";
18648
+ syncJoinButton.textContent = "Accepting…";
17538
18649
  try {
17539
18650
  const result = await importCoordinatorInvite(inviteValue);
17540
18651
  state.lastTeamJoin = result;
17541
- let feedback = {
18652
+ const resultType = typeof result.type === "string" ? result.type : "team_join";
18653
+ let feedback;
18654
+ if (resultType === "pair") {
18655
+ const peerId = String(result.peer_device_id ?? "").trim();
18656
+ feedback = {
18657
+ message: peerId ? `Paired with device ${peerId.slice(0, 8)}. It will appear in People & devices.` : "Paired the device. It will appear in People & devices.",
18658
+ tone: "success"
18659
+ };
18660
+ } else feedback = {
17542
18661
  message: result.status === "pending" ? "Join request sent. Waiting for admin approval." : "Joined the team.",
17543
18662
  tone: "success"
17544
18663
  };
@@ -17549,7 +18668,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
17549
18668
  await loadSyncData();
17550
18669
  } catch (error) {
17551
18670
  feedback = {
17552
- message: friendlyError(error, "Joined the team, but this view has not refreshed yet."),
18671
+ message: friendlyError(error, "Accepted the invite, but this view has not refreshed yet."),
17553
18672
  tone: "warning"
17554
18673
  };
17555
18674
  state.syncJoinFlowFeedback = feedback;
@@ -17557,7 +18676,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
17557
18676
  }
17558
18677
  } catch (error) {
17559
18678
  state.syncJoinFlowFeedback = {
17560
- message: friendlyError(error, "Failed to import invite. Check that the invite is complete, current, and meant for this team, then try again."),
18679
+ message: friendlyError(error, "Failed to accept. Check that the invite or pairing payload is complete and current, then try again."),
17561
18680
  tone: "warning"
17562
18681
  };
17563
18682
  setJoinFeedbackVisibility();
@@ -17567,7 +18686,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
17567
18686
  } finally {
17568
18687
  if (syncJoinButton.disabled) {
17569
18688
  syncJoinButton.disabled = false;
17570
- syncJoinButton.textContent = "Join team";
18689
+ syncJoinButton.textContent = "Accept";
17571
18690
  }
17572
18691
  }
17573
18692
  });
@@ -17646,16 +18765,38 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
17646
18765
  })]
17647
18766
  });
17648
18767
  }
17649
- function SyncInviteJoinPanels({ invitePanel, invitePanelOpen, inviteRestoreParent, joinPanel, joinRestoreParent, onToggleInvitePanel, pairedPeerCount, presenceStatus }) {
18768
+ function JoinToggleRow({ joinPanel, joinPanelOpen, joinRestoreParent, onToggle }) {
18769
+ return /* @__PURE__ */ u(k$3, { children: [/* @__PURE__ */ u("div", {
18770
+ className: "sync-action",
18771
+ children: [/* @__PURE__ */ u("div", {
18772
+ className: "sync-action-text",
18773
+ children: ["Accept an invite or pairing.", /* @__PURE__ */ u("span", {
18774
+ className: "sync-action-command",
18775
+ children: "Paste a team invite to join another team, or a pairing payload to connect another device."
18776
+ })]
18777
+ }), /* @__PURE__ */ u("button", {
18778
+ type: "button",
18779
+ className: "settings-button",
18780
+ onClick: onToggle,
18781
+ children: joinPanelOpen ? "Hide paste form" : "Paste invite or pairing"
18782
+ })]
18783
+ }), joinPanel ? /* @__PURE__ */ u(ExistingElementSlot, {
18784
+ element: joinPanel,
18785
+ hidden: !joinPanelOpen,
18786
+ restoreParent: joinRestoreParent
18787
+ }) : null] });
18788
+ }
18789
+ function SyncInviteJoinPanels({ invitePanel, invitePanelOpen, inviteRestoreParent, joinPanel, joinPanelOpen, joinRestoreParent, onToggleInvitePanel, onToggleJoinPanel, pairedPeerCount, presenceStatus }) {
18790
+ const notEnrolled = presenceStatus === "not_enrolled";
17650
18791
  return /* @__PURE__ */ u(k$3, { children: [
17651
- presenceStatus === "not_enrolled" ? /* @__PURE__ */ u(k$3, { children: [
18792
+ notEnrolled ? /* @__PURE__ */ u(k$3, { children: [
17652
18793
  /* @__PURE__ */ u("div", {
17653
18794
  className: "sync-action",
17654
18795
  children: /* @__PURE__ */ u("div", {
17655
18796
  className: "sync-action-text",
17656
18797
  children: ["Join this device.", /* @__PURE__ */ u("span", {
17657
18798
  className: "sync-action-command",
17658
- children: "Paste an invite for this device below to join an existing team."
18799
+ children: "Paste a team invite or pairing payload below to join an existing team or connect another of your devices."
17659
18800
  })]
17660
18801
  })
17661
18802
  }),
@@ -17679,8 +18820,17 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
17679
18820
  })]
17680
18821
  })
17681
18822
  })
17682
- ] }) : null,
17683
- presenceStatus !== "not_enrolled" ? /* @__PURE__ */ u(InviteToggleRow, {
18823
+ ] }) : /* @__PURE__ */ u(k$3, { children: [/* @__PURE__ */ u(JoinToggleRow, {
18824
+ joinPanel,
18825
+ joinPanelOpen,
18826
+ joinRestoreParent,
18827
+ onToggle: onToggleJoinPanel
18828
+ }), /* @__PURE__ */ u("div", {
18829
+ className: "peer-meta",
18830
+ id: "syncJoinFeedback",
18831
+ hidden: true
18832
+ })] }),
18833
+ !notEnrolled ? /* @__PURE__ */ u(InviteToggleRow, {
17684
18834
  invitePanel,
17685
18835
  invitePanelOpen,
17686
18836
  inviteRestoreParent,
@@ -17798,41 +18948,40 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
17798
18948
  function DiscoveredDeviceRow({ row, onInspectConflict, onRemoveConflict, onReview }) {
17799
18949
  const [busy, setBusy] = d$2(null);
17800
18950
  const [feedback, setFeedback] = d$2(null);
17801
- const [reviewLabel, setReviewLabel] = d$2(row.actionLabel || "Review device");
18951
+ const defaultReviewLabel = row.actionLabel || "Pair with this device";
18952
+ const [reviewLabel, setReviewLabel] = d$2(defaultReviewLabel);
17802
18953
  const [removeLabel, setRemoveLabel] = d$2("Remove broken device record");
17803
18954
  return /* @__PURE__ */ u("div", {
17804
- className: "actor-row",
18955
+ className: "peer-card peer-card--padded",
17805
18956
  "data-discovered-device-id": row.deviceId,
17806
18957
  children: [
17807
18958
  /* @__PURE__ */ u("div", {
17808
- className: "actor-details",
17809
- children: [/* @__PURE__ */ u("div", {
17810
- className: "actor-title",
17811
- children: [
17812
- /* @__PURE__ */ u("strong", {
17813
- title: row.displayTitle || void 0,
17814
- children: row.displayName
17815
- }),
17816
- /* @__PURE__ */ u("span", {
17817
- className: `badge actor-badge${row.availabilityLabel === "Offline" ? "" : " local"}`,
17818
- children: row.availabilityLabel
17819
- }),
17820
- /* @__PURE__ */ u("span", {
17821
- className: "badge actor-badge",
17822
- children: row.connectionLabel
17823
- }),
17824
- row.approvalBadgeLabel ? /* @__PURE__ */ u("span", {
17825
- className: "badge actor-badge",
17826
- children: row.approvalBadgeLabel
17827
- }) : null
17828
- ]
17829
- }), /* @__PURE__ */ u("div", {
17830
- className: "peer-meta",
17831
- children: row.note
17832
- })]
18959
+ className: "peer-title",
18960
+ children: [
18961
+ /* @__PURE__ */ u("strong", {
18962
+ title: row.displayTitle || void 0,
18963
+ children: row.displayName
18964
+ }),
18965
+ /* @__PURE__ */ u("span", {
18966
+ className: `badge actor-badge${row.availabilityLabel === "Offline" ? "" : " local"}`,
18967
+ children: row.availabilityLabel
18968
+ }),
18969
+ /* @__PURE__ */ u("span", {
18970
+ className: "badge actor-badge",
18971
+ children: row.connectionLabel
18972
+ }),
18973
+ row.approvalBadgeLabel ? /* @__PURE__ */ u("span", {
18974
+ className: "badge actor-badge",
18975
+ children: row.approvalBadgeLabel
18976
+ }) : null
18977
+ ]
17833
18978
  }),
17834
18979
  /* @__PURE__ */ u("div", {
17835
- className: "actor-actions",
18980
+ className: "peer-meta",
18981
+ children: row.note
18982
+ }),
18983
+ /* @__PURE__ */ u("div", {
18984
+ className: "peer-actions",
17836
18985
  children: [
17837
18986
  row.mode === "accept" ? /* @__PURE__ */ u("button", {
17838
18987
  type: "button",
@@ -17841,10 +18990,10 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
17841
18990
  disabled: busy !== null,
17842
18991
  onClick: async () => {
17843
18992
  setBusy("review");
17844
- setReviewLabel("Reviewing…");
18993
+ setReviewLabel("Pairing…");
17845
18994
  try {
17846
18995
  setFeedback(await onReview(row) || null);
17847
- setReviewLabel(row.actionLabel || "Review device");
18996
+ setReviewLabel(row.actionLabel || defaultReviewLabel);
17848
18997
  } catch {
17849
18998
  setReviewLabel("Retry");
17850
18999
  } finally {
@@ -17870,7 +19019,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
17870
19019
  children: "Open device details"
17871
19020
  }), /* @__PURE__ */ u("button", {
17872
19021
  type: "button",
17873
- className: "settings-button",
19022
+ className: "settings-button danger",
17874
19023
  "aria-label": `${removeLabel} for ${row.displayName}`,
17875
19024
  disabled: busy !== null,
17876
19025
  onClick: async () => {
@@ -17938,36 +19087,6 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
17938
19087
  children
17939
19088
  ] });
17940
19089
  }
17941
- function TeamStatusPortal({ mount, statusSummary }) {
17942
- return $$1(/* @__PURE__ */ u("div", {
17943
- className: "sync-team-summary",
17944
- children: [
17945
- /* @__PURE__ */ u(SectionHeading, { label: "Overview" }),
17946
- /* @__PURE__ */ u("div", {
17947
- className: "sync-team-status-row",
17948
- children: [/* @__PURE__ */ u("span", {
17949
- className: "sync-team-status-label",
17950
- children: "Current status"
17951
- }), /* @__PURE__ */ u("span", {
17952
- className: statusSummary.badgeClassName,
17953
- children: statusSummary.presenceLabel
17954
- })]
17955
- }),
17956
- statusSummary.headline ? /* @__PURE__ */ u("div", {
17957
- className: "sync-team-headline",
17958
- children: statusSummary.headline
17959
- }) : null,
17960
- statusSummary.detail ? /* @__PURE__ */ u("div", {
17961
- className: "section-meta",
17962
- children: statusSummary.detail
17963
- }) : null,
17964
- /* @__PURE__ */ u("div", {
17965
- className: "sync-team-metrics sync-team-metrics-secondary",
17966
- children: statusSummary.metricsText
17967
- })
17968
- ]
17969
- }), mount);
17970
- }
17971
19090
  function DiscoveredPortal({ mount, rows, onInspectConflict, onRemoveConflict, onReview }) {
17972
19091
  if (!mount || !rows.length && !state.syncDiscoveredFeedback) return null;
17973
19092
  return $$1(/* @__PURE__ */ u(k$3, { children: [
@@ -18005,10 +19124,6 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
18005
19124
  return /* @__PURE__ */ u(k$3, { children: [
18006
19125
  /* @__PURE__ */ u(ActionContent, { ...props }),
18007
19126
  /* @__PURE__ */ u(TeamActionsContent, { children: props.children }),
18008
- /* @__PURE__ */ u(TeamStatusPortal, {
18009
- mount: props.listMount,
18010
- statusSummary: props.statusSummary
18011
- }),
18012
19127
  /* @__PURE__ */ u(PendingRequestsPortal, {
18013
19128
  mount: props.joinRequestsMount,
18014
19129
  requests: props.pendingJoinRequests,
@@ -18078,10 +19193,8 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
18078
19193
  function renderTeamSync() {
18079
19194
  const meta = document.getElementById("syncTeamMeta");
18080
19195
  const setupPanel = document.getElementById("syncSetupPanel");
18081
- const list = document.getElementById("syncTeamStatus");
18082
- const listHeading = list?.previousElementSibling;
18083
19196
  const actions = document.getElementById("syncTeamActions");
18084
- if (!meta || !setupPanel || !list || !actions) return;
19197
+ if (!meta || !setupPanel || !actions) return;
18085
19198
  renderAdminSetupDisclosure();
18086
19199
  renderInvitePolicySelect();
18087
19200
  setInviteOutputVisibility();
@@ -18195,13 +19308,13 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
18195
19308
  };
18196
19309
  const reviewDiscoveredDeviceName = async (suggestedName) => {
18197
19310
  return await openSyncInputDialog({
18198
- title: "Review device",
18199
- description: "Choose a friendly name for this device before connecting it on this machine.",
19311
+ title: "Pair with this device",
19312
+ description: "Choose a friendly name for this device before pairing it on this machine.",
18200
19313
  initialValue: suggestedName,
18201
19314
  placeholder: "Desk Mini",
18202
- confirmLabel: "Connect device",
19315
+ confirmLabel: "Pair",
18203
19316
  cancelLabel: "Cancel",
18204
- validate: (nextValue) => nextValue.trim() ? null : "Enter a device name to connect this device."
19317
+ validate: (nextValue) => nextValue.trim() ? null : "Enter a device name to pair this device."
18205
19318
  });
18206
19319
  };
18207
19320
  const configured = Boolean(coordinator?.configured);
@@ -18210,32 +19323,18 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
18210
19323
  const onlineBadge = document.getElementById("syncOnlineBadge");
18211
19324
  if (onlineBadge) updateSyncOnlineBadge(onlineBadge, configured, String(coordinator?.presence_status || ""));
18212
19325
  if (!configured) {
18213
- teardownTeamSyncRender(actions, [
18214
- list,
18215
- joinRequests,
18216
- discoveredList
18217
- ]);
19326
+ teardownTeamSyncRender(actions, [joinRequests, discoveredList]);
18218
19327
  setupPanel.hidden = false;
18219
- list.hidden = true;
18220
- if (listHeading) listHeading.hidden = true;
18221
19328
  actions.hidden = true;
18222
19329
  if (joinRequests) joinRequests.hidden = true;
18223
19330
  if (discoveredPanel) discoveredPanel.hidden = true;
18224
19331
  return;
18225
19332
  }
18226
19333
  setupPanel.hidden = true;
18227
- list.hidden = false;
18228
- if (listHeading) listHeading.hidden = false;
18229
19334
  actions.hidden = false;
18230
19335
  const presenceStatus = String(coordinator.presence_status || "");
18231
- const presenceLabel = presenceStatus === "posted" ? "Connected" : presenceStatus === "not_enrolled" ? "Needs enrollment" : "Connection error";
18232
19336
  const localPeers = Array.isArray(state.lastSyncPeers) ? state.lastSyncPeers : [];
18233
19337
  const attentionItems = Array.isArray(syncView.attentionItems) ? syncView.attentionItems : [];
18234
- const connectedCount = Number(syncView.summary?.connectedDeviceCount || 0);
18235
- const seenOnTeamCount = Number(syncView.summary?.seenOnTeamCount || 0);
18236
- const offlineTeamDeviceCount = Number(syncView.summary?.offlineTeamDeviceCount || 0);
18237
- const metricParts = [`Connected ${connectedCount}`, `Team ${seenOnTeamCount}`];
18238
- if (offlineTeamDeviceCount > 0) metricParts.push(`Offline ${offlineTeamDeviceCount}`);
18239
19338
  const discoveredRows = (Array.isArray(coordinator.discovered_devices) ? coordinator.discovered_devices : []).map((device) => {
18240
19339
  const deviceId = String(device.device_id || "").trim();
18241
19340
  const displayName = resolveFriendlyDeviceName({
@@ -18283,7 +19382,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
18283
19382
  if (mode === "paired") pairedMessage = approvalSummary.state === "waiting-for-other-device" ? approvalSummary.description || "Waiting on the other device." : String(pairedPeer?.last_error || "").toLowerCase().includes("401") && String(pairedPeer?.last_error || "").toLowerCase().includes("unauthorized") ? "Waiting for the other device to trust this one before sync can work." : null;
18284
19383
  return {
18285
19384
  actionMessage,
18286
- actionLabel: approvalSummary.actionLabel || "Review device",
19385
+ actionLabel: approvalSummary.actionLabel || (pairedPeer ? "Review device" : "Pair with this device"),
18287
19386
  approvalBadgeLabel: approvalSummary.badgeLabel,
18288
19387
  availabilityLabel: device.stale ? "Offline" : "Available",
18289
19388
  connectionLabel: hasConflict ? SYNC_TERMINOLOGY.conflicts : pairedPeer ? SYNC_TERMINOLOGY.pairedLocally : "Not connected on this device",
@@ -18300,37 +19399,12 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
18300
19399
  const visibleDiscoveredRows = discoveredRows.filter((row) => row.mode !== "paired" && row.mode !== "none" && row.mode !== "scope-pending");
18301
19400
  const discoveredActionableCount = discoveredRows.filter((row) => row.mode === "accept" || row.mode === "scope-pending").length;
18302
19401
  const actionableCount = attentionItems.length + pendingJoinRequests.length + discoveredActionableCount;
18303
- const attentionParts = [];
18304
- if (attentionItems.length > 0) {
18305
- const repairItems = attentionItems.filter((item) => item.kind === "device-needs-repair");
18306
- const nameItems = attentionItems.filter((item) => item.kind === "name-device");
18307
- const reviewItems = attentionItems.filter((item) => item.kind === "review-team-device");
18308
- const duplicateItems = attentionItems.filter((item) => item.kind === "possible-duplicate-person");
18309
- if (repairItems.length > 0) attentionParts.push(`${repairItems.length} device issue${repairItems.length === 1 ? "" : "s"} to review`);
18310
- if (nameItems.length > 0) attentionParts.push(`${nameItems.length} device${nameItems.length === 1 ? "" : "s"} to name`);
18311
- if (reviewItems.length > 0) attentionParts.push(`${reviewItems.length} device${reviewItems.length === 1 ? "" : "s"} to review`);
18312
- if (duplicateItems.length > 0) attentionParts.push(`${duplicateItems.length} possible duplicate${duplicateItems.length === 1 ? "" : "s"}`);
18313
- }
18314
- if (pendingJoinRequests.length > 0) attentionParts.push(`${pendingJoinRequests.length} join request${pendingJoinRequests.length === 1 ? "" : "s"} to review`);
18315
- if (discoveredActionableCount > 0) attentionParts.push(`${discoveredActionableCount} discovered device${discoveredActionableCount === 1 ? "" : "s"}`);
18316
- const attentionDetail = attentionParts.join(", ");
18317
19402
  const teamLabel = (coordinator.groups || []).join(", ") || "none";
18318
- const statusSummary = {
18319
- badgeClassName: `pill ${presenceStatus === "posted" ? "pill-success" : presenceStatus === "not_enrolled" ? "pill-warning" : "pill-error"}`,
18320
- detail: presenceStatus === "posted" ? actionableCount > 0 ? `Team ${teamLabel}. Work through Needs attention above, then review people and devices.` : `Team ${teamLabel}. Nothing urgent is blocking sync right now.` : presenceStatus === "not_enrolled" ? `Team ${teamLabel}. Enroll this device first, then return here to review the rest of the team.` : `Team ${teamLabel}. Fix the current sync issue first, then verify the rest of the team state.`,
18321
- headline: presenceStatus === "posted" ? actionableCount > 0 ? attentionDetail : "Everything is healthy" : presenceStatus === "not_enrolled" ? "This device is not enrolled in the team yet" : "Sync needs attention",
18322
- metricsText: metricParts.join(" · "),
18323
- presenceLabel
18324
- };
18325
19403
  meta.textContent = presenceStatus === "posted" ? actionableCount > 0 ? `Team: ${teamLabel}. Start with the next step below, then scan the current team status.` : `Team: ${teamLabel}. Team status and device details are below.` : presenceStatus === "not_enrolled" ? `Team: ${teamLabel}. Enroll this device first, then return here to review the rest of the team.` : `Team: ${teamLabel}. Fix the current sync issue first, then use the rest of this card to verify the team state.`;
18326
19404
  if (discoveredPanel) discoveredPanel.hidden = visibleDiscoveredRows.length === 0 && !state.syncDiscoveredFeedback;
18327
- if (discoveredMeta) discoveredMeta.textContent = visibleDiscoveredRows.length ? "Review anything here that still needs trust, follow-up, or approval." : "";
19405
+ if (discoveredMeta) discoveredMeta.textContent = visibleDiscoveredRows.length ? "Pair with a teammate's device to see it appear in People & devices and start syncing." : "";
18328
19406
  if (joinRequests) joinRequests.hidden = pendingJoinRequests.length === 0 && !state.syncJoinRequestsFeedback;
18329
- teardownTeamSyncRender(actions, [
18330
- list,
18331
- joinRequests,
18332
- discoveredList
18333
- ]);
19407
+ teardownTeamSyncRender(actions, [joinRequests, discoveredList]);
18334
19408
  const actionMount = document.createElement("div");
18335
19409
  actionMount.id = TEAM_SYNC_ACTIONS_MOUNT_ID;
18336
19410
  actions.appendChild(actionMount);
@@ -18342,19 +19416,24 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
18342
19416
  invitePanelOpen: teamInvitePanelOpen,
18343
19417
  inviteRestoreParent,
18344
19418
  joinPanel,
19419
+ joinPanelOpen: teamJoinPanelOpen,
18345
19420
  joinRestoreParent,
18346
19421
  onToggleInvitePanel: () => {
18347
19422
  if (!invitePanel) return;
18348
19423
  setTeamInvitePanelOpen(!teamInvitePanelOpen);
18349
19424
  renderTeamSync();
18350
19425
  },
19426
+ onToggleJoinPanel: () => {
19427
+ if (!joinPanel) return;
19428
+ setTeamJoinPanelOpen(!teamJoinPanelOpen);
19429
+ renderTeamSync();
19430
+ },
18351
19431
  pairedPeerCount: Number(coordinator.paired_peer_count || 0),
18352
19432
  presenceStatus
18353
19433
  }),
18354
19434
  discoveredListMount: discoveredList,
18355
19435
  discoveredRows: visibleDiscoveredRows,
18356
19436
  joinRequestsMount: joinRequests,
18357
- listMount: list,
18358
19437
  onApproveJoinRequest: async () => null,
18359
19438
  onAttentionAction: async (item) => {
18360
19439
  if (item.kind === "possible-duplicate-person") {
@@ -18457,8 +19536,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
18457
19536
  }
18458
19537
  },
18459
19538
  pendingJoinRequests,
18460
- presenceStatus,
18461
- statusSummary
19539
+ presenceStatus
18462
19540
  }));
18463
19541
  }
18464
19542
  //#endregion
@@ -18670,9 +19748,20 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
18670
19748
  renderSyncDiagnosticsUnavailable();
18671
19749
  }
18672
19750
  }
19751
+ /**
19752
+ * Called after `/api/projects` resolves (see app.ts loadProjects) so the
19753
+ * Sync peer-scope picker rerenders with the freshly-cached project names.
19754
+ * Without this, loadSyncData's dedup hash would skip the next render when
19755
+ * the underlying sync payload hasn't changed, leaving the scope picker's
19756
+ * clickable project list stuck on whatever was cached at first paint.
19757
+ */
19758
+ function invalidateSyncPeerScopeCache() {
19759
+ lastSyncHash = "";
19760
+ if (state.lastSyncPeers?.length) renderSyncPeers();
19761
+ }
18673
19762
  async function loadPairingData() {
18674
19763
  try {
18675
- state.pairingPayloadRaw = await loadPairing(!isSyncRedactionEnabled()) || null;
19764
+ state.pairingPayloadRaw = await loadPairing() || null;
18676
19765
  renderPairing();
18677
19766
  } catch {
18678
19767
  state.pairingPayloadRaw = null;
@@ -18688,6 +19777,8 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
18688
19777
  initTeamSyncEvents(refreshCallback, loadSyncData);
18689
19778
  initPeopleEvents(loadSyncData);
18690
19779
  initDiagnosticsEvents(refreshCallback);
19780
+ applySyncSubView();
19781
+ ensureSyncSubViewListener();
18691
19782
  }
18692
19783
  //#endregion
18693
19784
  //#region src/app.ts
@@ -18702,7 +19793,7 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
18702
19793
  try {
18703
19794
  const runtime = await loadRuntimeInfo();
18704
19795
  if (!runtime?.version) return;
18705
- setRuntimeLabel(runtime.version, "80517a4");
19796
+ setRuntimeLabel(runtime.version, "c411f68");
18706
19797
  } catch {}
18707
19798
  }
18708
19799
  var lastAnnouncedRefreshState = null;
@@ -18724,14 +19815,6 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
18724
19815
  return false;
18725
19816
  }
18726
19817
  }
18727
- function stopReconnectLoop() {
18728
- if (reconnectTimer) {
18729
- clearTimeout(reconnectTimer);
18730
- reconnectTimer = null;
18731
- }
18732
- reconnecting = false;
18733
- setReconnectOverlay(false);
18734
- }
18735
19818
  function canResumeRefresh() {
18736
19819
  return document.visibilityState !== "hidden" && !isSettingsOpen();
18737
19820
  }
@@ -18743,12 +19826,20 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
18743
19826
  setReconnectOverlay(true, "The viewer server is restarting or temporarily unavailable. Trying again automatically…");
18744
19827
  const tick = async () => {
18745
19828
  if (await isViewerReady()) {
18746
- stopReconnectLoop();
19829
+ if (reconnectTimer) {
19830
+ clearTimeout(reconnectTimer);
19831
+ reconnectTimer = null;
19832
+ }
19833
+ reconnecting = false;
19834
+ setReconnectOverlay(true, "Viewer responded. Restoring your session…");
18747
19835
  if (canResumeRefresh()) {
18748
19836
  setRefreshStatus("refreshing");
18749
19837
  startPolling();
18750
- doRefresh();
19838
+ try {
19839
+ await doRefresh();
19840
+ } catch {}
18751
19841
  } else setRefreshStatus("paused", document.visibilityState === "hidden" ? "(tab hidden)" : "(settings open)");
19842
+ if (!reconnecting) setReconnectOverlay(false);
18752
19843
  return;
18753
19844
  }
18754
19845
  setReconnectOverlay(true, "Still reconnecting… the viewer will recover automatically as soon as the server responds.");
@@ -18832,14 +19923,16 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
18832
19923
  $(`tabBtn-${id}`)?.addEventListener("click", () => switchTab(id));
18833
19924
  });
18834
19925
  window.addEventListener("hashchange", () => {
18835
- const hash = window.location.hash.replace("#", "");
18836
- if (ALL_TAB_IDS.includes(hash) && hash !== state.activeTab) switchTab(hash);
19926
+ const top = parseTabFromHash();
19927
+ if (top && top !== state.activeTab) switchTab(top);
18837
19928
  });
18838
19929
  switchTab(state.activeTab);
18839
19930
  }
18840
19931
  async function loadProjects() {
18841
19932
  try {
18842
19933
  const projects = await loadProjects$1();
19934
+ state.knownProjects = projects;
19935
+ invalidateSyncPeerScopeCache();
18843
19936
  const projectFilter = $select("projectFilter");
18844
19937
  if (!projectFilter) return;
18845
19938
  projectFilter.textContent = "";
@@ -18933,9 +20026,17 @@ For more information, see https://radix-ui.com/primitives/docs/components/${titl
18933
20026
  scheduleReconnectLoop();
18934
20027
  return;
18935
20028
  }
18936
- stopReconnectLoop();
20029
+ if (reconnectTimer) {
20030
+ clearTimeout(reconnectTimer);
20031
+ reconnectTimer = null;
20032
+ }
20033
+ reconnecting = false;
20034
+ setReconnectOverlay(true, "Viewer responded. Restoring your session…");
18937
20035
  startPolling();
18938
- doRefresh();
20036
+ try {
20037
+ await doRefresh();
20038
+ } catch {}
20039
+ if (!reconnecting) setReconnectOverlay(false);
18939
20040
  });
18940
20041
  loadRuntimeLabel();
18941
20042
  refresh();