@pipe0/react 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/components/compound/search-catalog/category-filter.d.mts.map +1 -1
  3. package/dist/components/compound/search-catalog/category-filter.mjs +2 -1
  4. package/dist/components/compound/search-catalog/category-filter.mjs.map +1 -1
  5. package/dist/components/compound/searches-catalog/category-filter.d.mts.map +1 -1
  6. package/dist/components/compound/searches-catalog/category-filter.mjs +2 -1
  7. package/dist/components/compound/searches-catalog/category-filter.mjs.map +1 -1
  8. package/dist/components/defaults/adapters/connector-input.mjs +37 -26
  9. package/dist/components/defaults/adapters/connector-input.mjs.map +1 -1
  10. package/dist/components/defaults/adapters/context-select-input.mjs +10 -31
  11. package/dist/components/defaults/adapters/context-select-input.mjs.map +1 -1
  12. package/dist/components/defaults/adapters/pipes-run-if-input.mjs +2 -2
  13. package/dist/components/defaults/adapters/pipes-run-if-input.mjs.map +1 -1
  14. package/dist/components/defaults/adapters/select-input.mjs +1 -1
  15. package/dist/components/defaults/adapters/select-input.mjs.map +1 -1
  16. package/dist/components/field-renderer.d.mts.map +1 -1
  17. package/dist/components/field-renderer.mjs +3 -1
  18. package/dist/components/field-renderer.mjs.map +1 -1
  19. package/dist/hooks/use-form-core.d.mts.map +1 -1
  20. package/dist/hooks/use-form-core.mjs.map +1 -1
  21. package/dist/hooks/use-search-catalog-table.d.mts +6 -6
  22. package/dist/utils/build-section-handlers.mjs +4 -1
  23. package/dist/utils/build-section-handlers.mjs.map +1 -1
  24. package/package.json +2 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @pipe0/elements-react
2
2
 
3
+ ## 0.1.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 24afa62: Add sheet:rows search
8
+ - Updated dependencies [24afa62]
9
+ - @pipe0/base@0.4.1
10
+
3
11
  ## 0.1.0
4
12
 
5
13
  ### Minor Changes
@@ -1 +1 @@
1
- {"version":3,"file":"category-filter.d.mts","names":[],"sources":["../../../../src/components/compound/search-catalog/category-filter.tsx"],"mappings":";;;;;;UA6BiB,gCAAA;EACf,KAAA,EAAO,cAAA;EACP,QAAA,GAAW,KAAA,EAAO,cAAA;EAClB,OAAA,EAAS,aAAA,CAAc,cAAA,CAAe,cAAA;EACtC,MAAA,EAAQ,OAAA,CAAQ,MAAA,CAAO,cAAA;EACvB,UAAA;EACA,QAAA;AAAA;AAAA,UAGe,gCAAA,SACP,SAAA,CAAU,cAAA,QAAsB,gCAAA;EAPjB;EASvB,OAAA,GAAU,aAAA,CAAc,cAAA,CAAe,cAAA;AAAA;AAAA,iBAGzB,2BAAA,CAAA;EACd,OAAA;EACA,SAAA;EACA,MAAA;EAAA,GACG;AAAA,GACF,gCAAA,GAAgC,oBAAA,CAAA,GAAA,CAAA,OAAA"}
1
+ {"version":3,"file":"category-filter.d.mts","names":[],"sources":["../../../../src/components/compound/search-catalog/category-filter.tsx"],"mappings":";;;;;;UA8BiB,gCAAA;EACf,KAAA,EAAO,cAAA;EACP,QAAA,GAAW,KAAA,EAAO,cAAA;EAClB,OAAA,EAAS,aAAA,CAAc,cAAA,CAAe,cAAA;EACtC,MAAA,EAAQ,OAAA,CAAQ,MAAA,CAAO,cAAA;EACvB,UAAA;EACA,QAAA;AAAA;AAAA,UAGe,gCAAA,SACP,SAAA,CAAU,cAAA,QAAsB,gCAAA;EAPjB;EASvB,OAAA,GAAU,aAAA,CAAc,cAAA,CAAe,cAAA;AAAA;AAAA,iBAGzB,2BAAA,CAAA;EACd,OAAA;EACA,SAAA;EACA,MAAA;EAAA,GACG;AAAA,GACF,gCAAA,GAAgC,oBAAA,CAAA,GAAA,CAAA,OAAA"}
@@ -3,13 +3,14 @@ import { DefaultCategoryFilter } from "../../defaults/catalog/category-filter.mj
3
3
  import { mergeProps } from "@base-ui/react/merge-props";
4
4
  import { useRender } from "@base-ui/react/use-render";
5
5
  import { jsx } from "react/jsx-runtime";
6
- import { Building2, Database, User, X } from "lucide-react";
6
+ import { Building2, Database, Table, User, X } from "lucide-react";
7
7
  import { getSearchCategoryEntries } from "@pipe0/base";
8
8
 
9
9
  //#region src/components/compound/search-catalog/category-filter.tsx
10
10
  const SEARCH_CATEGORY_ICONS = {
11
11
  people: User,
12
12
  companies: Building2,
13
+ data: Table,
13
14
  deprecated: X
14
15
  };
