@flanksource/clicky-ui 0.3.31 → 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.
Files changed (81) hide show
  1. package/dist/comments/CommentCard.cjs +79 -44
  2. package/dist/comments/CommentCard.cjs.map +1 -1
  3. package/dist/comments/CommentCard.d.ts +2 -0
  4. package/dist/comments/CommentCard.d.ts.map +1 -1
  5. package/dist/comments/CommentCard.js +81 -46
  6. package/dist/comments/CommentCard.js.map +1 -1
  7. package/dist/comments/CommentCardParts.cjs +20 -0
  8. package/dist/comments/CommentCardParts.cjs.map +1 -1
  9. package/dist/comments/CommentCardParts.d.ts +4 -0
  10. package/dist/comments/CommentCardParts.d.ts.map +1 -1
  11. package/dist/comments/CommentCardParts.js +22 -2
  12. package/dist/comments/CommentCardParts.js.map +1 -1
  13. package/dist/comments/CommentProvider.cjs +3 -0
  14. package/dist/comments/CommentProvider.cjs.map +1 -1
  15. package/dist/comments/CommentProvider.d.ts +1 -1
  16. package/dist/comments/CommentProvider.d.ts.map +1 -1
  17. package/dist/comments/CommentProvider.js +3 -0
  18. package/dist/comments/CommentProvider.js.map +1 -1
  19. package/dist/comments/CommentSidePanel.cjs +43 -17
  20. package/dist/comments/CommentSidePanel.cjs.map +1 -1
  21. package/dist/comments/CommentSidePanel.d.ts.map +1 -1
  22. package/dist/comments/CommentSidePanel.js +44 -18
  23. package/dist/comments/CommentSidePanel.js.map +1 -1
  24. package/dist/comments/CommentThreadList.cjs +2 -0
  25. package/dist/comments/CommentThreadList.cjs.map +1 -1
  26. package/dist/comments/CommentThreadList.d.ts +3 -2
  27. package/dist/comments/CommentThreadList.d.ts.map +1 -1
  28. package/dist/comments/CommentThreadList.js +2 -0
  29. package/dist/comments/CommentThreadList.js.map +1 -1
  30. package/dist/comments/comment-types.cjs +16 -4
  31. package/dist/comments/comment-types.cjs.map +1 -1
  32. package/dist/comments/comment-types.d.ts +11 -1
  33. package/dist/comments/comment-types.d.ts.map +1 -1
  34. package/dist/comments/comment-types.js +16 -4
  35. package/dist/comments/comment-types.js.map +1 -1
  36. package/dist/comments/comment-utils.cjs +31 -1
  37. package/dist/comments/comment-utils.cjs.map +1 -1
  38. package/dist/comments/comment-utils.d.ts +9 -2
  39. package/dist/comments/comment-utils.d.ts.map +1 -1
  40. package/dist/comments/comment-utils.js +31 -1
  41. package/dist/comments/comment-utils.js.map +1 -1
  42. package/dist/comments.cjs +3 -0
  43. package/dist/comments.cjs.map +1 -1
  44. package/dist/comments.js +4 -1
  45. package/dist/components/EndpointSelector.cjs +6 -6
  46. package/dist/components/EndpointSelector.cjs.map +1 -1
  47. package/dist/components/EndpointSelector.d.ts.map +1 -1
  48. package/dist/components/EndpointSelector.js +6 -6
  49. package/dist/components/EndpointSelector.js.map +1 -1
  50. package/dist/components/ErrorWrapper.cjs +3 -2
  51. package/dist/components/ErrorWrapper.cjs.map +1 -1
  52. package/dist/components/ErrorWrapper.js +3 -2
  53. package/dist/components/ErrorWrapper.js.map +1 -1
  54. package/dist/components/RangeSlider.cjs +108 -45
  55. package/dist/components/RangeSlider.cjs.map +1 -1
  56. package/dist/components/RangeSlider.d.ts +3 -1
  57. package/dist/components/RangeSlider.d.ts.map +1 -1
  58. package/dist/components/RangeSlider.js +108 -45
  59. package/dist/components/RangeSlider.js.map +1 -1
  60. package/dist/components/SecretKeySelector.cjs +4 -4
  61. package/dist/components/SecretKeySelector.cjs.map +1 -1
  62. package/dist/components/SecretKeySelector.js +4 -4
  63. package/dist/components/SecretKeySelector.js.map +1 -1
  64. package/dist/data/test-runner/status.cjs +1 -1
  65. package/dist/data/test-runner/status.cjs.map +1 -1
  66. package/dist/data/test-runner/status.js +1 -1
  67. package/dist/data/test-runner/status.js.map +1 -1
  68. package/dist/data/test-runner/types.d.ts +6 -0
  69. package/dist/data/test-runner/types.d.ts.map +1 -1
  70. package/dist/data/verification/verifyReportTests.cjs +1 -0
  71. package/dist/data/verification/verifyReportTests.cjs.map +1 -1
  72. package/dist/data/verification/verifyReportTests.d.ts.map +1 -1
  73. package/dist/data/verification/verifyReportTests.js +1 -0
  74. package/dist/data/verification/verifyReportTests.js.map +1 -1
  75. package/dist/data/version-info.cjs +3 -3
  76. package/dist/data/version-info.js +3 -3
  77. package/dist/index.cjs +3 -0
  78. package/dist/index.cjs.map +1 -1
  79. package/dist/index.js +4 -1
  80. package/dist/styles.css +1 -1
  81. package/package.json +1 -1
