@flanksource/clicky-ui 0.3.18 → 0.3.19

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 (191) hide show
  1. package/dist/components/ComboboxMenu.cjs +5 -1
  2. package/dist/components/ComboboxMenu.cjs.map +1 -1
  3. package/dist/components/ComboboxMenu.d.ts.map +1 -1
  4. package/dist/components/ComboboxMenu.js +5 -1
  5. package/dist/components/ComboboxMenu.js.map +1 -1
  6. package/dist/components/EndpointSelector.model.cjs +96 -0
  7. package/dist/components/EndpointSelector.model.cjs.map +1 -0
  8. package/dist/components/EndpointSelector.model.d.ts +2 -0
  9. package/dist/components/EndpointSelector.model.d.ts.map +1 -1
  10. package/dist/components/EndpointSelector.model.js +96 -0
  11. package/dist/components/EndpointSelector.model.js.map +1 -0
  12. package/dist/components/FilterBar.cjs +52 -2
  13. package/dist/components/FilterBar.cjs.map +1 -1
  14. package/dist/components/FilterBar.d.ts +20 -2
  15. package/dist/components/FilterBar.d.ts.map +1 -1
  16. package/dist/components/FilterBar.js +52 -2
  17. package/dist/components/FilterBar.js.map +1 -1
  18. package/dist/components/JSONPathField.cjs +87 -66
  19. package/dist/components/JSONPathField.cjs.map +1 -1
  20. package/dist/components/JSONPathField.d.ts +26 -9
  21. package/dist/components/JSONPathField.d.ts.map +1 -1
  22. package/dist/components/JSONPathField.js +88 -67
  23. package/dist/components/JSONPathField.js.map +1 -1
  24. package/dist/components/JSONPathPlayground.cjs +225 -0
  25. package/dist/components/JSONPathPlayground.cjs.map +1 -0
  26. package/dist/components/JSONPathPlayground.d.ts +59 -0
  27. package/dist/components/JSONPathPlayground.d.ts.map +1 -0
  28. package/dist/components/JSONPathPlayground.js +225 -0
  29. package/dist/components/JSONPathPlayground.js.map +1 -0
  30. package/dist/components/OnePasswordSelector.cjs +178 -0
  31. package/dist/components/OnePasswordSelector.cjs.map +1 -0
  32. package/dist/components/OnePasswordSelector.d.ts +8 -0
  33. package/dist/components/OnePasswordSelector.d.ts.map +1 -0
  34. package/dist/components/OnePasswordSelector.js +178 -0
  35. package/dist/components/OnePasswordSelector.js.map +1 -0
  36. package/dist/components/OnePasswordSelector.model.cjs +31 -0
  37. package/dist/components/OnePasswordSelector.model.cjs.map +1 -0
  38. package/dist/components/OnePasswordSelector.model.d.ts +27 -0
  39. package/dist/components/OnePasswordSelector.model.d.ts.map +1 -0
  40. package/dist/components/OnePasswordSelector.model.js +31 -0
  41. package/dist/components/OnePasswordSelector.model.js.map +1 -0
  42. package/dist/components/SecretFormField.cjs +142 -0
  43. package/dist/components/SecretFormField.cjs.map +1 -0
  44. package/dist/components/SecretFormField.d.ts +9 -0
  45. package/dist/components/SecretFormField.d.ts.map +1 -0
  46. package/dist/components/SecretFormField.js +142 -0
  47. package/dist/components/SecretFormField.js.map +1 -0
  48. package/dist/components/SecretKeySelector.cjs +20 -14
  49. package/dist/components/SecretKeySelector.cjs.map +1 -1
  50. package/dist/components/SecretKeySelector.d.ts +4 -1
  51. package/dist/components/SecretKeySelector.d.ts.map +1 -1
  52. package/dist/components/SecretKeySelector.js +20 -14
  53. package/dist/components/SecretKeySelector.js.map +1 -1
  54. package/dist/components/TreePickerField.cjs +55 -29
  55. package/dist/components/TreePickerField.cjs.map +1 -1
  56. package/dist/components/TreePickerField.d.ts +10 -1
  57. package/dist/components/TreePickerField.d.ts.map +1 -1
  58. package/dist/components/TreePickerField.js +56 -30
  59. package/dist/components/TreePickerField.js.map +1 -1
  60. package/dist/components/combobox-types.d.ts +9 -0
  61. package/dist/components/combobox-types.d.ts.map +1 -1
  62. package/dist/components/filter-bar-utils.cjs +7 -0
  63. package/dist/components/filter-bar-utils.cjs.map +1 -1
  64. package/dist/components/filter-bar-utils.d.ts.map +1 -1
  65. package/dist/components/filter-bar-utils.js +7 -0
  66. package/dist/components/filter-bar-utils.js.map +1 -1
  67. package/dist/components/jotai-bindings-core.cjs.map +1 -1
  68. package/dist/components/jotai-bindings-core.d.ts +4 -1
  69. package/dist/components/jotai-bindings-core.d.ts.map +1 -1
  70. package/dist/components/jotai-bindings-core.js.map +1 -1
  71. package/dist/components/json-schema-form-render.cjs +2 -1
  72. package/dist/components/json-schema-form-render.cjs.map +1 -1
  73. package/dist/components/json-schema-form-render.d.ts.map +1 -1
  74. package/dist/components/json-schema-form-render.js +2 -1
  75. package/dist/components/json-schema-form-render.js.map +1 -1
  76. package/dist/components/json-schema-form-types.d.ts +9 -0
  77. package/dist/components/json-schema-form-types.d.ts.map +1 -1
  78. package/dist/components/jsonPathTree.cjs +189 -0
  79. package/dist/components/jsonPathTree.cjs.map +1 -0
  80. package/dist/components/jsonPathTree.d.ts +92 -0
  81. package/dist/components/jsonPathTree.d.ts.map +1 -0
  82. package/dist/components/jsonPathTree.js +189 -0
  83. package/dist/components/jsonPathTree.js.map +1 -0
  84. package/dist/components/secret-form-extension.cjs +30 -0
  85. package/dist/components/secret-form-extension.cjs.map +1 -0
  86. package/dist/components/secret-form-extension.d.ts +23 -0
  87. package/dist/components/secret-form-extension.d.ts.map +1 -0
  88. package/dist/components/secret-form-extension.js +30 -0
  89. package/dist/components/secret-form-extension.js.map +1 -0
  90. package/dist/components.cjs +16 -0
  91. package/dist/components.cjs.map +1 -1
  92. package/dist/components.d.ts +6 -0
  93. package/dist/components.d.ts.map +1 -1
  94. package/dist/components.js +16 -0
  95. package/dist/components.js.map +1 -1
  96. package/dist/data/TaskExecDetails.cjs +40 -0
  97. package/dist/data/TaskExecDetails.cjs.map +1 -0
  98. package/dist/data/TaskExecDetails.d.ts +5 -0
  99. package/dist/data/TaskExecDetails.d.ts.map +1 -0
  100. package/dist/data/TaskExecDetails.js +40 -0
  101. package/dist/data/TaskExecDetails.js.map +1 -0
  102. package/dist/data/TaskProgress.cjs +9 -3
  103. package/dist/data/TaskProgress.cjs.map +1 -1
  104. package/dist/data/TaskProgress.d.ts.map +1 -1
  105. package/dist/data/TaskProgress.js +9 -3
  106. package/dist/data/TaskProgress.js.map +1 -1
  107. package/dist/data/TaskSnapshot.cjs.map +1 -1
  108. package/dist/data/TaskSnapshot.d.ts +12 -1
  109. package/dist/data/TaskSnapshot.d.ts.map +1 -1
  110. package/dist/data/TaskSnapshot.js.map +1 -1
  111. package/dist/data/TreeNode.cjs +3 -0
  112. package/dist/data/TreeNode.cjs.map +1 -1
  113. package/dist/data/TreeNode.d.ts.map +1 -1
  114. package/dist/data/TreeNode.js +3 -0
  115. package/dist/data/TreeNode.js.map +1 -1
  116. package/dist/data/data-table-filter-values.cjs +20 -0
  117. package/dist/data/data-table-filter-values.cjs.map +1 -1
  118. package/dist/data/data-table-filter-values.d.ts +16 -0
  119. package/dist/data/data-table-filter-values.d.ts.map +1 -1
  120. package/dist/data/data-table-filter-values.js +20 -0
  121. package/dist/data/data-table-filter-values.js.map +1 -1
  122. package/dist/data/data-table-server-filters.cjs +23 -29
  123. package/dist/data/data-table-server-filters.cjs.map +1 -1
  124. package/dist/data/data-table-server-filters.d.ts.map +1 -1
  125. package/dist/data/data-table-server-filters.js +21 -27
  126. package/dist/data/data-table-server-filters.js.map +1 -1
  127. package/dist/data/query-browser/QueryBrowser.cjs +129 -157
  128. package/dist/data/query-browser/QueryBrowser.cjs.map +1 -1
  129. package/dist/data/query-browser/QueryBrowser.d.ts +1 -71
  130. package/dist/data/query-browser/QueryBrowser.d.ts.map +1 -1
  131. package/dist/data/query-browser/QueryBrowser.editor.cjs +88 -0
  132. package/dist/data/query-browser/QueryBrowser.editor.cjs.map +1 -0
  133. package/dist/data/query-browser/QueryBrowser.editor.d.ts +12 -0
  134. package/dist/data/query-browser/QueryBrowser.editor.d.ts.map +1 -0
  135. package/dist/data/query-browser/QueryBrowser.editor.js +88 -0
  136. package/dist/data/query-browser/QueryBrowser.editor.js.map +1 -0
  137. package/dist/data/query-browser/QueryBrowser.js +130 -158
  138. package/dist/data/query-browser/QueryBrowser.js.map +1 -1
  139. package/dist/data/query-browser/QueryBrowser.types.cjs +11 -0
  140. package/dist/data/query-browser/QueryBrowser.types.cjs.map +1 -0
  141. package/dist/data/query-browser/QueryBrowser.types.d.ts +92 -0
  142. package/dist/data/query-browser/QueryBrowser.types.d.ts.map +1 -0
  143. package/dist/data/query-browser/QueryBrowser.types.js +11 -0
  144. package/dist/data/query-browser/QueryBrowser.types.js.map +1 -0
  145. package/dist/data/query-browser/QueryBrowserDiagnosticsPanel.cjs +56 -0
  146. package/dist/data/query-browser/QueryBrowserDiagnosticsPanel.cjs.map +1 -0
  147. package/dist/data/query-browser/QueryBrowserDiagnosticsPanel.d.ts +5 -0
  148. package/dist/data/query-browser/QueryBrowserDiagnosticsPanel.d.ts.map +1 -0
  149. package/dist/data/query-browser/QueryBrowserDiagnosticsPanel.js +56 -0
  150. package/dist/data/query-browser/QueryBrowserDiagnosticsPanel.js.map +1 -0
  151. package/dist/data/query-browser/QueryBrowserResults.cjs +80 -0
  152. package/dist/data/query-browser/QueryBrowserResults.cjs.map +1 -0
  153. package/dist/data/query-browser/QueryBrowserResults.d.ts +16 -0
  154. package/dist/data/query-browser/QueryBrowserResults.d.ts.map +1 -0
  155. package/dist/data/query-browser/QueryBrowserResults.js +80 -0
  156. package/dist/data/query-browser/QueryBrowserResults.js.map +1 -0
  157. package/dist/data/query-browser/index.d.ts +2 -1
  158. package/dist/data/query-browser/index.d.ts.map +1 -1
  159. package/dist/data/task-exec-details.cjs +9 -0
  160. package/dist/data/task-exec-details.cjs.map +1 -0
  161. package/dist/data/task-exec-details.d.ts +3 -0
  162. package/dist/data/task-exec-details.d.ts.map +1 -0
  163. package/dist/data/task-exec-details.js +9 -0
  164. package/dist/data/task-exec-details.js.map +1 -0
  165. package/dist/data/version-info.cjs +3 -3
  166. package/dist/data/version-info.js +3 -3
  167. package/dist/data.cjs +2 -0
  168. package/dist/data.cjs.map +1 -1
  169. package/dist/data.d.ts +1 -1
  170. package/dist/data.d.ts.map +1 -1
  171. package/dist/data.js +2 -0
  172. package/dist/data.js.map +1 -1
  173. package/dist/index.cjs +18 -0
  174. package/dist/index.cjs.map +1 -1
  175. package/dist/index.js +18 -0
  176. package/dist/index.js.map +1 -1
  177. package/dist/rpc/FilterForm.cjs +20 -0
  178. package/dist/rpc/FilterForm.cjs.map +1 -1
  179. package/dist/rpc/FilterForm.js +20 -0
  180. package/dist/rpc/FilterForm.js.map +1 -1
  181. package/dist/rpc/formMetadata.cjs +34 -0
  182. package/dist/rpc/formMetadata.cjs.map +1 -1
  183. package/dist/rpc/formMetadata.d.ts.map +1 -1
  184. package/dist/rpc/formMetadata.js +35 -1
  185. package/dist/rpc/formMetadata.js.map +1 -1
  186. package/dist/rpc/types.cjs.map +1 -1
  187. package/dist/rpc/types.d.ts +9 -1
  188. package/dist/rpc/types.d.ts.map +1 -1
  189. package/dist/rpc/types.js.map +1 -1
  190. package/dist/styles.css +1 -1
  191. package/package.json +1 -1
