@powerhousedao/design-system 6.2.2-dev.2 → 6.2.2-dev.20

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.
@@ -4,7 +4,6 @@ import { Popover, PopoverContent, PopoverTrigger } from "../ui/components/popove
4
4
  import { SelectFieldRaw } from "../ui/components/select-field/select-field.js";
5
5
  import { Input } from "../ui/components/input/input.js";
6
6
  import { JsonViewer } from "../ui/components/json-viewer/json-viewer.js";
7
- import { SearchAutocomplete } from "../ui/components/search-autocomplete/search-autocomplete.js";
8
7
  import React, { Fragment, createElement, forwardRef, memo, useCallback, useEffect, useLayoutEffect, useMemo, useReducer, useRef, useState } from "react";
9
8
  import { twJoin, twMerge } from "tailwind-merge";
10
9
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -13,6 +12,7 @@ import { Controller, useForm } from "react-hook-form";
13
12
  import { Anchor, Content as Content$1, Portal as Portal$1, Root as Root$1, Trigger as Trigger$1 } from "@radix-ui/react-popover";
14
13
  import { format, formatDistanceToNow, parseISO } from "date-fns";
15
14
  import { useCopyToClipboard, useDebounceValue, useEventListener, useOnClickOutside } from "usehooks-ts";
15
+ import { Loader2, Mail, Monitor, Moon, Settings, Smartphone, Sun, Wallet } from "lucide-react";
16
16
  import { SyncOperationStatus, addFolder, getSyncStatusSync, preloadEditorModule, setSelectedDrive, setSelectedNode, showDeleteNodeModal, showPHModal, showRevisionHistory, useDocumentById, useDownloadDocument, useDragNode, useDropFile, useDropNode, useEditorModulesForDocumentType, useGetSwitchboardLink, useIsDragAndDropEnabled, useNodeActions, useNodeById, useNodeParentFolderById, useOnDropFile, useSelectedDocumentSafe, useSelectedDriveId, useSelectedDriveSafe, useSelectedNodePath, useTheme, useUserPermissions } from "@powerhousedao/reactor-browser";
17
17
  import Select, { components } from "react-select";
18
18
  import { Content as Content$2, List, Root as Root$2, Trigger as Trigger$2 } from "@radix-ui/react-tabs";
@@ -25,22 +25,152 @@ import { lightTheme } from "@uiw/react-json-view/light";
25
25
  import { isValidName } from "@powerhousedao/shared/document-drive";
26
26
  import { capitalCase } from "change-case";
27
27
  import { useVirtualizer } from "@tanstack/react-virtual";
28
- import { Monitor, Moon, Settings, Sun } from "lucide-react";
29
28
  //#region src/connect/components/account-popover/account-popover.tsx