@@ -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;AAgFlC,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"}
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 basis-56 shrink grow";
29
- const SCHEME_FIELD = "max-w-full min-w-0 basis-32 shrink grow-0";
30
- const PORT_FIELD = "max-w-full min-w-0 basis-36 shrink grow-0";
31
- const PATH_FIELD = "max-w-full min-w-0 basis-56 shrink grow";
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: "flex w-full max-w-full min-w-0 flex-nowrap items-end gap-density-2",
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.href}`);
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.href}`);
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.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":[],"mappings":"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"}
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;"}
@@ -11,65 +11,125 @@ function RangeSlider({
11
11
  step = 1,
12
12
  ariaLabelMin = "Minimum value",
13
13
  ariaLabelMax = "Maximum value",
14
+ editable = false,
14
15
  className,
15
16
  trackClassName,
16
17
  rangeClassName,
17
18
  thumbClassName: thumbOverrideClassName
18
19
  }) {
19
20
  const [lower, upper] = normalizeRangeValue(value, min, max);
20
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: utils.cn("relative h-6", className), children: [
21
- /* @__PURE__ */ jsxRuntime.jsx(
22
- "div",
23
- {
24
- className: utils.cn(
25
- "absolute left-0 right-0 top-1/2 h-1 -translate-y-1/2 rounded-full bg-border",
26
- trackClassName
27
- )
28
- }
29
- ),
30
- /* @__PURE__ */ jsxRuntime.jsx(
31
- "div",
32
- {
33
- className: utils.cn(
34
- "absolute top-1/2 h-1 -translate-y-1/2 rounded-full bg-primary/70",
35
- rangeClassName
36
- ),
37
- style: {
38
- left: `${valueToPercent(lower, min, max)}%`,
39
- right: `${100 - valueToPercent(upper, min, max)}%`
21
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: utils.cn(editable && "space-y-2", className), children: [
22
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative h-6", children: [
23
+ /* @__PURE__ */ jsxRuntime.jsx(
24
+ "div",
25
+ {
26
+ className: utils.cn(
27
+ "absolute left-0 right-0 top-1/2 h-1 -translate-y-1/2 rounded-full bg-border",
28
+ trackClassName
29
+ )
40
30
  }
41
- }
42
- ),
43
- /* @__PURE__ */ jsxRuntime.jsx(
44
- "input",
45
- {
46
- type: "range",
47
- "aria-label": ariaLabelMin,
48
- min,
49
- max,
50
- step,
51
- value: lower,
52
- className: utils.cn(baseSliderClassName, thumbClassName, thumbOverrideClassName),
53
- style: { zIndex: lower >= max ? 30 : 20 },
54
- onChange: (event) => {
55
- const nextLower = clampNumber(Number(event.target.value), min, max);
56
- onChange([Math.min(nextLower, upper), upper]);
31
+ ),
32
+ /* @__PURE__ */ jsxRuntime.jsx(
33
+ "div",
34
+ {
35
+ className: utils.cn(
36
+ "absolute top-1/2 h-1 -translate-y-1/2 rounded-full bg-primary/70",
37
+ rangeClassName
38
+ ),
39
+ style: {
40
+ left: `${valueToPercent(lower, min, max)}%`,
41
+ right: `${100 - valueToPercent(upper, min, max)}%`
42
+ }
57
43
  }
58
- }
59
- ),
44
+ ),
45
+ /* @__PURE__ */ jsxRuntime.jsx(
46
+ "input",
47
+ {
48
+ type: "range",
49
+ "aria-label": ariaLabelMin,
50
+ min,
51
+ max,
52
+ step,
53
+ value: lower,
54
+ className: utils.cn(baseSliderClassName, thumbClassName, thumbOverrideClassName),
55
+ style: { zIndex: lower >= max ? 30 : 20 },
56
+ onChange: (event) => {
57
+ const nextLower = clampNumber(Number(event.target.value), min, max);
58
+ onChange([Math.min(nextLower, upper), upper]);
59
+ }
60
+ }
61
+ ),
62
+ /* @__PURE__ */ jsxRuntime.jsx(
63
+ "input",
64
+ {
65
+ type: "range",
66
+ "aria-label": ariaLabelMax,
67
+ min,
68
+ max,
69
+ step,
70
+ value: upper,
71
+ className: utils.cn(baseSliderClassName, thumbClassName, thumbOverrideClassName),
72
+ onChange: (event) => {
73
+ const nextUpper = clampNumber(Number(event.target.value), min, max);
74
+ onChange([lower, Math.max(nextUpper, lower)]);
75
+ }
76
+ }
77
+ )
78
+ ] }),
79
+ editable ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
80
+ /* @__PURE__ */ jsxRuntime.jsx(
81
+ EditableBound,
82
+ {
83
+ label: "Min",
84
+ ariaLabel: `Edit ${lowercaseFirst(ariaLabelMin)}`,
85
+ min,
86
+ max: upper,
87
+ step,
88
+ value: lower,
89
+ onChange: (next) => onChange([next, upper])
90
+ }
91
+ ),
92
+ /* @__PURE__ */ jsxRuntime.jsx(
93
+ EditableBound,
94
+ {
95
+ label: "Max",
96
+ ariaLabel: `Edit ${lowercaseFirst(ariaLabelMax)}`,
97
+ min: lower,
98
+ max,
99
+ step,
100
+ value: upper,
101
+ onChange: (next) => onChange([lower, next])
102
+ }
103
+ )
104
+ ] }) : null
105
+ ] });
106
+ }
107
+ function EditableBound({
108
+ label,
109
+ ariaLabel,
110
+ min,
111
+ max,
112
+ step,
113
+ value,
114
+ onChange
115
+ }) {
116
+ return /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "grid grid-cols-[auto_minmax(0,1fr)] items-center gap-1.5 text-[11px] text-muted-foreground", children: [
117
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: label }),
60
118
  /* @__PURE__ */ jsxRuntime.jsx(
61
119
  "input",
62
120
  {
63
- type: "range",
64
- "aria-label": ariaLabelMax,
65
- min,
121
+ "aria-label": ariaLabel,
122
+ className: "h-7 min-w-0 rounded-md border border-input bg-background px-2 text-right font-mono text-xs tabular-nums text-foreground outline-none focus-visible:ring-2 focus-visible:ring-ring",
66
123
  max,
124
+ min,
67
125
  step,
68
- value: upper,
69
- className: utils.cn(baseSliderClassName, thumbClassName, thumbOverrideClassName),
126
+ type: "number",
127
+ value,
70
128
  onChange: (event) => {
71
- const nextUpper = clampNumber(Number(event.target.value), min, max);
72
- onChange([lower, Math.max(nextUpper, lower)]);
129
+ if (event.currentTarget.value === "") return;
130
+ const next = Number(event.currentTarget.value);
131
+ if (!Number.isFinite(next)) throw new Error(`${ariaLabel} must be a finite number`);
132
+ onChange(clampNumber(next, min, max));
73
133
  }
74
134
  }
75
135
  )
@@ -88,5 +148,8 @@ function valueToPercent(value, min, max) {
88
148
  if (max <= min) return 0;
89
149
  return (value - min) / (max - min) * 100;
90
150
  }
151
+ function lowercaseFirst(value) {
152
+ return value.charAt(0).toLowerCase() + value.slice(1);
153
+ }
91
154
  exports.RangeSlider = RangeSlider;
92
155
  //# sourceMappingURL=RangeSlider.cjs.map