@@ -124,7 +124,11 @@ function ComboboxMenu({
124
124
  )
125
125
  }
126
126
  ),
127
- /* @__PURE__ */ jsxRuntime.jsx(ComboboxOptionText, { option })
127
+ /* @__PURE__ */ jsxRuntime.jsx(ComboboxOptionText, { option }),
128
+ option.trailing != null && // Capped and truncating rather than `shrink-0`: in a menu
129
+ // clamped by the viewport edge the label is what identifies
130
+ // the option, so the preview yields first.
131
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-auto min-w-0 max-w-[55%] truncate pl-2 text-right text-xs text-muted-foreground", children: option.trailing })
128
132
  ] })
129
133
  }
130
134
  )
@@ -1 +1 @@
1
- {"version":3,"file":"ComboboxMenu.cjs","sources":["../../src/components/ComboboxMenu.tsx"],"sourcesContent":["import { Fragment, type ReactNode, type RefObject } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { FilterPill } from \"../data/FilterPill\";\nimport { Icon, LabelIcon } from \"../data/Icon\";\nimport { UiCheck } from \"../icons\";\nimport { cn } from \"../lib/utils\";\nimport type {\n ComboboxOption,\n ComboboxTriStateMode,\n} from \"./combobox-types\";\nimport type { ComboboxMenuPosition } from \"./combobox-utils\";\n\nexport function ComboboxMenu({\n customEntry,\n filtered,\n floatingZ,\n footer,\n highlighted,\n isSelected,\n listId,\n listRef,\n loading,\n menuPos,\n modes,\n multiple,\n onHighlight,\n onSelect,\n onSetMode,\n tristate,\n}: {\n customEntry: ComboboxOption | null;\n filtered: ComboboxOption[];\n floatingZ: number;\n footer: ReactNode;\n highlighted: number;\n isSelected: (value: string) => boolean;\n listId: string | undefined;\n listRef: RefObject<HTMLDivElement>;\n loading: boolean | undefined;\n menuPos: ComboboxMenuPosition;\n modes: Record<string, ComboboxTriStateMode>;\n multiple: boolean;\n onHighlight: (index: number) => void;\n onSelect: (option: ComboboxOption) => void;\n onSetMode: (value: string, mode: string) => void;\n tristate: boolean;\n}) {\n return createPortal(\n <div\n id={listId}\n ref={listRef}\n role=\"listbox\"\n aria-multiselectable={multiple || undefined}\n style={{\n position: \"fixed\",\n ...(menuPos.top != null\n ? { top: menuPos.top }\n : { bottom: menuPos.bottom }),\n left: menuPos.left,\n minWidth: menuPos.width,\n maxWidth: menuPos.maxWidth,\n maxHeight: menuPos.maxHeight,\n zIndex: floatingZ,\n }}\n className=\"w-max overflow-auto rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-lg shadow-black/5\"\n >\n {loading && filtered.length === 0 && (\n <div className=\"px-2 py-4 text-center text-sm text-muted-foreground\">\n Loading…\n </div>\n )}\n {!loading && filtered.length === 0 && !customEntry && (\n <div className=\"px-2 py-4 text-center text-sm text-muted-foreground\">\n No results\n </div>\n )}\n {filtered.map((option, index) => {\n const selected = isSelected(option.value);\n const mode = tristate ? modes[option.value] : undefined;\n const showHeader =\n option.group != null &&\n option.group !== filtered[index - 1]?.group;\n return (\n <Fragment key={option.value}>\n {showHeader && (\n <div\n role=\"presentation\"\n className=\"select-none px-2 pb-1 pt-2 text-[10px] font-medium uppercase tracking-wide text-muted-foreground\"\n >\n {option.group}\n </div>\n )}\n <div\n id={listId ? `${listId}-${index}` : undefined}\n role=\"option\"\n aria-selected={tristate ? mode != null : selected}\n aria-disabled={option.disabled}\n {...(mode != null\n ? {\n \"aria-label\": `${option.label}, ${\n mode === \"include\" ? \"included\" : \"excluded\"\n }`,\n }\n : {})}\n {...(option.title !== undefined ? { title: option.title } : {})}\n {...(tristate\n ? { \"data-filter-option\": option.value }\n : {})}\n onMouseDown={(event) => {\n event.preventDefault();\n if (!tristate && !option.disabled) onSelect(option);\n }}\n {...(tristate\n ? {\n onClick: () => {\n if (!option.disabled) onSelect(option);\n },\n }\n : {})}\n onMouseEnter={() => onHighlight(index)}\n className={cn(\n \"flex cursor-pointer gap-2 rounded-sm px-2 py-1.5 text-sm\",\n option.description ? \"items-start\" : \"items-center\",\n index === highlighted && \"bg-accent\",\n selected && !tristate && \"font-medium\",\n option.disabled && \"cursor-not-allowed opacity-50\",\n )}\n >\n {tristate ? (\n <div className=\"min-w-0 flex-1\">\n <FilterPill\n mode={mode ?? \"neutral\"}\n togglePosition=\"right\"\n interactive={false}\n label={option.label}\n onModeChange={(next) => onSetMode(option.value, next)}\n className=\"w-full justify-between\"\n />\n <ComboboxOptionDescription description={option.description} />\n </div>\n ) : (\n <>\n <Icon\n icon={UiCheck}\n className={cn(\n \"shrink-0 text-xs\",\n option.description && \"mt-1\",\n selected ? \"opacity-100\" : \"opacity-0\",\n )}\n />\n <LabelIcon\n icon={option.icon}\n className={cn(\n \"text-sm text-muted-foreground\",\n option.description && \"mt-1\",\n )}\n />\n <ComboboxOptionText option={option} />\n </>\n )}\n </div>\n </Fragment>\n );\n })}\n {customEntry && (\n <div\n id={listId ? `${listId}-${filtered.length}` : undefined}\n role=\"option\"\n aria-selected={false}\n data-filter-add-custom={customEntry.value}\n title={customEntry.title}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => onSelect(customEntry)}\n onMouseEnter={() => onHighlight(filtered.length)}\n className={cn(\n \"flex cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm text-primary\",\n highlighted === filtered.length && \"bg-accent\",\n )}\n >\n <LabelIcon\n icon={customEntry.icon}\n className=\"text-sm text-muted-foreground\"\n />\n <span className=\"min-w-0 truncate\">{customEntry.label}</span>\n </div>\n )}\n {footer != null && (\n <div className=\"select-none px-2 py-1.5 text-[11px] text-muted-foreground\">\n {footer}\n </div>\n )}\n </div>,\n document.body,\n );\n}\n\nfunction ComboboxOptionText({ option }: { option: ComboboxOption }) {\n return (\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate\">{option.label}</span>\n <ComboboxOptionDescription description={option.description} />\n </span>\n );\n}\n\nfunction ComboboxOptionDescription({ description }: { description: string | undefined }) {\n return description ? (\n <span className=\"mt-0.5 block whitespace-pre-line text-xs font-normal leading-4 text-muted-foreground\">\n {description}\n </span>\n ) : null;\n}\n"],"names":["createPortal","jsxs","jsx","Fragment","cn","FilterPill","Icon","UiCheck","LabelIcon"],"mappings":"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"}
1
+ {"version":3,"file":"ComboboxMenu.cjs","sources":["../../src/components/ComboboxMenu.tsx"],"sourcesContent":["import { Fragment, type ReactNode, type RefObject } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { FilterPill } from \"../data/FilterPill\";\nimport { Icon, LabelIcon } from \"../data/Icon\";\nimport { UiCheck } from \"../icons\";\nimport { cn } from \"../lib/utils\";\nimport type {\n ComboboxOption,\n ComboboxTriStateMode,\n} from \"./combobox-types\";\nimport type { ComboboxMenuPosition } from \"./combobox-utils\";\n\nexport function ComboboxMenu({\n customEntry,\n filtered,\n floatingZ,\n footer,\n highlighted,\n isSelected,\n listId,\n listRef,\n loading,\n menuPos,\n modes,\n multiple,\n onHighlight,\n onSelect,\n onSetMode,\n tristate,\n}: {\n customEntry: ComboboxOption | null;\n filtered: ComboboxOption[];\n floatingZ: number;\n footer: ReactNode;\n highlighted: number;\n isSelected: (value: string) => boolean;\n listId: string | undefined;\n listRef: RefObject<HTMLDivElement>;\n loading: boolean | undefined;\n menuPos: ComboboxMenuPosition;\n modes: Record<string, ComboboxTriStateMode>;\n multiple: boolean;\n onHighlight: (index: number) => void;\n onSelect: (option: ComboboxOption) => void;\n onSetMode: (value: string, mode: string) => void;\n tristate: boolean;\n}) {\n return createPortal(\n <div\n id={listId}\n ref={listRef}\n role=\"listbox\"\n aria-multiselectable={multiple || undefined}\n style={{\n position: \"fixed\",\n ...(menuPos.top != null\n ? { top: menuPos.top }\n : { bottom: menuPos.bottom }),\n left: menuPos.left,\n minWidth: menuPos.width,\n maxWidth: menuPos.maxWidth,\n maxHeight: menuPos.maxHeight,\n zIndex: floatingZ,\n }}\n className=\"w-max overflow-auto rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-lg shadow-black/5\"\n >\n {loading && filtered.length === 0 && (\n <div className=\"px-2 py-4 text-center text-sm text-muted-foreground\">\n Loading…\n </div>\n )}\n {!loading && filtered.length === 0 && !customEntry && (\n <div className=\"px-2 py-4 text-center text-sm text-muted-foreground\">\n No results\n </div>\n )}\n {filtered.map((option, index) => {\n const selected = isSelected(option.value);\n const mode = tristate ? modes[option.value] : undefined;\n const showHeader =\n option.group != null &&\n option.group !== filtered[index - 1]?.group;\n return (\n <Fragment key={option.value}>\n {showHeader && (\n <div\n role=\"presentation\"\n className=\"select-none px-2 pb-1 pt-2 text-[10px] font-medium uppercase tracking-wide text-muted-foreground\"\n >\n {option.group}\n </div>\n )}\n <div\n id={listId ? `${listId}-${index}` : undefined}\n role=\"option\"\n aria-selected={tristate ? mode != null : selected}\n aria-disabled={option.disabled}\n {...(mode != null\n ? {\n \"aria-label\": `${option.label}, ${\n mode === \"include\" ? \"included\" : \"excluded\"\n }`,\n }\n : {})}\n {...(option.title !== undefined ? { title: option.title } : {})}\n {...(tristate\n ? { \"data-filter-option\": option.value }\n : {})}\n onMouseDown={(event) => {\n event.preventDefault();\n if (!tristate && !option.disabled) onSelect(option);\n }}\n {...(tristate\n ? {\n onClick: () => {\n if (!option.disabled) onSelect(option);\n },\n }\n : {})}\n onMouseEnter={() => onHighlight(index)}\n className={cn(\n \"flex cursor-pointer gap-2 rounded-sm px-2 py-1.5 text-sm\",\n option.description ? \"items-start\" : \"items-center\",\n index === highlighted && \"bg-accent\",\n selected && !tristate && \"font-medium\",\n option.disabled && \"cursor-not-allowed opacity-50\",\n )}\n >\n {tristate ? (\n <div className=\"min-w-0 flex-1\">\n <FilterPill\n mode={mode ?? \"neutral\"}\n togglePosition=\"right\"\n interactive={false}\n label={option.label}\n onModeChange={(next) => onSetMode(option.value, next)}\n className=\"w-full justify-between\"\n />\n <ComboboxOptionDescription description={option.description} />\n </div>\n ) : (\n <>\n <Icon\n icon={UiCheck}\n className={cn(\n \"shrink-0 text-xs\",\n option.description && \"mt-1\",\n selected ? \"opacity-100\" : \"opacity-0\",\n )}\n />\n <LabelIcon\n icon={option.icon}\n className={cn(\n \"text-sm text-muted-foreground\",\n option.description && \"mt-1\",\n )}\n />\n <ComboboxOptionText option={option} />\n {option.trailing != null && (\n // Capped and truncating rather than `shrink-0`: in a menu\n // clamped by the viewport edge the label is what identifies\n // the option, so the preview yields first.\n <span className=\"ml-auto min-w-0 max-w-[55%] truncate pl-2 text-right text-xs text-muted-foreground\">\n {option.trailing}\n </span>\n )}\n </>\n )}\n </div>\n </Fragment>\n );\n })}\n {customEntry && (\n <div\n id={listId ? `${listId}-${filtered.length}` : undefined}\n role=\"option\"\n aria-selected={false}\n data-filter-add-custom={customEntry.value}\n title={customEntry.title}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => onSelect(customEntry)}\n onMouseEnter={() => onHighlight(filtered.length)}\n className={cn(\n \"flex cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm text-primary\",\n highlighted === filtered.length && \"bg-accent\",\n )}\n >\n <LabelIcon\n icon={customEntry.icon}\n className=\"text-sm text-muted-foreground\"\n />\n <span className=\"min-w-0 truncate\">{customEntry.label}</span>\n </div>\n )}\n {footer != null && (\n <div className=\"select-none px-2 py-1.5 text-[11px] text-muted-foreground\">\n {footer}\n </div>\n )}\n </div>,\n document.body,\n );\n}\n\nfunction ComboboxOptionText({ option }: { option: ComboboxOption }) {\n return (\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate\">{option.label}</span>\n <ComboboxOptionDescription description={option.description} />\n </span>\n );\n}\n\nfunction ComboboxOptionDescription({ description }: { description: string | undefined }) {\n return description ? (\n <span className=\"mt-0.5 block whitespace-pre-line text-xs font-normal leading-4 text-muted-foreground\">\n {description}\n </span>\n ) : null;\n}\n"],"names":["createPortal","jsxs","jsx","Fragment","cn","FilterPill","Icon","UiCheck","LabelIcon"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ComboboxMenu.d.ts","sourceRoot":"","sources":["../../src/components/ComboboxMenu.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAMjE,OAAO,KAAK,EACV,cAAc,EACd,oBAAoB,EACrB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAE7D,wBAAgB,YAAY,CAAC,EAC3B,WAAW,EACX,QAAQ,EACR,SAAS,EACT,MAAM,EACN,WAAW,EACX,UAAU,EACV,MAAM,EACN,OAAO,EACP,OAAO,EACP,OAAO,EACP,KAAK,EACL,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,SAAS,EACT,QAAQ,GACT,EAAE;IACD,WAAW,EAAE,cAAc,GAAG,IAAI,CAAC;IACnC,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,SAAS,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;IACvC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,OAAO,EAAE,SAAS,CAAC,cAAc,CAAC,CAAC;IACnC,OAAO,EAAE,OAAO,GAAG,SAAS,CAAC;IAC7B,OAAO,EAAE,oBAAoB,CAAC;IAC9B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;IAC5C,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,QAAQ,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,CAAC;IAC3C,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,QAAQ,EAAE,OAAO,CAAC;CACnB,+BAoJA"}
1
+ {"version":3,"file":"ComboboxMenu.d.ts","sourceRoot":"","sources":["../../src/components/ComboboxMenu.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAMjE,OAAO,KAAK,EACV,cAAc,EACd,oBAAoB,EACrB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAE7D,wBAAgB,YAAY,CAAC,EAC3B,WAAW,EACX,QAAQ,EACR,SAAS,EACT,MAAM,EACN,WAAW,EACX,UAAU,EACV,MAAM,EACN,OAAO,EACP,OAAO,EACP,OAAO,EACP,KAAK,EACL,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,SAAS,EACT,QAAQ,GACT,EAAE;IACD,WAAW,EAAE,cAAc,GAAG,IAAI,CAAC;IACnC,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,SAAS,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;IACvC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,OAAO,EAAE,SAAS,CAAC,cAAc,CAAC,CAAC;IACnC,OAAO,EAAE,OAAO,GAAG,SAAS,CAAC;IAC7B,OAAO,EAAE,oBAAoB,CAAC;IAC9B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;IAC5C,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,QAAQ,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,CAAC;IAC3C,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,QAAQ,EAAE,OAAO,CAAC;CACnB,+BA4JA"}
@@ -122,7 +122,11 @@ function ComboboxMenu({
122
122
  )
123
123
  }
124
124
  ),
125
- /* @__PURE__ */ jsx(ComboboxOptionText, { option })
125
+ /* @__PURE__ */ jsx(ComboboxOptionText, { option }),
126
+ option.trailing != null && // Capped and truncating rather than `shrink-0`: in a menu
127
+ // clamped by the viewport edge the label is what identifies
128
+ // the option, so the preview yields first.
129
+ /* @__PURE__ */ jsx("span", { className: "ml-auto min-w-0 max-w-[55%] truncate pl-2 text-right text-xs text-muted-foreground", children: option.trailing })
126
130
  ] })
