@pipe0/react 0.0.5 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/README.md +58 -2
- package/dist/components/compound/pipe-catalog/active-filters.d.mts +7 -10
- package/dist/components/compound/pipe-catalog/active-filters.d.mts.map +1 -1
- package/dist/components/compound/pipe-catalog/active-filters.mjs +22 -18
- package/dist/components/compound/pipe-catalog/active-filters.mjs.map +1 -1
- package/dist/components/compound/pipe-catalog/card.d.mts +3 -12
- package/dist/components/compound/pipe-catalog/card.d.mts.map +1 -1
- package/dist/components/compound/pipe-catalog/card.mjs +28 -25
- package/dist/components/compound/pipe-catalog/card.mjs.map +1 -1
- package/dist/components/compound/pipe-catalog/category-filter.d.mts +6 -13
- package/dist/components/compound/pipe-catalog/category-filter.d.mts.map +1 -1
- package/dist/components/compound/pipe-catalog/category-filter.mjs +12 -13
- package/dist/components/compound/pipe-catalog/category-filter.mjs.map +1 -1
- package/dist/components/compound/pipe-catalog/column-filter.d.mts +6 -14
- package/dist/components/compound/pipe-catalog/column-filter.d.mts.map +1 -1
- package/dist/components/compound/pipe-catalog/column-filter.mjs +9 -9
- package/dist/components/compound/pipe-catalog/column-filter.mjs.map +1 -1
- package/dist/components/compound/pipe-catalog/empty.d.mts +5 -10
- package/dist/components/compound/pipe-catalog/empty.d.mts.map +1 -1
- package/dist/components/compound/pipe-catalog/empty.mjs +12 -14
- package/dist/components/compound/pipe-catalog/empty.mjs.map +1 -1
- package/dist/components/compound/pipe-catalog/index.d.mts +1 -1
- package/dist/components/compound/pipe-catalog/input-field-filter.d.mts +3 -3
- package/dist/components/compound/pipe-catalog/input-field-filter.d.mts.map +1 -1
- package/dist/components/compound/pipe-catalog/input-field-filter.mjs.map +1 -1
- package/dist/components/compound/pipe-catalog/list.d.mts +8 -25
- package/dist/components/compound/pipe-catalog/list.d.mts.map +1 -1
- package/dist/components/compound/pipe-catalog/list.mjs +14 -14
- package/dist/components/compound/pipe-catalog/list.mjs.map +1 -1
- package/dist/components/compound/pipe-catalog/output-field-filter.d.mts +3 -3
- package/dist/components/compound/pipe-catalog/output-field-filter.d.mts.map +1 -1
- package/dist/components/compound/pipe-catalog/output-field-filter.mjs.map +1 -1
- package/dist/components/compound/pipe-catalog/provider-filter.d.mts +3 -3
- package/dist/components/compound/pipe-catalog/provider-filter.d.mts.map +1 -1
- package/dist/components/compound/pipe-catalog/provider-filter.mjs.map +1 -1
- package/dist/components/compound/pipe-catalog/root.d.mts +6 -6
- package/dist/components/compound/pipe-catalog/root.d.mts.map +1 -1
- package/dist/components/compound/pipe-catalog/root.mjs +2 -2
- package/dist/components/compound/pipe-catalog/root.mjs.map +1 -1
- package/dist/components/compound/pipe-catalog/search-filter.d.mts +5 -9
- package/dist/components/compound/pipe-catalog/search-filter.d.mts.map +1 -1
- package/dist/components/compound/pipe-catalog/search-filter.mjs +9 -10
- package/dist/components/compound/pipe-catalog/search-filter.mjs.map +1 -1
- package/dist/components/compound/pipe-catalog/tag-filter.d.mts +3 -3
- package/dist/components/compound/pipe-catalog/tag-filter.d.mts.map +1 -1
- package/dist/components/compound/pipe-catalog/tag-filter.mjs.map +1 -1
- package/dist/components/compound/pipe-form/content.d.mts +6 -3
- package/dist/components/compound/pipe-form/content.d.mts.map +1 -1
- package/dist/components/compound/pipe-form/content.mjs +17 -25
- package/dist/components/compound/pipe-form/content.mjs.map +1 -1
- package/dist/components/compound/pipe-form/errors.d.mts +23 -0
- package/dist/components/compound/pipe-form/errors.d.mts.map +1 -0
- package/dist/components/compound/pipe-form/errors.mjs +40 -0
- package/dist/components/compound/pipe-form/errors.mjs.map +1 -0
- package/dist/components/compound/pipe-form/footer.d.mts +7 -7
- package/dist/components/compound/pipe-form/footer.d.mts.map +1 -1
- package/dist/components/compound/pipe-form/footer.mjs +11 -6
- package/dist/components/compound/pipe-form/footer.mjs.map +1 -1
- package/dist/components/compound/pipe-form/header.d.mts +7 -7
- package/dist/components/compound/pipe-form/header.d.mts.map +1 -1
- package/dist/components/compound/pipe-form/header.mjs +11 -6
- package/dist/components/compound/pipe-form/header.mjs.map +1 -1
- package/dist/components/compound/pipe-form/index.d.mts +2 -1
- package/dist/components/compound/pipe-form/root.d.mts +18 -11
- package/dist/components/compound/pipe-form/root.d.mts.map +1 -1
- package/dist/components/compound/pipe-form/root.mjs +21 -27
- package/dist/components/compound/pipe-form/root.mjs.map +1 -1
- package/dist/components/compound/pipe-form/submit-button.d.mts +15 -4
- package/dist/components/compound/pipe-form/submit-button.d.mts.map +1 -1
- package/dist/components/compound/pipe-form/submit-button.mjs +23 -8
- package/dist/components/compound/pipe-form/submit-button.mjs.map +1 -1
- package/dist/components/compound/pipe-form/title.d.mts +9 -8
- package/dist/components/compound/pipe-form/title.d.mts.map +1 -1
- package/dist/components/compound/pipe-form/title.mjs +11 -6
- package/dist/components/compound/pipe-form/title.mjs.map +1 -1
- package/dist/components/compound/search-catalog/active-filters.d.mts +7 -10
- package/dist/components/compound/search-catalog/active-filters.d.mts.map +1 -1
- package/dist/components/compound/search-catalog/active-filters.mjs +22 -18
- package/dist/components/compound/search-catalog/active-filters.mjs.map +1 -1
- package/dist/components/compound/search-catalog/card.d.mts +4 -13
- package/dist/components/compound/search-catalog/card.d.mts.map +1 -1
- package/dist/components/compound/search-catalog/card.mjs +31 -28
- package/dist/components/compound/search-catalog/card.mjs.map +1 -1
- package/dist/components/compound/search-catalog/category-filter.d.mts +7 -13
- package/dist/components/compound/search-catalog/category-filter.d.mts.map +1 -1
- package/dist/components/compound/search-catalog/category-filter.mjs +12 -13
- package/dist/components/compound/search-catalog/category-filter.mjs.map +1 -1
- package/dist/components/compound/search-catalog/column-filter.d.mts +6 -10
- package/dist/components/compound/search-catalog/column-filter.d.mts.map +1 -1
- package/dist/components/compound/search-catalog/column-filter.mjs +9 -9
- package/dist/components/compound/search-catalog/column-filter.mjs.map +1 -1
- package/dist/components/compound/search-catalog/empty.d.mts +5 -10
- package/dist/components/compound/search-catalog/empty.d.mts.map +1 -1
- package/dist/components/compound/search-catalog/empty.mjs +12 -14
- package/dist/components/compound/search-catalog/empty.mjs.map +1 -1
- package/dist/components/compound/search-catalog/index.d.mts +1 -1
- package/dist/components/compound/search-catalog/list.d.mts +8 -10
- package/dist/components/compound/search-catalog/list.d.mts.map +1 -1
- package/dist/components/compound/search-catalog/list.mjs +14 -14
- package/dist/components/compound/search-catalog/list.mjs.map +1 -1
- package/dist/components/compound/search-catalog/output-field-filter.d.mts +3 -3
- package/dist/components/compound/search-catalog/output-field-filter.d.mts.map +1 -1
- package/dist/components/compound/search-catalog/output-field-filter.mjs.map +1 -1
- package/dist/components/compound/search-catalog/provider-filter.d.mts +3 -3
- package/dist/components/compound/search-catalog/provider-filter.d.mts.map +1 -1
- package/dist/components/compound/search-catalog/provider-filter.mjs.map +1 -1
- package/dist/components/compound/search-catalog/root.d.mts +6 -6
- package/dist/components/compound/search-catalog/root.d.mts.map +1 -1
- package/dist/components/compound/search-catalog/root.mjs +2 -2
- package/dist/components/compound/search-catalog/root.mjs.map +1 -1
- package/dist/components/compound/search-catalog/search-filter.d.mts +5 -9
- package/dist/components/compound/search-catalog/search-filter.d.mts.map +1 -1
- package/dist/components/compound/search-catalog/search-filter.mjs +9 -10
- package/dist/components/compound/search-catalog/search-filter.mjs.map +1 -1
- package/dist/components/compound/search-catalog/tag-filter.d.mts +3 -3
- package/dist/components/compound/search-catalog/tag-filter.d.mts.map +1 -1
- package/dist/components/compound/search-catalog/tag-filter.mjs.map +1 -1
- package/dist/components/compound/search-form/content.d.mts +6 -3
- package/dist/components/compound/search-form/content.d.mts.map +1 -1
- package/dist/components/compound/search-form/content.mjs +17 -25
- package/dist/components/compound/search-form/content.mjs.map +1 -1
- package/dist/components/compound/search-form/errors.d.mts +23 -0
- package/dist/components/compound/search-form/errors.d.mts.map +1 -0
- package/dist/components/compound/search-form/errors.mjs +40 -0
- package/dist/components/compound/search-form/errors.mjs.map +1 -0
- package/dist/components/compound/search-form/footer.d.mts +7 -7
- package/dist/components/compound/search-form/footer.d.mts.map +1 -1
- package/dist/components/compound/search-form/footer.mjs +11 -6
- package/dist/components/compound/search-form/footer.mjs.map +1 -1
- package/dist/components/compound/search-form/header.d.mts +7 -7
- package/dist/components/compound/search-form/header.d.mts.map +1 -1
- package/dist/components/compound/search-form/header.mjs +11 -6
- package/dist/components/compound/search-form/header.mjs.map +1 -1
- package/dist/components/compound/search-form/index.d.mts +2 -1
- package/dist/components/compound/search-form/root.d.mts +19 -12
- package/dist/components/compound/search-form/root.d.mts.map +1 -1
- package/dist/components/compound/search-form/root.mjs +21 -27
- package/dist/components/compound/search-form/root.mjs.map +1 -1
- package/dist/components/compound/search-form/submit-button.d.mts +15 -4
- package/dist/components/compound/search-form/submit-button.d.mts.map +1 -1
- package/dist/components/compound/search-form/submit-button.mjs +23 -8
- package/dist/components/compound/search-form/submit-button.mjs.map +1 -1
- package/dist/components/compound/search-form/title.d.mts +9 -8
- package/dist/components/compound/search-form/title.d.mts.map +1 -1
- package/dist/components/compound/search-form/title.mjs +11 -6
- package/dist/components/compound/search-form/title.mjs.map +1 -1
- package/dist/components/compound/searches-catalog/active-filters.d.mts +7 -10
- package/dist/components/compound/searches-catalog/active-filters.d.mts.map +1 -1
- package/dist/components/compound/searches-catalog/active-filters.mjs +22 -18
- package/dist/components/compound/searches-catalog/active-filters.mjs.map +1 -1
- package/dist/components/compound/searches-catalog/card.d.mts +5 -6
- package/dist/components/compound/searches-catalog/card.d.mts.map +1 -1
- package/dist/components/compound/searches-catalog/card.mjs +38 -28
- package/dist/components/compound/searches-catalog/card.mjs.map +1 -1
- package/dist/components/compound/searches-catalog/category-filter.d.mts +7 -13
- package/dist/components/compound/searches-catalog/category-filter.d.mts.map +1 -1
- package/dist/components/compound/searches-catalog/category-filter.mjs +12 -13
- package/dist/components/compound/searches-catalog/category-filter.mjs.map +1 -1
- package/dist/components/compound/searches-catalog/column-filter.d.mts +6 -10
- package/dist/components/compound/searches-catalog/column-filter.d.mts.map +1 -1
- package/dist/components/compound/searches-catalog/column-filter.mjs +9 -9
- package/dist/components/compound/searches-catalog/column-filter.mjs.map +1 -1
- package/dist/components/compound/searches-catalog/empty.d.mts +5 -10
- package/dist/components/compound/searches-catalog/empty.d.mts.map +1 -1
- package/dist/components/compound/searches-catalog/empty.mjs +12 -14
- package/dist/components/compound/searches-catalog/empty.mjs.map +1 -1
- package/dist/components/compound/searches-catalog/index.d.mts +1 -1
- package/dist/components/compound/searches-catalog/list.d.mts +8 -10
- package/dist/components/compound/searches-catalog/list.d.mts.map +1 -1
- package/dist/components/compound/searches-catalog/list.mjs +14 -14
- package/dist/components/compound/searches-catalog/list.mjs.map +1 -1
- package/dist/components/compound/searches-catalog/output-field-filter.d.mts +3 -3
- package/dist/components/compound/searches-catalog/output-field-filter.d.mts.map +1 -1
- package/dist/components/compound/searches-catalog/output-field-filter.mjs.map +1 -1
- package/dist/components/compound/searches-catalog/provider-filter.d.mts +3 -3
- package/dist/components/compound/searches-catalog/provider-filter.d.mts.map +1 -1
- package/dist/components/compound/searches-catalog/provider-filter.mjs.map +1 -1
- package/dist/components/compound/searches-catalog/root.d.mts +6 -6
- package/dist/components/compound/searches-catalog/root.d.mts.map +1 -1
- package/dist/components/compound/searches-catalog/root.mjs +2 -2
- package/dist/components/compound/searches-catalog/root.mjs.map +1 -1
- package/dist/components/compound/searches-catalog/search-filter.d.mts +5 -9
- package/dist/components/compound/searches-catalog/search-filter.d.mts.map +1 -1
- package/dist/components/compound/searches-catalog/search-filter.mjs +9 -10
- package/dist/components/compound/searches-catalog/search-filter.mjs.map +1 -1
- package/dist/components/compound/searches-catalog/tag-filter.d.mts +3 -3
- package/dist/components/compound/searches-catalog/tag-filter.d.mts.map +1 -1
- package/dist/components/compound/searches-catalog/tag-filter.mjs.map +1 -1
- package/dist/components/defaults/adapters/index.mjs +2 -2
- package/dist/components/defaults/adapters/index.mjs.map +1 -1
- package/dist/components/defaults/adapters/json-extraction-input.mjs +291 -199
- package/dist/components/defaults/adapters/json-extraction-input.mjs.map +1 -1
- package/dist/components/defaults/adapters/{pipes-trigger-input.mjs → pipes-run-if-input.mjs} +32 -32
- package/dist/components/defaults/adapters/pipes-run-if-input.mjs.map +1 -0
- package/dist/components/defaults/adapters/providers-input.mjs +221 -13
- package/dist/components/defaults/adapters/providers-input.mjs.map +1 -1
- package/dist/components/defaults/catalog/card-primitives.d.mts +14 -24
- package/dist/components/defaults/catalog/card-primitives.d.mts.map +1 -1
- package/dist/components/defaults/catalog/card-primitives.mjs +19 -19
- package/dist/components/defaults/catalog/card-primitives.mjs.map +1 -1
- package/dist/components/defaults/catalog/layout.mjs +7 -10
- package/dist/components/defaults/catalog/layout.mjs.map +1 -1
- package/dist/components/defaults/layout/field-wrapper.d.mts +2 -2
- package/dist/components/defaults/layout/field-wrapper.d.mts.map +1 -1
- package/dist/components/defaults/layout/field-wrapper.mjs +5 -2
- package/dist/components/defaults/layout/field-wrapper.mjs.map +1 -1
- package/dist/components/defaults/layout/group.d.mts +4 -4
- package/dist/components/defaults/layout/group.d.mts.map +1 -1
- package/dist/components/defaults/layout/group.mjs +69 -54
- package/dist/components/defaults/layout/group.mjs.map +1 -1
- package/dist/components/defaults/layout/section.d.mts +9 -4
- package/dist/components/defaults/layout/section.d.mts.map +1 -1
- package/dist/components/defaults/layout/section.mjs +11 -13
- package/dist/components/defaults/layout/section.mjs.map +1 -1
- package/dist/components/field-renderer.d.mts.map +1 -1
- package/dist/components/field-renderer.mjs +1 -1
- package/dist/components/field-renderer.mjs.map +1 -1
- package/dist/components/internal/LiquidEditor/ChipEditPopover.mjs +30 -15
- package/dist/components/internal/LiquidEditor/ChipEditPopover.mjs.map +1 -1
- package/dist/components/internal/icons.mjs +36 -1
- package/dist/components/internal/icons.mjs.map +1 -1
- package/dist/components/internal/multi-select-popover-trigger.mjs +0 -1
- package/dist/components/internal/multi-select-popover-trigger.mjs.map +1 -1
- package/dist/components/internal/tag-chip-decoration.mjs +15 -0
- package/dist/components/internal/tag-chip-decoration.mjs.map +1 -1
- package/dist/components/ui/badge.mjs +1 -1
- package/dist/components/ui/button.d.mts +1 -1
- package/dist/components/ui/combobox.mjs +0 -1
- package/dist/components/ui/combobox.mjs.map +1 -1
- package/dist/context/pipe-catalog-card-context.d.mts +7 -0
- package/dist/context/pipe-catalog-card-context.d.mts.map +1 -1
- package/dist/context/pipe-catalog-card-context.mjs.map +1 -1
- package/dist/context/pipe-form-context.d.mts +17 -3
- package/dist/context/pipe-form-context.d.mts.map +1 -1
- package/dist/context/pipe-form-context.mjs.map +1 -1
- package/dist/context/search-catalog-card-context.d.mts +8 -0
- package/dist/context/search-catalog-card-context.d.mts.map +1 -1
- package/dist/context/search-catalog-card-context.mjs.map +1 -1
- package/dist/context/search-form-context.d.mts +17 -3
- package/dist/context/search-form-context.d.mts.map +1 -1
- package/dist/context/search-form-context.mjs.map +1 -1
- package/dist/context/searches-catalog-card-context.d.mts +8 -0
- package/dist/context/searches-catalog-card-context.d.mts.map +1 -1
- package/dist/context/searches-catalog-card-context.mjs.map +1 -1
- package/dist/hooks/use-field-error.d.mts +2 -2
- package/dist/hooks/use-field-error.d.mts.map +1 -1
- package/dist/hooks/use-field-error.mjs +7 -3
- package/dist/hooks/use-field-error.mjs.map +1 -1
- package/dist/hooks/use-form-core.d.mts +0 -3
- package/dist/hooks/use-form-core.d.mts.map +1 -1
- package/dist/hooks/use-form-core.mjs +36 -2
- package/dist/hooks/use-form-core.mjs.map +1 -1
- package/dist/hooks/use-pipe-catalog-table.d.mts +8 -8
- package/dist/hooks/use-pipe-form.d.mts +11 -0
- package/dist/hooks/use-pipe-form.d.mts.map +1 -1
- package/dist/hooks/use-pipe-form.mjs +35 -6
- package/dist/hooks/use-pipe-form.mjs.map +1 -1
- package/dist/hooks/use-search-catalog-table.d.mts +6 -6
- package/dist/hooks/use-search-form.d.mts +11 -0
- package/dist/hooks/use-search-form.d.mts.map +1 -1
- package/dist/hooks/use-search-form.mjs +35 -6
- package/dist/hooks/use-search-form.mjs.map +1 -1
- package/dist/index.d.mts +9 -8
- package/dist/index.mjs +3 -9
- package/dist/styles/pipe0-form.css +4116 -1
- package/dist/types/adapters.d.mts +6 -5
- package/dist/types/adapters.d.mts.map +1 -1
- package/dist/types/catalog-adapters.d.mts +2 -2
- package/dist/types/field-props.d.mts +4 -16
- package/dist/types/field-props.d.mts.map +1 -1
- package/dist/types/form-handle.d.mts +81 -1
- package/dist/types/form-handle.d.mts.map +1 -1
- package/dist/utils/build-section-handlers.mjs +6 -2
- package/dist/utils/build-section-handlers.mjs.map +1 -1
- package/dist/utils/internal-form.mjs +28 -0
- package/dist/utils/internal-form.mjs.map +1 -0
- package/dist/widgets/avatar-group.d.mts +4 -7
- package/dist/widgets/avatar-group.d.mts.map +1 -1
- package/dist/widgets/avatar-group.mjs +13 -12
- package/dist/widgets/avatar-group.mjs.map +1 -1
- package/package.json +70 -18
- package/dist/components/compound/pipe-catalog/index.mjs +0 -15
- package/dist/components/compound/pipe-form/index.mjs +0 -11
- package/dist/components/compound/search-catalog/index.mjs +0 -14
- package/dist/components/compound/search-form/index.mjs +0 -11
- package/dist/components/compound/searches-catalog/index.mjs +0 -14
- package/dist/components/defaults/adapters/pipes-trigger-input.mjs.map +0 -1
- package/dist/components/defaults/layout/submit-button.d.mts +0 -9
- package/dist/components/defaults/layout/submit-button.d.mts.map +0 -1
- package/dist/components/defaults/layout/submit-button.mjs +0 -23
- package/dist/components/defaults/layout/submit-button.mjs.map +0 -1
- package/dist/components/defaults/toggle-advanced-button.mjs +0 -29
- package/dist/components/defaults/toggle-advanced-button.mjs.map +0 -1
- package/dist/components/ui/input-group.mjs +0 -30
- package/dist/components/ui/input-group.mjs.map +0 -1
- package/dist/context/form-customization-context.d.mts +0 -71
- package/dist/context/form-customization-context.d.mts.map +0 -1
- package/dist/context/form-customization-context.mjs +0 -114
- package/dist/context/form-customization-context.mjs.map +0 -1
- package/dist/hooks/use-disclosure.mjs +0 -35
- package/dist/hooks/use-disclosure.mjs.map +0 -1
- package/dist/utils/render-slot.d.mts +0 -44
- package/dist/utils/render-slot.d.mts.map +0 -1
- package/dist/utils/render-slot.mjs +0 -30
- package/dist/utils/render-slot.mjs.map +0 -1
- package/dist/widgets/index.mjs +0 -11
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"json-extraction-input.mjs","names":[],"sources":["../../../../src/components/defaults/adapters/json-extraction-input.tsx"],"sourcesContent":["import { Collapsible } from \"@base-ui/react/collapsible\";\nimport { Tabs } from \"@base-ui/react/tabs\";\nimport type { JSONExtraction, JSONExtractionMeta } from \"@pipe0/base\";\nimport { RECORD_FIELD_TYPES, TYPES_TO_FORMATS } from \"@pipe0/base\";\nimport { useMemo, useState } from \"react\";\nimport type { UseFormReturn } from \"react-hook-form\";\nimport { useFieldError } from \"../../../hooks/use-field-error.js\";\nimport { useJsonataPreview } from \"../../../hooks/use-jsonata-preview.js\";\nimport type { FieldHandle } from \"../../../types/field-handle.js\";\nimport { generateRandomString } from \"../../../utils/generate-random-string.js\";\nimport { HoverInfo } from \"../../hover-info.js\";\nimport { IconPlus, IconTrash } from \"../../internal/icons.js\";\nimport { Badge } from \"../../ui/badge.js\";\nimport { Button } from \"../../ui/button.js\";\nimport { Input } from \"../../ui/input.js\";\nimport { Label } from \"../../ui/label.js\";\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from \"../../ui/select.js\";\nimport { ToggleAdvancedButton } from \"../toggle-advanced-button.js\";\n\nfunction ExtractionPreview({\n exampleValue,\n extraction,\n}: {\n extraction: JSONExtraction[\"extractions\"][number];\n exampleValue: unknown;\n}) {\n const { preview, error, isLoading } = useJsonataPreview(extraction.path, exampleValue);\n\n return (\n <Tabs.Root\n defaultValue=\"extracted\"\n className=\"pz:flex pz:flex-col pz:gap-1 pz:rounded-md pz:border pz:border-input pz:bg-muted/30\"\n >\n <div className=\"pz:flex pz:items-center pz:justify-between pz:px-2 pz:py-1\">\n <span className=\"pz:text-xs pz:font-medium pz:text-muted-foreground\">Preview</span>\n <Tabs.List className=\"pz:inline-flex pz:gap-1\">\n {isLoading && <span className=\"pz:text-xs pz:text-muted-foreground\">...</span>}\n <Tabs.Tab\n value=\"extracted\"\n className=\"pz:rounded-sm pz:px-2 pz:py-0.5 pz:text-xs pz:hover:bg-accent pz:data-[active]:bg-accent pz:data-[active]:text-accent-foreground\"\n >\n Extracted\n </Tabs.Tab>\n <Tabs.Tab\n value=\"full\"\n className=\"pz:rounded-sm pz:px-2 pz:py-0.5 pz:text-xs pz:hover:bg-accent pz:data-[active]:bg-accent pz:data-[active]:text-accent-foreground\"\n >\n Full value\n </Tabs.Tab>\n </Tabs.List>\n </div>\n <Tabs.Panel value=\"full\">\n <pre className=\"pz:m-0 pz:overflow-auto pz:rounded-b-md pz:bg-muted/30 pz:p-2 pz:text-xs pz:text-foreground\">\n {JSON.stringify(exampleValue, null, 2)}\n </pre>\n </Tabs.Panel>\n <Tabs.Panel value=\"extracted\">\n <pre className=\"pz:m-0 pz:overflow-auto pz:rounded-b-md pz:bg-muted/30 pz:p-2 pz:text-xs pz:text-foreground\">\n {error ? error : JSON.stringify(preview, null, 2)}\n </pre>\n </Tabs.Panel>\n </Tabs.Root>\n );\n}\n\nfunction ExtractionCard({\n extraction,\n idx,\n isLast,\n option,\n form,\n basePath,\n onUpdate,\n onRemove,\n onAdd,\n}: {\n extraction: JSONExtraction[\"extractions\"][number];\n idx: number;\n isLast: boolean;\n option: JSONExtractionMeta[\"fields\"][number];\n form: UseFormReturn<any>;\n basePath: string;\n onUpdate: (idx: number, ext: JSONExtraction[\"extractions\"][number]) => void;\n onRemove: (idx: number) => void;\n onAdd: () => void;\n}) {\n const [showPreview, setShowPreview] = useState(false);\n const extractionPath = `${basePath}.extractions.${idx}`;\n const pathError = useFieldError(form, `${extractionPath}.path`);\n const nameError = useFieldError(form, `${extractionPath}.output_field.name`);\n\n const availableFormats = useMemo(\n () => TYPES_TO_FORMATS[extraction.output_field.type as keyof typeof TYPES_TO_FORMATS] ?? [],\n [extraction.output_field.type],\n );\n\n const updatePath = (value: string) => {\n onUpdate(idx, { ...extraction, path: value });\n };\n\n const updateOutputField = (\n property: \"type\" | \"format\" | \"name\" | \"label\" | \"description\",\n value: string | null,\n ) => {\n if (value === null) return;\n\n const newOutputField = { ...extraction.output_field, [property]: value };\n if (property === \"type\") {\n const newFormats = TYPES_TO_FORMATS[value as keyof typeof TYPES_TO_FORMATS] ?? [];\n if (newFormats.length === 0 || !newFormats.includes(newOutputField.format as never)) {\n newOutputField.format = null;\n }\n }\n onUpdate(idx, { ...extraction, output_field: newOutputField });\n };\n\n return (\n <div>\n <div className=\"pz:flex pz:flex-col pz:gap-2 pz:border-t pz:border-b pz:border-input pz:p-3\">\n <div className=\"pz:flex pz:items-center pz:justify-between\">\n <div className=\"pz:h-7 pz:px-2 pz:font-semibold pz:select-none pz:text-xs pz:rounded-sm pz:bg-accent pz:border pz:border-input pz:text-muted-foreground pz:grid pz:place-content-center\">\n {idx + 1}. Extraction\n </div>\n\n <Button\n variant=\"destructive\"\n size=\"icon\"\n className=\"pz:[&_svg]:size-3 pz:size-7 pz:rounded-sm\"\n onClick={() => onRemove(idx)}\n title=\"Remove condition\"\n >\n <IconTrash />\n </Button>\n </div>\n\n <div className=\"pz:flex pz:flex-col pz:gap-2\">\n {option.exampleValue && showPreview && (\n <ExtractionPreview exampleValue={option.exampleValue} extraction={extraction} />\n )}\n\n <div className=\"pz:flex pz:flex-col pz:gap-1\">\n <div className=\"pz:flex pz:items-center pz:justify-between\">\n <Label className=\"pz:text-xs pz:text-muted-foreground pz:inline-flex pz:items-center pz:gap-1\">\n Path <HoverInfo>Use JSONata</HoverInfo>\n </Label>\n {option.exampleValue ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n onClick={() => setShowPreview(!showPreview)}\n >\n {showPreview ? \"Hide preview\" : \"Show preview\"}\n </Button>\n ) : (\n <span className=\"pz:text-xs pz:text-muted-foreground\">No preview available</span>\n )}\n </div>\n <Input\n value={extraction.path}\n onChange={(e) => updatePath(e.target.value)}\n placeholder=\"ex. emails[0].value\"\n aria-invalid={!!pathError}\n />\n {pathError && (\n <span className=\"pz:text-destructive pz:text-xs pz:font-medium\" role=\"alert\">\n {pathError}\n </span>\n )}\n </div>\n\n <div className=\"pz:flex pz:items-end pz:gap-2\">\n <div className=\"pz:flex pz:flex-col pz:gap-1 pz:flex-1\">\n <Label className=\"pz:text-xs pz:text-muted-foreground\">Output Type</Label>\n <Select\n value={extraction.output_field.type}\n onValueChange={(v) => updateOutputField(\"type\", v as string)}\n >\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {RECORD_FIELD_TYPES.map((type) => (\n <SelectItem key={type} value={type}>\n {type}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n {availableFormats.length > 0 && (\n <div className=\"pz:flex pz:flex-col pz:gap-1 pz:flex-1\">\n <Label className=\"pz:text-xs pz:text-muted-foreground\">Format</Label>\n <Select\n value={extraction.output_field.format || \"\"}\n onValueChange={(v) => updateOutputField(\"format\", v)}\n >\n <SelectTrigger>\n <SelectValue placeholder=\"Select format\" />\n </SelectTrigger>\n <SelectContent>\n {availableFormats.map((format) => (\n <SelectItem key={format} value={format}>\n {format}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n )}\n </div>\n\n <Collapsible.Root>\n <Collapsible.Trigger\n render={<ToggleAdvancedButton>Open advanced</ToggleAdvancedButton>}\n />\n <Collapsible.Panel className=\"pz:flex pz:flex-col pz:gap-2 pz:pt-2\">\n <div className=\"pz:flex pz:flex-col pz:gap-1\">\n <Label className=\"pz:text-xs pz:text-muted-foreground\">Outpue field name</Label>\n <Input\n value={extraction.output_field.name}\n onChange={(e) => updateOutputField(\"name\", e.target.value)}\n aria-invalid={!!nameError}\n />\n {nameError && (\n <span className=\"pz:text-destructive pz:text-xs pz:font-medium\" role=\"alert\">\n {nameError}\n </span>\n )}\n </div>\n <div className=\"pz:flex pz:flex-col pz:gap-1\">\n <Label className=\"pz:text-xs pz:text-muted-foreground\">Output field label</Label>\n <Input\n value={extraction.output_field.label}\n onChange={(e) => updateOutputField(\"label\", e.target.value)}\n placeholder=\"Describe your new field\"\n />\n </div>\n </Collapsible.Panel>\n </Collapsible.Root>\n </div>\n </div>\n {isLast && (\n <div>\n <Button type=\"button\" variant=\"link\" size=\"xs\" onClick={onAdd}>\n <IconPlus />\n Add path\n </Button>\n </div>\n )}\n </div>\n );\n}\n\nexport function JsonExtractionInputAdapter(field: FieldHandle<\"json_extraction_input\">) {\n const meta = field.meta as JSONExtractionMeta;\n const value = (field.value ?? {\n field_name: \"\",\n extractions: [],\n }) as JSONExtraction;\n\n const addExtraction = (fieldName?: string) => {\n const inputFieldName = fieldName || value.field_name;\n const isInitial = value.extractions.length === 0;\n const newValue: JSONExtraction = {\n field_name: inputFieldName,\n extractions: [\n ...value.extractions,\n {\n path: \"\",\n output_field: {\n name: `extract_${inputFieldName}_${generateRandomString(4)}`,\n format: null,\n label: \"Extract JSON\",\n type: \"string\",\n },\n },\n ],\n };\n if (isInitial) {\n // First selection just scaffolds an empty extraction skeleton — the\n // user hasn't entered real data yet, so don't mark the field as\n // dirty/touched or trigger validation. RHF's own flags are the\n // idiomatic way to express this.\n field.form.setValue(field.path as any, newValue, {\n shouldDirty: false,\n shouldTouch: false,\n shouldValidate: false,\n });\n } else {\n field.setValue(newValue);\n }\n };\n\n const removeAllExtractions = () => {\n // resetField is the idiomatic RHF way to return a field to a pristine\n // baseline: clears value, dirty, touched, and errors in one call.\n field.form.resetField(field.path as any, {\n defaultValue: { field_name: \"\", extractions: [] },\n });\n };\n\n const updateExtraction = (idx: number, ext: JSONExtraction[\"extractions\"][number]) => {\n const newExtractions = [...value.extractions];\n newExtractions[idx] = ext;\n field.setValue({ ...value, extractions: newExtractions });\n };\n\n const removeExtraction = (idx: number) => {\n const newExtractions = [...value.extractions];\n newExtractions.splice(idx, 1);\n if (newExtractions.length === 0) {\n field.setValue({ field_name: \"\", extractions: [] });\n } else {\n field.setValue({ ...value, extractions: newExtractions });\n }\n };\n\n const option = useMemo(\n () => meta.fields.find((e) => e.fieldName === value.field_name),\n [value.field_name, meta.fields],\n );\n\n return (\n <div data-p0=\"input\" className=\"pz:flex pz:flex-col pz:gap-3\">\n {value.field_name && value.extractions.length > 0 && option ? (\n <div className=\"pz:flex pz:flex-col pz:gap-2\">\n <div className=\"pz:flex pz:items-center pz:justify-between\">\n <Badge\n variant=\"secondary\"\n className=\"pz:h-7 pz:bg-accent pz:border-input pz:border pz:text-accent-foreground pz:font-normal\"\n >\n Field: <b>{option.fieldLabel || option.fieldName}</b>\n </Badge>\n <Button\n type=\"button\"\n variant=\"destructive\"\n size=\"xs\"\n className=\"pz:font-normal pz:h-7\"\n onClick={removeAllExtractions}\n >\n Reset <IconTrash />\n </Button>\n </div>\n {value.extractions.map((extraction, idx) => (\n <ExtractionCard\n // biome-ignore lint/suspicious/noArrayIndexKey: index is stable\n key={idx}\n extraction={extraction}\n idx={idx}\n isLast={idx === value.extractions.length - 1}\n option={option}\n form={field.form}\n basePath={field.path}\n onUpdate={updateExtraction}\n onRemove={removeExtraction}\n onAdd={() => addExtraction()}\n />\n ))}\n </div>\n ) : meta.fields.length > 0 ? (\n <div className=\"pz:flex pz:flex-col pz:gap-2 pz:rounded-md pz:border-input\">\n <Select\n value=\"\"\n onValueChange={(v) => {\n if (v) addExtraction(v);\n }}\n >\n <SelectTrigger>\n <SelectValue placeholder=\"Select field\" />\n </SelectTrigger>\n <SelectContent>\n {meta.fields.map((f) => (\n <SelectItem key={f.fieldName} value={f.fieldName}>\n {f.fieldLabel} - {f.fieldName}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n ) : (\n <div className=\"pz:flex pz:items-center pz:gap-1.5 pz:rounded-md pz:px-1\">\n <div className=\"pz:text-xs pz:font-normal\">No JSON field available</div>\n <HoverInfo>\n A JSON field is required for this pipe. Add a json field to your pipeline.\n </HoverInfo>\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"json-extraction-input.mjs","names":[],"sources":["../../../../src/components/defaults/adapters/json-extraction-input.tsx"],"sourcesContent":["import type { JSONExtraction, JSONExtractionMeta } from \"@pipe0/base\";\nimport { RECORD_FIELD_TYPES, TYPES_TO_FORMATS } from \"@pipe0/base\";\nimport { type ReactNode, useMemo, useState } from \"react\";\nimport { useFieldError } from \"../../../hooks/use-field-error.js\";\nimport { useJsonataPreview } from \"../../../hooks/use-jsonata-preview.js\";\nimport { cn } from \"../../../lib/utils.js\";\nimport type { FieldHandle } from \"../../../types/field-handle.js\";\nimport type { FormHandle } from \"../../../types/form-handle.js\";\nimport { generateRandomString } from \"../../../utils/generate-random-string.js\";\nimport { HoverInfo } from \"../../hover-info.js\";\nimport {\n IconChevronDown,\n IconEye,\n IconEyeOff,\n IconPlus,\n IconRefresh,\n IconTrash,\n} from \"../../internal/icons.js\";\nimport { Button } from \"../../ui/button.js\";\nimport { Input } from \"../../ui/input.js\";\nimport { Label } from \"../../ui/label.js\";\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from \"../../ui/select.js\";\n\ntype PreviewType = \"string\" | \"number\" | \"boolean\" | \"object\" | \"array\" | \"null\" | \"undefined\";\n\nfunction inferPreviewType(value: unknown): PreviewType {\n if (value === null) return \"null\";\n if (value === undefined) return \"undefined\";\n if (Array.isArray(value)) return \"array\";\n if (typeof value === \"object\") return \"object\";\n return typeof value as PreviewType;\n}\n\nconst TOKEN_REGEX =\n /(\"(?:\\\\.|[^\"\\\\])*\"\\s*:)|(\"(?:\\\\.|[^\"\\\\])*\")|(-?\\d+(?:\\.\\d+)?(?:[eE][+-]?\\d+)?)|(true|false)|(null)/g;\n\n/**\n * Renders pretty-printed JSON with inline syntax styling. Sans-serif on\n * purpose — this surface inherits the form's display font, so we set\n * `font-sans` to override the scoped preflight that defaults <pre> to mono.\n */\nfunction JsonHighlight({ value }: { value: unknown }) {\n const json = useMemo(() => {\n try {\n return JSON.stringify(value, null, 2) ?? String(value);\n } catch {\n return String(value);\n }\n }, [value]);\n\n const tokens = useMemo<ReactNode[]>(() => {\n const out: ReactNode[] = [];\n let lastIndex = 0;\n let key = 0;\n TOKEN_REGEX.lastIndex = 0;\n let match: RegExpExecArray | null;\n // biome-ignore lint/suspicious/noAssignInExpressions: standard regex iteration\n while ((match = TOKEN_REGEX.exec(json)) !== null) {\n if (match.index > lastIndex) {\n out.push(json.slice(lastIndex, match.index));\n }\n const [whole, propKey, str, num, bool, nul] = match;\n if (propKey) {\n out.push(\n <span key={key++} className=\"pz:text-foreground/80\">\n {propKey}\n </span>,\n );\n } else if (str) {\n out.push(\n <span key={key++} className=\"pz:text-emerald-700 pz:dark:text-emerald-400\">\n {str}\n </span>,\n );\n } else if (num) {\n out.push(\n <span key={key++} className=\"pz:text-amber-700 pz:dark:text-amber-400\">\n {num}\n </span>,\n );\n } else if (bool) {\n out.push(\n <span key={key++} className=\"pz:text-rose-700 pz:dark:text-rose-400\">\n {bool}\n </span>,\n );\n } else if (nul) {\n out.push(\n <span key={key++} className=\"pz:text-muted-foreground pz:italic\">\n {nul}\n </span>,\n );\n } else {\n out.push(whole);\n }\n lastIndex = match.index + whole.length;\n }\n if (lastIndex < json.length) {\n out.push(json.slice(lastIndex));\n }\n return out;\n }, [json]);\n\n return (\n <pre className=\"pz:m-0 pz:font-sans pz:whitespace-pre pz:tabular-nums pz:text-xs pz:leading-5 pz:text-foreground\">\n {tokens}\n </pre>\n );\n}\n\nfunction PreviewStatusPill({\n type,\n state,\n}: {\n type: PreviewType | null;\n state: \"resolved\" | \"loading\" | \"error\";\n}) {\n const dotClass = {\n resolved: \"pz:bg-emerald-500\",\n loading: \"pz:bg-amber-500 pz:animate-pulse\",\n error: \"pz:bg-destructive\",\n }[state];\n const label = state === \"error\" ? \"Error\" : state === \"loading\" ? \"Resolving\" : \"Resolved\";\n return (\n <span className=\"pz:inline-flex pz:items-center pz:gap-1.5 pz:text-xs pz:text-muted-foreground pz:font-normal\">\n <span className={cn(\"pz:size-1.5 pz:rounded-full pz:shrink-0\", dotClass)} />\n {label}\n {state !== \"error\" && type && (\n <>\n <span className=\"pz:text-muted-foreground/60\">·</span>\n <span>{type}</span>\n </>\n )}\n </span>\n );\n}\n\nfunction PreviewTab({\n active,\n onClick,\n children,\n}: {\n active: boolean;\n onClick: () => void;\n children: ReactNode;\n}) {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n className={cn(\n \"pz:relative pz:px-0.5 pz:py-2 pz:text-xs pz:transition-colors pz:outline-none pz:focus-visible:text-foreground\",\n active\n ? \"pz:font-medium pz:text-foreground\"\n : \"pz:font-normal pz:text-muted-foreground pz:hover:text-foreground\",\n )}\n >\n {children}\n {active && (\n <span className=\"pz:absolute pz:inset-x-0 pz:-bottom-px pz:h-0.5 pz:bg-foreground pz:rounded-full\" />\n )}\n </button>\n );\n}\n\nfunction ExtractionPreview({\n exampleValue,\n extraction,\n}: {\n extraction: JSONExtraction[\"extractions\"][number];\n exampleValue: unknown;\n}) {\n const [tab, setTab] = useState<\"extracted\" | \"full\">(\"extracted\");\n const { preview, error, isLoading } = useJsonataPreview(extraction.path, exampleValue);\n\n const state: \"resolved\" | \"loading\" | \"error\" = error\n ? \"error\"\n : isLoading\n ? \"loading\"\n : \"resolved\";\n const previewType = useMemo(() => inferPreviewType(preview), [preview]);\n const valueToShow = tab === \"extracted\" ? preview : exampleValue;\n\n const tintClass =\n state === \"error\"\n ? \"pz:bg-rose-50/60 pz:dark:bg-rose-950/20\"\n : \"pz:bg-emerald-50/50 pz:dark:bg-emerald-950/15\";\n\n return (\n <div className=\"pz:flex pz:min-w-0 pz:flex-col pz:overflow-hidden pz:rounded-md pz:border pz:border-input\">\n <div className=\"pz:flex pz:items-center pz:justify-between pz:gap-2 pz:px-3 pz:bg-background pz:border-b pz:border-input\">\n <div className=\"pz:flex pz:items-center pz:gap-3\">\n <PreviewTab active={tab === \"extracted\"} onClick={() => setTab(\"extracted\")}>\n Extracted\n </PreviewTab>\n <PreviewTab active={tab === \"full\"} onClick={() => setTab(\"full\")}>\n Full response\n </PreviewTab>\n </div>\n <div className=\"pz:flex pz:items-center pz:gap-2 pz:py-1\">\n <PreviewStatusPill\n type={tab === \"extracted\" ? previewType : inferPreviewType(exampleValue)}\n state={tab === \"extracted\" ? state : \"resolved\"}\n />\n <span\n className={cn(\n \"pz:text-muted-foreground/60 pz:transition-opacity\",\n isLoading && \"pz:animate-spin pz:text-muted-foreground\",\n )}\n aria-hidden\n >\n <IconRefresh width={12} height={12} />\n </span>\n </div>\n </div>\n <div\n className={cn(\n \"pz:max-h-44 pz:max-w-full pz:overflow-auto pz:p-3 pz:relative\",\n tab === \"extracted\" ? tintClass : \"pz:bg-muted/20\",\n )}\n >\n {tab === \"extracted\" && error ? (\n <pre className=\"pz:m-0 pz:font-sans pz:whitespace-pre-wrap pz:break-words pz:text-xs pz:leading-5 pz:text-destructive\">\n {error}\n </pre>\n ) : (\n <JsonHighlight value={valueToShow} />\n )}\n </div>\n </div>\n );\n}\n\nfunction FieldRow({\n label,\n hint,\n error,\n children,\n}: {\n label: string;\n hint?: ReactNode;\n error?: string | null;\n children: ReactNode;\n}) {\n return (\n <div className=\"pz:flex pz:flex-col pz:gap-1.5\">\n <Label className=\"pz:inline-flex pz:items-center pz:gap-1 pz:text-xs pz:font-medium pz:text-muted-foreground\">\n {label}\n {hint && <HoverInfo>{hint}</HoverInfo>}\n </Label>\n {children}\n {error && (\n <span className=\"pz:text-destructive pz:text-xs pz:font-medium\" role=\"alert\">\n {error}\n </span>\n )}\n </div>\n );\n}\n\nfunction ExtractionCard({\n extraction,\n idx,\n option,\n form,\n basePath,\n onUpdate,\n onRemove,\n}: {\n extraction: JSONExtraction[\"extractions\"][number];\n idx: number;\n option: JSONExtractionMeta[\"fields\"][number];\n form: FormHandle;\n basePath: string;\n onUpdate: (idx: number, ext: JSONExtraction[\"extractions\"][number]) => void;\n onRemove: (idx: number) => void;\n}) {\n const [open, setOpen] = useState(true);\n const [showPreview, setShowPreview] = useState(false);\n const extractionPath = `${basePath}.extractions.${idx}`;\n const pathError = useFieldError(form, `${extractionPath}.path`);\n const nameError = useFieldError(form, `${extractionPath}.output_field.name`);\n\n const availableFormats = useMemo(\n () => TYPES_TO_FORMATS[extraction.output_field.type as keyof typeof TYPES_TO_FORMATS] ?? [],\n [extraction.output_field.type],\n );\n\n const updatePath = (value: string) => {\n onUpdate(idx, { ...extraction, path: value });\n };\n\n const updateOutputField = (\n property: \"type\" | \"format\" | \"name\" | \"label\" | \"description\",\n value: string | null,\n ) => {\n if (value === null) return;\n\n const newOutputField = { ...extraction.output_field, [property]: value };\n if (property === \"type\") {\n const newFormats = TYPES_TO_FORMATS[value as keyof typeof TYPES_TO_FORMATS] ?? [];\n if (newFormats.length === 0 || !newFormats.includes(newOutputField.format as never)) {\n newOutputField.format = null;\n }\n }\n onUpdate(idx, { ...extraction, output_field: newOutputField });\n };\n\n const canPreview = option.exampleValue != null;\n\n return (\n <div className=\"pz:flex pz:min-w-0 pz:flex-col pz:overflow-hidden pz:rounded-lg pz:border pz:border-input pz:bg-background\">\n <div className=\"pz:flex pz:items-center pz:justify-between pz:gap-2 pz:px-3 pz:py-1.5\">\n <button\n type=\"button\"\n onClick={() => setOpen((v) => !v)}\n className=\"pz:inline-flex pz:items-center pz:gap-1.5 pz:rounded-sm pz:py-1 pz:pr-1.5 pz:text-sm pz:font-medium pz:text-foreground pz:outline-none pz:focus-visible:ring-3 pz:focus-visible:ring-ring/50\"\n >\n <IconChevronDown\n width={14}\n height={14}\n className=\"pz:text-muted-foreground pz:transition-transform\"\n style={{ transform: open ? \"rotate(0deg)\" : \"rotate(-90deg)\" }}\n />\n Extraction {idx + 1}\n </button>\n <div className=\"pz:flex pz:items-center pz:gap-0.5\">\n {canPreview ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"xs\"\n onClick={() => {\n if (!open) setOpen(true);\n setShowPreview((v) => !v);\n }}\n className=\"pz:text-muted-foreground pz:hover:text-foreground pz:font-normal\"\n >\n {showPreview ? <IconEyeOff /> : <IconEye />}\n {showPreview ? \"Hide preview\" : \"Preview\"}\n </Button>\n ) : (\n <span className=\"pz:text-xs pz:text-muted-foreground pz:px-1.5\">No preview</span>\n )}\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-xs\"\n onClick={() => onRemove(idx)}\n title=\"Remove extraction\"\n className=\"pz:text-muted-foreground pz:hover:text-destructive pz:hover:bg-destructive/10\"\n >\n <IconTrash />\n </Button>\n </div>\n </div>\n\n {open && (\n <div className=\"pz:flex pz:min-w-0 pz:flex-col pz:gap-3 pz:px-3 pz:pt-1 pz:pb-3\">\n {showPreview && canPreview && (\n <ExtractionPreview exampleValue={option.exampleValue} extraction={extraction} />\n )}\n\n <FieldRow label=\"Output field label\" hint=\"The display name for this field.\">\n <Input\n value={extraction.output_field.label ?? \"\"}\n onChange={(e) => updateOutputField(\"label\", e.target.value)}\n placeholder=\"e.g. Full name\"\n />\n </FieldRow>\n\n <FieldRow\n label=\"Path\"\n hint=\"JSONata expression. Use dot or bracket notation to reach nested values.\"\n error={pathError}\n >\n <Input\n value={extraction.path}\n onChange={(e) => updatePath(e.target.value)}\n placeholder=\"e.g. emails[0].value\"\n aria-invalid={!!pathError}\n />\n </FieldRow>\n\n <div className=\"pz:grid pz:grid-cols-2 pz:gap-2\">\n <FieldRow label=\"Output type\">\n <Select\n value={extraction.output_field.type}\n onValueChange={(v) => updateOutputField(\"type\", v as string)}\n >\n <SelectTrigger className=\"pz:w-full\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {RECORD_FIELD_TYPES.map((type) => (\n <SelectItem key={type} value={type}>\n {type}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </FieldRow>\n <FieldRow label=\"Format\">\n <Select\n value={extraction.output_field.format || \"\"}\n onValueChange={(v) => updateOutputField(\"format\", v)}\n disabled={availableFormats.length === 0}\n >\n <SelectTrigger className=\"pz:w-full\">\n <SelectValue\n placeholder={availableFormats.length === 0 ? \"—\" : \"Select format\"}\n />\n </SelectTrigger>\n <SelectContent>\n {availableFormats.map((format) => (\n <SelectItem key={format} value={format}>\n {format}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </FieldRow>\n </div>\n\n <FieldRow\n label=\"Output field name\"\n hint=\"The internal identifier for this field. Must be unique.\"\n error={nameError}\n >\n <Input\n value={extraction.output_field.name}\n onChange={(e) => updateOutputField(\"name\", e.target.value)}\n placeholder=\"extract_full_name\"\n aria-invalid={!!nameError}\n />\n </FieldRow>\n </div>\n )}\n </div>\n );\n}\n\nexport function JsonExtractionInputAdapter(field: FieldHandle<\"json_extraction_input\">) {\n const meta = field.meta as JSONExtractionMeta;\n const value = (field.value ?? {\n field_name: \"\",\n extractions: [],\n }) as JSONExtraction;\n\n const addExtraction = (fieldName?: string) => {\n const inputFieldName = fieldName || value.field_name;\n const isInitial = value.extractions.length === 0;\n const newValue: JSONExtraction = {\n field_name: inputFieldName,\n extractions: [\n ...value.extractions,\n {\n path: \"\",\n output_field: {\n name: `extract_${inputFieldName}_${generateRandomString(4)}`,\n format: null,\n label: \"Extract JSON\",\n type: \"string\",\n },\n },\n ],\n };\n if (isInitial) {\n // First selection just scaffolds an empty extraction skeleton — the\n // user hasn't entered real data yet, so don't mark the field as\n // dirty/touched or trigger validation.\n field.form.setValue(field.path, newValue, {\n shouldDirty: false,\n shouldTouch: false,\n shouldValidate: false,\n });\n } else {\n field.setValue(newValue);\n }\n };\n\n // const removeAllExtractions = () => {\n // // Returns the field to a pristine baseline: clears value, dirty, touched,\n // // and errors in one call.\n // field.form.resetField(field.path, {\n // defaultValue: { field_name: \"\", extractions: [] },\n // });\n // };\n\n const updateExtraction = (idx: number, ext: JSONExtraction[\"extractions\"][number]) => {\n const newExtractions = [...value.extractions];\n newExtractions[idx] = ext;\n field.setValue({ ...value, extractions: newExtractions });\n };\n\n const removeExtraction = (idx: number) => {\n const newExtractions = [...value.extractions];\n newExtractions.splice(idx, 1);\n if (newExtractions.length === 0) {\n field.setValue({ field_name: \"\", extractions: [] });\n } else {\n field.setValue({ ...value, extractions: newExtractions });\n }\n };\n\n const option = useMemo(\n () => meta.fields.find((e) => e.fieldName === value.field_name),\n [value.field_name, meta.fields],\n );\n\n if (value.field_name && value.extractions.length > 0 && option) {\n return (\n <div data-p0=\"input\" className=\"pz:flex pz:min-w-0 pz:flex-col pz:gap-2\">\n <div className=\"pz:flex pz:min-w-0 pz:items-center pz:gap-1.5 pz:text-xs pz:text-muted-foreground\">\n <span>Extracting from</span>\n <span className=\"pz:truncate pz:font-medium pz:text-foreground\">\n {option.fieldLabel || option.fieldName}\n </span>\n </div>\n {value.extractions.map((extraction, idx) => (\n <ExtractionCard\n // biome-ignore lint/suspicious/noArrayIndexKey: index is stable\n key={idx}\n extraction={extraction}\n idx={idx}\n option={option}\n form={field.form}\n basePath={field.path}\n onUpdate={updateExtraction}\n onRemove={removeExtraction}\n />\n ))}\n <div className=\"pz:flex pz:items-center pz:justify-between pz:pt-0.5\">\n <Button\n type=\"button\"\n variant=\"link\"\n size=\"xs\"\n onClick={() => addExtraction()}\n className=\"pz:px-0\"\n >\n <IconPlus />\n Add extraction\n </Button>\n </div>\n </div>\n );\n }\n\n if (meta.fields.length > 0) {\n return (\n <div data-p0=\"input\" className=\"pz:flex pz:flex-col pz:gap-2\">\n <Select\n value=\"\"\n onValueChange={(v) => {\n if (v) addExtraction(v);\n }}\n >\n <SelectTrigger className=\"pz:w-full\">\n <SelectValue placeholder=\"Select a JSON field to extract from\" />\n </SelectTrigger>\n <SelectContent>\n {meta.fields.map((f) => (\n <SelectItem key={f.fieldName} value={f.fieldName}>\n {f.fieldLabel} - {f.fieldName}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n );\n }\n\n return (\n <div data-p0=\"input\" className=\"pz:flex pz:items-center pz:gap-1.5 pz:rounded-md pz:px-1\">\n <div className=\"pz:text-xs pz:font-normal\">No JSON field available</div>\n <HoverInfo>\n A JSON field is required for this pipe. Add a json field to your pipeline.\n </HoverInfo>\n </div>\n );\n}\n"],"mappings":"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"}
|
package/dist/components/defaults/adapters/{pipes-trigger-input.mjs → pipes-run-if-input.mjs}
RENAMED
|
@@ -9,9 +9,9 @@ import { useFieldError } from "../../../hooks/use-field-error.mjs";
|
|
|
9
9
|
import { FieldSectionEnumeration } from "../field-section-enumeration.mjs";
|
|
10
10
|
import { useCallback, useMemo } from "react";
|
|
11
11
|
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
12
|
-
import {
|
|
12
|
+
import { RUN_IF_OPERATOR_LABELS, RUN_IF_STATUS_OPERATORS, RUN_IF_VALUE_OPERATORS } from "@pipe0/base";
|
|
13
13
|
|
|
14
|
-
//#region src/components/defaults/adapters/pipes-
|
|
14
|
+
//#region src/components/defaults/adapters/pipes-run-if-input.tsx
|
|
15
15
|
const OPERATORS_BY_TYPE = {
|
|
16
16
|
string: [
|
|
17
17
|
"eq",
|
|
@@ -47,14 +47,14 @@ function ConditionRow({ condition, index, eligibleFields, fieldsByName, isFirst,
|
|
|
47
47
|
const hasEligibleFields = eligibleFields.length > 0;
|
|
48
48
|
const selectedField = condition.field_name ? fieldsByName.get(condition.field_name) : void 0;
|
|
49
49
|
const availableOperators = useMemo(() => {
|
|
50
|
-
if (condition.property === "status") return
|
|
50
|
+
if (condition.property === "status") return RUN_IF_STATUS_OPERATORS.map((op) => ({
|
|
51
51
|
value: op,
|
|
52
|
-
label:
|
|
52
|
+
label: RUN_IF_OPERATOR_LABELS[op]
|
|
53
53
|
}));
|
|
54
54
|
if (!selectedField?.type) return [];
|
|
55
|
-
return
|
|
55
|
+
return RUN_IF_VALUE_OPERATORS.map((op) => ({
|
|
56
56
|
value: op,
|
|
57
|
-
label:
|
|
57
|
+
label: RUN_IF_OPERATOR_LABELS[op]
|
|
58
58
|
})).filter((op) => OPERATORS_BY_TYPE[selectedField.type].includes(op.value));
|
|
59
59
|
}, [condition.property, selectedField]);
|
|
60
60
|
const renderValueInput = () => {
|
|
@@ -282,12 +282,12 @@ function ConditionRow({ condition, index, eligibleFields, fieldsByName, isFirst,
|
|
|
282
282
|
})
|
|
283
283
|
})] });
|
|
284
284
|
}
|
|
285
|
-
function
|
|
286
|
-
const
|
|
285
|
+
function PipesRunIfInputAdapter(field) {
|
|
286
|
+
const pipeRunIf = field.value;
|
|
287
287
|
const meta = field.meta;
|
|
288
288
|
const eligibleFields = useMemo(() => meta.fields.filter((f) => OPERATORS_BY_TYPE[f.type].length > 0), [meta.fields]);
|
|
289
289
|
const fieldsByName = useMemo(() => new Map(meta.fields.map((f) => [f.fieldName, f])), [meta.fields]);
|
|
290
|
-
const
|
|
290
|
+
const addRunIf = useCallback(() => {
|
|
291
291
|
field.setValue({
|
|
292
292
|
action: "run",
|
|
293
293
|
when: {
|
|
@@ -297,74 +297,74 @@ function PipesTriggerInputAdapter(field) {
|
|
|
297
297
|
});
|
|
298
298
|
}, [field]);
|
|
299
299
|
const updateCondition = (index, condition) => {
|
|
300
|
-
if (!
|
|
301
|
-
const newConditions = [...
|
|
300
|
+
if (!pipeRunIf) return;
|
|
301
|
+
const newConditions = [...pipeRunIf.when.conditions];
|
|
302
302
|
newConditions[index] = condition;
|
|
303
303
|
field.setValue({
|
|
304
|
-
...
|
|
304
|
+
...pipeRunIf,
|
|
305
305
|
when: {
|
|
306
|
-
...
|
|
306
|
+
...pipeRunIf.when,
|
|
307
307
|
conditions: newConditions
|
|
308
308
|
}
|
|
309
309
|
});
|
|
310
310
|
};
|
|
311
311
|
const removeCondition = (index) => {
|
|
312
|
-
if (!
|
|
313
|
-
if (
|
|
312
|
+
if (!pipeRunIf) return;
|
|
313
|
+
if (pipeRunIf.when.conditions.length <= 1) {
|
|
314
314
|
field.setValue(null);
|
|
315
315
|
return;
|
|
316
316
|
}
|
|
317
|
-
const newConditions =
|
|
317
|
+
const newConditions = pipeRunIf.when.conditions.filter((_, i) => i !== index);
|
|
318
318
|
field.setValue({
|
|
319
|
-
...
|
|
319
|
+
...pipeRunIf,
|
|
320
320
|
when: {
|
|
321
|
-
...
|
|
321
|
+
...pipeRunIf.when,
|
|
322
322
|
conditions: newConditions
|
|
323
323
|
}
|
|
324
324
|
});
|
|
325
325
|
};
|
|
326
326
|
const addCondition = () => {
|
|
327
|
-
if (!
|
|
327
|
+
if (!pipeRunIf) return;
|
|
328
328
|
field.setValue({
|
|
329
|
-
...
|
|
329
|
+
...pipeRunIf,
|
|
330
330
|
when: {
|
|
331
|
-
...
|
|
332
|
-
conditions: [...
|
|
331
|
+
...pipeRunIf.when,
|
|
332
|
+
conditions: [...pipeRunIf.when.conditions, { ...EMPTY_CONDITION }]
|
|
333
333
|
}
|
|
334
334
|
});
|
|
335
335
|
};
|
|
336
336
|
const changeLogic = (logic) => {
|
|
337
|
-
if (!
|
|
337
|
+
if (!pipeRunIf) return;
|
|
338
338
|
field.setValue({
|
|
339
|
-
...
|
|
339
|
+
...pipeRunIf,
|
|
340
340
|
when: {
|
|
341
|
-
...
|
|
341
|
+
...pipeRunIf.when,
|
|
342
342
|
logic
|
|
343
343
|
}
|
|
344
344
|
});
|
|
345
345
|
};
|
|
346
346
|
return /* @__PURE__ */ jsx("div", {
|
|
347
347
|
"data-p0": "input",
|
|
348
|
-
children: !
|
|
348
|
+
children: !pipeRunIf ? /* @__PURE__ */ jsx("div", {
|
|
349
349
|
className: "pz:flex pz:items-center",
|
|
350
350
|
children: /* @__PURE__ */ jsxs(Button, {
|
|
351
351
|
type: "button",
|
|
352
352
|
variant: "link",
|
|
353
353
|
size: "xs",
|
|
354
354
|
className: "pz:px-0",
|
|
355
|
-
onClick:
|
|
355
|
+
onClick: addRunIf,
|
|
356
356
|
children: [/* @__PURE__ */ jsx(IconPlus, {}), "New rule"]
|
|
357
357
|
})
|
|
358
358
|
}) : /* @__PURE__ */ jsx("div", {
|
|
359
359
|
className: "pz:flex pz:flex-col pz:gap-8",
|
|
360
|
-
children:
|
|
360
|
+
children: pipeRunIf.when.conditions.map((condition, idx) => /* @__PURE__ */ jsx(ConditionRow, {
|
|
361
361
|
condition,
|
|
362
362
|
index: idx,
|
|
363
363
|
eligibleFields,
|
|
364
364
|
fieldsByName,
|
|
365
365
|
isFirst: idx === 0,
|
|
366
|
-
isLast: idx ===
|
|
367
|
-
logic:
|
|
366
|
+
isLast: idx === pipeRunIf.when.conditions.length - 1,
|
|
367
|
+
logic: pipeRunIf.when.logic,
|
|
368
368
|
form: field.form,
|
|
369
369
|
basePath: field.path,
|
|
370
370
|
onUpdate: updateCondition,
|
|
@@ -377,5 +377,5 @@ function PipesTriggerInputAdapter(field) {
|
|
|
377
377
|
}
|
|
378
378
|
|
|
379
379
|
//#endregion
|
|
380
|
-
export {
|
|
381
|
-
//# sourceMappingURL=pipes-
|
|
380
|
+
export { PipesRunIfInputAdapter };
|
|
381
|
+
//# sourceMappingURL=pipes-run-if-input.mjs.map
|
|
@@ -0,0 +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 '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,20 +1,228 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { cn } from "../../../lib/utils.mjs";
|
|
2
|
+
import { IconGripVertical, IconPlus } from "../../internal/icons.mjs";
|
|
3
|
+
import { WidgetStrip } from "../../../widgets/widget-strip.mjs";
|
|
4
|
+
import { Popover, PopoverContent, PopoverTrigger } from "../../ui/popover.mjs";
|
|
5
|
+
import { useMemo, useState } from "react";
|
|
6
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
+
import { Search, X } from "lucide-react";
|
|
8
|
+
import { DndContext, KeyboardSensor, PointerSensor, closestCenter, useSensor, useSensors } from "@dnd-kit/core";
|
|
9
|
+
import { SortableContext, useSortable, verticalListSortingStrategy } from "@dnd-kit/sortable";
|
|
3
10
|
|
|
4
11
|
//#region src/components/defaults/adapters/providers-input.tsx
|
|
12
|
+
function splitWidgets(widgets) {
|
|
13
|
+
if (!widgets) return {
|
|
14
|
+
leading: void 0,
|
|
15
|
+
pricing: void 0
|
|
16
|
+
};
|
|
17
|
+
const { pricing, ...rest } = widgets;
|
|
18
|
+
return {
|
|
19
|
+
leading: Object.values(rest).some((v) => v != null) ? rest : void 0,
|
|
20
|
+
pricing
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Provider waterfall — vertical, ordered list of providers tried sequentially
|
|
25
|
+
* until a valid result is returned. The list makes the running order legible
|
|
26
|
+
* (numeric badge per row, drag-to-reorder), and the credit widget per
|
|
27
|
+
* provider stays visible.
|
|
28
|
+
*/
|
|
5
29
|
function ProvidersInputAdapter(field) {
|
|
6
|
-
|
|
30
|
+
const selected = useMemo(() => (field.value ?? []).map((p) => p.provider), [field.value]);
|
|
31
|
+
const options = field.options ?? [];
|
|
32
|
+
const optionByValue = useMemo(() => {
|
|
33
|
+
const map = /* @__PURE__ */ new Map();
|
|
34
|
+
for (const o of options) map.set(o.value, o);
|
|
35
|
+
return map;
|
|
36
|
+
}, [options]);
|
|
37
|
+
const maxItems = field.meta.maxItems;
|
|
38
|
+
const atMax = maxItems !== void 0 && selected.length >= maxItems;
|
|
39
|
+
const setValue = (next) => field.setValue(next.map((provider) => ({ provider })));
|
|
40
|
+
const handleRemove = (value) => setValue(selected.filter((v) => v !== value));
|
|
41
|
+
const handleAdd = (value) => {
|
|
42
|
+
if (selected.includes(value)) return;
|
|
43
|
+
setValue([...selected, value]);
|
|
44
|
+
};
|
|
45
|
+
const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 4 } }), useSensor(KeyboardSensor));
|
|
46
|
+
const handleDragEnd = (event) => {
|
|
47
|
+
const { active, over } = event;
|
|
48
|
+
if (!over || active.id === over.id) return;
|
|
49
|
+
const from = selected.indexOf(String(active.id));
|
|
50
|
+
const to = selected.indexOf(String(over.id));
|
|
51
|
+
if (from === -1 || to === -1) return;
|
|
52
|
+
const next = [...selected];
|
|
53
|
+
const [moved] = next.splice(from, 1);
|
|
54
|
+
next.splice(to, 0, moved);
|
|
55
|
+
setValue(next);
|
|
56
|
+
};
|
|
57
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
7
58
|
"data-p0": "input",
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
59
|
+
className: "pz:flex pz:flex-col pz:gap-1",
|
|
60
|
+
children: [selected.length > 0 && /* @__PURE__ */ jsx(DndContext, {
|
|
61
|
+
sensors,
|
|
62
|
+
collisionDetection: closestCenter,
|
|
63
|
+
onDragEnd: handleDragEnd,
|
|
64
|
+
children: /* @__PURE__ */ jsx(SortableContext, {
|
|
65
|
+
items: selected,
|
|
66
|
+
strategy: verticalListSortingStrategy,
|
|
67
|
+
children: /* @__PURE__ */ jsx("ul", {
|
|
68
|
+
className: "pz:flex pz:flex-col pz:gap-0.5 pz:list-none pz:m-0 pz:p-0",
|
|
69
|
+
children: selected.map((value, index) => {
|
|
70
|
+
const option = optionByValue.get(value);
|
|
71
|
+
return /* @__PURE__ */ jsx(ProviderRow, {
|
|
72
|
+
value,
|
|
73
|
+
index,
|
|
74
|
+
label: option?.label ?? value,
|
|
75
|
+
widgets: option?.widgets,
|
|
76
|
+
onRemove: () => handleRemove(value)
|
|
77
|
+
}, value);
|
|
78
|
+
})
|
|
79
|
+
})
|
|
80
|
+
})
|
|
81
|
+
}), !atMax && /* @__PURE__ */ jsx(AddProviderControl, {
|
|
82
|
+
options,
|
|
83
|
+
excluded: selected,
|
|
84
|
+
onAdd: handleAdd,
|
|
85
|
+
ariaInvalid: !!field.error
|
|
86
|
+
})]
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
function ProviderRow({ value, index, label, widgets, onRemove }) {
|
|
90
|
+
const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ id: value });
|
|
91
|
+
const style = {
|
|
92
|
+
transform: transform ? `translate3d(${Math.round(transform.x)}px, ${Math.round(transform.y)}px, 0)` : void 0,
|
|
93
|
+
transition,
|
|
94
|
+
opacity: isDragging ? .6 : 1
|
|
95
|
+
};
|
|
96
|
+
const { leading, pricing } = splitWidgets(widgets);
|
|
97
|
+
const orderLabel = String(index + 1).padStart(2, "0");
|
|
98
|
+
return /* @__PURE__ */ jsxs("li", {
|
|
99
|
+
ref: setNodeRef,
|
|
100
|
+
style,
|
|
101
|
+
className: cn("pz:group/prov pz:flex pz:items-center pz:gap-2.5 pz:rounded-md pz:px-1.5 pz:py-1.5", "pz:hover:bg-muted/60 pz:transition-colors"),
|
|
102
|
+
...attributes,
|
|
103
|
+
children: [
|
|
104
|
+
/* @__PURE__ */ jsx("button", {
|
|
105
|
+
type: "button",
|
|
106
|
+
"aria-label": "Drag to reorder",
|
|
107
|
+
className: cn("pz:flex pz:items-center pz:justify-center pz:size-4 pz:cursor-grab pz:touch-none", "pz:text-muted-foreground/60 pz:hover:text-foreground pz:transition-colors"),
|
|
108
|
+
...listeners,
|
|
109
|
+
children: /* @__PURE__ */ jsx(IconGripVertical, {
|
|
110
|
+
width: 11,
|
|
111
|
+
height: 14
|
|
112
|
+
})
|
|
113
|
+
}),
|
|
114
|
+
leading && /* @__PURE__ */ jsx("span", {
|
|
115
|
+
className: "pz:flex pz:items-center pz:shrink-0",
|
|
116
|
+
children: /* @__PURE__ */ jsx(WidgetStrip, {
|
|
117
|
+
widgets: leading,
|
|
118
|
+
size: 18
|
|
119
|
+
})
|
|
120
|
+
}),
|
|
121
|
+
/* @__PURE__ */ jsx("span", {
|
|
122
|
+
className: "pz:text-sm pz:font-medium pz:text-foreground pz:flex-1 pz:truncate",
|
|
123
|
+
children: label
|
|
124
|
+
}),
|
|
125
|
+
pricing && /* @__PURE__ */ jsxs("span", {
|
|
126
|
+
className: "pz:text-xs pz:text-muted-foreground pz:tabular-nums",
|
|
127
|
+
children: [pricing.credits, " cr"]
|
|
128
|
+
}),
|
|
129
|
+
/* @__PURE__ */ jsx("span", {
|
|
130
|
+
"aria-hidden": true,
|
|
131
|
+
className: cn("pz:inline-flex pz:items-center pz:justify-center pz:min-w-7 pz:h-5 pz:px-1.5", "pz:rounded-full pz:bg-muted pz:text-muted-foreground pz:text-[10.5px]", "pz:font-medium pz:tabular-nums"),
|
|
132
|
+
children: orderLabel
|
|
133
|
+
}),
|
|
134
|
+
/* @__PURE__ */ jsx("button", {
|
|
135
|
+
type: "button",
|
|
136
|
+
"aria-label": `Remove ${label}`,
|
|
137
|
+
onClick: (e) => {
|
|
138
|
+
e.stopPropagation();
|
|
139
|
+
onRemove();
|
|
140
|
+
},
|
|
141
|
+
className: cn("pz:flex pz:items-center pz:justify-center pz:size-5 pz:rounded", "pz:text-muted-foreground/70", "pz:hover:bg-destructive/10 pz:hover:text-destructive pz:transition-colors"),
|
|
142
|
+
children: /* @__PURE__ */ jsx(X, { className: "pz:size-3" })
|
|
143
|
+
})
|
|
144
|
+
]
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
function AddProviderControl({ options, excluded, onAdd, ariaInvalid }) {
|
|
148
|
+
const [open, setOpen] = useState(false);
|
|
149
|
+
const [query, setQuery] = useState("");
|
|
150
|
+
const excludedSet = useMemo(() => new Set(excluded), [excluded]);
|
|
151
|
+
const available = useMemo(() => options.filter((o) => !excludedSet.has(o.value)), [options, excludedSet]);
|
|
152
|
+
const filtered = useMemo(() => {
|
|
153
|
+
const q = query.trim().toLowerCase();
|
|
154
|
+
if (!q) return available;
|
|
155
|
+
return available.filter((o) => o.label.toLowerCase().includes(q) || o.value.toLowerCase().includes(q));
|
|
156
|
+
}, [available, query]);
|
|
157
|
+
if (available.length === 0 && excluded.length === 0) return /* @__PURE__ */ jsx("div", {
|
|
158
|
+
className: "pz:text-xs pz:text-muted-foreground pz:px-1.5 pz:py-2",
|
|
159
|
+
children: "No providers available"
|
|
160
|
+
});
|
|
161
|
+
if (available.length === 0) return null;
|
|
162
|
+
return /* @__PURE__ */ jsxs(Popover, {
|
|
163
|
+
open,
|
|
164
|
+
onOpenChange: (next) => {
|
|
165
|
+
setOpen(next);
|
|
166
|
+
if (!next) setQuery("");
|
|
167
|
+
},
|
|
168
|
+
children: [/* @__PURE__ */ jsxs(PopoverTrigger, {
|
|
169
|
+
"aria-invalid": ariaInvalid || void 0,
|
|
170
|
+
className: cn("pz:flex pz:items-center pz:justify-center pz:gap-1.5 pz:w-full", "pz:px-2.5 pz:py-1.5 pz:mt-1 pz:rounded-md", "pz:border pz:border-dashed pz:border-input pz:bg-transparent", "pz:text-xs pz:text-muted-foreground", "pz:hover:bg-muted/60 pz:hover:text-foreground pz:hover:border-muted-foreground/40", "pz:transition-colors pz:cursor-pointer"),
|
|
171
|
+
children: [/* @__PURE__ */ jsx(IconPlus, {
|
|
172
|
+
width: 12,
|
|
173
|
+
height: 12
|
|
174
|
+
}), "Add provider"]
|
|
175
|
+
}), /* @__PURE__ */ jsxs(PopoverContent, {
|
|
176
|
+
align: "start",
|
|
177
|
+
className: "pz:w-(--anchor-width) pz:p-0 pz:gap-0",
|
|
178
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
179
|
+
className: "pz:flex pz:items-center pz:gap-1.5 pz:px-2.5 pz:py-2 pz:border-b pz:border-border",
|
|
180
|
+
children: [/* @__PURE__ */ jsx(Search, { className: "pz:size-3.5 pz:text-muted-foreground pz:shrink-0" }), /* @__PURE__ */ jsx("input", {
|
|
181
|
+
value: query,
|
|
182
|
+
onChange: (e) => setQuery(e.target.value),
|
|
183
|
+
placeholder: "Search providers…",
|
|
184
|
+
autoFocus: true,
|
|
185
|
+
className: "pz:flex-1 pz:bg-transparent pz:outline-none pz:text-sm pz:placeholder:text-muted-foreground/70"
|
|
186
|
+
})]
|
|
187
|
+
}), /* @__PURE__ */ jsxs("ul", {
|
|
188
|
+
className: "pz:flex pz:flex-col pz:p-1 pz:max-h-72 pz:overflow-auto pz:list-none pz:m-0",
|
|
189
|
+
children: [filtered.length === 0 && /* @__PURE__ */ jsx("li", {
|
|
190
|
+
className: "pz:px-2 pz:py-3 pz:text-center pz:text-xs pz:text-muted-foreground",
|
|
191
|
+
children: "No providers"
|
|
192
|
+
}), filtered.map((option) => {
|
|
193
|
+
const { leading, pricing } = splitWidgets(option.widgets);
|
|
194
|
+
return /* @__PURE__ */ jsx("li", {
|
|
195
|
+
className: "pz:contents",
|
|
196
|
+
children: /* @__PURE__ */ jsxs("button", {
|
|
197
|
+
type: "button",
|
|
198
|
+
onClick: () => {
|
|
199
|
+
onAdd(option.value);
|
|
200
|
+
setOpen(false);
|
|
201
|
+
setQuery("");
|
|
202
|
+
},
|
|
203
|
+
className: cn("pz:flex pz:items-center pz:gap-2 pz:w-full pz:text-left", "pz:px-2 pz:py-1.5 pz:rounded-md pz:text-sm", "pz:hover:bg-accent pz:hover:text-accent-foreground", "pz:transition-colors pz:cursor-pointer"),
|
|
204
|
+
children: [
|
|
205
|
+
leading && /* @__PURE__ */ jsx("span", {
|
|
206
|
+
className: "pz:flex pz:items-center pz:shrink-0",
|
|
207
|
+
children: /* @__PURE__ */ jsx(WidgetStrip, {
|
|
208
|
+
widgets: leading,
|
|
209
|
+
size: 16
|
|
210
|
+
})
|
|
211
|
+
}),
|
|
212
|
+
/* @__PURE__ */ jsx("span", {
|
|
213
|
+
className: "pz:flex-1 pz:truncate",
|
|
214
|
+
children: option.label
|
|
215
|
+
}),
|
|
216
|
+
pricing && /* @__PURE__ */ jsxs("span", {
|
|
217
|
+
className: "pz:text-xs pz:text-muted-foreground pz:tabular-nums",
|
|
218
|
+
children: [pricing.credits, " cr"]
|
|
219
|
+
})
|
|
220
|
+
]
|
|
221
|
+
})
|
|
222
|
+
}, option.value);
|
|
223
|
+
})]
|
|
224
|
+
})]
|
|
225
|
+
})]
|
|
18
226
|
});
|
|
19
227
|
}
|
|
20
228
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"providers-input.mjs","names":[],"sources":["../../../../src/components/defaults/adapters/providers-input.tsx"],"sourcesContent":["import type { FieldHandle } from \"../../../types/field-handle.js\";\nimport { SuggestCombobox } from \"../../internal/combobox/suggest-combobox.js\";\n\nexport function ProvidersInputAdapter(field: FieldHandle<\"providers_input\">) {\n const selected = (field.value ?? []).map((p: { provider: string }) => p.provider);\n\n return (\n <div data-p0=\"input\">\n <SuggestCombobox\n value={selected}\n onChange={(next) => field.setValue(next.map((provider) => ({ provider })))}\n options={field.options}\n maxItems={field.meta.maxItems}\n ariaInvalid={!!field.error}\n placeholder=\"Select providers…\"\n emptyLabel=\"No providers available\"\n reorderable\n />\n </div>\n );\n}\n"],"mappings":";;;;AAGA,SAAgB,sBAAsB,OAAuC;AAG3E,QACE,oBAAC,OAAD;EAAK,WAAQ;YACX,oBAAC,iBAAD;GACE,QALY,MAAM,SAAS,EAAE,EAAE,KAAK,MAA4B,EAAE,SAAS;GAM3E,WAAW,SAAS,MAAM,SAAS,KAAK,KAAK,cAAc,EAAE,UAAU,EAAE,CAAC;GAC1E,SAAS,MAAM;GACf,UAAU,MAAM,KAAK;GACrB,aAAa,CAAC,CAAC,MAAM;GACrB,aAAY;GACZ,YAAW;GACX;GACA;EACE"}
|
|
1
|
+
{"version":3,"file":"providers-input.mjs","names":["XIcon","SearchIcon"],"sources":["../../../../src/components/defaults/adapters/providers-input.tsx"],"sourcesContent":["import {\n closestCenter,\n DndContext,\n type DragEndEvent,\n KeyboardSensor,\n PointerSensor,\n useSensor,\n useSensors,\n} from \"@dnd-kit/core\";\nimport { SortableContext, useSortable, verticalListSortingStrategy } from \"@dnd-kit/sortable\";\nimport type { WidgetsByKind } from \"@pipe0/base\";\nimport { Search as SearchIcon, X as XIcon } from \"lucide-react\";\nimport { type CSSProperties, useMemo, useState } from \"react\";\nimport { cn } from \"../../../lib/utils.js\";\nimport type { FieldHandle } from \"../../../types/field-handle.js\";\nimport { WidgetStrip } from \"../../../widgets/widget-strip.js\";\nimport { IconGripVertical, IconPlus } from \"../../internal/icons.js\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../../ui/popover.js\";\n\ntype ProviderOption = {\n value: string;\n label: string;\n widgets?: WidgetsByKind;\n};\n\nfunction splitWidgets(widgets: WidgetsByKind | undefined): {\n leading: WidgetsByKind | undefined;\n pricing: WidgetsByKind[\"pricing\"] | undefined;\n} {\n if (!widgets) return { leading: undefined, pricing: undefined };\n const { pricing, ...rest } = widgets;\n const hasLeading = Object.values(rest).some((v) => v != null);\n return { leading: hasLeading ? rest : undefined, pricing };\n}\n\n/**\n * Provider waterfall — vertical, ordered list of providers tried sequentially\n * until a valid result is returned. The list makes the running order legible\n * (numeric badge per row, drag-to-reorder), and the credit widget per\n * provider stays visible.\n */\nexport function ProvidersInputAdapter(field: FieldHandle<\"providers_input\">) {\n const selected: string[] = useMemo(\n () => (field.value ?? []).map((p: { provider: string }) => p.provider),\n [field.value],\n );\n\n const options = field.options ?? [];\n const optionByValue = useMemo(() => {\n const map = new Map<string, ProviderOption>();\n for (const o of options) map.set(o.value, o);\n return map;\n }, [options]);\n\n const maxItems = field.meta.maxItems;\n const atMax = maxItems !== undefined && selected.length >= maxItems;\n\n const setValue = (next: string[]) =>\n field.setValue(next.map((provider) => ({ provider })));\n\n const handleRemove = (value: string) => setValue(selected.filter((v) => v !== value));\n const handleAdd = (value: string) => {\n if (selected.includes(value)) return;\n setValue([...selected, value]);\n };\n\n const sensors = useSensors(\n useSensor(PointerSensor, { activationConstraint: { distance: 4 } }),\n useSensor(KeyboardSensor),\n );\n\n const handleDragEnd = (event: DragEndEvent) => {\n const { active, over } = event;\n if (!over || active.id === over.id) return;\n const from = selected.indexOf(String(active.id));\n const to = selected.indexOf(String(over.id));\n if (from === -1 || to === -1) return;\n const next = [...selected];\n const [moved] = next.splice(from, 1);\n next.splice(to, 0, moved);\n setValue(next);\n };\n\n return (\n <div data-p0=\"input\" className=\"pz:flex pz:flex-col pz:gap-1\">\n {selected.length > 0 && (\n <DndContext\n sensors={sensors}\n collisionDetection={closestCenter}\n onDragEnd={handleDragEnd}\n >\n <SortableContext items={selected} strategy={verticalListSortingStrategy}>\n <ul className=\"pz:flex pz:flex-col pz:gap-0.5 pz:list-none pz:m-0 pz:p-0\">\n {selected.map((value, index) => {\n const option = optionByValue.get(value);\n return (\n <ProviderRow\n key={value}\n value={value}\n index={index}\n label={option?.label ?? value}\n widgets={option?.widgets}\n onRemove={() => handleRemove(value)}\n />\n );\n })}\n </ul>\n </SortableContext>\n </DndContext>\n )}\n {!atMax && (\n <AddProviderControl\n options={options}\n excluded={selected}\n onAdd={handleAdd}\n ariaInvalid={!!field.error}\n />\n )}\n </div>\n );\n}\n\nfunction ProviderRow({\n value,\n index,\n label,\n widgets,\n onRemove,\n}: {\n value: string;\n index: number;\n label: string;\n widgets?: WidgetsByKind;\n onRemove: () => void;\n}) {\n const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({\n id: value,\n });\n const style: CSSProperties = {\n transform: transform\n ? `translate3d(${Math.round(transform.x)}px, ${Math.round(transform.y)}px, 0)`\n : undefined,\n transition,\n opacity: isDragging ? 0.6 : 1,\n };\n\n const { leading, pricing } = splitWidgets(widgets);\n const orderLabel = String(index + 1).padStart(2, \"0\");\n\n return (\n <li\n ref={setNodeRef}\n style={style}\n className={cn(\n \"pz:group/prov pz:flex pz:items-center pz:gap-2.5 pz:rounded-md pz:px-1.5 pz:py-1.5\",\n \"pz:hover:bg-muted/60 pz:transition-colors\",\n )}\n {...attributes}\n >\n <button\n type=\"button\"\n aria-label=\"Drag to reorder\"\n className={cn(\n \"pz:flex pz:items-center pz:justify-center pz:size-4 pz:cursor-grab pz:touch-none\",\n \"pz:text-muted-foreground/60 pz:hover:text-foreground pz:transition-colors\",\n )}\n {...listeners}\n >\n <IconGripVertical width={11} height={14} />\n </button>\n {leading && (\n <span className=\"pz:flex pz:items-center pz:shrink-0\">\n <WidgetStrip widgets={leading} size={18} />\n </span>\n )}\n <span className=\"pz:text-sm pz:font-medium pz:text-foreground pz:flex-1 pz:truncate\">\n {label}\n </span>\n {pricing && (\n <span className=\"pz:text-xs pz:text-muted-foreground pz:tabular-nums\">\n {pricing.credits} cr\n </span>\n )}\n <span\n aria-hidden\n className={cn(\n \"pz:inline-flex pz:items-center pz:justify-center pz:min-w-7 pz:h-5 pz:px-1.5\",\n \"pz:rounded-full pz:bg-muted pz:text-muted-foreground pz:text-[10.5px]\",\n \"pz:font-medium pz:tabular-nums\",\n )}\n >\n {orderLabel}\n </span>\n <button\n type=\"button\"\n aria-label={`Remove ${label}`}\n onClick={(e) => {\n e.stopPropagation();\n onRemove();\n }}\n className={cn(\n \"pz:flex pz:items-center pz:justify-center pz:size-5 pz:rounded\",\n \"pz:text-muted-foreground/70\",\n \"pz:hover:bg-destructive/10 pz:hover:text-destructive pz:transition-colors\",\n )}\n >\n <XIcon className=\"pz:size-3\" />\n </button>\n </li>\n );\n}\n\nfunction AddProviderControl({\n options,\n excluded,\n onAdd,\n ariaInvalid,\n}: {\n options: ProviderOption[];\n excluded: string[];\n onAdd: (value: string) => void;\n ariaInvalid?: boolean;\n}) {\n const [open, setOpen] = useState(false);\n const [query, setQuery] = useState(\"\");\n\n const excludedSet = useMemo(() => new Set(excluded), [excluded]);\n const available = useMemo(\n () => options.filter((o) => !excludedSet.has(o.value)),\n [options, excludedSet],\n );\n\n const filtered = useMemo(() => {\n const q = query.trim().toLowerCase();\n if (!q) return available;\n return available.filter(\n (o) => o.label.toLowerCase().includes(q) || o.value.toLowerCase().includes(q),\n );\n }, [available, query]);\n\n if (available.length === 0 && excluded.length === 0) {\n return (\n <div className=\"pz:text-xs pz:text-muted-foreground pz:px-1.5 pz:py-2\">\n No providers available\n </div>\n );\n }\n\n if (available.length === 0) return null;\n\n return (\n <Popover\n open={open}\n onOpenChange={(next) => {\n setOpen(next);\n if (!next) setQuery(\"\");\n }}\n >\n <PopoverTrigger\n aria-invalid={ariaInvalid || undefined}\n className={cn(\n \"pz:flex pz:items-center pz:justify-center pz:gap-1.5 pz:w-full\",\n \"pz:px-2.5 pz:py-1.5 pz:mt-1 pz:rounded-md\",\n \"pz:border pz:border-dashed pz:border-input pz:bg-transparent\",\n \"pz:text-xs pz:text-muted-foreground\",\n \"pz:hover:bg-muted/60 pz:hover:text-foreground pz:hover:border-muted-foreground/40\",\n \"pz:transition-colors pz:cursor-pointer\",\n )}\n >\n <IconPlus width={12} height={12} />\n Add provider\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"pz:w-(--anchor-width) pz:p-0 pz:gap-0\">\n <div className=\"pz:flex pz:items-center pz:gap-1.5 pz:px-2.5 pz:py-2 pz:border-b pz:border-border\">\n <SearchIcon className=\"pz:size-3.5 pz:text-muted-foreground pz:shrink-0\" />\n <input\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n placeholder=\"Search providers…\"\n // biome-ignore lint/a11y/noAutofocus: popover-scoped picker\n autoFocus\n className=\"pz:flex-1 pz:bg-transparent pz:outline-none pz:text-sm pz:placeholder:text-muted-foreground/70\"\n />\n </div>\n <ul className=\"pz:flex pz:flex-col pz:p-1 pz:max-h-72 pz:overflow-auto pz:list-none pz:m-0\">\n {filtered.length === 0 && (\n <li className=\"pz:px-2 pz:py-3 pz:text-center pz:text-xs pz:text-muted-foreground\">\n No providers\n </li>\n )}\n {filtered.map((option) => {\n const { leading, pricing } = splitWidgets(option.widgets);\n return (\n <li key={option.value} className=\"pz:contents\">\n <button\n type=\"button\"\n onClick={() => {\n onAdd(option.value);\n setOpen(false);\n setQuery(\"\");\n }}\n className={cn(\n \"pz:flex pz:items-center pz:gap-2 pz:w-full pz:text-left\",\n \"pz:px-2 pz:py-1.5 pz:rounded-md pz:text-sm\",\n \"pz:hover:bg-accent pz:hover:text-accent-foreground\",\n \"pz:transition-colors pz:cursor-pointer\",\n )}\n >\n {leading && (\n <span className=\"pz:flex pz:items-center pz:shrink-0\">\n <WidgetStrip widgets={leading} size={16} />\n </span>\n )}\n <span className=\"pz:flex-1 pz:truncate\">{option.label}</span>\n {pricing && (\n <span className=\"pz:text-xs pz:text-muted-foreground pz:tabular-nums\">\n {pricing.credits} cr\n </span>\n )}\n </button>\n </li>\n );\n })}\n </ul>\n </PopoverContent>\n </Popover>\n );\n}\n"],"mappings":";;;;;;;;;;;AAyBA,SAAS,aAAa,SAGpB;AACA,KAAI,CAAC,QAAS,QAAO;EAAE,SAAS;EAAW,SAAS;EAAW;CAC/D,MAAM,EAAE,SAAS,GAAG,SAAS;AAE7B,QAAO;EAAE,SADU,OAAO,OAAO,KAAK,CAAC,MAAM,MAAM,KAAK,KAAK,GAC9B,OAAO;EAAW;EAAS;;;;;;;;AAS5D,SAAgB,sBAAsB,OAAuC;CAC3E,MAAM,WAAqB,eAClB,MAAM,SAAS,EAAE,EAAE,KAAK,MAA4B,EAAE,SAAS,EACtE,CAAC,MAAM,MAAM,CACd;CAED,MAAM,UAAU,MAAM,WAAW,EAAE;CACnC,MAAM,gBAAgB,cAAc;EAClC,MAAM,sBAAM,IAAI,KAA6B;AAC7C,OAAK,MAAM,KAAK,QAAS,KAAI,IAAI,EAAE,OAAO,EAAE;AAC5C,SAAO;IACN,CAAC,QAAQ,CAAC;CAEb,MAAM,WAAW,MAAM,KAAK;CAC5B,MAAM,QAAQ,aAAa,UAAa,SAAS,UAAU;CAE3D,MAAM,YAAY,SAChB,MAAM,SAAS,KAAK,KAAK,cAAc,EAAE,UAAU,EAAE,CAAC;CAExD,MAAM,gBAAgB,UAAkB,SAAS,SAAS,QAAQ,MAAM,MAAM,MAAM,CAAC;CACrF,MAAM,aAAa,UAAkB;AACnC,MAAI,SAAS,SAAS,MAAM,CAAE;AAC9B,WAAS,CAAC,GAAG,UAAU,MAAM,CAAC;;CAGhC,MAAM,UAAU,WACd,UAAU,eAAe,EAAE,sBAAsB,EAAE,UAAU,GAAG,EAAE,CAAC,EACnE,UAAU,eAAe,CAC1B;CAED,MAAM,iBAAiB,UAAwB;EAC7C,MAAM,EAAE,QAAQ,SAAS;AACzB,MAAI,CAAC,QAAQ,OAAO,OAAO,KAAK,GAAI;EACpC,MAAM,OAAO,SAAS,QAAQ,OAAO,OAAO,GAAG,CAAC;EAChD,MAAM,KAAK,SAAS,QAAQ,OAAO,KAAK,GAAG,CAAC;AAC5C,MAAI,SAAS,MAAM,OAAO,GAAI;EAC9B,MAAM,OAAO,CAAC,GAAG,SAAS;EAC1B,MAAM,CAAC,SAAS,KAAK,OAAO,MAAM,EAAE;AACpC,OAAK,OAAO,IAAI,GAAG,MAAM;AACzB,WAAS,KAAK;;AAGhB,QACE,qBAAC,OAAD;EAAK,WAAQ;EAAQ,WAAU;YAA/B,CACG,SAAS,SAAS,KACjB,oBAAC,YAAD;GACW;GACT,oBAAoB;GACpB,WAAW;aAEX,oBAAC,iBAAD;IAAiB,OAAO;IAAU,UAAU;cAC1C,oBAAC,MAAD;KAAI,WAAU;eACX,SAAS,KAAK,OAAO,UAAU;MAC9B,MAAM,SAAS,cAAc,IAAI,MAAM;AACvC,aACE,oBAAC,aAAD;OAES;OACA;OACP,OAAO,QAAQ,SAAS;OACxB,SAAS,QAAQ;OACjB,gBAAgB,aAAa,MAAM;OACnC,EANK,MAML;OAEJ;KACC;IACW;GACP,GAEd,CAAC,SACA,oBAAC,oBAAD;GACW;GACT,UAAU;GACV,OAAO;GACP,aAAa,CAAC,CAAC,MAAM;GACrB,EAEA;;;AAIV,SAAS,YAAY,EACnB,OACA,OACA,OACA,SACA,YAOC;CACD,MAAM,EAAE,YAAY,WAAW,YAAY,WAAW,YAAY,eAAe,YAAY,EAC3F,IAAI,OACL,CAAC;CACF,MAAM,QAAuB;EAC3B,WAAW,YACP,eAAe,KAAK,MAAM,UAAU,EAAE,CAAC,MAAM,KAAK,MAAM,UAAU,EAAE,CAAC,UACrE;EACJ;EACA,SAAS,aAAa,KAAM;EAC7B;CAED,MAAM,EAAE,SAAS,YAAY,aAAa,QAAQ;CAClD,MAAM,aAAa,OAAO,QAAQ,EAAE,CAAC,SAAS,GAAG,IAAI;AAErD,QACE,qBAAC,MAAD;EACE,KAAK;EACE;EACP,WAAW,GACT,sFACA,4CACD;EACD,GAAI;YAPN;GASE,oBAAC,UAAD;IACE,MAAK;IACL,cAAW;IACX,WAAW,GACT,oFACA,4EACD;IACD,GAAI;cAEJ,oBAAC,kBAAD;KAAkB,OAAO;KAAI,QAAQ;KAAM;IACpC;GACR,WACC,oBAAC,QAAD;IAAM,WAAU;cACd,oBAAC,aAAD;KAAa,SAAS;KAAS,MAAM;KAAM;IACtC;GAET,oBAAC,QAAD;IAAM,WAAU;cACb;IACI;GACN,WACC,qBAAC,QAAD;IAAM,WAAU;cAAhB,CACG,QAAQ,SAAQ,MACZ;;GAET,oBAAC,QAAD;IACE;IACA,WAAW,GACT,gFACA,yEACA,iCACD;cAEA;IACI;GACP,oBAAC,UAAD;IACE,MAAK;IACL,cAAY,UAAU;IACtB,UAAU,MAAM;AACd,OAAE,iBAAiB;AACnB,eAAU;;IAEZ,WAAW,GACT,kEACA,+BACA,4EACD;cAED,oBAACA,GAAD,EAAO,WAAU,aAAc;IACxB;GACN;;;AAIT,SAAS,mBAAmB,EAC1B,SACA,UACA,OACA,eAMC;CACD,MAAM,CAAC,MAAM,WAAW,SAAS,MAAM;CACvC,MAAM,CAAC,OAAO,YAAY,SAAS,GAAG;CAEtC,MAAM,cAAc,cAAc,IAAI,IAAI,SAAS,EAAE,CAAC,SAAS,CAAC;CAChE,MAAM,YAAY,cACV,QAAQ,QAAQ,MAAM,CAAC,YAAY,IAAI,EAAE,MAAM,CAAC,EACtD,CAAC,SAAS,YAAY,CACvB;CAED,MAAM,WAAW,cAAc;EAC7B,MAAM,IAAI,MAAM,MAAM,CAAC,aAAa;AACpC,MAAI,CAAC,EAAG,QAAO;AACf,SAAO,UAAU,QACd,MAAM,EAAE,MAAM,aAAa,CAAC,SAAS,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC,SAAS,EAAE,CAC9E;IACA,CAAC,WAAW,MAAM,CAAC;AAEtB,KAAI,UAAU,WAAW,KAAK,SAAS,WAAW,EAChD,QACE,oBAAC,OAAD;EAAK,WAAU;YAAwD;EAEjE;AAIV,KAAI,UAAU,WAAW,EAAG,QAAO;AAEnC,QACE,qBAAC,SAAD;EACQ;EACN,eAAe,SAAS;AACtB,WAAQ,KAAK;AACb,OAAI,CAAC,KAAM,UAAS,GAAG;;YAJ3B,CAOE,qBAAC,gBAAD;GACE,gBAAc,eAAe;GAC7B,WAAW,GACT,kEACA,6CACA,gEACA,uCACA,qFACA,yCACD;aATH,CAWE,oBAAC,UAAD;IAAU,OAAO;IAAI,QAAQ;IAAM,kBAEpB;MACjB,qBAAC,gBAAD;GAAgB,OAAM;GAAQ,WAAU;aAAxC,CACE,qBAAC,OAAD;IAAK,WAAU;cAAf,CACE,oBAACC,QAAD,EAAY,WAAU,oDAAqD,GAC3E,oBAAC,SAAD;KACE,OAAO;KACP,WAAW,MAAM,SAAS,EAAE,OAAO,MAAM;KACzC,aAAY;KAEZ;KACA,WAAU;KACV,EACE;OACN,qBAAC,MAAD;IAAI,WAAU;cAAd,CACG,SAAS,WAAW,KACnB,oBAAC,MAAD;KAAI,WAAU;eAAqE;KAE9E,GAEN,SAAS,KAAK,WAAW;KACxB,MAAM,EAAE,SAAS,YAAY,aAAa,OAAO,QAAQ;AACzD,YACE,oBAAC,MAAD;MAAuB,WAAU;gBAC/B,qBAAC,UAAD;OACE,MAAK;OACL,eAAe;AACb,cAAM,OAAO,MAAM;AACnB,gBAAQ,MAAM;AACd,iBAAS,GAAG;;OAEd,WAAW,GACT,2DACA,8CACA,sDACA,yCACD;iBAZH;QAcG,WACC,oBAAC,QAAD;SAAM,WAAU;mBACd,oBAAC,aAAD;UAAa,SAAS;UAAS,MAAM;UAAM;SACtC;QAET,oBAAC,QAAD;SAAM,WAAU;mBAAyB,OAAO;SAAa;QAC5D,WACC,qBAAC,QAAD;SAAM,WAAU;mBAAhB,CACG,QAAQ,SAAQ,MACZ;;QAEF;;MACN,EA3BI,OAAO,MA2BX;MAEP,CACC;MACU;KACT"}
|