@tangle-network/sandbox-ui 0.118.0 → 0.120.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/README.md +31 -1
- package/dist/{dashboard-D4un5GtD.js → dashboard-CnGK2S3A.js} +11 -11
- package/dist/dashboard.js +1 -1
- package/dist/files.d.ts +1 -1
- package/dist/globals.css +154 -39
- package/dist/index-B6wKsKV6.d.ts +2 -0
- package/dist/{index-CcbhfDa-.d.ts → index-BxFd7DOv.d.ts} +34 -2
- package/dist/{index-z_zNuZHm.d.ts → index-DJyIXUx9.d.ts} +1 -1
- package/dist/{index-BHopt1SR.d.ts → index-SJKueyy4.d.ts} +2 -2
- package/dist/index.d.ts +5 -5
- package/dist/index.js +5 -5
- package/dist/integrations.js +82 -47
- package/dist/pages.d.ts +22 -1
- package/dist/pages.js +270 -223
- package/dist/primitives-BQGtwZX3.js +25 -0
- package/dist/primitives.d.ts +1 -1
- package/dist/primitives.js +1 -1
- package/dist/styles.css +154 -39
- package/dist/{workbench-DxYaeFaa.js → workbench-DuIQZobw.js} +1 -1
- package/dist/workbench.d.ts +1 -1
- package/dist/workbench.js +1 -1
- package/dist/{workspace--bNv-rQy.js → workspace-iRO3GeHT.js} +156 -64
- package/dist/workspace.d.ts +2 -2
- package/dist/workspace.js +2 -2
- package/package.json +3 -3
- package/dist/index-CXX5IpH2.d.ts +0 -2
- package/dist/primitives-N-59i3-7.js +0 -25
package/dist/pages.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { $ as Select, C as DialogTitle$1, G as Input$1, Nt as Textarea$1, Y as PageHeader$1, _ as DialogContent$1, a as Badge$1, b as DialogHeader$1, ct as SelectValue, et as SelectContent, h as Dialog$1, ht as Switch, nt as SelectItem, o as Button$1, st as SelectTrigger, v as DialogDescription$1, y as DialogFooter$1 } from "./primitives-
|
|
1
|
+
import { $ as Select$1, C as DialogTitle$1, G as Input$1, Nt as Textarea$1, Y as PageHeader$1, _ as DialogContent$1, a as Badge$1, b as DialogHeader$1, ct as SelectValue$1, et as SelectContent$1, h as Dialog$1, ht as Switch, nt as SelectItem$1, o as Button$1, st as SelectTrigger$1, v as DialogDescription$1, y as DialogFooter$1 } from "./primitives-BQGtwZX3.js";
|
|
2
2
|
import { t as cn$1 } from "./utils-DzWbktWG.js";
|
|
3
3
|
import { i as PricingPage, n as TemplateCard, o as BillingDashboard, r as UsageChart, t as InfoPanel } from "./info-panel-C9cqDzOL.js";
|
|
4
4
|
import { Badge, Button, Card, Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, EmptyState, Input, Skeleton, SkeletonCard, Tabs, TabsContent, TabsList, TabsTrigger } from "@tangle-network/ui/primitives";
|
|
@@ -1490,25 +1490,25 @@ function ProvisioningWizard({ environments: environmentsProp, onLoadEnvironments
|
|
|
1490
1490
|
htmlFor: `${fieldIdPrefix}-driver`,
|
|
1491
1491
|
className: cn$1(FIELD_LABEL_CLASS, "mb-1.5"),
|
|
1492
1492
|
children: "Virtualization Driver"
|
|
1493
|
-
}), /* @__PURE__ */ jsxs(Select, {
|
|
1493
|
+
}), /* @__PURE__ */ jsxs(Select$1, {
|
|
1494
1494
|
value: driver,
|
|
1495
1495
|
onValueChange: (value) => {
|
|
1496
1496
|
if (VALID_DRIVERS.has(value)) setDriver(value);
|
|
1497
1497
|
},
|
|
1498
|
-
children: [/* @__PURE__ */ jsx(SelectTrigger, {
|
|
1498
|
+
children: [/* @__PURE__ */ jsx(SelectTrigger$1, {
|
|
1499
1499
|
id: `${fieldIdPrefix}-driver`,
|
|
1500
1500
|
className: "h-9",
|
|
1501
|
-
children: /* @__PURE__ */ jsx(SelectValue, {})
|
|
1502
|
-
}), /* @__PURE__ */ jsxs(SelectContent, { children: [
|
|
1503
|
-
/* @__PURE__ */ jsx(SelectItem, {
|
|
1501
|
+
children: /* @__PURE__ */ jsx(SelectValue$1, {})
|
|
1502
|
+
}), /* @__PURE__ */ jsxs(SelectContent$1, { children: [
|
|
1503
|
+
/* @__PURE__ */ jsx(SelectItem$1, {
|
|
1504
1504
|
value: "docker",
|
|
1505
1505
|
children: "Docker container (Default)"
|
|
1506
1506
|
}),
|
|
1507
|
-
/* @__PURE__ */ jsx(SelectItem, {
|
|
1507
|
+
/* @__PURE__ */ jsx(SelectItem$1, {
|
|
1508
1508
|
value: "firecracker",
|
|
1509
1509
|
children: "Firecracker microVM (Secure)"
|
|
1510
1510
|
}),
|
|
1511
|
-
/* @__PURE__ */ jsx(SelectItem, {
|
|
1511
|
+
/* @__PURE__ */ jsx(SelectItem$1, {
|
|
1512
1512
|
value: "tangle",
|
|
1513
1513
|
children: "Tangle Distributed Node"
|
|
1514
1514
|
})
|
|
@@ -2698,7 +2698,13 @@ function parseEnvText(text) {
|
|
|
2698
2698
|
//#region src/pages/secrets-page.tsx
|
|
2699
2699
|
/** Cap pasted/uploaded import sources so a pathological file cannot blow up the parser/UI. */
|
|
2700
2700
|
const MAX_IMPORT_FILE_BYTES = 262144;
|
|
2701
|
-
|
|
2701
|
+
const DEFAULT_DESCRIPTION = "Secrets are securely stored and automatically exposed as environment variables across all your sandboxes.";
|
|
2702
|
+
const DEFAULT_CREATE_DESCRIPTION = "Secrets are automatically exposed as environment variables across all your new sandboxes.";
|
|
2703
|
+
const DEFAULT_EMPTY_DESCRIPTION = "Create a secret to inject into your sandboxes.";
|
|
2704
|
+
const DEFAULT_DELETE_CONSEQUENCE = "Sandboxes using this secret will lose access to it.";
|
|
2705
|
+
function SecretsPage({ apiClient, className, teamSecretsHint, title = "Environment Secrets", description = DEFAULT_DESCRIPTION, createDescription = DEFAULT_CREATE_DESCRIPTION, emptyDescription = DEFAULT_EMPTY_DESCRIPTION, deleteConsequence = DEFAULT_DELETE_CONSEQUENCE, variant = "page" }) {
|
|
2706
|
+
const pane = variant === "pane";
|
|
2707
|
+
const canReplace = typeof apiClient.updateSecret === "function";
|
|
2702
2708
|
const [secrets, setSecrets] = React$1.useState([]);
|
|
2703
2709
|
const [loading, setLoading] = React$1.useState(true);
|
|
2704
2710
|
const [error, setError] = React$1.useState(null);
|
|
@@ -2708,6 +2714,7 @@ function SecretsPage({ apiClient, className, teamSecretsHint }) {
|
|
|
2708
2714
|
const [showValue, setShowValue] = React$1.useState(false);
|
|
2709
2715
|
const [isCreating, setIsCreating] = React$1.useState(false);
|
|
2710
2716
|
const [createError, setCreateError] = React$1.useState(null);
|
|
2717
|
+
const [replaceTarget, setReplaceTarget] = React$1.useState(null);
|
|
2711
2718
|
const [deleteTarget, setDeleteTarget] = React$1.useState(null);
|
|
2712
2719
|
const [isDeleting, setIsDeleting] = React$1.useState(false);
|
|
2713
2720
|
const [isImportOpen, setIsImportOpen] = React$1.useState(false);
|
|
@@ -2740,16 +2747,39 @@ function SecretsPage({ apiClient, className, teamSecretsHint }) {
|
|
|
2740
2747
|
React$1.useEffect(() => {
|
|
2741
2748
|
loadSecrets();
|
|
2742
2749
|
}, [loadSecrets]);
|
|
2750
|
+
const openCreate = () => {
|
|
2751
|
+
setReplaceTarget(null);
|
|
2752
|
+
setNewName("");
|
|
2753
|
+
setNewValue("");
|
|
2754
|
+
setCreateError(null);
|
|
2755
|
+
setShowValue(false);
|
|
2756
|
+
setIsCreateOpen(true);
|
|
2757
|
+
};
|
|
2758
|
+
const openReplace = (name) => {
|
|
2759
|
+
setReplaceTarget(name);
|
|
2760
|
+
setNewName(name);
|
|
2761
|
+
setNewValue("");
|
|
2762
|
+
setCreateError(null);
|
|
2763
|
+
setShowValue(false);
|
|
2764
|
+
setIsCreateOpen(true);
|
|
2765
|
+
};
|
|
2766
|
+
const closeCreate = () => {
|
|
2767
|
+
setIsCreateOpen(false);
|
|
2768
|
+
setReplaceTarget(null);
|
|
2769
|
+
setNewName("");
|
|
2770
|
+
setNewValue("");
|
|
2771
|
+
setCreateError(null);
|
|
2772
|
+
setShowValue(false);
|
|
2773
|
+
};
|
|
2743
2774
|
const handleCreate = async () => {
|
|
2744
2775
|
if (!newName.trim() || !newValue.trim()) return;
|
|
2745
2776
|
setIsCreating(true);
|
|
2746
2777
|
setCreateError(null);
|
|
2747
2778
|
try {
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
setShowValue(false);
|
|
2779
|
+
const update = apiRef.current.updateSecret;
|
|
2780
|
+
if (replaceTarget && update) await update(replaceTarget, newValue);
|
|
2781
|
+
else await apiRef.current.createSecret(newName.trim(), newValue);
|
|
2782
|
+
closeCreate();
|
|
2753
2783
|
await loadSecrets(false);
|
|
2754
2784
|
} catch (err) {
|
|
2755
2785
|
setCreateError(err instanceof Error ? err.message : "Failed to create secret");
|
|
@@ -2886,26 +2916,48 @@ function SecretsPage({ apiClient, className, teamSecretsHint }) {
|
|
|
2886
2916
|
return dateStr;
|
|
2887
2917
|
}
|
|
2888
2918
|
};
|
|
2919
|
+
const actions = /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("button", {
|
|
2920
|
+
type: "button",
|
|
2921
|
+
onClick: () => setIsImportOpen(true),
|
|
2922
|
+
className: "inline-flex items-center gap-1.5 whitespace-nowrap rounded-lg border border-[var(--md3-outline-variant)] bg-surface-container px-3 py-2 text-sm font-semibold text-foreground transition-colors hover:bg-surface-container-high active:scale-[0.97] sm:gap-2",
|
|
2923
|
+
children: [/* @__PURE__ */ jsx(Upload, {
|
|
2924
|
+
className: "h-4 w-4",
|
|
2925
|
+
"aria-hidden": "true"
|
|
2926
|
+
}), "Import .env"]
|
|
2927
|
+
}), /* @__PURE__ */ jsxs("button", {
|
|
2928
|
+
type: "button",
|
|
2929
|
+
onClick: openCreate,
|
|
2930
|
+
className: "inline-flex items-center gap-1.5 whitespace-nowrap rounded-lg border border-[var(--border-accent,transparent)] bg-[var(--btn-primary-bg)] px-3 py-2 text-sm font-semibold text-[var(--btn-primary-text)] transition-colors hover:bg-[var(--btn-primary-hover)] active:scale-[0.97] sm:gap-2 sm:px-4",
|
|
2931
|
+
children: [/* @__PURE__ */ jsx(Plus, {
|
|
2932
|
+
className: "h-4 w-4",
|
|
2933
|
+
"aria-hidden": "true"
|
|
2934
|
+
}), "New Secret"]
|
|
2935
|
+
})] });
|
|
2889
2936
|
return /* @__PURE__ */ jsxs("div", {
|
|
2890
|
-
className: cn$1("mx-auto w-full max-w-6xl space-y-
|
|
2937
|
+
className: cn$1(pane ? "flex h-full min-h-0 w-full flex-col" : "mx-auto w-full max-w-6xl space-y-6", className),
|
|
2891
2938
|
children: [
|
|
2892
|
-
/* @__PURE__ */
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
|
|
2904
|
-
|
|
2905
|
-
|
|
2939
|
+
pane ? /* @__PURE__ */ jsxs("header", {
|
|
2940
|
+
className: "flex shrink-0 flex-wrap items-center justify-between gap-x-6 gap-y-3 border-b border-border px-4 py-4 sm:px-6",
|
|
2941
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
2942
|
+
className: "min-w-0 flex-1 basis-64",
|
|
2943
|
+
children: [/* @__PURE__ */ jsx("h1", {
|
|
2944
|
+
className: "text-lg font-semibold tracking-tight text-foreground",
|
|
2945
|
+
children: title
|
|
2946
|
+
}), description && /* @__PURE__ */ jsx("p", {
|
|
2947
|
+
className: "mt-0.5 text-sm text-muted-foreground",
|
|
2948
|
+
children: description
|
|
2949
|
+
})]
|
|
2950
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
2951
|
+
className: "flex shrink-0 items-center gap-2",
|
|
2952
|
+
children: actions
|
|
2953
|
+
})]
|
|
2954
|
+
}) : /* @__PURE__ */ jsx(PageHeader$1, {
|
|
2955
|
+
title,
|
|
2956
|
+
description,
|
|
2957
|
+
action: actions
|
|
2906
2958
|
}),
|
|
2907
2959
|
teamSecretsHint && /* @__PURE__ */ jsxs("div", {
|
|
2908
|
-
className: "flex flex-wrap items-center gap-3
|
|
2960
|
+
className: cn$1("flex flex-wrap items-center gap-3 border-[var(--md3-outline-variant)] bg-[var(--accent-surface-soft)]/40 px-4 py-3", pane ? "shrink-0 border-b sm:px-6" : "rounded-lg border"),
|
|
2909
2961
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
2910
2962
|
className: "flex min-w-[min(100%,18rem)] flex-1 items-start gap-3",
|
|
2911
2963
|
children: [/* @__PURE__ */ jsx(Users, {
|
|
@@ -2935,65 +2987,33 @@ function SecretsPage({ apiClient, className, teamSecretsHint }) {
|
|
|
2935
2987
|
})]
|
|
2936
2988
|
})]
|
|
2937
2989
|
}),
|
|
2938
|
-
/* @__PURE__ */ jsxs("div", {
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
}), /* @__PURE__ */ jsx("div", {
|
|
2947
|
-
className: "mt-2 flex items-baseline gap-2",
|
|
2948
|
-
children: /* @__PURE__ */ jsx("span", {
|
|
2949
|
-
className: "font-display text-2xl font-extrabold text-foreground",
|
|
2950
|
-
children: secrets.length
|
|
2951
|
-
})
|
|
2952
|
-
})]
|
|
2953
|
-
}),
|
|
2954
|
-
/* @__PURE__ */ jsxs("div", {
|
|
2955
|
-
className: "rounded-lg border border-[var(--md3-outline-variant)] bg-surface-container p-5 shadow-[var(--shadow-card)]",
|
|
2956
|
-
children: [/* @__PURE__ */ jsx("p", {
|
|
2957
|
-
className: "text-[10px] font-bold uppercase tracking-widest text-muted-foreground",
|
|
2958
|
-
children: "Status"
|
|
2959
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
2960
|
-
className: "mt-2 flex items-center gap-2",
|
|
2961
|
-
children: [/* @__PURE__ */ jsx(CheckCircle, { className: "h-4 w-4 text-[var(--surface-success-text,#047857)]" }), /* @__PURE__ */ jsx("span", {
|
|
2962
|
-
className: "text-sm font-semibold text-[var(--surface-success-text,#047857)]",
|
|
2963
|
-
children: "Encrypted"
|
|
2964
|
-
})]
|
|
2965
|
-
})]
|
|
2966
|
-
}),
|
|
2967
|
-
/* @__PURE__ */ jsx(InfoPanel, {
|
|
2968
|
-
className: "md:col-span-2",
|
|
2969
|
-
label: "Security Audit",
|
|
2970
|
-
title: "All engines operational.",
|
|
2971
|
-
description: "Secrets are encrypted at rest using AES-256."
|
|
2972
|
-
})
|
|
2973
|
-
]
|
|
2974
|
-
}),
|
|
2975
|
-
error && /* @__PURE__ */ jsxs("div", {
|
|
2976
|
-
className: "rounded-lg border border-destructive/30 bg-destructive/10 p-4 flex items-center gap-3",
|
|
2977
|
-
children: [/* @__PURE__ */ jsx(AlertCircle, { className: "h-5 w-5 text-destructive shrink-0" }), /* @__PURE__ */ jsx("p", {
|
|
2978
|
-
className: "text-destructive text-sm font-medium",
|
|
2990
|
+
error && (secrets.length > 0 || loading) && /* @__PURE__ */ jsxs("div", {
|
|
2991
|
+
role: "alert",
|
|
2992
|
+
className: cn$1("flex items-center gap-3 border-destructive/30 bg-destructive/10 p-4", pane ? "shrink-0 border-b sm:px-6" : "rounded-lg border"),
|
|
2993
|
+
children: [/* @__PURE__ */ jsx(AlertCircle, {
|
|
2994
|
+
className: "h-5 w-5 shrink-0 text-destructive",
|
|
2995
|
+
"aria-hidden": "true"
|
|
2996
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
2997
|
+
className: "text-sm font-medium text-destructive",
|
|
2979
2998
|
children: error
|
|
2980
2999
|
})]
|
|
2981
3000
|
}),
|
|
2982
3001
|
/* @__PURE__ */ jsx(Dialog, {
|
|
2983
3002
|
open: isCreateOpen,
|
|
2984
3003
|
onOpenChange: (open) => {
|
|
2985
|
-
if (!open)
|
|
2986
|
-
setIsCreateOpen(false);
|
|
2987
|
-
setNewName("");
|
|
2988
|
-
setNewValue("");
|
|
2989
|
-
setCreateError(null);
|
|
2990
|
-
setShowValue(false);
|
|
2991
|
-
}
|
|
3004
|
+
if (!open) closeCreate();
|
|
2992
3005
|
},
|
|
2993
3006
|
children: /* @__PURE__ */ jsxs(DialogContent, {
|
|
2994
3007
|
className: "max-w-md",
|
|
2995
3008
|
children: [
|
|
2996
|
-
/* @__PURE__ */ jsxs(DialogHeader, { children: [/* @__PURE__ */ jsx(DialogTitle, { children: "Create Secret" }), /* @__PURE__ */ jsx(DialogDescription, { children:
|
|
3009
|
+
/* @__PURE__ */ jsxs(DialogHeader, { children: [/* @__PURE__ */ jsx(DialogTitle, { children: replaceTarget ? "Replace Value" : "Create Secret" }), /* @__PURE__ */ jsx(DialogDescription, { children: replaceTarget ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3010
|
+
"Save a new value for ",
|
|
3011
|
+
/* @__PURE__ */ jsx("span", {
|
|
3012
|
+
className: "font-mono font-bold text-foreground",
|
|
3013
|
+
children: replaceTarget
|
|
3014
|
+
}),
|
|
3015
|
+
". The current value is overwritten and cannot be recovered."
|
|
3016
|
+
] }) : createDescription })] }),
|
|
2997
3017
|
/* @__PURE__ */ jsxs("form", {
|
|
2998
3018
|
onSubmit: (e) => {
|
|
2999
3019
|
e.preventDefault();
|
|
@@ -3013,6 +3033,8 @@ function SecretsPage({ apiClient, className, teamSecretsHint }) {
|
|
|
3013
3033
|
onChange: (e) => setNewName(e.target.value.toUpperCase().replace(/[^A-Z0-9_]/g, "_")),
|
|
3014
3034
|
placeholder: "MY_SECRET_KEY",
|
|
3015
3035
|
autoComplete: "off",
|
|
3036
|
+
readOnly: replaceTarget !== null,
|
|
3037
|
+
"aria-readonly": replaceTarget !== null,
|
|
3016
3038
|
className: `w-full rounded-md border bg-surface-container-low px-3 py-2.5 text-sm font-mono text-foreground placeholder:text-muted-foreground ${focusField}`
|
|
3017
3039
|
})] }),
|
|
3018
3040
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
@@ -3031,6 +3053,7 @@ function SecretsPage({ apiClient, className, teamSecretsHint }) {
|
|
|
3031
3053
|
onChange: (e) => setNewValue(e.target.value),
|
|
3032
3054
|
placeholder: "Enter secret value...",
|
|
3033
3055
|
autoComplete: "new-password",
|
|
3056
|
+
autoFocus: replaceTarget !== null,
|
|
3034
3057
|
className: `w-full rounded-md border bg-surface-container-low px-3 py-2.5 pr-10 text-sm font-mono text-foreground placeholder:text-muted-foreground ${focusField}`
|
|
3035
3058
|
}), /* @__PURE__ */ jsx("button", {
|
|
3036
3059
|
type: "button",
|
|
@@ -3042,7 +3065,7 @@ function SecretsPage({ apiClient, className, teamSecretsHint }) {
|
|
|
3042
3065
|
}),
|
|
3043
3066
|
/* @__PURE__ */ jsx("p", {
|
|
3044
3067
|
className: "mt-1.5 text-xs text-muted-foreground",
|
|
3045
|
-
children: "This value cannot be retrieved after
|
|
3068
|
+
children: "This value cannot be retrieved after it is saved."
|
|
3046
3069
|
})
|
|
3047
3070
|
] }),
|
|
3048
3071
|
/* @__PURE__ */ jsx("button", {
|
|
@@ -3060,12 +3083,7 @@ function SecretsPage({ apiClient, className, teamSecretsHint }) {
|
|
|
3060
3083
|
}),
|
|
3061
3084
|
/* @__PURE__ */ jsxs(DialogFooter, { children: [/* @__PURE__ */ jsx("button", {
|
|
3062
3085
|
type: "button",
|
|
3063
|
-
onClick:
|
|
3064
|
-
setIsCreateOpen(false);
|
|
3065
|
-
setNewName("");
|
|
3066
|
-
setNewValue("");
|
|
3067
|
-
setCreateError(null);
|
|
3068
|
-
},
|
|
3086
|
+
onClick: closeCreate,
|
|
3069
3087
|
className: "rounded-md border border-[var(--md3-outline-variant)] bg-surface-container px-4 py-2 text-sm font-medium text-foreground hover:bg-surface-container-high transition-colors",
|
|
3070
3088
|
children: "Cancel"
|
|
3071
3089
|
}), /* @__PURE__ */ jsx("button", {
|
|
@@ -3073,7 +3091,7 @@ function SecretsPage({ apiClient, className, teamSecretsHint }) {
|
|
|
3073
3091
|
onClick: handleCreate,
|
|
3074
3092
|
disabled: !newName.trim() || !newValue.trim() || isCreating,
|
|
3075
3093
|
className: "rounded-md bg-[var(--btn-primary-bg)] px-4 py-2 text-sm font-bold text-[var(--btn-primary-text)] hover:bg-[var(--btn-primary-hover)] transition-colors disabled:opacity-50 active:scale-[0.97]",
|
|
3076
|
-
children: isCreating ? "
|
|
3094
|
+
children: isCreating ? "Saving..." : replaceTarget ? "Replace Value" : "Create Secret"
|
|
3077
3095
|
})] })
|
|
3078
3096
|
]
|
|
3079
3097
|
})
|
|
@@ -3292,7 +3310,8 @@ function SecretsPage({ apiClient, className, teamSecretsHint }) {
|
|
|
3292
3310
|
className: "font-mono font-bold text-foreground",
|
|
3293
3311
|
children: deleteTarget
|
|
3294
3312
|
}),
|
|
3295
|
-
".
|
|
3313
|
+
". ",
|
|
3314
|
+
deleteConsequence
|
|
3296
3315
|
] })] }), /* @__PURE__ */ jsxs(DialogFooter, { children: [/* @__PURE__ */ jsx("button", {
|
|
3297
3316
|
type: "button",
|
|
3298
3317
|
onClick: () => setDeleteTarget(null),
|
|
@@ -3307,160 +3326,188 @@ function SecretsPage({ apiClient, className, teamSecretsHint }) {
|
|
|
3307
3326
|
})] })]
|
|
3308
3327
|
})
|
|
3309
3328
|
}),
|
|
3310
|
-
/* @__PURE__ */
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3329
|
+
/* @__PURE__ */ jsx("section", {
|
|
3330
|
+
"aria-label": title,
|
|
3331
|
+
className: cn$1(pane ? "min-h-0 flex-1 overflow-y-auto" : "overflow-hidden rounded-lg border border-[var(--md3-outline-variant)] bg-surface-container shadow-[var(--shadow-card)]"),
|
|
3332
|
+
children: loading ? /* @__PURE__ */ jsxs("div", {
|
|
3333
|
+
role: "status",
|
|
3334
|
+
"aria-busy": "true",
|
|
3335
|
+
className: "divide-y divide-border",
|
|
3336
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
3337
|
+
className: "sr-only",
|
|
3338
|
+
children: "Loading secrets…"
|
|
3339
|
+
}), [
|
|
3340
|
+
44,
|
|
3341
|
+
36,
|
|
3342
|
+
52
|
|
3343
|
+
].map((width) => /* @__PURE__ */ jsxs("div", {
|
|
3344
|
+
className: "flex items-center gap-3 px-4 py-4 sm:px-6",
|
|
3345
|
+
"aria-hidden": "true",
|
|
3346
|
+
children: [/* @__PURE__ */ jsx("div", { className: "h-4 w-4 animate-pulse rounded bg-muted" }), /* @__PURE__ */ jsx("div", {
|
|
3347
|
+
className: "h-4 animate-pulse rounded bg-muted",
|
|
3348
|
+
style: { width: `${width * 4}px` }
|
|
3349
|
+
})]
|
|
3350
|
+
}, width))]
|
|
3351
|
+
}) : error && secrets.length === 0 ? /* @__PURE__ */ jsxs("div", {
|
|
3352
|
+
role: "alert",
|
|
3353
|
+
className: "flex flex-col items-center justify-center px-6 py-16 text-center",
|
|
3354
|
+
children: [
|
|
3355
|
+
/* @__PURE__ */ jsx(AlertCircle, {
|
|
3356
|
+
className: "mb-4 h-10 w-10 text-destructive",
|
|
3357
|
+
"aria-hidden": "true"
|
|
3358
|
+
}),
|
|
3359
|
+
/* @__PURE__ */ jsx("h3", {
|
|
3360
|
+
className: "text-base font-semibold text-foreground",
|
|
3361
|
+
children: "Secrets could not load"
|
|
3362
|
+
}),
|
|
3363
|
+
/* @__PURE__ */ jsx("p", {
|
|
3364
|
+
className: "mt-1 max-w-sm text-sm text-muted-foreground",
|
|
3365
|
+
children: error
|
|
3366
|
+
}),
|
|
3367
|
+
/* @__PURE__ */ jsx("button", {
|
|
3317
3368
|
type: "button",
|
|
3318
|
-
|
|
3319
|
-
|
|
3369
|
+
onClick: () => void loadSecrets(),
|
|
3370
|
+
className: "mt-6 rounded-md border border-[var(--md3-outline-variant)] bg-surface-container px-4 py-2 text-sm font-semibold text-foreground transition-colors hover:bg-surface-container-high",
|
|
3371
|
+
children: "Retry"
|
|
3320
3372
|
})
|
|
3321
|
-
|
|
3322
|
-
className: "text-xs text-muted-foreground font-mono",
|
|
3323
|
-
children: [
|
|
3324
|
-
secrets.length,
|
|
3325
|
-
" secret",
|
|
3326
|
-
secrets.length !== 1 ? "s" : ""
|
|
3327
|
-
]
|
|
3328
|
-
})]
|
|
3329
|
-
}), loading ? /* @__PURE__ */ jsx("div", {
|
|
3330
|
-
className: "flex items-center justify-center py-16",
|
|
3331
|
-
children: /* @__PURE__ */ jsx("div", {
|
|
3332
|
-
className: "h-6 w-6 animate-spin rounded-full border-2 border-muted-foreground border-t-transparent",
|
|
3333
|
-
"data-motion": "essential"
|
|
3334
|
-
})
|
|
3373
|
+
]
|
|
3335
3374
|
}) : secrets.length === 0 ? /* @__PURE__ */ jsxs("div", {
|
|
3336
|
-
className: "flex flex-col items-center justify-center py-16 text-center",
|
|
3375
|
+
className: "flex flex-col items-center justify-center px-6 py-16 text-center",
|
|
3337
3376
|
children: [
|
|
3338
|
-
/* @__PURE__ */ jsx(Lock, {
|
|
3377
|
+
/* @__PURE__ */ jsx(Lock, {
|
|
3378
|
+
className: "mb-4 h-10 w-10 text-muted-foreground",
|
|
3379
|
+
"aria-hidden": "true"
|
|
3380
|
+
}),
|
|
3339
3381
|
/* @__PURE__ */ jsx("h3", {
|
|
3340
3382
|
className: "text-lg font-semibold text-foreground",
|
|
3341
3383
|
children: "No secrets yet"
|
|
3342
3384
|
}),
|
|
3343
3385
|
/* @__PURE__ */ jsx("p", {
|
|
3344
|
-
className: "mt-1 text-sm text-muted-foreground
|
|
3345
|
-
children:
|
|
3386
|
+
className: "mt-1 max-w-sm text-sm text-muted-foreground",
|
|
3387
|
+
children: emptyDescription
|
|
3346
3388
|
}),
|
|
3347
3389
|
/* @__PURE__ */ jsxs("button", {
|
|
3348
3390
|
type: "button",
|
|
3349
|
-
onClick:
|
|
3391
|
+
onClick: openCreate,
|
|
3350
3392
|
"aria-label": "Create your first secret",
|
|
3351
|
-
className: "mt-6 inline-flex items-center gap-2 rounded-md bg-[var(--btn-primary-bg)] px-4 py-2 text-sm font-semibold text-[var(--btn-primary-text)] hover:bg-[var(--btn-primary-hover)]
|
|
3352
|
-
children: [/* @__PURE__ */ jsx(Plus, {
|
|
3393
|
+
className: "mt-6 inline-flex items-center gap-2 rounded-md bg-[var(--btn-primary-bg)] px-4 py-2 text-sm font-semibold text-[var(--btn-primary-text)] transition-colors hover:bg-[var(--btn-primary-hover)] active:scale-[0.97]",
|
|
3394
|
+
children: [/* @__PURE__ */ jsx(Plus, {
|
|
3395
|
+
className: "h-4 w-4",
|
|
3396
|
+
"aria-hidden": "true"
|
|
3397
|
+
}), "New Secret"]
|
|
3353
3398
|
})
|
|
3354
3399
|
]
|
|
3355
3400
|
}) : /* @__PURE__ */ jsxs("table", {
|
|
3356
|
-
className: "w-full text-left
|
|
3357
|
-
children: [
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
/* @__PURE__ */ jsx("th", {
|
|
3361
|
-
scope: "col",
|
|
3362
|
-
className: "px-4 py-3 text-[10px] font-bold uppercase tracking-widest text-muted-foreground sm:px-6 sm:py-4",
|
|
3363
|
-
children: "Secret Name"
|
|
3364
|
-
}),
|
|
3365
|
-
/* @__PURE__ */ jsx("th", {
|
|
3366
|
-
scope: "col",
|
|
3367
|
-
className: "hidden px-6 py-4 text-[10px] font-bold uppercase tracking-widest text-muted-foreground sm:table-cell",
|
|
3368
|
-
children: "Encrypted Value"
|
|
3369
|
-
}),
|
|
3370
|
-
/* @__PURE__ */ jsx("th", {
|
|
3371
|
-
scope: "col",
|
|
3372
|
-
className: "hidden px-6 py-4 text-right text-[10px] font-bold uppercase tracking-widest text-muted-foreground sm:table-cell",
|
|
3373
|
-
children: "Created"
|
|
3374
|
-
}),
|
|
3375
|
-
/* @__PURE__ */ jsx("th", {
|
|
3376
|
-
scope: "col",
|
|
3377
|
-
"aria-label": "Actions",
|
|
3378
|
-
className: "w-12 px-3 py-3 sm:px-6 sm:py-4"
|
|
3379
|
-
})
|
|
3380
|
-
]
|
|
3381
|
-
}) }), /* @__PURE__ */ jsx("tbody", {
|
|
3382
|
-
className: "divide-y divide-border",
|
|
3383
|
-
children: secrets.map((secret) => /* @__PURE__ */ jsxs("tr", {
|
|
3384
|
-
className: "hover:bg-surface-container-high transition-colors",
|
|
3401
|
+
className: "w-full border-collapse text-left",
|
|
3402
|
+
children: [
|
|
3403
|
+
/* @__PURE__ */ jsxs("caption", {
|
|
3404
|
+
className: "sr-only",
|
|
3385
3405
|
children: [
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3406
|
+
secrets.length,
|
|
3407
|
+
" secret",
|
|
3408
|
+
secrets.length !== 1 ? "s" : ""
|
|
3409
|
+
]
|
|
3410
|
+
}),
|
|
3411
|
+
/* @__PURE__ */ jsx("thead", {
|
|
3412
|
+
className: cn$1(pane && "sticky top-0 z-10 bg-background"),
|
|
3413
|
+
children: /* @__PURE__ */ jsxs("tr", {
|
|
3414
|
+
className: "border-b border-[var(--md3-outline-variant)]",
|
|
3415
|
+
children: [
|
|
3416
|
+
/* @__PURE__ */ jsxs("th", {
|
|
3417
|
+
scope: "col",
|
|
3418
|
+
className: "px-4 py-2.5 text-xs font-medium text-muted-foreground sm:px-6",
|
|
3419
|
+
children: ["Name ", /* @__PURE__ */ jsx("span", {
|
|
3420
|
+
className: "ml-1 font-mono tabular-nums",
|
|
3421
|
+
children: secrets.length
|
|
3399
3422
|
})]
|
|
3423
|
+
}),
|
|
3424
|
+
/* @__PURE__ */ jsx("th", {
|
|
3425
|
+
scope: "col",
|
|
3426
|
+
className: "hidden px-4 py-2.5 text-xs font-medium text-muted-foreground md:table-cell",
|
|
3427
|
+
children: "Value"
|
|
3428
|
+
}),
|
|
3429
|
+
/* @__PURE__ */ jsx("th", {
|
|
3430
|
+
scope: "col",
|
|
3431
|
+
className: "hidden px-4 py-2.5 text-right text-xs font-medium text-muted-foreground sm:table-cell",
|
|
3432
|
+
children: "Updated"
|
|
3433
|
+
}),
|
|
3434
|
+
/* @__PURE__ */ jsx("th", {
|
|
3435
|
+
scope: "col",
|
|
3436
|
+
className: "w-px px-4 py-2.5 sm:pr-6",
|
|
3437
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
3438
|
+
className: "sr-only",
|
|
3439
|
+
children: "Actions"
|
|
3440
|
+
})
|
|
3400
3441
|
})
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3442
|
+
]
|
|
3443
|
+
})
|
|
3444
|
+
}),
|
|
3445
|
+
/* @__PURE__ */ jsx("tbody", {
|
|
3446
|
+
className: "divide-y divide-border",
|
|
3447
|
+
children: secrets.map((secret) => {
|
|
3448
|
+
const changedAt = formatDate(secret.updatedAt ?? secret.createdAt);
|
|
3449
|
+
return /* @__PURE__ */ jsxs("tr", {
|
|
3450
|
+
className: "transition-colors hover:bg-surface-container-high",
|
|
3451
|
+
children: [
|
|
3452
|
+
/* @__PURE__ */ jsx("td", {
|
|
3453
|
+
className: "py-3 pl-4 pr-1 sm:px-6",
|
|
3454
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
3455
|
+
className: "flex min-w-0 items-center gap-2.5 sm:gap-3",
|
|
3456
|
+
children: [/* @__PURE__ */ jsx(Key, {
|
|
3457
|
+
className: "h-4 w-4 shrink-0 text-muted-foreground",
|
|
3458
|
+
"aria-hidden": "true"
|
|
3459
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
3460
|
+
className: "min-w-0",
|
|
3461
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
3462
|
+
className: "font-mono text-[13px] font-semibold text-foreground [overflow-wrap:anywhere] sm:text-sm",
|
|
3463
|
+
children: secret.name
|
|
3464
|
+
}), /* @__PURE__ */ jsxs("span", {
|
|
3465
|
+
className: "mt-0.5 block text-xs text-muted-foreground sm:hidden",
|
|
3466
|
+
children: ["Updated ", changedAt]
|
|
3467
|
+
})]
|
|
3468
|
+
})]
|
|
3469
|
+
})
|
|
3470
|
+
}),
|
|
3471
|
+
/* @__PURE__ */ jsx("td", {
|
|
3472
|
+
className: "hidden px-4 py-3 md:table-cell",
|
|
3473
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
3474
|
+
className: "font-mono text-xs tracking-widest text-muted-foreground",
|
|
3475
|
+
"aria-label": "Value hidden",
|
|
3476
|
+
children: "••••••••••••"
|
|
3477
|
+
})
|
|
3478
|
+
}),
|
|
3479
|
+
/* @__PURE__ */ jsx("td", {
|
|
3480
|
+
className: "hidden whitespace-nowrap px-4 py-3 text-right text-xs text-muted-foreground sm:table-cell",
|
|
3481
|
+
children: changedAt
|
|
3482
|
+
}),
|
|
3483
|
+
/* @__PURE__ */ jsx("td", {
|
|
3484
|
+
className: "whitespace-nowrap py-3 pl-1 pr-3 sm:px-4 sm:pr-6",
|
|
3485
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
3486
|
+
className: "flex items-center justify-end gap-1",
|
|
3487
|
+
children: [canReplace && /* @__PURE__ */ jsx("button", {
|
|
3488
|
+
type: "button",
|
|
3489
|
+
onClick: () => openReplace(secret.name),
|
|
3490
|
+
className: "rounded-md px-2 py-1.5 text-xs font-semibold text-foreground transition-colors hover:bg-surface-container-high",
|
|
3491
|
+
"aria-label": `Replace value of ${secret.name}`,
|
|
3492
|
+
children: "Replace"
|
|
3493
|
+
}), /* @__PURE__ */ jsx("button", {
|
|
3494
|
+
type: "button",
|
|
3495
|
+
onClick: () => setDeleteTarget(secret.name),
|
|
3496
|
+
className: "rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-destructive/10 hover:text-destructive",
|
|
3497
|
+
"aria-label": `Delete ${secret.name}`,
|
|
3498
|
+
children: /* @__PURE__ */ jsx(Trash2, {
|
|
3499
|
+
className: "h-4 w-4",
|
|
3500
|
+
"aria-hidden": "true"
|
|
3501
|
+
})
|
|
3502
|
+
})]
|
|
3503
|
+
})
|
|
3504
|
+
})
|
|
3505
|
+
]
|
|
3506
|
+
}, secret.name);
|
|
3507
|
+
})
|
|
3508
|
+
})
|
|
3509
|
+
]
|
|
3510
|
+
})
|
|
3464
3511
|
})
|
|
3465
3512
|
]
|
|
3466
3513
|
});
|