@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.
- package/dist/components/ComboboxMenu.cjs +5 -1
- package/dist/components/ComboboxMenu.cjs.map +1 -1
- package/dist/components/ComboboxMenu.d.ts.map +1 -1
- package/dist/components/ComboboxMenu.js +5 -1
- package/dist/components/ComboboxMenu.js.map +1 -1
- package/dist/components/EndpointSelector.model.cjs +96 -0
- package/dist/components/EndpointSelector.model.cjs.map +1 -0
- package/dist/components/EndpointSelector.model.d.ts +2 -0
- package/dist/components/EndpointSelector.model.d.ts.map +1 -1
- package/dist/components/EndpointSelector.model.js +96 -0
- package/dist/components/EndpointSelector.model.js.map +1 -0
- package/dist/components/FilterBar.cjs +52 -2
- package/dist/components/FilterBar.cjs.map +1 -1
- package/dist/components/FilterBar.d.ts +20 -2
- package/dist/components/FilterBar.d.ts.map +1 -1
- package/dist/components/FilterBar.js +52 -2
- package/dist/components/FilterBar.js.map +1 -1
- package/dist/components/JSONPathField.cjs +87 -66
- package/dist/components/JSONPathField.cjs.map +1 -1
- package/dist/components/JSONPathField.d.ts +26 -9
- package/dist/components/JSONPathField.d.ts.map +1 -1
- package/dist/components/JSONPathField.js +88 -67
- package/dist/components/JSONPathField.js.map +1 -1
- package/dist/components/JSONPathPlayground.cjs +225 -0
- package/dist/components/JSONPathPlayground.cjs.map +1 -0
- package/dist/components/JSONPathPlayground.d.ts +59 -0
- package/dist/components/JSONPathPlayground.d.ts.map +1 -0
- package/dist/components/JSONPathPlayground.js +225 -0
- package/dist/components/JSONPathPlayground.js.map +1 -0
- package/dist/components/OnePasswordSelector.cjs +178 -0
- package/dist/components/OnePasswordSelector.cjs.map +1 -0
- package/dist/components/OnePasswordSelector.d.ts +8 -0
- package/dist/components/OnePasswordSelector.d.ts.map +1 -0
- package/dist/components/OnePasswordSelector.js +178 -0
- package/dist/components/OnePasswordSelector.js.map +1 -0
- package/dist/components/OnePasswordSelector.model.cjs +31 -0
- package/dist/components/OnePasswordSelector.model.cjs.map +1 -0
- package/dist/components/OnePasswordSelector.model.d.ts +27 -0
- package/dist/components/OnePasswordSelector.model.d.ts.map +1 -0
- package/dist/components/OnePasswordSelector.model.js +31 -0
- package/dist/components/OnePasswordSelector.model.js.map +1 -0
- package/dist/components/SecretFormField.cjs +142 -0
- package/dist/components/SecretFormField.cjs.map +1 -0
- package/dist/components/SecretFormField.d.ts +9 -0
- package/dist/components/SecretFormField.d.ts.map +1 -0
- package/dist/components/SecretFormField.js +142 -0
- package/dist/components/SecretFormField.js.map +1 -0
- package/dist/components/SecretKeySelector.cjs +20 -14
- package/dist/components/SecretKeySelector.cjs.map +1 -1
- package/dist/components/SecretKeySelector.d.ts +4 -1
- package/dist/components/SecretKeySelector.d.ts.map +1 -1
- package/dist/components/SecretKeySelector.js +20 -14
- package/dist/components/SecretKeySelector.js.map +1 -1
- package/dist/components/TreePickerField.cjs +55 -29
- package/dist/components/TreePickerField.cjs.map +1 -1
- package/dist/components/TreePickerField.d.ts +10 -1
- package/dist/components/TreePickerField.d.ts.map +1 -1
- package/dist/components/TreePickerField.js +56 -30
- package/dist/components/TreePickerField.js.map +1 -1
- package/dist/components/combobox-types.d.ts +9 -0
- package/dist/components/combobox-types.d.ts.map +1 -1
- package/dist/components/filter-bar-utils.cjs +7 -0
- package/dist/components/filter-bar-utils.cjs.map +1 -1
- package/dist/components/filter-bar-utils.d.ts.map +1 -1
- package/dist/components/filter-bar-utils.js +7 -0
- package/dist/components/filter-bar-utils.js.map +1 -1
- package/dist/components/jotai-bindings-core.cjs.map +1 -1
- package/dist/components/jotai-bindings-core.d.ts +4 -1
- package/dist/components/jotai-bindings-core.d.ts.map +1 -1
- package/dist/components/jotai-bindings-core.js.map +1 -1
- package/dist/components/json-schema-form-render.cjs +2 -1
- package/dist/components/json-schema-form-render.cjs.map +1 -1
- package/dist/components/json-schema-form-render.d.ts.map +1 -1
- package/dist/components/json-schema-form-render.js +2 -1
- package/dist/components/json-schema-form-render.js.map +1 -1
- package/dist/components/json-schema-form-types.d.ts +9 -0
- package/dist/components/json-schema-form-types.d.ts.map +1 -1
- package/dist/components/jsonPathTree.cjs +189 -0
- package/dist/components/jsonPathTree.cjs.map +1 -0
- package/dist/components/jsonPathTree.d.ts +92 -0
- package/dist/components/jsonPathTree.d.ts.map +1 -0
- package/dist/components/jsonPathTree.js +189 -0
- package/dist/components/jsonPathTree.js.map +1 -0
- package/dist/components/secret-form-extension.cjs +30 -0
- package/dist/components/secret-form-extension.cjs.map +1 -0
- package/dist/components/secret-form-extension.d.ts +23 -0
- package/dist/components/secret-form-extension.d.ts.map +1 -0
- package/dist/components/secret-form-extension.js +30 -0
- package/dist/components/secret-form-extension.js.map +1 -0
- package/dist/components.cjs +16 -0
- package/dist/components.cjs.map +1 -1
- package/dist/components.d.ts +6 -0
- package/dist/components.d.ts.map +1 -1
- package/dist/components.js +16 -0
- package/dist/components.js.map +1 -1
- package/dist/data/TaskExecDetails.cjs +40 -0
- package/dist/data/TaskExecDetails.cjs.map +1 -0
- package/dist/data/TaskExecDetails.d.ts +5 -0
- package/dist/data/TaskExecDetails.d.ts.map +1 -0
- package/dist/data/TaskExecDetails.js +40 -0
- package/dist/data/TaskExecDetails.js.map +1 -0
- package/dist/data/TaskProgress.cjs +9 -3
- package/dist/data/TaskProgress.cjs.map +1 -1
- package/dist/data/TaskProgress.d.ts.map +1 -1
- package/dist/data/TaskProgress.js +9 -3
- package/dist/data/TaskProgress.js.map +1 -1
- package/dist/data/TaskSnapshot.cjs.map +1 -1
- package/dist/data/TaskSnapshot.d.ts +12 -1
- package/dist/data/TaskSnapshot.d.ts.map +1 -1
- package/dist/data/TaskSnapshot.js.map +1 -1
- package/dist/data/TreeNode.cjs +3 -0
- package/dist/data/TreeNode.cjs.map +1 -1
- package/dist/data/TreeNode.d.ts.map +1 -1
- package/dist/data/TreeNode.js +3 -0
- package/dist/data/TreeNode.js.map +1 -1
- package/dist/data/data-table-filter-values.cjs +20 -0
- package/dist/data/data-table-filter-values.cjs.map +1 -1
- package/dist/data/data-table-filter-values.d.ts +16 -0
- package/dist/data/data-table-filter-values.d.ts.map +1 -1
- package/dist/data/data-table-filter-values.js +20 -0
- package/dist/data/data-table-filter-values.js.map +1 -1
- package/dist/data/data-table-server-filters.cjs +23 -29
- package/dist/data/data-table-server-filters.cjs.map +1 -1
- package/dist/data/data-table-server-filters.d.ts.map +1 -1
- package/dist/data/data-table-server-filters.js +21 -27
- package/dist/data/data-table-server-filters.js.map +1 -1
- package/dist/data/query-browser/QueryBrowser.cjs +129 -157
- package/dist/data/query-browser/QueryBrowser.cjs.map +1 -1
- package/dist/data/query-browser/QueryBrowser.d.ts +1 -71
- package/dist/data/query-browser/QueryBrowser.d.ts.map +1 -1
- package/dist/data/query-browser/QueryBrowser.editor.cjs +88 -0
- package/dist/data/query-browser/QueryBrowser.editor.cjs.map +1 -0
- package/dist/data/query-browser/QueryBrowser.editor.d.ts +12 -0
- package/dist/data/query-browser/QueryBrowser.editor.d.ts.map +1 -0
- package/dist/data/query-browser/QueryBrowser.editor.js +88 -0
- package/dist/data/query-browser/QueryBrowser.editor.js.map +1 -0
- package/dist/data/query-browser/QueryBrowser.js +130 -158
- package/dist/data/query-browser/QueryBrowser.js.map +1 -1
- package/dist/data/query-browser/QueryBrowser.types.cjs +11 -0
- package/dist/data/query-browser/QueryBrowser.types.cjs.map +1 -0
- package/dist/data/query-browser/QueryBrowser.types.d.ts +92 -0
- package/dist/data/query-browser/QueryBrowser.types.d.ts.map +1 -0
- package/dist/data/query-browser/QueryBrowser.types.js +11 -0
- package/dist/data/query-browser/QueryBrowser.types.js.map +1 -0
- package/dist/data/query-browser/QueryBrowserDiagnosticsPanel.cjs +56 -0
- package/dist/data/query-browser/QueryBrowserDiagnosticsPanel.cjs.map +1 -0
- package/dist/data/query-browser/QueryBrowserDiagnosticsPanel.d.ts +5 -0
- package/dist/data/query-browser/QueryBrowserDiagnosticsPanel.d.ts.map +1 -0
- package/dist/data/query-browser/QueryBrowserDiagnosticsPanel.js +56 -0
- package/dist/data/query-browser/QueryBrowserDiagnosticsPanel.js.map +1 -0
- package/dist/data/query-browser/QueryBrowserResults.cjs +80 -0
- package/dist/data/query-browser/QueryBrowserResults.cjs.map +1 -0
- package/dist/data/query-browser/QueryBrowserResults.d.ts +16 -0
- package/dist/data/query-browser/QueryBrowserResults.d.ts.map +1 -0
- package/dist/data/query-browser/QueryBrowserResults.js +80 -0
- package/dist/data/query-browser/QueryBrowserResults.js.map +1 -0
- package/dist/data/query-browser/index.d.ts +2 -1
- package/dist/data/query-browser/index.d.ts.map +1 -1
- package/dist/data/task-exec-details.cjs +9 -0
- package/dist/data/task-exec-details.cjs.map +1 -0
- package/dist/data/task-exec-details.d.ts +3 -0
- package/dist/data/task-exec-details.d.ts.map +1 -0
- package/dist/data/task-exec-details.js +9 -0
- package/dist/data/task-exec-details.js.map +1 -0
- package/dist/data/version-info.cjs +3 -3
- package/dist/data/version-info.js +3 -3
- package/dist/data.cjs +2 -0
- package/dist/data.cjs.map +1 -1
- package/dist/data.d.ts +1 -1
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +2 -0
- package/dist/data.js.map +1 -1
- package/dist/index.cjs +18 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -1
- package/dist/rpc/FilterForm.cjs +20 -0
- package/dist/rpc/FilterForm.cjs.map +1 -1
- package/dist/rpc/FilterForm.js +20 -0
- package/dist/rpc/FilterForm.js.map +1 -1
- package/dist/rpc/formMetadata.cjs +34 -0
- package/dist/rpc/formMetadata.cjs.map +1 -1
- package/dist/rpc/formMetadata.d.ts.map +1 -1
- package/dist/rpc/formMetadata.js +35 -1
- package/dist/rpc/formMetadata.js.map +1 -1
- package/dist/rpc/types.cjs.map +1 -1
- package/dist/rpc/types.d.ts +9 -1
- package/dist/rpc/types.d.ts.map +1 -1
- package/dist/rpc/types.js.map +1 -1
- package/dist/styles.css +1 -1
- 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,+
|
|
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":";;;;;;;AAYO,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAiBG;AACD,SAAO;AAAA,IACL;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,IAAI;AAAA,QACJ,KAAK;AAAA,QACL,MAAK;AAAA,QACL,wBAAsB,YAAY;AAAA,QAClC,OAAO;AAAA,UACL,UAAU;AAAA,UACV,GAAI,QAAQ,OAAO,OACf,EAAE,KAAK,QAAQ,QACf,EAAE,QAAQ,QAAQ,OAAA;AAAA,UACtB,MAAM,QAAQ;AAAA,UACd,UAAU,QAAQ;AAAA,UAClB,UAAU,QAAQ;AAAA,UAClB,WAAW,QAAQ;AAAA,UACnB,QAAQ;AAAA,QAAA;AAAA,QAEV,WAAU;AAAA,QAET,UAAA;AAAA,UAAA,WAAW,SAAS,WAAW,yBAC7B,OAAA,EAAI,WAAU,uDAAsD,UAAA,WAAA,CAErE;AAAA,UAED,CAAC,WAAW,SAAS,WAAW,KAAK,CAAC,eACrC,oBAAC,OAAA,EAAI,WAAU,uDAAsD,UAAA,aAAA,CAErE;AAAA,UAED,SAAS,IAAI,CAAC,QAAQ,UAAU;;AAC/B,kBAAM,WAAW,WAAW,OAAO,KAAK;AACxC,kBAAM,OAAO,WAAW,MAAM,OAAO,KAAK,IAAI;AAC9C,kBAAM,aACJ,OAAO,SAAS,QAChB,OAAO,YAAU,cAAS,QAAQ,CAAC,MAAlB,mBAAqB;AACxC,mBACE,qBAACA,UAAA,EACE,UAAA;AAAA,cAAA,cACC;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,MAAK;AAAA,kBACL,WAAU;AAAA,kBAET,UAAA,OAAO;AAAA,gBAAA;AAAA,cAAA;AAAA,cAGZ;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,IAAI,SAAS,GAAG,MAAM,IAAI,KAAK,KAAK;AAAA,kBACpC,MAAK;AAAA,kBACL,iBAAe,WAAW,QAAQ,OAAO;AAAA,kBACzC,iBAAe,OAAO;AAAA,kBACrB,GAAI,QAAQ,OACT;AAAA,oBACE,cAAc,GAAG,OAAO,KAAK,KAC3B,SAAS,YAAY,aAAa,UACpC;AAAA,kBAAA,IAEF,CAAA;AAAA,kBACH,GAAI,OAAO,UAAU,SAAY,EAAE,OAAO,OAAO,MAAA,IAAU,CAAA;AAAA,kBAC3D,GAAI,WACD,EAAE,sBAAsB,OAAO,MAAA,IAC/B,CAAA;AAAA,kBACJ,aAAa,CAAC,UAAU;AACtB,0BAAM,eAAA;AACN,wBAAI,CAAC,YAAY,CAAC,OAAO,mBAAmB,MAAM;AAAA,kBACpD;AAAA,kBACC,GAAI,WACD;AAAA,oBACE,SAAS,MAAM;AACb,0BAAI,CAAC,OAAO,SAAU,UAAS,MAAM;AAAA,oBACvC;AAAA,kBAAA,IAEF,CAAA;AAAA,kBACJ,cAAc,MAAM,YAAY,KAAK;AAAA,kBACrC,WAAW;AAAA,oBACT;AAAA,oBACA,OAAO,cAAc,gBAAgB;AAAA,oBACrC,UAAU,eAAe;AAAA,oBACzB,YAAY,CAAC,YAAY;AAAA,oBACzB,OAAO,YAAY;AAAA,kBAAA;AAAA,kBAGpB,UAAA,WACC,qBAAC,OAAA,EAAI,WAAU,kBACb,UAAA;AAAA,oBAAA;AAAA,sBAAC;AAAA,sBAAA;AAAA,wBACC,MAAM,QAAQ;AAAA,wBACd,gBAAe;AAAA,wBACf,aAAa;AAAA,wBACb,OAAO,OAAO;AAAA,wBACd,cAAc,CAAC,SAAS,UAAU,OAAO,OAAO,IAAI;AAAA,wBACpD,WAAU;AAAA,sBAAA;AAAA,oBAAA;AAAA,oBAEZ,oBAAC,2BAAA,EAA0B,aAAa,OAAO,YAAA,CAAa;AAAA,kBAAA,EAAA,CAC9D,IAEA,qBAAAA,YAAA,EACE,UAAA;AAAA,oBAAA;AAAA,sBAAC;AAAA,sBAAA;AAAA,wBACC,MAAM;AAAA,wBACN,WAAW;AAAA,0BACT;AAAA,0BACA,OAAO,eAAe;AAAA,0BACtB,WAAW,gBAAgB;AAAA,wBAAA;AAAA,sBAC7B;AAAA,oBAAA;AAAA,oBAEF;AAAA,sBAAC;AAAA,sBAAA;AAAA,wBACC,MAAM,OAAO;AAAA,wBACb,WAAW;AAAA,0BACT;AAAA,0BACA,OAAO,eAAe;AAAA,wBAAA;AAAA,sBACxB;AAAA,oBAAA;AAAA,oBAEF,oBAAC,sBAAmB,OAAA,CAAgB;AAAA,kBAAA,EAAA,CACtC;AAAA,gBAAA;AAAA,cAAA;AAAA,YAEJ,EAAA,GA7Ea,OAAO,KA8EtB;AAAA,UAEJ,CAAC;AAAA,UACA,eACC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,IAAI,SAAS,GAAG,MAAM,IAAI,SAAS,MAAM,KAAK;AAAA,cAC9C,MAAK;AAAA,cACL,iBAAe;AAAA,cACf,0BAAwB,YAAY;AAAA,cACpC,OAAO,YAAY;AAAA,cACnB,aAAa,CAAC,UAAU,MAAM,eAAA;AAAA,cAC9B,SAAS,MAAM,SAAS,WAAW;AAAA,cACnC,cAAc,MAAM,YAAY,SAAS,MAAM;AAAA,cAC/C,WAAW;AAAA,gBACT;AAAA,gBACA,gBAAgB,SAAS,UAAU;AAAA,cAAA;AAAA,cAGrC,UAAA;AAAA,gBAAA;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,MAAM,YAAY;AAAA,oBAClB,WAAU;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAEZ,oBAAC,QAAA,EAAK,WAAU,oBAAoB,sBAAY,MAAA,CAAM;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAGzD,UAAU,QACT,oBAAC,OAAA,EAAI,WAAU,6DACZ,UAAA,OAAA,CACH;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,IAGJ,SAAS;AAAA,EAAA;AAEb;AAEA,SAAS,mBAAmB,EAAE,UAAsC;AAClE,SACE,qBAAC,QAAA,EAAK,WAAU,kBACd,UAAA;AAAA,IAAA,oBAAC,QAAA,EAAK,WAAU,kBAAkB,UAAA,OAAO,OAAM;AAAA,IAC/C,oBAAC,2BAAA,EAA0B,aAAa,OAAO,YAAA,CAAa;AAAA,EAAA,GAC9D;AAEJ;AAEA,SAAS,0BAA0B,EAAE,eAAoD;AACvF,SAAO,cACL,oBAAC,QAAA,EAAK,WAAU,wFACb,uBACH,IACE;AACN;"}
|
|
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":"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"}
|
|
@@ -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;
|
|
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;
|