127
131
  }
128
132
  )
@@ -1 +1 @@
1
- {"version":3,"file":"ComboboxMenu.js","sources":["../../src/components/ComboboxMenu.tsx"],"sourcesContent":["import { Fragment, type ReactNode, type RefObject } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { FilterPill } from \"../data/FilterPill\";\nimport { Icon, LabelIcon } from \"../data/Icon\";\nimport { UiCheck } from \"../icons\";\nimport { cn } from \"../lib/utils\";\nimport type {\n ComboboxOption,\n ComboboxTriStateMode,\n} from \"./combobox-types\";\nimport type { ComboboxMenuPosition } from \"./combobox-utils\";\n\nexport function ComboboxMenu({\n customEntry,\n filtered,\n floatingZ,\n footer,\n highlighted,\n isSelected,\n listId,\n listRef,\n loading,\n menuPos,\n modes,\n multiple,\n onHighlight,\n onSelect,\n onSetMode,\n tristate,\n}: {\n customEntry: ComboboxOption | null;\n filtered: ComboboxOption[];\n floatingZ: number;\n footer: ReactNode;\n highlighted: number;\n isSelected: (value: string) => boolean;\n listId: string | undefined;\n listRef: RefObject<HTMLDivElement>;\n loading: boolean | undefined;\n menuPos: ComboboxMenuPosition;\n modes: Record<string, ComboboxTriStateMode>;\n multiple: boolean;\n onHighlight: (index: number) => void;\n onSelect: (option: ComboboxOption) => void;\n onSetMode: (value: string, mode: string) => void;\n tristate: boolean;\n}) {\n return createPortal(\n <div\n id={listId}\n ref={listRef}\n role=\"listbox\"\n aria-multiselectable={multiple || undefined}\n style={{\n position: \"fixed\",\n ...(menuPos.top != null\n ? { top: menuPos.top }\n : { bottom: menuPos.bottom }),\n left: menuPos.left,\n minWidth: menuPos.width,\n maxWidth: menuPos.maxWidth,\n maxHeight: menuPos.maxHeight,\n zIndex: floatingZ,\n }}\n className=\"w-max overflow-auto rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-lg shadow-black/5\"\n >\n {loading && filtered.length === 0 && (\n <div className=\"px-2 py-4 text-center text-sm text-muted-foreground\">\n Loading…\n </div>\n )}\n {!loading && filtered.length === 0 && !customEntry && (\n <div className=\"px-2 py-4 text-center text-sm text-muted-foreground\">\n No results\n </div>\n )}\n {filtered.map((option, index) => {\n const selected = isSelected(option.value);\n const mode = tristate ? modes[option.value] : undefined;\n const showHeader =\n option.group != null &&\n option.group !== filtered[index - 1]?.group;\n return (\n <Fragment key={option.value}>\n {showHeader && (\n <div\n role=\"presentation\"\n className=\"select-none px-2 pb-1 pt-2 text-[10px] font-medium uppercase tracking-wide text-muted-foreground\"\n >\n {option.group}\n </div>\n )}\n <div\n id={listId ? `${listId}-${index}` : undefined}\n role=\"option\"\n aria-selected={tristate ? mode != null : selected}\n aria-disabled={option.disabled}\n {...(mode != null\n ? {\n \"aria-label\": `${option.label}, ${\n mode === \"include\" ? \"included\" : \"excluded\"\n }`,\n }\n : {})}\n {...(option.title !== undefined ? { title: option.title } : {})}\n {...(tristate\n ? { \"data-filter-option\": option.value }\n : {})}\n onMouseDown={(event) => {\n event.preventDefault();\n if (!tristate && !option.disabled) onSelect(option);\n }}\n {...(tristate\n ? {\n onClick: () => {\n if (!option.disabled) onSelect(option);\n },\n }\n : {})}\n onMouseEnter={() => onHighlight(index)}\n className={cn(\n \"flex cursor-pointer gap-2 rounded-sm px-2 py-1.5 text-sm\",\n option.description ? \"items-start\" : \"items-center\",\n index === highlighted && \"bg-accent\",\n selected && !tristate && \"font-medium\",\n option.disabled && \"cursor-not-allowed opacity-50\",\n )}\n >\n {tristate ? (\n <div className=\"min-w-0 flex-1\">\n <FilterPill\n mode={mode ?? \"neutral\"}\n togglePosition=\"right\"\n interactive={false}\n label={option.label}\n onModeChange={(next) => onSetMode(option.value, next)}\n className=\"w-full justify-between\"\n />\n <ComboboxOptionDescription description={option.description} />\n </div>\n ) : (\n <>\n <Icon\n icon={UiCheck}\n className={cn(\n \"shrink-0 text-xs\",\n option.description && \"mt-1\",\n selected ? \"opacity-100\" : \"opacity-0\",\n )}\n />\n <LabelIcon\n icon={option.icon}\n className={cn(\n \"text-sm text-muted-foreground\",\n option.description && \"mt-1\",\n )}\n />\n <ComboboxOptionText option={option} />\n </>\n )}\n </div>\n </Fragment>\n );\n })}\n {customEntry && (\n <div\n id={listId ? `${listId}-${filtered.length}` : undefined}\n role=\"option\"\n aria-selected={false}\n data-filter-add-custom={customEntry.value}\n title={customEntry.title}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => onSelect(customEntry)}\n onMouseEnter={() => onHighlight(filtered.length)}\n className={cn(\n \"flex cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm text-primary\",\n highlighted === filtered.length && \"bg-accent\",\n )}\n >\n <LabelIcon\n icon={customEntry.icon}\n className=\"text-sm text-muted-foreground\"\n />\n <span className=\"min-w-0 truncate\">{customEntry.label}</span>\n </div>\n )}\n {footer != null && (\n <div className=\"select-none px-2 py-1.5 text-[11px] text-muted-foreground\">\n {footer}\n </div>\n )}\n </div>,\n document.body,\n );\n}\n\nfunction ComboboxOptionText({ option }: { option: ComboboxOption }) {\n return (\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate\">{option.label}</span>\n <ComboboxOptionDescription description={option.description} />\n </span>\n );\n}\n\nfunction ComboboxOptionDescription({ description }: { description: string | undefined }) {\n return description ? (\n <span className=\"mt-0.5 block whitespace-pre-line text-xs font-normal leading-4 text-muted-foreground\">\n {description}\n </span>\n ) : null;\n}\n"],"names":["Fragment"],"mappings":"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"}
1
+ {"version":3,"file":"ComboboxMenu.js","sources":["../../src/components/ComboboxMenu.tsx"],"sourcesContent":["import { Fragment, type ReactNode, type RefObject } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { FilterPill } from \"../data/FilterPill\";\nimport { Icon, LabelIcon } from \"../data/Icon\";\nimport { UiCheck } from \"../icons\";\nimport { cn } from \"../lib/utils\";\nimport type {\n ComboboxOption,\n ComboboxTriStateMode,\n} from \"./combobox-types\";\nimport type { ComboboxMenuPosition } from \"./combobox-utils\";\n\nexport function ComboboxMenu({\n customEntry,\n filtered,\n floatingZ,\n footer,\n highlighted,\n isSelected,\n listId,\n listRef,\n loading,\n menuPos,\n modes,\n multiple,\n onHighlight,\n onSelect,\n onSetMode,\n tristate,\n}: {\n customEntry: ComboboxOption | null;\n filtered: ComboboxOption[];\n floatingZ: number;\n footer: ReactNode;\n highlighted: number;\n isSelected: (value: string) => boolean;\n listId: string | undefined;\n listRef: RefObject<HTMLDivElement>;\n loading: boolean | undefined;\n menuPos: ComboboxMenuPosition;\n modes: Record<string, ComboboxTriStateMode>;\n multiple: boolean;\n onHighlight: (index: number) => void;\n onSelect: (option: ComboboxOption) => void;\n onSetMode: (value: string, mode: string) => void;\n tristate: boolean;\n}) {\n return createPortal(\n <div\n id={listId}\n ref={listRef}\n role=\"listbox\"\n aria-multiselectable={multiple || undefined}\n style={{\n position: \"fixed\",\n ...(menuPos.top != null\n ? { top: menuPos.top }\n : { bottom: menuPos.bottom }),\n left: menuPos.left,\n minWidth: menuPos.width,\n maxWidth: menuPos.maxWidth,\n maxHeight: menuPos.maxHeight,\n zIndex: floatingZ,\n }}\n className=\"w-max overflow-auto rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-lg shadow-black/5\"\n >\n {loading && filtered.length === 0 && (\n <div className=\"px-2 py-4 text-center text-sm text-muted-foreground\">\n Loading…\n </div>\n )}\n {!loading && filtered.length === 0 && !customEntry && (\n <div className=\"px-2 py-4 text-center text-sm text-muted-foreground\">\n No results\n </div>\n )}\n {filtered.map((option, index) => {\n const selected = isSelected(option.value);\n const mode = tristate ? modes[option.value] : undefined;\n const showHeader =\n option.group != null &&\n option.group !== filtered[index - 1]?.group;\n return (\n <Fragment key={option.value}>\n {showHeader && (\n <div\n role=\"presentation\"\n className=\"select-none px-2 pb-1 pt-2 text-[10px] font-medium uppercase tracking-wide text-muted-foreground\"\n >\n {option.group}\n </div>\n )}\n <div\n id={listId ? `${listId}-${index}` : undefined}\n role=\"option\"\n aria-selected={tristate ? mode != null : selected}\n aria-disabled={option.disabled}\n {...(mode != null\n ? {\n \"aria-label\": `${option.label}, ${\n mode === \"include\" ? \"included\" : \"excluded\"\n }`,\n }\n : {})}\n {...(option.title !== undefined ? { title: option.title } : {})}\n {...(tristate\n ? { \"data-filter-option\": option.value }\n : {})}\n onMouseDown={(event) => {\n event.preventDefault();\n if (!tristate && !option.disabled) onSelect(option);\n }}\n {...(tristate\n ? {\n onClick: () => {\n if (!option.disabled) onSelect(option);\n },\n }\n : {})}\n onMouseEnter={() => onHighlight(index)}\n className={cn(\n \"flex cursor-pointer gap-2 rounded-sm px-2 py-1.5 text-sm\",\n option.description ? \"items-start\" : \"items-center\",\n index === highlighted && \"bg-accent\",\n selected && !tristate && \"font-medium\",\n option.disabled && \"cursor-not-allowed opacity-50\",\n )}\n >\n {tristate ? (\n <div className=\"min-w-0 flex-1\">\n <FilterPill\n mode={mode ?? \"neutral\"}\n togglePosition=\"right\"\n interactive={false}\n label={option.label}\n onModeChange={(next) => onSetMode(option.value, next)}\n className=\"w-full justify-between\"\n />\n <ComboboxOptionDescription description={option.description} />\n </div>\n ) : (\n <>\n <Icon\n icon={UiCheck}\n className={cn(\n \"shrink-0 text-xs\",\n option.description && \"mt-1\",\n selected ? \"opacity-100\" : \"opacity-0\",\n )}\n />\n <LabelIcon\n icon={option.icon}\n className={cn(\n \"text-sm text-muted-foreground\",\n option.description && \"mt-1\",\n )}\n />\n <ComboboxOptionText option={option} />\n {option.trailing != null && (\n // Capped and truncating rather than `shrink-0`: in a menu\n // clamped by the viewport edge the label is what identifies\n // the option, so the preview yields first.\n <span className=\"ml-auto min-w-0 max-w-[55%] truncate pl-2 text-right text-xs text-muted-foreground\">\n {option.trailing}\n </span>\n )}\n </>\n )}\n </div>\n </Fragment>\n );\n })}\n {customEntry && (\n <div\n id={listId ? `${listId}-${filtered.length}` : undefined}\n role=\"option\"\n aria-selected={false}\n data-filter-add-custom={customEntry.value}\n title={customEntry.title}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => onSelect(customEntry)}\n onMouseEnter={() => onHighlight(filtered.length)}\n className={cn(\n \"flex cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm text-primary\",\n highlighted === filtered.length && \"bg-accent\",\n )}\n >\n <LabelIcon\n icon={customEntry.icon}\n className=\"text-sm text-muted-foreground\"\n />\n <span className=\"min-w-0 truncate\">{customEntry.label}</span>\n </div>\n )}\n {footer != null && (\n <div className=\"select-none px-2 py-1.5 text-[11px] text-muted-foreground\">\n {footer}\n </div>\n )}\n </div>,\n document.body,\n );\n}\n\nfunction ComboboxOptionText({ option }: { option: ComboboxOption }) {\n return (\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate\">{option.label}</span>\n <ComboboxOptionDescription description={option.description} />\n </span>\n );\n}\n\nfunction ComboboxOptionDescription({ description }: { description: string | undefined }) {\n return description ? (\n <span className=\"mt-0.5 block whitespace-pre-line text-xs font-normal leading-4 text-muted-foreground\">\n {description}\n </span>\n ) : null;\n}\n"],"names":["Fragment"],"mappings":"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"}
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const SecretKeySelector_model = require("./SecretKeySelector.model.cjs");
4
+ const SCHEME_TO_MODE = {
5
+ svc: "service",
6
+ ip: "cluster-ip",
7
+ proxy: "api-proxy",
8
+ host: "ingress",
9
+ portforward: "port-forward"
10
+ };
11
+ const MODE_TO_SCHEME = Object.fromEntries(
12
+ Object.entries(SCHEME_TO_MODE).map(([scheme, mode]) => [mode, scheme])
13
+ );
14
+ const WORKLOAD_URL = /^([a-z]+):\/\/([^/:?#]*)(?::(\d+))?([^?#]*)(?:\?(.+))?$/;
15
+ function validPort(port) {
16
+ return /^\d+$/.test(port) && Number(port) >= 1 && Number(port) <= 65535;
17
+ }
18
+ function parseTarget(mode, host, query) {
19
+ const dot = host.indexOf(".");
20
+ const name = dot >= 0 ? host.slice(0, dot) : host;
21
+ const namespace = dot >= 0 ? host.slice(dot + 1) : "";
22
+ if (!name) return void 0;
23
+ const kind = mode === "ingress" ? "ingress" : mode === "port-forward" && new URLSearchParams(query).get("kind") === "deployment" ? "deployment" : "service";
24
+ return {
25
+ kind,
26
+ name,
27
+ ...namespace ? { namespace } : {}
28
+ };
29
+ }
30
+ function parseWorkloadValue(raw) {
31
+ const match = WORKLOAD_URL.exec(raw);
32
+ if (!match) return void 0;
33
+ const [, scheme = "", host = "", port = "", path = "", query = ""] = match;
34
+ const mode = SCHEME_TO_MODE[scheme];
35
+ if (!mode || port && !validPort(port)) return void 0;
36
+ if (mode === "port-forward" && (new URLSearchParams(query).has("selector") || !["", "service", "deployment"].includes(
37
+ new URLSearchParams(query).get("kind") ?? ""
38
+ ))) {
39
+ return void 0;
40
+ }
41
+ const target = parseTarget(mode, host, query);
42
+ if (!target) return void 0;
43
+ return {
44
+ mode,
45
+ target,
46
+ ...port ? { port } : {},
47
+ ...path ? { path } : {}
48
+ };
49
+ }
50
+ function parseEndpointValue(raw) {
51
+ if (typeof raw !== "string" || raw === "") return void 0;
52
+ return parseWorkloadValue(raw) ?? {
53
+ mode: "url",
54
+ source: SecretKeySelector_model.parseSecretRef(raw)
55
+ };
56
+ }
57
+ function workloadHost(target) {
58
+ if (!target.name) {
59
+ throw new Error("Endpoint workload mode requires a workload name");
60
+ }
61
+ return target.namespace ? `${target.name}.${target.namespace}` : target.name;
62
+ }
63
+ function validateWorkloadValue(value) {
64
+ if (value.mode === "ingress" && value.target.kind !== "ingress") {
65
+ throw new Error("Ingress endpoint mode requires an ingress target");
66
+ }
67
+ if (value.mode !== "ingress" && value.mode !== "port-forward" && value.target.kind !== "service") {
68
+ throw new Error(`${value.mode} endpoint mode requires a service target`);
69
+ }
70
+ if (value.mode === "port-forward" && !["service", "deployment"].includes(value.target.kind)) {
71
+ throw new Error(
72
+ "Port-forward endpoint mode requires a service or deployment target"
73
+ );
74
+ }
75
+ if (value.port && !validPort(value.port)) {
76
+ throw new Error(
77
+ `Endpoint port "${value.port}" must be between 1 and 65535`
78
+ );
79
+ }
80
+ if (value.path && !value.path.startsWith("/")) {
81
+ throw new Error(`Endpoint path "${value.path}" must start with /`);
82
+ }
83
+ }
84
+ function serializeEndpointValue(value) {
85
+ if (!value) return "";
86
+ if (value.mode === "url") return SecretKeySelector_model.serializeSecretRef(value.source);
87
+ validateWorkloadValue(value);
88
+ const scheme = MODE_TO_SCHEME[value.mode];
89
+ const port = value.port ? `:${value.port}` : "";
90
+ const path = value.path ?? "";
91
+ const kind = value.mode === "port-forward" && value.target.kind === "deployment" ? "?kind=deployment" : "";
92
+ return `${scheme}://${workloadHost(value.target)}${port}${path}${kind}`;
93
+ }
94
+ exports.parseEndpointValue = parseEndpointValue;
95
+ exports.serializeEndpointValue = serializeEndpointValue;
96
+ //# sourceMappingURL=EndpointSelector.model.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EndpointSelector.model.cjs","sources":["../../src/components/EndpointSelector.model.ts"],"sourcesContent":["import type { SecretKeySelectorProps, SecretKeyValue } from \"./SecretKeySelector\";\nimport type {\n WorkloadKind,\n WorkloadResource,\n} from \"./workload-picker-utils\";\nimport type { WorkloadPickerProps } from \"./WorkloadPicker\";\nimport {\n parseSecretRef,\n serializeSecretRef,\n} from \"./SecretKeySelector.model\";\n\nexport type EndpointMode =\n | \"url\"\n | \"service\"\n | \"cluster-ip\"\n | \"api-proxy\"\n | \"ingress\"\n | \"port-forward\";\n\nexport type EndpointWorkloadMode = Exclude<EndpointMode, \"url\">;\n\nexport type EndpointTarget =\n | {\n kind: \"ingress\";\n name: string;\n host?: string;\n namespace?: string;\n }\n | {\n kind: Exclude<WorkloadKind, \"ingress\">;\n name: string;\n namespace?: string;\n };\n\nexport type EndpointWorkloadValue = {\n mode: EndpointWorkloadMode;\n target: EndpointTarget;\n scheme?: string;\n port?: string;\n path?: string;\n};\n\nexport type EndpointSelectorValue =\n | {\n mode: \"url\";\n source: SecretKeyValue;\n }\n | EndpointWorkloadValue;\n\nexport type EndpointSelectorDefaults = {\n scheme?: string;\n path?: string;\n};\n\nexport type EndpointUrlSelectorProps = Omit<\n SecretKeySelectorProps,\n \"value\" | \"onChange\"\n>;\n\nexport type EndpointSelectorProps = {\n value: EndpointSelectorValue | undefined;\n onChange: (value: EndpointSelectorValue | undefined) => void;\n namespace?: string;\n modes: EndpointMode[];\n defaultMode?: EndpointMode;\n loadWorkloads: WorkloadPickerProps[\"loadWorkloads\"];\n urlSelector?: EndpointUrlSelectorProps;\n modeKinds?: Partial<Record<EndpointWorkloadMode, WorkloadKind[]>>;\n defaults?: EndpointSelectorDefaults;\n preferredPorts?: readonly number[];\n schemes?: string[];\n allowCustomScheme?: boolean;\n allowCustomPort?: boolean;\n showScheme?: boolean;\n showPath?: boolean;\n showIngressPort?: boolean;\n className?: string;\n};\n\nexport type EndpointResources = Partial<\n Record<WorkloadKind, WorkloadResource[]>\n>;\n\nconst SCHEME_TO_MODE = {\n svc: \"service\",\n ip: \"cluster-ip\",\n proxy: \"api-proxy\",\n host: \"ingress\",\n portforward: \"port-forward\",\n} as const satisfies Record<string, EndpointMode>;\n\nconst MODE_TO_SCHEME = Object.fromEntries(\n Object.entries(SCHEME_TO_MODE).map(([scheme, mode]) => [mode, scheme]),\n) as Record<EndpointWorkloadMode, keyof typeof SCHEME_TO_MODE>;\n\nconst WORKLOAD_URL =\n /^([a-z]+):\\/\\/([^/:?#]*)(?::(\\d+))?([^?#]*)(?:\\?(.+))?$/;\n\nfunction validPort(port: string) {\n return /^\\d+$/.test(port) && Number(port) >= 1 && Number(port) <= 65535;\n}\n\nfunction parseTarget(\n mode: EndpointWorkloadMode,\n host: string,\n query: string,\n): EndpointTarget | undefined {\n const dot = host.indexOf(\".\");\n const name = dot >= 0 ? host.slice(0, dot) : host;\n const namespace = dot >= 0 ? host.slice(dot + 1) : \"\";\n if (!name) return undefined;\n\n const kind =\n mode === \"ingress\"\n ? \"ingress\"\n : mode === \"port-forward\" &&\n new URLSearchParams(query).get(\"kind\") === \"deployment\"\n ? \"deployment\"\n : \"service\";\n return {\n kind,\n name,\n ...(namespace ? { namespace } : {}),\n };\n}\n\nfunction parseWorkloadValue(raw: string): EndpointWorkloadValue | undefined {\n const match = WORKLOAD_URL.exec(raw);\n if (!match) return undefined;\n const [, scheme = \"\", host = \"\", port = \"\", path = \"\", query = \"\"] =\n match;\n const mode = SCHEME_TO_MODE[scheme as keyof typeof SCHEME_TO_MODE];\n if (!mode || (port && !validPort(port))) return undefined;\n if (\n mode === \"port-forward\" &&\n (new URLSearchParams(query).has(\"selector\") ||\n ![\"\", \"service\", \"deployment\"].includes(\n new URLSearchParams(query).get(\"kind\") ?? \"\",\n ))\n ) {\n return undefined;\n }\n\n const target = parseTarget(mode, host, query);\n if (!target) return undefined;\n return {\n mode,\n target,\n ...(port ? { port } : {}),\n ...(path ? { path } : {}),\n };\n}\n\nexport function parseEndpointValue(\n raw: unknown,\n): EndpointSelectorValue | undefined {\n if (typeof raw !== \"string\" || raw === \"\") return undefined;\n return (\n parseWorkloadValue(raw) ?? {\n mode: \"url\",\n source: parseSecretRef(raw)!,\n }\n );\n}\n\nfunction workloadHost(target: EndpointTarget) {\n if (!target.name) {\n throw new Error(\"Endpoint workload mode requires a workload name\");\n }\n return target.namespace\n ? `${target.name}.${target.namespace}`\n : target.name;\n}\n\nfunction validateWorkloadValue(value: EndpointWorkloadValue) {\n if (value.mode === \"ingress\" && value.target.kind !== \"ingress\") {\n throw new Error(\"Ingress endpoint mode requires an ingress target\");\n }\n if (\n value.mode !== \"ingress\" &&\n value.mode !== \"port-forward\" &&\n value.target.kind !== \"service\"\n ) {\n throw new Error(`${value.mode} endpoint mode requires a service target`);\n }\n if (\n value.mode === \"port-forward\" &&\n ![\"service\", \"deployment\"].includes(value.target.kind)\n ) {\n throw new Error(\n \"Port-forward endpoint mode requires a service or deployment target\",\n );\n }\n if (value.port && !validPort(value.port)) {\n throw new Error(\n `Endpoint port \"${value.port}\" must be between 1 and 65535`,\n );\n }\n if (value.path && !value.path.startsWith(\"/\")) {\n throw new Error(`Endpoint path \"${value.path}\" must start with /`);\n }\n}\n\nexport function serializeEndpointValue(\n value: EndpointSelectorValue | undefined,\n): string {\n if (!value) return \"\";\n if (value.mode === \"url\") return serializeSecretRef(value.source);\n validateWorkloadValue(value);\n const scheme = MODE_TO_SCHEME[value.mode];\n const port = value.port ? `:${value.port}` : \"\";\n const path = value.path ?? \"\";\n const kind =\n value.mode === \"port-forward\" && value.target.kind === \"deployment\"\n ? \"?kind=deployment\"\n : \"\";\n return `${scheme}://${workloadHost(value.target)}${port}${path}${kind}`;\n}\n"],"names":["parseSecretRef","serializeSecretRef"],"mappings":";;;AAmFA,MAAM,iBAAiB;AAAA,EACrB,KAAK;AAAA,EACL,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,MAAM;AAAA,EACN,aAAa;AACf;AAEA,MAAM,iBAAiB,OAAO;AAAA,EAC5B,OAAO,QAAQ,cAAc,EAAE,IAAI,CAAC,CAAC,QAAQ,IAAI,MAAM,CAAC,MAAM,MAAM,CAAC;AACvE;AAEA,MAAM,eACJ;AAEF,SAAS,UAAU,MAAc;AAC/B,SAAO,QAAQ,KAAK,IAAI,KAAK,OAAO,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK;AACpE;AAEA,SAAS,YACP,MACA,MACA,OAC4B;AAC5B,QAAM,MAAM,KAAK,QAAQ,GAAG;AAC5B,QAAM,OAAO,OAAO,IAAI,KAAK,MAAM,GAAG,GAAG,IAAI;AAC7C,QAAM,YAAY,OAAO,IAAI,KAAK,MAAM,MAAM,CAAC,IAAI;AACnD,MAAI,CAAC,KAAM,QAAO;AAElB,QAAM,OACJ,SAAS,YACL,YACA,SAAS,kBACP,IAAI,gBAAgB,KAAK,EAAE,IAAI,MAAM,MAAM,eAC3C,eACA;AACR,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,GAAI,YAAY,EAAE,cAAc,CAAA;AAAA,EAAC;AAErC;AAEA,SAAS,mBAAmB,KAAgD;AAC1E,QAAM,QAAQ,aAAa,KAAK,GAAG;AACnC,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,GAAG,SAAS,IAAI,OAAO,IAAI,OAAO,IAAI,OAAO,IAAI,QAAQ,EAAE,IAC/D;AACF,QAAM,OAAO,eAAe,MAAqC;AACjE,MAAI,CAAC,QAAS,QAAQ,CAAC,UAAU,IAAI,EAAI,QAAO;AAChD,MACE,SAAS,mBACR,IAAI,gBAAgB,KAAK,EAAE,IAAI,UAAU,KACxC,CAAC,CAAC,IAAI,WAAW,YAAY,EAAE;AAAA,IAC7B,IAAI,gBAAgB,KAAK,EAAE,IAAI,MAAM,KAAK;AAAA,EAAA,IAE9C;AACA,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,YAAY,MAAM,MAAM,KAAK;AAC5C,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,GAAI,OAAO,EAAE,KAAA,IAAS,CAAA;AAAA,IACtB,GAAI,OAAO,EAAE,SAAS,CAAA;AAAA,EAAC;AAE3B;AAEO,SAAS,mBACd,KACmC;AACnC,MAAI,OAAO,QAAQ,YAAY,QAAQ,GAAI,QAAO;AAClD,SACE,mBAAmB,GAAG,KAAK;AAAA,IACzB,MAAM;AAAA,IACN,QAAQA,wBAAAA,eAAe,GAAG;AAAA,EAAA;AAGhC;AAEA,SAAS,aAAa,QAAwB;AAC5C,MAAI,CAAC,OAAO,MAAM;AAChB,UAAM,IAAI,MAAM,iDAAiD;AAAA,EACnE;AACA,SAAO,OAAO,YACV,GAAG,OAAO,IAAI,IAAI,OAAO,SAAS,KAClC,OAAO;AACb;AAEA,SAAS,sBAAsB,OAA8B;AAC3D,MAAI,MAAM,SAAS,aAAa,MAAM,OAAO,SAAS,WAAW;AAC/D,UAAM,IAAI,MAAM,kDAAkD;AAAA,EACpE;AACA,MACE,MAAM,SAAS,aACf,MAAM,SAAS,kBACf,MAAM,OAAO,SAAS,WACtB;AACA,UAAM,IAAI,MAAM,GAAG,MAAM,IAAI,0CAA0C;AAAA,EACzE;AACA,MACE,MAAM,SAAS,kBACf,CAAC,CAAC,WAAW,YAAY,EAAE,SAAS,MAAM,OAAO,IAAI,GACrD;AACA,UAAM,IAAI;AAAA,MACR;AAAA,IAAA;AAAA,EAEJ;AACA,MAAI,MAAM,QAAQ,CAAC,UAAU,MAAM,IAAI,GAAG;AACxC,UAAM,IAAI;AAAA,MACR,kBAAkB,MAAM,IAAI;AAAA,IAAA;AAAA,EAEhC;AACA,MAAI,MAAM,QAAQ,CAAC,MAAM,KAAK,WAAW,GAAG,GAAG;AAC7C,UAAM,IAAI,MAAM,kBAAkB,MAAM,IAAI,qBAAqB;AAAA,EACnE;AACF;AAEO,SAAS,uBACd,OACQ;AACR,MAAI,CAAC,MAAO,QAAO;AACnB,MAAI,MAAM,SAAS,MAAO,QAAOC,wBAAAA,mBAAmB,MAAM,MAAM;AAChE,wBAAsB,KAAK;AAC3B,QAAM,SAAS,eAAe,MAAM,IAAI;AACxC,QAAM,OAAO,MAAM,OAAO,IAAI,MAAM,IAAI,KAAK;AAC7C,QAAM,OAAO,MAAM,QAAQ;AAC3B,QAAM,OACJ,MAAM,SAAS,kBAAkB,MAAM,OAAO,SAAS,eACnD,qBACA;AACN,SAAO,GAAG,MAAM,MAAM,aAAa,MAAM,MAAM,CAAC,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI;AACvE;;;"}
@@ -49,4 +49,6 @@ export type EndpointSelectorProps = {
49
49
  className?: string;
50
50
  };
51
51
  export type EndpointResources = Partial<Record<WorkloadKind, WorkloadResource[]>>;
52
+ export declare function parseEndpointValue(raw: unknown): EndpointSelectorValue | undefined;
53
+ export declare function serializeEndpointValue(value: EndpointSelectorValue | undefined): string;
52
54
  //# sourceMappingURL=EndpointSelector.model.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"EndpointSelector.model.d.ts","sourceRoot":"","sources":["../../src/components/EndpointSelector.model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAClF,OAAO,KAAK,EACV,YAAY,EACZ,gBAAgB,EACjB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAE5D,MAAM,MAAM,YAAY,GACpB,KAAK,GACL,SAAS,GACT,YAAY,GACZ,WAAW,GACX,SAAS,GACT,cAAc,CAAC;AAEnB,MAAM,MAAM,oBAAoB,GAAG,OAAO,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;AAEhE,MAAM,MAAM,cAAc,GACtB;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GACD;IACE,IAAI,EAAE,OAAO,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEN,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,EAAE,oBAAoB,CAAC;IAC3B,MAAM,EAAE,cAAc,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAC7B;IACE,IAAI,EAAE,KAAK,CAAC;IACZ,MAAM,EAAE,cAAc,CAAC;CACxB,GACD,qBAAqB,CAAC;AAE1B,MAAM,MAAM,wBAAwB,GAAG;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG,IAAI,CACzC,sBAAsB,EACtB,OAAO,GAAG,UAAU,CACrB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,EAAE,qBAAqB,GAAG,SAAS,CAAC;IACzC,QAAQ,EAAE,CAAC,KAAK,EAAE,qBAAqB,GAAG,SAAS,KAAK,IAAI,CAAC;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,WAAW,CAAC,EAAE,YAAY,CAAC;IAC3B,aAAa,EAAE,mBAAmB,CAAC,eAAe,CAAC,CAAC;IACpD,WAAW,CAAC,EAAE,wBAAwB,CAAC;IACvC,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,oBAAoB,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC;IAClE,QAAQ,CAAC,EAAE,wBAAwB,CAAC;IACpC,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,OAAO,CACrC,MAAM,CAAC,YAAY,EAAE,gBAAgB,EAAE,CAAC,CACzC,CAAC"}
1
+ {"version":3,"file":"EndpointSelector.model.d.ts","sourceRoot":"","sources":["../../src/components/EndpointSelector.model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAClF,OAAO,KAAK,EACV,YAAY,EACZ,gBAAgB,EACjB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAM5D,MAAM,MAAM,YAAY,GACpB,KAAK,GACL,SAAS,GACT,YAAY,GACZ,WAAW,GACX,SAAS,GACT,cAAc,CAAC;AAEnB,MAAM,MAAM,oBAAoB,GAAG,OAAO,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;AAEhE,MAAM,MAAM,cAAc,GACtB;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GACD;IACE,IAAI,EAAE,OAAO,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEN,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,EAAE,oBAAoB,CAAC;IAC3B,MAAM,EAAE,cAAc,CAAC;IACvB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAC7B;IACE,IAAI,EAAE,KAAK,CAAC;IACZ,MAAM,EAAE,cAAc,CAAC;CACxB,GACD,qBAAqB,CAAC;AAE1B,MAAM,MAAM,wBAAwB,GAAG;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG,IAAI,CACzC,sBAAsB,EACtB,OAAO,GAAG,UAAU,CACrB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,EAAE,qBAAqB,GAAG,SAAS,CAAC;IACzC,QAAQ,EAAE,CAAC,KAAK,EAAE,qBAAqB,GAAG,SAAS,KAAK,IAAI,CAAC;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,WAAW,CAAC,EAAE,YAAY,CAAC;IAC3B,aAAa,EAAE,mBAAmB,CAAC,eAAe,CAAC,CAAC;IACpD,WAAW,CAAC,EAAE,wBAAwB,CAAC;IACvC,SAAS,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,oBAAoB,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC;IAClE,QAAQ,CAAC,EAAE,wBAAwB,CAAC;IACpC,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,OAAO,CACrC,MAAM,CAAC,YAAY,EAAE,gBAAgB,EAAE,CAAC,CACzC,CAAC;AAwEF,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,OAAO,GACX,qBAAqB,GAAG,SAAS,CAQnC;AAwCD,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,qBAAqB,GAAG,SAAS,GACvC,MAAM,CAYR"}
@@ -0,0 +1,96 @@
1
+ import { parseSecretRef, serializeSecretRef } from "./SecretKeySelector.model.js";
2
+ const SCHEME_TO_MODE = {
3
+ svc: "service",
4
+ ip: "cluster-ip",
5
+ proxy: "api-proxy",
6
+ host: "ingress",
7
+ portforward: "port-forward"
8
+ };
9
+ const MODE_TO_SCHEME = Object.fromEntries(
10
+ Object.entries(SCHEME_TO_MODE).map(([scheme, mode]) => [mode, scheme])
11
+ );
12
+ const WORKLOAD_URL = /^([a-z]+):\/\/([^/:?#]*)(?::(\d+))?([^?#]*)(?:\?(.+))?$/;
13
+ function validPort(port) {
14
+ return /^\d+$/.test(port) && Number(port) >= 1 && Number(port) <= 65535;
15
+ }
16
+ function parseTarget(mode, host, query) {
17
+ const dot = host.indexOf(".");
18
+ const name = dot >= 0 ? host.slice(0, dot) : host;
19
+ const namespace = dot >= 0 ? host.slice(dot + 1) : "";
20
+ if (!name) return void 0;
21
+ const kind = mode === "ingress" ? "ingress" : mode === "port-forward" && new URLSearchParams(query).get("kind") === "deployment" ? "deployment" : "service";
22
+ return {
23
+ kind,
24
+ name,
25
+ ...namespace ? { namespace } : {}
26
+ };
27
+ }
28
+ function parseWorkloadValue(raw) {
29
+ const match = WORKLOAD_URL.exec(raw);
30
+ if (!match) return void 0;
31
+ const [, scheme = "", host = "", port = "", path = "", query = ""] = match;
32
+ const mode = SCHEME_TO_MODE[scheme];
33
+ if (!mode || port && !validPort(port)) return void 0;
34
+ if (mode === "port-forward" && (new URLSearchParams(query).has("selector") || !["", "service", "deployment"].includes(
35
+ new URLSearchParams(query).get("kind") ?? ""
36
+ ))) {
37
+ return void 0;
38
+ }
39
+ const target = parseTarget(mode, host, query);
40
+ if (!target) return void 0;
41
+ return {
42
+ mode,
43
+ target,
44
+ ...port ? { port } : {},
45
+ ...path ? { path } : {}
46
+ };
47
+ }
48
+ function parseEndpointValue(raw) {
49
+ if (typeof raw !== "string" || raw === "") return void 0;
50
+ return parseWorkloadValue(raw) ?? {
51
+ mode: "url",
52
+ source: parseSecretRef(raw)
53
+ };
54
+ }
55
+ function workloadHost(target) {
56
+ if (!target.name) {
57
+ throw new Error("Endpoint workload mode requires a workload name");
58
+ }
59
+ return target.namespace ? `${target.name}.${target.namespace}` : target.name;
60
+ }
61
+ function validateWorkloadValue(value) {
62
+ if (value.mode === "ingress" && value.target.kind !== "ingress") {
63
+ throw new Error("Ingress endpoint mode requires an ingress target");
64
+ }
65
+ if (value.mode !== "ingress" && value.mode !== "port-forward" && value.target.kind !== "service") {
66
+ throw new Error(`${value.mode} endpoint mode requires a service target`);
67
+ }
68
+ if (value.mode === "port-forward" && !["service", "deployment"].includes(value.target.kind)) {
69
+ throw new Error(
70
+ "Port-forward endpoint mode requires a service or deployment target"
71
+ );
72
+ }
73
+ if (value.port && !validPort(value.port)) {
74
+ throw new Error(
75
+ `Endpoint port "${value.port}" must be between 1 and 65535`
76
+ );
77
+ }
78
+ if (value.path && !value.path.startsWith("/")) {
79
+ throw new Error(`Endpoint path "${value.path}" must start with /`);
80
+ }
81
+ }
82
+ function serializeEndpointValue(value) {
83
+ if (!value) return "";
84
+ if (value.mode === "url") return serializeSecretRef(value.source);
85
+ validateWorkloadValue(value);
86
+ const scheme = MODE_TO_SCHEME[value.mode];
87
+ const port = value.port ? `:${value.port}` : "";
88
+ const path = value.path ?? "";
89
+ const kind = value.mode === "port-forward" && value.target.kind === "deployment" ? "?kind=deployment" : "";
90
+ return `${scheme}://${workloadHost(value.target)}${port}${path}${kind}`;
91
+ }
92
+ export {
93
+ parseEndpointValue,
94
+ serializeEndpointValue
95
+ };
96
+ //# sourceMappingURL=EndpointSelector.model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EndpointSelector.model.js","sources":["../../src/components/EndpointSelector.model.ts"],"sourcesContent":["import type { SecretKeySelectorProps, SecretKeyValue } from \"./SecretKeySelector\";\nimport type {\n WorkloadKind,\n WorkloadResource,\n} from \"./workload-picker-utils\";\nimport type { WorkloadPickerProps } from \"./WorkloadPicker\";\nimport {\n parseSecretRef,\n serializeSecretRef,\n} from \"./SecretKeySelector.model\";\n\nexport type EndpointMode =\n | \"url\"\n | \"service\"\n | \"cluster-ip\"\n | \"api-proxy\"\n | \"ingress\"\n | \"port-forward\";\n\nexport type EndpointWorkloadMode = Exclude<EndpointMode, \"url\">;\n\nexport type EndpointTarget =\n | {\n kind: \"ingress\";\n name: string;\n host?: string;\n namespace?: string;\n }\n | {\n kind: Exclude<WorkloadKind, \"ingress\">;\n name: string;\n namespace?: string;\n };\n\nexport type EndpointWorkloadValue = {\n mode: EndpointWorkloadMode;\n target: EndpointTarget;\n scheme?: string;\n port?: string;\n path?: string;\n};\n\nexport type EndpointSelectorValue =\n | {\n mode: \"url\";\n source: SecretKeyValue;\n }\n | EndpointWorkloadValue;\n\nexport type EndpointSelectorDefaults = {\n scheme?: string;\n path?: string;\n};\n\nexport type EndpointUrlSelectorProps = Omit<\n SecretKeySelectorProps,\n \"value\" | \"onChange\"\n>;\n\nexport type EndpointSelectorProps = {\n value: EndpointSelectorValue | undefined;\n onChange: (value: EndpointSelectorValue | undefined) => void;\n namespace?: string;\n modes: EndpointMode[];\n defaultMode?: EndpointMode;\n loadWorkloads: WorkloadPickerProps[\"loadWorkloads\"];\n urlSelector?: EndpointUrlSelectorProps;\n modeKinds?: Partial<Record<EndpointWorkloadMode, WorkloadKind[]>>;\n defaults?: EndpointSelectorDefaults;\n preferredPorts?: readonly number[];\n schemes?: string[];\n allowCustomScheme?: boolean;\n allowCustomPort?: boolean;\n showScheme?: boolean;\n showPath?: boolean;\n showIngressPort?: boolean;\n className?: string;\n};\n\nexport type EndpointResources = Partial<\n Record<WorkloadKind, WorkloadResource[]>\n>;\n\nconst SCHEME_TO_MODE = {\n svc: \"service\",\n ip: \"cluster-ip\",\n proxy: \"api-proxy\",\n host: \"ingress\",\n portforward: \"port-forward\",\n} as const satisfies Record<string, EndpointMode>;\n\nconst MODE_TO_SCHEME = Object.fromEntries(\n Object.entries(SCHEME_TO_MODE).map(([scheme, mode]) => [mode, scheme]),\n) as Record<EndpointWorkloadMode, keyof typeof SCHEME_TO_MODE>;\n\nconst WORKLOAD_URL =\n /^([a-z]+):\\/\\/([^/:?#]*)(?::(\\d+))?([^?#]*)(?:\\?(.+))?$/;\n\nfunction validPort(port: string) {\n return /^\\d+$/.test(port) && Number(port) >= 1 && Number(port) <= 65535;\n}\n\nfunction parseTarget(\n mode: EndpointWorkloadMode,\n host: string,\n query: string,\n): EndpointTarget | undefined {\n const dot = host.indexOf(\".\");\n const name = dot >= 0 ? host.slice(0, dot) : host;\n const namespace = dot >= 0 ? host.slice(dot + 1) : \"\";\n if (!name) return undefined;\n\n const kind =\n mode === \"ingress\"\n ? \"ingress\"\n : mode === \"port-forward\" &&\n new URLSearchParams(query).get(\"kind\") === \"deployment\"\n ? \"deployment\"\n : \"service\";\n return {\n kind,\n name,\n ...(namespace ? { namespace } : {}),\n };\n}\n\nfunction parseWorkloadValue(raw: string): EndpointWorkloadValue | undefined {\n const match = WORKLOAD_URL.exec(raw);\n if (!match) return undefined;\n const [, scheme = \"\", host = \"\", port = \"\", path = \"\", query = \"\"] =\n match;\n const mode = SCHEME_TO_MODE[scheme as keyof typeof SCHEME_TO_MODE];\n if (!mode || (port && !validPort(port))) return undefined;\n if (\n mode === \"port-forward\" &&\n (new URLSearchParams(query).has(\"selector\") ||\n ![\"\", \"service\", \"deployment\"].includes(\n new URLSearchParams(query).get(\"kind\") ?? \"\",\n ))\n ) {\n return undefined;\n }\n\n const target = parseTarget(mode, host, query);\n if (!target) return undefined;\n return {\n mode,\n target,\n ...(port ? { port } : {}),\n ...(path ? { path } : {}),\n };\n}\n\nexport function parseEndpointValue(\n raw: unknown,\n): EndpointSelectorValue | undefined {\n if (typeof raw !== \"string\" || raw === \"\") return undefined;\n return (\n parseWorkloadValue(raw) ?? {\n mode: \"url\",\n source: parseSecretRef(raw)!,\n }\n );\n}\n\nfunction workloadHost(target: EndpointTarget) {\n if (!target.name) {\n throw new Error(\"Endpoint workload mode requires a workload name\");\n }\n return target.namespace\n ? `${target.name}.${target.namespace}`\n : target.name;\n}\n\nfunction validateWorkloadValue(value: EndpointWorkloadValue) {\n if (value.mode === \"ingress\" && value.target.kind !== \"ingress\") {\n throw new Error(\"Ingress endpoint mode requires an ingress target\");\n }\n if (\n value.mode !== \"ingress\" &&\n value.mode !== \"port-forward\" &&\n value.target.kind !== \"service\"\n ) {\n throw new Error(`${value.mode} endpoint mode requires a service target`);\n }\n if (\n value.mode === \"port-forward\" &&\n ![\"service\", \"deployment\"].includes(value.target.kind)\n ) {\n throw new Error(\n \"Port-forward endpoint mode requires a service or deployment target\",\n );\n }\n if (value.port && !validPort(value.port)) {\n throw new Error(\n `Endpoint port \"${value.port}\" must be between 1 and 65535`,\n );\n }\n if (value.path && !value.path.startsWith(\"/\")) {\n throw new Error(`Endpoint path \"${value.path}\" must start with /`);\n }\n}\n\nexport function serializeEndpointValue(\n value: EndpointSelectorValue | undefined,\n): string {\n if (!value) return \"\";\n if (value.mode === \"url\") return serializeSecretRef(value.source);\n validateWorkloadValue(value);\n const scheme = MODE_TO_SCHEME[value.mode];\n const port = value.port ? `:${value.port}` : \"\";\n const path = value.path ?? \"\";\n const kind =\n value.mode === \"port-forward\" && value.target.kind === \"deployment\"\n ? \"?kind=deployment\"\n : \"\";\n return `${scheme}://${workloadHost(value.target)}${port}${path}${kind}`;\n}\n"],"names":[],"mappings":"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"}
@@ -230,9 +230,28 @@ function FilterBarFilterPanelContent({
230
230
  filter.kind === "enum" && /* @__PURE__ */ jsxRuntime.jsx(EnumFilterField, { filter, grow: true }),
231
231
  filter.kind === "boolean" && /* @__PURE__ */ jsxRuntime.jsx(BooleanFilterField, { filter }),
232
232
  filter.kind === "tristate" && /* @__PURE__ */ jsxRuntime.jsx(TriStateFilterField, { filter }),
233
+ filter.kind === "date-range" && /* @__PURE__ */ jsxRuntime.jsx(
234
+ FilterBarRangePanel,
235
+ {
236
+ kind: filter.timeEnabled === false ? "date" : "time",
237
+ label: filter.label,
238
+ ...dateRangeFilterProps(filter)
239
+ }
240
+ ),
233
241
  filter.kind === "text" && /* @__PURE__ */ jsxRuntime.jsx(TextFilterField, { filter, grow: true })
234
242
  ] });
235
243
  }
244
+ function dateRangeFilterProps(filter) {
245
+ const {
246
+ key: _key,
247
+ kind: _kind,
248
+ label: _label,
249
+ icon: _icon,
250
+ description: _description,
251
+ ...range
252
+ } = filter;
253
+ return range;
254
+ }
236
255
  function renderFilterField(filter, grow) {
237
256
  if (filter.kind === "lookup") {
238
257
  return /* @__PURE__ */ jsxRuntime.jsx(LookupFilterField, { filter, grow });
@@ -261,6 +280,16 @@ function renderFilterField(filter, grow) {
261
280
  if (filter.kind === "tristate") {
262
281
  return /* @__PURE__ */ jsxRuntime.jsx(TriStateFilterField, { filter });
263
282
  }
283
+ if (filter.kind === "date-range") {
284
+ return /* @__PURE__ */ jsxRuntime.jsx(
285
+ RangeControlButton,
286
+ {
287
+ kind: filter.timeEnabled === false ? "date" : "time",
288
+ label: filter.label,
289
+ ...dateRangeFilterProps(filter)
290
+ }
291
+ );
292
+ }
264
293
  return /* @__PURE__ */ jsxRuntime.jsx(TextFilterField, { filter, grow });
265
294
  }
266
295
  function OverflowFiltersMenu({
@@ -452,6 +481,16 @@ function OverflowFiltersMenu({
452
481
  );
453
482
  }
454
483
  function FilterBarKeyValueControl({ filter }) {
484
+ if (filter.kind === "date-range") {
485
+ return /* @__PURE__ */ jsxRuntime.jsx(
486
+ RangeControlButton,
487
+ {
488
+ kind: filter.timeEnabled === false ? "date" : "time",
489
+ label: filter.label,
490
+ ...dateRangeFilterProps(filter)
491
+ }
492
+ );
493
+ }
455
494
  if (filter.kind === "text") {
456
495
  return /* @__PURE__ */ jsxRuntime.jsx(TextFilterValueControl, { filter });
457
496
  }
@@ -656,7 +695,8 @@ function FilterBarRangePanel({
656
695
  timeZones,
657
696
  fromPlaceholder,
658
697
  toPlaceholder,
659
- emptyLabel
698
+ emptyLabel,
699
+ disabled
660
700
  }) {
661
701
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-72 p-3 text-popover-foreground", children: /* @__PURE__ */ jsxRuntime.jsx(
662
702
  TimeRange.TimeRange,
@@ -667,6 +707,7 @@ function FilterBarRangePanel({
667
707
  from,
668
708
  to,
669
709
  onApply,
710
+ ...disabled !== void 0 ? { disabled } : {},
670
711
  ...presets ? { presets } : {},
671
712
  ...timeEnabled !== void 0 ? { timeEnabled } : {},
672
713
  ...timeZone ? { timeZone } : {},
@@ -1577,7 +1618,8 @@ function RangeControlButton({
1577
1618
  fromPlaceholder,
1578
1619
  toPlaceholder,
1579
1620
  emptyLabel,
1580
- className
1621
+ className,
1622
+ disabled
1581
1623
  }) {
1582
1624
  return /* @__PURE__ */ jsxRuntime.jsx(
1583
1625
  TimeRange.TimeRange,
@@ -1587,6 +1629,7 @@ function RangeControlButton({
1587
1629
  from,
1588
1630
  to,
1589
1631
  onApply,
1632
+ ...disabled !== void 0 ? { disabled } : {},
1590
1633
  ...presets ? { presets } : {},
1591
1634
  ...timeEnabled !== void 0 ? { timeEnabled } : {},
1592
1635
  ...timeZone ? { timeZone } : {},
@@ -1762,10 +1805,15 @@ function formatRawNumber(value) {
1762
1805
  function createFilterValueMap(filters) {
1763
1806
  return Object.fromEntries(filters.map((filter) => [filter.key, filterBarFilterValue(filter)]));
1764
1807
  }
1808
+ function isStageableFilter(filter) {
1809
+ return filter.kind !== "date-range";
1810
+ }
1765
1811
  function filterBarFilterValue(filter) {
1812
+ if (!isStageableFilter(filter)) return void 0;
1766
1813
  return filter.value;
1767
1814
  }
1768
1815
  function filterWithStagedValue(filter, value, onChange) {
1816
+ if (!isStageableFilter(filter)) return filter;
1769
1817
  if (filter.kind === "text") {
1770
1818
  return {
1771
1819
  ...filter,
@@ -1837,12 +1885,14 @@ function filterWithStagedValue(filter, value, onChange) {
1837
1885
  }
1838
1886
  function applyStagedFilterValues(filters, stagedValues) {
1839
1887
  for (const filter of filters) {
1888
+ if (!isStageableFilter(filter)) continue;
1840
1889
  const next = Object.hasOwn(stagedValues, filter.key) ? stagedValues[filter.key] : filterBarFilterValue(filter);
1841
1890
  if (sameFilterBarValue(filterBarFilterValue(filter), next)) continue;
1842
1891
  applyFilterBarValue(filter, next);
1843
1892
  }
1844
1893
  }
1845
1894
  function applyFilterBarValue(filter, value) {
1895
+ if (!isStageableFilter(filter)) return;
1846
1896
  if (filter.kind === "text" || filter.kind === "lookup" || filter.kind === "enum") {
1847
1897
  filter.onChange(String(value ?? ""));
1848
1898
  return;