15
16
  const DEFAULT_OPTIONS = [{
@@ -1 +1 @@
1
- {"version":3,"file":"category-filter.mjs","names":[],"sources":["../../../../src/components/compound/search-catalog/category-filter.tsx"],"sourcesContent":["import { mergeProps } from \"@base-ui/react/merge-props\";\nimport { useRender } from \"@base-ui/react/use-render\";\nimport { getSearchCategoryEntries, type SearchCategory } from \"@pipe0/base\";\nimport { Building2, Database, User, X } from \"lucide-react\";\nimport { useSearchCatalogContext } from \"../../../context/search-catalog-context.js\";\nimport {\n type CategoryOption,\n DefaultCategoryFilter,\n} from \"../../defaults/catalog/category-filter.js\";\n\nconst SEARCH_CATEGORY_ICONS: Record<SearchCategory, CategoryOption<SearchCategory>[\"icon\"]> = {\n people: User,\n companies: Building2,\n deprecated: X,\n};\n\nconst DEFAULT_OPTIONS: ReadonlyArray<CategoryOption<SearchCategory>> = [\n { id: null, label: \"All\", icon: Database },\n ...[...getSearchCategoryEntries()]\n .sort((a, b) => a.order - b.order)\n .map(\n (entry): CategoryOption<SearchCategory> => ({\n id: entry.id,\n label: entry.label,\n icon: SEARCH_CATEGORY_ICONS[entry.id],\n }),\n ),\n];\n\nexport interface SearchCatalogCategoryFilterState {\n value: SearchCategory | null;\n setValue: (value: SearchCategory | null) => void;\n options: ReadonlyArray<CategoryOption<SearchCategory>>;\n counts: Partial<Record<SearchCategory, number>>;\n totalCount: number;\n isActive: boolean;\n}\n\nexport interface SearchCatalogCategoryFilterProps\n extends useRender.ComponentProps<\"div\", SearchCatalogCategoryFilterState> {\n /** Override the default category options. */\n options?: ReadonlyArray<CategoryOption<SearchCategory>>;\n}\n\nexport function SearchCatalogCategoryFilter({\n options = DEFAULT_OPTIONS,\n className,\n render,\n ...props\n}: SearchCatalogCategoryFilterProps) {\n const ctx = useSearchCatalogContext();\n const value = ctx.category;\n const isActive = value !== null;\n\n const element = useRender({\n defaultTagName: \"div\",\n render,\n state: {\n value,\n setValue: ctx.setCategory,\n options,\n counts: ctx.baselineCategoryCounts,\n totalCount: ctx.baselineCardCount,\n isActive,\n },\n stateAttributesMapping: {\n setValue: () => null,\n options: () => null,\n counts: () => null,\n },\n props: mergeProps<\"div\">(\n {\n className,\n ...({ \"data-p0\": \"catalog-category-filter\" } as Record<string, string>),\n },\n props,\n ),\n });\n\n if (render) return element;\n\n return (\n <DefaultCategoryFilter\n options={options}\n value={ctx.category}\n onChange={ctx.setCategory}\n className={className}\n />\n );\n}\n"],"mappings":";;;;;;;;;AAUA,MAAM,wBAAwF;CAC5F,QAAQ;CACR,WAAW;CACX,YAAY;CACb;AAED,MAAM,kBAAiE,CACrE;CAAE,IAAI;CAAM,OAAO;CAAO,MAAM;CAAU,EAC1C,GAAG,CAAC,GAAG,0BAA0B,CAAC,CAC/B,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM,CACjC,KACE,WAA2C;CAC1C,IAAI,MAAM;CACV,OAAO,MAAM;CACb,MAAM,sBAAsB,MAAM;CACnC,EACF,CACJ;AAiBD,SAAgB,4BAA4B,EAC1C,UAAU,iBACV,WACA,QACA,GAAG,SACgC;CACnC,MAAM,MAAM,yBAAyB;CACrC,MAAM,QAAQ,IAAI;CAClB,MAAM,WAAW,UAAU;CAE3B,MAAM,UAAU,UAAU;EACxB,gBAAgB;EAChB;EACA,OAAO;GACL;GACA,UAAU,IAAI;GACd;GACA,QAAQ,IAAI;GACZ,YAAY,IAAI;GAChB;GACD;EACD,wBAAwB;GACtB,gBAAgB;GAChB,eAAe;GACf,cAAc;GACf;EACD,OAAO,WACL;GACE;GACM,WAAW;GAClB,EACD,MACD;EACF,CAAC;AAEF,KAAI,OAAQ,QAAO;AAEnB,QACE,oBAAC,uBAAD;EACW;EACT,OAAO,IAAI;EACX,UAAU,IAAI;EACH;EACX"}
1
+ {"version":3,"file":"category-filter.mjs","names":[],"sources":["../../../../src/components/compound/search-catalog/category-filter.tsx"],"sourcesContent":["import { mergeProps } from \"@base-ui/react/merge-props\";\nimport { useRender } from \"@base-ui/react/use-render\";\nimport { getSearchCategoryEntries, type SearchCategory } from \"@pipe0/base\";\nimport { Building2, Database, Table, User, X } from \"lucide-react\";\nimport { useSearchCatalogContext } from \"../../../context/search-catalog-context.js\";\nimport {\n type CategoryOption,\n DefaultCategoryFilter,\n} from \"../../defaults/catalog/category-filter.js\";\n\nconst SEARCH_CATEGORY_ICONS: Record<SearchCategory, CategoryOption<SearchCategory>[\"icon\"]> = {\n people: User,\n companies: Building2,\n data: Table,\n deprecated: X,\n};\n\nconst DEFAULT_OPTIONS: ReadonlyArray<CategoryOption<SearchCategory>> = [\n { id: null, label: \"All\", icon: Database },\n ...[...getSearchCategoryEntries()]\n .sort((a, b) => a.order - b.order)\n .map(\n (entry): CategoryOption<SearchCategory> => ({\n id: entry.id,\n label: entry.label,\n icon: SEARCH_CATEGORY_ICONS[entry.id],\n }),\n ),\n];\n\nexport interface SearchCatalogCategoryFilterState {\n value: SearchCategory | null;\n setValue: (value: SearchCategory | null) => void;\n options: ReadonlyArray<CategoryOption<SearchCategory>>;\n counts: Partial<Record<SearchCategory, number>>;\n totalCount: number;\n isActive: boolean;\n}\n\nexport interface SearchCatalogCategoryFilterProps\n extends useRender.ComponentProps<\"div\", SearchCatalogCategoryFilterState> {\n /** Override the default category options. */\n options?: ReadonlyArray<CategoryOption<SearchCategory>>;\n}\n\nexport function SearchCatalogCategoryFilter({\n options = DEFAULT_OPTIONS,\n className,\n render,\n ...props\n}: SearchCatalogCategoryFilterProps) {\n const ctx = useSearchCatalogContext();\n const value = ctx.category;\n const isActive = value !== null;\n\n const element = useRender({\n defaultTagName: \"div\",\n render,\n state: {\n value,\n setValue: ctx.setCategory,\n options,\n counts: ctx.baselineCategoryCounts,\n totalCount: ctx.baselineCardCount,\n isActive,\n },\n stateAttributesMapping: {\n setValue: () => null,\n options: () => null,\n counts: () => null,\n },\n props: mergeProps<\"div\">(\n {\n className,\n ...({ \"data-p0\": \"catalog-category-filter\" } as Record<string, string>),\n },\n props,\n ),\n });\n\n if (render) return element;\n\n return (\n <DefaultCategoryFilter\n options={options}\n value={ctx.category}\n onChange={ctx.setCategory}\n className={className}\n />\n );\n}\n"],"mappings":";;;;;;;;;AAUA,MAAM,wBAAwF;CAC5F,QAAQ;CACR,WAAW;CACX,MAAM;CACN,YAAY;CACb;AAED,MAAM,kBAAiE,CACrE;CAAE,IAAI;CAAM,OAAO;CAAO,MAAM;CAAU,EAC1C,GAAG,CAAC,GAAG,0BAA0B,CAAC,CAC/B,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM,CACjC,KACE,WAA2C;CAC1C,IAAI,MAAM;CACV,OAAO,MAAM;CACb,MAAM,sBAAsB,MAAM;CACnC,EACF,CACJ;AAiBD,SAAgB,4BAA4B,EAC1C,UAAU,iBACV,WACA,QACA,GAAG,SACgC;CACnC,MAAM,MAAM,yBAAyB;CACrC,MAAM,QAAQ,IAAI;CAClB,MAAM,WAAW,UAAU;CAE3B,MAAM,UAAU,UAAU;EACxB,gBAAgB;EAChB;EACA,OAAO;GACL;GACA,UAAU,IAAI;GACd;GACA,QAAQ,IAAI;GACZ,YAAY,IAAI;GAChB;GACD;EACD,wBAAwB;GACtB,gBAAgB;GAChB,eAAe;GACf,cAAc;GACf;EACD,OAAO,WACL;GACE;GACM,WAAW;GAClB,EACD,MACD;EACF,CAAC;AAEF,KAAI,OAAQ,QAAO;AAEnB,QACE,oBAAC,uBAAD;EACW;EACT,OAAO,IAAI;EACX,UAAU,IAAI;EACH;EACX"}
@@ -1 +1 @@
1
- {"version":3,"file":"category-filter.d.mts","names":[],"sources":["../../../../src/components/compound/searches-catalog/category-filter.tsx"],"mappings":";;;;;;UA6BiB,kCAAA;EACf,KAAA,EAAO,cAAA;EACP,QAAA,GAAW,KAAA,EAAO,cAAA;EAClB,OAAA,EAAS,aAAA,CAAc,cAAA,CAAe,cAAA;EACtC,MAAA,EAAQ,OAAA,CAAQ,MAAA,CAAO,cAAA;EACvB,UAAA;EACA,QAAA;AAAA;AAAA,UAGe,kCAAA,SACP,SAAA,CAAU,cAAA,QAAsB,kCAAA;EAPjB;EASvB,OAAA,GAAU,aAAA,CAAc,cAAA,CAAe,cAAA;AAAA;AAAA,iBAGzB,6BAAA,CAAA;EACd,OAAA;EACA,SAAA;EACA,MAAA;EAAA,GACG;AAAA,GACF,kCAAA,GAAkC,oBAAA,CAAA,GAAA,CAAA,OAAA"}
1
+ {"version":3,"file":"category-filter.d.mts","names":[],"sources":["../../../../src/components/compound/searches-catalog/category-filter.tsx"],"mappings":";;;;;;UA8BiB,kCAAA;EACf,KAAA,EAAO,cAAA;EACP,QAAA,GAAW,KAAA,EAAO,cAAA;EAClB,OAAA,EAAS,aAAA,CAAc,cAAA,CAAe,cAAA;EACtC,MAAA,EAAQ,OAAA,CAAQ,MAAA,CAAO,cAAA;EACvB,UAAA;EACA,QAAA;AAAA;AAAA,UAGe,kCAAA,SACP,SAAA,CAAU,cAAA,QAAsB,kCAAA;EAPjB;EASvB,OAAA,GAAU,aAAA,CAAc,cAAA,CAAe,cAAA;AAAA;AAAA,iBAGzB,6BAAA,CAAA;EACd,OAAA;EACA,SAAA;EACA,MAAA;EAAA,GACG;AAAA,GACF,kCAAA,GAAkC,oBAAA,CAAA,GAAA,CAAA,OAAA"}
@@ -3,13 +3,14 @@ import { DefaultCategoryFilter } from "../../defaults/catalog/category-filter.mj
3
3
  import { mergeProps } from "@base-ui/react/merge-props";
4
4
  import { useRender } from "@base-ui/react/use-render";
5
5
  import { jsx } from "react/jsx-runtime";
6
- import { Building2, Database, User, X } from "lucide-react";
6
+ import { Building2, Database, Table, User, X } from "lucide-react";
7
7
  import { getSearchCategoryEntries } from "@pipe0/base";
8
8
 
9
9
  //#region src/components/compound/searches-catalog/category-filter.tsx
10
10
  const SEARCH_CATEGORY_ICONS = {
11
11
  people: User,
12
12
  companies: Building2,
13
+ data: Table,
13
14
  deprecated: X
14
15
  };
15
16
  const DEFAULT_OPTIONS = [{
@@ -1 +1 @@
1
- {"version":3,"file":"category-filter.mjs","names":[],"sources":["../../../../src/components/compound/searches-catalog/category-filter.tsx"],"sourcesContent":["import { mergeProps } from \"@base-ui/react/merge-props\";\nimport { useRender } from \"@base-ui/react/use-render\";\nimport { getSearchCategoryEntries, type SearchCategory } from \"@pipe0/base\";\nimport { Building2, Database, User, X } from \"lucide-react\";\nimport { useSearchesCatalogContext } from \"../../../context/searches-catalog-context.js\";\nimport {\n type CategoryOption,\n DefaultCategoryFilter,\n} from \"../../defaults/catalog/category-filter.js\";\n\nconst SEARCH_CATEGORY_ICONS: Record<SearchCategory, CategoryOption<SearchCategory>[\"icon\"]> = {\n people: User,\n companies: Building2,\n deprecated: X,\n};\n\nconst DEFAULT_OPTIONS: ReadonlyArray<CategoryOption<SearchCategory>> = [\n { id: null, label: \"All\", icon: Database },\n ...[...getSearchCategoryEntries()]\n .sort((a, b) => a.order - b.order)\n .map(\n (entry): CategoryOption<SearchCategory> => ({\n id: entry.id,\n label: entry.label,\n icon: SEARCH_CATEGORY_ICONS[entry.id],\n }),\n ),\n];\n\nexport interface SearchesCatalogCategoryFilterState {\n value: SearchCategory | null;\n setValue: (value: SearchCategory | null) => void;\n options: ReadonlyArray<CategoryOption<SearchCategory>>;\n counts: Partial<Record<SearchCategory, number>>;\n totalCount: number;\n isActive: boolean;\n}\n\nexport interface SearchesCatalogCategoryFilterProps\n extends useRender.ComponentProps<\"div\", SearchesCatalogCategoryFilterState> {\n /** Override the default category options. */\n options?: ReadonlyArray<CategoryOption<SearchCategory>>;\n}\n\nexport function SearchesCatalogCategoryFilter({\n options = DEFAULT_OPTIONS,\n className,\n render,\n ...props\n}: SearchesCatalogCategoryFilterProps) {\n const ctx = useSearchesCatalogContext();\n const value = ctx.category;\n const isActive = value !== null;\n\n const element = useRender({\n defaultTagName: \"div\",\n render,\n state: {\n value,\n setValue: ctx.setCategory,\n options,\n counts: ctx.baselineCategoryCounts,\n totalCount: ctx.baselineCardCount,\n isActive,\n },\n stateAttributesMapping: {\n setValue: () => null,\n options: () => null,\n counts: () => null,\n },\n props: mergeProps<\"div\">(\n {\n className,\n ...({ \"data-p0\": \"catalog-category-filter\" } as Record<string, string>),\n },\n props,\n ),\n });\n\n if (render) return element;\n\n return (\n <DefaultCategoryFilter\n options={options}\n value={ctx.category}\n onChange={ctx.setCategory}\n className={className}\n />\n );\n}\n"],"mappings":";;;;;;;;;AAUA,MAAM,wBAAwF;CAC5F,QAAQ;CACR,WAAW;CACX,YAAY;CACb;AAED,MAAM,kBAAiE,CACrE;CAAE,IAAI;CAAM,OAAO;CAAO,MAAM;CAAU,EAC1C,GAAG,CAAC,GAAG,0BAA0B,CAAC,CAC/B,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM,CACjC,KACE,WAA2C;CAC1C,IAAI,MAAM;CACV,OAAO,MAAM;CACb,MAAM,sBAAsB,MAAM;CACnC,EACF,CACJ;AAiBD,SAAgB,8BAA8B,EAC5C,UAAU,iBACV,WACA,QACA,GAAG,SACkC;CACrC,MAAM,MAAM,2BAA2B;CACvC,MAAM,QAAQ,IAAI;CAClB,MAAM,WAAW,UAAU;CAE3B,MAAM,UAAU,UAAU;EACxB,gBAAgB;EAChB;EACA,OAAO;GACL;GACA,UAAU,IAAI;GACd;GACA,QAAQ,IAAI;GACZ,YAAY,IAAI;GAChB;GACD;EACD,wBAAwB;GACtB,gBAAgB;GAChB,eAAe;GACf,cAAc;GACf;EACD,OAAO,WACL;GACE;GACM,WAAW;GAClB,EACD,MACD;EACF,CAAC;AAEF,KAAI,OAAQ,QAAO;AAEnB,QACE,oBAAC,uBAAD;EACW;EACT,OAAO,IAAI;EACX,UAAU,IAAI;EACH;EACX"}
1
+ {"version":3,"file":"category-filter.mjs","names":[],"sources":["../../../../src/components/compound/searches-catalog/category-filter.tsx"],"sourcesContent":["import { mergeProps } from \"@base-ui/react/merge-props\";\nimport { useRender } from \"@base-ui/react/use-render\";\nimport { getSearchCategoryEntries, type SearchCategory } from \"@pipe0/base\";\nimport { Building2, Database, Table, User, X } from \"lucide-react\";\nimport { useSearchesCatalogContext } from \"../../../context/searches-catalog-context.js\";\nimport {\n type CategoryOption,\n DefaultCategoryFilter,\n} from \"../../defaults/catalog/category-filter.js\";\n\nconst SEARCH_CATEGORY_ICONS: Record<SearchCategory, CategoryOption<SearchCategory>[\"icon\"]> = {\n people: User,\n companies: Building2,\n data: Table,\n deprecated: X,\n};\n\nconst DEFAULT_OPTIONS: ReadonlyArray<CategoryOption<SearchCategory>> = [\n { id: null, label: \"All\", icon: Database },\n ...[...getSearchCategoryEntries()]\n .sort((a, b) => a.order - b.order)\n .map(\n (entry): CategoryOption<SearchCategory> => ({\n id: entry.id,\n label: entry.label,\n icon: SEARCH_CATEGORY_ICONS[entry.id],\n }),\n ),\n];\n\nexport interface SearchesCatalogCategoryFilterState {\n value: SearchCategory | null;\n setValue: (value: SearchCategory | null) => void;\n options: ReadonlyArray<CategoryOption<SearchCategory>>;\n counts: Partial<Record<SearchCategory, number>>;\n totalCount: number;\n isActive: boolean;\n}\n\nexport interface SearchesCatalogCategoryFilterProps\n extends useRender.ComponentProps<\"div\", SearchesCatalogCategoryFilterState> {\n /** Override the default category options. */\n options?: ReadonlyArray<CategoryOption<SearchCategory>>;\n}\n\nexport function SearchesCatalogCategoryFilter({\n options = DEFAULT_OPTIONS,\n className,\n render,\n ...props\n}: SearchesCatalogCategoryFilterProps) {\n const ctx = useSearchesCatalogContext();\n const value = ctx.category;\n const isActive = value !== null;\n\n const element = useRender({\n defaultTagName: \"div\",\n render,\n state: {\n value,\n setValue: ctx.setCategory,\n options,\n counts: ctx.baselineCategoryCounts,\n totalCount: ctx.baselineCardCount,\n isActive,\n },\n stateAttributesMapping: {\n setValue: () => null,\n options: () => null,\n counts: () => null,\n },\n props: mergeProps<\"div\">(\n {\n className,\n ...({ \"data-p0\": \"catalog-category-filter\" } as Record<string, string>),\n },\n props,\n ),\n });\n\n if (render) return element;\n\n return (\n <DefaultCategoryFilter\n options={options}\n value={ctx.category}\n onChange={ctx.setCategory}\n className={className}\n />\n );\n}\n"],"mappings":";;;;;;;;;AAUA,MAAM,wBAAwF;CAC5F,QAAQ;CACR,WAAW;CACX,MAAM;CACN,YAAY;CACb;AAED,MAAM,kBAAiE,CACrE;CAAE,IAAI;CAAM,OAAO;CAAO,MAAM;CAAU,EAC1C,GAAG,CAAC,GAAG,0BAA0B,CAAC,CAC/B,MAAM,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM,CACjC,KACE,WAA2C;CAC1C,IAAI,MAAM;CACV,OAAO,MAAM;CACb,MAAM,sBAAsB,MAAM;CACnC,EACF,CACJ;AAiBD,SAAgB,8BAA8B,EAC5C,UAAU,iBACV,WACA,QACA,GAAG,SACkC;CACrC,MAAM,MAAM,2BAA2B;CACvC,MAAM,QAAQ,IAAI;CAClB,MAAM,WAAW,UAAU;CAE3B,MAAM,UAAU,UAAU;EACxB,gBAAgB;EAChB;EACA,OAAO;GACL;GACA,UAAU,IAAI;GACd;GACA,QAAQ,IAAI;GACZ,YAAY,IAAI;GAChB;GACD;EACD,wBAAwB;GACtB,gBAAgB;GAChB,eAAe;GACf,cAAc;GACf;EACD,OAAO,WACL;GACE;GACM,WAAW;GAClB,EACD,MACD;EACF,CAAC;AAEF,KAAI,OAAQ,QAAO;AAEnB,QACE,oBAAC,uBAAD;EACW;EACT,OAAO,IAAI;EACX,UAAU,IAAI;EACH;EACX"}
@@ -12,7 +12,10 @@ function ConnectorInputAdapter(field) {
12
12
  const connections = field.meta.filteredConnections ?? [];
13
13
  const value = field.value ?? null;
14
14
  const current = value?.connections ?? [];
15
- const hasError = !!useFieldError(field.form, field.path);
15
+ const connectionsError = useFieldError(field.form, `${field.path}.connections`);
16
+ const connectorError = useFieldError(field.form, field.path);
17
+ const error = connectionsError ?? connectorError;
18
+ const hasError = !!error;
16
19
  const options = useMemo(() => connections.map((c) => ({
17
20
  value: c.connection,
18
21
  label: c.connection
@@ -61,32 +64,40 @@ function ConnectorInputAdapter(field) {
61
64
  return /* @__PURE__ */ jsxs("div", {
62
65
  "data-p0": "input",
63
66
  className: "pz:flex pz:flex-col pz:gap-1",
64
- children: [/* @__PURE__ */ jsx("div", {
65
- className: cn(hasError && "pz:[&_[data-slot=combobox-chips]]:border-destructive"),
66
- children: /* @__PURE__ */ jsx(SuggestCombobox, {
67
- value: current.map((c) => c.connection),
68
- onChange: (next) => field.setValue({
69
- ...value,
70
- connections: next.map((connection) => ({
71
- type: "vault",
72
- connection
73
- }))
74
- }),
75
- options,
76
- iconFor: renderLogo,
77
- ariaInvalid: hasError,
78
- placeholder: "Select a connection"
67
+ children: [
68
+ /* @__PURE__ */ jsx("div", {
69
+ className: cn(hasError && "pz:[&_[data-slot=combobox-chips]]:border-destructive"),
70
+ children: /* @__PURE__ */ jsx(SuggestCombobox, {
71
+ value: current.map((c) => c.connection),
72
+ onChange: (next) => field.setValue({
73
+ ...value,
74
+ connections: next.map((connection) => ({
75
+ type: "vault",
76
+ connection
77
+ }))
78
+ }),
79
+ options,
80
+ iconFor: renderLogo,
81
+ ariaInvalid: hasError,
82
+ placeholder: "Select a connection"
83
+ })
84
+ }),
85
+ hasError && /* @__PURE__ */ jsx("span", {
86
+ className: "pz:text-destructive pz:text-xs pz:font-medium",
87
+ role: "alert",
88
+ children: error
89
+ }),
90
+ /* @__PURE__ */ jsx("div", {
91
+ className: "pz:flex pz:items-center pz:justify-end",
92
+ children: /* @__PURE__ */ jsx(Button, {
93
+ type: "button",
94
+ variant: "link",
95
+ size: "xs",
96
+ onClick: () => field.setValue(null),
97
+ children: "Reset"
98
+ })
79
99
  })
80
- }), /* @__PURE__ */ jsx("div", {
81
- className: "pz:flex pz:items-center pz:justify-end",
82
- children: /* @__PURE__ */ jsx(Button, {
83
- type: "button",
84
- variant: "link",
85
- size: "xs",
86
- onClick: () => field.setValue(null),
87
- children: "Reset"
88
- })
89
- })]
100
+ ]
90
101
  });
91
102
  }
92
103
 
@@ -1 +1 @@
1
- {"version":3,"file":"connector-input.mjs","names":[],"sources":["../../../../src/components/defaults/adapters/connector-input.tsx"],"sourcesContent":["import type { ProviderName } from \"@pipe0/base\";\nimport { useMemo } from \"react\";\nimport { useFieldError } from \"../../../hooks/use-field-error.js\";\nimport { cn } from \"../../../lib/utils.js\";\nimport type { FieldHandle } from \"../../../types/field-handle.js\";\nimport { ProviderLogo } from \"../../../widgets/provider-logo.js\";\nimport { SuggestCombobox } from \"../../internal/combobox/suggest-combobox.js\";\nimport { IconPlus } from \"../../internal/icons.js\";\nimport { Button } from \"../../ui/button.js\";\n\nexport function ConnectorInputAdapter(field: FieldHandle<\"connector_input\">) {\n const connections = field.meta.filteredConnections ?? [];\n const value = field.value ?? null;\n const current = value?.connections ?? [];\n const error = useFieldError(field.form, field.path);\n const hasError = !!error;\n\n const options = useMemo(\n () =>\n connections.map((c) => ({\n value: c.connection,\n label: c.connection,\n })),\n [connections],\n );\n\n const providerByConnection = useMemo(() => {\n const map = new Map<string, string>();\n for (const c of connections) map.set(c.connection, c.provider);\n return map;\n }, [connections]);\n\n const renderLogo = (connectionId: string) => {\n const provider = providerByConnection.get(connectionId);\n if (!provider) return null;\n return <ProviderLogo provider={provider as ProviderName} size={16} />;\n };\n\n if (field.meta.connectorMode === \"disabled\") {\n return (\n <div\n data-p0=\"input\"\n className=\"pz:flex pz:items-center pz:rounded-md pz:border pz:border-input pz:bg-muted pz:px-3 pz:py-2 pz:opacity-60\"\n >\n <span className=\"pz:text-sm pz:text-muted-foreground\">\n Custom connections are not supported for this pipe.\n </span>\n </div>\n );\n }\n\n if (connections.length === 0) {\n return (\n <div\n data-p0=\"input\"\n className=\"pz:flex pz:flex-col pz:gap-2 pz:rounded-md pz:border pz:border-input pz:bg-transparent pz:px-3 pz:py-2\"\n >\n <span className=\"pz:text-xs pz:text-muted-foreground\">No connections available.</span>\n </div>\n );\n }\n\n if (value == null) {\n return (\n <div data-p0=\"input\" className=\"pz:flex pz:items-center\">\n <Button\n type=\"button\"\n variant=\"link\"\n size=\"xs\"\n className=\"pz:px-0\"\n onClick={() => field.setValue({ connections: [] })}\n >\n <IconPlus />\n Add custom connection\n </Button>\n </div>\n );\n }\n\n return (\n <div data-p0=\"input\" className=\"pz:flex pz:flex-col pz:gap-1\">\n <div className={cn(hasError && \"pz:[&_[data-slot=combobox-chips]]:border-destructive\")}>\n <SuggestCombobox\n value={current.map((c) => c.connection)}\n onChange={(next) =>\n field.setValue({\n ...value,\n connections: next.map((connection) => ({\n type: \"vault\",\n connection,\n })),\n })\n }\n options={options}\n iconFor={renderLogo}\n ariaInvalid={hasError}\n placeholder=\"Select a connection\"\n />\n </div>\n <div className=\"pz:flex pz:items-center pz:justify-end\">\n <Button type=\"button\" variant=\"link\" size=\"xs\" onClick={() => field.setValue(null)}>\n Reset\n </Button>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;AAUA,SAAgB,sBAAsB,OAAuC;CAC3E,MAAM,cAAc,MAAM,KAAK,uBAAuB,EAAE;CACxD,MAAM,QAAQ,MAAM,SAAS;CAC7B,MAAM,UAAU,OAAO,eAAe,EAAE;CAExC,MAAM,WAAW,CAAC,CADJ,cAAc,MAAM,MAAM,MAAM,KAAK;CAGnD,MAAM,UAAU,cAEZ,YAAY,KAAK,OAAO;EACtB,OAAO,EAAE;EACT,OAAO,EAAE;EACV,EAAE,EACL,CAAC,YAAY,CACd;CAED,MAAM,uBAAuB,cAAc;EACzC,MAAM,sBAAM,IAAI,KAAqB;AACrC,OAAK,MAAM,KAAK,YAAa,KAAI,IAAI,EAAE,YAAY,EAAE,SAAS;AAC9D,SAAO;IACN,CAAC,YAAY,CAAC;CAEjB,MAAM,cAAc,iBAAyB;EAC3C,MAAM,WAAW,qBAAqB,IAAI,aAAa;AACvD,MAAI,CAAC,SAAU,QAAO;AACtB,SAAO,oBAAC,cAAD;GAAwB;GAA0B,MAAM;GAAM;;AAGvE,KAAI,MAAM,KAAK,kBAAkB,WAC/B,QACE,oBAAC,OAAD;EACE,WAAQ;EACR,WAAU;YAEV,oBAAC,QAAD;GAAM,WAAU;aAAsC;GAE/C;EACH;AAIV,KAAI,YAAY,WAAW,EACzB,QACE,oBAAC,OAAD;EACE,WAAQ;EACR,WAAU;YAEV,oBAAC,QAAD;GAAM,WAAU;aAAsC;GAAgC;EAClF;AAIV,KAAI,SAAS,KACX,QACE,oBAAC,OAAD;EAAK,WAAQ;EAAQ,WAAU;YAC7B,qBAAC,QAAD;GACE,MAAK;GACL,SAAQ;GACR,MAAK;GACL,WAAU;GACV,eAAe,MAAM,SAAS,EAAE,aAAa,EAAE,EAAE,CAAC;aALpD,CAOE,oBAAC,UAAD,EAAY,2BAEL;;EACL;AAIV,QACE,qBAAC,OAAD;EAAK,WAAQ;EAAQ,WAAU;YAA/B,CACE,oBAAC,OAAD;GAAK,WAAW,GAAG,YAAY,uDAAuD;aACpF,oBAAC,iBAAD;IACE,OAAO,QAAQ,KAAK,MAAM,EAAE,WAAW;IACvC,WAAW,SACT,MAAM,SAAS;KACb,GAAG;KACH,aAAa,KAAK,KAAK,gBAAgB;MACrC,MAAM;MACN;MACD,EAAE;KACJ,CAAC;IAEK;IACT,SAAS;IACT,aAAa;IACb,aAAY;IACZ;GACE,GACN,oBAAC,OAAD;GAAK,WAAU;aACb,oBAAC,QAAD;IAAQ,MAAK;IAAS,SAAQ;IAAO,MAAK;IAAK,eAAe,MAAM,SAAS,KAAK;cAAE;IAE3E;GACL,EACF"}
1
+ {"version":3,"file":"connector-input.mjs","names":[],"sources":["../../../../src/components/defaults/adapters/connector-input.tsx"],"sourcesContent":["import type { ProviderName } from \"@pipe0/base\";\nimport { useMemo } from \"react\";\nimport { useFieldError } from \"../../../hooks/use-field-error.js\";\nimport { cn } from \"../../../lib/utils.js\";\nimport type { FieldHandle } from \"../../../types/field-handle.js\";\nimport { ProviderLogo } from \"../../../widgets/provider-logo.js\";\nimport { SuggestCombobox } from \"../../internal/combobox/suggest-combobox.js\";\nimport { IconPlus } from \"../../internal/icons.js\";\nimport { Button } from \"../../ui/button.js\";\n\nexport function ConnectorInputAdapter(field: FieldHandle<\"connector_input\">) {\n const connections = field.meta.filteredConnections ?? [];\n const value = field.value ?? null;\n const current = value?.connections ?? [];\n // The required-connector schema attaches its `.min(1)` failure to the\n // `connections` array, not the connector object itself; fall back to the\n // top-level path for whole-connector errors (e.g. a null required value).\n const connectionsError = useFieldError(field.form, `${field.path}.connections`);\n const connectorError = useFieldError(field.form, field.path);\n const error = connectionsError ?? connectorError;\n const hasError = !!error;\n\n const options = useMemo(\n () =>\n connections.map((c) => ({\n value: c.connection,\n label: c.connection,\n })),\n [connections],\n );\n\n const providerByConnection = useMemo(() => {\n const map = new Map<string, string>();\n for (const c of connections) map.set(c.connection, c.provider);\n return map;\n }, [connections]);\n\n const renderLogo = (connectionId: string) => {\n const provider = providerByConnection.get(connectionId);\n if (!provider) return null;\n return <ProviderLogo provider={provider as ProviderName} size={16} />;\n };\n\n if (field.meta.connectorMode === \"disabled\") {\n return (\n <div\n data-p0=\"input\"\n className=\"pz:flex pz:items-center pz:rounded-md pz:border pz:border-input pz:bg-muted pz:px-3 pz:py-2 pz:opacity-60\"\n >\n <span className=\"pz:text-sm pz:text-muted-foreground\">\n Custom connections are not supported for this pipe.\n </span>\n </div>\n );\n }\n\n if (connections.length === 0) {\n return (\n <div\n data-p0=\"input\"\n className=\"pz:flex pz:flex-col pz:gap-2 pz:rounded-md pz:border pz:border-input pz:bg-transparent pz:px-3 pz:py-2\"\n >\n <span className=\"pz:text-xs pz:text-muted-foreground\">No connections available.</span>\n </div>\n );\n }\n\n if (value == null) {\n return (\n <div data-p0=\"input\" className=\"pz:flex pz:items-center\">\n <Button\n type=\"button\"\n variant=\"link\"\n size=\"xs\"\n className=\"pz:px-0\"\n onClick={() => field.setValue({ connections: [] })}\n >\n <IconPlus />\n Add custom connection\n </Button>\n </div>\n );\n }\n\n return (\n <div data-p0=\"input\" className=\"pz:flex pz:flex-col pz:gap-1\">\n <div className={cn(hasError && \"pz:[&_[data-slot=combobox-chips]]:border-destructive\")}>\n <SuggestCombobox\n value={current.map((c) => c.connection)}\n onChange={(next) =>\n field.setValue({\n ...value,\n connections: next.map((connection) => ({\n type: \"vault\",\n connection,\n })),\n })\n }\n options={options}\n iconFor={renderLogo}\n ariaInvalid={hasError}\n placeholder=\"Select a connection\"\n />\n </div>\n {hasError && (\n <span className=\"pz:text-destructive pz:text-xs pz:font-medium\" role=\"alert\">\n {error}\n </span>\n )}\n <div className=\"pz:flex pz:items-center pz:justify-end\">\n <Button type=\"button\" variant=\"link\" size=\"xs\" onClick={() => field.setValue(null)}>\n Reset\n </Button>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;AAUA,SAAgB,sBAAsB,OAAuC;CAC3E,MAAM,cAAc,MAAM,KAAK,uBAAuB,EAAE;CACxD,MAAM,QAAQ,MAAM,SAAS;CAC7B,MAAM,UAAU,OAAO,eAAe,EAAE;CAIxC,MAAM,mBAAmB,cAAc,MAAM,MAAM,GAAG,MAAM,KAAK,cAAc;CAC/E,MAAM,iBAAiB,cAAc,MAAM,MAAM,MAAM,KAAK;CAC5D,MAAM,QAAQ,oBAAoB;CAClC,MAAM,WAAW,CAAC,CAAC;CAEnB,MAAM,UAAU,cAEZ,YAAY,KAAK,OAAO;EACtB,OAAO,EAAE;EACT,OAAO,EAAE;EACV,EAAE,EACL,CAAC,YAAY,CACd;CAED,MAAM,uBAAuB,cAAc;EACzC,MAAM,sBAAM,IAAI,KAAqB;AACrC,OAAK,MAAM,KAAK,YAAa,KAAI,IAAI,EAAE,YAAY,EAAE,SAAS;AAC9D,SAAO;IACN,CAAC,YAAY,CAAC;CAEjB,MAAM,cAAc,iBAAyB;EAC3C,MAAM,WAAW,qBAAqB,IAAI,aAAa;AACvD,MAAI,CAAC,SAAU,QAAO;AACtB,SAAO,oBAAC,cAAD;GAAwB;GAA0B,MAAM;GAAM;;AAGvE,KAAI,MAAM,KAAK,kBAAkB,WAC/B,QACE,oBAAC,OAAD;EACE,WAAQ;EACR,WAAU;YAEV,oBAAC,QAAD;GAAM,WAAU;aAAsC;GAE/C;EACH;AAIV,KAAI,YAAY,WAAW,EACzB,QACE,oBAAC,OAAD;EACE,WAAQ;EACR,WAAU;YAEV,oBAAC,QAAD;GAAM,WAAU;aAAsC;GAAgC;EAClF;AAIV,KAAI,SAAS,KACX,QACE,oBAAC,OAAD;EAAK,WAAQ;EAAQ,WAAU;YAC7B,qBAAC,QAAD;GACE,MAAK;GACL,SAAQ;GACR,MAAK;GACL,WAAU;GACV,eAAe,MAAM,SAAS,EAAE,aAAa,EAAE,EAAE,CAAC;aALpD,CAOE,oBAAC,UAAD,EAAY,2BAEL;;EACL;AAIV,QACE,qBAAC,OAAD;EAAK,WAAQ;EAAQ,WAAU;YAA/B;GACE,oBAAC,OAAD;IAAK,WAAW,GAAG,YAAY,uDAAuD;cACpF,oBAAC,iBAAD;KACE,OAAO,QAAQ,KAAK,MAAM,EAAE,WAAW;KACvC,WAAW,SACT,MAAM,SAAS;MACb,GAAG;MACH,aAAa,KAAK,KAAK,gBAAgB;OACrC,MAAM;OACN;OACD,EAAE;MACJ,CAAC;KAEK;KACT,SAAS;KACT,aAAa;KACb,aAAY;KACZ;IACE;GACL,YACC,oBAAC,QAAD;IAAM,WAAU;IAAgD,MAAK;cAClE;IACI;GAET,oBAAC,OAAD;IAAK,WAAU;cACb,oBAAC,QAAD;KAAQ,MAAK;KAAS,SAAQ;KAAO,MAAK;KAAK,eAAe,MAAM,SAAS,KAAK;eAAE;KAE3E;IACL;GACF"}
@@ -5,50 +5,26 @@ import { jsx, jsxs } from "react/jsx-runtime";
5
5
 
6
6
  //#region src/components/defaults/adapters/context-select-input.tsx
7
7
  function ContextSelectInputAdapter(field) {
8
- if (field.pending) return /* @__PURE__ */ jsx("div", {
9
- "data-p0": "input",
10
- className: cn("pz:opacity-60"),
11
- children: /* @__PURE__ */ jsxs(Select, {
12
- disabled: true,
13
- children: [/* @__PURE__ */ jsx(SelectTrigger, {
14
- className: "pz:w-full",
15
- children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Loading…" })
16
- }), /* @__PURE__ */ jsx(SelectContent, {})]
17
- })
18
- });
19
- if (field.suggestionsDisabled) return /* @__PURE__ */ jsxs("div", {
20
- "data-p0": "input",
21
- className: "pz:flex pz:flex-col pz:gap-1.5",
22
- children: [/* @__PURE__ */ jsxs(Select, {
23
- disabled: true,
24
- children: [/* @__PURE__ */ jsx(SelectTrigger, {
25
- className: "pz:w-full",
26
- children: /* @__PURE__ */ jsx(SelectValue, { placeholder: field.meta.placeholder ?? "Select" })
27
- }), /* @__PURE__ */ jsx(SelectContent, {})]
28
- }), /* @__PURE__ */ jsxs("div", {
29
- className: "pz:text-xs pz:gap-y-1 pz:text-muted-foreground pz:italic",
30
- children: [field.suggestionsDisabledReason ?? "Suggestions unavailable", " "]
31
- })]
32
- });
33
8
  const hasOptions = field.options.length > 0;
34
9
  const selectedOption = field.options.find((o) => o.value === field.selectedValue);
10
+ const placeholder = field.pending ? "Loading…" : field.meta.placeholder ?? (field.suggestionsDisabled ? "Select" : "— Select —");
35
11
  return /* @__PURE__ */ jsxs("div", {
36
12
  "data-p0": "input",
37
- className: "pz:flex pz:flex-col pz:gap-1",
13
+ className: cn("pz:flex pz:flex-col pz:gap-1", field.pending && "pz:opacity-60"),
38
14
  children: [/* @__PURE__ */ jsxs(Select, {
39
- value: field.selectedValue || void 0,
15
+ value: field.selectedValue || null,
40
16
  onValueChange: (v) => {
41
17
  if (v === null) return;
42
18
  field.onSelect(v);
43
19
  },
44
20
  name: field.path,
45
- disabled: !hasOptions,
21
+ disabled: field.pending || field.suggestionsDisabled || !hasOptions,
46
22
  children: [/* @__PURE__ */ jsx(SelectTrigger, {
47
23
  id: field.id,
48
24
  "aria-invalid": !!field.error,
49
25
  className: "pz:w-full",
50
26
  children: /* @__PURE__ */ jsx(SelectValue, {
51
- placeholder: field.meta.placeholder ?? "— Select —",
27
+ placeholder,
52
28
  children: selectedOption ? /* @__PURE__ */ jsxs("span", {
53
29
  className: "pz:flex pz:items-center pz:gap-2",
54
30
  children: [/* @__PURE__ */ jsx(WidgetStrip, { widgets: selectedOption.widgets }), /* @__PURE__ */ jsx("span", { children: selectedOption.label })]
@@ -62,10 +38,13 @@ function ContextSelectInputAdapter(field) {
62
38
  children: [/* @__PURE__ */ jsx(WidgetStrip, { widgets: opt.widgets }), /* @__PURE__ */ jsx("span", { children: opt.label })]
63
39
  })
64
40
  }, opt.value)) })]
65
- }), !hasOptions && /* @__PURE__ */ jsx("span", {
41
+ }), field.suggestionsDisabled ? /* @__PURE__ */ jsxs("div", {
42
+ className: "pz:text-xs pz:gap-y-1 pz:text-muted-foreground pz:italic",
43
+ children: [field.suggestionsDisabledReason ?? "Suggestions unavailable", " "]
44
+ }) : !field.pending && !hasOptions ? /* @__PURE__ */ jsx("span", {
66
45
  className: "pz:text-xs pz:text-muted-foreground",
67
46
  children: "No fields available"
68
- })]
47
+ }) : null]
69
48
  });
70
49
  }
71
50
 
@@ -1 +1 @@
1
- {"version":3,"file":"context-select-input.mjs","names":[],"sources":["../../../../src/components/defaults/adapters/context-select-input.tsx"],"sourcesContent":["import type { StoreOption } from \"@pipe0/base\";\nimport { cn } from \"../../../lib/utils.js\";\nimport type { FieldHandle } from \"../../../types/field-handle.js\";\nimport { WidgetStrip } from \"../../../widgets/widget-strip.js\";\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from \"../../ui/select.js\";\n\nexport function ContextSelectInputAdapter(field: FieldHandle<\"context_select_input\">) {\n if (field.pending) {\n return (\n <div data-p0=\"input\" className={cn(\"pz:opacity-60\")}>\n <Select disabled>\n <SelectTrigger className=\"pz:w-full\">\n <SelectValue placeholder=\"Loading…\" />\n </SelectTrigger>\n <SelectContent />\n </Select>\n </div>\n );\n }\n\n // Suggestions sub-feature gated. The input itself is disabled when there\n // are no options to choose from. The gating reason renders as a muted\n // info card directly below the input matching the suggestions popover\n // styling used by the tagged-text-input adapter.\n if (field.suggestionsDisabled) {\n return (\n <div data-p0=\"input\" className=\"pz:flex pz:flex-col pz:gap-1.5\">\n <Select disabled>\n <SelectTrigger className=\"pz:w-full\">\n <SelectValue placeholder={field.meta.placeholder ?? \"Select\"} />\n </SelectTrigger>\n <SelectContent />\n </Select>\n <div className=\"pz:text-xs pz:gap-y-1 pz:text-muted-foreground pz:italic\">\n {field.suggestionsDisabledReason ?? \"Suggestions unavailable\"}{\" \"}\n </div>\n </div>\n );\n }\n\n const hasOptions = field.options.length > 0;\n const selectedOption = field.options.find((o) => o.value === field.selectedValue);\n\n return (\n <div data-p0=\"input\" className=\"pz:flex pz:flex-col pz:gap-1\">\n <Select\n value={field.selectedValue || undefined}\n onValueChange={(v) => {\n if (v === null) return;\n field.onSelect(v);\n }}\n name={field.path}\n disabled={!hasOptions}\n >\n <SelectTrigger id={field.id} aria-invalid={!!field.error} className=\"pz:w-full\">\n <SelectValue placeholder={field.meta.placeholder ?? \"— Select —\"}>\n {selectedOption ? (\n <span className=\"pz:flex pz:items-center pz:gap-2\">\n <WidgetStrip widgets={selectedOption.widgets} />\n <span>{selectedOption.label}</span>\n </span>\n ) : undefined}\n </SelectValue>\n </SelectTrigger>\n <SelectContent>\n {field.options.map((opt: StoreOption) => (\n <SelectItem key={opt.value} value={opt.value} label={opt.label}>\n <span className=\"pz:flex pz:items-center pz:gap-2\">\n <WidgetStrip widgets={opt.widgets} />\n <span>{opt.label}</span>\n </span>\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {!hasOptions && (\n <span className=\"pz:text-xs pz:text-muted-foreground\">No fields available</span>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;;AAMA,SAAgB,0BAA0B,OAA4C;AACpF,KAAI,MAAM,QACR,QACE,oBAAC,OAAD;EAAK,WAAQ;EAAQ,WAAW,GAAG,gBAAgB;YACjD,qBAAC,QAAD;GAAQ;aAAR,CACE,oBAAC,eAAD;IAAe,WAAU;cACvB,oBAAC,aAAD,EAAa,aAAY,YAAa;IACxB,GAChB,oBAAC,eAAD,EAAiB,EACV;;EACL;AAQV,KAAI,MAAM,oBACR,QACE,qBAAC,OAAD;EAAK,WAAQ;EAAQ,WAAU;YAA/B,CACE,qBAAC,QAAD;GAAQ;aAAR,CACE,oBAAC,eAAD;IAAe,WAAU;cACvB,oBAAC,aAAD,EAAa,aAAa,MAAM,KAAK,eAAe,UAAY;IAClD,GAChB,oBAAC,eAAD,EAAiB,EACV;MACT,qBAAC,OAAD;GAAK,WAAU;aAAf,CACG,MAAM,6BAA6B,2BAA2B,IAC3D;KACF;;CAIV,MAAM,aAAa,MAAM,QAAQ,SAAS;CAC1C,MAAM,iBAAiB,MAAM,QAAQ,MAAM,MAAM,EAAE,UAAU,MAAM,cAAc;AAEjF,QACE,qBAAC,OAAD;EAAK,WAAQ;EAAQ,WAAU;YAA/B,CACE,qBAAC,QAAD;GACE,OAAO,MAAM,iBAAiB;GAC9B,gBAAgB,MAAM;AACpB,QAAI,MAAM,KAAM;AAChB,UAAM,SAAS,EAAE;;GAEnB,MAAM,MAAM;GACZ,UAAU,CAAC;aAPb,CASE,oBAAC,eAAD;IAAe,IAAI,MAAM;IAAI,gBAAc,CAAC,CAAC,MAAM;IAAO,WAAU;cAClE,oBAAC,aAAD;KAAa,aAAa,MAAM,KAAK,eAAe;eACjD,iBACC,qBAAC,QAAD;MAAM,WAAU;gBAAhB,CACE,oBAAC,aAAD,EAAa,SAAS,eAAe,SAAW,GAChD,oBAAC,QAAD,YAAO,eAAe,OAAa,EAC9B;UACL;KACQ;IACA,GAChB,oBAAC,eAAD,YACG,MAAM,QAAQ,KAAK,QAClB,oBAAC,YAAD;IAA4B,OAAO,IAAI;IAAO,OAAO,IAAI;cACvD,qBAAC,QAAD;KAAM,WAAU;eAAhB,CACE,oBAAC,aAAD,EAAa,SAAS,IAAI,SAAW,GACrC,oBAAC,QAAD,YAAO,IAAI,OAAa,EACnB;;IACI,EALI,IAAI,MAKR,CACb,EACY,EACT;MACR,CAAC,cACA,oBAAC,QAAD;GAAM,WAAU;aAAsC;GAA0B,EAE9E"}
1
+ {"version":3,"file":"context-select-input.mjs","names":[],"sources":["../../../../src/components/defaults/adapters/context-select-input.tsx"],"sourcesContent":["import type { StoreOption } from \"@pipe0/base\";\nimport { cn } from \"../../../lib/utils.js\";\nimport type { FieldHandle } from \"../../../types/field-handle.js\";\nimport { WidgetStrip } from \"../../../widgets/widget-strip.js\";\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from \"../../ui/select.js\";\n\nexport function ContextSelectInputAdapter(field: FieldHandle<\"context_select_input\">) {\n const hasOptions = field.options.length > 0;\n const selectedOption = field.options.find((o) => o.value === field.selectedValue);\n\n // ONE always-controlled Select across every state (loading / gated / ready).\n // Rendering a separate <Select> tree per state or using\n // `value={... || undefined}` — flips Base UI between uncontrolled and\n // controlled, which warns and now actually fires on the loading→ready\n // transition (the field finally re-renders through it). `null` is Base UI's\n // controlled \"no selection\" sentinel (cf. connector-input + the `v === null`\n // guard below), so the value is never `undefined` and the control stays\n // controlled for its whole lifetime. State differences are expressed only via\n // `disabled` / `placeholder` / the helper line below — not via remounting.\n const placeholder = field.pending\n ? \"Loading…\"\n : (field.meta.placeholder ?? (field.suggestionsDisabled ? \"Select\" : \"— Select —\"));\n\n return (\n <div\n data-p0=\"input\"\n className={cn(\"pz:flex pz:flex-col pz:gap-1\", field.pending && \"pz:opacity-60\")}\n >\n <Select\n value={field.selectedValue || null}\n onValueChange={(v) => {\n if (v === null) return;\n field.onSelect(v);\n }}\n name={field.path}\n disabled={field.pending || field.suggestionsDisabled || !hasOptions}\n >\n <SelectTrigger id={field.id} aria-invalid={!!field.error} className=\"pz:w-full\">\n <SelectValue placeholder={placeholder}>\n {selectedOption ? (\n <span className=\"pz:flex pz:items-center pz:gap-2\">\n <WidgetStrip widgets={selectedOption.widgets} />\n <span>{selectedOption.label}</span>\n </span>\n ) : undefined}\n </SelectValue>\n </SelectTrigger>\n <SelectContent>\n {field.options.map((opt: StoreOption) => (\n <SelectItem key={opt.value} value={opt.value} label={opt.label}>\n <span className=\"pz:flex pz:items-center pz:gap-2\">\n <WidgetStrip widgets={opt.widgets} />\n <span>{opt.label}</span>\n </span>\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {field.suggestionsDisabled ? (\n <div className=\"pz:text-xs pz:gap-y-1 pz:text-muted-foreground pz:italic\">\n {field.suggestionsDisabledReason ?? \"Suggestions unavailable\"}{\" \"}\n </div>\n ) : !field.pending && !hasOptions ? (\n <span className=\"pz:text-xs pz:text-muted-foreground\">No fields available</span>\n ) : null}\n </div>\n );\n}\n"],"mappings":";;;;;;AAMA,SAAgB,0BAA0B,OAA4C;CACpF,MAAM,aAAa,MAAM,QAAQ,SAAS;CAC1C,MAAM,iBAAiB,MAAM,QAAQ,MAAM,MAAM,EAAE,UAAU,MAAM,cAAc;CAWjF,MAAM,cAAc,MAAM,UACtB,aACC,MAAM,KAAK,gBAAgB,MAAM,sBAAsB,WAAW;AAEvE,QACE,qBAAC,OAAD;EACE,WAAQ;EACR,WAAW,GAAG,gCAAgC,MAAM,WAAW,gBAAgB;YAFjF,CAIE,qBAAC,QAAD;GACE,OAAO,MAAM,iBAAiB;GAC9B,gBAAgB,MAAM;AACpB,QAAI,MAAM,KAAM;AAChB,UAAM,SAAS,EAAE;;GAEnB,MAAM,MAAM;GACZ,UAAU,MAAM,WAAW,MAAM,uBAAuB,CAAC;aAP3D,CASE,oBAAC,eAAD;IAAe,IAAI,MAAM;IAAI,gBAAc,CAAC,CAAC,MAAM;IAAO,WAAU;cAClE,oBAAC,aAAD;KAA0B;eACvB,iBACC,qBAAC,QAAD;MAAM,WAAU;gBAAhB,CACE,oBAAC,aAAD,EAAa,SAAS,eAAe,SAAW,GAChD,oBAAC,QAAD,YAAO,eAAe,OAAa,EAC9B;UACL;KACQ;IACA,GAChB,oBAAC,eAAD,YACG,MAAM,QAAQ,KAAK,QAClB,oBAAC,YAAD;IAA4B,OAAO,IAAI;IAAO,OAAO,IAAI;cACvD,qBAAC,QAAD;KAAM,WAAU;eAAhB,CACE,oBAAC,aAAD,EAAa,SAAS,IAAI,SAAW,GACrC,oBAAC,QAAD,YAAO,IAAI,OAAa,EACnB;;IACI,EALI,IAAI,MAKR,CACb,EACY,EACT;MACR,MAAM,sBACL,qBAAC,OAAD;GAAK,WAAU;aAAf,CACG,MAAM,6BAA6B,2BAA2B,IAC3D;OACJ,CAAC,MAAM,WAAW,CAAC,aACrB,oBAAC,QAAD;GAAM,WAAU;aAAsC;GAA0B,IAC9E,KACA"}
@@ -65,7 +65,7 @@ function ConditionRow({ condition, index, eligibleFields, fieldsByName, isFirst,
65
65
  "aria-invalid": !!valueError
66
66
  });
67
67
  if (condition.property === "status") return /* @__PURE__ */ jsxs(Select, {
68
- value: String(condition.value) || void 0,
68
+ value: String(condition.value) || null,
69
69
  onValueChange: (v) => onUpdate(index, {
70
70
  ...condition,
71
71
  value: v
@@ -188,7 +188,7 @@ function ConditionRow({ condition, index, eligibleFields, fieldsByName, isFirst,
188
188
  onRemove
189
189
  }),
190
190
  /* @__PURE__ */ jsxs(Select, {
191
- value: condition.field_name || void 0,
191
+ value: condition.field_name || null,
192
192
  disabled: !hasEligibleFields,
193
193
  onValueChange: (v) => {
194
194
  if (v === null) return;
@@ -1 +1 @@
1
- {"version":3,"file":"pipes-run-if-input.mjs","names":[],"sources":["../../../../src/components/defaults/adapters/pipes-run-if-input.tsx"],"sourcesContent":["import {\n type ConditionOperators,\n type PipeRunIf,\n type PipesRunIfMeta,\n type RecordFieldType,\n RUN_IF_OPERATOR_LABELS,\n RUN_IF_STATUS_OPERATORS,\n RUN_IF_VALUE_OPERATORS,\n} from \"@pipe0/base\";\nimport { useCallback, useMemo } from \"react\";\nimport { useFieldError } from \"../../../hooks/use-field-error.js\";\nimport { cn } from \"../../../lib/utils.js\";\nimport type { FieldHandle } from \"../../../types/field-handle.js\";\nimport type { FormHandle } from \"../../../types/form-handle.js\";\nimport { HoverInfo } from \"../../hover-info.js\";\nimport { IconPlus } from \"../../internal/icons.js\";\nimport { Badge } from \"../../ui/badge.js\";\nimport { Button } from \"../../ui/button.js\";\nimport { Input } from \"../../ui/input.js\";\nimport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"../../ui/select.js\";\nimport { FieldSectionEnumeration } from \"../field-section-enumeration.js\";\n\n// Use a loose type for internal manipulation since the discriminated union\n// is strict about property/operator/value combinations.\ntype Condition = {\n field_name: string;\n property: string;\n operator: string;\n value: unknown;\n};\n\nconst OPERATORS_BY_TYPE: Record<RecordFieldType, ConditionOperators[]> = {\n string: [\"eq\", \"neq\", \"contains\"],\n number: [\"eq\", \"neq\", \"gt\", \"gte\", \"lt\", \"lte\"],\n boolean: [\"eq\", \"neq\"],\n json: [],\n unknown: [],\n};\n\nconst EMPTY_CONDITION: Condition = {\n field_name: \"\",\n property: \"value\",\n operator: \"eq\",\n value: \"\",\n};\n\nconst CONNECTOR_GAP = 32;\n\ntype MetaField = {\n fieldName: string;\n fieldLabel: string;\n type: RecordFieldType;\n format: string | null;\n};\n\nfunction ConditionRow({\n condition,\n index,\n eligibleFields,\n fieldsByName,\n isFirst,\n isLast,\n logic,\n form,\n basePath,\n onUpdate,\n onRemove,\n onAddCondition,\n onLogicChange,\n}: {\n condition: Condition;\n index: number;\n eligibleFields: MetaField[];\n fieldsByName: ReadonlyMap<string, MetaField>;\n isFirst: boolean;\n isLast: boolean;\n logic: PipeRunIf[\"when\"][\"logic\"];\n form: FormHandle;\n basePath: string;\n onUpdate: (index: number, condition: Condition) => void;\n onRemove: (index: number) => void;\n onAddCondition: () => void;\n onLogicChange: (logic: PipeRunIf[\"when\"][\"logic\"]) => void;\n}) {\n const conditionPath = `${basePath}.when.conditions.${index}`;\n const valueError = useFieldError(form, `${conditionPath}.value`);\n const fieldNameError = useFieldError(form, `${conditionPath}.field_name`);\n const operatorError = useFieldError(form, `${conditionPath}.operator`);\n const propertyError = useFieldError(form, `${conditionPath}.property`);\n\n const showConnector = !(isFirst && isLast);\n const hasEligibleFields = eligibleFields.length > 0;\n const selectedField = condition.field_name ? fieldsByName.get(condition.field_name) : undefined;\n\n const availableOperators = useMemo(() => {\n if (condition.property === \"status\") {\n return RUN_IF_STATUS_OPERATORS.map((op) => ({\n value: op,\n label: RUN_IF_OPERATOR_LABELS[op],\n }));\n }\n if (!selectedField?.type) return [];\n return RUN_IF_VALUE_OPERATORS.map((op) => ({\n value: op,\n label: RUN_IF_OPERATOR_LABELS[op],\n })).filter((op) => OPERATORS_BY_TYPE[selectedField.type].includes(op.value));\n }, [condition.property, selectedField]);\n\n const renderValueInput = () => {\n if (!condition.field_name || !selectedField) {\n return <Input className=\"pz:w-32\" placeholder=\"\" disabled aria-invalid={!!valueError} />;\n }\n\n if (condition.property === \"status\") {\n return (\n <Select\n value={String(condition.value) || undefined}\n onValueChange={(v) => onUpdate(index, { ...condition, value: v })}\n >\n <SelectTrigger className=\"pz:w-32\" aria-invalid={!!valueError}>\n <SelectValue placeholder=\"--status--\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"completed\">completed</SelectItem>\n <SelectItem value=\"skipped\">skipped</SelectItem>\n <SelectItem value=\"failed\">failed</SelectItem>\n <SelectItem value=\"no_result\">no_result</SelectItem>\n </SelectContent>\n </Select>\n );\n }\n\n if (selectedField.type === \"boolean\") {\n return (\n <Select\n value={String(condition.value)}\n onValueChange={(v) => onUpdate(index, { ...condition, value: v })}\n >\n <SelectTrigger className=\"pz:w-24\" aria-invalid={!!valueError}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"true\">true</SelectItem>\n <SelectItem value=\"false\">false</SelectItem>\n </SelectContent>\n </Select>\n );\n }\n\n if (selectedField.type === \"number\") {\n return (\n <Input\n type=\"number\"\n className=\"pz:w-32\"\n aria-invalid={!!valueError}\n value={String(Number(condition.value ?? 0))}\n onChange={(e) =>\n onUpdate(index, {\n ...condition,\n value: Number(e.target.value) || 0,\n })\n }\n placeholder=\"\"\n />\n );\n }\n\n return (\n <Input\n className=\"pz:w-32\"\n aria-invalid={!!valueError}\n value={String(condition.value ?? \"\")}\n onChange={(e) => onUpdate(index, { ...condition, value: e.target.value })}\n placeholder=\"\"\n />\n );\n };\n\n const errorMessage = valueError || fieldNameError || operatorError || propertyError;\n\n return (\n <div>\n <div className={cn(\"pz:relative\", showConnector && \"pz:pl-17\")}>\n {showConnector && (\n <>\n {isFirst ? (\n <div\n className=\"pz:absolute pz:left-7 pz:w-10 pz:border-l-2 pz:border-t-2 pz:border-input pz:rounded-tl-lg pz:pointer-events-none\"\n style={{ top: \"50%\", bottom: -CONNECTOR_GAP }}\n />\n ) : (\n <div\n className=\"pz:absolute pz:left-7 pz:w-10 pz:border-l-2 pz:border-b-2 pz:border-input pz:rounded-bl-lg pz:pointer-events-none\"\n style={{ top: -CONNECTOR_GAP, bottom: \"50%\" }}\n />\n )}\n {!isFirst && !isLast && (\n <div\n className=\"pz:absolute pz:left-7 pz:border-l-2 pz:border-input pz:pointer-events-none\"\n style={{ top: \"50%\", bottom: -CONNECTOR_GAP }}\n />\n )}\n {!isFirst && (\n <div\n className=\"pz:absolute pz:left-7 pz:z-10\"\n style={{\n top: -CONNECTOR_GAP / 2,\n transform: \"translate(-50%, -50%)\",\n }}\n >\n <Select value={logic} onValueChange={(v) => onLogicChange(v as \"and\" | \"or\")}>\n <SelectTrigger className=\"pz:w-17 pz:h-6 pz:text-xs pz:bg-background pz:hover:bg-accent\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectGroup>\n <SelectItem value=\"and\">AND</SelectItem>\n <SelectItem value=\"or\">OR</SelectItem>\n </SelectGroup>\n </SelectContent>\n </Select>\n </div>\n )}\n </>\n )}\n <div className=\"pz:flex pz:flex-wrap pz:items-center pz:gap-2\">\n <FieldSectionEnumeration index={index} onRemove={onRemove} />\n <Select\n value={condition.field_name || undefined}\n disabled={!hasEligibleFields}\n onValueChange={(v) => {\n if (v === null) return;\n onUpdate(index, {\n ...condition,\n field_name: v,\n operator: \"eq\",\n value: \"\",\n });\n }}\n >\n <SelectTrigger className=\"pz:w-40\" aria-invalid={!!fieldNameError}>\n <SelectValue placeholder=\"Select field\" />\n </SelectTrigger>\n <SelectContent>\n {eligibleFields.map((f) => (\n <SelectItem key={f.fieldName} value={f.fieldName}>\n {f.fieldLabel || f.fieldName}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {!hasEligibleFields && (\n <span className=\"pz:text-xs pz:text-muted-foreground\">\n No fields available{\" \"}\n <HoverInfo>Conditions require plain fields. JSON fields are not allowed.</HoverInfo>\n </span>\n )}\n\n {selectedField?.type && (\n <>\n <Badge\n variant=\"secondary\"\n className=\"pz:bg-accent pz:border pz:border-input pz:font-normal pz:text-muted-foreground pz:h-8\"\n >\n &apos;s\n </Badge>\n <Select\n defaultValue=\"value\"\n value={condition.property}\n onValueChange={(v) => {\n if (v === null) return;\n onUpdate(index, {\n ...condition,\n property: v,\n operator: \"eq\",\n value: \"\",\n });\n }}\n >\n <SelectTrigger className=\"pz:w-28\" aria-invalid={!!propertyError}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"value\">value</SelectItem>\n <SelectItem value=\"status\">status</SelectItem>\n </SelectContent>\n </Select>\n\n <Select\n value={condition.operator}\n onValueChange={(v) =>\n onUpdate(index, {\n ...condition,\n operator: v as ConditionOperators,\n })\n }\n >\n <SelectTrigger className=\"pz:w-28\" aria-invalid={!!operatorError}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {availableOperators.map((op) => (\n <SelectItem key={op.value} value={op.value}>\n {op.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n\n {renderValueInput()}\n </>\n )}\n </div>\n {errorMessage && (\n <span\n className=\"pz:text-destructive pz:text-xs pz:font-medium pz:mt-1 pz:block\"\n role=\"alert\"\n >\n {errorMessage}\n </span>\n )}\n </div>\n {isLast && (\n <div className=\"pz:flex pz:items-center pz:gap-2\">\n <Button type=\"button\" variant=\"link\" size=\"xs\" onClick={onAddCondition}>\n <IconPlus />\n New rule\n </Button>\n </div>\n )}\n </div>\n );\n}\n\nexport function PipesRunIfInputAdapter(field: FieldHandle<\"pipes_run_if_input\">) {\n const pipeRunIf = field.value as PipeRunIf | null;\n const meta = field.meta as PipesRunIfMeta;\n\n // Built once per render of the adapter and reused across every condition\n // row, instead of each row scanning `meta.fields` linearly. With N rows and\n // M fields this turns O(N·M) lookups into O(N+M).\n const eligibleFields = useMemo(\n () => meta.fields.filter((f) => OPERATORS_BY_TYPE[f.type].length > 0),\n [meta.fields],\n );\n const fieldsByName = useMemo(\n () => new Map(meta.fields.map((f) => [f.fieldName, f])),\n [meta.fields],\n );\n\n const addRunIf = useCallback(() => {\n field.setValue({\n action: \"run\",\n when: {\n logic: \"and\",\n conditions: [{ ...EMPTY_CONDITION }],\n },\n });\n }, [field]);\n\n const updateCondition = (index: number, condition: Condition) => {\n if (!pipeRunIf) return;\n const newConditions = [...pipeRunIf.when.conditions] as Condition[];\n newConditions[index] = condition;\n field.setValue({\n ...pipeRunIf,\n when: { ...pipeRunIf.when, conditions: newConditions },\n });\n };\n\n const removeCondition = (index: number) => {\n if (!pipeRunIf) return;\n if (pipeRunIf.when.conditions.length <= 1) {\n field.setValue(null);\n return;\n }\n const newConditions = pipeRunIf.when.conditions.filter((_, i) => i !== index);\n field.setValue({\n ...pipeRunIf,\n when: { ...pipeRunIf.when, conditions: newConditions },\n });\n };\n\n const addCondition = () => {\n if (!pipeRunIf) return;\n field.setValue({\n ...pipeRunIf,\n when: {\n ...pipeRunIf.when,\n conditions: [...pipeRunIf.when.conditions, { ...EMPTY_CONDITION }],\n },\n });\n };\n\n const changeLogic = (logic: \"and\" | \"or\") => {\n if (!pipeRunIf) return;\n field.setValue({\n ...pipeRunIf,\n when: { ...pipeRunIf.when, logic },\n });\n };\n\n return (\n <div data-p0=\"input\">\n {!pipeRunIf ? (\n <div className=\"pz:flex pz:items-center\">\n <Button type=\"button\" variant=\"link\" size=\"xs\" className=\"pz:px-0\" onClick={addRunIf}>\n <IconPlus />\n New rule\n </Button>\n </div>\n ) : (\n <div className=\"pz:flex pz:flex-col pz:gap-8\">\n {pipeRunIf.when.conditions.map((condition, idx) => (\n <ConditionRow\n key={idx}\n condition={condition}\n index={idx}\n eligibleFields={eligibleFields}\n fieldsByName={fieldsByName}\n isFirst={idx === 0}\n isLast={idx === pipeRunIf.when.conditions.length - 1}\n logic={pipeRunIf.when.logic}\n form={field.form}\n basePath={field.path}\n onUpdate={updateCondition}\n onRemove={removeCondition}\n onAddCondition={addCondition}\n onLogicChange={changeLogic}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"pipes-run-if-input.mjs","names":[],"sources":["../../../../src/components/defaults/adapters/pipes-run-if-input.tsx"],"sourcesContent":["import {\n type ConditionOperators,\n type PipeRunIf,\n type PipesRunIfMeta,\n type RecordFieldType,\n RUN_IF_OPERATOR_LABELS,\n RUN_IF_STATUS_OPERATORS,\n RUN_IF_VALUE_OPERATORS,\n} from \"@pipe0/base\";\nimport { useCallback, useMemo } from \"react\";\nimport { useFieldError } from \"../../../hooks/use-field-error.js\";\nimport { cn } from \"../../../lib/utils.js\";\nimport type { FieldHandle } from \"../../../types/field-handle.js\";\nimport type { FormHandle } from \"../../../types/form-handle.js\";\nimport { HoverInfo } from \"../../hover-info.js\";\nimport { IconPlus } from \"../../internal/icons.js\";\nimport { Badge } from \"../../ui/badge.js\";\nimport { Button } from \"../../ui/button.js\";\nimport { Input } from \"../../ui/input.js\";\nimport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"../../ui/select.js\";\nimport { FieldSectionEnumeration } from \"../field-section-enumeration.js\";\n\n// Use a loose type for internal manipulation since the discriminated union\n// is strict about property/operator/value combinations.\ntype Condition = {\n field_name: string;\n property: string;\n operator: string;\n value: unknown;\n};\n\nconst OPERATORS_BY_TYPE: Record<RecordFieldType, ConditionOperators[]> = {\n string: [\"eq\", \"neq\", \"contains\"],\n number: [\"eq\", \"neq\", \"gt\", \"gte\", \"lt\", \"lte\"],\n boolean: [\"eq\", \"neq\"],\n json: [],\n unknown: [],\n};\n\nconst EMPTY_CONDITION: Condition = {\n field_name: \"\",\n property: \"value\",\n operator: \"eq\",\n value: \"\",\n};\n\nconst CONNECTOR_GAP = 32;\n\ntype MetaField = {\n fieldName: string;\n fieldLabel: string;\n type: RecordFieldType;\n format: string | null;\n};\n\nfunction ConditionRow({\n condition,\n index,\n eligibleFields,\n fieldsByName,\n isFirst,\n isLast,\n logic,\n form,\n basePath,\n onUpdate,\n onRemove,\n onAddCondition,\n onLogicChange,\n}: {\n condition: Condition;\n index: number;\n eligibleFields: MetaField[];\n fieldsByName: ReadonlyMap<string, MetaField>;\n isFirst: boolean;\n isLast: boolean;\n logic: PipeRunIf[\"when\"][\"logic\"];\n form: FormHandle;\n basePath: string;\n onUpdate: (index: number, condition: Condition) => void;\n onRemove: (index: number) => void;\n onAddCondition: () => void;\n onLogicChange: (logic: PipeRunIf[\"when\"][\"logic\"]) => void;\n}) {\n const conditionPath = `${basePath}.when.conditions.${index}`;\n const valueError = useFieldError(form, `${conditionPath}.value`);\n const fieldNameError = useFieldError(form, `${conditionPath}.field_name`);\n const operatorError = useFieldError(form, `${conditionPath}.operator`);\n const propertyError = useFieldError(form, `${conditionPath}.property`);\n\n const showConnector = !(isFirst && isLast);\n const hasEligibleFields = eligibleFields.length > 0;\n const selectedField = condition.field_name ? fieldsByName.get(condition.field_name) : undefined;\n\n const availableOperators = useMemo(() => {\n if (condition.property === \"status\") {\n return RUN_IF_STATUS_OPERATORS.map((op) => ({\n value: op,\n label: RUN_IF_OPERATOR_LABELS[op],\n }));\n }\n if (!selectedField?.type) return [];\n return RUN_IF_VALUE_OPERATORS.map((op) => ({\n value: op,\n label: RUN_IF_OPERATOR_LABELS[op],\n })).filter((op) => OPERATORS_BY_TYPE[selectedField.type].includes(op.value));\n }, [condition.property, selectedField]);\n\n const renderValueInput = () => {\n if (!condition.field_name || !selectedField) {\n return <Input className=\"pz:w-32\" placeholder=\"\" disabled aria-invalid={!!valueError} />;\n }\n\n if (condition.property === \"status\") {\n return (\n <Select\n value={String(condition.value) || null}\n onValueChange={(v) => onUpdate(index, { ...condition, value: v })}\n >\n <SelectTrigger className=\"pz:w-32\" aria-invalid={!!valueError}>\n <SelectValue placeholder=\"--status--\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"completed\">completed</SelectItem>\n <SelectItem value=\"skipped\">skipped</SelectItem>\n <SelectItem value=\"failed\">failed</SelectItem>\n <SelectItem value=\"no_result\">no_result</SelectItem>\n </SelectContent>\n </Select>\n );\n }\n\n if (selectedField.type === \"boolean\") {\n return (\n <Select\n value={String(condition.value)}\n onValueChange={(v) => onUpdate(index, { ...condition, value: v })}\n >\n <SelectTrigger className=\"pz:w-24\" aria-invalid={!!valueError}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"true\">true</SelectItem>\n <SelectItem value=\"false\">false</SelectItem>\n </SelectContent>\n </Select>\n );\n }\n\n if (selectedField.type === \"number\") {\n return (\n <Input\n type=\"number\"\n className=\"pz:w-32\"\n aria-invalid={!!valueError}\n value={String(Number(condition.value ?? 0))}\n onChange={(e) =>\n onUpdate(index, {\n ...condition,\n value: Number(e.target.value) || 0,\n })\n }\n placeholder=\"\"\n />\n );\n }\n\n return (\n <Input\n className=\"pz:w-32\"\n aria-invalid={!!valueError}\n value={String(condition.value ?? \"\")}\n onChange={(e) => onUpdate(index, { ...condition, value: e.target.value })}\n placeholder=\"\"\n />\n );\n };\n\n const errorMessage = valueError || fieldNameError || operatorError || propertyError;\n\n return (\n <div>\n <div className={cn(\"pz:relative\", showConnector && \"pz:pl-17\")}>\n {showConnector && (\n <>\n {isFirst ? (\n <div\n className=\"pz:absolute pz:left-7 pz:w-10 pz:border-l-2 pz:border-t-2 pz:border-input pz:rounded-tl-lg pz:pointer-events-none\"\n style={{ top: \"50%\", bottom: -CONNECTOR_GAP }}\n />\n ) : (\n <div\n className=\"pz:absolute pz:left-7 pz:w-10 pz:border-l-2 pz:border-b-2 pz:border-input pz:rounded-bl-lg pz:pointer-events-none\"\n style={{ top: -CONNECTOR_GAP, bottom: \"50%\" }}\n />\n )}\n {!isFirst && !isLast && (\n <div\n className=\"pz:absolute pz:left-7 pz:border-l-2 pz:border-input pz:pointer-events-none\"\n style={{ top: \"50%\", bottom: -CONNECTOR_GAP }}\n />\n )}\n {!isFirst && (\n <div\n className=\"pz:absolute pz:left-7 pz:z-10\"\n style={{\n top: -CONNECTOR_GAP / 2,\n transform: \"translate(-50%, -50%)\",\n }}\n >\n <Select value={logic} onValueChange={(v) => onLogicChange(v as \"and\" | \"or\")}>\n <SelectTrigger className=\"pz:w-17 pz:h-6 pz:text-xs pz:bg-background pz:hover:bg-accent\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectGroup>\n <SelectItem value=\"and\">AND</SelectItem>\n <SelectItem value=\"or\">OR</SelectItem>\n </SelectGroup>\n </SelectContent>\n </Select>\n </div>\n )}\n </>\n )}\n <div className=\"pz:flex pz:flex-wrap pz:items-center pz:gap-2\">\n <FieldSectionEnumeration index={index} onRemove={onRemove} />\n <Select\n value={condition.field_name || null}\n disabled={!hasEligibleFields}\n onValueChange={(v) => {\n if (v === null) return;\n onUpdate(index, {\n ...condition,\n field_name: v,\n operator: \"eq\",\n value: \"\",\n });\n }}\n >\n <SelectTrigger className=\"pz:w-40\" aria-invalid={!!fieldNameError}>\n <SelectValue placeholder=\"Select field\" />\n </SelectTrigger>\n <SelectContent>\n {eligibleFields.map((f) => (\n <SelectItem key={f.fieldName} value={f.fieldName}>\n {f.fieldLabel || f.fieldName}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n {!hasEligibleFields && (\n <span className=\"pz:text-xs pz:text-muted-foreground\">\n No fields available{\" \"}\n <HoverInfo>Conditions require plain fields. JSON fields are not allowed.</HoverInfo>\n </span>\n )}\n\n {selectedField?.type && (\n <>\n <Badge\n variant=\"secondary\"\n className=\"pz:bg-accent pz:border pz:border-input pz:font-normal pz:text-muted-foreground pz:h-8\"\n >\n &apos;s\n </Badge>\n <Select\n defaultValue=\"value\"\n value={condition.property}\n onValueChange={(v) => {\n if (v === null) return;\n onUpdate(index, {\n ...condition,\n property: v,\n operator: \"eq\",\n value: \"\",\n });\n }}\n >\n <SelectTrigger className=\"pz:w-28\" aria-invalid={!!propertyError}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"value\">value</SelectItem>\n <SelectItem value=\"status\">status</SelectItem>\n </SelectContent>\n </Select>\n\n <Select\n value={condition.operator}\n onValueChange={(v) =>\n onUpdate(index, {\n ...condition,\n operator: v as ConditionOperators,\n })\n }\n >\n <SelectTrigger className=\"pz:w-28\" aria-invalid={!!operatorError}>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {availableOperators.map((op) => (\n <SelectItem key={op.value} value={op.value}>\n {op.label}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n\n {renderValueInput()}\n </>\n )}\n </div>\n {errorMessage && (\n <span\n className=\"pz:text-destructive pz:text-xs pz:font-medium pz:mt-1 pz:block\"\n role=\"alert\"\n >\n {errorMessage}\n </span>\n )}\n </div>\n {isLast && (\n <div className=\"pz:flex pz:items-center pz:gap-2\">\n <Button type=\"button\" variant=\"link\" size=\"xs\" onClick={onAddCondition}>\n <IconPlus />\n New rule\n </Button>\n </div>\n )}\n </div>\n );\n}\n\nexport function PipesRunIfInputAdapter(field: FieldHandle<\"pipes_run_if_input\">) {\n const pipeRunIf = field.value as PipeRunIf | null;\n const meta = field.meta as PipesRunIfMeta;\n\n // Built once per render of the adapter and reused across every condition\n // row, instead of each row scanning `meta.fields` linearly. With N rows and\n // M fields this turns O(N·M) lookups into O(N+M).\n const eligibleFields = useMemo(\n () => meta.fields.filter((f) => OPERATORS_BY_TYPE[f.type].length > 0),\n [meta.fields],\n );\n const fieldsByName = useMemo(\n () => new Map(meta.fields.map((f) => [f.fieldName, f])),\n [meta.fields],\n );\n\n const addRunIf = useCallback(() => {\n field.setValue({\n action: \"run\",\n when: {\n logic: \"and\",\n conditions: [{ ...EMPTY_CONDITION }],\n },\n });\n }, [field]);\n\n const updateCondition = (index: number, condition: Condition) => {\n if (!pipeRunIf) return;\n const newConditions = [...pipeRunIf.when.conditions] as Condition[];\n newConditions[index] = condition;\n field.setValue({\n ...pipeRunIf,\n when: { ...pipeRunIf.when, conditions: newConditions },\n });\n };\n\n const removeCondition = (index: number) => {\n if (!pipeRunIf) return;\n if (pipeRunIf.when.conditions.length <= 1) {\n field.setValue(null);\n return;\n }\n const newConditions = pipeRunIf.when.conditions.filter((_, i) => i !== index);\n field.setValue({\n ...pipeRunIf,\n when: { ...pipeRunIf.when, conditions: newConditions },\n });\n };\n\n const addCondition = () => {\n if (!pipeRunIf) return;\n field.setValue({\n ...pipeRunIf,\n when: {\n ...pipeRunIf.when,\n conditions: [...pipeRunIf.when.conditions, { ...EMPTY_CONDITION }],\n },\n });\n };\n\n const changeLogic = (logic: \"and\" | \"or\") => {\n if (!pipeRunIf) return;\n field.setValue({\n ...pipeRunIf,\n when: { ...pipeRunIf.when, logic },\n });\n };\n\n return (\n <div data-p0=\"input\">\n {!pipeRunIf ? (\n <div className=\"pz:flex pz:items-center\">\n <Button type=\"button\" variant=\"link\" size=\"xs\" className=\"pz:px-0\" onClick={addRunIf}>\n <IconPlus />\n New rule\n </Button>\n </div>\n ) : (\n <div className=\"pz:flex pz:flex-col pz:gap-8\">\n {pipeRunIf.when.conditions.map((condition, idx) => (\n <ConditionRow\n key={idx}\n condition={condition}\n index={idx}\n eligibleFields={eligibleFields}\n fieldsByName={fieldsByName}\n isFirst={idx === 0}\n isLast={idx === pipeRunIf.when.conditions.length - 1}\n logic={pipeRunIf.when.logic}\n form={field.form}\n basePath={field.path}\n onUpdate={updateCondition}\n onRemove={removeCondition}\n onAddCondition={addCondition}\n onLogicChange={changeLogic}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -17,7 +17,7 @@ function SelectInputAdapter(field) {
17
17
  "data-p0": "input",
18
18
  className: "pz:flex pz:flex-col pz:gap-1",
19
19
  children: [/* @__PURE__ */ jsxs(Select, {
20
- value: field.selectedValue || void 0,
20
+ value: field.selectedValue || null,
21
21
  onValueChange: (v) => {
22
22
  if (v === null) return;
23
23
  field.onSelect(v);
@@ -1 +1 @@
1
- {"version":3,"file":"select-input.mjs","names":[],"sources":["../../../../src/components/defaults/adapters/select-input.tsx"],"sourcesContent":["import type { WidgetsByKind } from \"@pipe0/base\";\nimport type { FieldHandle } from \"../../../types/field-handle.js\";\nimport { WidgetStrip } from \"../../../widgets/widget-strip.js\";\nimport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"../../ui/select.js\";\n\nfunction OptionContent({ label, widgets }: { label: string; widgets?: WidgetsByKind }) {\n return (\n <span className=\"pz:flex pz:items-center pz:gap-2\">\n <WidgetStrip widgets={widgets} />\n <span>{label}</span>\n </span>\n );\n}\n\nexport function SelectInputAdapter(field: FieldHandle<\"select_input\">) {\n const placeholder = field.meta.placeholder ?? \"— Select —\";\n const selectedOption = field.options.find((o) => o.value === field.selectedValue);\n const hasOptions = field.options.length > 0;\n\n return (\n <div data-p0=\"input\" className=\"pz:flex pz:flex-col pz:gap-1\">\n <Select\n value={field.selectedValue || undefined}\n onValueChange={(v) => {\n if (v === null) return;\n field.onSelect(v);\n }}\n name={field.path}\n disabled={!hasOptions}\n >\n <SelectTrigger id={field.id} aria-invalid={!!field.error} className=\"pz:w-full\">\n <SelectValue placeholder={placeholder}>\n {selectedOption ? (\n <OptionContent label={selectedOption.label} widgets={selectedOption.widgets} />\n ) : undefined}\n </SelectValue>\n </SelectTrigger>\n <SelectContent>\n <SelectGroup>\n {field.options.map((opt) => (\n <SelectItem key={opt.value} value={opt.value}>\n <OptionContent label={opt.label} widgets={opt.widgets} />\n </SelectItem>\n ))}\n </SelectGroup>\n </SelectContent>\n </Select>\n {!hasOptions && (\n <span className=\"pz:text-xs pz:text-muted-foreground\">No options available</span>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;AAYA,SAAS,cAAc,EAAE,OAAO,WAAuD;AACrF,QACE,qBAAC,QAAD;EAAM,WAAU;YAAhB,CACE,oBAAC,aAAD,EAAsB,SAAW,GACjC,oBAAC,QAAD,YAAO,OAAa,EACf;;;AAIX,SAAgB,mBAAmB,OAAoC;CACrE,MAAM,cAAc,MAAM,KAAK,eAAe;CAC9C,MAAM,iBAAiB,MAAM,QAAQ,MAAM,MAAM,EAAE,UAAU,MAAM,cAAc;CACjF,MAAM,aAAa,MAAM,QAAQ,SAAS;AAE1C,QACE,qBAAC,OAAD;EAAK,WAAQ;EAAQ,WAAU;YAA/B,CACE,qBAAC,QAAD;GACE,OAAO,MAAM,iBAAiB;GAC9B,gBAAgB,MAAM;AACpB,QAAI,MAAM,KAAM;AAChB,UAAM,SAAS,EAAE;;GAEnB,MAAM,MAAM;GACZ,UAAU,CAAC;aAPb,CASE,oBAAC,eAAD;IAAe,IAAI,MAAM;IAAI,gBAAc,CAAC,CAAC,MAAM;IAAO,WAAU;cAClE,oBAAC,aAAD;KAA0B;eACvB,iBACC,oBAAC,eAAD;MAAe,OAAO,eAAe;MAAO,SAAS,eAAe;MAAW,IAC7E;KACQ;IACA,GAChB,oBAAC,eAAD,YACE,oBAAC,aAAD,YACG,MAAM,QAAQ,KAAK,QAClB,oBAAC,YAAD;IAA4B,OAAO,IAAI;cACrC,oBAAC,eAAD;KAAe,OAAO,IAAI;KAAO,SAAS,IAAI;KAAW;IAC9C,EAFI,IAAI,MAER,CACb,EACU,GACA,EACT;MACR,CAAC,cACA,oBAAC,QAAD;GAAM,WAAU;aAAsC;GAA2B,EAE/E"}
1
+ {"version":3,"file":"select-input.mjs","names":[],"sources":["../../../../src/components/defaults/adapters/select-input.tsx"],"sourcesContent":["import type { WidgetsByKind } from \"@pipe0/base\";\nimport type { FieldHandle } from \"../../../types/field-handle.js\";\nimport { WidgetStrip } from \"../../../widgets/widget-strip.js\";\nimport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"../../ui/select.js\";\n\nfunction OptionContent({ label, widgets }: { label: string; widgets?: WidgetsByKind }) {\n return (\n <span className=\"pz:flex pz:items-center pz:gap-2\">\n <WidgetStrip widgets={widgets} />\n <span>{label}</span>\n </span>\n );\n}\n\nexport function SelectInputAdapter(field: FieldHandle<\"select_input\">) {\n const placeholder = field.meta.placeholder ?? \"— Select —\";\n const selectedOption = field.options.find((o) => o.value === field.selectedValue);\n const hasOptions = field.options.length > 0;\n\n return (\n <div data-p0=\"input\" className=\"pz:flex pz:flex-col pz:gap-1\">\n <Select\n // `null` (not `undefined`) keeps the Select controlled for its whole\n // lifetime — `undefined` makes it uncontrolled while empty and flips to\n // controlled on first selection, which warns.\n value={field.selectedValue || null}\n onValueChange={(v) => {\n if (v === null) return;\n field.onSelect(v);\n }}\n name={field.path}\n disabled={!hasOptions}\n >\n <SelectTrigger id={field.id} aria-invalid={!!field.error} className=\"pz:w-full\">\n <SelectValue placeholder={placeholder}>\n {selectedOption ? (\n <OptionContent label={selectedOption.label} widgets={selectedOption.widgets} />\n ) : undefined}\n </SelectValue>\n </SelectTrigger>\n <SelectContent>\n <SelectGroup>\n {field.options.map((opt) => (\n <SelectItem key={opt.value} value={opt.value}>\n <OptionContent label={opt.label} widgets={opt.widgets} />\n </SelectItem>\n ))}\n </SelectGroup>\n </SelectContent>\n </Select>\n {!hasOptions && (\n <span className=\"pz:text-xs pz:text-muted-foreground\">No options available</span>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;AAYA,SAAS,cAAc,EAAE,OAAO,WAAuD;AACrF,QACE,qBAAC,QAAD;EAAM,WAAU;YAAhB,CACE,oBAAC,aAAD,EAAsB,SAAW,GACjC,oBAAC,QAAD,YAAO,OAAa,EACf;;;AAIX,SAAgB,mBAAmB,OAAoC;CACrE,MAAM,cAAc,MAAM,KAAK,eAAe;CAC9C,MAAM,iBAAiB,MAAM,QAAQ,MAAM,MAAM,EAAE,UAAU,MAAM,cAAc;CACjF,MAAM,aAAa,MAAM,QAAQ,SAAS;AAE1C,QACE,qBAAC,OAAD;EAAK,WAAQ;EAAQ,WAAU;YAA/B,CACE,qBAAC,QAAD;GAIE,OAAO,MAAM,iBAAiB;GAC9B,gBAAgB,MAAM;AACpB,QAAI,MAAM,KAAM;AAChB,UAAM,SAAS,EAAE;;GAEnB,MAAM,MAAM;GACZ,UAAU,CAAC;aAVb,CAYE,oBAAC,eAAD;IAAe,IAAI,MAAM;IAAI,gBAAc,CAAC,CAAC,MAAM;IAAO,WAAU;cAClE,oBAAC,aAAD;KAA0B;eACvB,iBACC,oBAAC,eAAD;MAAe,OAAO,eAAe;MAAO,SAAS,eAAe;MAAW,IAC7E;KACQ;IACA,GAChB,oBAAC,eAAD,YACE,oBAAC,aAAD,YACG,MAAM,QAAQ,KAAK,QAClB,oBAAC,YAAD;IAA4B,OAAO,IAAI;cACrC,oBAAC,eAAD;KAAe,OAAO,IAAI;KAAO,SAAS,IAAI;KAAW;IAC9C,EAFI,IAAI,MAER,CACb,EACU,GACA,EACT;MACR,CAAC,cACA,oBAAC,QAAD;GAAM,WAAU;aAAsC;GAA2B,EAE/E"}
@@ -1 +1 @@
1
- {"version":3,"file":"field-renderer.d.mts","names":[],"sources":["../../src/components/field-renderer.tsx"],"mappings":";;;;;iBAKS,kBAAA,CAAA;EAAqB;AAAA;EAAW,KAAA,EAAO,aAAA;AAAA,IAAmB,SAAA;AAAA,cA+BtD,aAAA,EAAa,OAAA,CAAA,mBAAA,QAAA,kBAAA"}
1
+ {"version":3,"file":"field-renderer.d.mts","names":[],"sources":["../../src/components/field-renderer.tsx"],"mappings":";;;;;iBAKS,kBAAA,CAAA;EAAqB;AAAA;EAAW,KAAA,EAAO,aAAA;AAAA,IAAmB,SAAA;AAAA,cAyCtD,aAAA,EAAa,OAAA,CAAA,mBAAA,QAAA,kBAAA"}
@@ -13,7 +13,9 @@ function FieldRendererInner({ field }) {
13
13
  const FieldRenderer = memo(FieldRendererInner, (prev, next) => {
14
14
  const a = prev.field;
15
15
  const b = next.field;
16
- return a.kind === b.kind && a.path === b.path && a.value === b.value && a.error === b.error && a.disabled === b.disabled && a.disabledReason === b.disabledReason && a.touched === b.touched && a.dirty === b.dirty && a.meta === b.meta;
16
+ const aLoad = a;
17
+ const bLoad = b;
18
+ return a.kind === b.kind && a.path === b.path && a.value === b.value && a.error === b.error && a.disabled === b.disabled && a.disabledReason === b.disabledReason && a.touched === b.touched && a.dirty === b.dirty && a.meta === b.meta && aLoad.pending === bLoad.pending && aLoad.suggestionsDisabled === bLoad.suggestionsDisabled && aLoad.suggestionsDisabledReason === bLoad.suggestionsDisabledReason;
17
19
  });
18
20
 
19
21
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"field-renderer.mjs","names":[],"sources":["../../src/components/field-renderer.tsx"],"sourcesContent":["import { type ComponentType, memo, type ReactNode } from \"react\";\nimport { useFormConfig } from \"../context/form-context.js\";\nimport type { AnyFieldHandle } from \"../types/field-handle.js\";\nimport { defaultAdapters } from \"./defaults/adapters/index.js\";\n\nfunction FieldRendererInner({ field }: { field: AnyFieldHandle }): ReactNode {\n const { adapters } = useFormConfig();\n\n const adapter = adapters?.[field.kind] ?? defaultAdapters[field.kind];\n\n if (!adapter) {\n return null;\n }\n\n // Render as a component (not a direct call) so React Fast Refresh can track\n // the adapter's type and hot-swap it on edits.\n const Adapter = adapter as unknown as ComponentType<AnyFieldHandle>;\n return <Adapter {...field} />;\n}\n\n// `buildSectionHandles` rebuilds every field handle on every form-state\n// change, so a single keystroke causes every sibling adapter to receive a new\n// `field` reference. A custom comparator lets us skip re-rendering when the\n// load-bearing slice of the handle is identity-equal — primitive values short\n// out via `Object.is`, while object-valued kinds (include/exclude, ranges)\n// will miss and re-render, which is the acceptable tradeoff.\n//\n// `meta` is included so meta-only updates (e.g. `connector_input`'s\n// `filteredConnections` populating after the async `getConnections` resolver\n// resolves) actually re-render. `meta` is passed through from `formConfig`\n// which is memoized on `store` (not `watchedValues`), so its identity stays\n// stable across keystrokes and only flips when the form metadata actually\n// changes.\n//\n// Adapter swaps via `<FormProvider adapters={...}>` still propagate: context\n// changes re-render every consumer regardless of the memo decision.\nexport const FieldRenderer = memo(FieldRendererInner, (prev, next) => {\n const a = prev.field;\n const b = next.field;\n return (\n a.kind === b.kind &&\n a.path === b.path &&\n a.value === b.value &&\n a.error === b.error &&\n a.disabled === b.disabled &&\n a.disabledReason === b.disabledReason &&\n a.touched === b.touched &&\n a.dirty === b.dirty &&\n a.meta === b.meta\n );\n});\n"],"mappings":";;;;;;AAKA,SAAS,mBAAmB,EAAE,SAA+C;CAC3E,MAAM,EAAE,aAAa,eAAe;CAEpC,MAAM,UAAU,WAAW,MAAM,SAAS,gBAAgB,MAAM;AAEhE,KAAI,CAAC,QACH,QAAO;AAMT,QAAO,oBADS,SACT,EAAS,GAAI,OAAS;;AAmB/B,MAAa,gBAAgB,KAAK,qBAAqB,MAAM,SAAS;CACpE,MAAM,IAAI,KAAK;CACf,MAAM,IAAI,KAAK;AACf,QACE,EAAE,SAAS,EAAE,QACb,EAAE,SAAS,EAAE,QACb,EAAE,UAAU,EAAE,SACd,EAAE,UAAU,EAAE,SACd,EAAE,aAAa,EAAE,YACjB,EAAE,mBAAmB,EAAE,kBACvB,EAAE,YAAY,EAAE,WAChB,EAAE,UAAU,EAAE,SACd,EAAE,SAAS,EAAE;EAEf"}
1
+ {"version":3,"file":"field-renderer.mjs","names":[],"sources":["../../src/components/field-renderer.tsx"],"sourcesContent":["import { type ComponentType, memo, type ReactNode } from \"react\";\nimport { useFormConfig } from \"../context/form-context.js\";\nimport type { AnyFieldHandle } from \"../types/field-handle.js\";\nimport { defaultAdapters } from \"./defaults/adapters/index.js\";\n\nfunction FieldRendererInner({ field }: { field: AnyFieldHandle }): ReactNode {\n const { adapters } = useFormConfig();\n\n const adapter = adapters?.[field.kind] ?? defaultAdapters[field.kind];\n\n if (!adapter) {\n return null;\n }\n\n // Render as a component (not a direct call) so React Fast Refresh can track\n // the adapter's type and hot-swap it on edits.\n const Adapter = adapter as unknown as ComponentType<AnyFieldHandle>;\n return <Adapter {...field} />;\n}\n\n// `buildSectionHandles` rebuilds every field handle on every form-state\n// change, so a single keystroke causes every sibling adapter to receive a new\n// `field` reference. A custom comparator lets us skip re-rendering when the\n// load-bearing slice of the handle is identity-equal — primitive values short\n// out via `Object.is`, while object-valued kinds (include/exclude, ranges)\n// will miss and re-render, which is the acceptable tradeoff.\n//\n// `meta` is included so meta-only updates (e.g. `connector_input`'s\n// `filteredConnections` populating after the async `getConnections` resolver\n// resolves) actually re-render. `meta` is passed through from `formConfig`\n// which is memoized on `store` (not `watchedValues`), so its identity stays\n// stable across keystrokes and only flips when the form metadata actually\n// changes.\n//\n// Adapter swaps via `<FormProvider adapters={...}>` still propagate: context\n// changes re-render every consumer regardless of the memo decision.\n//\n// The load-state slice (`pending` / `suggestionsDisabled`) must be compared too:\n// for `context_select_input` / `tagged_text_input`, an async field-context fetch\n// flips `pending` from `true` → `false` (and may toggle the suggestions gate)\n// WITHOUT changing `meta`/`value`/`disabled`. These are primitives derived from\n// the field's load state, so they don't churn across handle rebuilds the way\n// `options` (a fresh array) would — and `options` arrival is already covered by\n// the `meta` comparison (`meta` is memoized on `store`). Omitting `pending` here\n// is what previously froze a context-select on \"Loading…\" after its options had\n// already arrived.\nexport const FieldRenderer = memo(FieldRendererInner, (prev, next) => {\n const a = prev.field;\n const b = next.field;\n const aLoad = a as {\n pending?: boolean;\n suggestionsDisabled?: boolean;\n suggestionsDisabledReason?: string;\n };\n const bLoad = b as {\n pending?: boolean;\n suggestionsDisabled?: boolean;\n suggestionsDisabledReason?: string;\n };\n return (\n a.kind === b.kind &&\n a.path === b.path &&\n a.value === b.value &&\n a.error === b.error &&\n a.disabled === b.disabled &&\n a.disabledReason === b.disabledReason &&\n a.touched === b.touched &&\n a.dirty === b.dirty &&\n a.meta === b.meta &&\n aLoad.pending === bLoad.pending &&\n aLoad.suggestionsDisabled === bLoad.suggestionsDisabled &&\n aLoad.suggestionsDisabledReason === bLoad.suggestionsDisabledReason\n );\n});\n"],"mappings":";;;;;;AAKA,SAAS,mBAAmB,EAAE,SAA+C;CAC3E,MAAM,EAAE,aAAa,eAAe;CAEpC,MAAM,UAAU,WAAW,MAAM,SAAS,gBAAgB,MAAM;AAEhE,KAAI,CAAC,QACH,QAAO;AAMT,QAAO,oBADS,SACT,EAAS,GAAI,OAAS;;AA6B/B,MAAa,gBAAgB,KAAK,qBAAqB,MAAM,SAAS;CACpE,MAAM,IAAI,KAAK;CACf,MAAM,IAAI,KAAK;CACf,MAAM,QAAQ;CAKd,MAAM,QAAQ;AAKd,QACE,EAAE,SAAS,EAAE,QACb,EAAE,SAAS,EAAE,QACb,EAAE,UAAU,EAAE,SACd,EAAE,UAAU,EAAE,SACd,EAAE,aAAa,EAAE,YACjB,EAAE,mBAAmB,EAAE,kBACvB,EAAE,YAAY,EAAE,WAChB,EAAE,UAAU,EAAE,SACd,EAAE,SAAS,EAAE,QACb,MAAM,YAAY,MAAM,WACxB,MAAM,wBAAwB,MAAM,uBACpC,MAAM,8BAA8B,MAAM;EAE5C"}
@@ -1 +1 @@
1
- {"version":3,"file":"use-form-core.d.mts","names":[],"sources":["../../src/hooks/use-form-core.ts"],"mappings":";;KAkCY,cAAA;AAAA,KASA,cAAA;EACV,MAAA,EAAQ,cAAA,EADgB;EAGxB,QAAA,WAFsB;EAItB,cAAA,WAJQ;EAMR,mBAAA,WAFA;EAIA,yBAAA;AAAA"}
1
+ {"version":3,"file":"use-form-core.d.mts","names":[],"sources":["../../src/hooks/use-form-core.ts"],"mappings":";;KA8BY,cAAA;AAAA,KASA,cAAA;EACV,MAAA,EAAQ,cAAA,EADgB;EAGxB,QAAA,WAFsB;EAItB,cAAA,WAJQ;EAMR,mBAAA,WAFA;EAIA,yBAAA;AAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"use-form-core.mjs","names":[],"sources":["../../src/hooks/use-form-core.ts"],"sourcesContent":["import { zodResolver } from \"@hookform/resolvers/zod\";\nimport type {\n EnabledIf,\n EnabledResult,\n FormResolvers,\n FormSection,\n FormStore,\n GeneratedInputMeta,\n PipesEnvironment,\n ProviderName,\n} from \"@pipe0/base\";\nimport {\n type Dispatch,\n type SetStateAction,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { type FieldValues, type UseFormReturn, useForm } from \"react-hook-form\";\nimport type {\n AnyFieldProps,\n ConstantSuggestion,\n SecretSuggestion,\n} from \"../types/field-props.js\";\nimport type { FormSectionHandle } from \"../types/form-handle.js\";\nimport { buildSectionHandles } from \"../utils/build-section-handlers.js\";\nimport { mergeFormStores } from \"../utils/merge-form-stores.js\";\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport type ResourceStatus = \"idle\" | \"loading\" | \"ready\" | \"error\";\n\nexport type SlotId = \"field\" | \"suggestions\";\n\nexport type FieldEnabledState = {\n disabled: boolean;\n reason?: string;\n};\n\nexport type FieldLoadState = {\n status: ResourceStatus;\n /** Field-level disabled (from `meta.enabledIf`). */\n disabled: boolean;\n /** Field-level disabled reason. */\n disabledReason?: string;\n /** Suggestions sub-feature gate (from `optionsDef.enabledIf`). */\n suggestionsDisabled: boolean;\n /** Suggestions sub-feature reason. */\n suggestionsDisabledReason?: string;\n};\n\nexport interface UseFormCoreOptions<T extends FieldValues> {\n pipeOrSearchId: string;\n kind: \"pipe\" | \"search\";\n schema: any;\n publicKey: string;\n defaultValues?: T;\n formConfig: FormSection[];\n resolvers?: FormResolvers;\n store: FormStore;\n setStore: Dispatch<SetStateAction<FormStore>>;\n environment?: PipesEnvironment;\n /**\n * Form-level scope tags. Bundled into every `resolvers.getSecrets` call so\n * the backend can return only the secrets allowed in the declared scopes\n * (intersection on top of cascade visibility).\n */\n scopes?: string[];\n /**\n * Current team context. Bundled into every `resolvers.getSecrets` call so\n * the backend can restrict team-level secrets to exactly this team.\n */\n teamId?: string;\n}\n\nexport interface UseFormCoreReturn<T extends FieldValues> {\n connectionsStatus: ResourceStatus;\n /** Map of field path → load state for dynamic context_select_input fields. */\n fieldLoadStates: Record<string, FieldLoadState>;\n /** Subset of `fieldLoadStates` where `status === \"error\"`. RHF-style. */\n fieldLoaderErrors: Record<string, FieldLoadState>;\n /** Subset of `fieldLoadStates` where `status === \"loading\"`. RHF-style. */\n loadingFieldLoaders: Record<string, FieldLoadState>;\n /** True when any field loader has errored. */\n hasFieldLoaderError: boolean;\n /** True when any field loader is currently loading. */\n isFieldLoaderLoading: boolean;\n form: UseFormReturn<T, any, any>;\n sections: FormSectionHandle[];\n fields: AnyFieldProps[];\n reset: (values?: T) => void;\n}\n\ntype EnabledSlot = {\n fieldPath: string;\n slotId: SlotId;\n enabledIf: EnabledIf;\n /** Only present for \"suggestions\" slots — used to drive option fetching. */\n optionsDef?: {\n requires: { connection?: ProviderName; fields?: readonly string[] };\n };\n};\n\nfunction collectEnabledSlots(formConfig: FormSection[]): EnabledSlot[] {\n const out: EnabledSlot[] = [];\n for (const section of formConfig) {\n for (const group of section.groups) {\n for (const field of group.fields as GeneratedInputMeta[]) {\n if (field.enabledIf) {\n out.push({\n fieldPath: field.path,\n slotId: \"field\",\n enabledIf: field.enabledIf,\n });\n }\n const supportsOptionsDef =\n field.type === \"context_select_input\" || field.type === \"tagged_text_input\";\n if (supportsOptionsDef && \"optionsDef\" in field && field.optionsDef) {\n const optionsDef = field.optionsDef as EnabledSlot[\"optionsDef\"] & {\n enabledIf?: EnabledIf;\n };\n if (optionsDef?.enabledIf) {\n out.push({\n fieldPath: field.path,\n slotId: \"suggestions\",\n enabledIf: optionsDef.enabledIf,\n optionsDef,\n });\n } else {\n // Even without a sub-feature enabledIf, we still need to track\n // this field as having a fetchable suggestions slot — it's\n // always enabled and the fetch fires on every value change.\n out.push({\n fieldPath: field.path,\n slotId: \"suggestions\",\n enabledIf: () => ({ disabled: false }),\n optionsDef,\n });\n }\n }\n }\n }\n }\n return out;\n}\n\nfunction getPathValue(obj: unknown, path: string): unknown {\n const parts = path.split(\".\");\n let cur: any = obj;\n for (const part of parts) {\n if (cur == null) return undefined;\n cur = cur[part];\n }\n return cur;\n}\n\nfunction evalSlot(slot: EnabledSlot, payload: unknown): EnabledResult {\n return slot.enabledIf(payload);\n}\n\n// ---------------------------------------------------------------------------\n// Hook\n// ---------------------------------------------------------------------------\n\nexport function useFormCore<T extends FieldValues>(\n options: UseFormCoreOptions<T>,\n): UseFormCoreReturn<T> {\n const {\n schema,\n publicKey,\n defaultValues,\n formConfig,\n resolvers,\n pipeOrSearchId,\n kind,\n setStore,\n environment = \"production\",\n scopes,\n teamId,\n } = options;\n\n // Stable signature for `scopes` so its identity doesn't churn the effect\n // dep across renders when callers pass a fresh array literal each time.\n const scopesKey = useMemo(() => (scopes ? JSON.stringify(scopes) : \"\"), [scopes]);\n\n // --- Per-resource status ---\n const [connectionsStatus, setConnectionsStatus] = useState<ResourceStatus>(\n resolvers?.getConnections ? \"loading\" : \"idle\",\n );\n const [fieldLoadStates, setFieldLoadStates] = useState<Record<string, FieldLoadState>>({});\n\n // --- Form ---\n const form = useForm<T>({\n resolver: zodResolver(schema),\n defaultValues: defaultValues as any,\n });\n\n // --- Helpers ---\n const mergeStore = useCallback(\n (incoming: FormStore) => setStore((old) => mergeFormStores(old, incoming)),\n [setStore],\n );\n\n // --- Effect 1: Load connections ---\n useEffect(() => {\n if (!resolvers?.getConnections) {\n setConnectionsStatus(\"idle\");\n return;\n }\n\n let cancelled = false;\n setConnectionsStatus(\"loading\");\n\n Promise.resolve(resolvers.getConnections({ id: pipeOrSearchId, environment }))\n .then((conns) => {\n if (cancelled) return;\n\n mergeStore({\n field_options: {\n connections: {\n options: conns.map((c) => ({\n label: c.public_id,\n value: c.public_id,\n widgets: {\n provider_logo: { provider: c.provider as ProviderName },\n },\n })),\n },\n },\n });\n\n setConnectionsStatus(\"ready\");\n })\n .catch(() => {\n if (!cancelled) setConnectionsStatus(\"error\");\n });\n\n return () => {\n cancelled = true;\n };\n }, [pipeOrSearchId, environment, resolvers?.getConnections, mergeStore]);\n\n // --- Curried secrets search ---\n // Each keystroke in the reference picker fires this with the latest query.\n // The picker handles debounce + race-correctness; here we just bundle in\n // form-level args (environment / scopes / teamId) and call the resolver.\n // No caching: every call hits the resolver. Returns [] if no resolver.\n const getSecretsResolver = resolvers?.getSecrets;\n const searchSecrets = useCallback(\n async (query: string): Promise<SecretSuggestion[]> => {\n if (!getSecretsResolver) return [];\n return Promise.resolve(getSecretsResolver({ query, environment, scopes, teamId }));\n },\n // `scopesKey` is the stable serialization of `scopes`; depending on the\n // raw array would churn the callback identity on every parent render.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [getSecretsResolver, environment, scopesKey, teamId],\n );\n\n // --- Curried constants search ---\n // Mirrors `searchSecrets` exactly. Same per-keystroke contract, same\n // form-level arg bundling. Returns [] when no resolver is wired.\n const getConstantsResolver = resolvers?.getConstants;\n const searchConstants = useCallback(\n async (query: string): Promise<ConstantSuggestion[]> => {\n if (!getConstantsResolver) return [];\n return Promise.resolve(getConstantsResolver({ query, environment, scopes, teamId }));\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [getConstantsResolver, environment, scopesKey, teamId],\n );\n\n // --- Effect 2: Evaluate enabledIf slots + drive context_select fetching ---\n const slots = useMemo(() => collectEnabledSlots(formConfig), [formConfig]);\n\n // Subscribe to all form value changes so resolvers re-evaluate.\n const watchedValues = form.watch();\n\n // Evaluate every slot against the current payload. Keep the result\n // serialized so the effect's deps stay stable across reference-identical\n // re-renders.\n const slotResults = useMemo(() => {\n const out: Record<string, EnabledResult> = {};\n for (const slot of slots) {\n out[`${slot.fieldPath}::${slot.slotId}`] = evalSlot(slot, watchedValues);\n }\n return out;\n }, [slots, watchedValues]);\n const slotResultsSig = useMemo(() => JSON.stringify(slotResults), [slotResults]);\n\n // Track previous results so we can detect enabled→disabled transitions\n // (drives field-value clearing) and last-fired fetch signatures.\n const prevResultsRef = useRef<Record<string, EnabledResult>>({});\n const lastFiredSigRef = useRef<Record<string, string>>({});\n\n useEffect(() => {\n if (slots.length === 0) return;\n\n let cancelled = false;\n const nextLoadStates: Record<string, FieldLoadState> = {\n ...fieldLoadStates,\n };\n\n // Group slot results by field path for the load-state map.\n const byField: Record<string, { field?: EnabledResult; suggestions?: EnabledResult }> = {};\n for (const slot of slots) {\n const r = slotResults[`${slot.fieldPath}::${slot.slotId}`];\n if (r == null) continue;\n byField[slot.fieldPath] ??= {};\n byField[slot.fieldPath][slot.slotId] = r;\n }\n\n for (const slot of slots) {\n const key = `${slot.fieldPath}::${slot.slotId}`;\n const r = slotResults[key];\n if (r == null) continue;\n const prev = prevResultsRef.current[key];\n\n // Field-slot only: clear value on enabled→disabled transition.\n if (slot.slotId === \"field\" && r.disabled && prev != null && !prev.disabled) {\n form.setValue(slot.fieldPath as any, \"\" as any, {\n shouldDirty: true,\n shouldTouch: true,\n });\n }\n\n // Suggestions-slot: drive the existing context_select_input fetch.\n if (slot.slotId === \"suggestions\" && resolvers?.getFieldContext) {\n // If suggestions are gated, skip the fetch and reset dedupe so\n // re-enabling re-fires.\n if (r.disabled) {\n delete lastFiredSigRef.current[slot.fieldPath];\n continue;\n }\n\n // Resolve the connection for the legacy `requires.connection`\n // (still needed to pick the right secret for the fetch).\n const watchedConnections = (\n watchedValues as {\n connector?: { connections?: { connection?: string }[] };\n }\n )?.connector?.connections;\n const required = slot.optionsDef?.requires;\n\n let connectionId: string | undefined;\n if (required?.connection) {\n const match = watchedConnections?.find((c) =>\n c?.connection?.startsWith(`${required.connection}_`),\n );\n connectionId = match?.connection;\n // No matching connection — can't fetch, even if enabledIf passed.\n if (!connectionId) continue;\n }\n\n // Per-field signature for dedupe.\n const perFieldSig = JSON.stringify({\n connectionId,\n deps: required?.fields?.map((d) => getPathValue(watchedValues, d)) ?? [],\n });\n if (lastFiredSigRef.current[slot.fieldPath] === perFieldSig) continue;\n lastFiredSigRef.current[slot.fieldPath] = perFieldSig;\n\n // Mark loading for this field's fetch.\n const existing = nextLoadStates[slot.fieldPath];\n nextLoadStates[slot.fieldPath] = {\n status: \"loading\",\n disabled: existing?.disabled ?? false,\n disabledReason: existing?.disabledReason,\n suggestionsDisabled: false,\n suggestionsDisabledReason: undefined,\n };\n\n const idKey = kind === \"search\" ? \"search_id\" : \"pipe_id\";\n\n Promise.resolve(\n resolvers.getFieldContext({\n fieldPath: slot.fieldPath,\n query: \"\",\n payload: {\n ...(watchedValues as Record<string, unknown>),\n [idKey]: pipeOrSearchId,\n },\n }),\n )\n .then((incoming: FormStore) => {\n if (cancelled) return;\n mergeStore(incoming);\n setFieldLoadStates((s) => ({\n ...s,\n [slot.fieldPath]: {\n ...(s[slot.fieldPath] ?? {\n disabled: false,\n suggestionsDisabled: false,\n }),\n status: \"ready\",\n },\n }));\n })\n .catch(() => {\n if (cancelled) return;\n setFieldLoadStates((s) => ({\n ...s,\n [slot.fieldPath]: {\n ...(s[slot.fieldPath] ?? {\n disabled: false,\n suggestionsDisabled: false,\n }),\n status: \"error\",\n },\n }));\n });\n }\n }\n\n // Reflect the latest enabledIf evaluation into fieldLoadStates so the\n // adapters and field-wrapper can render the disabled state.\n for (const fieldPath of Object.keys(byField)) {\n const { field: fieldR, suggestions: sugR } = byField[fieldPath]!;\n const prevState = nextLoadStates[fieldPath];\n nextLoadStates[fieldPath] = {\n status: prevState?.status ?? \"idle\",\n disabled: fieldR == null ? (prevState?.disabled ?? false) : fieldR.disabled,\n disabledReason: fieldR == null ? prevState?.disabledReason : fieldR.message,\n suggestionsDisabled:\n sugR == null ? (prevState?.suggestionsDisabled ?? false) : sugR.disabled,\n suggestionsDisabledReason:\n sugR == null ? prevState?.suggestionsDisabledReason : sugR.message,\n };\n }\n\n setFieldLoadStates(nextLoadStates);\n prevResultsRef.current = slotResults;\n\n return () => {\n cancelled = true;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [slotResultsSig, slots, pipeOrSearchId]);\n\n // --- Sections & fields ---\n const isSubmitted = form.formState.isSubmitted;\n const formErrors = form.formState.errors;\n\n // `watchedValues` and `formErrors` must be in the dep array: field handles\n // bake `form.getValues(path)` snapshots into `field.value` / textareaProps /\n // selectedValue, and adapters render those as controlled inputs. Without\n // these deps, the memo never refreshes on keystrokes and the controlled\n // inputs snap back to their stale snapshot — typing/selecting appears to\n // do nothing. See FieldRenderer's memo comment for the intended contract.\n const sections = useMemo(\n () =>\n buildSectionHandles(formConfig, form as any, publicKey, {\n fieldLoadStates,\n searchSecrets,\n searchConstants,\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [\n formConfig,\n form,\n publicKey,\n fieldLoadStates,\n isSubmitted,\n searchSecrets,\n searchConstants,\n watchedValues,\n formErrors,\n ],\n );\n\n const fields = useMemo(\n () => sections.flatMap((s) => s.groups.flatMap((g) => g.fields)),\n [sections],\n );\n\n const { fieldLoaderErrors, loadingFieldLoaders, hasFieldLoaderError, isFieldLoaderLoading } =\n useMemo(() => {\n const errors: Record<string, FieldLoadState> = {};\n const loading: Record<string, FieldLoadState> = {};\n for (const [path, state] of Object.entries(fieldLoadStates)) {\n if (state.status === \"error\") errors[path] = state;\n else if (state.status === \"loading\") loading[path] = state;\n }\n return {\n fieldLoaderErrors: errors,\n loadingFieldLoaders: loading,\n hasFieldLoaderError: Object.keys(errors).length > 0,\n isFieldLoaderLoading: Object.keys(loading).length > 0,\n };\n }, [fieldLoadStates]);\n\n return {\n connectionsStatus,\n fieldLoadStates,\n fieldLoaderErrors,\n loadingFieldLoaders,\n hasFieldLoaderError,\n isFieldLoaderLoading,\n form,\n sections,\n fields,\n reset: form.reset,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"use-form-core.mjs","names":[],"sources":["../../src/hooks/use-form-core.ts"],"sourcesContent":["import { zodResolver } from \"@hookform/resolvers/zod\";\nimport type {\n EnabledIf,\n EnabledResult,\n FormResolvers,\n FormSection,\n FormStore,\n GeneratedInputMeta,\n PipesEnvironment,\n ProviderName,\n} from \"@pipe0/base\";\nimport {\n type Dispatch,\n type SetStateAction,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { type FieldValues, type UseFormReturn, useForm } from \"react-hook-form\";\nimport type { AnyFieldProps, ConstantSuggestion, SecretSuggestion } from \"../types/field-props.js\";\nimport type { FormSectionHandle } from \"../types/form-handle.js\";\nimport { buildSectionHandles } from \"../utils/build-section-handlers.js\";\nimport { mergeFormStores } from \"../utils/merge-form-stores.js\";\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport type ResourceStatus = \"idle\" | \"loading\" | \"ready\" | \"error\";\n\nexport type SlotId = \"field\" | \"suggestions\";\n\nexport type FieldEnabledState = {\n disabled: boolean;\n reason?: string;\n};\n\nexport type FieldLoadState = {\n status: ResourceStatus;\n /** Field-level disabled (from `meta.enabledIf`). */\n disabled: boolean;\n /** Field-level disabled reason. */\n disabledReason?: string;\n /** Suggestions sub-feature gate (from `optionsDef.enabledIf`). */\n suggestionsDisabled: boolean;\n /** Suggestions sub-feature reason. */\n suggestionsDisabledReason?: string;\n};\n\nexport interface UseFormCoreOptions<T extends FieldValues> {\n pipeOrSearchId: string;\n kind: \"pipe\" | \"search\";\n schema: any;\n publicKey: string;\n defaultValues?: T;\n formConfig: FormSection[];\n resolvers?: FormResolvers;\n store: FormStore;\n setStore: Dispatch<SetStateAction<FormStore>>;\n environment?: PipesEnvironment;\n /**\n * Form-level scope tags. Bundled into every `resolvers.getSecrets` call so\n * the backend can return only the secrets allowed in the declared scopes\n * (intersection on top of cascade visibility).\n */\n scopes?: string[];\n /**\n * Current team context. Bundled into every `resolvers.getSecrets` call so\n * the backend can restrict team-level secrets to exactly this team.\n */\n teamId?: string;\n}\n\nexport interface UseFormCoreReturn<T extends FieldValues> {\n connectionsStatus: ResourceStatus;\n /** Map of field path → load state for dynamic context_select_input fields. */\n fieldLoadStates: Record<string, FieldLoadState>;\n /** Subset of `fieldLoadStates` where `status === \"error\"`. RHF-style. */\n fieldLoaderErrors: Record<string, FieldLoadState>;\n /** Subset of `fieldLoadStates` where `status === \"loading\"`. RHF-style. */\n loadingFieldLoaders: Record<string, FieldLoadState>;\n /** True when any field loader has errored. */\n hasFieldLoaderError: boolean;\n /** True when any field loader is currently loading. */\n isFieldLoaderLoading: boolean;\n form: UseFormReturn<T, any, any>;\n sections: FormSectionHandle[];\n fields: AnyFieldProps[];\n reset: (values?: T) => void;\n}\n\ntype EnabledSlot = {\n fieldPath: string;\n slotId: SlotId;\n enabledIf: EnabledIf;\n /** Only present for \"suggestions\" slots — used to drive option fetching. */\n optionsDef?: {\n requires: { connection?: ProviderName; fields?: readonly string[] };\n };\n};\n\nfunction collectEnabledSlots(formConfig: FormSection[]): EnabledSlot[] {\n const out: EnabledSlot[] = [];\n for (const section of formConfig) {\n for (const group of section.groups) {\n for (const field of group.fields as GeneratedInputMeta[]) {\n if (field.enabledIf) {\n out.push({\n fieldPath: field.path,\n slotId: \"field\",\n enabledIf: field.enabledIf,\n });\n }\n const supportsOptionsDef =\n field.type === \"context_select_input\" || field.type === \"tagged_text_input\";\n if (supportsOptionsDef && \"optionsDef\" in field && field.optionsDef) {\n const optionsDef = field.optionsDef as EnabledSlot[\"optionsDef\"] & {\n enabledIf?: EnabledIf;\n };\n if (optionsDef?.enabledIf) {\n out.push({\n fieldPath: field.path,\n slotId: \"suggestions\",\n enabledIf: optionsDef.enabledIf,\n optionsDef,\n });\n } else {\n // Even without a sub-feature enabledIf, we still need to track\n // this field as having a fetchable suggestions slot — it's\n // always enabled and the fetch fires on every value change.\n out.push({\n fieldPath: field.path,\n slotId: \"suggestions\",\n enabledIf: () => ({ disabled: false }),\n optionsDef,\n });\n }\n }\n }\n }\n }\n return out;\n}\n\nfunction getPathValue(obj: unknown, path: string): unknown {\n const parts = path.split(\".\");\n let cur: any = obj;\n for (const part of parts) {\n if (cur == null) return undefined;\n cur = cur[part];\n }\n return cur;\n}\n\nfunction evalSlot(slot: EnabledSlot, payload: unknown): EnabledResult {\n return slot.enabledIf(payload);\n}\n\n// ---------------------------------------------------------------------------\n// Hook\n// ---------------------------------------------------------------------------\n\nexport function useFormCore<T extends FieldValues>(\n options: UseFormCoreOptions<T>,\n): UseFormCoreReturn<T> {\n const {\n schema,\n publicKey,\n defaultValues,\n formConfig,\n resolvers,\n pipeOrSearchId,\n kind,\n setStore,\n environment = \"production\",\n scopes,\n teamId,\n } = options;\n\n // Stable signature for `scopes` so its identity doesn't churn the effect\n // dep across renders when callers pass a fresh array literal each time.\n const scopesKey = useMemo(() => (scopes ? JSON.stringify(scopes) : \"\"), [scopes]);\n\n // --- Per-resource status ---\n const [connectionsStatus, setConnectionsStatus] = useState<ResourceStatus>(\n resolvers?.getConnections ? \"loading\" : \"idle\",\n );\n const [fieldLoadStates, setFieldLoadStates] = useState<Record<string, FieldLoadState>>({});\n\n // --- Form ---\n const form = useForm<T>({\n resolver: zodResolver(schema),\n defaultValues: defaultValues as any,\n });\n\n // --- Helpers ---\n const mergeStore = useCallback(\n (incoming: FormStore) => setStore((old) => mergeFormStores(old, incoming)),\n [setStore],\n );\n\n // --- Effect 1: Load connections ---\n useEffect(() => {\n if (!resolvers?.getConnections) {\n setConnectionsStatus(\"idle\");\n return;\n }\n\n let cancelled = false;\n setConnectionsStatus(\"loading\");\n\n Promise.resolve(resolvers.getConnections({ id: pipeOrSearchId, environment }))\n .then((conns) => {\n if (cancelled) return;\n\n mergeStore({\n field_options: {\n connections: {\n options: conns.map((c) => ({\n label: c.public_id,\n value: c.public_id,\n widgets: {\n provider_logo: { provider: c.provider as ProviderName },\n },\n })),\n },\n },\n });\n\n setConnectionsStatus(\"ready\");\n })\n .catch(() => {\n if (!cancelled) setConnectionsStatus(\"error\");\n });\n\n return () => {\n cancelled = true;\n };\n }, [pipeOrSearchId, environment, resolvers?.getConnections, mergeStore]);\n\n // --- Curried secrets search ---\n // Each keystroke in the reference picker fires this with the latest query.\n // The picker handles debounce + race-correctness; here we just bundle in\n // form-level args (environment / scopes / teamId) and call the resolver.\n // No caching: every call hits the resolver. Returns [] if no resolver.\n const getSecretsResolver = resolvers?.getSecrets;\n const searchSecrets = useCallback(\n async (query: string): Promise<SecretSuggestion[]> => {\n if (!getSecretsResolver) return [];\n return Promise.resolve(getSecretsResolver({ query, environment, scopes, teamId }));\n },\n // `scopesKey` is the stable serialization of `scopes`; depending on the\n // raw array would churn the callback identity on every parent render.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [getSecretsResolver, environment, scopesKey, teamId],\n );\n\n // --- Curried constants search ---\n // Mirrors `searchSecrets` exactly. Same per-keystroke contract, same\n // form-level arg bundling. Returns [] when no resolver is wired.\n const getConstantsResolver = resolvers?.getConstants;\n const searchConstants = useCallback(\n async (query: string): Promise<ConstantSuggestion[]> => {\n if (!getConstantsResolver) return [];\n return Promise.resolve(getConstantsResolver({ query, environment, scopes, teamId }));\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [getConstantsResolver, environment, scopesKey, teamId],\n );\n\n // --- Effect 2: Evaluate enabledIf slots + drive context_select fetching ---\n const slots = useMemo(() => collectEnabledSlots(formConfig), [formConfig]);\n\n // Subscribe to all form value changes so resolvers re-evaluate.\n const watchedValues = form.watch();\n\n // Evaluate every slot against the current payload. Keep the result\n // serialized so the effect's deps stay stable across reference-identical\n // re-renders.\n const slotResults = useMemo(() => {\n const out: Record<string, EnabledResult> = {};\n for (const slot of slots) {\n out[`${slot.fieldPath}::${slot.slotId}`] = evalSlot(slot, watchedValues);\n }\n return out;\n }, [slots, watchedValues]);\n const slotResultsSig = useMemo(() => JSON.stringify(slotResults), [slotResults]);\n\n // Track previous results so we can detect enabled→disabled transitions\n // (drives field-value clearing) and last-fired fetch signatures.\n const prevResultsRef = useRef<Record<string, EnabledResult>>({});\n const lastFiredSigRef = useRef<Record<string, string>>({});\n\n useEffect(() => {\n if (slots.length === 0) return;\n\n let cancelled = false;\n const nextLoadStates: Record<string, FieldLoadState> = {\n ...fieldLoadStates,\n };\n\n // Group slot results by field path for the load-state map.\n const byField: Record<string, { field?: EnabledResult; suggestions?: EnabledResult }> = {};\n for (const slot of slots) {\n const r = slotResults[`${slot.fieldPath}::${slot.slotId}`];\n if (r == null) continue;\n byField[slot.fieldPath] ??= {};\n byField[slot.fieldPath][slot.slotId] = r;\n }\n\n for (const slot of slots) {\n const key = `${slot.fieldPath}::${slot.slotId}`;\n const r = slotResults[key];\n if (r == null) continue;\n const prev = prevResultsRef.current[key];\n\n // Field-slot only: clear value on enabled→disabled transition.\n if (slot.slotId === \"field\" && r.disabled && prev != null && !prev.disabled) {\n form.setValue(slot.fieldPath as any, \"\" as any, {\n shouldDirty: true,\n shouldTouch: true,\n });\n }\n\n // Suggestions-slot: drive the existing context_select_input fetch.\n if (slot.slotId === \"suggestions\" && resolvers?.getFieldContext) {\n // If suggestions are gated, skip the fetch and reset dedupe so\n // re-enabling re-fires.\n if (r.disabled) {\n delete lastFiredSigRef.current[slot.fieldPath];\n continue;\n }\n\n // Resolve the connection for the legacy `requires.connection`\n // (still needed to pick the right secret for the fetch).\n const watchedConnections = (\n watchedValues as {\n connector?: { connections?: { connection?: string }[] };\n }\n )?.connector?.connections;\n const required = slot.optionsDef?.requires;\n\n let connectionId: string | undefined;\n if (required?.connection) {\n const match = watchedConnections?.find((c) =>\n c?.connection?.startsWith(`${required.connection}_`),\n );\n connectionId = match?.connection;\n // No matching connection — can't fetch, even if enabledIf passed.\n if (!connectionId) continue;\n }\n\n // Per-field signature for dedupe.\n const perFieldSig = JSON.stringify({\n connectionId,\n deps: required?.fields?.map((d) => getPathValue(watchedValues, d)) ?? [],\n });\n if (lastFiredSigRef.current[slot.fieldPath] === perFieldSig) continue;\n lastFiredSigRef.current[slot.fieldPath] = perFieldSig;\n\n // Mark loading for this field's fetch.\n const existing = nextLoadStates[slot.fieldPath];\n nextLoadStates[slot.fieldPath] = {\n status: \"loading\",\n disabled: existing?.disabled ?? false,\n disabledReason: existing?.disabledReason,\n suggestionsDisabled: false,\n suggestionsDisabledReason: undefined,\n };\n\n const idKey = kind === \"search\" ? \"search_id\" : \"pipe_id\";\n\n Promise.resolve(\n resolvers.getFieldContext({\n fieldPath: slot.fieldPath,\n query: \"\",\n payload: {\n ...(watchedValues as Record<string, unknown>),\n [idKey]: pipeOrSearchId,\n },\n }),\n )\n .then((incoming: FormStore) => {\n if (cancelled) return;\n mergeStore(incoming);\n setFieldLoadStates((s) => ({\n ...s,\n [slot.fieldPath]: {\n ...(s[slot.fieldPath] ?? {\n disabled: false,\n suggestionsDisabled: false,\n }),\n status: \"ready\",\n },\n }));\n })\n .catch(() => {\n if (cancelled) return;\n setFieldLoadStates((s) => ({\n ...s,\n [slot.fieldPath]: {\n ...(s[slot.fieldPath] ?? {\n disabled: false,\n suggestionsDisabled: false,\n }),\n status: \"error\",\n },\n }));\n });\n }\n }\n\n // Reflect the latest enabledIf evaluation into fieldLoadStates so the\n // adapters and field-wrapper can render the disabled state.\n for (const fieldPath of Object.keys(byField)) {\n const { field: fieldR, suggestions: sugR } = byField[fieldPath]!;\n const prevState = nextLoadStates[fieldPath];\n nextLoadStates[fieldPath] = {\n status: prevState?.status ?? \"idle\",\n disabled: fieldR == null ? (prevState?.disabled ?? false) : fieldR.disabled,\n disabledReason: fieldR == null ? prevState?.disabledReason : fieldR.message,\n suggestionsDisabled:\n sugR == null ? (prevState?.suggestionsDisabled ?? false) : sugR.disabled,\n suggestionsDisabledReason:\n sugR == null ? prevState?.suggestionsDisabledReason : sugR.message,\n };\n }\n\n setFieldLoadStates(nextLoadStates);\n prevResultsRef.current = slotResults;\n\n return () => {\n cancelled = true;\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [slotResultsSig, slots, pipeOrSearchId]);\n\n // --- Sections & fields ---\n const isSubmitted = form.formState.isSubmitted;\n const formErrors = form.formState.errors;\n\n // `watchedValues` and `formErrors` must be in the dep array: field handles\n // bake `form.getValues(path)` snapshots into `field.value` / textareaProps /\n // selectedValue, and adapters render those as controlled inputs. Without\n // these deps, the memo never refreshes on keystrokes and the controlled\n // inputs snap back to their stale snapshot — typing/selecting appears to\n // do nothing. See FieldRenderer's memo comment for the intended contract.\n const sections = useMemo(\n () =>\n buildSectionHandles(formConfig, form as any, publicKey, {\n fieldLoadStates,\n searchSecrets,\n searchConstants,\n }),\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [\n formConfig,\n form,\n publicKey,\n fieldLoadStates,\n isSubmitted,\n searchSecrets,\n searchConstants,\n watchedValues,\n formErrors,\n ],\n );\n\n const fields = useMemo(\n () => sections.flatMap((s) => s.groups.flatMap((g) => g.fields)),\n [sections],\n );\n\n const { fieldLoaderErrors, loadingFieldLoaders, hasFieldLoaderError, isFieldLoaderLoading } =\n useMemo(() => {\n const errors: Record<string, FieldLoadState> = {};\n const loading: Record<string, FieldLoadState> = {};\n for (const [path, state] of Object.entries(fieldLoadStates)) {\n if (state.status === \"error\") errors[path] = state;\n else if (state.status === \"loading\") loading[path] = state;\n }\n return {\n fieldLoaderErrors: errors,\n loadingFieldLoaders: loading,\n hasFieldLoaderError: Object.keys(errors).length > 0,\n isFieldLoaderLoading: Object.keys(loading).length > 0,\n };\n }, [fieldLoadStates]);\n\n return {\n connectionsStatus,\n fieldLoadStates,\n fieldLoaderErrors,\n loadingFieldLoaders,\n hasFieldLoaderError,\n isFieldLoaderLoading,\n form,\n sections,\n fields,\n reset: form.reset,\n };\n}\n"],"mappings":"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"}
@@ -27,12 +27,12 @@ declare function useSearchCatalogTable(config?: {
27
27
  removeColumnFilter: (id: "inputFields" | "outputFields" | "tags" | "providers") => void;
28
28
  resetFilters: () => void;
29
29
  getColumnFilterValue: (id: "inputFields" | "outputFields" | "tags" | "providers") => string;
30
- sortedOutputFieldEntries: [string, ("companies:profiles:crustdata@1" | "companies:profiles:crustdata@2" | "companies:profiles:amplemarket@1" | "companies:profiles:amplemarket@2" | "people:profiles:crustdata@1" | "people:profiles:crustdata@2" | "people:profiles:amplemarket@1" | "people:profiles:amplemarket@2" | "companies:entitysearch:parallel@1" | "people:entitysearch:parallel@1" | "people:eventguests:luma@1")[]][];
31
- sortedTagEntries: [string, ("companies:profiles:crustdata@1" | "companies:profiles:crustdata@2" | "companies:profiles:amplemarket@1" | "companies:profiles:amplemarket@2" | "people:profiles:crustdata@1" | "people:profiles:crustdata@2" | "people:profiles:amplemarket@1" | "people:profiles:amplemarket@2" | "companies:entitysearch:parallel@1" | "people:entitysearch:parallel@1" | "people:eventguests:luma@1")[]][];
32
- sortedProviderEntries: [string, ("companies:profiles:crustdata@1" | "companies:profiles:crustdata@2" | "companies:profiles:amplemarket@1" | "companies:profiles:amplemarket@2" | "people:profiles:crustdata@1" | "people:profiles:crustdata@2" | "people:profiles:amplemarket@1" | "people:profiles:amplemarket@2" | "companies:entitysearch:parallel@1" | "people:entitysearch:parallel@1" | "people:eventguests:luma@1")[]][];
33
- searchIdsByOutputField: Record<string, ("companies:profiles:crustdata@1" | "companies:profiles:crustdata@2" | "companies:profiles:amplemarket@1" | "companies:profiles:amplemarket@2" | "people:profiles:crustdata@1" | "people:profiles:crustdata@2" | "people:profiles:amplemarket@1" | "people:profiles:amplemarket@2" | "companies:entitysearch:parallel@1" | "people:entitysearch:parallel@1" | "people:eventguests:luma@1")[]>;
34
- searchIdsByProvider: Record<string, ("companies:profiles:crustdata@1" | "companies:profiles:crustdata@2" | "companies:profiles:amplemarket@1" | "companies:profiles:amplemarket@2" | "people:profiles:crustdata@1" | "people:profiles:crustdata@2" | "people:profiles:amplemarket@1" | "people:profiles:amplemarket@2" | "companies:entitysearch:parallel@1" | "people:entitysearch:parallel@1" | "people:eventguests:luma@1")[]>;
35
- searchIdsByTag: Record<string, ("companies:profiles:crustdata@1" | "companies:profiles:crustdata@2" | "companies:profiles:amplemarket@1" | "companies:profiles:amplemarket@2" | "people:profiles:crustdata@1" | "people:profiles:crustdata@2" | "people:profiles:amplemarket@1" | "people:profiles:amplemarket@2" | "companies:entitysearch:parallel@1" | "people:entitysearch:parallel@1" | "people:eventguests:luma@1")[]>;
30
+ sortedOutputFieldEntries: [string, ("companies:profiles:crustdata@1" | "companies:profiles:crustdata@2" | "companies:profiles:amplemarket@1" | "companies:profiles:amplemarket@2" | "people:profiles:crustdata@1" | "people:profiles:crustdata@2" | "people:profiles:amplemarket@1" | "people:profiles:amplemarket@2" | "companies:entitysearch:parallel@1" | "people:entitysearch:parallel@1" | "people:eventguests:luma@1" | "sheet:rows@1")[]][];
31
+ sortedTagEntries: [string, ("companies:profiles:crustdata@1" | "companies:profiles:crustdata@2" | "companies:profiles:amplemarket@1" | "companies:profiles:amplemarket@2" | "people:profiles:crustdata@1" | "people:profiles:crustdata@2" | "people:profiles:amplemarket@1" | "people:profiles:amplemarket@2" | "companies:entitysearch:parallel@1" | "people:entitysearch:parallel@1" | "people:eventguests:luma@1" | "sheet:rows@1")[]][];
32
+ sortedProviderEntries: [string, ("companies:profiles:crustdata@1" | "companies:profiles:crustdata@2" | "companies:profiles:amplemarket@1" | "companies:profiles:amplemarket@2" | "people:profiles:crustdata@1" | "people:profiles:crustdata@2" | "people:profiles:amplemarket@1" | "people:profiles:amplemarket@2" | "companies:entitysearch:parallel@1" | "people:entitysearch:parallel@1" | "people:eventguests:luma@1" | "sheet:rows@1")[]][];
33
+ searchIdsByOutputField: Record<string, ("companies:profiles:crustdata@1" | "companies:profiles:crustdata@2" | "companies:profiles:amplemarket@1" | "companies:profiles:amplemarket@2" | "people:profiles:crustdata@1" | "people:profiles:crustdata@2" | "people:profiles:amplemarket@1" | "people:profiles:amplemarket@2" | "companies:entitysearch:parallel@1" | "people:entitysearch:parallel@1" | "people:eventguests:luma@1" | "sheet:rows@1")[]>;
34
+ searchIdsByProvider: Record<string, ("companies:profiles:crustdata@1" | "companies:profiles:crustdata@2" | "companies:profiles:amplemarket@1" | "companies:profiles:amplemarket@2" | "people:profiles:crustdata@1" | "people:profiles:crustdata@2" | "people:profiles:amplemarket@1" | "people:profiles:amplemarket@2" | "companies:entitysearch:parallel@1" | "people:entitysearch:parallel@1" | "people:eventguests:luma@1" | "sheet:rows@1")[]>;
35
+ searchIdsByTag: Record<string, ("companies:profiles:crustdata@1" | "companies:profiles:crustdata@2" | "companies:profiles:amplemarket@1" | "companies:profiles:amplemarket@2" | "people:profiles:crustdata@1" | "people:profiles:crustdata@2" | "people:profiles:amplemarket@1" | "people:profiles:amplemarket@2" | "companies:entitysearch:parallel@1" | "people:entitysearch:parallel@1" | "people:eventguests:luma@1" | "sheet:rows@1")[]>;
36
36
  };
37
37
  type UseSearchCatalogTableReturn = ReturnType<typeof useSearchCatalogTable>;
38
38
  //#endregion
@@ -419,7 +419,10 @@ function applyFormCustomization(sections, customization) {
419
419
  description: fieldOverride.description ?? field.description
420
420
  };
421
421
  });
422
- const errorCount = group.errorCount > 0 ? fields.filter((f) => f.error != null).length : 0;
422
+ const fieldErrorsBefore = group.fields.filter((f) => f.error != null).length;
423
+ const groupPathErrors = group.errorCount - fieldErrorsBefore;
424
+ const fieldErrorsAfter = fields.filter((f) => f.error != null).length;
425
+ const errorCount = group.errorCount > 0 ? fieldErrorsAfter + groupPathErrors : 0;
423
426
  const setCount = fields.filter((f) => !isEmptyValue(f.value)).length;
424
427
  const dirtyCount = fields.filter((f) => f.dirty).length;
425
428
  return {
@@ -1 +1 @@
1
- {"version":3,"file":"build-section-handlers.mjs","names":[],"sources":["../../src/utils/build-section-handlers.ts"],"sourcesContent":["import type { FormSection, GeneratedInputMeta, SecretSuggestion, SectionKeys } 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 { FormCustomizationState } from \"../types/form-customization.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.key_value_list_input(meta)) {\n const rows = (base.value as Array<{ key: string; value: string }>) ?? [];\n return {\n rows,\n addRow: () => base.setValue([...rows, { key: \"\", value: \"\" }]),\n removeRow: (index: number) => base.setValue(rows.filter((_, i) => i !== index)),\n setKey: (index: number, key: string) =>\n base.setValue(rows.map((row, i) => (i === index ? { ...row, key } : row))),\n setValue: (index: number, value: string) =>\n base.setValue(rows.map((row, i) => (i === index ? { ...row, value } : row))),\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 // 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.map((section) => {\n const groups: FormGroupHandle[] = section.groups.map((group) => {\n const fields = group.fields.map((meta) =>\n buildFieldProps(meta, form, publicKey, loadingCtx),\n ) 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\n return {\n key: section.metadata.path,\n label: section.metadata.label,\n description: section.metadata.description,\n groups,\n };\n });\n}\n\nexport function applyFormCustomization(\n sections: FormSectionHandle[],\n customization: FormCustomizationState,\n): FormSectionHandle[] {\n const { sectionMap, groupMap, pathMap } = customization;\n\n const hasSectionOverrides = Object.keys(sectionMap).length > 0;\n const hasGroupOverrides = Object.keys(groupMap).length > 0;\n const hasPathOverrides = Object.keys(pathMap).length > 0;\n\n if (!hasSectionOverrides && !hasGroupOverrides && !hasPathOverrides) {\n return sections;\n }\n\n return sections\n .filter((section) => sectionMap[section.key as SectionKeys] !== null)\n .map((section) => {\n const sectionOverride = sectionMap[section.key as SectionKeys];\n const mergedSection = sectionOverride\n ? {\n ...section,\n label: sectionOverride.label ?? section.label,\n description: sectionOverride.description ?? section.description,\n }\n : section;\n\n const groups = mergedSection.groups\n .filter((group) => groupMap[group.key] !== null)\n .map((group) => {\n const groupOverride = groupMap[group.key];\n const mergedGroup = groupOverride\n ? {\n ...group,\n label: groupOverride.label ?? group.label,\n description: groupOverride.description ?? group.description,\n iconKey: groupOverride.iconKey ?? group.iconKey,\n defaultExpand: groupOverride.defaultExpand ?? group.defaultExpand,\n }\n : group;\n\n const fields = mergedGroup.fields\n .filter((field) => pathMap[field.path] !== null)\n .map((field) => {\n const fieldOverride = pathMap[field.path];\n if (!fieldOverride) return field;\n return {\n ...field,\n label: fieldOverride.label ?? field.label,\n description: fieldOverride.description ?? field.description,\n };\n });\n\n // Preserve the submit-gated error count from buildSectionHandles:\n // if the original group was not flagged, don't resurrect errors\n // here just because we recount post-filter.\n const errorCount =\n group.errorCount > 0 ? fields.filter((f) => f.error != null).length : 0;\n const setCount = fields.filter((f) => !isEmptyValue(f.value)).length;\n const dirtyCount = fields.filter((f) => f.dirty).length;\n\n return { ...mergedGroup, fields, errorCount, setCount, dirtyCount };\n })\n .filter((group) => group.fields.length > 0);\n\n return { ...mergedSection, groups };\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, SectionKeys } 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 { FormCustomizationState } from \"../types/form-customization.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.key_value_list_input(meta)) {\n const rows = (base.value as Array<{ key: string; value: string }>) ?? [];\n return {\n rows,\n addRow: () => base.setValue([...rows, { key: \"\", value: \"\" }]),\n removeRow: (index: number) => base.setValue(rows.filter((_, i) => i !== index)),\n setKey: (index: number, key: string) =>\n base.setValue(rows.map((row, i) => (i === index ? { ...row, key } : row))),\n setValue: (index: number, value: string) =>\n base.setValue(rows.map((row, i) => (i === index ? { ...row, value } : row))),\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 // 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.map((section) => {\n const groups: FormGroupHandle[] = section.groups.map((group) => {\n const fields = group.fields.map((meta) =>\n buildFieldProps(meta, form, publicKey, loadingCtx),\n ) 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\n return {\n key: section.metadata.path,\n label: section.metadata.label,\n description: section.metadata.description,\n groups,\n };\n });\n}\n\nexport function applyFormCustomization(\n sections: FormSectionHandle[],\n customization: FormCustomizationState,\n): FormSectionHandle[] {\n const { sectionMap, groupMap, pathMap } = customization;\n\n const hasSectionOverrides = Object.keys(sectionMap).length > 0;\n const hasGroupOverrides = Object.keys(groupMap).length > 0;\n const hasPathOverrides = Object.keys(pathMap).length > 0;\n\n if (!hasSectionOverrides && !hasGroupOverrides && !hasPathOverrides) {\n return sections;\n }\n\n return sections\n .filter((section) => sectionMap[section.key as SectionKeys] !== null)\n .map((section) => {\n const sectionOverride = sectionMap[section.key as SectionKeys];\n const mergedSection = sectionOverride\n ? {\n ...section,\n label: sectionOverride.label ?? section.label,\n description: sectionOverride.description ?? section.description,\n }\n : section;\n\n const groups = mergedSection.groups\n .filter((group) => groupMap[group.key] !== null)\n .map((group) => {\n const groupOverride = groupMap[group.key];\n const mergedGroup = groupOverride\n ? {\n ...group,\n label: groupOverride.label ?? group.label,\n description: groupOverride.description ?? group.description,\n iconKey: groupOverride.iconKey ?? group.iconKey,\n defaultExpand: groupOverride.defaultExpand ?? group.defaultExpand,\n }\n : group;\n\n const fields = mergedGroup.fields\n .filter((field) => pathMap[field.path] !== null)\n .map((field) => {\n const fieldOverride = pathMap[field.path];\n if (!fieldOverride) return field;\n return {\n ...field,\n label: fieldOverride.label ?? field.label,\n description: fieldOverride.description ?? field.description,\n };\n });\n\n // Preserve the submit-gated error count from buildSectionHandles:\n // if the original group was not flagged, don't resurrect errors\n // here just because we recount post-filter. We must also preserve\n // the group-path portion of the count — errors that attach to the\n // group container (e.g. the required connector's nested\n // `connector.connections` failure) surface there, not on any\n // field's own `error`, so recounting field errors alone would drop\n // them. Recover that portion as `original total − original field\n // errors`, then re-add it after filtering removed fields.\n const fieldErrorsBefore = group.fields.filter((f) => f.error != null).length;\n const groupPathErrors = group.errorCount - fieldErrorsBefore;\n const fieldErrorsAfter = fields.filter((f) => f.error != null).length;\n const errorCount = group.errorCount > 0 ? fieldErrorsAfter + groupPathErrors : 0;\n const setCount = fields.filter((f) => !isEmptyValue(f.value)).length;\n const dirtyCount = fields.filter((f) => f.dirty).length;\n\n return { ...mergedGroup, fields, errorCount, setCount, dirtyCount };\n })\n .filter((group) => group.fields.length > 0);\n\n return { ...mergedSection, groups };\n })\n .filter((section) => section.groups.length > 0);\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pipe0/react",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
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
  "lucide-react": "^0.475.0",
85
85
  "swr": "^2.4.1",
86
86
  "tailwind-merge": "^3.3.1",
87
- "@pipe0/base": "0.4.0"
87
+ "@pipe0/base": "0.4.1"
88
88
  },
89
89
  "devDependencies": {
90
90
  "@dnd-kit/core": "^6.3.1",