30
- const AccountPopover = ({ children, content }) => {
31
- return /* @__PURE__ */ jsxs(Popover, { children: [/* @__PURE__ */ jsx(PopoverTrigger, {
32
- asChild: true,
33
- children: /* @__PURE__ */ jsx("button", {
29
+ const AccountPopover = ({ children, content, open, onOpenChange }) => {
30
+ return /* @__PURE__ */ jsxs(Popover, {
31
+ open,
32
+ onOpenChange,
33
+ children: [/* @__PURE__ */ jsx(PopoverTrigger, {
34
+ asChild: true,
35
+ children: /* @__PURE__ */ jsx("button", {
36
+ type: "button",
37
+ "aria-label": "Open Account",
38
+ className: "cursor-pointer",
39
+ children
40
+ })
41
+ }), /* @__PURE__ */ jsx(PopoverContent, {
42
+ className: "w-52 p-0",
43
+ align: "start",
44
+ children: content
45
+ })]
46
+ });
47
+ };
48
+ //#endregion
49
+ //#region src/connect/components/account-popover/account-popover-login.tsx
50
+ const AccountPopoverLogin = ({ onLogin }) => {
51
+ const allowLogin = !!onLogin;
52
+ return /* @__PURE__ */ jsxs("div", {
53
+ className: "p-4",
54
+ children: [/* @__PURE__ */ jsx("div", {
55
+ className: "mb-4 flex justify-center",
56
+ children: /* @__PURE__ */ jsx("div", {
57
+ className: "flex h-5.5 w-20.75 items-center justify-center overflow-hidden text-foreground",
58
+ children: /* @__PURE__ */ jsx(Icon, {
59
+ name: "RenownLight",
60
+ size: 83
61
+ })
62
+ })
63
+ }), /* @__PURE__ */ jsx("button", {
64
+ onClick: allowLogin ? onLogin : void 0,
65
+ className: allowLogin ? "mt-4 flex h-7 w-full cursor-pointer items-center justify-center rounded-lg border border-border bg-transparent text-sm text-foreground active:active-effect" : "mt-4 flex h-7 w-full cursor-wait items-center justify-center rounded-lg border border-border bg-transparent text-sm text-foreground",
34
66
  type: "button",
35
- "aria-label": "Open Account",
36
- className: "cursor-pointer",
37
- children
67
+ children: /* @__PURE__ */ jsx("span", { children: "Connect" })
68
+ })]
69
+ });
70
+ };
71
+ //#endregion
72
+ //#region src/connect/components/renown-login/renown-login-methods.tsx
73
+ const GoogleMark = () => /* @__PURE__ */ jsxs("svg", {
74
+ width: "18",
75
+ height: "18",
76
+ viewBox: "0 0 18 18",
77
+ "aria-hidden": "true",
78
+ children: [
79
+ /* @__PURE__ */ jsx("path", {
80
+ fill: "#4285F4",
81
+ d: "M17.64 9.205c0-.639-.057-1.252-.164-1.841H9v3.481h4.844a4.14 4.14 0 0 1-1.796 2.716v2.259h2.908c1.702-1.567 2.684-3.875 2.684-6.615z"
82
+ }),
83
+ /* @__PURE__ */ jsx("path", {
84
+ fill: "#34A853",
85
+ d: "M9 18c2.43 0 4.467-.806 5.956-2.18l-2.908-2.259c-.806.54-1.837.859-3.048.859-2.344 0-4.328-1.583-5.036-3.71H.957v2.332A8.997 8.997 0 0 0 9 18z"
86
+ }),
87
+ /* @__PURE__ */ jsx("path", {
88
+ fill: "#FBBC05",
89
+ d: "M3.964 10.71A5.41 5.41 0 0 1 3.682 9c0-.593.102-1.17.282-1.71V4.958H.957A8.997 8.997 0 0 0 0 9c0 1.452.348 2.827.957 4.042l3.007-2.332z"
90
+ }),
91
+ /* @__PURE__ */ jsx("path", {
92
+ fill: "#EA4335",
93
+ d: "M9 3.58c1.321 0 2.508.454 3.44 1.346l2.582-2.581C13.463.891 11.426 0 9 0A8.997 8.997 0 0 0 .957 4.958L3.964 7.29C4.672 5.163 6.656 3.58 9 3.58z"
38
94
  })
39
- }), /* @__PURE__ */ jsx(PopoverContent, {
40
- className: "w-52 p-0",
41
- align: "start",
42
- children: content
43
- })] });
95
+ ]
96
+ });
97
+ const AppleMark = () => /* @__PURE__ */ jsx("svg", {
98
+ width: "18",
99
+ height: "18",
100
+ viewBox: "0 0 24 24",
101
+ fill: "currentColor",
102
+ "aria-hidden": "true",
103
+ children: /* @__PURE__ */ jsx("path", { d: "M17.05 20.28c-.98.95-2.05.8-3.08.35-1.09-.46-2.09-.48-3.24 0-1.44.62-2.2.44-3.06-.35C2.79 15.25 3.51 7.59 9.05 7.31c1.35.07 2.29.74 3.08.8 1.18-.24 2.31-.93 3.57-.84 1.51.12 2.65.72 3.4 1.8-3.12 1.87-2.38 5.98.48 7.13-.57 1.5-1.31 2.99-2.51 4.09zM12.03 7.25c-.15-2.23 1.66-4.07 3.74-4.25.29 2.58-2.34 4.5-3.74 4.25z" })
104
+ });
105
+ const METHOD_ICONS = {
106
+ wallet: /* @__PURE__ */ jsx(Wallet, {
107
+ size: 18,
108
+ "aria-hidden": "true"
109
+ }),
110
+ email: /* @__PURE__ */ jsx(Mail, {
111
+ size: 18,
112
+ "aria-hidden": "true"
113
+ }),
114
+ sms: /* @__PURE__ */ jsx(Smartphone, {
115
+ size: 18,
116
+ "aria-hidden": "true"
117
+ }),
118
+ google: /* @__PURE__ */ jsx(GoogleMark, {}),
119
+ apple: /* @__PURE__ */ jsx(AppleMark, {})
120
+ };
121
+ const baseButton = "relative flex h-10 w-full items-center justify-center gap-2 rounded-lg px-3 text-sm font-semibold transition-colors disabled:pointer-events-none disabled:opacity-60";
122
+ const primaryButton = "bg-primary text-primary-foreground hover:bg-primary/85";
123
+ const secondaryButton = "border border-border bg-card text-foreground hover:bg-muted";
124
+ const RenownLoginMethods = ({ methods, loading = false, error, className }) => {
125
+ const [pendingId, setPendingId] = useState(null);
126
+ const wallet = methods.find((method) => method.id === "wallet");
127
+ const others = methods.filter((method) => method.id !== "wallet");
128
+ const renderButton = (method, primary) => {
129
+ const isPending = loading && pendingId === method.id;
130
+ return /* @__PURE__ */ jsxs("button", {
131
+ type: "button",
132
+ disabled: loading,
133
+ onClick: () => {
134
+ setPendingId(method.id);
135
+ method.onSelect();
136
+ },
137
+ className: twMerge(baseButton, primary ? primaryButton : secondaryButton, isPending && "animate-pulse"),
138
+ children: [
139
+ isPending ? /* @__PURE__ */ jsx(Loader2, {
140
+ size: 18,
141
+ className: "animate-spin",
142
+ "aria-hidden": "true"
143
+ }) : METHOD_ICONS[method.id],
144
+ /* @__PURE__ */ jsx("span", { children: method.label }),
145
+ method.lastUsed ? /* @__PURE__ */ jsx("span", {
146
+ className: "absolute -top-2 right-2 rounded-full bg-foreground px-1.5 py-0.5 text-[10px] leading-none font-semibold text-background shadow-sm",
147
+ children: "Last used"
148
+ }) : null
149
+ ]
150
+ }, method.id);
151
+ };
152
+ return /* @__PURE__ */ jsxs("div", {
153
+ className: twMerge("flex w-full flex-col gap-3", className),
154
+ children: [
155
+ wallet ? renderButton(wallet, true) : null,
156
+ wallet && others.length > 0 ? /* @__PURE__ */ jsxs("div", {
157
+ className: "my-1 flex items-center gap-3",
158
+ children: [
159
+ /* @__PURE__ */ jsx("div", { className: "h-px flex-1 bg-border" }),
160
+ /* @__PURE__ */ jsx("span", {
161
+ className: "text-xs tracking-wider text-muted-foreground uppercase",
162
+ children: "or"
163
+ }),
164
+ /* @__PURE__ */ jsx("div", { className: "h-px flex-1 bg-border" })
165
+ ]
166
+ }) : null,
167
+ others.map((method) => renderButton(method, false)),
168
+ error ? /* @__PURE__ */ jsx("p", {
169
+ className: "text-center text-xs text-destructive",
170
+ children: error
171
+ }) : null
172
+ ]
173
+ });
44
174
  };
45
175
  //#endregion
46
176
  //#region assets/connect-loader.mp4
@@ -1643,33 +1773,35 @@ function TabContent(props) {
1643
1773
  //#endregion
1644
1774
  //#region src/connect/components/tabs/tabs.tsx
1645
1775
  const toTabValue = (label) => label.trim().replace(/\s+/g, "-");
1646
- function Tabs({ children, defaultValue }) {
1776
+ const resolveTabValue = (props) => props.value ?? toTabValue(props.label);
1777
+ function Tabs({ children, defaultValue, onValueChange, listClassName }) {
1647
1778
  return /* @__PURE__ */ jsxs(Root$2, {
1648
1779
  defaultValue: toTabValue(defaultValue),
1780
+ onValueChange,
1649
1781
  className: "flex min-h-0 flex-1 flex-col gap-2",
1650
1782
  children: [/* @__PURE__ */ jsx("div", {
1651
- className: "flex w-full shrink-0 justify-between",
1783
+ className: twMerge("flex w-full shrink-0 justify-between", listClassName),
1652
1784
  children: /* @__PURE__ */ jsx(List, {
1653
1785
  className: "flex w-full gap-x-2 rounded-xl p-1 text-sm font-semibold text-foreground outline-none",
1654
1786
  children: React.Children.map(children, (child, _i) => {
1655
1787
  if (!/* @__PURE__ */ React.isValidElement(child)) return;
1656
- const { label, disabled } = child.props;
1788
+ const props = child.props;
1789
+ const value = resolveTabValue(props);
1657
1790
  return /* @__PURE__ */ jsx(Trigger$2, {
1658
1791
  className: "flex min-h-7 flex-1 items-center justify-center rounded-lg border border-border bg-background py-2 text-foreground transition duration-300 data-disabled:disabled-effect data-[state=active]:bg-accent data-[state=active]:text-foreground",
1659
- value: toTabValue(label),
1660
- disabled: disabled ?? false,
1661
- children: label
1662
- }, label);
1792
+ value,
1793
+ disabled: props.disabled ?? false,
1794
+ children: props.label
1795
+ }, value);
1663
1796
  })
1664
1797
  })
1665
1798
  }), /* @__PURE__ */ jsx("div", {
1666
1799
  className: "mt-3 min-h-0 flex-1 rounded-md bg-background",
1667
1800
  children: React.Children.map(children, (child, i) => {
1668
1801
  if (!/* @__PURE__ */ React.isValidElement(child)) return;
1669
- const { label } = child.props;
1670
1802
  return /* @__PURE__ */ jsx(Content$2, {
1671
1803
  className: "h-full",
1672
- value: toTabValue(label),
1804
+ value: resolveTabValue(child.props),
1673
1805
  children: child
1674
1806
  }, i);
1675
1807
  })
@@ -2441,11 +2573,6 @@ function ControlsContainerSlot(props) {
2441
2573
  }
2442
2574
  //#endregion
2443
2575
  //#region src/connect/components/drive-auth-gate/drive-auth-gate.tsx
2444
- /**
2445
- * Reusable "log in to access this drive" card. Used both as the content of the
2446
- * drive-add auth modal and as the full-page gate shown when the user logs out
2447
- * while inside a protected drive — so the two stay visually identical.
2448
- */
2449
2576
  function DriveAuthGate(props) {
2450
2577
  const { mode = "login", onLogin, onLogout, className } = props;
2451
2578
  return /* @__PURE__ */ jsx("div", {
@@ -7373,6 +7500,76 @@ function buildPackageSpec(name, tag) {
7373
7500
  return tag ? `${name}@${tag}` : name;
7374
7501
  }
7375
7502
  //#endregion
7503
+ //#region src/connect/components/modal/settings-modal-v2/package-manager/filter-packages.ts
7504
+ /**
7505
+ * Client-side package filter used by both Package Manager tabs. Matches the
7506
+ * query's name part (any `@tag` suffix is ignored for matching — it drives
7507
+ * version preselection instead) against the package name only.
7508
+ *
7509
+ * This is the seam a future registry search endpoint replaces: when the
7510
+ * Available tab searches server-side, its panel skips this function and
7511
+ * renders the API results as-is.
7512
+ */
7513
+ function filterPackages(packages, query) {
7514
+ const { name } = parsePackageSpec(query);
7515
+ const needle = name.toLowerCase();
7516
+ if (!needle) return packages;
7517
+ return packages.filter((pkg) => pkg.name.toLowerCase().includes(needle));
7518
+ }
7519
+ //#endregion
7520
+ //#region src/connect/components/modal/settings-modal-v2/package-manager/npm-fallback-row.tsx
7521
+ /**
7522
+ * Shown in the Available tab when the search query matches nothing in the
7523
+ * registry but looks like a valid npm package name: the registry's verdaccio
7524
+ * backend proxies npmjs.org, so the install can still succeed. Replaces the
7525
+ * old SearchAutocomplete fallback option. The button label is "Install from
7526
+ * npm" (not "Install") so it doesn't collide with the row-kebab menu item.
7527
+ */
7528
+ const NpmFallbackRow = (props) => {
7529
+ const { query, onInstall, disabled } = props;
7530
+ const [isInstalling, setIsInstalling] = useState(false);
7531
+ const { name, tag } = parsePackageSpec(query);
7532
+ const spec = buildPackageSpec(name, tag);
7533
+ function handleInstall() {
7534
+ setIsInstalling(true);
7535
+ onInstall(spec).catch(console.error).finally(() => setIsInstalling(false));
7536
+ }
7537
+ return /* @__PURE__ */ jsxs("div", {
7538
+ className: "flex items-start justify-between gap-3 rounded-md border border-dashed border-border bg-background p-3 text-sm/5",
7539
+ children: [/* @__PURE__ */ jsxs("div", {
7540
+ className: "min-w-0 flex-1",
7541
+ children: [
7542
+ /* @__PURE__ */ jsx("p", {
7543
+ className: "truncate font-semibold text-foreground",
7544
+ children: tag ? `${name} @ ${tag}` : name
7545
+ }),
7546
+ /* @__PURE__ */ jsx("p", {
7547
+ className: "text-xs text-foreground",
7548
+ children: "Not published to this registry. Install via the npmjs.org uplink."
7549
+ }),
7550
+ /* @__PURE__ */ jsx("p", {
7551
+ className: "text-xs text-muted-foreground",
7552
+ children: "npm fallback"
7553
+ })
7554
+ ]
7555
+ }), /* @__PURE__ */ jsx("div", {
7556
+ className: "shrink-0 self-center",
7557
+ children: /* @__PURE__ */ jsx("button", {
7558
+ onClick: handleInstall,
7559
+ disabled: disabled || isInstalling,
7560
+ className: "rounded-md bg-primary px-3 py-1 text-xs font-medium text-primary-foreground transition-colors hover:hover-effect disabled:disabled-effect",
7561
+ children: isInstalling ? "Installing..." : "Install from npm"
7562
+ })
7563
+ })]
7564
+ });
7565
+ };
7566
+ //#endregion
7567
+ //#region src/connect/components/modal/settings-modal-v2/package-manager/npm-name.ts
7568
+ const NPM_NAME_RE = /^@[a-z0-9][a-z0-9._-]*\/[a-z0-9][a-z0-9._-]*$|^[a-z0-9][a-z0-9._-]*$/i;
7569
+ function isPlausiblePackageName(name) {
7570
+ return name.length >= 2 && NPM_NAME_RE.test(name);
7571
+ }
7572
+ //#endregion
7376
7573
  //#region src/connect/components/modal/settings-modal-v2/package-manager/version-picker.tsx
7377
7574
  function resolveDefaultVersionSelection(options) {
7378
7575
  const { distTags, versions, version, preferredTag } = options;
@@ -7516,147 +7713,6 @@ const VersionPicker = (props) => {
7516
7713
  });
7517
7714
  };
7518
7715
  //#endregion
7519
- //#region src/connect/components/modal/settings-modal-v2/package-manager/package-manager-input.tsx
7520
- const NPM_NAME_RE = /^@[a-z0-9][a-z0-9._-]*\/[a-z0-9][a-z0-9._-]*$|^[a-z0-9][a-z0-9._-]*$/i;
7521
- function isPlausiblePackageName(name) {
7522
- return name.length >= 2 && NPM_NAME_RE.test(name);
7523
- }
7524
- function PackageResultCard(props) {
7525
- const { option, ctx, typedTag } = props;
7526
- const { selectingValue, selectLabel, selectingContent, handleSelect } = ctx;
7527
- const baseName = option.label.split(" @ ")[0] ?? option.value;
7528
- const hasVersionMetadata = option.distTags && Object.keys(option.distTags).length > 0 || (option.versions?.length ?? 0) > 0;
7529
- const [selected, setSelected] = useState(() => resolveDefaultVersionSelection({
7530
- distTags: option.distTags,
7531
- versions: option.versions,
7532
- version: option.version,
7533
- preferredTag: typedTag
7534
- }));
7535
- useEffect(() => {
7536
- if (!typedTag) return;
7537
- if (option.distTags && typedTag in option.distTags) setSelected({
7538
- kind: "tag",
7539
- value: typedTag
7540
- });
7541
- else if (option.versions?.includes(typedTag)) setSelected({
7542
- kind: "version",
7543
- value: typedTag
7544
- });
7545
- }, [
7546
- typedTag,
7547
- option.distTags,
7548
- option.versions
7549
- ]);
7550
- const installSpec = hasVersionMetadata ? buildPackageSpec(baseName, selected.value) : option.value;
7551
- const isSelecting = selectingValue === installSpec;
7552
- const isDisabled = option.disabled === true;
7553
- return /* @__PURE__ */ jsxs("div", {
7554
- className: "flex items-start justify-between gap-3 rounded-md p-2 hover:hover-effect",
7555
- children: [/* @__PURE__ */ jsxs("div", {
7556
- className: "min-w-0 flex-1",
7557
- children: [
7558
- /* @__PURE__ */ jsx("p", {
7559
- className: "truncate text-sm font-medium text-foreground",
7560
- children: baseName
7561
- }),
7562
- option.description && /* @__PURE__ */ jsx("p", {
7563
- className: "truncate text-xs text-foreground",
7564
- children: option.description
7565
- }),
7566
- option.meta && /* @__PURE__ */ jsx("p", {
7567
- className: "truncate text-xs text-foreground",
7568
- children: option.meta
7569
- }),
7570
- hasVersionMetadata && /* @__PURE__ */ jsx("div", {
7571
- className: "mt-2",
7572
- children: /* @__PURE__ */ jsx(VersionPicker, {
7573
- distTags: option.distTags,
7574
- versions: option.versions,
7575
- selected,
7576
- onChange: setSelected,
7577
- disabled: isDisabled
7578
- })
7579
- })
7580
- ]
7581
- }), /* @__PURE__ */ jsx("div", {
7582
- className: "shrink-0 self-center",
7583
- children: isSelecting && selectingContent ? /* @__PURE__ */ jsx("div", {
7584
- className: "flex items-center justify-center",
7585
- children: selectingContent
7586
- }) : isDisabled ? /* @__PURE__ */ jsx("span", {
7587
- className: "rounded-md bg-muted px-3 py-1 text-xs font-medium text-muted-foreground",
7588
- children: option.disabledLabel ?? "Unavailable"
7589
- }) : /* @__PURE__ */ jsx("button", {
7590
- onClick: () => handleSelect(installSpec),
7591
- disabled: isSelecting,
7592
- className: "rounded-md bg-primary px-3 py-1 text-xs font-medium text-primary-foreground transition-colors hover:hover-effect disabled:disabled-effect",
7593
- children: isSelecting ? "..." : selectLabel
7594
- })
7595
- })]
7596
- });
7597
- }
7598
- const PackageManagerInput = (props) => {
7599
- const { registryPackageList, onInstall, disabled, className } = props;
7600
- const [typedTag, setTypedTag] = useState(void 0);
7601
- const fetchOptions = async (query) => {
7602
- const { name: namePart, tag } = parsePackageSpec(query);
7603
- setTypedTag(tag);
7604
- const needle = namePart.toLowerCase();
7605
- const localOptions = registryPackageList.filter((pkg) => pkg.name.toLowerCase().includes(needle) || pkg.manifest?.description?.toLowerCase().includes(needle)).map((pkg) => {
7606
- const isInstalled = pkg.status === "local-install" || pkg.status === "registry-install";
7607
- return {
7608
- value: pkg.name,
7609
- label: pkg.name,
7610
- version: pkg.version,
7611
- description: pkg.manifest?.description,
7612
- meta: pkg.manifest?.publisher?.name,
7613
- disabled: isInstalled,
7614
- disabledLabel: isInstalled ? "Installed" : void 0,
7615
- distTags: pkg.distTags,
7616
- versions: pkg.versions
7617
- };
7618
- });
7619
- if (!isPlausiblePackageName(namePart) || localOptions.length > 0) return Promise.resolve(localOptions);
7620
- const fallbackOption = {
7621
- value: buildPackageSpec(namePart, tag),
7622
- label: tag ? `${namePart} @ ${tag}` : namePart,
7623
- version: tag,
7624
- description: "Not published to this registry. Install via the npmjs.org uplink.",
7625
- meta: "npm fallback"
7626
- };
7627
- return Promise.resolve([fallbackOption]);
7628
- };
7629
- const handleSelect = useCallback((value) => {
7630
- return onInstall(value);
7631
- }, [onInstall]);
7632
- const renderRow = useCallback((option, ctx) => /* @__PURE__ */ jsx(PackageResultCard, {
7633
- option,
7634
- ctx,
7635
- typedTag
7636
- }), [typedTag]);
7637
- return /* @__PURE__ */ jsxs("div", {
7638
- className,
7639
- children: [/* @__PURE__ */ jsx("h3", {
7640
- className: "mb-4 font-semibold text-foreground",
7641
- children: "Install Package"
7642
- }), /* @__PURE__ */ jsx(SearchAutocomplete, {
7643
- fetchOptions,
7644
- onSelect: handleSelect,
7645
- selectLabel: "Install",
7646
- selectingContent: /* @__PURE__ */ jsx(PackageAnimation, {
7647
- animate: true,
7648
- loop: true,
7649
- color: "#6b7280",
7650
- size: 48
7651
- }),
7652
- placeholder: "Search packages (e.g. my-pkg, my-pkg@dev, my-pkg@1.2.3)...",
7653
- disabled,
7654
- renderRow,
7655
- keepOpenSelector: "[data-version-picker],[data-version-picker-trigger]"
7656
- })]
7657
- });
7658
- };
7659
- //#endregion
7660
7716
  //#region src/connect/components/modal/settings-modal-v2/package-manager/package-manager-list.tsx
7661
7717
  const PackageDetail = ({ label, value }) => {
7662
7718
  return /* @__PURE__ */ jsxs("div", {
@@ -7671,15 +7727,31 @@ const PackageDetail = ({ label, value }) => {
7671
7727
  });
7672
7728
  };
7673
7729
  const PackageManagerListItem = (props) => {
7674
- const { registryPackage, onInstall, onUninstall, className } = props;
7730
+ const { registryPackage, onInstall, onUninstall, preferredTag, className } = props;
7675
7731
  const [isDropdownMenuOpen, setIsDropdownMenuOpen] = useState(false);
7676
7732
  const canPickVersion = registryPackage.status === "available" || registryPackage.status === "dismissed";
7677
7733
  const hasVersionMetadata = registryPackage.distTags && Object.keys(registryPackage.distTags).length > 0 || (registryPackage.versions?.length ?? 0) > 0;
7678
7734
  const [selected, setSelected] = useState(() => resolveDefaultVersionSelection({
7679
7735
  distTags: registryPackage.distTags,
7680
7736
  versions: registryPackage.versions,
7681
- version: registryPackage.version
7737
+ version: registryPackage.version,
7738
+ preferredTag
7682
7739
  }));
7740
+ useEffect(() => {
7741
+ if (!preferredTag) return;
7742
+ if (registryPackage.distTags && preferredTag in registryPackage.distTags) setSelected({
7743
+ kind: "tag",
7744
+ value: preferredTag
7745
+ });
7746
+ else if (registryPackage.versions?.includes(preferredTag)) setSelected({
7747
+ kind: "version",
7748
+ value: preferredTag
7749
+ });
7750
+ }, [
7751
+ preferredTag,
7752
+ registryPackage.distTags,
7753
+ registryPackage.versions
7754
+ ]);
7683
7755
  const installDropdownItem = {
7684
7756
  id: "install",
7685
7757
  label: "Install",
@@ -7716,31 +7788,38 @@ const PackageManagerListItem = (props) => {
7716
7788
  }),
7717
7789
  registryPackage.manifest !== null && (() => {
7718
7790
  const { description, category, publisher } = registryPackage.manifest;
7719
- if (!(description != null || category != null || publisher?.name != null || publisher?.url != null)) return null;
7791
+ const publisherName = publisher?.name;
7792
+ const publisherUrl = publisher?.url;
7793
+ const hasText = (value) => typeof value === "string" && value.trim() !== "";
7794
+ const showDescription = hasText(description);
7795
+ const showCategory = hasText(category);
7796
+ const showPublisher = hasText(publisherName);
7797
+ const showPublisherUrl = hasText(publisherUrl);
7798
+ if (!showDescription && !showCategory && !showPublisher && !showPublisherUrl) return null;
7720
7799
  return /* @__PURE__ */ jsxs(Fragment$1, { children: [
7721
- description != null && /* @__PURE__ */ jsx(PackageDetail, {
7800
+ showDescription && /* @__PURE__ */ jsx(PackageDetail, {
7722
7801
  label: "Description",
7723
7802
  value: description
7724
7803
  }),
7725
- category != null && /* @__PURE__ */ jsx(PackageDetail, {
7804
+ showCategory && /* @__PURE__ */ jsx(PackageDetail, {
7726
7805
  label: "Category",
7727
7806
  value: category
7728
7807
  }),
7729
- publisher?.name != null && /* @__PURE__ */ jsx(PackageDetail, {
7808
+ showPublisher && /* @__PURE__ */ jsx(PackageDetail, {
7730
7809
  label: "Publisher",
7731
- value: publisher.name
7810
+ value: publisherName
7732
7811
  }),
7733
- publisher?.url != null && /* @__PURE__ */ jsx(PackageDetail, {
7812
+ showPublisherUrl && /* @__PURE__ */ jsx(PackageDetail, {
7734
7813
  label: "Publisher URL",
7735
7814
  value: /* @__PURE__ */ jsx("a", {
7736
7815
  className: "underline",
7737
- href: publisher.url,
7738
- children: publisher.url
7816
+ href: publisherUrl,
7817
+ children: publisherUrl
7739
7818
  })
7740
7819
  })
7741
7820
  ] });
7742
7821
  })(),
7743
- /* @__PURE__ */ jsx(ConnectDropdownMenu, {
7822
+ dropdownItems.length > 0 && /* @__PURE__ */ jsx(ConnectDropdownMenu, {
7744
7823
  items: dropdownItems,
7745
7824
  onItemClick: (id) => {
7746
7825
  if (id === "install") {
@@ -7766,141 +7845,46 @@ const PackageManagerListItem = (props) => {
7766
7845
  ]
7767
7846
  });
7768
7847
  };
7769
- const PackageManagerList = (props) => {
7770
- const { className, registryPackageList, onInstall, onUninstall } = props;
7771
- const [maxHeight, setMaxHeight] = useState();
7772
- const locallyInstalledPackages = registryPackageList.filter((p) => p.status === "local-install");
7773
- const registryInstalledPackages = registryPackageList.filter((p) => p.status === "registry-install");
7774
- const availablePackages = registryPackageList.filter((p) => p.status === "available");
7775
- const dismissedPackages = registryPackageList.filter((p) => p.status === "dismissed");
7776
- useLayoutEffect(() => {
7777
- const calculateMaxHeight = () => {
7778
- const availableHeight = window.innerHeight - 516;
7779
- setMaxHeight(Math.max(200, availableHeight));
7780
- };
7781
- calculateMaxHeight();
7782
- window.addEventListener("resize", calculateMaxHeight);
7783
- return () => window.removeEventListener("resize", calculateMaxHeight);
7784
- }, []);
7785
- const hasLocallyInstalled = locallyInstalledPackages.length > 0;
7786
- const hasRegistryInstalled = registryInstalledPackages.length > 0;
7787
- const hasAnyInstalled = hasLocallyInstalled || hasRegistryInstalled;
7788
- const hasAvailable = availablePackages.length > 0;
7789
- const hasDismissed = dismissedPackages.length > 0;
7790
- const installedCount = locallyInstalledPackages.length + registryInstalledPackages.length;
7791
- return /* @__PURE__ */ jsx("div", {
7792
- className: twMerge("flex flex-col items-stretch overflow-hidden", className),
7793
- style: { maxHeight },
7794
- children: /* @__PURE__ */ jsxs("div", {
7795
- className: "flex-1 overflow-y-auto pr-2",
7796
- children: [
7797
- /* @__PURE__ */ jsxs(PackageSection, {
7798
- sectionId: "installed",
7799
- title: "Installed Packages",
7800
- count: installedCount,
7801
- isEmpty: !hasAnyInstalled,
7802
- emptyText: "No packages installed.",
7803
- children: [hasLocallyInstalled && /* @__PURE__ */ jsx(PackageSubSection, {
7804
- title: "Locally installed",
7805
- count: locallyInstalledPackages.length,
7806
- children: /* @__PURE__ */ jsx(PackageList, {
7807
- packages: locallyInstalledPackages,
7808
- onInstall,
7809
- onUninstall
7810
- })
7811
- }), hasRegistryInstalled && /* @__PURE__ */ jsx(PackageSubSection, {
7812
- title: "Installed from registry",
7813
- count: registryInstalledPackages.length,
7814
- children: /* @__PURE__ */ jsx(PackageList, {
7815
- packages: registryInstalledPackages,
7816
- onInstall,
7817
- onUninstall
7818
- })
7819
- })]
7820
- }),
7821
- /* @__PURE__ */ jsx(PackageSection, {
7822
- sectionId: "available",
7823
- title: "Available Packages",
7824
- count: availablePackages.length,
7825
- isEmpty: !hasAvailable,
7826
- emptyText: "No packages available to install.",
7827
- children: /* @__PURE__ */ jsx(PackageList, {
7828
- packages: availablePackages,
7829
- onInstall,
7830
- onUninstall
7831
- })
7832
- }),
7833
- hasDismissed && /* @__PURE__ */ jsx(PackageSection, {
7834
- sectionId: "dismissed",
7835
- title: "Dismissed Packages",
7836
- count: dismissedPackages.length,
7837
- children: /* @__PURE__ */ jsx(PackageList, {
7838
- packages: dismissedPackages,
7839
- onInstall,
7840
- onUninstall
7841
- })
7842
- })
7843
- ]
7844
- })
7848
+ /**
7849
+ * Scroll region shared by both Package Manager tab panels. Fills the space
7850
+ * the panel gives it and scrolls its overflow. This works because the tab
7851
+ * panel sits inside the settings content card, which has a bounded height
7852
+ * (`m-6 ... h-full flex-1 overflow-hidden`); the flex chain down to here is
7853
+ * unbroken (`min-h-0` + `flex-1`/`h-full` at every level), so no
7854
+ * viewport-measuring hack is needed.
7855
+ */
7856
+ const PackagePanelScrollArea = ({ children, className, onReachEnd }) => {
7857
+ const scrollRef = useRef(null);
7858
+ const sentinelRef = useRef(null);
7859
+ const onReachEndRef = useRef(onReachEnd);
7860
+ useEffect(() => {
7861
+ onReachEndRef.current = onReachEnd;
7845
7862
  });
7846
- };
7847
- const STORAGE_KEY = "ph:package-manager:collapsed-sections";
7848
- function loadCollapsedSections() {
7849
- if (typeof window === "undefined") return {};
7850
- try {
7851
- const raw = window.localStorage.getItem(STORAGE_KEY);
7852
- return raw ? JSON.parse(raw) : {};
7853
- } catch {
7854
- return {};
7855
- }
7856
- }
7857
- function useCollapsedSection(sectionId) {
7858
- const [collapsed, setCollapsed] = useState(() => loadCollapsedSections()[sectionId] ?? true);
7863
+ const hasHandler = onReachEnd !== void 0;
7859
7864
  useEffect(() => {
7860
- if (typeof window === "undefined") return;
7861
- try {
7862
- const current = loadCollapsedSections();
7863
- current[sectionId] = collapsed;
7864
- window.localStorage.setItem(STORAGE_KEY, JSON.stringify(current));
7865
- } catch {}
7866
- }, [sectionId, collapsed]);
7867
- return [collapsed, useCallback(() => setCollapsed((prev) => !prev), [])];
7868
- }
7869
- const PackageSection = ({ sectionId, title, count, isEmpty, emptyText, children }) => {
7870
- const [collapsed, toggle] = useCollapsedSection(sectionId);
7871
- const contentId = `package-section-${sectionId}`;
7872
- return /* @__PURE__ */ jsxs("section", {
7873
- className: "mb-6",
7874
- children: [/* @__PURE__ */ jsx("h3", {
7875
- className: "sticky top-0 z-10 mb-3 border-b border-border bg-background text-foreground",
7876
- children: /* @__PURE__ */ jsxs("button", {
7877
- type: "button",
7878
- onClick: toggle,
7879
- "aria-expanded": !collapsed,
7880
- "aria-controls": contentId,
7881
- className: "flex w-full items-center gap-2 pb-2 text-left text-base font-semibold text-foreground hover:hover-effect",
7882
- children: [
7883
- /* @__PURE__ */ jsx(Icon, {
7884
- name: "ChevronDown",
7885
- size: 16,
7886
- className: twMerge("shrink-0 text-foreground transition-transform", collapsed && "-rotate-90")
7887
- }),
7888
- /* @__PURE__ */ jsx("span", { children: title }),
7889
- /* @__PURE__ */ jsx("span", {
7890
- className: "text-xs font-medium text-foreground",
7891
- children: count
7892
- })
7893
- ]
7894
- })
7895
- }), !collapsed && /* @__PURE__ */ jsx("div", {
7896
- id: contentId,
7897
- children: isEmpty ? /* @__PURE__ */ jsx("p", {
7898
- className: "text-sm text-foreground",
7899
- children: emptyText
7900
- }) : /* @__PURE__ */ jsx("div", {
7901
- className: "flex flex-col gap-4",
7902
- children
7903
- })
7865
+ if (!hasHandler) return;
7866
+ const root = scrollRef.current;
7867
+ const sentinel = sentinelRef.current;
7868
+ if (!root || !sentinel) return;
7869
+ const observer = new IntersectionObserver((entries) => {
7870
+ if (entries.some((e) => e.isIntersecting)) onReachEndRef.current?.();
7871
+ }, {
7872
+ root,
7873
+ rootMargin: "200px"
7874
+ });
7875
+ observer.observe(sentinel);
7876
+ return () => observer.disconnect();
7877
+ }, [hasHandler]);
7878
+ return /* @__PURE__ */ jsxs("div", {
7879
+ ref: scrollRef,
7880
+ className: twMerge("min-h-0 flex-1 overflow-y-auto", className),
7881
+ children: [/* @__PURE__ */ jsx("div", {
7882
+ className: "pr-3 pb-3",
7883
+ children
7884
+ }), hasHandler && /* @__PURE__ */ jsx("div", {
7885
+ ref: sentinelRef,
7886
+ "aria-hidden": true,
7887
+ className: "h-px w-full"
7904
7888
  })]
7905
7889
  });
7906
7890
  };
@@ -7917,31 +7901,286 @@ const PackageSubSection = ({ title, count, children }) => {
7917
7901
  })]
7918
7902
  }), children] });
7919
7903
  };
7920
- const PackageList = ({ packages, onInstall, onUninstall }) => {
7904
+ const PackageList = ({ packages, onInstall, onUninstall, preferredTag }) => {
7921
7905
  return /* @__PURE__ */ jsx("ul", {
7922
- className: "flex flex-col items-stretch gap-4 pr-2",
7906
+ className: "flex flex-col items-stretch gap-4",
7923
7907
  children: packages.map((pkg) => /* @__PURE__ */ jsx(PackageManagerListItem, {
7924
7908
  registryPackage: pkg,
7925
7909
  onInstall,
7926
- onUninstall
7910
+ onUninstall,
7911
+ preferredTag
7927
7912
  }, pkg.name))
7928
7913
  });
7929
7914
  };
7930
7915
  //#endregion
7916
+ //#region src/connect/components/modal/settings-modal-v2/package-manager/package-registry-error.tsx
7917
+ /**
7918
+ * Friendly registry-error banner. Never surfaces raw API / network messages —
7919
+ * those stay in the console for debugging.
7920
+ */
7921
+ const PackageRegistryError = ({ variant, onRetry }) => {
7922
+ const isEmpty = variant === "empty";
7923
+ return /* @__PURE__ */ jsxs("div", {
7924
+ className: isEmpty ? "flex items-start gap-3 rounded-lg border border-destructive bg-destructive/10 p-4" : "flex items-start gap-3 rounded-lg border border-destructive bg-destructive/10 px-3 py-2.5",
7925
+ role: "alert",
7926
+ children: [
7927
+ /* @__PURE__ */ jsx(Icon, {
7928
+ name: "Error",
7929
+ size: 16,
7930
+ className: "mt-0.5 shrink-0 text-destructive"
7931
+ }),
7932
+ /* @__PURE__ */ jsxs("div", {
7933
+ className: "min-w-0 flex-1",
7934
+ children: [
7935
+ /* @__PURE__ */ jsx("p", {
7936
+ className: "text-sm font-medium text-destructive",
7937
+ children: isEmpty ? "Couldn't load packages" : "Couldn't refresh packages"
7938
+ }),
7939
+ /* @__PURE__ */ jsx("p", {
7940
+ className: "mt-0.5 text-xs text-muted-foreground",
7941
+ children: isEmpty ? "We couldn't reach the package registry. Check your connection and try again." : "Showing previously loaded packages. Check your connection and try again."
7942
+ }),
7943
+ isEmpty && onRetry && /* @__PURE__ */ jsx("button", {
7944
+ type: "button",
7945
+ onClick: onRetry,
7946
+ className: "mt-3 rounded-md bg-primary px-3 py-1.5 text-xs font-medium text-primary-foreground transition-colors hover:hover-effect",
7947
+ children: "Try again"
7948
+ })
7949
+ ]
7950
+ }),
7951
+ !isEmpty && onRetry && /* @__PURE__ */ jsx("button", {
7952
+ type: "button",
7953
+ onClick: onRetry,
7954
+ className: "shrink-0 self-center rounded-md border border-border bg-background px-2.5 py-1 text-xs font-medium text-foreground transition-colors hover:hover-effect",
7955
+ children: "Try again"
7956
+ })
7957
+ ]
7958
+ });
7959
+ };
7960
+ //#endregion
7961
+ //#region src/connect/components/modal/settings-modal-v2/package-manager/package-search-input.tsx
7962
+ /**
7963
+ * Plain controlled search box shared by the Installed/Available tabs. It only
7964
+ * reports the query — filtering happens in the panels (client-side today, a
7965
+ * registry search endpoint later).
7966
+ */
7967
+ const PackageSearchInput = (props) => {
7968
+ const { value, onChange, placeholder, disabled, className } = props;
7969
+ return /* @__PURE__ */ jsxs("div", {
7970
+ className: twMerge("relative", className),
7971
+ children: [/* @__PURE__ */ jsx(Icon, {
7972
+ name: "Search",
7973
+ size: 14,
7974
+ className: "absolute top-1/2 left-2 -translate-y-1/2 text-muted-foreground"
7975
+ }), /* @__PURE__ */ jsx(Input, {
7976
+ value,
7977
+ onChange: (e) => onChange(e.target.value),
7978
+ placeholder,
7979
+ disabled,
7980
+ className: "pl-7"
7981
+ })]
7982
+ });
7983
+ };
7984
+ //#endregion
7985
+ //#region src/connect/components/modal/settings-modal-v2/package-manager/available-packages-panel.tsx
7986
+ const LoadingRow = ({ label, center }) => /* @__PURE__ */ jsxs("div", {
7987
+ className: `flex items-center gap-2 text-sm text-muted-foreground ${center ? "justify-center" : ""}`,
7988
+ children: [/* @__PURE__ */ jsx(PackageAnimation, {
7989
+ animate: true,
7990
+ loop: true,
7991
+ color: "#6b7280",
7992
+ size: 24
7993
+ }), /* @__PURE__ */ jsx("span", { children: label })]
7994
+ });
7995
+ const AvailablePackagesPanel = (props) => {
7996
+ const { packages, installedNames, query, onQueryChange, serverSearch, isLoading, isLoadingMore, hasMore, onLoadMore, error, onRetry, mutable, onInstall, onUninstall, disabled } = props;
7997
+ const filtered = serverSearch ? packages : filterPackages(packages, query);
7998
+ const available = filtered.filter((p) => p.status === "available");
7999
+ const dismissed = filtered.filter((p) => p.status === "dismissed");
8000
+ const { name: queryName, tag: queryTag } = parsePackageSpec(query);
8001
+ const showNpmFallback = mutable && filtered.length === 0 && isPlausiblePackageName(queryName) && !installedNames.includes(queryName);
8002
+ const isEmpty = filtered.length === 0;
8003
+ const paginated = onLoadMore !== void 0;
8004
+ function renderContent() {
8005
+ if (isEmpty && isLoading) return /* @__PURE__ */ jsx(LoadingRow, {
8006
+ label: "Loading packages…",
8007
+ center: true
8008
+ });
8009
+ if (isEmpty && error) return /* @__PURE__ */ jsx(PackageRegistryError, {
8010
+ variant: "empty",
8011
+ onRetry
8012
+ });
8013
+ if (isEmpty) {
8014
+ if (showNpmFallback) return /* @__PURE__ */ jsx(NpmFallbackRow, {
8015
+ query,
8016
+ onInstall,
8017
+ disabled
8018
+ });
8019
+ return /* @__PURE__ */ jsx("p", {
8020
+ className: "text-sm text-foreground",
8021
+ children: query ? "No packages match your search." : "No packages available to install."
8022
+ });
8023
+ }
8024
+ return /* @__PURE__ */ jsxs("div", {
8025
+ className: "flex flex-col gap-4",
8026
+ children: [
8027
+ available.length > 0 && /* @__PURE__ */ jsx(PackageList, {
8028
+ packages: available,
8029
+ onInstall,
8030
+ onUninstall,
8031
+ preferredTag: queryTag
8032
+ }),
8033
+ dismissed.length > 0 && /* @__PURE__ */ jsx(PackageSubSection, {
8034
+ title: "Dismissed",
8035
+ count: dismissed.length,
8036
+ children: /* @__PURE__ */ jsx(PackageList, {
8037
+ packages: dismissed,
8038
+ onInstall,
8039
+ onUninstall,
8040
+ preferredTag: queryTag
8041
+ })
8042
+ }),
8043
+ isLoadingMore && /* @__PURE__ */ jsx(LoadingRow, {
8044
+ label: "Loading more…",
8045
+ center: true
8046
+ }),
8047
+ paginated && !hasMore && !isLoadingMore && /* @__PURE__ */ jsx("p", {
8048
+ className: "py-2 text-center text-sm text-muted-foreground",
8049
+ children: "You’ve reached the end of the list."
8050
+ })
8051
+ ]
8052
+ });
8053
+ }
8054
+ return /* @__PURE__ */ jsxs("div", {
8055
+ className: "flex h-full flex-col gap-3",
8056
+ children: [/* @__PURE__ */ jsxs("div", {
8057
+ className: "pr-3",
8058
+ children: [
8059
+ /* @__PURE__ */ jsx(PackageSearchInput, {
8060
+ value: query,
8061
+ onChange: onQueryChange,
8062
+ placeholder: "Search available packages",
8063
+ disabled
8064
+ }),
8065
+ !isEmpty && isLoading && /* @__PURE__ */ jsx("div", {
8066
+ className: "mt-3",
8067
+ children: /* @__PURE__ */ jsx(LoadingRow, { label: "Refreshing packages…" })
8068
+ }),
8069
+ !isEmpty && error && /* @__PURE__ */ jsx("div", {
8070
+ className: "mt-3",
8071
+ children: /* @__PURE__ */ jsx(PackageRegistryError, {
8072
+ variant: "refresh",
8073
+ onRetry
8074
+ })
8075
+ })
8076
+ ]
8077
+ }), /* @__PURE__ */ jsx(PackagePanelScrollArea, {
8078
+ onReachEnd: hasMore && onLoadMore ? onLoadMore : void 0,
8079
+ children: renderContent()
8080
+ })]
8081
+ });
8082
+ };
8083
+ //#endregion
8084
+ //#region src/connect/components/modal/settings-modal-v2/package-manager/installed-packages-panel.tsx
8085
+ const InstalledPackagesPanel = (props) => {
8086
+ const { packages, query, onQueryChange, onInstall, onUninstall, disabled } = props;
8087
+ const filtered = filterPackages(packages, query);
8088
+ const locallyInstalled = filtered.filter((p) => p.status === "local-install");
8089
+ const registryInstalled = filtered.filter((p) => p.status === "registry-install");
8090
+ return /* @__PURE__ */ jsxs("div", {
8091
+ className: "flex h-full flex-col gap-3",
8092
+ children: [/* @__PURE__ */ jsx("div", {
8093
+ className: "pr-3",
8094
+ children: /* @__PURE__ */ jsx(PackageSearchInput, {
8095
+ value: query,
8096
+ onChange: onQueryChange,
8097
+ placeholder: "Search installed packages",
8098
+ disabled
8099
+ })
8100
+ }), /* @__PURE__ */ jsx(PackagePanelScrollArea, { children: packages.length === 0 ? /* @__PURE__ */ jsx("p", {
8101
+ className: "text-sm text-foreground",
8102
+ children: "No packages installed."
8103
+ }) : filtered.length === 0 ? /* @__PURE__ */ jsx("p", {
8104
+ className: "text-sm text-foreground",
8105
+ children: "No installed packages match your search."
8106
+ }) : /* @__PURE__ */ jsxs("div", {
8107
+ className: "flex flex-col gap-4",
8108
+ children: [locallyInstalled.length > 0 && /* @__PURE__ */ jsx(PackageSubSection, {
8109
+ title: "Locally installed",
8110
+ count: locallyInstalled.length,
8111
+ children: /* @__PURE__ */ jsx(PackageList, {
8112
+ packages: locallyInstalled,
8113
+ onInstall,
8114
+ onUninstall
8115
+ })
8116
+ }), registryInstalled.length > 0 && /* @__PURE__ */ jsx(PackageSubSection, {
8117
+ title: "Installed from registry",
8118
+ count: registryInstalled.length,
8119
+ children: /* @__PURE__ */ jsx(PackageList, {
8120
+ packages: registryInstalled,
8121
+ onInstall,
8122
+ onUninstall
8123
+ })
8124
+ })]
8125
+ }) })]
8126
+ });
8127
+ };
8128
+ //#endregion
7931
8129
  //#region src/connect/components/modal/settings-modal-v2/package-manager/package-manager.tsx
7932
8130
  const PackageManager = (props) => {
7933
- const { registryPackageList, onInstall, onUninstall, mutable, disabled, className } = props;
8131
+ const { installedPackages, availablePackages, isAvailableLoading, isLoadingMoreAvailable, hasMoreAvailable, onLoadMoreAvailable, availableError, onAvailableRetry, onAvailableSearchChange, onInstall, onUninstall, onAvailableTabOpen, initialTab = "installed", mutable, disabled, className } = props;
8132
+ const [installedQuery, setInstalledQuery] = useState("");
8133
+ const [availableQuery, setAvailableQuery] = useState("");
8134
+ useEffect(() => {
8135
+ if (initialTab === "available") onAvailableTabOpen?.();
8136
+ }, []);
8137
+ const installedNames = installedPackages.map((p) => p.name);
7934
8138
  return /* @__PURE__ */ jsxs("div", {
7935
- className: twMerge("flex h-full flex-1 flex-col rounded-lg bg-background p-3 text-foreground", className),
7936
- children: [mutable && /* @__PURE__ */ jsx(PackageManagerInput, {
7937
- className: "mb-4",
7938
- registryPackageList,
7939
- onInstall,
7940
- disabled
7941
- }), /* @__PURE__ */ jsx(PackageManagerList, {
7942
- registryPackageList,
7943
- onUninstall,
7944
- onInstall
8139
+ className: twMerge("flex min-h-0 flex-1 flex-col rounded-lg bg-background pt-3 pl-3 text-foreground", className),
8140
+ children: [/* @__PURE__ */ jsx("h2", {
8141
+ className: "mb-4 shrink-0 pr-3 font-semibold text-foreground",
8142
+ children: "Packages"
8143
+ }), /* @__PURE__ */ jsxs(Tabs, {
8144
+ defaultValue: initialTab,
8145
+ listClassName: "pr-3",
8146
+ onValueChange: (value) => {
8147
+ if (value === "available") onAvailableTabOpen?.();
8148
+ },
8149
+ children: [/* @__PURE__ */ jsx(TabContent, {
8150
+ value: "installed",
8151
+ label: `Installed (${installedPackages.length})`,
8152
+ children: /* @__PURE__ */ jsx(InstalledPackagesPanel, {
8153
+ packages: installedPackages,
8154
+ query: installedQuery,
8155
+ onQueryChange: setInstalledQuery,
8156
+ onInstall,
8157
+ onUninstall,
8158
+ disabled
8159
+ })
8160
+ }), /* @__PURE__ */ jsx(TabContent, {
8161
+ value: "available",
8162
+ label: "Available",
8163
+ children: /* @__PURE__ */ jsx(AvailablePackagesPanel, {
8164
+ packages: availablePackages,
8165
+ installedNames,
8166
+ query: availableQuery,
8167
+ onQueryChange: (q) => {
8168
+ setAvailableQuery(q);
8169
+ onAvailableSearchChange?.(q);
8170
+ },
8171
+ serverSearch: onAvailableSearchChange !== void 0,
8172
+ isLoading: isAvailableLoading,
8173
+ isLoadingMore: isLoadingMoreAvailable,
8174
+ hasMore: hasMoreAvailable,
8175
+ onLoadMore: onLoadMoreAvailable,
8176
+ error: availableError,
8177
+ onRetry: onAvailableRetry,
8178
+ mutable,
8179
+ onInstall,
8180
+ onUninstall,
8181
+ disabled
8182
+ })
8183
+ })]
7945
8184
  })]
7946
8185
  });
7947
8186
  };
@@ -7950,19 +8189,21 @@ const PackageManager = (props) => {
7950
8189
  function SettingsModal(props) {
7951
8190
  const { title, overlayProps, contentProps, onOpenChange, tabs, defaultTab, navFooter, ...restProps } = props;
7952
8191
  const [selectedTab, setSelectedTab] = useState(defaultTab ?? tabs.at(0)?.id);
7953
- const tabsContent = tabs.map((tab) => /* @__PURE__ */ jsx("button", {
7954
- type: "button",
7955
- onClick: () => setSelectedTab(tab.id),
7956
- children: /* @__PURE__ */ jsxs("div", {
7957
- className: twMerge("flex h-9 w-48 cursor-pointer items-center gap-x-2 rounded-md pl-3 text-foreground hover:hover-effect", selectedTab === tab.id ? "bg-background" : "bg-transparent"),
8192
+ const tabsContent = tabs.map((tab) => {
8193
+ const isActive = selectedTab === tab.id;
8194
+ return /* @__PURE__ */ jsxs("button", {
8195
+ type: "button",
8196
+ "aria-current": isActive ? "page" : void 0,
8197
+ onClick: isActive ? void 0 : () => setSelectedTab(tab.id),
8198
+ className: twMerge("flex h-9 w-48 items-center gap-x-2 rounded-md pl-3 text-left text-foreground", isActive ? "cursor-default bg-accent" : "cursor-pointer bg-transparent hover:bg-accent"),
7958
8199
  children: [tab.icon, /* @__PURE__ */ jsx("span", { children: tab.label })]
7959
- })
7960
- }, tab.id));
8200
+ }, tab.id);
8201
+ });
7961
8202
  const SelectedTabComponent = tabs.find((tab) => tab.id === selectedTab)?.content;
7962
8203
  return /* @__PURE__ */ jsxs(Modal, {
7963
8204
  contentProps: {
7964
8205
  ...contentProps,
7965
- className: twMerge("min-h-full w-full max-w-4xl rounded-xl", contentProps?.className)
8206
+ className: twMerge("flex max-h-[calc(100dvh-14rem)] min-h-full w-full max-w-4xl flex-col rounded-xl", contentProps?.className)
7966
8207
  },
7967
8208
  onOpenChange,
7968
8209
  overlayProps: {
@@ -7986,7 +8227,7 @@ function SettingsModal(props) {
7986
8227
  })
7987
8228
  })]
7988
8229
  }), /* @__PURE__ */ jsxs("div", {
7989
- className: "flex flex-1",
8230
+ className: "flex min-h-0 flex-1",
7990
8231
  children: [/* @__PURE__ */ jsxs("div", {
7991
8232
  className: "flex flex-col p-3 pt-6",
7992
8233
  children: [/* @__PURE__ */ jsx("div", {
@@ -7997,7 +8238,7 @@ function SettingsModal(props) {
7997
8238
  children: navFooter
7998
8239
  })]
7999
8240
  }), /* @__PURE__ */ jsx("div", {
8000
- className: "m-6 flex h-full flex-1 flex-col overflow-hidden rounded-lg border border-border bg-background",
8241
+ className: "m-6 flex min-h-0 flex-1 flex-col overflow-hidden rounded-lg border border-border bg-background",
8001
8242
  children: typeof SelectedTabComponent === "function" ? /* @__PURE__ */ jsx(SelectedTabComponent, {}) : SelectedTabComponent
8002
8243
  })]
8003
8244
  })]
@@ -8772,50 +9013,20 @@ var renown_short_hover_default = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAA
8772
9013
  //#region assets/renown-short.png
8773
9014
  var renown_short_default = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJAAAACQCAYAAADnRuK4AAAACXBIWXMAACxLAAAsSwGlPZapAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAtmSURBVHgB7Z3dbtvmGcefl5LsqHYCq0C6tEUCZ0kDzAFqd0NTYAmweAfr0YD0CrpeQboriH0H6RUsu4ChAYodtCdJD3LQBGttILEBJ4tdJ2uzBoi0yIpsi+S790+ZDkmREilSHySfX6FKpkgliH5+nuf9pKAEkFLO1Bu7VzRNzEuiWfXzglDHSIgZYsYC9b1sCaEeJFZMU66WCnS7XC5vUUwE9Qmk2dndvar+ZpetB5NCxIr6Hr+II1NkgQ7FMeTnHGGygxLhRkGj5agiRRKo3mxeY3EyjkZLR8vl5bCnhxKo2WzOGqb4UpJcCDpH1T+E/wpKY+3gU4XoO0MyCaKyhvVsqifTNNWzVM8y8Hz1rW2pr3ExTDTq+Q3vNPc/lYZ+3S/qwI+iVlDSCJYlZcgDiVqGQdLXJVGTJD47NjV5s9vndP3W6429a8rZpY6LIE6hoB4aMenHMMxgkXqktECBguSBNHhwxMkWiEgt3SRDpbgOukjka8HLxt4VQeaX3uOlIkedrKPr7WjkRWiFv0yXJ/7ecdx7AAWzbsgfnDUPgs1EsWgVykz2QTTaa+melCZqRU1+4C2sO8KJSoe3vAXzZInlyRMoTxAw3MgZXbXEvee6BELdg6EI5zGkLa538gcCRkk1lNzIhXqjseQ8cmiGlbpM2nS+WdA0migViMkvKKx1V00kavr+5OlKRdTw02EEUqnrmvNCBJ1SkQvmvFMsauROQHKmOPHqc/sn6y2/6MMtLsams2X2OgpZhrQM92h6u6OQ5WHadItCliWqSL7quqDAdQ/jpqB5nBDaH6wnv/R1ZKLILS/GBbqEdvdarmP6/pGK5k1f1qg6y8N4gBHevsBSafeKOuSeoqGxPEwAXjcwvUfVQGLedZLGxTPjj9cNKWhWw/9cJ3EAYgLwuqHaZvM4Nus+zAYxAXSkMDGj9TiHYQ7pVEP1BxEzFL6+9T3tvGrS4u/fpzcrRykrcMU8BLb/85yePa/STmOX1h49oSzBAg2BJ0qgw9dPn1OWYIEGzH5LtyKQ8+dnv1QpK7BAA2ZbRRxI42T1wSZlBRZowKw/2u44hnpov9WiLMACDRCI8qK64/ve2sZTygIs0ABZvf848L31je1MRCEWaEA82vxZRaBa4Puoi1bvp78WYoEGxOra457nrD18kvoWGQs0AFYfPLY6DcOdm+4oxAIlzE6jSSsRpEChvbaR3t5pFihBUBR/fft7isq9lY3UpjIWKEHufLceOnV1XHtvzYpeaYMFSgjUPds/9T/OBfEQvdLWtGeBEgDyrCRQDFsS3UqXRCxQTJKSx+ZFbSdVErFAMbi38jBReWwg0Vff3E1FTcQC9YHV2lJRYm1jmwaFXRONu0Si3mi69qEqT5aICQb9NnfurvXd2uqHhfO/pvnzp2kcaHpWp7JAIUHUWX2wNdCo0403Z6Zp8eL7ND1VplHCAvXBuuopXlHFsndi2Cg4O/u2FY1GJRILFBJEnEebz2j94fZQ01UYpqeO0InjlZGIxAL1ADUOJsFjOsY4RJxenHr3OJ05/Tadeuc4DQMWKAC0dtqtnvGKNmGZKBXp4oU5S6hB4hWIm/EHoO8lrfIAa/XHT8NfMsQCHXDirYqqK9J7FytEoLmzp2jYcArzgCiEqRWYUTjuEQnSWPWPSlsoqocB10ARwIJATH7vNrd5FECc35w7SXPnTlmvhwkL1AdokY1DRBqlODYsUAzQmTiqOcwnVTP90kdzIxPHhgWKSXuQ819Di0YQ5sMPzlk90OMAC5QQd1c2rCGOQYIe548v/856Hhe8AvEGU31yYeGcFR0GldLQpbB4aX7kKasXLFAMMM0CJC3RGZWuLqle5TQwcoGGUUsMMgUkLVGa5AEjF+gf/7xDwwQyTb9RpomJIlVmpg96oON1wiUlEeb8pEkekLsUhohnRz10FNpfOiRCr26/rR1IhPGofgtriL14cZ7SBtdAB2AaBx5YZXF29p2+ppBCov/+UlMDs3WKyri1tsLCg6keEJ3QYYjU+mjr50jXosWEaadRW04fLryXSnkACxQARMLk+ah1DUSYP6iJwoDmOoYm0goL1ANEI4gUhTk1XhV2asjFC+cpzbBAIUAqiypRmCiEc9KaumxYoJBAoij7+PSaoAZxxmV8Kw4sUASwj8+LavgWVrcodEa19NIefQALFBGshw9LtyiUhegDWKCIWP1FEXYT84tCGK7IQvQBqe1IxBdwJuRvcbW6Qy/+V09s3A1Ne0SXMODWTugXcq4xO3s6G9EHpFcgNZ61EKG/BSQ1NRU9zVi5OlHqPXfKnvhuD3HYq0qzQq5SGH7z//ynj2LXH+077oSfaO9cNfqrDMkDclcD2Ss4464BQy0UFqS7k+8et0bbo0bNcSe3g6noAf7qm+/6Xv8eNQ3+UY2RZZHctsKsIjxGMVvtY8Q9i+S6GR9nR4s0r6NPklwLlKW7J4+KXAs07ise0gD3RDOxyLVAadiBbNzJtUAvYrSksjKWFZdcC/TvzWhznp1gKIXJsUDYEzFKb7KXSmWamBwLtP7waay+nCwNiMYhlwJh7VfcHedPvJXe/RSTJFcdIdbCwfubsVIXwDykMFM58kBqBdp51bSW3IShgY0zlTRJDT9kaUJYXNIrkJJhFNvNofbh+uc13BMdkYsp2z1j0LBAEcjCQsCkYYFCghmMC2Ny07dxggUKgXWzt0vp27tnGPB8hh6My/7M4wr/qwQAYbDJVJq3XhkGLJAPuJ0AVk9w1OkN10A+oJeZ5QkHC+QD7tCDladMb1L7a4be4I8Xfxv4fpwbo2Cm4trGU262hyCzESjuLZE4CoUjswLZ99bqFzsKMd3JdA3EUWjwZFogjkKDJ/OtMI5CgyXzAtkbPPULR6Hu5KIfaO69eMMRHIWCyYVA7W3l+p8Ez1EomNz0RM/H3BmMo5A/uRGo187xveAo5E+uxsI4CiVPrgTiKJQ8uRuN5yiULLkTiKNQsuRyPhDulBMHjkKvyaVAWJocZ30XR6HX5HZG4pmYtzvgKNQmtwLFHWTlKNQmtwLFneoBOArlfFI9R6H4iHqjKZ0HypO8cRITTHPPHXFVBJKuG19JSQzji58amiRR630awygzTLcbgmhLE0KsOA+a7A8TgFcNKZRAZJo/Og8apkkM44fpdcOUq0hhrggkuQhiAjA9bsAdzWjt3nSdpHIYO8R4QWAxPfWNUaDbWqVSqSmVbjvf0E2DGMaJ2VFAy5VKubzV7kiU9K3zTUPnOohx0zLcTphSfIFnSyBd373u7A+Ca7rBUYhpYyh5vLUx0heeLYGsNGa2jbLRdZNrIcYSxxt9BGk3kL7arw+oVqszxYnJTXXocLpesahRqVAgJr/s64YVgZzoGp22BTocTA2KQpzK8ouuxPHKo6qfZVseILwX1Ru7P6jAteA8NqlGrDVNEJMfkLp29933lBWq53n6jbJr27aO6Ry6Jj/xDrBi2gJ3MOYHQzXZ91rezCNrLUGL3nM7BEJ4klL81XWpesBGTmfZB2nLL2BIKnzmTF02vhPKjk2Xb5BJy97jLVUToajiaJQ9rNaW+m7x6MRcPjY1edPvuq6FTb3eXFKKXeu4SCXDYkGzHkz6QdTRffp62pjLR6emloKu7VkZv3zZuCIK4m/O5v3hxQciFVSBjddMeoAsuolWlgwQR9aEKmWmkY26EOpbrzabsyVJt9SfMxt0DlppmmiLhNf4YJZqPLAFQXGMEXW/gVEnmCPWEvITv5qn41yKQFBKY7KCtPoCjx4tL4W9InKIQDQqGOaSENqnxGSEtjj69JHrFeGd4tydvnNMWyS6rMLdVW/HI5MShBoQNejbfsR5/REJcCiTJZKYl4Jm1QfPEjMmyBoWT2AOj+rQ+REzCY2pIzf7lcbJ/wH9VD8KK3ri6QAAAABJRU5ErkJggg==";
8774
9015
  //#endregion
8775
- //#region src/connect/components/account-popover/account-popover-login.tsx
8776
- const AccountPopoverLogin = ({ onLogin }) => {
8777
- const [loading, setLoading] = useState(false);
8778
- const allowLogin = !loading && !!onLogin;
8779
- const content = loading ? /* @__PURE__ */ jsx(Icon, {
8780
- name: "Reload",
8781
- size: 14,
8782
- className: "animate-spin"
8783
- }) : /* @__PURE__ */ jsx("span", { children: "Connect" });
8784
- const handleLogin = () => {
8785
- if (onLogin) {
8786
- setLoading(true);
8787
- onLogin();
8788
- }
8789
- };
8790
- return /* @__PURE__ */ jsxs("div", {
8791
- className: "p-4",
8792
- children: [/* @__PURE__ */ jsx("div", {
8793
- className: "mb-4 flex justify-center",
8794
- children: /* @__PURE__ */ jsx("div", {
8795
- className: "flex h-5.5 w-20.75 items-center justify-center overflow-hidden text-foreground",
8796
- children: /* @__PURE__ */ jsx(Icon, {
8797
- name: "RenownLight",
8798
- size: 83
8799
- })
8800
- })
8801
- }), /* @__PURE__ */ jsx("button", {
8802
- onClick: allowLogin ? handleLogin : void 0,
8803
- className: twMerge("mt-4 flex h-7 w-full cursor-pointer items-center justify-center rounded-lg border border-border bg-transparent text-sm text-foreground active:active-effect", allowLogin ? "cursor-pointer" : "cursor-wait"),
8804
- type: "button",
8805
- children: content
8806
- })]
8807
- });
8808
- };
8809
- //#endregion
8810
9016
  //#region src/connect/components/sidebar/sidebar-login.tsx
8811
9017
  const SidebarLogin = ({ onLogin }) => {
8812
- const content = /* @__PURE__ */ jsx(AccountPopoverLogin, { onLogin });
9018
+ const [open, setOpen] = useState(false);
8813
9019
  const { theme } = useTheme();
8814
9020
  const isDark = theme === "dark";
8815
9021
  const src = isDark ? renown_short_dark_default : renown_short_default;
8816
9022
  const hoverSrc = isDark ? renown_short_hover_dark_default : renown_short_hover_default;
8817
9023
  return /* @__PURE__ */ jsx(AccountPopover, {
8818
- content,
9024
+ open,
9025
+ onOpenChange: setOpen,
9026
+ content: /* @__PURE__ */ jsx(AccountPopoverLogin, { onLogin: onLogin ? () => {
9027
+ setOpen(false);
9028
+ onLogin();
9029
+ } : void 0 }),
8819
9030
  children: /* @__PURE__ */ jsxs("div", {
8820
9031
  className: twMerge("group/sidebar-footer flex w-full items-baseline justify-start text-sm/10 font-semibold text-foreground", onLogin ? "cursor-pointer" : "cursor-wait"),
8821
9032
  children: [/* @__PURE__ */ jsx("img", {
@@ -9139,6 +9350,6 @@ const removeSuccessFiles = (files) => {
9139
9350
  return files.filter((file) => file.status !== "SUCCESS");
9140
9351
  };
9141
9352
  //#endregion
9142
- export { About, AccountPopover, AddDriveModal, AddLocalDriveForm, AddRemoteDriveForm, AnimatedLoader, Breadcrumb, Breadcrumbs, CONFLICT, ChannelInspector, Combobox, ConnectConfirmationModal, ConnectDeleteDriveModal, ConnectDeleteItemModal, ConnectDropdownMenu, ConnectReplaceDuplicateModal, ConnectSearchBar, ConnectSelect, ConnectSidebar, ConnectSidebarFooter, ConnectSidebarHeader, ConnectTooltip, ConnectTooltipProvider, ConnectUpgradeDriveModal, ConnectionStateBadge, CookieBanner, CreateDocumentModal, DBExplorer, DangerZone, DebugInspector, DefaultEditor, DefaultEditorLoader, DefaultEditorSelect, DependencyVersions, Disclosure, Divider, DocumentStateViewer, DocumentTimeline, DocumentToolbar, DriveAuthGate, DriveSettingsModal, DropZone, DropZoneWrapper, ENSAvatar, ERROR, EditorActionButtons, EditorUndoRedoButtons, FileItem, FolderItem, Footer, FooterLink, FormInput, FormattedJsonViewer, HomeBackgroundImage, HomeScreen, HomeScreenAddDriveItem, HomeScreenItem, INITIAL_SYNC, InspectorModal, IntegrityInspector, LoadingScreen, LogoAnimation, MISSING, NodeInput, ObjectInspectorModal, PackageInstallModal, PackageManager, PackageManagerInput, PackageManagerList, PackageManagerListItem, ProcessorsInspector, QueueInspector, ReadRequiredModal, RemotesInspector, RevisionHistory, SUCCESS, SYNCING, SettingsModal, SidebarAddDriveItem, SidebarItem, SidebarLogin, SidebarUser, SyncStatusIcon, TabContent, Tabs, ThemeSwitch, Toggle, ToolbarButton, ToolbarCloseButton, ToolbarContainer, ToolbarControlsContainer, ToolbarDownloadButton, ToolbarHistoryButton, ToolbarInput, ToolbarName, ToolbarRedoButton, ToolbarSwitchboardButton, ToolbarUndoButton, UploadFileItem, UploadFileList, UploadFileListContainer, WorkerInspector, debugNodeOptions, debugNodeOptionsMap, defaultDriveOptions, defaultNodeOptions, fileNodeDropdownOptions, folderNodeDropdownOptions, formatEthAddress, getFolderStatus, locationInfoByLocation, nodeOptions, normalNodeOptions, removeSuccessFiles, sharingTypeOptions, sortFilesByStatus, syncStatuses, useEns, verifyPackageJsonFields };
9353
+ export { About, AccountPopover, AccountPopoverLogin, AddDriveModal, AddLocalDriveForm, AddRemoteDriveForm, AnimatedLoader, AvailablePackagesPanel, Breadcrumb, Breadcrumbs, CONFLICT, ChannelInspector, Combobox, ConnectConfirmationModal, ConnectDeleteDriveModal, ConnectDeleteItemModal, ConnectDropdownMenu, ConnectReplaceDuplicateModal, ConnectSearchBar, ConnectSelect, ConnectSidebar, ConnectSidebarFooter, ConnectSidebarHeader, ConnectTooltip, ConnectTooltipProvider, ConnectUpgradeDriveModal, ConnectionStateBadge, CookieBanner, CreateDocumentModal, DBExplorer, DangerZone, DebugInspector, DefaultEditor, DefaultEditorLoader, DefaultEditorSelect, DependencyVersions, Disclosure, Divider, DocumentStateViewer, DocumentTimeline, DocumentToolbar, DriveAuthGate, DriveSettingsModal, DropZone, DropZoneWrapper, ENSAvatar, ERROR, EditorActionButtons, EditorUndoRedoButtons, FileItem, FolderItem, Footer, FooterLink, FormInput, FormattedJsonViewer, HomeBackgroundImage, HomeScreen, HomeScreenAddDriveItem, HomeScreenItem, INITIAL_SYNC, InspectorModal, InstalledPackagesPanel, IntegrityInspector, LoadingScreen, LogoAnimation, MISSING, ModalButton, NodeInput, ObjectInspectorModal, PackageInstallModal, PackageList, PackageManager, PackageManagerListItem, PackagePanelScrollArea, PackageRegistryError, PackageSubSection, ProcessorsInspector, QueueInspector, ReadRequiredModal, RemotesInspector, RenownLoginMethods, RevisionHistory, SUCCESS, SYNCING, SettingsModal, SidebarAddDriveItem, SidebarItem, SidebarLogin, SidebarUser, SyncStatusIcon, TabContent, Tabs, ThemeSwitch, Toggle, ToolbarButton, ToolbarCloseButton, ToolbarContainer, ToolbarControlsContainer, ToolbarDownloadButton, ToolbarHistoryButton, ToolbarInput, ToolbarName, ToolbarRedoButton, ToolbarSwitchboardButton, ToolbarUndoButton, UploadFileItem, UploadFileList, UploadFileListContainer, WorkerInspector, debugNodeOptions, debugNodeOptionsMap, defaultDriveOptions, defaultNodeOptions, fileNodeDropdownOptions, folderNodeDropdownOptions, formatEthAddress, formatFileSize, generateId, getFolderStatus, locationInfoByLocation, mapProgressStageToStatus, mapUploadsToFileItems, nodeOptions, normalNodeOptions, removeSuccessFiles, sharingTypeOptions, sortFilesByStatus, syncStatuses, useEns, verifyPackageJsonFields };
9143
9354
 
9144
9355
  //# sourceMappingURL=index.js.map