@flanksource/clicky-ui 0.3.32 → 0.3.33
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/EndpointSelector.cjs +6 -6
- package/dist/components/EndpointSelector.cjs.map +1 -1
- package/dist/components/EndpointSelector.d.ts.map +1 -1
- package/dist/components/EndpointSelector.js +6 -6
- package/dist/components/EndpointSelector.js.map +1 -1
- package/dist/components/ErrorWrapper.cjs +3 -2
- package/dist/components/ErrorWrapper.cjs.map +1 -1
- package/dist/components/ErrorWrapper.js +3 -2
- package/dist/components/ErrorWrapper.js.map +1 -1
- package/dist/components/RangeSlider.cjs +108 -45
- package/dist/components/RangeSlider.cjs.map +1 -1
- package/dist/components/RangeSlider.d.ts +3 -1
- package/dist/components/RangeSlider.d.ts.map +1 -1
- package/dist/components/RangeSlider.js +108 -45
- package/dist/components/RangeSlider.js.map +1 -1
- package/dist/components/SecretKeySelector.cjs +4 -4
- package/dist/components/SecretKeySelector.cjs.map +1 -1
- package/dist/components/SecretKeySelector.js +4 -4
- package/dist/components/SecretKeySelector.js.map +1 -1
- package/dist/data/version-info.cjs +3 -3
- package/dist/data/version-info.js +3 -3
- package/dist/styles.css +1 -1
- package/package.json +1 -1
|
@@ -27,10 +27,10 @@ const DEFAULT_MODE_KINDS = {
|
|
|
27
27
|
ingress: ["ingress"],
|
|
28
28
|
"port-forward": ["service", "deployment"]
|
|
29
29
|
};
|
|
30
|
-
const WORKLOAD_FIELD = "max-w-full min-w-0
|
|
31
|
-
const SCHEME_FIELD = "max-w-full min-w-0
|
|
32
|
-
const PORT_FIELD = "max-w-full min-w-0
|
|
33
|
-
const PATH_FIELD = "max-w-full min-w-0
|
|
30
|
+
const WORKLOAD_FIELD = "col-span-2 max-w-full min-w-0 @min-[40rem]/endpoint:col-span-1";
|
|
31
|
+
const SCHEME_FIELD = "max-w-full min-w-0 w-full";
|
|
32
|
+
const PORT_FIELD = "max-w-full min-w-0 w-full";
|
|
33
|
+
const PATH_FIELD = "col-span-2 max-w-full min-w-0 @min-[40rem]/endpoint:col-span-3 @min-[56rem]/endpoint:col-span-1";
|
|
34
34
|
function isWorkloadValue(value) {
|
|
35
35
|
return value !== void 0 && value.mode !== "url";
|
|
36
36
|
}
|
|
@@ -268,7 +268,7 @@ function EndpointSelector({
|
|
|
268
268
|
};
|
|
269
269
|
const workloadValue = isWorkloadValue(value) && value.mode === activeMode ? targetKey(value.target, namespace, selectedResource) : "";
|
|
270
270
|
const showPort = activeMode !== "url" && (activeMode !== "ingress" || showIngressPort);
|
|
271
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: utils.cn("space-y-density-2", className), children: [
|
|
271
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: utils.cn("@container/endpoint space-y-density-2", className), children: [
|
|
272
272
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
273
273
|
SegmentedControl.SegmentedControl,
|
|
274
274
|
{
|
|
@@ -294,7 +294,7 @@ function EndpointSelector({
|
|
|
294
294
|
})() : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-density-2", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
295
295
|
"div",
|
|
296
296
|
{
|
|
297
|
-
className: "
|
|
297
|
+
className: "grid w-full max-w-full min-w-0 grid-cols-2 items-end gap-density-2 @min-[40rem]/endpoint:grid-cols-[minmax(14rem,1fr)_auto_auto] @min-[56rem]/endpoint:grid-cols-[minmax(14rem,1fr)_auto_auto_minmax(14rem,1fr)]",
|
|
298
298
|
"data-slot": "endpoint-fields",
|
|
299
299
|
children: [
|
|
300
300
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EndpointSelector.cjs","sources":["../../src/components/EndpointSelector.tsx"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { UiWarningTriangle } from \"../icons\";\nimport { Combobox, type ComboboxOption } from \"./Combobox\";\nimport {\n DEFAULT_PREFERRED_ENDPOINT_PORTS,\n preferredEndpointPort,\n} from \"./endpoint-port\";\nimport { Field } from \"./Field\";\nimport { InputField } from \"./InputField\";\nimport { SecretKeySelector } from \"./SecretKeySelector\";\nimport { SegmentedControl, type SegmentedOption } from \"./SegmentedControl\";\nimport { WorkloadPicker } from \"./WorkloadPicker\";\nimport {\n parseWorkloadKey,\n workloadKey,\n type WorkloadKind,\n type WorkloadResource,\n} from \"./workload-picker-utils\";\nimport type {\n EndpointMode,\n EndpointResources,\n EndpointSelectorProps,\n EndpointSelectorValue,\n EndpointTarget,\n EndpointWorkloadValue,\n EndpointWorkloadMode,\n} from \"./EndpointSelector.model\";\nconst MODE_LABELS: Record<EndpointMode, string> = {\n url: \"URL\",\n service: \"Service\",\n \"cluster-ip\": \"Cluster IP\",\n \"api-proxy\": \"API proxy\",\n ingress: \"Ingress\",\n \"port-forward\": \"Port-forward\",\n};\nconst DEFAULT_MODE_KINDS: Record<EndpointWorkloadMode, WorkloadKind[]> = {\n service: [\"service\"],\n \"cluster-ip\": [\"service\"],\n \"api-proxy\": [\"service\"],\n ingress: [\"ingress\"],\n \"port-forward\": [\"service\", \"deployment\"],\n};\nconst WORKLOAD_FIELD =\n \"max-w-full min-w-0 basis-56 shrink grow\";\nconst SCHEME_FIELD =\n \"max-w-full min-w-0 basis-32 shrink grow-0\";\nconst PORT_FIELD =\n \"max-w-full min-w-0 basis-36 shrink grow-0\";\nconst PATH_FIELD =\n \"max-w-full min-w-0 basis-56 shrink grow\";\nfunction isWorkloadValue(\n value: EndpointSelectorValue | undefined,\n): value is EndpointWorkloadValue {\n return value !== undefined && value.mode !== \"url\";\n}\n\nfunction sameTarget(left: EndpointTarget, right: EndpointTarget) {\n if (left.kind !== right.kind || left.namespace !== right.namespace)\n return false;\n if (left.kind === \"ingress\" && right.kind === \"ingress\") {\n return left.name === right.name && left.host === right.host;\n }\n return left.name === right.name;\n}\n\nfunction targetKey(\n target: EndpointTarget,\n namespace: string | undefined,\n resource: WorkloadResource | undefined,\n) {\n if (target.kind === \"ingress\") {\n return workloadKey(target.namespace ?? namespace, target.kind, {\n name: target.name,\n hosts: [target.host ?? resource?.hosts?.[0] ?? target.name],\n });\n }\n return workloadKey(target.namespace ?? namespace, target.kind, {\n name: target.name,\n });\n}\n\nfunction findResource(\n resources: EndpointResources,\n kind: WorkloadKind,\n selectedName: string,\n) {\n return resources[kind]?.find((resource) =>\n kind === \"ingress\"\n ? resource.hosts?.[0] === selectedName\n : resource.name === selectedName,\n );\n}\n\nfunction portOptions(resource: WorkloadResource | undefined): ComboboxOption[] {\n return (resource?.ports ?? []).map((port) => ({\n value: String(port.number),\n label: port.name ? `${port.name} (${port.number})` : String(port.number),\n }));\n}\n\nfunction validPort(port: string) {\n if (!/^\\d+$/.test(port)) return false;\n const number = Number(port);\n return number >= 1 && number <= 65535;\n}\n\nexport function EndpointSelector({\n value,\n onChange,\n namespace,\n modes,\n defaultMode,\n loadWorkloads,\n allowNamespaceSelection = false,\n loadNamespaces,\n onNamespaceChange,\n urlSelector,\n modeKinds,\n defaults,\n preferredPorts = DEFAULT_PREFERRED_ENDPOINT_PORTS,\n schemes,\n allowCustomScheme = true,\n allowCustomPort = false,\n showScheme = false,\n showPath = false,\n showIngressPort = false,\n className,\n}: EndpointSelectorProps) {\n const fallbackMode = defaultMode ?? modes[0];\n if (!fallbackMode || !modes.includes(fallbackMode)) {\n throw new Error(\n \"EndpointSelector requires a default mode included in modes\",\n );\n }\n if (value && !modes.includes(value.mode)) {\n throw new Error(`EndpointSelector value mode \"${value.mode}\" is disabled`);\n }\n if (allowNamespaceSelection && !loadNamespaces) {\n throw new Error(\n \"EndpointSelector namespace selection requires loadNamespaces\",\n );\n }\n\n const [activeMode, setActiveMode] = useState<EndpointMode>(\n value?.mode ?? fallbackMode,\n );\n const [resources, setResources] = useState<EndpointResources>({});\n const resourcesRef = useRef<EndpointResources>({});\n const resourcesNamespaceRef = useRef(namespace);\n const modesKey = modes.join(\",\");\n\n useEffect(() => {\n setActiveMode(\n (current) =>\n value?.mode ?? (modes.includes(current) ? current : fallbackMode),\n );\n }, [value, fallbackMode, modesKey]);\n\n const enabledKinds = useMemo(\n () =>\n activeMode === \"url\"\n ? []\n : (modeKinds?.[activeMode] ?? DEFAULT_MODE_KINDS[activeMode]),\n [activeMode, modeKinds],\n );\n\n const rememberingLoader = useCallback(\n async (kinds: WorkloadKind[], selectedNamespace?: string) => {\n const workloadNamespace = selectedNamespace ?? namespace;\n if (resourcesNamespaceRef.current !== workloadNamespace) {\n resourcesNamespaceRef.current = workloadNamespace;\n resourcesRef.current = {};\n setResources({});\n }\n const loaded = workloadNamespace\n ? await loadWorkloads(kinds, workloadNamespace)\n : await loadWorkloads(kinds);\n const filtered = { ...loaded };\n if (kinds.includes(\"ingress\")) {\n filtered.ingress = (loaded.ingress ?? []).filter(\n (resource) => resource.hosts?.[0],\n );\n }\n if (resourcesNamespaceRef.current === workloadNamespace) {\n resourcesRef.current = { ...resourcesRef.current, ...filtered };\n setResources(resourcesRef.current);\n }\n return filtered;\n },\n [loadWorkloads, namespace],\n );\n\n const selectedResource = useMemo(() => {\n if (!isWorkloadValue(value)) return undefined;\n const target = value.target;\n return resources[target.kind]?.find((resource) => {\n if (target.kind === \"ingress\") {\n return (\n resource.name === target.name || resource.hosts?.[0] === target.host\n );\n }\n return resource.name === target.name;\n });\n }, [resources, value]);\n\n const options = useMemo(\n () => portOptions(selectedResource),\n [selectedResource],\n );\n const selectedPort = isWorkloadValue(value) ? value.port : undefined;\n const selectedPortWarning =\n selectedPort &&\n selectedResource &&\n options.length > 0 &&\n !options.some((option) => option.value === selectedPort)\n ? `Port ${selectedPort} is not exposed by workload \"${selectedResource.name}\"`\n : undefined;\n useEffect(() => {\n if (\n !isWorkloadValue(value) ||\n value.port ||\n !selectedResource\n ) {\n return;\n }\n const port = preferredEndpointPort(\n selectedResource.ports,\n preferredPorts,\n );\n if (port) onChange({ ...value, port });\n }, [\n onChange,\n preferredPorts,\n selectedResource,\n value,\n ]);\n\n const modeOptions = useMemo<SegmentedOption<EndpointMode>[]>(\n () => modes.map((mode) => ({ id: mode, label: MODE_LABELS[mode] })),\n [modes],\n );\n\n const selectMode = (nextMode: EndpointMode) => {\n setActiveMode(nextMode);\n if (nextMode === \"url\") {\n onNamespaceChange?.(undefined);\n if (value?.mode !== \"url\") onChange(undefined);\n return;\n }\n if (\n isWorkloadValue(value) &&\n (modeKinds?.[nextMode] ?? DEFAULT_MODE_KINDS[nextMode]).includes(\n value.target.kind,\n )\n ) {\n onChange({ ...value, mode: nextMode });\n return;\n }\n onChange(undefined);\n };\n\n const selectWorkload = (key: string) => {\n const parsed = key ? parseWorkloadKey(key) : undefined;\n // A namespace-only key (empty name) means a namespace is in scope with no\n // workload picked in it. An endpoint needs a workload to address, so there\n // is nothing to report yet — the namespace reaches the consumer through\n // onNamespaceChange instead.\n if (!parsed || !parsed.name) {\n onChange(undefined);\n return;\n }\n const kind = parsed.kind;\n if (!kind || !enabledKinds.includes(kind)) {\n throw new Error(\n `EndpointSelector received unsupported workload key \"${key}\"`,\n );\n }\n const resource = findResource(resourcesRef.current, kind, parsed.name);\n if (!resource) {\n throw new Error(`EndpointSelector workload \"${key}\" was not loaded`);\n }\n\n const selectedNamespace = parsed.namespace ?? namespace;\n let target: EndpointTarget;\n if (kind === \"ingress\") {\n const host = resource.hosts?.[0];\n if (!host) {\n throw new Error(`Ingress \"${resource.name}\" has no routable host`);\n }\n target = {\n kind,\n name: resource.name,\n host,\n ...(selectedNamespace ? { namespace: selectedNamespace } : {}),\n };\n } else {\n target = {\n kind,\n name: resource.name,\n ...(selectedNamespace ? { namespace: selectedNamespace } : {}),\n };\n }\n\n const previous = isWorkloadValue(value) ? value : undefined;\n const exposed = portOptions(resource).map((option) => option.value);\n const currentPort = previous?.port ?? \"\";\n const port = currentPort &&\n (previous && sameTarget(previous.target, target) ||\n exposed.includes(currentPort))\n ? currentPort\n : (preferredEndpointPort(resource.ports, preferredPorts) ?? defaults?.port);\n const next: EndpointWorkloadValue = {\n mode: activeMode as EndpointWorkloadMode,\n target,\n };\n const scheme = previous?.scheme ?? defaults?.scheme;\n const path = previous?.path ?? defaults?.path;\n if (scheme) next.scheme = scheme;\n if (port) next.port = port;\n if (path) next.path = path;\n onChange(next);\n };\n\n const patchValue = (\n field: \"scheme\" | \"port\" | \"path\",\n fieldValue: string,\n ) => {\n if (!isWorkloadValue(value)) return;\n const next = { ...value };\n if (fieldValue) {\n next[field] = fieldValue;\n } else {\n delete next[field];\n }\n onChange(next);\n };\n\n const workloadValue =\n isWorkloadValue(value) && value.mode === activeMode\n ? targetKey(value.target, namespace, selectedResource)\n : \"\";\n const showPort =\n activeMode !== \"url\" && (activeMode !== \"ingress\" || showIngressPort);\n\n return (\n <div className={cn(\"space-y-density-2\", className)}>\n <SegmentedControl\n value={activeMode}\n options={modeOptions}\n onChange={selectMode}\n wrap\n aria-label=\"Endpoint access mode\"\n />\n\n {activeMode === \"url\" ? (\n (() => {\n if (!urlSelector) {\n throw new Error(\"EndpointSelector url mode requires urlSelector\");\n }\n return (\n <SecretKeySelector\n {...urlSelector}\n value={value?.mode === \"url\" ? value.source : undefined}\n onChange={(source) =>\n onChange(source ? { mode: \"url\", source } : undefined)\n }\n />\n );\n })()\n ) : (\n <div className=\"space-y-density-2\">\n <div\n className=\"flex w-full max-w-full min-w-0 flex-nowrap items-end gap-density-2\"\n data-slot=\"endpoint-fields\"\n >\n <div\n className={WORKLOAD_FIELD}\n data-slot=\"endpoint-workload-field\"\n >\n <Field label=\"Workload\">\n <WorkloadPicker\n value={workloadValue}\n onChange={selectWorkload}\n loadWorkloads={rememberingLoader}\n {...(namespace ? { namespace } : {})}\n {...(allowNamespaceSelection\n ? { allowNamespaceSelection: true }\n : {})}\n {...(loadNamespaces ? { loadNamespaces } : {})}\n {...(onNamespaceChange ? { onNamespaceChange } : {})}\n kinds={enabledKinds}\n strict\n allowCustomValue={false}\n placeholder=\"Select workload…\"\n />\n </Field>\n </div>\n {showScheme && (\n <div\n className={SCHEME_FIELD}\n data-slot=\"endpoint-scheme-field\"\n >\n <Field label=\"Scheme\">\n {schemes?.length && !allowCustomScheme ? (\n <SegmentedControl\n value={isWorkloadValue(value) ? (value.scheme ?? \"\") : \"\"}\n options={schemes.map((scheme) => ({\n id: scheme,\n label: scheme,\n }))}\n onChange={(scheme) => patchValue(\"scheme\", scheme)}\n aria-label=\"Scheme\"\n />\n ) : schemes?.length ? (\n <Combobox\n options={schemes.map((scheme) => ({\n value: scheme,\n label: scheme,\n }))}\n value={isWorkloadValue(value) ? (value.scheme ?? \"\") : \"\"}\n onChange={(scheme) => patchValue(\"scheme\", scheme)}\n allowCustomValue={allowCustomScheme}\n ariaLabel=\"Scheme\"\n />\n ) : (\n <InputField\n value={isWorkloadValue(value) ? (value.scheme ?? \"\") : \"\"}\n onChange={(scheme) => patchValue(\"scheme\", scheme)}\n aria-label=\"Scheme\"\n />\n )}\n </Field>\n </div>\n )}\n {showPort && (\n <div\n className={PORT_FIELD}\n data-slot=\"endpoint-port-field\"\n >\n <Field label=\"Port\">\n <Combobox\n options={options}\n value={isWorkloadValue(value) ? (value.port ?? \"\") : \"\"}\n onChange={(port) => patchValue(\"port\", port)}\n onNew={(port) => {\n if (!validPort(port)) return null;\n if (!options.length || !selectedResource) {\n return { value: port, label: port };\n }\n const warning = `Port ${port} is not exposed by workload \"${selectedResource.name}\"`;\n return {\n value: port,\n label: `Use ${port} — not exposed by ${selectedResource.name}`,\n selectedLabel: port,\n icon: (\n <UiWarningTriangle\n className=\"size-4 shrink-0 text-amber-600\"\n title={warning}\n />\n ),\n title: warning,\n };\n }}\n onCreate={(option) =>\n validPort(option.value) ? option.value : null\n }\n prefix={\n selectedPortWarning ? (\n <UiWarningTriangle\n className=\"size-4 shrink-0 text-amber-600\"\n title={selectedPortWarning}\n />\n ) : undefined\n }\n allowCustomValue={allowCustomPort}\n ariaLabel=\"Port\"\n />\n </Field>\n </div>\n )}\n {showPath && (\n <div\n className={PATH_FIELD}\n data-slot=\"endpoint-path-field\"\n >\n <Field label=\"Path\">\n <InputField\n value={isWorkloadValue(value) ? (value.path ?? \"\") : \"\"}\n onChange={(path) => patchValue(\"path\", path)}\n aria-label=\"Path\"\n {...(isWorkloadValue(value) && value.path\n ? { title: value.path }\n : {})}\n />\n </Field>\n </div>\n )}\n </div>\n </div>\n )}\n </div>\n );\n}\n"],"names":["workloadKey","_a","DEFAULT_PREFERRED_ENDPOINT_PORTS","useState","useRef","useEffect","useMemo","useCallback","preferredEndpointPort","parseWorkloadKey","cn","jsx","SegmentedControl","SecretKeySelector","jsxs","Field","WorkloadPicker","Combobox","InputField","UiWarningTriangle"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"EndpointSelector.cjs","sources":["../../src/components/EndpointSelector.tsx"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { UiWarningTriangle } from \"../icons\";\nimport { Combobox, type ComboboxOption } from \"./Combobox\";\nimport {\n DEFAULT_PREFERRED_ENDPOINT_PORTS,\n preferredEndpointPort,\n} from \"./endpoint-port\";\nimport { Field } from \"./Field\";\nimport { InputField } from \"./InputField\";\nimport { SecretKeySelector } from \"./SecretKeySelector\";\nimport { SegmentedControl, type SegmentedOption } from \"./SegmentedControl\";\nimport { WorkloadPicker } from \"./WorkloadPicker\";\nimport {\n parseWorkloadKey,\n workloadKey,\n type WorkloadKind,\n type WorkloadResource,\n} from \"./workload-picker-utils\";\nimport type {\n EndpointMode,\n EndpointResources,\n EndpointSelectorProps,\n EndpointSelectorValue,\n EndpointTarget,\n EndpointWorkloadValue,\n EndpointWorkloadMode,\n} from \"./EndpointSelector.model\";\nconst MODE_LABELS: Record<EndpointMode, string> = {\n url: \"URL\",\n service: \"Service\",\n \"cluster-ip\": \"Cluster IP\",\n \"api-proxy\": \"API proxy\",\n ingress: \"Ingress\",\n \"port-forward\": \"Port-forward\",\n};\nconst DEFAULT_MODE_KINDS: Record<EndpointWorkloadMode, WorkloadKind[]> = {\n service: [\"service\"],\n \"cluster-ip\": [\"service\"],\n \"api-proxy\": [\"service\"],\n ingress: [\"ingress\"],\n \"port-forward\": [\"service\", \"deployment\"],\n};\nconst WORKLOAD_FIELD =\n \"col-span-2 max-w-full min-w-0 @min-[40rem]/endpoint:col-span-1\";\nconst SCHEME_FIELD = \"max-w-full min-w-0 w-full\";\nconst PORT_FIELD = \"max-w-full min-w-0 w-full\";\nconst PATH_FIELD =\n \"col-span-2 max-w-full min-w-0 @min-[40rem]/endpoint:col-span-3 @min-[56rem]/endpoint:col-span-1\";\nfunction isWorkloadValue(\n value: EndpointSelectorValue | undefined,\n): value is EndpointWorkloadValue {\n return value !== undefined && value.mode !== \"url\";\n}\n\nfunction sameTarget(left: EndpointTarget, right: EndpointTarget) {\n if (left.kind !== right.kind || left.namespace !== right.namespace)\n return false;\n if (left.kind === \"ingress\" && right.kind === \"ingress\") {\n return left.name === right.name && left.host === right.host;\n }\n return left.name === right.name;\n}\n\nfunction targetKey(\n target: EndpointTarget,\n namespace: string | undefined,\n resource: WorkloadResource | undefined,\n) {\n if (target.kind === \"ingress\") {\n return workloadKey(target.namespace ?? namespace, target.kind, {\n name: target.name,\n hosts: [target.host ?? resource?.hosts?.[0] ?? target.name],\n });\n }\n return workloadKey(target.namespace ?? namespace, target.kind, {\n name: target.name,\n });\n}\n\nfunction findResource(\n resources: EndpointResources,\n kind: WorkloadKind,\n selectedName: string,\n) {\n return resources[kind]?.find((resource) =>\n kind === \"ingress\"\n ? resource.hosts?.[0] === selectedName\n : resource.name === selectedName,\n );\n}\n\nfunction portOptions(resource: WorkloadResource | undefined): ComboboxOption[] {\n return (resource?.ports ?? []).map((port) => ({\n value: String(port.number),\n label: port.name ? `${port.name} (${port.number})` : String(port.number),\n }));\n}\n\nfunction validPort(port: string) {\n if (!/^\\d+$/.test(port)) return false;\n const number = Number(port);\n return number >= 1 && number <= 65535;\n}\n\nexport function EndpointSelector({\n value,\n onChange,\n namespace,\n modes,\n defaultMode,\n loadWorkloads,\n allowNamespaceSelection = false,\n loadNamespaces,\n onNamespaceChange,\n urlSelector,\n modeKinds,\n defaults,\n preferredPorts = DEFAULT_PREFERRED_ENDPOINT_PORTS,\n schemes,\n allowCustomScheme = true,\n allowCustomPort = false,\n showScheme = false,\n showPath = false,\n showIngressPort = false,\n className,\n}: EndpointSelectorProps) {\n const fallbackMode = defaultMode ?? modes[0];\n if (!fallbackMode || !modes.includes(fallbackMode)) {\n throw new Error(\n \"EndpointSelector requires a default mode included in modes\",\n );\n }\n if (value && !modes.includes(value.mode)) {\n throw new Error(`EndpointSelector value mode \"${value.mode}\" is disabled`);\n }\n if (allowNamespaceSelection && !loadNamespaces) {\n throw new Error(\n \"EndpointSelector namespace selection requires loadNamespaces\",\n );\n }\n\n const [activeMode, setActiveMode] = useState<EndpointMode>(\n value?.mode ?? fallbackMode,\n );\n const [resources, setResources] = useState<EndpointResources>({});\n const resourcesRef = useRef<EndpointResources>({});\n const resourcesNamespaceRef = useRef(namespace);\n const modesKey = modes.join(\",\");\n\n useEffect(() => {\n setActiveMode(\n (current) =>\n value?.mode ?? (modes.includes(current) ? current : fallbackMode),\n );\n }, [value, fallbackMode, modesKey]);\n\n const enabledKinds = useMemo(\n () =>\n activeMode === \"url\"\n ? []\n : (modeKinds?.[activeMode] ?? DEFAULT_MODE_KINDS[activeMode]),\n [activeMode, modeKinds],\n );\n\n const rememberingLoader = useCallback(\n async (kinds: WorkloadKind[], selectedNamespace?: string) => {\n const workloadNamespace = selectedNamespace ?? namespace;\n if (resourcesNamespaceRef.current !== workloadNamespace) {\n resourcesNamespaceRef.current = workloadNamespace;\n resourcesRef.current = {};\n setResources({});\n }\n const loaded = workloadNamespace\n ? await loadWorkloads(kinds, workloadNamespace)\n : await loadWorkloads(kinds);\n const filtered = { ...loaded };\n if (kinds.includes(\"ingress\")) {\n filtered.ingress = (loaded.ingress ?? []).filter(\n (resource) => resource.hosts?.[0],\n );\n }\n if (resourcesNamespaceRef.current === workloadNamespace) {\n resourcesRef.current = { ...resourcesRef.current, ...filtered };\n setResources(resourcesRef.current);\n }\n return filtered;\n },\n [loadWorkloads, namespace],\n );\n\n const selectedResource = useMemo(() => {\n if (!isWorkloadValue(value)) return undefined;\n const target = value.target;\n return resources[target.kind]?.find((resource) => {\n if (target.kind === \"ingress\") {\n return (\n resource.name === target.name || resource.hosts?.[0] === target.host\n );\n }\n return resource.name === target.name;\n });\n }, [resources, value]);\n\n const options = useMemo(\n () => portOptions(selectedResource),\n [selectedResource],\n );\n const selectedPort = isWorkloadValue(value) ? value.port : undefined;\n const selectedPortWarning =\n selectedPort &&\n selectedResource &&\n options.length > 0 &&\n !options.some((option) => option.value === selectedPort)\n ? `Port ${selectedPort} is not exposed by workload \"${selectedResource.name}\"`\n : undefined;\n useEffect(() => {\n if (\n !isWorkloadValue(value) ||\n value.port ||\n !selectedResource\n ) {\n return;\n }\n const port = preferredEndpointPort(\n selectedResource.ports,\n preferredPorts,\n );\n if (port) onChange({ ...value, port });\n }, [\n onChange,\n preferredPorts,\n selectedResource,\n value,\n ]);\n\n const modeOptions = useMemo<SegmentedOption<EndpointMode>[]>(\n () => modes.map((mode) => ({ id: mode, label: MODE_LABELS[mode] })),\n [modes],\n );\n\n const selectMode = (nextMode: EndpointMode) => {\n setActiveMode(nextMode);\n if (nextMode === \"url\") {\n onNamespaceChange?.(undefined);\n if (value?.mode !== \"url\") onChange(undefined);\n return;\n }\n if (\n isWorkloadValue(value) &&\n (modeKinds?.[nextMode] ?? DEFAULT_MODE_KINDS[nextMode]).includes(\n value.target.kind,\n )\n ) {\n onChange({ ...value, mode: nextMode });\n return;\n }\n onChange(undefined);\n };\n\n const selectWorkload = (key: string) => {\n const parsed = key ? parseWorkloadKey(key) : undefined;\n // A namespace-only key (empty name) means a namespace is in scope with no\n // workload picked in it. An endpoint needs a workload to address, so there\n // is nothing to report yet — the namespace reaches the consumer through\n // onNamespaceChange instead.\n if (!parsed || !parsed.name) {\n onChange(undefined);\n return;\n }\n const kind = parsed.kind;\n if (!kind || !enabledKinds.includes(kind)) {\n throw new Error(\n `EndpointSelector received unsupported workload key \"${key}\"`,\n );\n }\n const resource = findResource(resourcesRef.current, kind, parsed.name);\n if (!resource) {\n throw new Error(`EndpointSelector workload \"${key}\" was not loaded`);\n }\n\n const selectedNamespace = parsed.namespace ?? namespace;\n let target: EndpointTarget;\n if (kind === \"ingress\") {\n const host = resource.hosts?.[0];\n if (!host) {\n throw new Error(`Ingress \"${resource.name}\" has no routable host`);\n }\n target = {\n kind,\n name: resource.name,\n host,\n ...(selectedNamespace ? { namespace: selectedNamespace } : {}),\n };\n } else {\n target = {\n kind,\n name: resource.name,\n ...(selectedNamespace ? { namespace: selectedNamespace } : {}),\n };\n }\n\n const previous = isWorkloadValue(value) ? value : undefined;\n const exposed = portOptions(resource).map((option) => option.value);\n const currentPort = previous?.port ?? \"\";\n const port = currentPort &&\n (previous && sameTarget(previous.target, target) ||\n exposed.includes(currentPort))\n ? currentPort\n : (preferredEndpointPort(resource.ports, preferredPorts) ?? defaults?.port);\n const next: EndpointWorkloadValue = {\n mode: activeMode as EndpointWorkloadMode,\n target,\n };\n const scheme = previous?.scheme ?? defaults?.scheme;\n const path = previous?.path ?? defaults?.path;\n if (scheme) next.scheme = scheme;\n if (port) next.port = port;\n if (path) next.path = path;\n onChange(next);\n };\n\n const patchValue = (\n field: \"scheme\" | \"port\" | \"path\",\n fieldValue: string,\n ) => {\n if (!isWorkloadValue(value)) return;\n const next = { ...value };\n if (fieldValue) {\n next[field] = fieldValue;\n } else {\n delete next[field];\n }\n onChange(next);\n };\n\n const workloadValue =\n isWorkloadValue(value) && value.mode === activeMode\n ? targetKey(value.target, namespace, selectedResource)\n : \"\";\n const showPort =\n activeMode !== \"url\" && (activeMode !== \"ingress\" || showIngressPort);\n\n return (\n <div className={cn(\"@container/endpoint space-y-density-2\", className)}>\n <SegmentedControl\n value={activeMode}\n options={modeOptions}\n onChange={selectMode}\n wrap\n aria-label=\"Endpoint access mode\"\n />\n\n {activeMode === \"url\" ? (\n (() => {\n if (!urlSelector) {\n throw new Error(\"EndpointSelector url mode requires urlSelector\");\n }\n return (\n <SecretKeySelector\n {...urlSelector}\n value={value?.mode === \"url\" ? value.source : undefined}\n onChange={(source) =>\n onChange(source ? { mode: \"url\", source } : undefined)\n }\n />\n );\n })()\n ) : (\n <div className=\"space-y-density-2\">\n <div\n className=\"grid w-full max-w-full min-w-0 grid-cols-2 items-end gap-density-2 @min-[40rem]/endpoint:grid-cols-[minmax(14rem,1fr)_auto_auto] @min-[56rem]/endpoint:grid-cols-[minmax(14rem,1fr)_auto_auto_minmax(14rem,1fr)]\"\n data-slot=\"endpoint-fields\"\n >\n <div\n className={WORKLOAD_FIELD}\n data-slot=\"endpoint-workload-field\"\n >\n <Field label=\"Workload\">\n <WorkloadPicker\n value={workloadValue}\n onChange={selectWorkload}\n loadWorkloads={rememberingLoader}\n {...(namespace ? { namespace } : {})}\n {...(allowNamespaceSelection\n ? { allowNamespaceSelection: true }\n : {})}\n {...(loadNamespaces ? { loadNamespaces } : {})}\n {...(onNamespaceChange ? { onNamespaceChange } : {})}\n kinds={enabledKinds}\n strict\n allowCustomValue={false}\n placeholder=\"Select workload…\"\n />\n </Field>\n </div>\n {showScheme && (\n <div\n className={SCHEME_FIELD}\n data-slot=\"endpoint-scheme-field\"\n >\n <Field label=\"Scheme\">\n {schemes?.length && !allowCustomScheme ? (\n <SegmentedControl\n value={isWorkloadValue(value) ? (value.scheme ?? \"\") : \"\"}\n options={schemes.map((scheme) => ({\n id: scheme,\n label: scheme,\n }))}\n onChange={(scheme) => patchValue(\"scheme\", scheme)}\n aria-label=\"Scheme\"\n />\n ) : schemes?.length ? (\n <Combobox\n options={schemes.map((scheme) => ({\n value: scheme,\n label: scheme,\n }))}\n value={isWorkloadValue(value) ? (value.scheme ?? \"\") : \"\"}\n onChange={(scheme) => patchValue(\"scheme\", scheme)}\n allowCustomValue={allowCustomScheme}\n ariaLabel=\"Scheme\"\n />\n ) : (\n <InputField\n value={isWorkloadValue(value) ? (value.scheme ?? \"\") : \"\"}\n onChange={(scheme) => patchValue(\"scheme\", scheme)}\n aria-label=\"Scheme\"\n />\n )}\n </Field>\n </div>\n )}\n {showPort && (\n <div\n className={PORT_FIELD}\n data-slot=\"endpoint-port-field\"\n >\n <Field label=\"Port\">\n <Combobox\n options={options}\n value={isWorkloadValue(value) ? (value.port ?? \"\") : \"\"}\n onChange={(port) => patchValue(\"port\", port)}\n onNew={(port) => {\n if (!validPort(port)) return null;\n if (!options.length || !selectedResource) {\n return { value: port, label: port };\n }\n const warning = `Port ${port} is not exposed by workload \"${selectedResource.name}\"`;\n return {\n value: port,\n label: `Use ${port} — not exposed by ${selectedResource.name}`,\n selectedLabel: port,\n icon: (\n <UiWarningTriangle\n className=\"size-4 shrink-0 text-amber-600\"\n title={warning}\n />\n ),\n title: warning,\n };\n }}\n onCreate={(option) =>\n validPort(option.value) ? option.value : null\n }\n prefix={\n selectedPortWarning ? (\n <UiWarningTriangle\n className=\"size-4 shrink-0 text-amber-600\"\n title={selectedPortWarning}\n />\n ) : undefined\n }\n allowCustomValue={allowCustomPort}\n ariaLabel=\"Port\"\n />\n </Field>\n </div>\n )}\n {showPath && (\n <div\n className={PATH_FIELD}\n data-slot=\"endpoint-path-field\"\n >\n <Field label=\"Path\">\n <InputField\n value={isWorkloadValue(value) ? (value.path ?? \"\") : \"\"}\n onChange={(path) => patchValue(\"path\", path)}\n aria-label=\"Path\"\n {...(isWorkloadValue(value) && value.path\n ? { title: value.path }\n : {})}\n />\n </Field>\n </div>\n )}\n </div>\n </div>\n )}\n </div>\n );\n}\n"],"names":["workloadKey","_a","DEFAULT_PREFERRED_ENDPOINT_PORTS","useState","useRef","useEffect","useMemo","useCallback","preferredEndpointPort","parseWorkloadKey","cn","jsx","SegmentedControl","SecretKeySelector","jsxs","Field","WorkloadPicker","Combobox","InputField","UiWarningTriangle"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EndpointSelector.d.ts","sourceRoot":"","sources":["../../src/components/EndpointSelector.tsx"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAGV,qBAAqB,EAKtB,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"EndpointSelector.d.ts","sourceRoot":"","sources":["../../src/components/EndpointSelector.tsx"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAGV,qBAAqB,EAKtB,MAAM,0BAA0B,CAAC;AA8ElC,wBAAgB,gBAAgB,CAAC,EAC/B,KAAK,EACL,QAAQ,EACR,SAAS,EACT,KAAK,EACL,WAAW,EACX,aAAa,EACb,uBAA+B,EAC/B,cAAc,EACd,iBAAiB,EACjB,WAAW,EACX,SAAS,EACT,QAAQ,EACR,cAAiD,EACjD,OAAO,EACP,iBAAwB,EACxB,eAAuB,EACvB,UAAkB,EAClB,QAAgB,EAChB,eAAuB,EACvB,SAAS,GACV,EAAE,qBAAqB,+BAuXvB"}
|
|
@@ -25,10 +25,10 @@ const DEFAULT_MODE_KINDS = {
|
|
|
25
25
|
ingress: ["ingress"],
|
|
26
26
|
"port-forward": ["service", "deployment"]
|
|
27
27
|
};
|
|
28
|
-
const WORKLOAD_FIELD = "max-w-full min-w-0
|
|
29
|
-
const SCHEME_FIELD = "max-w-full min-w-0
|
|
30
|
-
const PORT_FIELD = "max-w-full min-w-0
|
|
31
|
-
const PATH_FIELD = "max-w-full min-w-0
|
|
28
|
+
const WORKLOAD_FIELD = "col-span-2 max-w-full min-w-0 @min-[40rem]/endpoint:col-span-1";
|
|
29
|
+
const SCHEME_FIELD = "max-w-full min-w-0 w-full";
|
|
30
|
+
const PORT_FIELD = "max-w-full min-w-0 w-full";
|
|
31
|
+
const PATH_FIELD = "col-span-2 max-w-full min-w-0 @min-[40rem]/endpoint:col-span-3 @min-[56rem]/endpoint:col-span-1";
|
|
32
32
|
function isWorkloadValue(value) {
|
|
33
33
|
return value !== void 0 && value.mode !== "url";
|
|
34
34
|
}
|
|
@@ -266,7 +266,7 @@ function EndpointSelector({
|
|
|
266
266
|
};
|
|
267
267
|
const workloadValue = isWorkloadValue(value) && value.mode === activeMode ? targetKey(value.target, namespace, selectedResource) : "";
|
|
268
268
|
const showPort = activeMode !== "url" && (activeMode !== "ingress" || showIngressPort);
|
|
269
|
-
return /* @__PURE__ */ jsxs("div", { className: cn("space-y-density-2", className), children: [
|
|
269
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("@container/endpoint space-y-density-2", className), children: [
|
|
270
270
|
/* @__PURE__ */ jsx(
|
|
271
271
|
SegmentedControl,
|
|
272
272
|
{
|
|
@@ -292,7 +292,7 @@ function EndpointSelector({
|
|
|
292
292
|
})() : /* @__PURE__ */ jsx("div", { className: "space-y-density-2", children: /* @__PURE__ */ jsxs(
|
|
293
293
|
"div",
|
|
294
294
|
{
|
|
295
|
-
className: "
|
|
295
|
+
className: "grid w-full max-w-full min-w-0 grid-cols-2 items-end gap-density-2 @min-[40rem]/endpoint:grid-cols-[minmax(14rem,1fr)_auto_auto] @min-[56rem]/endpoint:grid-cols-[minmax(14rem,1fr)_auto_auto_minmax(14rem,1fr)]",
|
|
296
296
|
"data-slot": "endpoint-fields",
|
|
297
297
|
children: [
|
|
298
298
|
/* @__PURE__ */ jsx(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EndpointSelector.js","sources":["../../src/components/EndpointSelector.tsx"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { UiWarningTriangle } from \"../icons\";\nimport { Combobox, type ComboboxOption } from \"./Combobox\";\nimport {\n DEFAULT_PREFERRED_ENDPOINT_PORTS,\n preferredEndpointPort,\n} from \"./endpoint-port\";\nimport { Field } from \"./Field\";\nimport { InputField } from \"./InputField\";\nimport { SecretKeySelector } from \"./SecretKeySelector\";\nimport { SegmentedControl, type SegmentedOption } from \"./SegmentedControl\";\nimport { WorkloadPicker } from \"./WorkloadPicker\";\nimport {\n parseWorkloadKey,\n workloadKey,\n type WorkloadKind,\n type WorkloadResource,\n} from \"./workload-picker-utils\";\nimport type {\n EndpointMode,\n EndpointResources,\n EndpointSelectorProps,\n EndpointSelectorValue,\n EndpointTarget,\n EndpointWorkloadValue,\n EndpointWorkloadMode,\n} from \"./EndpointSelector.model\";\nconst MODE_LABELS: Record<EndpointMode, string> = {\n url: \"URL\",\n service: \"Service\",\n \"cluster-ip\": \"Cluster IP\",\n \"api-proxy\": \"API proxy\",\n ingress: \"Ingress\",\n \"port-forward\": \"Port-forward\",\n};\nconst DEFAULT_MODE_KINDS: Record<EndpointWorkloadMode, WorkloadKind[]> = {\n service: [\"service\"],\n \"cluster-ip\": [\"service\"],\n \"api-proxy\": [\"service\"],\n ingress: [\"ingress\"],\n \"port-forward\": [\"service\", \"deployment\"],\n};\nconst WORKLOAD_FIELD =\n \"max-w-full min-w-0 basis-56 shrink grow\";\nconst SCHEME_FIELD =\n \"max-w-full min-w-0 basis-32 shrink grow-0\";\nconst PORT_FIELD =\n \"max-w-full min-w-0 basis-36 shrink grow-0\";\nconst PATH_FIELD =\n \"max-w-full min-w-0 basis-56 shrink grow\";\nfunction isWorkloadValue(\n value: EndpointSelectorValue | undefined,\n): value is EndpointWorkloadValue {\n return value !== undefined && value.mode !== \"url\";\n}\n\nfunction sameTarget(left: EndpointTarget, right: EndpointTarget) {\n if (left.kind !== right.kind || left.namespace !== right.namespace)\n return false;\n if (left.kind === \"ingress\" && right.kind === \"ingress\") {\n return left.name === right.name && left.host === right.host;\n }\n return left.name === right.name;\n}\n\nfunction targetKey(\n target: EndpointTarget,\n namespace: string | undefined,\n resource: WorkloadResource | undefined,\n) {\n if (target.kind === \"ingress\") {\n return workloadKey(target.namespace ?? namespace, target.kind, {\n name: target.name,\n hosts: [target.host ?? resource?.hosts?.[0] ?? target.name],\n });\n }\n return workloadKey(target.namespace ?? namespace, target.kind, {\n name: target.name,\n });\n}\n\nfunction findResource(\n resources: EndpointResources,\n kind: WorkloadKind,\n selectedName: string,\n) {\n return resources[kind]?.find((resource) =>\n kind === \"ingress\"\n ? resource.hosts?.[0] === selectedName\n : resource.name === selectedName,\n );\n}\n\nfunction portOptions(resource: WorkloadResource | undefined): ComboboxOption[] {\n return (resource?.ports ?? []).map((port) => ({\n value: String(port.number),\n label: port.name ? `${port.name} (${port.number})` : String(port.number),\n }));\n}\n\nfunction validPort(port: string) {\n if (!/^\\d+$/.test(port)) return false;\n const number = Number(port);\n return number >= 1 && number <= 65535;\n}\n\nexport function EndpointSelector({\n value,\n onChange,\n namespace,\n modes,\n defaultMode,\n loadWorkloads,\n allowNamespaceSelection = false,\n loadNamespaces,\n onNamespaceChange,\n urlSelector,\n modeKinds,\n defaults,\n preferredPorts = DEFAULT_PREFERRED_ENDPOINT_PORTS,\n schemes,\n allowCustomScheme = true,\n allowCustomPort = false,\n showScheme = false,\n showPath = false,\n showIngressPort = false,\n className,\n}: EndpointSelectorProps) {\n const fallbackMode = defaultMode ?? modes[0];\n if (!fallbackMode || !modes.includes(fallbackMode)) {\n throw new Error(\n \"EndpointSelector requires a default mode included in modes\",\n );\n }\n if (value && !modes.includes(value.mode)) {\n throw new Error(`EndpointSelector value mode \"${value.mode}\" is disabled`);\n }\n if (allowNamespaceSelection && !loadNamespaces) {\n throw new Error(\n \"EndpointSelector namespace selection requires loadNamespaces\",\n );\n }\n\n const [activeMode, setActiveMode] = useState<EndpointMode>(\n value?.mode ?? fallbackMode,\n );\n const [resources, setResources] = useState<EndpointResources>({});\n const resourcesRef = useRef<EndpointResources>({});\n const resourcesNamespaceRef = useRef(namespace);\n const modesKey = modes.join(\",\");\n\n useEffect(() => {\n setActiveMode(\n (current) =>\n value?.mode ?? (modes.includes(current) ? current : fallbackMode),\n );\n }, [value, fallbackMode, modesKey]);\n\n const enabledKinds = useMemo(\n () =>\n activeMode === \"url\"\n ? []\n : (modeKinds?.[activeMode] ?? DEFAULT_MODE_KINDS[activeMode]),\n [activeMode, modeKinds],\n );\n\n const rememberingLoader = useCallback(\n async (kinds: WorkloadKind[], selectedNamespace?: string) => {\n const workloadNamespace = selectedNamespace ?? namespace;\n if (resourcesNamespaceRef.current !== workloadNamespace) {\n resourcesNamespaceRef.current = workloadNamespace;\n resourcesRef.current = {};\n setResources({});\n }\n const loaded = workloadNamespace\n ? await loadWorkloads(kinds, workloadNamespace)\n : await loadWorkloads(kinds);\n const filtered = { ...loaded };\n if (kinds.includes(\"ingress\")) {\n filtered.ingress = (loaded.ingress ?? []).filter(\n (resource) => resource.hosts?.[0],\n );\n }\n if (resourcesNamespaceRef.current === workloadNamespace) {\n resourcesRef.current = { ...resourcesRef.current, ...filtered };\n setResources(resourcesRef.current);\n }\n return filtered;\n },\n [loadWorkloads, namespace],\n );\n\n const selectedResource = useMemo(() => {\n if (!isWorkloadValue(value)) return undefined;\n const target = value.target;\n return resources[target.kind]?.find((resource) => {\n if (target.kind === \"ingress\") {\n return (\n resource.name === target.name || resource.hosts?.[0] === target.host\n );\n }\n return resource.name === target.name;\n });\n }, [resources, value]);\n\n const options = useMemo(\n () => portOptions(selectedResource),\n [selectedResource],\n );\n const selectedPort = isWorkloadValue(value) ? value.port : undefined;\n const selectedPortWarning =\n selectedPort &&\n selectedResource &&\n options.length > 0 &&\n !options.some((option) => option.value === selectedPort)\n ? `Port ${selectedPort} is not exposed by workload \"${selectedResource.name}\"`\n : undefined;\n useEffect(() => {\n if (\n !isWorkloadValue(value) ||\n value.port ||\n !selectedResource\n ) {\n return;\n }\n const port = preferredEndpointPort(\n selectedResource.ports,\n preferredPorts,\n );\n if (port) onChange({ ...value, port });\n }, [\n onChange,\n preferredPorts,\n selectedResource,\n value,\n ]);\n\n const modeOptions = useMemo<SegmentedOption<EndpointMode>[]>(\n () => modes.map((mode) => ({ id: mode, label: MODE_LABELS[mode] })),\n [modes],\n );\n\n const selectMode = (nextMode: EndpointMode) => {\n setActiveMode(nextMode);\n if (nextMode === \"url\") {\n onNamespaceChange?.(undefined);\n if (value?.mode !== \"url\") onChange(undefined);\n return;\n }\n if (\n isWorkloadValue(value) &&\n (modeKinds?.[nextMode] ?? DEFAULT_MODE_KINDS[nextMode]).includes(\n value.target.kind,\n )\n ) {\n onChange({ ...value, mode: nextMode });\n return;\n }\n onChange(undefined);\n };\n\n const selectWorkload = (key: string) => {\n const parsed = key ? parseWorkloadKey(key) : undefined;\n // A namespace-only key (empty name) means a namespace is in scope with no\n // workload picked in it. An endpoint needs a workload to address, so there\n // is nothing to report yet — the namespace reaches the consumer through\n // onNamespaceChange instead.\n if (!parsed || !parsed.name) {\n onChange(undefined);\n return;\n }\n const kind = parsed.kind;\n if (!kind || !enabledKinds.includes(kind)) {\n throw new Error(\n `EndpointSelector received unsupported workload key \"${key}\"`,\n );\n }\n const resource = findResource(resourcesRef.current, kind, parsed.name);\n if (!resource) {\n throw new Error(`EndpointSelector workload \"${key}\" was not loaded`);\n }\n\n const selectedNamespace = parsed.namespace ?? namespace;\n let target: EndpointTarget;\n if (kind === \"ingress\") {\n const host = resource.hosts?.[0];\n if (!host) {\n throw new Error(`Ingress \"${resource.name}\" has no routable host`);\n }\n target = {\n kind,\n name: resource.name,\n host,\n ...(selectedNamespace ? { namespace: selectedNamespace } : {}),\n };\n } else {\n target = {\n kind,\n name: resource.name,\n ...(selectedNamespace ? { namespace: selectedNamespace } : {}),\n };\n }\n\n const previous = isWorkloadValue(value) ? value : undefined;\n const exposed = portOptions(resource).map((option) => option.value);\n const currentPort = previous?.port ?? \"\";\n const port = currentPort &&\n (previous && sameTarget(previous.target, target) ||\n exposed.includes(currentPort))\n ? currentPort\n : (preferredEndpointPort(resource.ports, preferredPorts) ?? defaults?.port);\n const next: EndpointWorkloadValue = {\n mode: activeMode as EndpointWorkloadMode,\n target,\n };\n const scheme = previous?.scheme ?? defaults?.scheme;\n const path = previous?.path ?? defaults?.path;\n if (scheme) next.scheme = scheme;\n if (port) next.port = port;\n if (path) next.path = path;\n onChange(next);\n };\n\n const patchValue = (\n field: \"scheme\" | \"port\" | \"path\",\n fieldValue: string,\n ) => {\n if (!isWorkloadValue(value)) return;\n const next = { ...value };\n if (fieldValue) {\n next[field] = fieldValue;\n } else {\n delete next[field];\n }\n onChange(next);\n };\n\n const workloadValue =\n isWorkloadValue(value) && value.mode === activeMode\n ? targetKey(value.target, namespace, selectedResource)\n : \"\";\n const showPort =\n activeMode !== \"url\" && (activeMode !== \"ingress\" || showIngressPort);\n\n return (\n <div className={cn(\"space-y-density-2\", className)}>\n <SegmentedControl\n value={activeMode}\n options={modeOptions}\n onChange={selectMode}\n wrap\n aria-label=\"Endpoint access mode\"\n />\n\n {activeMode === \"url\" ? (\n (() => {\n if (!urlSelector) {\n throw new Error(\"EndpointSelector url mode requires urlSelector\");\n }\n return (\n <SecretKeySelector\n {...urlSelector}\n value={value?.mode === \"url\" ? value.source : undefined}\n onChange={(source) =>\n onChange(source ? { mode: \"url\", source } : undefined)\n }\n />\n );\n })()\n ) : (\n <div className=\"space-y-density-2\">\n <div\n className=\"flex w-full max-w-full min-w-0 flex-nowrap items-end gap-density-2\"\n data-slot=\"endpoint-fields\"\n >\n <div\n className={WORKLOAD_FIELD}\n data-slot=\"endpoint-workload-field\"\n >\n <Field label=\"Workload\">\n <WorkloadPicker\n value={workloadValue}\n onChange={selectWorkload}\n loadWorkloads={rememberingLoader}\n {...(namespace ? { namespace } : {})}\n {...(allowNamespaceSelection\n ? { allowNamespaceSelection: true }\n : {})}\n {...(loadNamespaces ? { loadNamespaces } : {})}\n {...(onNamespaceChange ? { onNamespaceChange } : {})}\n kinds={enabledKinds}\n strict\n allowCustomValue={false}\n placeholder=\"Select workload…\"\n />\n </Field>\n </div>\n {showScheme && (\n <div\n className={SCHEME_FIELD}\n data-slot=\"endpoint-scheme-field\"\n >\n <Field label=\"Scheme\">\n {schemes?.length && !allowCustomScheme ? (\n <SegmentedControl\n value={isWorkloadValue(value) ? (value.scheme ?? \"\") : \"\"}\n options={schemes.map((scheme) => ({\n id: scheme,\n label: scheme,\n }))}\n onChange={(scheme) => patchValue(\"scheme\", scheme)}\n aria-label=\"Scheme\"\n />\n ) : schemes?.length ? (\n <Combobox\n options={schemes.map((scheme) => ({\n value: scheme,\n label: scheme,\n }))}\n value={isWorkloadValue(value) ? (value.scheme ?? \"\") : \"\"}\n onChange={(scheme) => patchValue(\"scheme\", scheme)}\n allowCustomValue={allowCustomScheme}\n ariaLabel=\"Scheme\"\n />\n ) : (\n <InputField\n value={isWorkloadValue(value) ? (value.scheme ?? \"\") : \"\"}\n onChange={(scheme) => patchValue(\"scheme\", scheme)}\n aria-label=\"Scheme\"\n />\n )}\n </Field>\n </div>\n )}\n {showPort && (\n <div\n className={PORT_FIELD}\n data-slot=\"endpoint-port-field\"\n >\n <Field label=\"Port\">\n <Combobox\n options={options}\n value={isWorkloadValue(value) ? (value.port ?? \"\") : \"\"}\n onChange={(port) => patchValue(\"port\", port)}\n onNew={(port) => {\n if (!validPort(port)) return null;\n if (!options.length || !selectedResource) {\n return { value: port, label: port };\n }\n const warning = `Port ${port} is not exposed by workload \"${selectedResource.name}\"`;\n return {\n value: port,\n label: `Use ${port} — not exposed by ${selectedResource.name}`,\n selectedLabel: port,\n icon: (\n <UiWarningTriangle\n className=\"size-4 shrink-0 text-amber-600\"\n title={warning}\n />\n ),\n title: warning,\n };\n }}\n onCreate={(option) =>\n validPort(option.value) ? option.value : null\n }\n prefix={\n selectedPortWarning ? (\n <UiWarningTriangle\n className=\"size-4 shrink-0 text-amber-600\"\n title={selectedPortWarning}\n />\n ) : undefined\n }\n allowCustomValue={allowCustomPort}\n ariaLabel=\"Port\"\n />\n </Field>\n </div>\n )}\n {showPath && (\n <div\n className={PATH_FIELD}\n data-slot=\"endpoint-path-field\"\n >\n <Field label=\"Path\">\n <InputField\n value={isWorkloadValue(value) ? (value.path ?? \"\") : \"\"}\n onChange={(path) => patchValue(\"path\", path)}\n aria-label=\"Path\"\n {...(isWorkloadValue(value) && value.path\n ? { title: value.path }\n : {})}\n />\n </Field>\n </div>\n )}\n </div>\n </div>\n )}\n </div>\n );\n}\n"],"names":["_a"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"EndpointSelector.js","sources":["../../src/components/EndpointSelector.tsx"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { cn } from \"../lib/utils\";\nimport { UiWarningTriangle } from \"../icons\";\nimport { Combobox, type ComboboxOption } from \"./Combobox\";\nimport {\n DEFAULT_PREFERRED_ENDPOINT_PORTS,\n preferredEndpointPort,\n} from \"./endpoint-port\";\nimport { Field } from \"./Field\";\nimport { InputField } from \"./InputField\";\nimport { SecretKeySelector } from \"./SecretKeySelector\";\nimport { SegmentedControl, type SegmentedOption } from \"./SegmentedControl\";\nimport { WorkloadPicker } from \"./WorkloadPicker\";\nimport {\n parseWorkloadKey,\n workloadKey,\n type WorkloadKind,\n type WorkloadResource,\n} from \"./workload-picker-utils\";\nimport type {\n EndpointMode,\n EndpointResources,\n EndpointSelectorProps,\n EndpointSelectorValue,\n EndpointTarget,\n EndpointWorkloadValue,\n EndpointWorkloadMode,\n} from \"./EndpointSelector.model\";\nconst MODE_LABELS: Record<EndpointMode, string> = {\n url: \"URL\",\n service: \"Service\",\n \"cluster-ip\": \"Cluster IP\",\n \"api-proxy\": \"API proxy\",\n ingress: \"Ingress\",\n \"port-forward\": \"Port-forward\",\n};\nconst DEFAULT_MODE_KINDS: Record<EndpointWorkloadMode, WorkloadKind[]> = {\n service: [\"service\"],\n \"cluster-ip\": [\"service\"],\n \"api-proxy\": [\"service\"],\n ingress: [\"ingress\"],\n \"port-forward\": [\"service\", \"deployment\"],\n};\nconst WORKLOAD_FIELD =\n \"col-span-2 max-w-full min-w-0 @min-[40rem]/endpoint:col-span-1\";\nconst SCHEME_FIELD = \"max-w-full min-w-0 w-full\";\nconst PORT_FIELD = \"max-w-full min-w-0 w-full\";\nconst PATH_FIELD =\n \"col-span-2 max-w-full min-w-0 @min-[40rem]/endpoint:col-span-3 @min-[56rem]/endpoint:col-span-1\";\nfunction isWorkloadValue(\n value: EndpointSelectorValue | undefined,\n): value is EndpointWorkloadValue {\n return value !== undefined && value.mode !== \"url\";\n}\n\nfunction sameTarget(left: EndpointTarget, right: EndpointTarget) {\n if (left.kind !== right.kind || left.namespace !== right.namespace)\n return false;\n if (left.kind === \"ingress\" && right.kind === \"ingress\") {\n return left.name === right.name && left.host === right.host;\n }\n return left.name === right.name;\n}\n\nfunction targetKey(\n target: EndpointTarget,\n namespace: string | undefined,\n resource: WorkloadResource | undefined,\n) {\n if (target.kind === \"ingress\") {\n return workloadKey(target.namespace ?? namespace, target.kind, {\n name: target.name,\n hosts: [target.host ?? resource?.hosts?.[0] ?? target.name],\n });\n }\n return workloadKey(target.namespace ?? namespace, target.kind, {\n name: target.name,\n });\n}\n\nfunction findResource(\n resources: EndpointResources,\n kind: WorkloadKind,\n selectedName: string,\n) {\n return resources[kind]?.find((resource) =>\n kind === \"ingress\"\n ? resource.hosts?.[0] === selectedName\n : resource.name === selectedName,\n );\n}\n\nfunction portOptions(resource: WorkloadResource | undefined): ComboboxOption[] {\n return (resource?.ports ?? []).map((port) => ({\n value: String(port.number),\n label: port.name ? `${port.name} (${port.number})` : String(port.number),\n }));\n}\n\nfunction validPort(port: string) {\n if (!/^\\d+$/.test(port)) return false;\n const number = Number(port);\n return number >= 1 && number <= 65535;\n}\n\nexport function EndpointSelector({\n value,\n onChange,\n namespace,\n modes,\n defaultMode,\n loadWorkloads,\n allowNamespaceSelection = false,\n loadNamespaces,\n onNamespaceChange,\n urlSelector,\n modeKinds,\n defaults,\n preferredPorts = DEFAULT_PREFERRED_ENDPOINT_PORTS,\n schemes,\n allowCustomScheme = true,\n allowCustomPort = false,\n showScheme = false,\n showPath = false,\n showIngressPort = false,\n className,\n}: EndpointSelectorProps) {\n const fallbackMode = defaultMode ?? modes[0];\n if (!fallbackMode || !modes.includes(fallbackMode)) {\n throw new Error(\n \"EndpointSelector requires a default mode included in modes\",\n );\n }\n if (value && !modes.includes(value.mode)) {\n throw new Error(`EndpointSelector value mode \"${value.mode}\" is disabled`);\n }\n if (allowNamespaceSelection && !loadNamespaces) {\n throw new Error(\n \"EndpointSelector namespace selection requires loadNamespaces\",\n );\n }\n\n const [activeMode, setActiveMode] = useState<EndpointMode>(\n value?.mode ?? fallbackMode,\n );\n const [resources, setResources] = useState<EndpointResources>({});\n const resourcesRef = useRef<EndpointResources>({});\n const resourcesNamespaceRef = useRef(namespace);\n const modesKey = modes.join(\",\");\n\n useEffect(() => {\n setActiveMode(\n (current) =>\n value?.mode ?? (modes.includes(current) ? current : fallbackMode),\n );\n }, [value, fallbackMode, modesKey]);\n\n const enabledKinds = useMemo(\n () =>\n activeMode === \"url\"\n ? []\n : (modeKinds?.[activeMode] ?? DEFAULT_MODE_KINDS[activeMode]),\n [activeMode, modeKinds],\n );\n\n const rememberingLoader = useCallback(\n async (kinds: WorkloadKind[], selectedNamespace?: string) => {\n const workloadNamespace = selectedNamespace ?? namespace;\n if (resourcesNamespaceRef.current !== workloadNamespace) {\n resourcesNamespaceRef.current = workloadNamespace;\n resourcesRef.current = {};\n setResources({});\n }\n const loaded = workloadNamespace\n ? await loadWorkloads(kinds, workloadNamespace)\n : await loadWorkloads(kinds);\n const filtered = { ...loaded };\n if (kinds.includes(\"ingress\")) {\n filtered.ingress = (loaded.ingress ?? []).filter(\n (resource) => resource.hosts?.[0],\n );\n }\n if (resourcesNamespaceRef.current === workloadNamespace) {\n resourcesRef.current = { ...resourcesRef.current, ...filtered };\n setResources(resourcesRef.current);\n }\n return filtered;\n },\n [loadWorkloads, namespace],\n );\n\n const selectedResource = useMemo(() => {\n if (!isWorkloadValue(value)) return undefined;\n const target = value.target;\n return resources[target.kind]?.find((resource) => {\n if (target.kind === \"ingress\") {\n return (\n resource.name === target.name || resource.hosts?.[0] === target.host\n );\n }\n return resource.name === target.name;\n });\n }, [resources, value]);\n\n const options = useMemo(\n () => portOptions(selectedResource),\n [selectedResource],\n );\n const selectedPort = isWorkloadValue(value) ? value.port : undefined;\n const selectedPortWarning =\n selectedPort &&\n selectedResource &&\n options.length > 0 &&\n !options.some((option) => option.value === selectedPort)\n ? `Port ${selectedPort} is not exposed by workload \"${selectedResource.name}\"`\n : undefined;\n useEffect(() => {\n if (\n !isWorkloadValue(value) ||\n value.port ||\n !selectedResource\n ) {\n return;\n }\n const port = preferredEndpointPort(\n selectedResource.ports,\n preferredPorts,\n );\n if (port) onChange({ ...value, port });\n }, [\n onChange,\n preferredPorts,\n selectedResource,\n value,\n ]);\n\n const modeOptions = useMemo<SegmentedOption<EndpointMode>[]>(\n () => modes.map((mode) => ({ id: mode, label: MODE_LABELS[mode] })),\n [modes],\n );\n\n const selectMode = (nextMode: EndpointMode) => {\n setActiveMode(nextMode);\n if (nextMode === \"url\") {\n onNamespaceChange?.(undefined);\n if (value?.mode !== \"url\") onChange(undefined);\n return;\n }\n if (\n isWorkloadValue(value) &&\n (modeKinds?.[nextMode] ?? DEFAULT_MODE_KINDS[nextMode]).includes(\n value.target.kind,\n )\n ) {\n onChange({ ...value, mode: nextMode });\n return;\n }\n onChange(undefined);\n };\n\n const selectWorkload = (key: string) => {\n const parsed = key ? parseWorkloadKey(key) : undefined;\n // A namespace-only key (empty name) means a namespace is in scope with no\n // workload picked in it. An endpoint needs a workload to address, so there\n // is nothing to report yet — the namespace reaches the consumer through\n // onNamespaceChange instead.\n if (!parsed || !parsed.name) {\n onChange(undefined);\n return;\n }\n const kind = parsed.kind;\n if (!kind || !enabledKinds.includes(kind)) {\n throw new Error(\n `EndpointSelector received unsupported workload key \"${key}\"`,\n );\n }\n const resource = findResource(resourcesRef.current, kind, parsed.name);\n if (!resource) {\n throw new Error(`EndpointSelector workload \"${key}\" was not loaded`);\n }\n\n const selectedNamespace = parsed.namespace ?? namespace;\n let target: EndpointTarget;\n if (kind === \"ingress\") {\n const host = resource.hosts?.[0];\n if (!host) {\n throw new Error(`Ingress \"${resource.name}\" has no routable host`);\n }\n target = {\n kind,\n name: resource.name,\n host,\n ...(selectedNamespace ? { namespace: selectedNamespace } : {}),\n };\n } else {\n target = {\n kind,\n name: resource.name,\n ...(selectedNamespace ? { namespace: selectedNamespace } : {}),\n };\n }\n\n const previous = isWorkloadValue(value) ? value : undefined;\n const exposed = portOptions(resource).map((option) => option.value);\n const currentPort = previous?.port ?? \"\";\n const port = currentPort &&\n (previous && sameTarget(previous.target, target) ||\n exposed.includes(currentPort))\n ? currentPort\n : (preferredEndpointPort(resource.ports, preferredPorts) ?? defaults?.port);\n const next: EndpointWorkloadValue = {\n mode: activeMode as EndpointWorkloadMode,\n target,\n };\n const scheme = previous?.scheme ?? defaults?.scheme;\n const path = previous?.path ?? defaults?.path;\n if (scheme) next.scheme = scheme;\n if (port) next.port = port;\n if (path) next.path = path;\n onChange(next);\n };\n\n const patchValue = (\n field: \"scheme\" | \"port\" | \"path\",\n fieldValue: string,\n ) => {\n if (!isWorkloadValue(value)) return;\n const next = { ...value };\n if (fieldValue) {\n next[field] = fieldValue;\n } else {\n delete next[field];\n }\n onChange(next);\n };\n\n const workloadValue =\n isWorkloadValue(value) && value.mode === activeMode\n ? targetKey(value.target, namespace, selectedResource)\n : \"\";\n const showPort =\n activeMode !== \"url\" && (activeMode !== \"ingress\" || showIngressPort);\n\n return (\n <div className={cn(\"@container/endpoint space-y-density-2\", className)}>\n <SegmentedControl\n value={activeMode}\n options={modeOptions}\n onChange={selectMode}\n wrap\n aria-label=\"Endpoint access mode\"\n />\n\n {activeMode === \"url\" ? (\n (() => {\n if (!urlSelector) {\n throw new Error(\"EndpointSelector url mode requires urlSelector\");\n }\n return (\n <SecretKeySelector\n {...urlSelector}\n value={value?.mode === \"url\" ? value.source : undefined}\n onChange={(source) =>\n onChange(source ? { mode: \"url\", source } : undefined)\n }\n />\n );\n })()\n ) : (\n <div className=\"space-y-density-2\">\n <div\n className=\"grid w-full max-w-full min-w-0 grid-cols-2 items-end gap-density-2 @min-[40rem]/endpoint:grid-cols-[minmax(14rem,1fr)_auto_auto] @min-[56rem]/endpoint:grid-cols-[minmax(14rem,1fr)_auto_auto_minmax(14rem,1fr)]\"\n data-slot=\"endpoint-fields\"\n >\n <div\n className={WORKLOAD_FIELD}\n data-slot=\"endpoint-workload-field\"\n >\n <Field label=\"Workload\">\n <WorkloadPicker\n value={workloadValue}\n onChange={selectWorkload}\n loadWorkloads={rememberingLoader}\n {...(namespace ? { namespace } : {})}\n {...(allowNamespaceSelection\n ? { allowNamespaceSelection: true }\n : {})}\n {...(loadNamespaces ? { loadNamespaces } : {})}\n {...(onNamespaceChange ? { onNamespaceChange } : {})}\n kinds={enabledKinds}\n strict\n allowCustomValue={false}\n placeholder=\"Select workload…\"\n />\n </Field>\n </div>\n {showScheme && (\n <div\n className={SCHEME_FIELD}\n data-slot=\"endpoint-scheme-field\"\n >\n <Field label=\"Scheme\">\n {schemes?.length && !allowCustomScheme ? (\n <SegmentedControl\n value={isWorkloadValue(value) ? (value.scheme ?? \"\") : \"\"}\n options={schemes.map((scheme) => ({\n id: scheme,\n label: scheme,\n }))}\n onChange={(scheme) => patchValue(\"scheme\", scheme)}\n aria-label=\"Scheme\"\n />\n ) : schemes?.length ? (\n <Combobox\n options={schemes.map((scheme) => ({\n value: scheme,\n label: scheme,\n }))}\n value={isWorkloadValue(value) ? (value.scheme ?? \"\") : \"\"}\n onChange={(scheme) => patchValue(\"scheme\", scheme)}\n allowCustomValue={allowCustomScheme}\n ariaLabel=\"Scheme\"\n />\n ) : (\n <InputField\n value={isWorkloadValue(value) ? (value.scheme ?? \"\") : \"\"}\n onChange={(scheme) => patchValue(\"scheme\", scheme)}\n aria-label=\"Scheme\"\n />\n )}\n </Field>\n </div>\n )}\n {showPort && (\n <div\n className={PORT_FIELD}\n data-slot=\"endpoint-port-field\"\n >\n <Field label=\"Port\">\n <Combobox\n options={options}\n value={isWorkloadValue(value) ? (value.port ?? \"\") : \"\"}\n onChange={(port) => patchValue(\"port\", port)}\n onNew={(port) => {\n if (!validPort(port)) return null;\n if (!options.length || !selectedResource) {\n return { value: port, label: port };\n }\n const warning = `Port ${port} is not exposed by workload \"${selectedResource.name}\"`;\n return {\n value: port,\n label: `Use ${port} — not exposed by ${selectedResource.name}`,\n selectedLabel: port,\n icon: (\n <UiWarningTriangle\n className=\"size-4 shrink-0 text-amber-600\"\n title={warning}\n />\n ),\n title: warning,\n };\n }}\n onCreate={(option) =>\n validPort(option.value) ? option.value : null\n }\n prefix={\n selectedPortWarning ? (\n <UiWarningTriangle\n className=\"size-4 shrink-0 text-amber-600\"\n title={selectedPortWarning}\n />\n ) : undefined\n }\n allowCustomValue={allowCustomPort}\n ariaLabel=\"Port\"\n />\n </Field>\n </div>\n )}\n {showPath && (\n <div\n className={PATH_FIELD}\n data-slot=\"endpoint-path-field\"\n >\n <Field label=\"Path\">\n <InputField\n value={isWorkloadValue(value) ? (value.path ?? \"\") : \"\"}\n onChange={(path) => patchValue(\"path\", path)}\n aria-label=\"Path\"\n {...(isWorkloadValue(value) && value.path\n ? { title: value.path }\n : {})}\n />\n </Field>\n </div>\n )}\n </div>\n </div>\n )}\n </div>\n );\n}\n"],"names":["_a"],"mappings":"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"}
|
|
@@ -152,8 +152,9 @@ function errorReport(error, componentStack) {
|
|
|
152
152
|
];
|
|
153
153
|
if (error.name !== "Error") lines.push(`Type: ${error.name}`);
|
|
154
154
|
if (error.cause !== void 0) lines.push(`Cause: ${String(error.cause)}`);
|
|
155
|
-
if (typeof window !== "undefined")
|
|
156
|
-
lines.push(`Page: ${window.location.
|
|
155
|
+
if (typeof window !== "undefined") {
|
|
156
|
+
lines.push(`Page: ${window.location.origin}${window.location.pathname}`);
|
|
157
|
+
}
|
|
157
158
|
if (typeof navigator !== "undefined" && navigator.userAgent) {
|
|
158
159
|
lines.push(`User agent: ${navigator.userAgent}`);
|
|
159
160
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ErrorWrapper.cjs","sources":["../../src/components/ErrorWrapper.tsx"],"sourcesContent":["import {\n Component,\n useMemo,\n useState,\n type ErrorInfo,\n type ReactNode,\n} from \"react\";\nimport { ErrorDetails } from \"../data/diagnostics/ErrorDetails\";\nimport {\n normalizeErrorDiagnostics,\n type ErrorDiagnostics,\n} from \"../data/diagnostics/error-diagnostics\";\nimport { Icon } from \"../data/Icon\";\nimport { UiCheck, UiCopy, UiWarningTriangle } from \"../icons\";\nimport { cn } from \"../lib/utils\";\nimport { Button } from \"./button\";\n\nexport type ErrorWrapperProps = {\n children: ReactNode;\n onError?: (error: Error, errorInfo: ErrorInfo) => void;\n};\n\ntype ErrorWrapperState = {\n error: Error | null;\n componentStack: string | null;\n};\n\nexport class ErrorWrapper extends Component<\n ErrorWrapperProps,\n ErrorWrapperState\n> {\n override state: ErrorWrapperState = {\n error: null,\n componentStack: null,\n };\n\n static getDerivedStateFromError(error: Error) {\n return { error };\n }\n\n override componentDidCatch(error: Error, errorInfo: ErrorInfo) {\n this.setState({ componentStack: errorInfo.componentStack ?? null });\n this.props.onError?.(error, errorInfo);\n }\n\n override render() {\n if (this.state.error) {\n return (\n <ErrorFallback\n error={this.state.error}\n componentStack={this.state.componentStack}\n />\n );\n }\n return this.props.children;\n }\n}\n\ntype CopyState = \"idle\" | \"copied\" | \"failed\";\n\nfunction copyStatusMessage(copyState: CopyState): string {\n if (copyState === \"copied\") return \"Error details copied to clipboard.\";\n if (copyState === \"failed\") {\n return \"Clipboard access failed. Expand the error details to copy individual values.\";\n }\n return \"\";\n}\n\nfunction ErrorFallback({\n error,\n componentStack,\n}: {\n error: Error;\n componentStack: string | null;\n}) {\n const [copyState, setCopyState] = useState<CopyState>(\"idle\");\n const diagnostics = useMemo(\n () => errorDiagnostics(error, componentStack),\n [componentStack, error],\n );\n\n const copyDetails = async () => {\n if (!navigator.clipboard?.writeText) {\n setCopyState(\"failed\");\n return;\n }\n try {\n await navigator.clipboard.writeText(errorReport(error, componentStack));\n setCopyState(\"copied\");\n } catch {\n setCopyState(\"failed\");\n }\n };\n\n return (\n <main\n data-slot=\"error-wrapper\"\n role=\"alert\"\n aria-labelledby=\"error-wrapper-title\"\n className=\"flex min-h-dvh w-full items-center justify-center bg-background p-density-6 text-foreground\"\n >\n <div className=\"w-full max-w-3xl\">\n <div className=\"mb-density-4 flex items-start gap-density-3\">\n <span className=\"grid size-12 shrink-0 place-items-center rounded-full bg-destructive/10 text-destructive\">\n <Icon icon={UiWarningTriangle} className=\"size-6\" />\n </span>\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-xs font-semibold uppercase tracking-wide text-destructive\">\n Unexpected application error\n </p>\n <h1\n id=\"error-wrapper-title\"\n className=\"mt-density-1 text-2xl font-semibold tracking-tight\"\n >\n Something went wrong\n </h1>\n <p className=\"mt-density-2 break-words text-sm text-muted-foreground\">\n {diagnostics.message}\n </p>\n </div>\n </div>\n\n <div className=\"mb-density-3 flex items-center gap-density-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => void copyDetails()}\n >\n <Icon icon={copyState === \"copied\" ? UiCheck : UiCopy} />\n {/* Distinct from ErrorDetails' own \"Copy error details\" control\n below: this copies the page-level report (URL, user agent,\n React component stack), and two identically named buttons in\n one view are ambiguous to assistive tech. */}\n {copyState === \"copied\" ? \"Copied\" : \"Copy error report\"}\n </Button>\n <span\n aria-live=\"polite\"\n className={cn(\n \"text-xs\",\n copyState === \"failed\"\n ? \"text-destructive\"\n : \"text-muted-foreground\",\n )}\n >\n {copyStatusMessage(copyState)}\n </span>\n </div>\n\n <ErrorDetails diagnostics={diagnostics} />\n </div>\n </main>\n );\n}\n\nfunction errorDiagnostics(\n error: Error,\n componentStack: string | null,\n): ErrorDiagnostics {\n const diagnostics = normalizeErrorDiagnostics(\n error,\n \"An unexpected error was thrown without a message.\",\n );\n if (!diagnostics) {\n throw new Error(\"ErrorWrapper could not normalize the captured error\");\n }\n\n const cause =\n error.cause === undefined\n ? []\n : [[\"cause\", String(error.cause)] as [string, string]];\n const reactStack = componentStack?.trim();\n return {\n ...diagnostics,\n context: [...diagnostics.context, ...cause],\n ...(reactStack\n ? {\n stacktrace: [\n diagnostics.stacktrace,\n \"React component stack:\",\n reactStack,\n ]\n .filter(Boolean)\n .join(\"\\n\\n\"),\n }\n : {}),\n };\n}\n\nfunction errorReport(error: Error, componentStack: string | null) {\n const lines = [\n `Error: ${error.message || \"An unexpected error was thrown without a message.\"}`,\n ];\n if (error.name !== \"Error\") lines.push(`Type: ${error.name}`);\n if (error.cause !== undefined) lines.push(`Cause: ${String(error.cause)}`);\n if (typeof window !== \"undefined\")\n lines.push(`Page: ${window.location.href}`);\n if (typeof navigator !== \"undefined\" && navigator.userAgent) {\n lines.push(`User agent: ${navigator.userAgent}`);\n }\n lines.push(`Time: ${new Date().toISOString()}`);\n if (error.stack) lines.push(\"\", \"Stack trace:\", error.stack);\n if (componentStack?.trim()) {\n lines.push(\"\", \"React component stack:\", componentStack.trim());\n }\n return lines.join(\"\\n\");\n}\n"],"names":["Component","jsx","useState","useMemo","jsxs","Icon","UiWarningTriangle","Button","UiCheck","UiCopy","cn","ErrorDetails","normalizeErrorDiagnostics"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ErrorWrapper.cjs","sources":["../../src/components/ErrorWrapper.tsx"],"sourcesContent":["import {\n Component,\n useMemo,\n useState,\n type ErrorInfo,\n type ReactNode,\n} from \"react\";\nimport { ErrorDetails } from \"../data/diagnostics/ErrorDetails\";\nimport {\n normalizeErrorDiagnostics,\n type ErrorDiagnostics,\n} from \"../data/diagnostics/error-diagnostics\";\nimport { Icon } from \"../data/Icon\";\nimport { UiCheck, UiCopy, UiWarningTriangle } from \"../icons\";\nimport { cn } from \"../lib/utils\";\nimport { Button } from \"./button\";\n\nexport type ErrorWrapperProps = {\n children: ReactNode;\n onError?: (error: Error, errorInfo: ErrorInfo) => void;\n};\n\ntype ErrorWrapperState = {\n error: Error | null;\n componentStack: string | null;\n};\n\nexport class ErrorWrapper extends Component<\n ErrorWrapperProps,\n ErrorWrapperState\n> {\n override state: ErrorWrapperState = {\n error: null,\n componentStack: null,\n };\n\n static getDerivedStateFromError(error: Error) {\n return { error };\n }\n\n override componentDidCatch(error: Error, errorInfo: ErrorInfo) {\n this.setState({ componentStack: errorInfo.componentStack ?? null });\n this.props.onError?.(error, errorInfo);\n }\n\n override render() {\n if (this.state.error) {\n return (\n <ErrorFallback\n error={this.state.error}\n componentStack={this.state.componentStack}\n />\n );\n }\n return this.props.children;\n }\n}\n\ntype CopyState = \"idle\" | \"copied\" | \"failed\";\n\nfunction copyStatusMessage(copyState: CopyState): string {\n if (copyState === \"copied\") return \"Error details copied to clipboard.\";\n if (copyState === \"failed\") {\n return \"Clipboard access failed. Expand the error details to copy individual values.\";\n }\n return \"\";\n}\n\nfunction ErrorFallback({\n error,\n componentStack,\n}: {\n error: Error;\n componentStack: string | null;\n}) {\n const [copyState, setCopyState] = useState<CopyState>(\"idle\");\n const diagnostics = useMemo(\n () => errorDiagnostics(error, componentStack),\n [componentStack, error],\n );\n\n const copyDetails = async () => {\n if (!navigator.clipboard?.writeText) {\n setCopyState(\"failed\");\n return;\n }\n try {\n await navigator.clipboard.writeText(errorReport(error, componentStack));\n setCopyState(\"copied\");\n } catch {\n setCopyState(\"failed\");\n }\n };\n\n return (\n <main\n data-slot=\"error-wrapper\"\n role=\"alert\"\n aria-labelledby=\"error-wrapper-title\"\n className=\"flex min-h-dvh w-full items-center justify-center bg-background p-density-6 text-foreground\"\n >\n <div className=\"w-full max-w-3xl\">\n <div className=\"mb-density-4 flex items-start gap-density-3\">\n <span className=\"grid size-12 shrink-0 place-items-center rounded-full bg-destructive/10 text-destructive\">\n <Icon icon={UiWarningTriangle} className=\"size-6\" />\n </span>\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-xs font-semibold uppercase tracking-wide text-destructive\">\n Unexpected application error\n </p>\n <h1\n id=\"error-wrapper-title\"\n className=\"mt-density-1 text-2xl font-semibold tracking-tight\"\n >\n Something went wrong\n </h1>\n <p className=\"mt-density-2 break-words text-sm text-muted-foreground\">\n {diagnostics.message}\n </p>\n </div>\n </div>\n\n <div className=\"mb-density-3 flex items-center gap-density-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => void copyDetails()}\n >\n <Icon icon={copyState === \"copied\" ? UiCheck : UiCopy} />\n {/* Distinct from ErrorDetails' own \"Copy error details\" control\n below: this copies the page-level report (URL, user agent,\n React component stack), and two identically named buttons in\n one view are ambiguous to assistive tech. */}\n {copyState === \"copied\" ? \"Copied\" : \"Copy error report\"}\n </Button>\n <span\n aria-live=\"polite\"\n className={cn(\n \"text-xs\",\n copyState === \"failed\"\n ? \"text-destructive\"\n : \"text-muted-foreground\",\n )}\n >\n {copyStatusMessage(copyState)}\n </span>\n </div>\n\n <ErrorDetails diagnostics={diagnostics} />\n </div>\n </main>\n );\n}\n\nfunction errorDiagnostics(\n error: Error,\n componentStack: string | null,\n): ErrorDiagnostics {\n const diagnostics = normalizeErrorDiagnostics(\n error,\n \"An unexpected error was thrown without a message.\",\n );\n if (!diagnostics) {\n throw new Error(\"ErrorWrapper could not normalize the captured error\");\n }\n\n const cause =\n error.cause === undefined\n ? []\n : [[\"cause\", String(error.cause)] as [string, string]];\n const reactStack = componentStack?.trim();\n return {\n ...diagnostics,\n context: [...diagnostics.context, ...cause],\n ...(reactStack\n ? {\n stacktrace: [\n diagnostics.stacktrace,\n \"React component stack:\",\n reactStack,\n ]\n .filter(Boolean)\n .join(\"\\n\\n\"),\n }\n : {}),\n };\n}\n\nfunction errorReport(error: Error, componentStack: string | null) {\n const lines = [\n `Error: ${error.message || \"An unexpected error was thrown without a message.\"}`,\n ];\n if (error.name !== \"Error\") lines.push(`Type: ${error.name}`);\n if (error.cause !== undefined) lines.push(`Cause: ${String(error.cause)}`);\n if (typeof window !== \"undefined\") {\n // Origin and path only: an error report is pasted into issues and chats,\n // and a query string or fragment routinely carries a session token, a\n // signed URL or a search term the reporter did not mean to publish.\n lines.push(`Page: ${window.location.origin}${window.location.pathname}`);\n }\n if (typeof navigator !== \"undefined\" && navigator.userAgent) {\n lines.push(`User agent: ${navigator.userAgent}`);\n }\n lines.push(`Time: ${new Date().toISOString()}`);\n if (error.stack) lines.push(\"\", \"Stack trace:\", error.stack);\n if (componentStack?.trim()) {\n lines.push(\"\", \"React component stack:\", componentStack.trim());\n }\n return lines.join(\"\\n\");\n}\n"],"names":["Component","jsx","useState","useMemo","jsxs","Icon","UiWarningTriangle","Button","UiCheck","UiCopy","cn","ErrorDetails","normalizeErrorDiagnostics"],"mappings":"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"}
|
|
@@ -150,8 +150,9 @@ function errorReport(error, componentStack) {
|
|
|
150
150
|
];
|
|
151
151
|
if (error.name !== "Error") lines.push(`Type: ${error.name}`);
|
|
152
152
|
if (error.cause !== void 0) lines.push(`Cause: ${String(error.cause)}`);
|
|
153
|
-
if (typeof window !== "undefined")
|
|
154
|
-
lines.push(`Page: ${window.location.
|
|
153
|
+
if (typeof window !== "undefined") {
|
|
154
|
+
lines.push(`Page: ${window.location.origin}${window.location.pathname}`);
|
|
155
|
+
}
|
|
155
156
|
if (typeof navigator !== "undefined" && navigator.userAgent) {
|
|
156
157
|
lines.push(`User agent: ${navigator.userAgent}`);
|
|
157
158
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ErrorWrapper.js","sources":["../../src/components/ErrorWrapper.tsx"],"sourcesContent":["import {\n Component,\n useMemo,\n useState,\n type ErrorInfo,\n type ReactNode,\n} from \"react\";\nimport { ErrorDetails } from \"../data/diagnostics/ErrorDetails\";\nimport {\n normalizeErrorDiagnostics,\n type ErrorDiagnostics,\n} from \"../data/diagnostics/error-diagnostics\";\nimport { Icon } from \"../data/Icon\";\nimport { UiCheck, UiCopy, UiWarningTriangle } from \"../icons\";\nimport { cn } from \"../lib/utils\";\nimport { Button } from \"./button\";\n\nexport type ErrorWrapperProps = {\n children: ReactNode;\n onError?: (error: Error, errorInfo: ErrorInfo) => void;\n};\n\ntype ErrorWrapperState = {\n error: Error | null;\n componentStack: string | null;\n};\n\nexport class ErrorWrapper extends Component<\n ErrorWrapperProps,\n ErrorWrapperState\n> {\n override state: ErrorWrapperState = {\n error: null,\n componentStack: null,\n };\n\n static getDerivedStateFromError(error: Error) {\n return { error };\n }\n\n override componentDidCatch(error: Error, errorInfo: ErrorInfo) {\n this.setState({ componentStack: errorInfo.componentStack ?? null });\n this.props.onError?.(error, errorInfo);\n }\n\n override render() {\n if (this.state.error) {\n return (\n <ErrorFallback\n error={this.state.error}\n componentStack={this.state.componentStack}\n />\n );\n }\n return this.props.children;\n }\n}\n\ntype CopyState = \"idle\" | \"copied\" | \"failed\";\n\nfunction copyStatusMessage(copyState: CopyState): string {\n if (copyState === \"copied\") return \"Error details copied to clipboard.\";\n if (copyState === \"failed\") {\n return \"Clipboard access failed. Expand the error details to copy individual values.\";\n }\n return \"\";\n}\n\nfunction ErrorFallback({\n error,\n componentStack,\n}: {\n error: Error;\n componentStack: string | null;\n}) {\n const [copyState, setCopyState] = useState<CopyState>(\"idle\");\n const diagnostics = useMemo(\n () => errorDiagnostics(error, componentStack),\n [componentStack, error],\n );\n\n const copyDetails = async () => {\n if (!navigator.clipboard?.writeText) {\n setCopyState(\"failed\");\n return;\n }\n try {\n await navigator.clipboard.writeText(errorReport(error, componentStack));\n setCopyState(\"copied\");\n } catch {\n setCopyState(\"failed\");\n }\n };\n\n return (\n <main\n data-slot=\"error-wrapper\"\n role=\"alert\"\n aria-labelledby=\"error-wrapper-title\"\n className=\"flex min-h-dvh w-full items-center justify-center bg-background p-density-6 text-foreground\"\n >\n <div className=\"w-full max-w-3xl\">\n <div className=\"mb-density-4 flex items-start gap-density-3\">\n <span className=\"grid size-12 shrink-0 place-items-center rounded-full bg-destructive/10 text-destructive\">\n <Icon icon={UiWarningTriangle} className=\"size-6\" />\n </span>\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-xs font-semibold uppercase tracking-wide text-destructive\">\n Unexpected application error\n </p>\n <h1\n id=\"error-wrapper-title\"\n className=\"mt-density-1 text-2xl font-semibold tracking-tight\"\n >\n Something went wrong\n </h1>\n <p className=\"mt-density-2 break-words text-sm text-muted-foreground\">\n {diagnostics.message}\n </p>\n </div>\n </div>\n\n <div className=\"mb-density-3 flex items-center gap-density-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => void copyDetails()}\n >\n <Icon icon={copyState === \"copied\" ? UiCheck : UiCopy} />\n {/* Distinct from ErrorDetails' own \"Copy error details\" control\n below: this copies the page-level report (URL, user agent,\n React component stack), and two identically named buttons in\n one view are ambiguous to assistive tech. */}\n {copyState === \"copied\" ? \"Copied\" : \"Copy error report\"}\n </Button>\n <span\n aria-live=\"polite\"\n className={cn(\n \"text-xs\",\n copyState === \"failed\"\n ? \"text-destructive\"\n : \"text-muted-foreground\",\n )}\n >\n {copyStatusMessage(copyState)}\n </span>\n </div>\n\n <ErrorDetails diagnostics={diagnostics} />\n </div>\n </main>\n );\n}\n\nfunction errorDiagnostics(\n error: Error,\n componentStack: string | null,\n): ErrorDiagnostics {\n const diagnostics = normalizeErrorDiagnostics(\n error,\n \"An unexpected error was thrown without a message.\",\n );\n if (!diagnostics) {\n throw new Error(\"ErrorWrapper could not normalize the captured error\");\n }\n\n const cause =\n error.cause === undefined\n ? []\n : [[\"cause\", String(error.cause)] as [string, string]];\n const reactStack = componentStack?.trim();\n return {\n ...diagnostics,\n context: [...diagnostics.context, ...cause],\n ...(reactStack\n ? {\n stacktrace: [\n diagnostics.stacktrace,\n \"React component stack:\",\n reactStack,\n ]\n .filter(Boolean)\n .join(\"\\n\\n\"),\n }\n : {}),\n };\n}\n\nfunction errorReport(error: Error, componentStack: string | null) {\n const lines = [\n `Error: ${error.message || \"An unexpected error was thrown without a message.\"}`,\n ];\n if (error.name !== \"Error\") lines.push(`Type: ${error.name}`);\n if (error.cause !== undefined) lines.push(`Cause: ${String(error.cause)}`);\n if (typeof window !== \"undefined\")\n lines.push(`Page: ${window.location.
|
|
1
|
+
{"version":3,"file":"ErrorWrapper.js","sources":["../../src/components/ErrorWrapper.tsx"],"sourcesContent":["import {\n Component,\n useMemo,\n useState,\n type ErrorInfo,\n type ReactNode,\n} from \"react\";\nimport { ErrorDetails } from \"../data/diagnostics/ErrorDetails\";\nimport {\n normalizeErrorDiagnostics,\n type ErrorDiagnostics,\n} from \"../data/diagnostics/error-diagnostics\";\nimport { Icon } from \"../data/Icon\";\nimport { UiCheck, UiCopy, UiWarningTriangle } from \"../icons\";\nimport { cn } from \"../lib/utils\";\nimport { Button } from \"./button\";\n\nexport type ErrorWrapperProps = {\n children: ReactNode;\n onError?: (error: Error, errorInfo: ErrorInfo) => void;\n};\n\ntype ErrorWrapperState = {\n error: Error | null;\n componentStack: string | null;\n};\n\nexport class ErrorWrapper extends Component<\n ErrorWrapperProps,\n ErrorWrapperState\n> {\n override state: ErrorWrapperState = {\n error: null,\n componentStack: null,\n };\n\n static getDerivedStateFromError(error: Error) {\n return { error };\n }\n\n override componentDidCatch(error: Error, errorInfo: ErrorInfo) {\n this.setState({ componentStack: errorInfo.componentStack ?? null });\n this.props.onError?.(error, errorInfo);\n }\n\n override render() {\n if (this.state.error) {\n return (\n <ErrorFallback\n error={this.state.error}\n componentStack={this.state.componentStack}\n />\n );\n }\n return this.props.children;\n }\n}\n\ntype CopyState = \"idle\" | \"copied\" | \"failed\";\n\nfunction copyStatusMessage(copyState: CopyState): string {\n if (copyState === \"copied\") return \"Error details copied to clipboard.\";\n if (copyState === \"failed\") {\n return \"Clipboard access failed. Expand the error details to copy individual values.\";\n }\n return \"\";\n}\n\nfunction ErrorFallback({\n error,\n componentStack,\n}: {\n error: Error;\n componentStack: string | null;\n}) {\n const [copyState, setCopyState] = useState<CopyState>(\"idle\");\n const diagnostics = useMemo(\n () => errorDiagnostics(error, componentStack),\n [componentStack, error],\n );\n\n const copyDetails = async () => {\n if (!navigator.clipboard?.writeText) {\n setCopyState(\"failed\");\n return;\n }\n try {\n await navigator.clipboard.writeText(errorReport(error, componentStack));\n setCopyState(\"copied\");\n } catch {\n setCopyState(\"failed\");\n }\n };\n\n return (\n <main\n data-slot=\"error-wrapper\"\n role=\"alert\"\n aria-labelledby=\"error-wrapper-title\"\n className=\"flex min-h-dvh w-full items-center justify-center bg-background p-density-6 text-foreground\"\n >\n <div className=\"w-full max-w-3xl\">\n <div className=\"mb-density-4 flex items-start gap-density-3\">\n <span className=\"grid size-12 shrink-0 place-items-center rounded-full bg-destructive/10 text-destructive\">\n <Icon icon={UiWarningTriangle} className=\"size-6\" />\n </span>\n <div className=\"min-w-0 flex-1\">\n <p className=\"text-xs font-semibold uppercase tracking-wide text-destructive\">\n Unexpected application error\n </p>\n <h1\n id=\"error-wrapper-title\"\n className=\"mt-density-1 text-2xl font-semibold tracking-tight\"\n >\n Something went wrong\n </h1>\n <p className=\"mt-density-2 break-words text-sm text-muted-foreground\">\n {diagnostics.message}\n </p>\n </div>\n </div>\n\n <div className=\"mb-density-3 flex items-center gap-density-2\">\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => void copyDetails()}\n >\n <Icon icon={copyState === \"copied\" ? UiCheck : UiCopy} />\n {/* Distinct from ErrorDetails' own \"Copy error details\" control\n below: this copies the page-level report (URL, user agent,\n React component stack), and two identically named buttons in\n one view are ambiguous to assistive tech. */}\n {copyState === \"copied\" ? \"Copied\" : \"Copy error report\"}\n </Button>\n <span\n aria-live=\"polite\"\n className={cn(\n \"text-xs\",\n copyState === \"failed\"\n ? \"text-destructive\"\n : \"text-muted-foreground\",\n )}\n >\n {copyStatusMessage(copyState)}\n </span>\n </div>\n\n <ErrorDetails diagnostics={diagnostics} />\n </div>\n </main>\n );\n}\n\nfunction errorDiagnostics(\n error: Error,\n componentStack: string | null,\n): ErrorDiagnostics {\n const diagnostics = normalizeErrorDiagnostics(\n error,\n \"An unexpected error was thrown without a message.\",\n );\n if (!diagnostics) {\n throw new Error(\"ErrorWrapper could not normalize the captured error\");\n }\n\n const cause =\n error.cause === undefined\n ? []\n : [[\"cause\", String(error.cause)] as [string, string]];\n const reactStack = componentStack?.trim();\n return {\n ...diagnostics,\n context: [...diagnostics.context, ...cause],\n ...(reactStack\n ? {\n stacktrace: [\n diagnostics.stacktrace,\n \"React component stack:\",\n reactStack,\n ]\n .filter(Boolean)\n .join(\"\\n\\n\"),\n }\n : {}),\n };\n}\n\nfunction errorReport(error: Error, componentStack: string | null) {\n const lines = [\n `Error: ${error.message || \"An unexpected error was thrown without a message.\"}`,\n ];\n if (error.name !== \"Error\") lines.push(`Type: ${error.name}`);\n if (error.cause !== undefined) lines.push(`Cause: ${String(error.cause)}`);\n if (typeof window !== \"undefined\") {\n // Origin and path only: an error report is pasted into issues and chats,\n // and a query string or fragment routinely carries a session token, a\n // signed URL or a search term the reporter did not mean to publish.\n lines.push(`Page: ${window.location.origin}${window.location.pathname}`);\n }\n if (typeof navigator !== \"undefined\" && navigator.userAgent) {\n lines.push(`User agent: ${navigator.userAgent}`);\n }\n lines.push(`Time: ${new Date().toISOString()}`);\n if (error.stack) lines.push(\"\", \"Stack trace:\", error.stack);\n if (componentStack?.trim()) {\n lines.push(\"\", \"React component stack:\", componentStack.trim());\n }\n return lines.join(\"\\n\");\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;AA2BO,MAAM,qBAAqB,UAGhC;AAAA,EAHK;AAAA;AAII,iCAA2B;AAAA,MAClC,OAAO;AAAA,MACP,gBAAgB;AAAA,IAAA;AAAA;AAAA,EAGlB,OAAO,yBAAyB,OAAc;AAC5C,WAAO,EAAE,MAAA;AAAA,EACX;AAAA,EAES,kBAAkB,OAAc,WAAsB;;AAC7D,SAAK,SAAS,EAAE,gBAAgB,UAAU,kBAAkB,MAAM;AAClE,qBAAK,OAAM,YAAX,4BAAqB,OAAO;AAAA,EAC9B;AAAA,EAES,SAAS;AAChB,QAAI,KAAK,MAAM,OAAO;AACpB,aACE;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,OAAO,KAAK,MAAM;AAAA,UAClB,gBAAgB,KAAK,MAAM;AAAA,QAAA;AAAA,MAAA;AAAA,IAGjC;AACA,WAAO,KAAK,MAAM;AAAA,EACpB;AACF;AAIA,SAAS,kBAAkB,WAA8B;AACvD,MAAI,cAAc,SAAU,QAAO;AACnC,MAAI,cAAc,UAAU;AAC1B,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,SAAS,cAAc;AAAA,EACrB;AAAA,EACA;AACF,GAGG;AACD,QAAM,CAAC,WAAW,YAAY,IAAI,SAAoB,MAAM;AAC5D,QAAM,cAAc;AAAA,IAClB,MAAM,iBAAiB,OAAO,cAAc;AAAA,IAC5C,CAAC,gBAAgB,KAAK;AAAA,EAAA;AAGxB,QAAM,cAAc,YAAY;;AAC9B,QAAI,GAAC,eAAU,cAAV,mBAAqB,YAAW;AACnC,mBAAa,QAAQ;AACrB;AAAA,IACF;AACA,QAAI;AACF,YAAM,UAAU,UAAU,UAAU,YAAY,OAAO,cAAc,CAAC;AACtE,mBAAa,QAAQ;AAAA,IACvB,QAAQ;AACN,mBAAa,QAAQ;AAAA,IACvB;AAAA,EACF;AAEA,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,aAAU;AAAA,MACV,MAAK;AAAA,MACL,mBAAgB;AAAA,MAChB,WAAU;AAAA,MAEV,UAAA,qBAAC,OAAA,EAAI,WAAU,oBACb,UAAA;AAAA,QAAA,qBAAC,OAAA,EAAI,WAAU,+CACb,UAAA;AAAA,UAAA,oBAAC,QAAA,EAAK,WAAU,4FACd,UAAA,oBAAC,QAAK,MAAM,mBAAmB,WAAU,SAAA,CAAS,EAAA,CACpD;AAAA,UACA,qBAAC,OAAA,EAAI,WAAU,kBACb,UAAA;AAAA,YAAA,oBAAC,KAAA,EAAE,WAAU,kEAAiE,UAAA,gCAE9E;AAAA,YACA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,IAAG;AAAA,gBACH,WAAU;AAAA,gBACX,UAAA;AAAA,cAAA;AAAA,YAAA;AAAA,YAGD,oBAAC,KAAA,EAAE,WAAU,0DACV,sBAAY,QAAA,CACf;AAAA,UAAA,EAAA,CACF;AAAA,QAAA,GACF;AAAA,QAEA,qBAAC,OAAA,EAAI,WAAU,gDACb,UAAA;AAAA,UAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAQ;AAAA,cACR,SAAS,MAAM,KAAK,YAAA;AAAA,cAEpB,UAAA;AAAA,gBAAA,oBAAC,MAAA,EAAK,MAAM,cAAc,WAAW,UAAU,QAAQ;AAAA,gBAKtD,cAAc,WAAW,WAAW;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAEvC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,aAAU;AAAA,cACV,WAAW;AAAA,gBACT;AAAA,gBACA,cAAc,WACV,qBACA;AAAA,cAAA;AAAA,cAGL,4BAAkB,SAAS;AAAA,YAAA;AAAA,UAAA;AAAA,QAC9B,GACF;AAAA,QAEA,oBAAC,gBAAa,YAAA,CAA0B;AAAA,MAAA,EAAA,CAC1C;AAAA,IAAA;AAAA,EAAA;AAGN;AAEA,SAAS,iBACP,OACA,gBACkB;AAClB,QAAM,cAAc;AAAA,IAClB;AAAA,IACA;AAAA,EAAA;AAEF,MAAI,CAAC,aAAa;AAChB,UAAM,IAAI,MAAM,qDAAqD;AAAA,EACvE;AAEA,QAAM,QACJ,MAAM,UAAU,SACZ,CAAA,IACA,CAAC,CAAC,SAAS,OAAO,MAAM,KAAK,CAAC,CAAqB;AACzD,QAAM,aAAa,iDAAgB;AACnC,SAAO;AAAA,IACL,GAAG;AAAA,IACH,SAAS,CAAC,GAAG,YAAY,SAAS,GAAG,KAAK;AAAA,IAC1C,GAAI,aACA;AAAA,MACE,YAAY;AAAA,QACV,YAAY;AAAA,QACZ;AAAA,QACA;AAAA,MAAA,EAEC,OAAO,OAAO,EACd,KAAK,MAAM;AAAA,IAAA,IAEhB,CAAA;AAAA,EAAC;AAET;AAEA,SAAS,YAAY,OAAc,gBAA+B;AAChE,QAAM,QAAQ;AAAA,IACZ,UAAU,MAAM,WAAW,mDAAmD;AAAA,EAAA;AAEhF,MAAI,MAAM,SAAS,QAAS,OAAM,KAAK,SAAS,MAAM,IAAI,EAAE;AAC5D,MAAI,MAAM,UAAU,OAAW,OAAM,KAAK,UAAU,OAAO,MAAM,KAAK,CAAC,EAAE;AACzE,MAAI,OAAO,WAAW,aAAa;AAIjC,UAAM,KAAK,SAAS,OAAO,SAAS,MAAM,GAAG,OAAO,SAAS,QAAQ,EAAE;AAAA,EACzE;AACA,MAAI,OAAO,cAAc,eAAe,UAAU,WAAW;AAC3D,UAAM,KAAK,eAAe,UAAU,SAAS,EAAE;AAAA,EACjD;AACA,QAAM,KAAK,UAAS,oBAAI,QAAO,YAAA,CAAa,EAAE;AAC9C,MAAI,MAAM,MAAO,OAAM,KAAK,IAAI,gBAAgB,MAAM,KAAK;AAC3D,MAAI,iDAAgB,QAAQ;AAC1B,UAAM,KAAK,IAAI,0BAA0B,eAAe,MAAM;AAAA,EAChE;AACA,SAAO,MAAM,KAAK,IAAI;AACxB;"}
|