@pipe0/react 0.2.4 → 0.2.6
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/CHANGELOG.md +16 -0
- package/dist/components/defaults/adapters/context-select-input.mjs +161 -0
- package/dist/components/defaults/adapters/context-select-input.mjs.map +1 -1
- package/dist/components/defaults/adapters/field-select-input.mjs +33 -0
- package/dist/components/defaults/adapters/field-select-input.mjs.map +1 -0
- package/dist/components/defaults/adapters/index.d.mts.map +1 -1
- package/dist/components/defaults/adapters/index.mjs +4 -0
- package/dist/components/defaults/adapters/index.mjs.map +1 -1
- package/dist/components/defaults/adapters/pipes-run-if-input.mjs +53 -5
- package/dist/components/defaults/adapters/pipes-run-if-input.mjs.map +1 -1
- package/dist/components/defaults/adapters/tagged-ordered-multi-create-input.mjs.map +1 -1
- package/dist/components/defaults/adapters/typed-fields-select-input.mjs +48 -0
- package/dist/components/defaults/adapters/typed-fields-select-input.mjs.map +1 -0
- package/dist/components/internal/combobox/suggest-combobox.mjs +35 -6
- package/dist/components/internal/combobox/suggest-combobox.mjs.map +1 -1
- package/dist/hooks/use-effect-catalog-table.d.mts.map +1 -1
- package/dist/hooks/use-effect-catalog-table.mjs +18 -11
- package/dist/hooks/use-effect-catalog-table.mjs.map +1 -1
- package/dist/hooks/use-form-core.d.mts.map +1 -1
- package/dist/hooks/use-form-core.mjs +48 -8
- package/dist/hooks/use-form-core.mjs.map +1 -1
- package/dist/hooks/use-pipe-catalog-table.d.mts +8 -8
- package/dist/hooks/use-pipe-catalog-table.d.mts.map +1 -1
- package/dist/hooks/use-pipe-catalog-table.mjs +20 -16
- package/dist/hooks/use-pipe-catalog-table.mjs.map +1 -1
- package/dist/hooks/use-search-catalog-table.d.mts +6 -6
- package/dist/hooks/use-search-catalog-table.d.mts.map +1 -1
- package/dist/hooks/use-search-catalog-table.mjs +20 -13
- package/dist/hooks/use-search-catalog-table.mjs.map +1 -1
- package/dist/hooks/use-searches-catalog-table.d.mts.map +1 -1
- package/dist/hooks/use-searches-catalog-table.mjs +20 -13
- package/dist/hooks/use-searches-catalog-table.mjs.map +1 -1
- package/dist/types/field-props.d.mts +37 -3
- package/dist/types/field-props.d.mts.map +1 -1
- package/dist/utils/build-section-handlers.mjs +21 -2
- package/dist/utils/build-section-handlers.mjs.map +1 -1
- package/dist/utils/catalog-helpers.mjs +10 -1
- package/dist/utils/catalog-helpers.mjs.map +1 -1
- package/package.json +2 -2
|
@@ -1,23 +1,20 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { catalogSearchFilter, catalogSearchSort } from "../utils/catalog-helpers.mjs";
|
|
2
2
|
import { useDebounce } from "./use-debounce.mjs";
|
|
3
3
|
import { useCallback, useMemo, useState } from "react";
|
|
4
|
-
import { filterSearchEntries, getDefaultSearchOutputFields, getInitialSearchTableData, getLoweestSearchCreditAmount, getSearchTableDataAggregates, getStartingCostPerSearchProvider } from "@pipe0/base";
|
|
5
|
-
import { createColumnHelper, getCoreRowModel, getFilteredRowModel, useReactTable } from "@tanstack/react-table";
|
|
4
|
+
import { filterSearchEntries, getDefaultSearchOutputFields, getInitialSearchTableData, getLoweestSearchCreditAmount, getSearchSearchTarget, getSearchTableDataAggregates, getStartingCostPerSearchProvider } from "@pipe0/base";
|
|
5
|
+
import { createColumnHelper, getCoreRowModel, getFilteredRowModel, getSortedRowModel, useReactTable } from "@tanstack/react-table";
|
|
6
6
|
|
|
7
7
|
//#region src/hooks/use-search-catalog-table.ts
|
|
8
8
|
const columnHelper = createColumnHelper();
|
|
9
9
|
const columns = [
|
|
10
10
|
columnHelper.accessor("searchId", {
|
|
11
11
|
filterFn: "includesString",
|
|
12
|
-
enableGlobalFilter:
|
|
13
|
-
}),
|
|
14
|
-
columnHelper.accessor("description", {
|
|
15
|
-
filterFn: "fuzzy",
|
|
16
|
-
enableGlobalFilter: true
|
|
12
|
+
enableGlobalFilter: false
|
|
17
13
|
}),
|
|
14
|
+
columnHelper.accessor("description", { enableGlobalFilter: false }),
|
|
18
15
|
columnHelper.accessor("label", {
|
|
19
16
|
filterFn: "includesString",
|
|
20
|
-
enableGlobalFilter:
|
|
17
|
+
enableGlobalFilter: false
|
|
21
18
|
}),
|
|
22
19
|
columnHelper.accessor((row) => getDefaultSearchOutputFields(row.searchId) || [], {
|
|
23
20
|
id: "outputFields",
|
|
@@ -27,11 +24,17 @@ const columns = [
|
|
|
27
24
|
columnHelper.accessor((row) => row.tags || [], {
|
|
28
25
|
id: "tags",
|
|
29
26
|
filterFn: "arrIncludes",
|
|
30
|
-
enableGlobalFilter:
|
|
27
|
+
enableGlobalFilter: false
|
|
31
28
|
}),
|
|
32
29
|
columnHelper.accessor((row) => row.provider, {
|
|
33
30
|
id: "providers",
|
|
34
|
-
enableGlobalFilter:
|
|
31
|
+
enableGlobalFilter: false
|
|
32
|
+
}),
|
|
33
|
+
columnHelper.accessor((row) => getSearchSearchTarget(row), {
|
|
34
|
+
id: "search",
|
|
35
|
+
enableGlobalFilter: true,
|
|
36
|
+
enableSorting: true,
|
|
37
|
+
sortingFn: catalogSearchSort
|
|
35
38
|
})
|
|
36
39
|
];
|
|
37
40
|
function useSearchCatalogTable(config = {}) {
|
|
@@ -44,8 +47,8 @@ function useSearchCatalogTable(config = {}) {
|
|
|
44
47
|
data: initialSearchTableData,
|
|
45
48
|
getCoreRowModel: getCoreRowModel(),
|
|
46
49
|
getFilteredRowModel: getFilteredRowModel(),
|
|
47
|
-
|
|
48
|
-
|
|
50
|
+
getSortedRowModel: getSortedRowModel(),
|
|
51
|
+
globalFilterFn: catalogSearchFilter,
|
|
49
52
|
getColumnCanGlobalFilter: (column) => column.columnDef.enableGlobalFilter !== false,
|
|
50
53
|
initialState: {
|
|
51
54
|
columnFilters: initialColumnFilters,
|
|
@@ -57,6 +60,10 @@ function useSearchCatalogTable(config = {}) {
|
|
|
57
60
|
const [globalFilterInput, setGlobalFilterInput, setGlobalFilterImmediately] = useDebounce((v) => {
|
|
58
61
|
if (v === table.getState().globalFilter) return;
|
|
59
62
|
table.setGlobalFilter(v);
|
|
63
|
+
table.setSorting(v ? [{
|
|
64
|
+
id: "search",
|
|
65
|
+
desc: true
|
|
66
|
+
}] : []);
|
|
60
67
|
if (v) {
|
|
61
68
|
setCategory(null);
|
|
62
69
|
table.setColumnFilters([]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-search-catalog-table.mjs","names":[],"sources":["../../src/hooks/use-search-catalog-table.ts"],"sourcesContent":["import {\n type CatalogFilter,\n filterSearchEntries,\n getDefaultSearchOutputFields,\n getInitialSearchTableData,\n getLoweestSearchCreditAmount,\n getSearchTableDataAggregates,\n getStartingCostPerSearchProvider,\n type SearchCatalogEntry,\n type SearchCatalogTableData,\n type SearchCategory,\n type SearchId,\n} from \"@pipe0/base\";\nimport {\n type ColumnFilter,\n createColumnHelper,\n getCoreRowModel,\n getFilteredRowModel,\n useReactTable,\n} from \"@tanstack/react-table\";\nimport { useCallback, useMemo, useState } from \"react\";\nimport type { CostMode, SearchCardData } from \"../types/catalog-adapters.js\";\nimport { fuzzyFilter } from \"../utils/catalog-helpers.js\";\nimport { useDebounce } from \"./use-debounce.js\";\n\nexport type SearchOutputFieldEntries = Record<string, SearchId[]>;\n\nconst columnHelper = createColumnHelper<SearchCatalogTableData>();\n\nconst columns = [\n columnHelper.accessor(\"searchId\", {\n filterFn: \"includesString\",\n enableGlobalFilter: true,\n }),\n columnHelper.accessor(\"description\", {\n filterFn: \"fuzzy\" as any,\n enableGlobalFilter: true,\n }),\n columnHelper.accessor(\"label\", {\n filterFn: \"includesString\",\n enableGlobalFilter: true,\n }),\n columnHelper.accessor((row) => getDefaultSearchOutputFields(row.searchId) || [], {\n id: \"outputFields\",\n filterFn: \"arrIncludes\",\n enableGlobalFilter: false,\n }),\n columnHelper.accessor((row) => row.tags || [], {\n id: \"tags\",\n filterFn: \"arrIncludes\",\n enableGlobalFilter: true,\n }),\n columnHelper.accessor((row) => row.provider, {\n id: \"providers\",\n enableGlobalFilter: true,\n }),\n];\n\nexport function useSearchCatalogTable(\n config: {\n initialColumnFilters?: ColumnFilter[];\n /** Optional whitelist/blacklist of searches and providers. Memoize. */\n filter?: CatalogFilter;\n } = {},\n) {\n const [category, setCategory] = useState<SearchCategory | null>(null);\n const { initialColumnFilters = [] as ColumnFilter[], filter } = config;\n\n const initialSearchTableData = useMemo(\n () => filterSearchEntries(getInitialSearchTableData(category), filter),\n [category, filter],\n );\n\n // Baseline (config.filter applied, but no category / column / global filter).\n // Drives the stable category-button counts so the row doesn't jump.\n const baselineTableData = useMemo(\n () => filterSearchEntries(getInitialSearchTableData(null), filter),\n [filter],\n );\n\n const table = useReactTable({\n columns,\n data: initialSearchTableData,\n getCoreRowModel: getCoreRowModel(),\n getFilteredRowModel: getFilteredRowModel(),\n globalFilterFn: fuzzyFilter,\n filterFns: {\n fuzzy: fuzzyFilter,\n },\n getColumnCanGlobalFilter: (column) => column.columnDef.enableGlobalFilter !== false,\n initialState: {\n columnFilters: initialColumnFilters,\n pagination: {\n pageSize: 10,\n },\n },\n });\n\n const columnFilters = table.getState().columnFilters;\n\n const aggregates = useMemo(\n () => getSearchTableDataAggregates(initialSearchTableData, category),\n [category, initialSearchTableData],\n );\n\n const [globalFilterInput, setGlobalFilterInput, setGlobalFilterImmediately] = useDebounce((v) => {\n if (v === table.getState().globalFilter) return;\n table.setGlobalFilter(v);\n if (v) {\n setCategory(null);\n table.setColumnFilters([]);\n }\n });\n\n const addColumnFilter = useCallback(\n (id: \"inputFields\" | \"outputFields\" | \"tags\" | \"providers\", value: string) => {\n setGlobalFilterImmediately(\"\");\n table.setColumnFilters([{ id, value }]);\n },\n [setGlobalFilterImmediately, table],\n );\n\n const resetFilters = useCallback(() => {\n setGlobalFilterImmediately(\"\");\n setCategory(null);\n }, [setGlobalFilterImmediately]);\n\n const removeColumnFilter = useCallback(\n (id: \"inputFields\" | \"outputFields\" | \"tags\" | \"providers\") => {\n table.getColumn(id)?.setFilterValue(null);\n },\n [table],\n );\n\n const handleCategoryChange = useCallback(\n (category: SearchCategory | null) => {\n setCategory(category);\n table.setColumnFilters([]);\n setGlobalFilterImmediately(\"\");\n },\n [table, setGlobalFilterImmediately],\n );\n\n const getColumnFilterValue = useCallback(\n (id: \"inputFields\" | \"outputFields\" | \"tags\" | \"providers\") => {\n const res = columnFilters.find((f) => f.id === id)?.value;\n return res as string;\n },\n [columnFilters],\n );\n\n const rows = table.getRowModel().rows;\n const cards = useMemo<SearchCardData[]>(\n () =>\n rows.map((row) => {\n const entry = row.original;\n const latestEntry = (aggregates.searchEntriesByBaseSearch[entry.baseSearch]?.[0] ??\n entry) as SearchCatalogEntry & { searchId: SearchId };\n return {\n searchId: latestEntry.searchId,\n baseSearch: entry.baseSearch,\n label: entry.label,\n description: entry.description,\n provider: entry.provider,\n providers: [entry.provider],\n startingCostPerProvider: getStartingCostPerSearchProvider(latestEntry.searchId),\n startingCreditAmount: getLoweestSearchCreditAmount(latestEntry),\n costMode: (latestEntry.cost.mode ?? \"per_page\") as CostMode,\n defaultOutputFields: getDefaultSearchOutputFields(latestEntry.searchId),\n docPath: latestEntry.docPath,\n entry: entry as SearchCatalogTableData,\n latestEntry,\n };\n }),\n [rows, aggregates.searchEntriesByBaseSearch],\n );\n\n const cardsByCategory = useMemo<{ category: SearchCategory; cards: SearchCardData[] }[]>(() => {\n const groups = new Map<SearchCategory, SearchCardData[]>();\n for (const card of cards) {\n const cats = (card.entry.categories ?? []) as SearchCategory[];\n for (const cat of cats) {\n const arr = groups.get(cat);\n if (arr) arr.push(card);\n else groups.set(cat, [card]);\n }\n }\n return Array.from(groups, ([category, group]) => ({\n category,\n cards: group,\n }));\n }, [cards]);\n\n const categoryCounts = useMemo<Partial<Record<SearchCategory, number>>>(() => {\n const counts: Partial<Record<SearchCategory, number>> = {};\n for (const card of cards) {\n const cats = (card.entry.categories ?? []) as SearchCategory[];\n for (const cat of cats) {\n counts[cat] = (counts[cat] ?? 0) + 1;\n }\n }\n return counts;\n }, [cards]);\n\n // Stable counts based on the baseline (no category / column / global filter\n // applied).\n const baselineCardCount = baselineTableData.length;\n const baselineCategoryCounts = useMemo<Partial<Record<SearchCategory, number>>>(() => {\n const counts: Partial<Record<SearchCategory, number>> = {};\n for (const entry of baselineTableData) {\n const cats = (entry.categories ?? []) as SearchCategory[];\n for (const cat of cats) {\n counts[cat] = (counts[cat] ?? 0) + 1;\n }\n }\n return counts;\n }, [baselineTableData]);\n\n return {\n table,\n cards,\n cardsByCategory,\n categoryCounts,\n baselineCardCount,\n baselineCategoryCounts,\n\n category,\n setCategory: handleCategoryChange,\n globalFilterInput,\n setGlobalFilterInput,\n\n addColumnFilter,\n removeColumnFilter,\n resetFilters,\n getColumnFilterValue,\n\n sortedOutputFieldEntries: aggregates.sortedOutputFieldEntries,\n sortedTagEntries: aggregates.sortedTagEntries,\n sortedProviderEntries: aggregates.sortedProviderEntries,\n\n searchIdsByOutputField: aggregates.searchIdsByOutputField,\n searchIdsByProvider: aggregates.searchIdsByProvider,\n searchIdsByTag: aggregates.searchIdsByTag,\n };\n}\n\nexport type UseSearchCatalogTableReturn = ReturnType<typeof useSearchCatalogTable>;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"use-search-catalog-table.mjs","names":[],"sources":["../../src/hooks/use-search-catalog-table.ts"],"sourcesContent":["import {\n type CatalogFilter,\n filterSearchEntries,\n getDefaultSearchOutputFields,\n getInitialSearchTableData,\n getLoweestSearchCreditAmount,\n getSearchSearchTarget,\n getSearchTableDataAggregates,\n getStartingCostPerSearchProvider,\n type SearchCatalogEntry,\n type SearchCatalogTableData,\n type SearchCategory,\n type SearchId,\n} from \"@pipe0/base\";\nimport {\n type ColumnFilter,\n createColumnHelper,\n getCoreRowModel,\n getFilteredRowModel,\n getSortedRowModel,\n useReactTable,\n} from \"@tanstack/react-table\";\nimport { useCallback, useMemo, useState } from \"react\";\nimport type { CostMode, SearchCardData } from \"../types/catalog-adapters.js\";\nimport { catalogSearchFilter, catalogSearchSort } from \"../utils/catalog-helpers.js\";\nimport { useDebounce } from \"./use-debounce.js\";\n\nexport type SearchOutputFieldEntries = Record<string, SearchId[]>;\n\nconst columnHelper = createColumnHelper<SearchCatalogTableData>();\n\nconst columns = [\n columnHelper.accessor(\"searchId\", {\n filterFn: \"includesString\",\n enableGlobalFilter: false,\n }),\n columnHelper.accessor(\"description\", {\n enableGlobalFilter: false,\n }),\n columnHelper.accessor(\"label\", {\n filterFn: \"includesString\",\n enableGlobalFilter: false,\n }),\n columnHelper.accessor((row) => getDefaultSearchOutputFields(row.searchId) || [], {\n id: \"outputFields\",\n filterFn: \"arrIncludes\",\n enableGlobalFilter: false,\n }),\n columnHelper.accessor((row) => row.tags || [], {\n id: \"tags\",\n filterFn: \"arrIncludes\",\n enableGlobalFilter: false,\n }),\n columnHelper.accessor((row) => row.provider, {\n id: \"providers\",\n enableGlobalFilter: false,\n }),\n // Hidden relevance column — the ONLY globally-filterable one, so the global\n // filter scores each row exactly once and catalogSearchSort can read the\n // score back from this column's filter meta.\n columnHelper.accessor((row) => getSearchSearchTarget(row), {\n id: \"search\",\n enableGlobalFilter: true,\n enableSorting: true,\n sortingFn: catalogSearchSort,\n }),\n];\n\nexport function useSearchCatalogTable(\n config: {\n initialColumnFilters?: ColumnFilter[];\n /** Optional whitelist/blacklist of searches and providers. Memoize. */\n filter?: CatalogFilter;\n } = {},\n) {\n const [category, setCategory] = useState<SearchCategory | null>(null);\n const { initialColumnFilters = [] as ColumnFilter[], filter } = config;\n\n const initialSearchTableData = useMemo(\n () => filterSearchEntries(getInitialSearchTableData(category), filter),\n [category, filter],\n );\n\n // Baseline (config.filter applied, but no category / column / global filter).\n // Drives the stable category-button counts so the row doesn't jump.\n const baselineTableData = useMemo(\n () => filterSearchEntries(getInitialSearchTableData(null), filter),\n [filter],\n );\n\n const table = useReactTable({\n columns,\n data: initialSearchTableData,\n getCoreRowModel: getCoreRowModel(),\n getFilteredRowModel: getFilteredRowModel(),\n getSortedRowModel: getSortedRowModel(),\n globalFilterFn: catalogSearchFilter,\n getColumnCanGlobalFilter: (column) => column.columnDef.enableGlobalFilter !== false,\n initialState: {\n columnFilters: initialColumnFilters,\n pagination: {\n pageSize: 10,\n },\n },\n });\n\n const columnFilters = table.getState().columnFilters;\n\n const aggregates = useMemo(\n () => getSearchTableDataAggregates(initialSearchTableData, category),\n [category, initialSearchTableData],\n );\n\n const [globalFilterInput, setGlobalFilterInput, setGlobalFilterImmediately] = useDebounce((v) => {\n if (v === table.getState().globalFilter) return;\n table.setGlobalFilter(v);\n // Relevance order only while a query is active; empty query restores\n // catalog order.\n table.setSorting(v ? [{ id: \"search\", desc: true }] : []);\n if (v) {\n setCategory(null);\n table.setColumnFilters([]);\n }\n });\n\n const addColumnFilter = useCallback(\n (id: \"inputFields\" | \"outputFields\" | \"tags\" | \"providers\", value: string) => {\n setGlobalFilterImmediately(\"\");\n table.setColumnFilters([{ id, value }]);\n },\n [setGlobalFilterImmediately, table],\n );\n\n const resetFilters = useCallback(() => {\n setGlobalFilterImmediately(\"\");\n setCategory(null);\n }, [setGlobalFilterImmediately]);\n\n const removeColumnFilter = useCallback(\n (id: \"inputFields\" | \"outputFields\" | \"tags\" | \"providers\") => {\n table.getColumn(id)?.setFilterValue(null);\n },\n [table],\n );\n\n const handleCategoryChange = useCallback(\n (category: SearchCategory | null) => {\n setCategory(category);\n table.setColumnFilters([]);\n setGlobalFilterImmediately(\"\");\n },\n [table, setGlobalFilterImmediately],\n );\n\n const getColumnFilterValue = useCallback(\n (id: \"inputFields\" | \"outputFields\" | \"tags\" | \"providers\") => {\n const res = columnFilters.find((f) => f.id === id)?.value;\n return res as string;\n },\n [columnFilters],\n );\n\n const rows = table.getRowModel().rows;\n const cards = useMemo<SearchCardData[]>(\n () =>\n rows.map((row) => {\n const entry = row.original;\n const latestEntry = (aggregates.searchEntriesByBaseSearch[entry.baseSearch]?.[0] ??\n entry) as SearchCatalogEntry & { searchId: SearchId };\n return {\n searchId: latestEntry.searchId,\n baseSearch: entry.baseSearch,\n label: entry.label,\n description: entry.description,\n provider: entry.provider,\n providers: [entry.provider],\n startingCostPerProvider: getStartingCostPerSearchProvider(latestEntry.searchId),\n startingCreditAmount: getLoweestSearchCreditAmount(latestEntry),\n costMode: (latestEntry.cost.mode ?? \"per_page\") as CostMode,\n defaultOutputFields: getDefaultSearchOutputFields(latestEntry.searchId),\n docPath: latestEntry.docPath,\n entry: entry as SearchCatalogTableData,\n latestEntry,\n };\n }),\n [rows, aggregates.searchEntriesByBaseSearch],\n );\n\n const cardsByCategory = useMemo<{ category: SearchCategory; cards: SearchCardData[] }[]>(() => {\n const groups = new Map<SearchCategory, SearchCardData[]>();\n for (const card of cards) {\n const cats = (card.entry.categories ?? []) as SearchCategory[];\n for (const cat of cats) {\n const arr = groups.get(cat);\n if (arr) arr.push(card);\n else groups.set(cat, [card]);\n }\n }\n return Array.from(groups, ([category, group]) => ({\n category,\n cards: group,\n }));\n }, [cards]);\n\n const categoryCounts = useMemo<Partial<Record<SearchCategory, number>>>(() => {\n const counts: Partial<Record<SearchCategory, number>> = {};\n for (const card of cards) {\n const cats = (card.entry.categories ?? []) as SearchCategory[];\n for (const cat of cats) {\n counts[cat] = (counts[cat] ?? 0) + 1;\n }\n }\n return counts;\n }, [cards]);\n\n // Stable counts based on the baseline (no category / column / global filter\n // applied).\n const baselineCardCount = baselineTableData.length;\n const baselineCategoryCounts = useMemo<Partial<Record<SearchCategory, number>>>(() => {\n const counts: Partial<Record<SearchCategory, number>> = {};\n for (const entry of baselineTableData) {\n const cats = (entry.categories ?? []) as SearchCategory[];\n for (const cat of cats) {\n counts[cat] = (counts[cat] ?? 0) + 1;\n }\n }\n return counts;\n }, [baselineTableData]);\n\n return {\n table,\n cards,\n cardsByCategory,\n categoryCounts,\n baselineCardCount,\n baselineCategoryCounts,\n\n category,\n setCategory: handleCategoryChange,\n globalFilterInput,\n setGlobalFilterInput,\n\n addColumnFilter,\n removeColumnFilter,\n resetFilters,\n getColumnFilterValue,\n\n sortedOutputFieldEntries: aggregates.sortedOutputFieldEntries,\n sortedTagEntries: aggregates.sortedTagEntries,\n sortedProviderEntries: aggregates.sortedProviderEntries,\n\n searchIdsByOutputField: aggregates.searchIdsByOutputField,\n searchIdsByProvider: aggregates.searchIdsByProvider,\n searchIdsByTag: aggregates.searchIdsByTag,\n };\n}\n\nexport type UseSearchCatalogTableReturn = ReturnType<typeof useSearchCatalogTable>;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-searches-catalog-table.d.mts","names":[],"sources":["../../src/hooks/use-searches-catalog-table.ts"],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"use-searches-catalog-table.d.mts","names":[],"sources":["../../src/hooks/use-searches-catalog-table.ts"],"mappings":";;;;;;;KA2BY,0BAAA,GAA6B,MAAA,SAAe,UAAA;AAAA,iBAyCxC,uBAAA,CACd,MAAA;EAAU,oBAAA,GAAuB,YAAA;EAAgB,MAAA,GAAS,aAAA;AAAA;;;;cAmHd,cAAA;WAAuB,gBAAA;EAAA;;;;;0BA1CtD,cAAA;;yCAAc,OAAA,CAAA,cAAA;+EApBiC,KAAA;;;;;;;;;;;KAmIlD,6BAAA,GAAgC,UAAA,QAAkB,uBAAA"}
|
|
@@ -1,23 +1,20 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { catalogSearchFilter, catalogSearchSort } from "../utils/catalog-helpers.mjs";
|
|
2
2
|
import { useDebounce } from "./use-debounce.mjs";
|
|
3
3
|
import { useCallback, useMemo, useState } from "react";
|
|
4
|
-
import { filterSearchesEntries, getDefaultSearchesOutputFields, getInitialSearchesTableData, getLoweestSearchesCreditAmount, getSearchesTableDataAggregates, getStartingCostPerSearchesProvider } from "@pipe0/base";
|
|
5
|
-
import { createColumnHelper, getCoreRowModel, getFilteredRowModel, useReactTable } from "@tanstack/react-table";
|
|
4
|
+
import { filterSearchesEntries, getDefaultSearchesOutputFields, getInitialSearchesTableData, getLoweestSearchesCreditAmount, getSearchesSearchTarget, getSearchesTableDataAggregates, getStartingCostPerSearchesProvider } from "@pipe0/base";
|
|
5
|
+
import { createColumnHelper, getCoreRowModel, getFilteredRowModel, getSortedRowModel, useReactTable } from "@tanstack/react-table";
|
|
6
6
|
|
|
7
7
|
//#region src/hooks/use-searches-catalog-table.ts
|
|
8
8
|
const columnHelper = createColumnHelper();
|
|
9
9
|
const columns = [
|
|
10
10
|
columnHelper.accessor("searchId", {
|
|
11
11
|
filterFn: "includesString",
|
|
12
|
-
enableGlobalFilter:
|
|
13
|
-
}),
|
|
14
|
-
columnHelper.accessor("description", {
|
|
15
|
-
filterFn: "fuzzy",
|
|
16
|
-
enableGlobalFilter: true
|
|
12
|
+
enableGlobalFilter: false
|
|
17
13
|
}),
|
|
14
|
+
columnHelper.accessor("description", { enableGlobalFilter: false }),
|
|
18
15
|
columnHelper.accessor("label", {
|
|
19
16
|
filterFn: "includesString",
|
|
20
|
-
enableGlobalFilter:
|
|
17
|
+
enableGlobalFilter: false
|
|
21
18
|
}),
|
|
22
19
|
columnHelper.accessor((row) => getDefaultSearchesOutputFields(row.searchId) || [], {
|
|
23
20
|
id: "outputFields",
|
|
@@ -27,11 +24,17 @@ const columns = [
|
|
|
27
24
|
columnHelper.accessor((row) => row.tags || [], {
|
|
28
25
|
id: "tags",
|
|
29
26
|
filterFn: "arrIncludes",
|
|
30
|
-
enableGlobalFilter:
|
|
27
|
+
enableGlobalFilter: false
|
|
31
28
|
}),
|
|
32
29
|
columnHelper.accessor((row) => row.provider, {
|
|
33
30
|
id: "providers",
|
|
34
|
-
enableGlobalFilter:
|
|
31
|
+
enableGlobalFilter: false
|
|
32
|
+
}),
|
|
33
|
+
columnHelper.accessor((row) => getSearchesSearchTarget(row), {
|
|
34
|
+
id: "search",
|
|
35
|
+
enableGlobalFilter: true,
|
|
36
|
+
enableSorting: true,
|
|
37
|
+
sortingFn: catalogSearchSort
|
|
35
38
|
})
|
|
36
39
|
];
|
|
37
40
|
function useSearchesCatalogTable(config = {}) {
|
|
@@ -44,8 +47,8 @@ function useSearchesCatalogTable(config = {}) {
|
|
|
44
47
|
data: initialSearchTableData,
|
|
45
48
|
getCoreRowModel: getCoreRowModel(),
|
|
46
49
|
getFilteredRowModel: getFilteredRowModel(),
|
|
47
|
-
|
|
48
|
-
|
|
50
|
+
getSortedRowModel: getSortedRowModel(),
|
|
51
|
+
globalFilterFn: catalogSearchFilter,
|
|
49
52
|
getColumnCanGlobalFilter: (column) => column.columnDef.enableGlobalFilter !== false,
|
|
50
53
|
initialState: {
|
|
51
54
|
columnFilters: initialColumnFilters,
|
|
@@ -57,6 +60,10 @@ function useSearchesCatalogTable(config = {}) {
|
|
|
57
60
|
const [globalFilterInput, setGlobalFilterInput, setGlobalFilterImmediately] = useDebounce((v) => {
|
|
58
61
|
if (v === table.getState().globalFilter) return;
|
|
59
62
|
table.setGlobalFilter(v);
|
|
63
|
+
table.setSorting(v ? [{
|
|
64
|
+
id: "search",
|
|
65
|
+
desc: true
|
|
66
|
+
}] : []);
|
|
60
67
|
if (v) {
|
|
61
68
|
setCategory(null);
|
|
62
69
|
table.setColumnFilters([]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-searches-catalog-table.mjs","names":[],"sources":["../../src/hooks/use-searches-catalog-table.ts"],"sourcesContent":["import {\n type CatalogFilter,\n filterSearchesEntries,\n getDefaultSearchesOutputFields,\n getInitialSearchesTableData,\n getLoweestSearchesCreditAmount,\n getSearchesTableDataAggregates,\n getStartingCostPerSearchesProvider,\n type SearchCategory,\n type SearchesCatalogEntry,\n type SearchesCatalogTableData,\n type SearchesId,\n} from \"@pipe0/base\";\nimport {\n type ColumnFilter,\n createColumnHelper,\n getCoreRowModel,\n getFilteredRowModel,\n useReactTable,\n} from \"@tanstack/react-table\";\nimport { useCallback, useMemo, useState } from \"react\";\nimport type { CostMode, SearchesCardData } from \"../types/catalog-adapters.js\";\nimport { fuzzyFilter } from \"../utils/catalog-helpers.js\";\nimport { useDebounce } from \"./use-debounce.js\";\n\nexport type SearchesOutputFieldEntries = Record<string, SearchesId[]>;\n\nconst columnHelper = createColumnHelper<SearchesCatalogTableData>();\n\nconst columns = [\n columnHelper.accessor(\"searchId\", {\n filterFn: \"includesString\",\n enableGlobalFilter: true,\n }),\n columnHelper.accessor(\"description\", {\n filterFn: \"fuzzy\" as any,\n enableGlobalFilter: true,\n }),\n columnHelper.accessor(\"label\", {\n filterFn: \"includesString\",\n enableGlobalFilter: true,\n }),\n columnHelper.accessor((row) => getDefaultSearchesOutputFields(row.searchId) || [], {\n id: \"outputFields\",\n filterFn: \"arrIncludes\",\n enableGlobalFilter: false,\n }),\n columnHelper.accessor((row) => row.tags || [], {\n id: \"tags\",\n filterFn: \"arrIncludes\",\n enableGlobalFilter: true,\n }),\n columnHelper.accessor((row) => row.provider, {\n id: \"providers\",\n enableGlobalFilter: true,\n }),\n];\n\nexport function useSearchesCatalogTable(\n config: { initialColumnFilters?: ColumnFilter[]; filter?: CatalogFilter } = {},\n) {\n const [category, setCategory] = useState<SearchCategory | null>(null);\n const { initialColumnFilters = [] as ColumnFilter[], filter } = config;\n\n const initialSearchTableData = useMemo(\n () => filterSearchesEntries(getInitialSearchesTableData(category), filter),\n [category, filter],\n );\n\n // Baseline (config.filter applied, but no category / column / global filter).\n // Drives the stable category-button counts so the row doesn't jump.\n const baselineTableData = useMemo(\n () => filterSearchesEntries(getInitialSearchesTableData(null), filter),\n [filter],\n );\n\n const table = useReactTable({\n columns,\n data: initialSearchTableData,\n getCoreRowModel: getCoreRowModel(),\n getFilteredRowModel: getFilteredRowModel(),\n globalFilterFn: fuzzyFilter,\n filterFns: {\n fuzzy: fuzzyFilter,\n },\n getColumnCanGlobalFilter: (column) => column.columnDef.enableGlobalFilter !== false,\n initialState: {\n columnFilters: initialColumnFilters,\n pagination: {\n pageSize: 10,\n },\n },\n });\n\n const columnFilters = table.getState().columnFilters;\n\n const aggregates = useMemo(\n () => getSearchesTableDataAggregates(initialSearchTableData, category),\n [category, initialSearchTableData],\n );\n\n const [globalFilterInput, setGlobalFilterInput, setGlobalFilterImmediately] = useDebounce((v) => {\n if (v === table.getState().globalFilter) return;\n table.setGlobalFilter(v);\n if (v) {\n setCategory(null);\n table.setColumnFilters([]);\n }\n });\n\n const addColumnFilter = useCallback(\n (id: \"inputFields\" | \"outputFields\" | \"tags\" | \"providers\", value: string) => {\n setGlobalFilterImmediately(\"\");\n table.setColumnFilters([{ id, value }]);\n },\n [setGlobalFilterImmediately, table],\n );\n\n const resetFilters = useCallback(() => {\n setGlobalFilterImmediately(\"\");\n setCategory(null);\n }, [setGlobalFilterImmediately]);\n\n const removeColumnFilter = useCallback(\n (id: \"inputFields\" | \"outputFields\" | \"tags\" | \"providers\") => {\n table.getColumn(id)?.setFilterValue(null);\n },\n [table],\n );\n\n const handleCategoryChange = useCallback(\n (category: SearchCategory | null) => {\n setCategory(category);\n table.setColumnFilters([]);\n setGlobalFilterImmediately(\"\");\n },\n [table, setGlobalFilterImmediately],\n );\n\n const getColumnFilterValue = useCallback(\n (id: \"inputFields\" | \"outputFields\" | \"tags\" | \"providers\") => {\n const res = columnFilters.find((f) => f.id === id)?.value;\n return res as string;\n },\n [columnFilters],\n );\n\n const rows = table.getRowModel().rows;\n const cards = useMemo<SearchesCardData[]>(\n () =>\n rows.map((row) => {\n const entry = row.original;\n const latestEntry = (aggregates.searchEntriesByBaseSearch[entry.baseSearch]?.[0] ??\n entry) as SearchesCatalogEntry & { searchesId: SearchesId };\n return {\n searchesId: latestEntry.searchesId,\n baseSearches: entry.baseSearch,\n label: entry.label,\n description: entry.description,\n provider: entry.provider,\n providers: [entry.provider],\n startingCostPerProvider: getStartingCostPerSearchesProvider(latestEntry.searchesId),\n startingCreditAmount: getLoweestSearchesCreditAmount(latestEntry),\n costMode: latestEntry.cost.mode as CostMode,\n defaultOutputFields: getDefaultSearchesOutputFields(latestEntry.searchesId),\n docPath: latestEntry.docPath,\n entry: entry as SearchesCatalogTableData,\n latestEntry,\n };\n }),\n [rows, aggregates.searchEntriesByBaseSearch],\n );\n\n const cardsByCategory = useMemo<{ category: SearchCategory; cards: SearchesCardData[] }[]>(() => {\n const groups = new Map<SearchCategory, SearchesCardData[]>();\n for (const card of cards) {\n const cats = (card.entry.categories ?? []) as SearchCategory[];\n for (const cat of cats) {\n const arr = groups.get(cat);\n if (arr) arr.push(card);\n else groups.set(cat, [card]);\n }\n }\n return Array.from(groups, ([category, group]) => ({\n category,\n cards: group,\n }));\n }, [cards]);\n\n const categoryCounts = useMemo<Partial<Record<SearchCategory, number>>>(() => {\n const counts: Partial<Record<SearchCategory, number>> = {};\n for (const card of cards) {\n const cats = (card.entry.categories ?? []) as SearchCategory[];\n for (const cat of cats) {\n counts[cat] = (counts[cat] ?? 0) + 1;\n }\n }\n return counts;\n }, [cards]);\n\n // Stable counts based on the baseline (no category / column / global filter\n // applied).\n const baselineCardCount = baselineTableData.length;\n const baselineCategoryCounts = useMemo<Partial<Record<SearchCategory, number>>>(() => {\n const counts: Partial<Record<SearchCategory, number>> = {};\n for (const entry of baselineTableData) {\n const cats = (entry.categories ?? []) as SearchCategory[];\n for (const cat of cats) {\n counts[cat] = (counts[cat] ?? 0) + 1;\n }\n }\n return counts;\n }, [baselineTableData]);\n\n return {\n table,\n cards,\n cardsByCategory,\n categoryCounts,\n baselineCardCount,\n baselineCategoryCounts,\n\n category,\n setCategory: handleCategoryChange,\n globalFilterInput,\n setGlobalFilterInput,\n\n addColumnFilter,\n removeColumnFilter,\n resetFilters,\n getColumnFilterValue,\n\n sortedOutputFieldEntries: aggregates.sortedOutputFieldEntries,\n sortedTagEntries: aggregates.sortedTagEntries,\n sortedProviderEntries: aggregates.sortedProviderEntries,\n\n searchIdsByOutputField: aggregates.searchIdsByOutputField,\n searchIdsByProvider: aggregates.searchIdsByProvider,\n searchIdsByTag: aggregates.searchIdsByTag,\n };\n}\n\nexport type UseSearchesCatalogTableReturn = ReturnType<typeof useSearchesCatalogTable>;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"use-searches-catalog-table.mjs","names":[],"sources":["../../src/hooks/use-searches-catalog-table.ts"],"sourcesContent":["import {\n type CatalogFilter,\n filterSearchesEntries,\n getDefaultSearchesOutputFields,\n getInitialSearchesTableData,\n getLoweestSearchesCreditAmount,\n getSearchesSearchTarget,\n getSearchesTableDataAggregates,\n getStartingCostPerSearchesProvider,\n type SearchCategory,\n type SearchesCatalogEntry,\n type SearchesCatalogTableData,\n type SearchesId,\n} from \"@pipe0/base\";\nimport {\n type ColumnFilter,\n createColumnHelper,\n getCoreRowModel,\n getFilteredRowModel,\n getSortedRowModel,\n useReactTable,\n} from \"@tanstack/react-table\";\nimport { useCallback, useMemo, useState } from \"react\";\nimport type { CostMode, SearchesCardData } from \"../types/catalog-adapters.js\";\nimport { catalogSearchFilter, catalogSearchSort } from \"../utils/catalog-helpers.js\";\nimport { useDebounce } from \"./use-debounce.js\";\n\nexport type SearchesOutputFieldEntries = Record<string, SearchesId[]>;\n\nconst columnHelper = createColumnHelper<SearchesCatalogTableData>();\n\nconst columns = [\n columnHelper.accessor(\"searchId\", {\n filterFn: \"includesString\",\n enableGlobalFilter: false,\n }),\n columnHelper.accessor(\"description\", {\n enableGlobalFilter: false,\n }),\n columnHelper.accessor(\"label\", {\n filterFn: \"includesString\",\n enableGlobalFilter: false,\n }),\n columnHelper.accessor((row) => getDefaultSearchesOutputFields(row.searchId) || [], {\n id: \"outputFields\",\n filterFn: \"arrIncludes\",\n enableGlobalFilter: false,\n }),\n columnHelper.accessor((row) => row.tags || [], {\n id: \"tags\",\n filterFn: \"arrIncludes\",\n enableGlobalFilter: false,\n }),\n columnHelper.accessor((row) => row.provider, {\n id: \"providers\",\n enableGlobalFilter: false,\n }),\n // Hidden relevance column — the ONLY globally-filterable one, so the global\n // filter scores each row exactly once and catalogSearchSort can read the\n // score back from this column's filter meta.\n columnHelper.accessor((row) => getSearchesSearchTarget(row), {\n id: \"search\",\n enableGlobalFilter: true,\n enableSorting: true,\n sortingFn: catalogSearchSort,\n }),\n];\n\nexport function useSearchesCatalogTable(\n config: { initialColumnFilters?: ColumnFilter[]; filter?: CatalogFilter } = {},\n) {\n const [category, setCategory] = useState<SearchCategory | null>(null);\n const { initialColumnFilters = [] as ColumnFilter[], filter } = config;\n\n const initialSearchTableData = useMemo(\n () => filterSearchesEntries(getInitialSearchesTableData(category), filter),\n [category, filter],\n );\n\n // Baseline (config.filter applied, but no category / column / global filter).\n // Drives the stable category-button counts so the row doesn't jump.\n const baselineTableData = useMemo(\n () => filterSearchesEntries(getInitialSearchesTableData(null), filter),\n [filter],\n );\n\n const table = useReactTable({\n columns,\n data: initialSearchTableData,\n getCoreRowModel: getCoreRowModel(),\n getFilteredRowModel: getFilteredRowModel(),\n getSortedRowModel: getSortedRowModel(),\n globalFilterFn: catalogSearchFilter,\n getColumnCanGlobalFilter: (column) => column.columnDef.enableGlobalFilter !== false,\n initialState: {\n columnFilters: initialColumnFilters,\n pagination: {\n pageSize: 10,\n },\n },\n });\n\n const columnFilters = table.getState().columnFilters;\n\n const aggregates = useMemo(\n () => getSearchesTableDataAggregates(initialSearchTableData, category),\n [category, initialSearchTableData],\n );\n\n const [globalFilterInput, setGlobalFilterInput, setGlobalFilterImmediately] = useDebounce((v) => {\n if (v === table.getState().globalFilter) return;\n table.setGlobalFilter(v);\n // Relevance order only while a query is active; empty query restores\n // catalog order.\n table.setSorting(v ? [{ id: \"search\", desc: true }] : []);\n if (v) {\n setCategory(null);\n table.setColumnFilters([]);\n }\n });\n\n const addColumnFilter = useCallback(\n (id: \"inputFields\" | \"outputFields\" | \"tags\" | \"providers\", value: string) => {\n setGlobalFilterImmediately(\"\");\n table.setColumnFilters([{ id, value }]);\n },\n [setGlobalFilterImmediately, table],\n );\n\n const resetFilters = useCallback(() => {\n setGlobalFilterImmediately(\"\");\n setCategory(null);\n }, [setGlobalFilterImmediately]);\n\n const removeColumnFilter = useCallback(\n (id: \"inputFields\" | \"outputFields\" | \"tags\" | \"providers\") => {\n table.getColumn(id)?.setFilterValue(null);\n },\n [table],\n );\n\n const handleCategoryChange = useCallback(\n (category: SearchCategory | null) => {\n setCategory(category);\n table.setColumnFilters([]);\n setGlobalFilterImmediately(\"\");\n },\n [table, setGlobalFilterImmediately],\n );\n\n const getColumnFilterValue = useCallback(\n (id: \"inputFields\" | \"outputFields\" | \"tags\" | \"providers\") => {\n const res = columnFilters.find((f) => f.id === id)?.value;\n return res as string;\n },\n [columnFilters],\n );\n\n const rows = table.getRowModel().rows;\n const cards = useMemo<SearchesCardData[]>(\n () =>\n rows.map((row) => {\n const entry = row.original;\n const latestEntry = (aggregates.searchEntriesByBaseSearch[entry.baseSearch]?.[0] ??\n entry) as SearchesCatalogEntry & { searchesId: SearchesId };\n return {\n searchesId: latestEntry.searchesId,\n baseSearches: entry.baseSearch,\n label: entry.label,\n description: entry.description,\n provider: entry.provider,\n providers: [entry.provider],\n startingCostPerProvider: getStartingCostPerSearchesProvider(latestEntry.searchesId),\n startingCreditAmount: getLoweestSearchesCreditAmount(latestEntry),\n costMode: latestEntry.cost.mode as CostMode,\n defaultOutputFields: getDefaultSearchesOutputFields(latestEntry.searchesId),\n docPath: latestEntry.docPath,\n entry: entry as SearchesCatalogTableData,\n latestEntry,\n };\n }),\n [rows, aggregates.searchEntriesByBaseSearch],\n );\n\n const cardsByCategory = useMemo<{ category: SearchCategory; cards: SearchesCardData[] }[]>(() => {\n const groups = new Map<SearchCategory, SearchesCardData[]>();\n for (const card of cards) {\n const cats = (card.entry.categories ?? []) as SearchCategory[];\n for (const cat of cats) {\n const arr = groups.get(cat);\n if (arr) arr.push(card);\n else groups.set(cat, [card]);\n }\n }\n return Array.from(groups, ([category, group]) => ({\n category,\n cards: group,\n }));\n }, [cards]);\n\n const categoryCounts = useMemo<Partial<Record<SearchCategory, number>>>(() => {\n const counts: Partial<Record<SearchCategory, number>> = {};\n for (const card of cards) {\n const cats = (card.entry.categories ?? []) as SearchCategory[];\n for (const cat of cats) {\n counts[cat] = (counts[cat] ?? 0) + 1;\n }\n }\n return counts;\n }, [cards]);\n\n // Stable counts based on the baseline (no category / column / global filter\n // applied).\n const baselineCardCount = baselineTableData.length;\n const baselineCategoryCounts = useMemo<Partial<Record<SearchCategory, number>>>(() => {\n const counts: Partial<Record<SearchCategory, number>> = {};\n for (const entry of baselineTableData) {\n const cats = (entry.categories ?? []) as SearchCategory[];\n for (const cat of cats) {\n counts[cat] = (counts[cat] ?? 0) + 1;\n }\n }\n return counts;\n }, [baselineTableData]);\n\n return {\n table,\n cards,\n cardsByCategory,\n categoryCounts,\n baselineCardCount,\n baselineCategoryCounts,\n\n category,\n setCategory: handleCategoryChange,\n globalFilterInput,\n setGlobalFilterInput,\n\n addColumnFilter,\n removeColumnFilter,\n resetFilters,\n getColumnFilterValue,\n\n sortedOutputFieldEntries: aggregates.sortedOutputFieldEntries,\n sortedTagEntries: aggregates.sortedTagEntries,\n sortedProviderEntries: aggregates.sortedProviderEntries,\n\n searchIdsByOutputField: aggregates.searchIdsByOutputField,\n searchIdsByProvider: aggregates.searchIdsByProvider,\n searchIdsByTag: aggregates.searchIdsByTag,\n };\n}\n\nexport type UseSearchesCatalogTableReturn = ReturnType<typeof useSearchesCatalogTable>;\n"],"mappings":"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"}
|
|
@@ -148,13 +148,25 @@ interface FieldExtras {
|
|
|
148
148
|
options: Array<{
|
|
149
149
|
value: string;
|
|
150
150
|
label: string;
|
|
151
|
-
widgets?: _$_pipe0_base0.WidgetsByKind;
|
|
151
|
+
widgets?: _$_pipe0_base0.WidgetsByKind; /** Opaque per-option payload (e.g. a bucket's contract) for compound adapters. */
|
|
152
|
+
data?: Record<string, string>;
|
|
152
153
|
}>;
|
|
153
154
|
selectedValue: string;
|
|
154
155
|
onSelect: (v: string) => void; /** True while this field's options are being fetched. */
|
|
155
156
|
pending: boolean; /** Suggestions sub-feature gate. The input itself remains active even when true. */
|
|
156
157
|
suggestionsDisabled: boolean; /** Reason from the suggestions sub-feature `enabledIf`. */
|
|
157
158
|
suggestionsDisabledReason?: string;
|
|
159
|
+
/**
|
|
160
|
+
* Per-keystroke server-side option search through the field-context
|
|
161
|
+
* channel. Present when the host wires a `getFieldContext` resolver —
|
|
162
|
+
* adapters upgrade to a searchable combobox when set.
|
|
163
|
+
*/
|
|
164
|
+
loadOptions?: (query: string) => Promise<Array<{
|
|
165
|
+
value: string;
|
|
166
|
+
label: string;
|
|
167
|
+
widgets?: _$_pipe0_base0.WidgetsByKind;
|
|
168
|
+
data?: Record<string, string>;
|
|
169
|
+
}>>;
|
|
158
170
|
};
|
|
159
171
|
multi_select_input: {
|
|
160
172
|
options: Array<{
|
|
@@ -303,14 +315,36 @@ interface FieldExtras {
|
|
|
303
315
|
/**
|
|
304
316
|
* Bare condition-block editor. `searchSecrets`/`searchConstants` feed the
|
|
305
317
|
* value cell's `/` reference picker when the meta carries `inputFields`
|
|
306
|
-
* (pipes-side conditions with liquid-templated values).
|
|
318
|
+
* (pipes-side conditions with liquid-templated values). When the meta
|
|
319
|
+
* carries an `optionsDef`, `meta.options` holds fetched `field_name`
|
|
320
|
+
* suggestions and the editor upgrades the field-name input to a suggest
|
|
321
|
+
* combobox (free typing preserved).
|
|
307
322
|
*/
|
|
308
323
|
condition_block_input: {
|
|
309
324
|
searchSecrets?: (query: string) => Promise<SecretSuggestion[]>;
|
|
310
|
-
searchConstants?: (query: string) => Promise<ConstantSuggestion[]>;
|
|
325
|
+
searchConstants?: (query: string) => Promise<ConstantSuggestion[]>; /** True while `field_name` suggestions (`optionsDef`) are being fetched. */
|
|
326
|
+
pending?: boolean;
|
|
311
327
|
};
|
|
312
328
|
connector_input: {};
|
|
313
329
|
fields_select_input: {};
|
|
330
|
+
typed_fields_select_input: {};
|
|
331
|
+
/**
|
|
332
|
+
* Single-column picker (`{ field_name }`). Options come from the CURRENT
|
|
333
|
+
* sheet's columns or — when the meta carries an `optionsDef` — from the
|
|
334
|
+
* field-context fetch (e.g. a sibling-selected sheet's columns). Free
|
|
335
|
+
* typing is always allowed.
|
|
336
|
+
*/
|
|
337
|
+
field_select_input: {
|
|
338
|
+
options: Array<{
|
|
339
|
+
value: string;
|
|
340
|
+
label: string;
|
|
341
|
+
widgets?: _$_pipe0_base0.WidgetsByKind; /** Opaque per-option payload (e.g. the column's type/format). */
|
|
342
|
+
data?: Record<string, string>;
|
|
343
|
+
}>; /** True while suggestions are being fetched. */
|
|
344
|
+
pending: boolean; /** Sub-feature gate — the input itself stays editable. */
|
|
345
|
+
suggestionsDisabled: boolean;
|
|
346
|
+
suggestionsDisabledReason?: string;
|
|
347
|
+
};
|
|
314
348
|
json_schema_input: {};
|
|
315
349
|
cursor_pagination_metadata: {};
|
|
316
350
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"field-props.d.mts","names":[],"sources":["../../src/types/field-props.ts"],"mappings":";;;;;;;AA0BA;;;;;;;;;;;;;KAAY,SAAA,WAAoB,sBAAA,IAA0B,qBAAA,CAAsB,CAAA;AAAA,UAM/D,cAAA,WAAyB,sBAAA;EACxC,IAAA,EAAM,CAAA;EACN,IAAA,EAAM,qBAAA,CAAsB,CAAA;EAC5B,IAAA,EAAM,UAAA;EACN,IAAA;EACA,EAAA;EAH4B;;;;EAQ5B,KAAA;EAe4B;;;;EAV5B,WAAA;EAdA;;;;EAmBA,IAAA;EACA,KAAA;EACA,OAAA;EACA,KAAA;EACA,KAAA,EAAO,aAAA,CAAc,CAAA;EACrB,QAAA,GAAW,CAAA,EAAG,aAAA,CAAc,CAAA;EAC5B,KAAA;EANA;EAQA,QAAA;EANA;EAQA,cAAA;AAAA;AAAA,UAOQ,oBAAA;EACR,OAAA;IACE,KAAA;IACA,GAAA,GAAM,CAAA;IACN,MAAA,GAAS,CAAA;EAAA;EAEX,OAAA;IACE,KAAA;IACA,GAAA,GAAM,CAAA;IACN,MAAA,GAAS,CAAA;EAAA;EATH;EAYR,OAAA,GAAU,KAAA;IACR,KAAA;IACA,KAAA;IACA,OAAA,GAf0B,cAAA,CAeM,aAAA;EAAA;EAIhC;EADF,WAAA,IAAe,KAAA,aAAkB,OAAA,CAC/B,KAAA;IACE,KAAA;IACA,KAAA;IACA,OAAA,GAVW,cAAA,CAUqB,aAAA;EAAA;AAAA;AAAA,UAK5B,UAAA;EACR,KAAA;EACA,GAAA,GAAM,CAAA;EACN,MAAA,GAAS,CAAA;EAvBP;EAyBF,OAAA,GAAU,KAAA;IACR,KAAA;IACA,KAAA;IACA,OAAA,GARgB,cAAA,CAQgB,aAAA;EAAA;EAvBxB;EA0BV,WAAA,IAAe,KAAA,aAAkB,OAAA,CAC/B,KAAA;IACE,KAAA;IACA,KAAA;IACA,OAAA,GAVW,cAAA,CAUqB,aAAA;EAAA;AAAA;AAAA,UAK5B,cAAA;EACR,IAAA;IAAQ,KAAA,EAAO,CAAA;IAAG,GAAA,GAAM,CAAA,EAAG,CAAA;EAAA;EAC3B,EAAA;IAAM,KAAA,EAAO,CAAA;IAAG,GAAA,GAAM,CAAA,EAAG,CAAA;EAAA;AAAA;AAAA,UAGjB,mBAAA;EACR,WAAA;IACE,QAAA;IACA,KAAA;IACA,WAAA,GAAc,EAAA;IACd,QAAA,GAAW,CAAA;EAAA;EAEb,QAAA;IACE,QAAA;IACA,KAAA;IACA,WAAA,GAAc,EAAA;IACd,QAAA,GAAW,CAAA;EAAA;AAAA;;;;;;;UAcE,WAAA;EAEf,UAAA;IACE,UAAA,EAAY,KAAA,CAAM,mBAAA,CAAoB,gBAAA;EAAA;EAExC,cAAA;IACE,aAAA,EAAe,KAAA,CAAM,sBAAA,CAAuB,mBAAA;EAAA;EAE9C,SAAA;IACE,UAAA,EAAY,KAAA,CAAM,mBAAA,CAAoB,gBAAA;EAAA;EAExC,YAAA;IACE,UAAA,EAAY,KAAA,CAAM,mBAAA,CAAoB,gBAAA;EAAA;EAIxC,YAAA;IACE,OAAA,EAAS,KAAA;MACP,KAAA;MACA,KAAA;MACA,OAAA,GARmC,cAAA,CAQH,aAAA;IAAA;IAElC,aAAA;IACA,QAAA,GAAW,CAAA;EAAA;EAEb,oBAAA;IACE,OAAA,EAAS,KAAA;MACP,KAAA;MACA,KAAA;MACA,OAAA,GAZY,cAAA,CAYoB,aAAA;IAAA;
|
|
1
|
+
{"version":3,"file":"field-props.d.mts","names":[],"sources":["../../src/types/field-props.ts"],"mappings":"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"}
|
|
@@ -90,13 +90,15 @@ function buildExtras(meta, base, publicKey, loadingCtx) {
|
|
|
90
90
|
};
|
|
91
91
|
if (inputGuards.context_select_input(meta)) {
|
|
92
92
|
const loadState = loadingCtx?.fieldLoadStates?.[meta.path];
|
|
93
|
+
const searchFieldContext = loadingCtx?.searchFieldContext;
|
|
93
94
|
return {
|
|
94
95
|
options: meta.options ?? [],
|
|
95
96
|
selectedValue: base.value ?? "",
|
|
96
97
|
onSelect: (v) => base.setValue(v),
|
|
97
98
|
pending: loadState?.status === "loading",
|
|
98
99
|
suggestionsDisabled: loadState?.suggestionsDisabled ?? false,
|
|
99
|
-
suggestionsDisabledReason: loadState?.suggestionsDisabledReason
|
|
100
|
+
suggestionsDisabledReason: loadState?.suggestionsDisabledReason,
|
|
101
|
+
loadOptions: searchFieldContext ? async (query) => withMergedWidgets(await searchFieldContext(meta.path, query), meta.optionsDef?.widgets) : void 0
|
|
100
102
|
};
|
|
101
103
|
}
|
|
102
104
|
if (inputGuards.tagged_text_input(meta)) {
|
|
@@ -327,10 +329,27 @@ function buildExtras(meta, base, publicKey, loadingCtx) {
|
|
|
327
329
|
searchSecrets: loadingCtx?.searchSecrets,
|
|
328
330
|
searchConstants: loadingCtx?.searchConstants
|
|
329
331
|
};
|
|
330
|
-
if (inputGuards.prompt_input(meta) || inputGuards.template_input(meta)
|
|
332
|
+
if (inputGuards.prompt_input(meta) || inputGuards.template_input(meta)) return {
|
|
331
333
|
searchSecrets: loadingCtx?.searchSecrets,
|
|
332
334
|
searchConstants: loadingCtx?.searchConstants
|
|
333
335
|
};
|
|
336
|
+
if (inputGuards.condition_block_input(meta)) {
|
|
337
|
+
const loadState = loadingCtx?.fieldLoadStates?.[meta.path];
|
|
338
|
+
return {
|
|
339
|
+
searchSecrets: loadingCtx?.searchSecrets,
|
|
340
|
+
searchConstants: loadingCtx?.searchConstants,
|
|
341
|
+
pending: loadState?.status === "loading"
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
if (inputGuards.field_select_input(meta)) {
|
|
345
|
+
const loadState = loadingCtx?.fieldLoadStates?.[meta.path];
|
|
346
|
+
return {
|
|
347
|
+
options: meta.options ?? [],
|
|
348
|
+
pending: loadState?.status === "loading",
|
|
349
|
+
suggestionsDisabled: loadState?.suggestionsDisabled ?? false,
|
|
350
|
+
suggestionsDisabledReason: loadState?.suggestionsDisabledReason
|
|
351
|
+
};
|
|
352
|
+
}
|
|
334
353
|
return {};
|
|
335
354
|
}
|
|
336
355
|
function isEmptyValue(value) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-section-handlers.mjs","names":[],"sources":["../../src/utils/build-section-handlers.ts"],"sourcesContent":["import type { FormSection, GeneratedInputMeta, SecretSuggestion } from \"@pipe0/base\";\nimport { inputGuards } from \"@pipe0/base\";\nimport type { UseFormReturn } from \"react-hook-form\";\nimport type { FieldLoadState } from \"../hooks/use-form-core.js\";\nimport type {\n AnyFieldProps,\n ConstantSuggestion,\n GeneratedFieldProps,\n} from \"../types/field-props.js\";\nimport type { FormGroupHandle, FormSectionHandle } from \"../types/form-handle.js\";\n\nexport interface FieldLoadingContext {\n /** Per-field load states for dynamic context_select_input fields, keyed by path. */\n fieldLoadStates: Record<string, FieldLoadState>;\n /**\n * Curried per-keystroke secrets searcher. Bundles the form-level\n * `environment` / `scopes` / `teamId` so adapters only need to pass the\n * user's typed query. Returns `[]` when no `getSecrets` resolver is wired.\n */\n searchSecrets?: (query: string) => Promise<SecretSuggestion[]>;\n /**\n * Curried per-keystroke constants searcher. Mirrors `searchSecrets`.\n * Returns `[]` when no `getConstants` resolver is wired.\n */\n searchConstants?: (query: string) => Promise<ConstantSuggestion[]>;\n}\n\n/**\n * Builds a fully-typed `GeneratedFieldProps` from raw metadata + form state.\n *\n * The returned object includes:\n * - Base props (kind, meta, value, setValue, error, etc.)\n * - Kind-specific extras (inputProps, options, toggle, etc.)\n */\nexport function buildFieldProps<Meta extends GeneratedInputMeta>(\n meta: Meta,\n form: UseFormReturn<Record<string, unknown>>,\n publicKey: string,\n loadingCtx?: FieldLoadingContext,\n): GeneratedFieldProps<Meta[\"type\"]> {\n const path = meta.path;\n const fieldState = form.getFieldState(path as any);\n const value = form.getValues(path as any);\n const id = `p0-field-${path.replace(/\\./g, \"-\")}`;\n\n const setValue = (v: unknown) =>\n form.setValue(path as any, v, {\n shouldDirty: true,\n shouldTouch: true,\n shouldValidate: true,\n });\n\n // Match the submit-gated behavior used everywhere else (group errorCount,\n // `useFieldError`): don't surface the field's error until the user has\n // attempted a submit. Otherwise `setValue`-triggered validation would\n // flash errors the moment the form is interacted with.\n const hasSubmitted = form.formState.isSubmitted;\n\n const loadState = loadingCtx?.fieldLoadStates?.[path];\n\n const base = {\n kind: meta.type,\n meta,\n form,\n path,\n label: meta.label ?? \"\",\n description: meta.description,\n info: meta.info,\n error: hasSubmitted ? fieldState.error?.message : undefined,\n touched: fieldState.isTouched,\n dirty: fieldState.isDirty,\n id,\n value,\n setValue,\n reset: () => form.resetField(path as any),\n disabled: loadState?.disabled ?? false,\n disabledReason: loadState?.disabledReason,\n };\n\n const extras = buildExtras(meta, { path, id, value, setValue }, publicKey, loadingCtx);\n\n return { ...base, ...extras } as unknown as GeneratedFieldProps<Meta[\"type\"]>;\n}\n\n// Re-export under old name for backward compat\nexport { buildFieldProps as buildFieldHandle };\n\ntype OptionLike = {\n value: string;\n label: string;\n widgets?: Record<string, Record<string, unknown>>;\n};\n\nfunction withMergedWidgets<T extends OptionLike>(\n options: T[],\n staticWidgets: Record<string, Record<string, unknown>> | undefined,\n): T[] {\n if (!staticWidgets) return options;\n return options.map((o) => ({\n ...o,\n widgets: { ...staticWidgets, ...(o.widgets ?? {}) },\n }));\n}\n\nfunction buildExtras(\n meta: GeneratedInputMeta,\n base: {\n path: string;\n id: string;\n value: unknown;\n setValue: (v: unknown) => void;\n },\n publicKey: string,\n loadingCtx?: FieldLoadingContext,\n): Record<string, unknown> {\n if (\n inputGuards.text_input(meta) ||\n inputGuards.int_input(meta) ||\n inputGuards.number_input(meta)\n ) {\n const isNumber = inputGuards.int_input(meta) || inputGuards.number_input(meta);\n return {\n inputProps: {\n type: isNumber ? \"number\" : (meta as any).inputType || \"text\",\n name: base.path,\n id: base.id,\n value: base.value != null ? String(base.value) : \"\",\n onChange: (e: React.ChangeEvent<HTMLInputElement>) => {\n const v = e.target.value;\n base.setValue(isNumber ? (v === \"\" ? null : Number(v)) : v);\n },\n placeholder: meta.placeholder,\n step: inputGuards.number_input(meta) ? \"0.001\" : undefined,\n },\n };\n }\n\n if (inputGuards.textarea_input(meta)) {\n return {\n textareaProps: {\n name: base.path,\n id: base.id,\n value: (base.value as string) ?? \"\",\n onChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => base.setValue(e.target.value),\n placeholder: meta.placeholder,\n rows: meta.rows,\n },\n };\n }\n\n if (inputGuards.select_input(meta)) {\n return {\n options: meta.options ?? [],\n selectedValue: (base.value as string) ?? \"\",\n onSelect: (v: string) => base.setValue(v),\n };\n }\n\n if (inputGuards.context_select_input(meta)) {\n const loadState = loadingCtx?.fieldLoadStates?.[meta.path];\n return {\n options: meta.options ?? [],\n selectedValue: (base.value as string) ?? \"\",\n onSelect: (v: string) => base.setValue(v),\n pending: loadState?.status === \"loading\",\n suggestionsDisabled: loadState?.suggestionsDisabled ?? false,\n suggestionsDisabledReason: loadState?.suggestionsDisabledReason,\n };\n }\n\n if (inputGuards.tagged_text_input(meta)) {\n const loadState = loadingCtx?.fieldLoadStates?.[meta.path];\n return {\n options: meta.options ?? [],\n pending: loadState?.status === \"loading\",\n suggestionsDisabled: loadState?.suggestionsDisabled ?? false,\n suggestionsDisabledReason: loadState?.suggestionsDisabledReason,\n searchSecrets: loadingCtx?.searchSecrets,\n searchConstants: loadingCtx?.searchConstants,\n };\n }\n\n if (inputGuards.providers_input(meta)) {\n return {\n options: meta.options ?? [],\n };\n }\n\n if (inputGuards.multi_select_input(meta)) {\n const selected = (base.value as string[]) ?? [];\n return {\n options: meta.options ?? [],\n selected,\n onToggle: (v: string) =>\n base.setValue(selected.includes(v) ? selected.filter((s) => s !== v) : [...selected, v]),\n onClear: () => base.setValue([]),\n };\n }\n\n if (inputGuards.async_multi_select_input(meta)) {\n const selected = (base.value as string[]) ?? [];\n return {\n loadOptions: async (query: string) =>\n withMergedWidgets(\n await meta.optionsDef.options({ query, token: publicKey }),\n meta.optionsDef.widgets,\n ),\n selected,\n onToggle: (v: string) =>\n base.setValue(selected.includes(v) ? selected.filter((s) => s !== v) : [...selected, v]),\n onClear: () => base.setValue([]),\n };\n }\n\n if (inputGuards.boolean_input(meta) || inputGuards.nullable_boolean_input(meta)) {\n return {\n checked: base.value === true,\n isNull: base.value === null || base.value === undefined,\n toggle: () => base.setValue(base.value === true ? false : true),\n clear: () => base.setValue(null),\n };\n }\n\n if (\n inputGuards.include_exclude_input(meta) ||\n inputGuards.include_exclude_select_input(meta) ||\n inputGuards.async_include_exclude_select_input(meta)\n ) {\n const current = (base.value as {\n include: string[];\n exclude: string[];\n }) ?? { include: [], exclude: [] };\n const result: Record<string, unknown> = {\n include: {\n value: current.include,\n add: (v: string) => base.setValue({ ...current, include: [...current.include, v] }),\n remove: (v: string) =>\n base.setValue({\n ...current,\n include: current.include.filter((i) => i !== v),\n }),\n },\n exclude: {\n value: current.exclude,\n add: (v: string) => base.setValue({ ...current, exclude: [...current.exclude, v] }),\n remove: (v: string) =>\n base.setValue({\n ...current,\n exclude: current.exclude.filter((i) => i !== v),\n }),\n },\n };\n const m = meta as any;\n if (m.optionsDef?.options && typeof m.optionsDef.options === \"function\") {\n result.loadOptions = async (query: string) =>\n withMergedWidgets(\n await m.optionsDef.options({ query, token: publicKey }),\n m.optionsDef.widgets,\n );\n } else if (m.optionsDef?.options) {\n result.options = withMergedWidgets(m.optionsDef.options, m.optionsDef.widgets);\n }\n if (m.suggestionsDef?.options) {\n if (typeof m.suggestionsDef.options === \"function\") {\n result.loadOptions = async (query: string) =>\n withMergedWidgets(\n await m.suggestionsDef.options({ query, token: publicKey }),\n m.suggestionsDef.widgets,\n );\n } else {\n result.options = withMergedWidgets(m.suggestionsDef.options, m.suggestionsDef.widgets);\n }\n }\n return result;\n }\n\n if (inputGuards.range_input(meta)) {\n const current = (base.value as {\n from: number | null;\n to: number | null;\n }) ?? { from: null, to: null };\n return {\n from: {\n value: current.from,\n set: (v: number | null) => base.setValue({ ...current, from: v }),\n },\n to: {\n value: current.to,\n set: (v: number | null) => base.setValue({ ...current, to: v }),\n },\n };\n }\n\n if (inputGuards.date_range_input(meta)) {\n const current = (base.value as Record<string, string>) ?? {};\n return {\n from: {\n value: current.gte ?? current.gt ?? \"\",\n set: (v: string) => base.setValue({ ...current, gte: v }),\n },\n to: {\n value: current.lte ?? current.lt ?? \"\",\n set: (v: string) => base.setValue({ ...current, lte: v }),\n },\n };\n }\n\n if (inputGuards.exact_range_input(meta)) {\n const current = (base.value as Record<string, number | null>) ?? {};\n return {\n greaterThan: {\n operator: current.gt != null ? \"gt\" : \"gte\",\n value: current.gt ?? current.gte ?? null,\n setOperator: (op: string) => {\n const otherOp = op === \"gt\" ? \"gte\" : \"gt\";\n const val = current[otherOp] ?? current[op];\n const updated = { ...current };\n delete updated[otherOp];\n if (val != null) updated[op] = val;\n base.setValue(updated);\n },\n setValue: (v: number | null) => {\n const op = current.gt != null ? \"gt\" : \"gte\";\n const updated = { ...current };\n if (v != null) updated[op] = v;\n else delete updated[op];\n base.setValue(updated);\n },\n },\n lessThan: {\n operator: current.lt != null ? \"lt\" : \"lte\",\n value: current.lt ?? current.lte ?? null,\n setOperator: (op: string) => {\n const otherOp = op === \"lt\" ? \"lte\" : \"lt\";\n const val = current[otherOp] ?? current[op];\n const updated = { ...current };\n delete updated[otherOp];\n if (val != null) updated[op] = val;\n base.setValue(updated);\n },\n setValue: (v: number | null) => {\n const op = current.lt != null ? \"lt\" : \"lte\";\n const updated = { ...current };\n if (v != null) updated[op] = v;\n else delete updated[op];\n base.setValue(updated);\n },\n },\n };\n }\n\n if (inputGuards.min_max_int_input(meta)) {\n const current = (base.value as {\n min: number | null;\n max: number | null;\n }) ?? { min: null, max: null };\n return {\n from: {\n value: current.min,\n set: (v: number | null) => base.setValue({ ...current, min: v }),\n },\n to: {\n value: current.max,\n set: (v: number | null) => base.setValue({ ...current, max: v }),\n },\n };\n }\n\n if (inputGuards.multi_create_input(meta) || inputGuards.ordered_multi_create_input(meta)) {\n const items = (base.value as string[]) ?? [];\n const result: Record<string, unknown> = {\n items,\n add: (v: string) => base.setValue([...items, v]),\n remove: (v: string) => base.setValue(items.filter((i) => i !== v)),\n };\n if (inputGuards.ordered_multi_create_input(meta)) {\n result.reorder = (from: number, to: number) => {\n const next = [...items];\n const [moved] = next.splice(from, 1);\n next.splice(to, 0, moved);\n base.setValue(next);\n };\n }\n const m = meta as any;\n if (m.suggestionsDef?.options) {\n if (typeof m.suggestionsDef.options === \"function\") {\n result.loadOptions = async (query: string) =>\n withMergedWidgets(\n await m.suggestionsDef.options({ query, token: publicKey }),\n m.suggestionsDef.widgets,\n );\n } else {\n result.options = withMergedWidgets(m.suggestionsDef.options, m.suggestionsDef.widgets);\n }\n }\n return result;\n }\n\n if (inputGuards.tagged_ordered_multi_create_input(meta)) {\n const items = (base.value as string[]) ?? [];\n const result: Record<string, unknown> = {\n items,\n setItems: (next: string[]) => base.setValue(next),\n inputFields: meta.inputFields ?? [],\n };\n const m = meta as any;\n if (m.suggestionsDef?.options) {\n if (typeof m.suggestionsDef.options === \"function\") {\n result.loadOptions = async (query: string) =>\n withMergedWidgets(\n await m.suggestionsDef.options({ query, token: publicKey }),\n m.suggestionsDef.widgets,\n );\n } else {\n result.options = withMergedWidgets(m.suggestionsDef.options, m.suggestionsDef.widgets);\n }\n }\n return result;\n }\n\n if (inputGuards.loose_object_input(meta)) {\n const value = (base.value as Record<string, string>) ?? {};\n return {\n value,\n setObject: (next: Record<string, string>) => base.setValue(next),\n searchSecrets: loadingCtx?.searchSecrets,\n searchConstants: loadingCtx?.searchConstants,\n };\n }\n\n if (\n inputGuards.prompt_input(meta) ||\n inputGuards.template_input(meta) ||\n inputGuards.condition_block_input(meta)\n ) {\n return {\n searchSecrets: loadingCtx?.searchSecrets,\n searchConstants: loadingCtx?.searchConstants,\n };\n }\n\n // Remaining types need no extras beyond base\n return {};\n}\n\nfunction isEmptyValue(value: unknown): boolean {\n if (value === null || typeof value === \"undefined\") return true;\n if (typeof value === \"string\") return value === \"\";\n if (Array.isArray(value)) return value.length === 0;\n if (typeof value === \"object\") {\n const keys = Object.keys(value);\n if (keys.length === 0) return true;\n return keys.every((k) => isEmptyValue((value as Record<string, unknown>)[k]));\n }\n return false;\n}\n\nexport function buildSectionHandles(\n formConfig: FormSection[],\n form: UseFormReturn<Record<string, unknown>>,\n publicKey: string,\n loadingCtx?: FieldLoadingContext,\n): FormSectionHandle[] {\n // In onSubmit validation mode, don't flag groups as invalid until the\n // user has actually attempted a submit. This matches RHF's own field-level\n // behavior where `formState.errors` is only populated after the first\n // submit (and updated reactively thereafter per `reValidateMode`).\n const hasSubmitted = form.formState.isSubmitted;\n\n return formConfig\n .map((section) => {\n const groups: FormGroupHandle[] = section.groups\n .map((group) => {\n // Drop a connector field whose mode is \"disabled\" (custom connections\n // unsupported) — there's nothing to configure, so we hide the whole\n // group/section rather than render a \"not supported\" placeholder.\n const fields = group.fields\n .filter(\n (meta) => !(inputGuards.connector_input(meta) && meta.connectorMode === \"disabled\"),\n )\n .map((meta) => buildFieldProps(meta, form, publicKey, loadingCtx)) as AnyFieldProps[];\n\n const groupPathError = form.getFieldState(group.groupPath as any).error;\n const errorCount = hasSubmitted\n ? fields.filter((f) => f.error != null).length + (groupPathError ? 1 : 0)\n : 0;\n const setCount = fields.filter((f) => !isEmptyValue(f.value)).length;\n const dirtyCount = fields.filter((f) => f.dirty).length;\n\n return {\n key: group.groupPath,\n label: group.label,\n description: group.description,\n iconKey: group.iconKey,\n defaultExpand: group.defaultExpand ?? false,\n fields,\n errorCount,\n setCount,\n dirtyCount,\n };\n })\n .filter((group) => group.fields.length > 0);\n\n return {\n key: section.metadata.path,\n label: section.metadata.label,\n description: section.metadata.description,\n groups,\n };\n })\n .filter((section) => section.groups.length > 0);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"build-section-handlers.mjs","names":[],"sources":["../../src/utils/build-section-handlers.ts"],"sourcesContent":["import type { FormSection, GeneratedInputMeta, SecretSuggestion, StoreOption } from \"@pipe0/base\";\nimport { inputGuards } from \"@pipe0/base\";\nimport type { UseFormReturn } from \"react-hook-form\";\nimport type { FieldLoadState } from \"../hooks/use-form-core.js\";\nimport type {\n AnyFieldProps,\n ConstantSuggestion,\n GeneratedFieldProps,\n} from \"../types/field-props.js\";\nimport type { FormGroupHandle, FormSectionHandle } from \"../types/form-handle.js\";\n\nexport interface FieldLoadingContext {\n /** Per-field load states for dynamic context_select_input fields, keyed by path. */\n fieldLoadStates: Record<string, FieldLoadState>;\n /**\n * Curried per-keystroke secrets searcher. Bundles the form-level\n * `environment` / `scopes` / `teamId` so adapters only need to pass the\n * user's typed query. Returns `[]` when no `getSecrets` resolver is wired.\n */\n searchSecrets?: (query: string) => Promise<SecretSuggestion[]>;\n /**\n * Curried per-keystroke constants searcher. Mirrors `searchSecrets`.\n * Returns `[]` when no `getConstants` resolver is wired.\n */\n searchConstants?: (query: string) => Promise<ConstantSuggestion[]>;\n /**\n * Curried per-keystroke field-context searcher: server-side option search\n * for ONE optionsDef-capable field (bundles the live payload). Returns the\n * options directly — never merged into the shared form store. Absent when\n * no `getFieldContext` resolver is wired.\n */\n searchFieldContext?: (fieldPath: string, query: string) => Promise<StoreOption[]>;\n}\n\n/**\n * Builds a fully-typed `GeneratedFieldProps` from raw metadata + form state.\n *\n * The returned object includes:\n * - Base props (kind, meta, value, setValue, error, etc.)\n * - Kind-specific extras (inputProps, options, toggle, etc.)\n */\nexport function buildFieldProps<Meta extends GeneratedInputMeta>(\n meta: Meta,\n form: UseFormReturn<Record<string, unknown>>,\n publicKey: string,\n loadingCtx?: FieldLoadingContext,\n): GeneratedFieldProps<Meta[\"type\"]> {\n const path = meta.path;\n const fieldState = form.getFieldState(path as any);\n const value = form.getValues(path as any);\n const id = `p0-field-${path.replace(/\\./g, \"-\")}`;\n\n const setValue = (v: unknown) =>\n form.setValue(path as any, v, {\n shouldDirty: true,\n shouldTouch: true,\n shouldValidate: true,\n });\n\n // Match the submit-gated behavior used everywhere else (group errorCount,\n // `useFieldError`): don't surface the field's error until the user has\n // attempted a submit. Otherwise `setValue`-triggered validation would\n // flash errors the moment the form is interacted with.\n const hasSubmitted = form.formState.isSubmitted;\n\n const loadState = loadingCtx?.fieldLoadStates?.[path];\n\n const base = {\n kind: meta.type,\n meta,\n form,\n path,\n label: meta.label ?? \"\",\n description: meta.description,\n info: meta.info,\n error: hasSubmitted ? fieldState.error?.message : undefined,\n touched: fieldState.isTouched,\n dirty: fieldState.isDirty,\n id,\n value,\n setValue,\n reset: () => form.resetField(path as any),\n disabled: loadState?.disabled ?? false,\n disabledReason: loadState?.disabledReason,\n };\n\n const extras = buildExtras(meta, { path, id, value, setValue }, publicKey, loadingCtx);\n\n return { ...base, ...extras } as unknown as GeneratedFieldProps<Meta[\"type\"]>;\n}\n\n// Re-export under old name for backward compat\nexport { buildFieldProps as buildFieldHandle };\n\ntype OptionLike = {\n value: string;\n label: string;\n widgets?: Record<string, Record<string, unknown>>;\n};\n\nfunction withMergedWidgets<T extends OptionLike>(\n options: T[],\n staticWidgets: Record<string, Record<string, unknown>> | undefined,\n): T[] {\n if (!staticWidgets) return options;\n return options.map((o) => ({\n ...o,\n widgets: { ...staticWidgets, ...(o.widgets ?? {}) },\n }));\n}\n\nfunction buildExtras(\n meta: GeneratedInputMeta,\n base: {\n path: string;\n id: string;\n value: unknown;\n setValue: (v: unknown) => void;\n },\n publicKey: string,\n loadingCtx?: FieldLoadingContext,\n): Record<string, unknown> {\n if (\n inputGuards.text_input(meta) ||\n inputGuards.int_input(meta) ||\n inputGuards.number_input(meta)\n ) {\n const isNumber = inputGuards.int_input(meta) || inputGuards.number_input(meta);\n return {\n inputProps: {\n type: isNumber ? \"number\" : (meta as any).inputType || \"text\",\n name: base.path,\n id: base.id,\n value: base.value != null ? String(base.value) : \"\",\n onChange: (e: React.ChangeEvent<HTMLInputElement>) => {\n const v = e.target.value;\n base.setValue(isNumber ? (v === \"\" ? null : Number(v)) : v);\n },\n placeholder: meta.placeholder,\n step: inputGuards.number_input(meta) ? \"0.001\" : undefined,\n },\n };\n }\n\n if (inputGuards.textarea_input(meta)) {\n return {\n textareaProps: {\n name: base.path,\n id: base.id,\n value: (base.value as string) ?? \"\",\n onChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => base.setValue(e.target.value),\n placeholder: meta.placeholder,\n rows: meta.rows,\n },\n };\n }\n\n if (inputGuards.select_input(meta)) {\n return {\n options: meta.options ?? [],\n selectedValue: (base.value as string) ?? \"\",\n onSelect: (v: string) => base.setValue(v),\n };\n }\n\n if (inputGuards.context_select_input(meta)) {\n const loadState = loadingCtx?.fieldLoadStates?.[meta.path];\n const searchFieldContext = loadingCtx?.searchFieldContext;\n return {\n options: meta.options ?? [],\n selectedValue: (base.value as string) ?? \"\",\n onSelect: (v: string) => base.setValue(v),\n pending: loadState?.status === \"loading\",\n suggestionsDisabled: loadState?.suggestionsDisabled ?? false,\n suggestionsDisabledReason: loadState?.suggestionsDisabledReason,\n // Per-keystroke server-side search through the field-context channel.\n // Static widgets merge exactly as `resolveField` does for store options.\n loadOptions: searchFieldContext\n ? async (query: string) =>\n withMergedWidgets(await searchFieldContext(meta.path, query), meta.optionsDef?.widgets)\n : undefined,\n };\n }\n\n if (inputGuards.tagged_text_input(meta)) {\n const loadState = loadingCtx?.fieldLoadStates?.[meta.path];\n return {\n options: meta.options ?? [],\n pending: loadState?.status === \"loading\",\n suggestionsDisabled: loadState?.suggestionsDisabled ?? false,\n suggestionsDisabledReason: loadState?.suggestionsDisabledReason,\n searchSecrets: loadingCtx?.searchSecrets,\n searchConstants: loadingCtx?.searchConstants,\n };\n }\n\n if (inputGuards.providers_input(meta)) {\n return {\n options: meta.options ?? [],\n };\n }\n\n if (inputGuards.multi_select_input(meta)) {\n const selected = (base.value as string[]) ?? [];\n return {\n options: meta.options ?? [],\n selected,\n onToggle: (v: string) =>\n base.setValue(selected.includes(v) ? selected.filter((s) => s !== v) : [...selected, v]),\n onClear: () => base.setValue([]),\n };\n }\n\n if (inputGuards.async_multi_select_input(meta)) {\n const selected = (base.value as string[]) ?? [];\n return {\n loadOptions: async (query: string) =>\n withMergedWidgets(\n await meta.optionsDef.options({ query, token: publicKey }),\n meta.optionsDef.widgets,\n ),\n selected,\n onToggle: (v: string) =>\n base.setValue(selected.includes(v) ? selected.filter((s) => s !== v) : [...selected, v]),\n onClear: () => base.setValue([]),\n };\n }\n\n if (inputGuards.boolean_input(meta) || inputGuards.nullable_boolean_input(meta)) {\n return {\n checked: base.value === true,\n isNull: base.value === null || base.value === undefined,\n toggle: () => base.setValue(base.value === true ? false : true),\n clear: () => base.setValue(null),\n };\n }\n\n if (\n inputGuards.include_exclude_input(meta) ||\n inputGuards.include_exclude_select_input(meta) ||\n inputGuards.async_include_exclude_select_input(meta)\n ) {\n const current = (base.value as {\n include: string[];\n exclude: string[];\n }) ?? { include: [], exclude: [] };\n const result: Record<string, unknown> = {\n include: {\n value: current.include,\n add: (v: string) => base.setValue({ ...current, include: [...current.include, v] }),\n remove: (v: string) =>\n base.setValue({\n ...current,\n include: current.include.filter((i) => i !== v),\n }),\n },\n exclude: {\n value: current.exclude,\n add: (v: string) => base.setValue({ ...current, exclude: [...current.exclude, v] }),\n remove: (v: string) =>\n base.setValue({\n ...current,\n exclude: current.exclude.filter((i) => i !== v),\n }),\n },\n };\n const m = meta as any;\n if (m.optionsDef?.options && typeof m.optionsDef.options === \"function\") {\n result.loadOptions = async (query: string) =>\n withMergedWidgets(\n await m.optionsDef.options({ query, token: publicKey }),\n m.optionsDef.widgets,\n );\n } else if (m.optionsDef?.options) {\n result.options = withMergedWidgets(m.optionsDef.options, m.optionsDef.widgets);\n }\n if (m.suggestionsDef?.options) {\n if (typeof m.suggestionsDef.options === \"function\") {\n result.loadOptions = async (query: string) =>\n withMergedWidgets(\n await m.suggestionsDef.options({ query, token: publicKey }),\n m.suggestionsDef.widgets,\n );\n } else {\n result.options = withMergedWidgets(m.suggestionsDef.options, m.suggestionsDef.widgets);\n }\n }\n return result;\n }\n\n if (inputGuards.range_input(meta)) {\n const current = (base.value as {\n from: number | null;\n to: number | null;\n }) ?? { from: null, to: null };\n return {\n from: {\n value: current.from,\n set: (v: number | null) => base.setValue({ ...current, from: v }),\n },\n to: {\n value: current.to,\n set: (v: number | null) => base.setValue({ ...current, to: v }),\n },\n };\n }\n\n if (inputGuards.date_range_input(meta)) {\n const current = (base.value as Record<string, string>) ?? {};\n return {\n from: {\n value: current.gte ?? current.gt ?? \"\",\n set: (v: string) => base.setValue({ ...current, gte: v }),\n },\n to: {\n value: current.lte ?? current.lt ?? \"\",\n set: (v: string) => base.setValue({ ...current, lte: v }),\n },\n };\n }\n\n if (inputGuards.exact_range_input(meta)) {\n const current = (base.value as Record<string, number | null>) ?? {};\n return {\n greaterThan: {\n operator: current.gt != null ? \"gt\" : \"gte\",\n value: current.gt ?? current.gte ?? null,\n setOperator: (op: string) => {\n const otherOp = op === \"gt\" ? \"gte\" : \"gt\";\n const val = current[otherOp] ?? current[op];\n const updated = { ...current };\n delete updated[otherOp];\n if (val != null) updated[op] = val;\n base.setValue(updated);\n },\n setValue: (v: number | null) => {\n const op = current.gt != null ? \"gt\" : \"gte\";\n const updated = { ...current };\n if (v != null) updated[op] = v;\n else delete updated[op];\n base.setValue(updated);\n },\n },\n lessThan: {\n operator: current.lt != null ? \"lt\" : \"lte\",\n value: current.lt ?? current.lte ?? null,\n setOperator: (op: string) => {\n const otherOp = op === \"lt\" ? \"lte\" : \"lt\";\n const val = current[otherOp] ?? current[op];\n const updated = { ...current };\n delete updated[otherOp];\n if (val != null) updated[op] = val;\n base.setValue(updated);\n },\n setValue: (v: number | null) => {\n const op = current.lt != null ? \"lt\" : \"lte\";\n const updated = { ...current };\n if (v != null) updated[op] = v;\n else delete updated[op];\n base.setValue(updated);\n },\n },\n };\n }\n\n if (inputGuards.min_max_int_input(meta)) {\n const current = (base.value as {\n min: number | null;\n max: number | null;\n }) ?? { min: null, max: null };\n return {\n from: {\n value: current.min,\n set: (v: number | null) => base.setValue({ ...current, min: v }),\n },\n to: {\n value: current.max,\n set: (v: number | null) => base.setValue({ ...current, max: v }),\n },\n };\n }\n\n if (inputGuards.multi_create_input(meta) || inputGuards.ordered_multi_create_input(meta)) {\n const items = (base.value as string[]) ?? [];\n const result: Record<string, unknown> = {\n items,\n add: (v: string) => base.setValue([...items, v]),\n remove: (v: string) => base.setValue(items.filter((i) => i !== v)),\n };\n if (inputGuards.ordered_multi_create_input(meta)) {\n result.reorder = (from: number, to: number) => {\n const next = [...items];\n const [moved] = next.splice(from, 1);\n next.splice(to, 0, moved);\n base.setValue(next);\n };\n }\n const m = meta as any;\n if (m.suggestionsDef?.options) {\n if (typeof m.suggestionsDef.options === \"function\") {\n result.loadOptions = async (query: string) =>\n withMergedWidgets(\n await m.suggestionsDef.options({ query, token: publicKey }),\n m.suggestionsDef.widgets,\n );\n } else {\n result.options = withMergedWidgets(m.suggestionsDef.options, m.suggestionsDef.widgets);\n }\n }\n return result;\n }\n\n if (inputGuards.tagged_ordered_multi_create_input(meta)) {\n const items = (base.value as string[]) ?? [];\n const result: Record<string, unknown> = {\n items,\n setItems: (next: string[]) => base.setValue(next),\n inputFields: meta.inputFields ?? [],\n };\n const m = meta as any;\n if (m.suggestionsDef?.options) {\n if (typeof m.suggestionsDef.options === \"function\") {\n result.loadOptions = async (query: string) =>\n withMergedWidgets(\n await m.suggestionsDef.options({ query, token: publicKey }),\n m.suggestionsDef.widgets,\n );\n } else {\n result.options = withMergedWidgets(m.suggestionsDef.options, m.suggestionsDef.widgets);\n }\n }\n return result;\n }\n\n if (inputGuards.loose_object_input(meta)) {\n const value = (base.value as Record<string, string>) ?? {};\n return {\n value,\n setObject: (next: Record<string, string>) => base.setValue(next),\n searchSecrets: loadingCtx?.searchSecrets,\n searchConstants: loadingCtx?.searchConstants,\n };\n }\n\n if (inputGuards.prompt_input(meta) || inputGuards.template_input(meta)) {\n return {\n searchSecrets: loadingCtx?.searchSecrets,\n searchConstants: loadingCtx?.searchConstants,\n };\n }\n\n if (inputGuards.condition_block_input(meta)) {\n const loadState = loadingCtx?.fieldLoadStates?.[meta.path];\n return {\n searchSecrets: loadingCtx?.searchSecrets,\n searchConstants: loadingCtx?.searchConstants,\n // Field-name suggestions themselves ride on `meta.options` (merged from\n // the form store by `resolveField`); only the load state comes through.\n pending: loadState?.status === \"loading\",\n };\n }\n\n if (inputGuards.field_select_input(meta)) {\n const loadState = loadingCtx?.fieldLoadStates?.[meta.path];\n return {\n options: meta.options ?? [],\n pending: loadState?.status === \"loading\",\n suggestionsDisabled: loadState?.suggestionsDisabled ?? false,\n suggestionsDisabledReason: loadState?.suggestionsDisabledReason,\n };\n }\n\n // Remaining types need no extras beyond base\n return {};\n}\n\nfunction isEmptyValue(value: unknown): boolean {\n if (value === null || typeof value === \"undefined\") return true;\n if (typeof value === \"string\") return value === \"\";\n if (Array.isArray(value)) return value.length === 0;\n if (typeof value === \"object\") {\n const keys = Object.keys(value);\n if (keys.length === 0) return true;\n return keys.every((k) => isEmptyValue((value as Record<string, unknown>)[k]));\n }\n return false;\n}\n\nexport function buildSectionHandles(\n formConfig: FormSection[],\n form: UseFormReturn<Record<string, unknown>>,\n publicKey: string,\n loadingCtx?: FieldLoadingContext,\n): FormSectionHandle[] {\n // In onSubmit validation mode, don't flag groups as invalid until the\n // user has actually attempted a submit. This matches RHF's own field-level\n // behavior where `formState.errors` is only populated after the first\n // submit (and updated reactively thereafter per `reValidateMode`).\n const hasSubmitted = form.formState.isSubmitted;\n\n return formConfig\n .map((section) => {\n const groups: FormGroupHandle[] = section.groups\n .map((group) => {\n // Drop a connector field whose mode is \"disabled\" (custom connections\n // unsupported) — there's nothing to configure, so we hide the whole\n // group/section rather than render a \"not supported\" placeholder.\n const fields = group.fields\n .filter(\n (meta) => !(inputGuards.connector_input(meta) && meta.connectorMode === \"disabled\"),\n )\n .map((meta) => buildFieldProps(meta, form, publicKey, loadingCtx)) as AnyFieldProps[];\n\n const groupPathError = form.getFieldState(group.groupPath as any).error;\n const errorCount = hasSubmitted\n ? fields.filter((f) => f.error != null).length + (groupPathError ? 1 : 0)\n : 0;\n const setCount = fields.filter((f) => !isEmptyValue(f.value)).length;\n const dirtyCount = fields.filter((f) => f.dirty).length;\n\n return {\n key: group.groupPath,\n label: group.label,\n description: group.description,\n iconKey: group.iconKey,\n defaultExpand: group.defaultExpand ?? false,\n fields,\n errorCount,\n setCount,\n dirtyCount,\n };\n })\n .filter((group) => group.fields.length > 0);\n\n return {\n key: section.metadata.path,\n label: section.metadata.label,\n description: section.metadata.description,\n groups,\n };\n })\n .filter((section) => section.groups.length > 0);\n}\n"],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { scoreCatalogSearch } from "@pipe0/base";
|
|
1
2
|
import { BookDashed, Bookmark, Braces, CheckCheck, Hash, HelpCircle, Loader, Pause, ToggleRight, TriangleDashed, Type, X } from "lucide-react";
|
|
2
3
|
import { rankItem } from "@tanstack/match-sorter-utils";
|
|
3
4
|
|
|
@@ -29,7 +30,15 @@ const fuzzyFilter = (row, columnId, value, addMeta) => {
|
|
|
29
30
|
addMeta({ itemRank });
|
|
30
31
|
return itemRank.passed;
|
|
31
32
|
};
|
|
33
|
+
const catalogSearchFilter = (row, columnId, value, addMeta) => {
|
|
34
|
+
const score = scoreCatalogSearch(row.getValue(columnId), String(value ?? ""));
|
|
35
|
+
addMeta({ searchScore: score });
|
|
36
|
+
return score > 0;
|
|
37
|
+
};
|
|
38
|
+
const catalogSearchSort = (rowA, rowB, columnId) => {
|
|
39
|
+
return (rowA.columnFiltersMeta[columnId]?.searchScore ?? 0) - (rowB.columnFiltersMeta[columnId]?.searchScore ?? 0);
|
|
40
|
+
};
|
|
32
41
|
|
|
33
42
|
//#endregion
|
|
34
|
-
export { fuzzyFilter, getFieldStatusIcon, getFieldTypeIcon };
|
|
43
|
+
export { catalogSearchFilter, catalogSearchSort, fuzzyFilter, getFieldStatusIcon, getFieldTypeIcon };
|
|
35
44
|
//# sourceMappingURL=catalog-helpers.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalog-helpers.mjs","names":[],"sources":["../../src/utils/catalog-helpers.tsx"],"sourcesContent":["import type
|
|
1
|
+
{"version":3,"file":"catalog-helpers.mjs","names":[],"sources":["../../src/utils/catalog-helpers.tsx"],"sourcesContent":["import { type RecordFieldStatus, type RecordFieldType, scoreCatalogSearch } from \"@pipe0/base\";\nimport { rankItem } from \"@tanstack/match-sorter-utils\";\nimport type { FilterFn, SortingFn } from \"@tanstack/react-table\";\nimport {\n BookDashed,\n Bookmark,\n Braces,\n CheckCheck,\n Hash,\n HelpCircle,\n Loader,\n Pause,\n ToggleRight,\n TriangleDashed,\n Type,\n X,\n} from \"lucide-react\";\nimport type { ComponentType } from \"react\";\n\nconst fieldStatusIconMap = {\n completed: CheckCheck,\n failed: X,\n no_result: BookDashed,\n pending: Bookmark,\n processing: Loader,\n queued: Pause,\n skipped: TriangleDashed,\n} satisfies Record<RecordFieldStatus, ComponentType>;\n\nconst FieldTypeIconMap = {\n boolean: ToggleRight,\n json: Braces,\n number: Hash,\n string: Type,\n unknown: HelpCircle,\n} satisfies Record<RecordFieldType, ComponentType>;\n\nexport function getFieldTypeIcon(fieldType: RecordFieldType) {\n return FieldTypeIconMap[fieldType];\n}\n\nexport function getFieldStatusIcon(fieldStatus: RecordFieldStatus) {\n return fieldStatusIconMap[fieldStatus];\n}\n\nexport const fuzzyFilter: FilterFn<any> = (row, columnId, value, addMeta) => {\n const itemRank = rankItem(row.getValue(columnId), value);\n addMeta({ itemRank });\n return itemRank.passed;\n};\n\n// Global-filter fn for the catalog tables' hidden \"search\" column (its value\n// is a precomputed CatalogSearchTarget). Stashes the score so\n// catalogSearchSort can order rows by relevance while a query is active.\nexport const catalogSearchFilter: FilterFn<any> = (row, columnId, value, addMeta) => {\n const score = scoreCatalogSearch(row.getValue(columnId), String(value ?? \"\"));\n addMeta({ searchScore: score } as any);\n return score > 0;\n};\n\nexport const catalogSearchSort: SortingFn<any> = (rowA, rowB, columnId) => {\n const a = (rowA.columnFiltersMeta[columnId] as any)?.searchScore ?? 0;\n const b = (rowB.columnFiltersMeta[columnId] as any)?.searchScore ?? 0;\n return a - b; // paired with `desc: true` → highest score first\n};\n"],"mappings":";;;;;AAmBA,MAAM,qBAAqB;CACzB,WAAW;CACX,QAAQ;CACR,WAAW;CACX,SAAS;CACT,YAAY;CACZ,QAAQ;CACR,SAAS;CACV;AAED,MAAM,mBAAmB;CACvB,SAAS;CACT,MAAM;CACN,QAAQ;CACR,QAAQ;CACR,SAAS;CACV;AAED,SAAgB,iBAAiB,WAA4B;AAC3D,QAAO,iBAAiB;;AAG1B,SAAgB,mBAAmB,aAAgC;AACjE,QAAO,mBAAmB;;AAG5B,MAAa,eAA8B,KAAK,UAAU,OAAO,YAAY;CAC3E,MAAM,WAAW,SAAS,IAAI,SAAS,SAAS,EAAE,MAAM;AACxD,SAAQ,EAAE,UAAU,CAAC;AACrB,QAAO,SAAS;;AAMlB,MAAa,uBAAsC,KAAK,UAAU,OAAO,YAAY;CACnF,MAAM,QAAQ,mBAAmB,IAAI,SAAS,SAAS,EAAE,OAAO,SAAS,GAAG,CAAC;AAC7E,SAAQ,EAAE,aAAa,OAAO,CAAQ;AACtC,QAAO,QAAQ;;AAGjB,MAAa,qBAAqC,MAAM,MAAM,aAAa;AAGzE,SAFW,KAAK,kBAAkB,WAAmB,eAAe,MACzD,KAAK,kBAAkB,WAAmB,eAAe"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pipe0/react",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.6",
|
|
4
4
|
"description": "React component library for building forms and catalogs powered by pipe0 pipes and searches.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "pipe0",
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
"react-hook-form": "^7.62.0",
|
|
85
85
|
"swr": "^2.4.1",
|
|
86
86
|
"tailwind-merge": "^3.3.1",
|
|
87
|
-
"@pipe0/base": "0.5.
|
|
87
|
+
"@pipe0/base": "0.5.6"
|
|
88
88
|
},
|
|
89
89
|
"devDependencies": {
|
|
90
90
|
"@base-ui/react": "^1.3.0",
|