@pipe0/react 1.0.32 → 1.0.33

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/components/defaults/catalog/card-derived.d.mts +1 -1
  3. package/dist/components/defaults/catalog/card-derived.mjs +0 -1
  4. package/dist/components/defaults/catalog/card-derived.mjs.map +1 -1
  5. package/dist/components/defaults/catalog/card-primitives.d.mts +2 -2
  6. package/dist/components/defaults/catalog/card-primitives.mjs +2 -2
  7. package/dist/components/defaults/catalog/card-primitives.mjs.map +1 -1
  8. package/dist/components/internal/LiquidEditor/ChipEditPopover.mjs +60 -14
  9. package/dist/components/internal/LiquidEditor/ChipEditPopover.mjs.map +1 -1
  10. package/dist/context/catalog-card-context.mjs +3 -7
  11. package/dist/context/catalog-card-context.mjs.map +1 -1
  12. package/dist/context/catalog-config-context.d.mts +1 -1
  13. package/dist/context/catalog-config-context.mjs +1 -1
  14. package/dist/context/catalog-config-context.mjs.map +1 -1
  15. package/dist/hooks/use-pipe-catalog-table.d.mts +8 -8
  16. package/dist/index.d.mts +2 -17
  17. package/dist/index.mjs +1 -16
  18. package/dist/types/catalog-adapters.d.mts +2 -19
  19. package/dist/types/catalog-adapters.d.mts.map +1 -1
  20. package/package.json +2 -2
  21. package/dist/components/compound/searches-catalog/active-filters.d.mts +0 -23
  22. package/dist/components/compound/searches-catalog/active-filters.d.mts.map +0 -1
  23. package/dist/components/compound/searches-catalog/active-filters.mjs +0 -50
  24. package/dist/components/compound/searches-catalog/active-filters.mjs.map +0 -1
  25. package/dist/components/compound/searches-catalog/card.d.mts +0 -22
  26. package/dist/components/compound/searches-catalog/card.d.mts.map +0 -1
  27. package/dist/components/compound/searches-catalog/card.mjs +0 -82
  28. package/dist/components/compound/searches-catalog/card.mjs.map +0 -1
  29. package/dist/components/compound/searches-catalog/category-filter.d.mts +0 -27
  30. package/dist/components/compound/searches-catalog/category-filter.d.mts.map +0 -1
  31. package/dist/components/compound/searches-catalog/category-filter.mjs +0 -61
  32. package/dist/components/compound/searches-catalog/category-filter.mjs.map +0 -1
  33. package/dist/components/compound/searches-catalog/column-filter.d.mts +0 -29
  34. package/dist/components/compound/searches-catalog/column-filter.d.mts.map +0 -1
  35. package/dist/components/compound/searches-catalog/column-filter.mjs +0 -64
  36. package/dist/components/compound/searches-catalog/column-filter.mjs.map +0 -1
  37. package/dist/components/compound/searches-catalog/column-filters.d.mts +0 -15
  38. package/dist/components/compound/searches-catalog/column-filters.d.mts.map +0 -1
  39. package/dist/components/compound/searches-catalog/column-filters.mjs +0 -16
  40. package/dist/components/compound/searches-catalog/column-filters.mjs.map +0 -1
  41. package/dist/components/compound/searches-catalog/empty.d.mts +0 -17
  42. package/dist/components/compound/searches-catalog/empty.d.mts.map +0 -1
  43. package/dist/components/compound/searches-catalog/empty.mjs +0 -29
  44. package/dist/components/compound/searches-catalog/empty.mjs.map +0 -1
  45. package/dist/components/compound/searches-catalog/index.d.mts +0 -12
  46. package/dist/components/compound/searches-catalog/list.d.mts +0 -19
  47. package/dist/components/compound/searches-catalog/list.d.mts.map +0 -1
  48. package/dist/components/compound/searches-catalog/list.mjs +0 -33
  49. package/dist/components/compound/searches-catalog/list.mjs.map +0 -1
  50. package/dist/components/compound/searches-catalog/output-field-filter.d.mts +0 -22
  51. package/dist/components/compound/searches-catalog/output-field-filter.d.mts.map +0 -1
  52. package/dist/components/compound/searches-catalog/output-field-filter.mjs +0 -22
  53. package/dist/components/compound/searches-catalog/output-field-filter.mjs.map +0 -1
  54. package/dist/components/compound/searches-catalog/provider-filter.d.mts +0 -22
  55. package/dist/components/compound/searches-catalog/provider-filter.d.mts.map +0 -1
  56. package/dist/components/compound/searches-catalog/provider-filter.mjs +0 -29
  57. package/dist/components/compound/searches-catalog/provider-filter.mjs.map +0 -1
  58. package/dist/components/compound/searches-catalog/root.d.mts +0 -33
  59. package/dist/components/compound/searches-catalog/root.d.mts.map +0 -1
  60. package/dist/components/compound/searches-catalog/root.mjs +0 -74
  61. package/dist/components/compound/searches-catalog/root.mjs.map +0 -1
  62. package/dist/components/compound/searches-catalog/search-filter.d.mts +0 -21
  63. package/dist/components/compound/searches-catalog/search-filter.d.mts.map +0 -1
  64. package/dist/components/compound/searches-catalog/search-filter.mjs +0 -47
  65. package/dist/components/compound/searches-catalog/search-filter.mjs.map +0 -1
  66. package/dist/components/compound/searches-catalog/tag-filter.d.mts +0 -22
  67. package/dist/components/compound/searches-catalog/tag-filter.d.mts.map +0 -1
  68. package/dist/components/compound/searches-catalog/tag-filter.mjs +0 -22
  69. package/dist/components/compound/searches-catalog/tag-filter.mjs.map +0 -1
  70. package/dist/context/searches-catalog-card-context.d.mts +0 -24
  71. package/dist/context/searches-catalog-card-context.d.mts.map +0 -1
  72. package/dist/context/searches-catalog-card-context.mjs +0 -13
  73. package/dist/context/searches-catalog-card-context.mjs.map +0 -1
  74. package/dist/context/searches-catalog-context.d.mts +0 -20
  75. package/dist/context/searches-catalog-context.d.mts.map +0 -1
  76. package/dist/context/searches-catalog-context.mjs +0 -13
  77. package/dist/context/searches-catalog-context.mjs.map +0 -1
  78. package/dist/hooks/use-searches-catalog-table.d.mts +0 -56
  79. package/dist/hooks/use-searches-catalog-table.d.mts.map +0 -1
  80. package/dist/hooks/use-searches-catalog-table.mjs +0 -159
  81. package/dist/hooks/use-searches-catalog-table.mjs.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # @pipe0/elements-react
2
2
 
3
+ ## 1.0.33
4
+
5
+ ### Patch Changes
6
+
7
+ - e50e746: feat: fix update row
8
+ - e50e746: Remove /run and /searches
9
+ - Updated dependencies [e50e746]
10
+ - Updated dependencies [e50e746]
11
+ - @pipe0/base@1.0.33
12
+
3
13
  ## 1.0.32
4
14
 
5
15
  ### Patch Changes
@@ -85,7 +85,7 @@ declare function CatalogDocsBadge({
85
85
  variant
86
86
  }: CatalogDocsBadgeProps): _$react_jsx_runtime0.JSX.Element | null;
87
87
  interface CatalogCopyIdProps {
88
- /** Override the auto-bound id. Defaults to `card.pipeId` / `card.searchId` / `card.searchesId`. */
88
+ /** Override the auto-bound id. Defaults to `card.pipeId` / `card.searchId`. */
89
89
  value?: string;
90
90
  className?: string;
91
91
  }
@@ -168,7 +168,6 @@ function CatalogCopyId({ value, className }) {
168
168
  function deriveCardId(card) {
169
169
  if (!card) return void 0;
170
170
  if ("pipeId" in card) return card.pipeId;
171
- if ("searchesId" in card) return card.searchesId;
172
171
  if ("searchId" in card) return card.searchId;
173
172
  if ("effectId" in card) return card.effectId;
174
173
  }
@@ -1 +1 @@
1
- {"version":3,"file":"card-derived.mjs","names":[],"sources":["../../../../src/components/defaults/catalog/card-derived.tsx"],"sourcesContent":["import { Check, Coins, Copy, ExternalLink, ListChecks, ListPlus } from \"lucide-react\";\nimport { type ReactNode, useState } from \"react\";\nimport type { AnyCardData } from \"../../../context/catalog-card-context.js\";\nimport {\n useAnyCatalogCardOptional,\n useAnyCatalogContextOptional,\n} from \"../../../context/catalog-card-context.js\";\nimport { useCatalogConfig } from \"../../../context/catalog-config-context.js\";\nimport { cn } from \"../../../lib/utils.js\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../../ui/popover.js\";\nimport { CatalogCardBadge, type CatalogCardBadgeProps } from \"./card-primitives.js\";\n\n/* -------------------------------------------------------------------------- */\n/* Credit badge — \"Starts at X / result|search|page\" or \"Free\" */\n/* -------------------------------------------------------------------------- */\n\nexport interface CatalogCreditBadgeProps {\n /** Override the auto-bound credit amount. */\n creditAmount?: number;\n /** Override the auto-bound cost mode. */\n costMode?: \"per_result\" | \"per_search\" | \"per_page\" | \"usage\";\n freeLabel?: ReactNode;\n creditPrefix?: ReactNode;\n className?: string;\n disabled?: boolean;\n variant?: CatalogCardBadgeProps[\"variant\"];\n}\n\n/**\n * Displays the starting credit cost for the surrounding card. Self-binds to\n * `card.startingCreditAmount` + `card.costMode` from card context unless\n * overridden via props.\n */\nexport function CatalogCreditBadge({\n creditAmount,\n costMode,\n freeLabel = \"Free\",\n creditPrefix = \"Starts at\",\n disabled = true,\n className,\n variant,\n}: CatalogCreditBadgeProps) {\n const card = useAnyCatalogCardOptional()?.card;\n const amount =\n creditAmount ?? (card && \"startingCreditAmount\" in card ? card.startingCreditAmount : 0);\n const mode = costMode ?? (card && \"costMode\" in card ? card.costMode : \"per_result\");\n const denom = mode === \"per_result\" ? \"result\" : mode === \"per_search\" ? \"search\" : \"page\";\n // Round away floating-point noise; flat per-use prices are already clean.\n const display = Math.round(amount * 1000) / 1000;\n return (\n <CatalogCardBadge\n disabled={disabled}\n variant={variant}\n className={cn(\"pz:whitespace-nowrap\", className)}\n >\n {mode === \"usage\" ? (\n <span className=\"pz:inline-flex pz:items-center pz:gap-1\">\n <Coins className=\"pz:size-3\" />\n <span>Usage</span>\n </span>\n ) : display > 0 ? (\n <span className=\"pz:inline-flex pz:items-center pz:gap-0.5\">\n {creditPrefix ? <span className=\"pz:mr-1\">{creditPrefix}</span> : null}\n <span>{display}</span>\n <Coins className=\"pz:size-3\" />\n <span>/ {denom}</span>\n </span>\n ) : (\n freeLabel\n )}\n </CatalogCardBadge>\n );\n}\n\n/* -------------------------------------------------------------------------- */\n/* Field badge — dropdown listing input or output fields, click to filter */\n/* -------------------------------------------------------------------------- */\n\nexport interface CatalogFieldBadgeState {\n fields: string[];\n isOpen: boolean;\n setOpen: (open: boolean) => void;\n /** Calls onSelectField (or the auto-wired catalog filter) and closes the popover. */\n onSelect: (fieldName: string) => void;\n isFieldAvailable: (fieldName: string) => boolean;\n}\n\nexport interface CatalogFieldBadgeProps {\n fieldType: \"input\" | \"output\";\n /** Override the auto-bound fields list. */\n fields?: string[];\n /** Override the auto-wired filter handler. */\n onSelectField?: (fieldName: string) => void;\n /** Returns true if the field has any matching cards. Defaults to a reverse-index lookup on the catalog. */\n isFieldAvailable?: (fieldName: string) => boolean;\n label?: ReactNode;\n fieldIcon?: (fieldName: string) => ReactNode;\n className?: string;\n variant?: CatalogCardBadgeProps[\"variant\"];\n /** Render the entire dropdown UI yourself. Receives the merged state. */\n render?: (state: CatalogFieldBadgeState) => ReactNode;\n}\n\n/**\n * Dropdown that lists a card's input or output fields, with click-to-filter\n * wiring. By default, clicking a field filters the catalog by that field\n * (`addColumnFilter(\"inputFields\"|\"outputFields\", field)`); pass `onSelectField`\n * to override (e.g. inverted-filter UX).\n */\nexport function CatalogFieldBadge({\n fieldType,\n fields,\n onSelectField,\n isFieldAvailable,\n label,\n fieldIcon,\n className,\n variant = \"outline\",\n render,\n}: CatalogFieldBadgeProps) {\n const [open, setOpen] = useState(false);\n const card = useAnyCatalogCardOptional()?.card;\n const ctx = useAnyCatalogContextOptional();\n\n const resolvedFields = fields ?? deriveCardFields(card, fieldType);\n\n const handleSelect =\n onSelectField ??\n ((field: string) => {\n ctx?.addColumnFilter(fieldType === \"input\" ? \"inputFields\" : \"outputFields\", field);\n });\n\n const handleAvailable =\n isFieldAvailable ??\n ((field: string) => {\n if (!ctx) return true;\n const map =\n fieldType === \"input\"\n ? (ctx as { pipeIdsByInputField?: Record<string, unknown[]> }).pipeIdsByInputField\n : pickOutputIndex(ctx);\n if (!map) return true;\n return !!map[field];\n });\n\n if (render) {\n return (\n <>\n {render({\n fields: resolvedFields,\n isOpen: open,\n setOpen,\n onSelect: (field: string) => {\n handleSelect(field);\n setOpen(false);\n },\n isFieldAvailable: handleAvailable,\n })}\n </>\n );\n }\n\n if (!resolvedFields.length) return null;\n const Icon = fieldType === \"input\" ? ListPlus : ListChecks;\n const text = label ?? (fieldType === \"input\" ? \"Show inputs\" : \"Show outputs\");\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger\n render={\n <CatalogCardBadge\n variant={variant}\n className={cn(\n \"pz:font-normal pz:text-muted-foreground pz:hover:text-foreground\",\n className,\n )}\n >\n <Icon className=\"pz:size-3\" />\n {text}\n </CatalogCardBadge>\n }\n />\n <PopoverContent align=\"start\" side=\"bottom\" className=\"pz:w-auto pz:min-w-40 pz:p-1\">\n <ul\n data-p0=\"catalog-card-field-badge-list\"\n className=\"pz:flex pz:flex-col pz:gap-0.5 pz:list-none pz:m-0 pz:p-0\"\n >\n {resolvedFields.map((field) => {\n const available = handleAvailable(field);\n return (\n <li key={field} className=\"pz:flex\">\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n handleSelect(field);\n setOpen(false);\n }}\n className={cn(\n \"pz:w-full pz:text-sm pz:text-left pz:py-1 pz:px-2 pz:rounded pz:flex pz:items-center pz:gap-2 pz:transition-all\",\n available\n ? \"pz:text-muted-foreground pz:hover:text-foreground pz:hover:bg-muted\"\n : \"pz:text-muted-foreground/50 pz:cursor-not-allowed\",\n )}\n data-available={available}\n >\n {fieldIcon?.(field)}\n {field}\n </button>\n </li>\n );\n })}\n </ul>\n </PopoverContent>\n </Popover>\n );\n}\n\nfunction deriveCardFields(card: AnyCardData | undefined, fieldType: \"input\" | \"output\"): string[] {\n if (!card) return [];\n if (fieldType === \"output\") {\n return (\"defaultOutputFields\" in card ? card.defaultOutputFields : []) ?? [];\n }\n if (\"defaultInputFields\" in card) {\n return card.defaultInputFields.map((f) => f.name);\n }\n return [];\n}\n\nfunction pickOutputIndex(ctx: unknown): Record<string, unknown[]> | undefined {\n const c = ctx as {\n pipeIdsByOutputField?: Record<string, unknown[]>;\n searchIdsByOutputField?: Record<string, unknown[]>;\n };\n return c.pipeIdsByOutputField ?? c.searchIdsByOutputField;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Docs badge — external link to provider docs */\n/* -------------------------------------------------------------------------- */\n\nexport interface CatalogDocsBadgeProps {\n /** Base URL prepended to the card's docPath. */\n baseUrl?: string;\n /** Override the full URL (skips baseUrl + card.docPath composition). */\n href?: string;\n label?: ReactNode;\n className?: string;\n variant?: CatalogCardBadgeProps[\"variant\"];\n}\n\nexport function CatalogDocsBadge({\n baseUrl,\n href,\n label = \"Go to docs\",\n className,\n variant = \"outline\",\n}: CatalogDocsBadgeProps) {\n const card = useAnyCatalogCardOptional()?.card;\n const docPath = card && \"docPath\" in card ? card.docPath : undefined;\n const resolvedHref = href ?? (baseUrl && docPath ? `${baseUrl}${docPath}` : docPath);\n if (!resolvedHref) return null;\n return (\n <a target=\"_blank\" href={resolvedHref} rel=\"noreferrer\" onClick={(e) => e.stopPropagation()}>\n <CatalogCardBadge\n variant={variant}\n className={cn(\n \"pz:font-normal pz:text-muted-foreground pz:hover:text-foreground\",\n className,\n )}\n >\n <ExternalLink className=\"pz:size-3\" />\n {label}\n </CatalogCardBadge>\n </a>\n );\n}\n\n/* -------------------------------------------------------------------------- */\n/* Copy-id input — small input with a copy button */\n/* -------------------------------------------------------------------------- */\n\nexport interface CatalogCopyIdProps {\n /** Override the auto-bound id. Defaults to `card.pipeId` / `card.searchId` / `card.searchesId`. */\n value?: string;\n className?: string;\n}\n\nexport function CatalogCopyId({ value, className }: CatalogCopyIdProps) {\n const { classNames } = useCatalogConfig();\n const card = useAnyCatalogCardOptional()?.card;\n const resolved = value ?? deriveCardId(card);\n const [copied, setCopied] = useState(false);\n\n if (!resolved) return null;\n\n const handleCopy = (e: React.MouseEvent) => {\n e.stopPropagation();\n e.preventDefault();\n void navigator.clipboard?.writeText(resolved).then(() => {\n setCopied(true);\n setTimeout(() => setCopied(false), 1500);\n });\n };\n\n return (\n <div\n data-p0=\"catalog-card-copy-id\"\n className={cn(\n \"pz:flex pz:items-center pz:gap-2 pz:rounded-md pz:border pz:border-input pz:bg-background pz:px-2 pz:py-1\",\n classNames?.copyId,\n className,\n )}\n onClick={(e) => e.stopPropagation()}\n >\n <code className=\"pz:flex-1 pz:text-xs pz:text-muted-foreground pz:truncate pz:font-mono\">\n {resolved}\n </code>\n <button\n type=\"button\"\n onClick={handleCopy}\n aria-label=\"Copy\"\n className=\"pz:inline-flex pz:items-center pz:justify-center pz:size-6 pz:rounded pz:text-muted-foreground pz:hover:text-foreground pz:hover:bg-muted pz:transition-all\"\n >\n {copied ? <Check className=\"pz:size-3\" /> : <Copy className=\"pz:size-3\" />}\n </button>\n </div>\n );\n}\n\nfunction deriveCardId(card: AnyCardData | undefined): string | undefined {\n if (!card) return undefined;\n if (\"pipeId\" in card) return card.pipeId;\n if (\"searchesId\" in card) return card.searchesId;\n if (\"searchId\" in card) return card.searchId;\n if (\"effectId\" in card) return card.effectId;\n return undefined;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"card-derived.mjs","names":[],"sources":["../../../../src/components/defaults/catalog/card-derived.tsx"],"sourcesContent":["import { Check, Coins, Copy, ExternalLink, ListChecks, ListPlus } from \"lucide-react\";\nimport { type ReactNode, useState } from \"react\";\nimport type { AnyCardData } from \"../../../context/catalog-card-context.js\";\nimport {\n useAnyCatalogCardOptional,\n useAnyCatalogContextOptional,\n} from \"../../../context/catalog-card-context.js\";\nimport { useCatalogConfig } from \"../../../context/catalog-config-context.js\";\nimport { cn } from \"../../../lib/utils.js\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../../ui/popover.js\";\nimport { CatalogCardBadge, type CatalogCardBadgeProps } from \"./card-primitives.js\";\n\n/* -------------------------------------------------------------------------- */\n/* Credit badge — \"Starts at X / result|search|page\" or \"Free\" */\n/* -------------------------------------------------------------------------- */\n\nexport interface CatalogCreditBadgeProps {\n /** Override the auto-bound credit amount. */\n creditAmount?: number;\n /** Override the auto-bound cost mode. */\n costMode?: \"per_result\" | \"per_search\" | \"per_page\" | \"usage\";\n freeLabel?: ReactNode;\n creditPrefix?: ReactNode;\n className?: string;\n disabled?: boolean;\n variant?: CatalogCardBadgeProps[\"variant\"];\n}\n\n/**\n * Displays the starting credit cost for the surrounding card. Self-binds to\n * `card.startingCreditAmount` + `card.costMode` from card context unless\n * overridden via props.\n */\nexport function CatalogCreditBadge({\n creditAmount,\n costMode,\n freeLabel = \"Free\",\n creditPrefix = \"Starts at\",\n disabled = true,\n className,\n variant,\n}: CatalogCreditBadgeProps) {\n const card = useAnyCatalogCardOptional()?.card;\n const amount =\n creditAmount ?? (card && \"startingCreditAmount\" in card ? card.startingCreditAmount : 0);\n const mode = costMode ?? (card && \"costMode\" in card ? card.costMode : \"per_result\");\n const denom = mode === \"per_result\" ? \"result\" : mode === \"per_search\" ? \"search\" : \"page\";\n // Round away floating-point noise; flat per-use prices are already clean.\n const display = Math.round(amount * 1000) / 1000;\n return (\n <CatalogCardBadge\n disabled={disabled}\n variant={variant}\n className={cn(\"pz:whitespace-nowrap\", className)}\n >\n {mode === \"usage\" ? (\n <span className=\"pz:inline-flex pz:items-center pz:gap-1\">\n <Coins className=\"pz:size-3\" />\n <span>Usage</span>\n </span>\n ) : display > 0 ? (\n <span className=\"pz:inline-flex pz:items-center pz:gap-0.5\">\n {creditPrefix ? <span className=\"pz:mr-1\">{creditPrefix}</span> : null}\n <span>{display}</span>\n <Coins className=\"pz:size-3\" />\n <span>/ {denom}</span>\n </span>\n ) : (\n freeLabel\n )}\n </CatalogCardBadge>\n );\n}\n\n/* -------------------------------------------------------------------------- */\n/* Field badge — dropdown listing input or output fields, click to filter */\n/* -------------------------------------------------------------------------- */\n\nexport interface CatalogFieldBadgeState {\n fields: string[];\n isOpen: boolean;\n setOpen: (open: boolean) => void;\n /** Calls onSelectField (or the auto-wired catalog filter) and closes the popover. */\n onSelect: (fieldName: string) => void;\n isFieldAvailable: (fieldName: string) => boolean;\n}\n\nexport interface CatalogFieldBadgeProps {\n fieldType: \"input\" | \"output\";\n /** Override the auto-bound fields list. */\n fields?: string[];\n /** Override the auto-wired filter handler. */\n onSelectField?: (fieldName: string) => void;\n /** Returns true if the field has any matching cards. Defaults to a reverse-index lookup on the catalog. */\n isFieldAvailable?: (fieldName: string) => boolean;\n label?: ReactNode;\n fieldIcon?: (fieldName: string) => ReactNode;\n className?: string;\n variant?: CatalogCardBadgeProps[\"variant\"];\n /** Render the entire dropdown UI yourself. Receives the merged state. */\n render?: (state: CatalogFieldBadgeState) => ReactNode;\n}\n\n/**\n * Dropdown that lists a card's input or output fields, with click-to-filter\n * wiring. By default, clicking a field filters the catalog by that field\n * (`addColumnFilter(\"inputFields\"|\"outputFields\", field)`); pass `onSelectField`\n * to override (e.g. inverted-filter UX).\n */\nexport function CatalogFieldBadge({\n fieldType,\n fields,\n onSelectField,\n isFieldAvailable,\n label,\n fieldIcon,\n className,\n variant = \"outline\",\n render,\n}: CatalogFieldBadgeProps) {\n const [open, setOpen] = useState(false);\n const card = useAnyCatalogCardOptional()?.card;\n const ctx = useAnyCatalogContextOptional();\n\n const resolvedFields = fields ?? deriveCardFields(card, fieldType);\n\n const handleSelect =\n onSelectField ??\n ((field: string) => {\n ctx?.addColumnFilter(fieldType === \"input\" ? \"inputFields\" : \"outputFields\", field);\n });\n\n const handleAvailable =\n isFieldAvailable ??\n ((field: string) => {\n if (!ctx) return true;\n const map =\n fieldType === \"input\"\n ? (ctx as { pipeIdsByInputField?: Record<string, unknown[]> }).pipeIdsByInputField\n : pickOutputIndex(ctx);\n if (!map) return true;\n return !!map[field];\n });\n\n if (render) {\n return (\n <>\n {render({\n fields: resolvedFields,\n isOpen: open,\n setOpen,\n onSelect: (field: string) => {\n handleSelect(field);\n setOpen(false);\n },\n isFieldAvailable: handleAvailable,\n })}\n </>\n );\n }\n\n if (!resolvedFields.length) return null;\n const Icon = fieldType === \"input\" ? ListPlus : ListChecks;\n const text = label ?? (fieldType === \"input\" ? \"Show inputs\" : \"Show outputs\");\n return (\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger\n render={\n <CatalogCardBadge\n variant={variant}\n className={cn(\n \"pz:font-normal pz:text-muted-foreground pz:hover:text-foreground\",\n className,\n )}\n >\n <Icon className=\"pz:size-3\" />\n {text}\n </CatalogCardBadge>\n }\n />\n <PopoverContent align=\"start\" side=\"bottom\" className=\"pz:w-auto pz:min-w-40 pz:p-1\">\n <ul\n data-p0=\"catalog-card-field-badge-list\"\n className=\"pz:flex pz:flex-col pz:gap-0.5 pz:list-none pz:m-0 pz:p-0\"\n >\n {resolvedFields.map((field) => {\n const available = handleAvailable(field);\n return (\n <li key={field} className=\"pz:flex\">\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n handleSelect(field);\n setOpen(false);\n }}\n className={cn(\n \"pz:w-full pz:text-sm pz:text-left pz:py-1 pz:px-2 pz:rounded pz:flex pz:items-center pz:gap-2 pz:transition-all\",\n available\n ? \"pz:text-muted-foreground pz:hover:text-foreground pz:hover:bg-muted\"\n : \"pz:text-muted-foreground/50 pz:cursor-not-allowed\",\n )}\n data-available={available}\n >\n {fieldIcon?.(field)}\n {field}\n </button>\n </li>\n );\n })}\n </ul>\n </PopoverContent>\n </Popover>\n );\n}\n\nfunction deriveCardFields(card: AnyCardData | undefined, fieldType: \"input\" | \"output\"): string[] {\n if (!card) return [];\n if (fieldType === \"output\") {\n return (\"defaultOutputFields\" in card ? card.defaultOutputFields : []) ?? [];\n }\n if (\"defaultInputFields\" in card) {\n return card.defaultInputFields.map((f) => f.name);\n }\n return [];\n}\n\nfunction pickOutputIndex(ctx: unknown): Record<string, unknown[]> | undefined {\n const c = ctx as {\n pipeIdsByOutputField?: Record<string, unknown[]>;\n searchIdsByOutputField?: Record<string, unknown[]>;\n };\n return c.pipeIdsByOutputField ?? c.searchIdsByOutputField;\n}\n\n/* -------------------------------------------------------------------------- */\n/* Docs badge — external link to provider docs */\n/* -------------------------------------------------------------------------- */\n\nexport interface CatalogDocsBadgeProps {\n /** Base URL prepended to the card's docPath. */\n baseUrl?: string;\n /** Override the full URL (skips baseUrl + card.docPath composition). */\n href?: string;\n label?: ReactNode;\n className?: string;\n variant?: CatalogCardBadgeProps[\"variant\"];\n}\n\nexport function CatalogDocsBadge({\n baseUrl,\n href,\n label = \"Go to docs\",\n className,\n variant = \"outline\",\n}: CatalogDocsBadgeProps) {\n const card = useAnyCatalogCardOptional()?.card;\n const docPath = card && \"docPath\" in card ? card.docPath : undefined;\n const resolvedHref = href ?? (baseUrl && docPath ? `${baseUrl}${docPath}` : docPath);\n if (!resolvedHref) return null;\n return (\n <a target=\"_blank\" href={resolvedHref} rel=\"noreferrer\" onClick={(e) => e.stopPropagation()}>\n <CatalogCardBadge\n variant={variant}\n className={cn(\n \"pz:font-normal pz:text-muted-foreground pz:hover:text-foreground\",\n className,\n )}\n >\n <ExternalLink className=\"pz:size-3\" />\n {label}\n </CatalogCardBadge>\n </a>\n );\n}\n\n/* -------------------------------------------------------------------------- */\n/* Copy-id input — small input with a copy button */\n/* -------------------------------------------------------------------------- */\n\nexport interface CatalogCopyIdProps {\n /** Override the auto-bound id. Defaults to `card.pipeId` / `card.searchId`. */\n value?: string;\n className?: string;\n}\n\nexport function CatalogCopyId({ value, className }: CatalogCopyIdProps) {\n const { classNames } = useCatalogConfig();\n const card = useAnyCatalogCardOptional()?.card;\n const resolved = value ?? deriveCardId(card);\n const [copied, setCopied] = useState(false);\n\n if (!resolved) return null;\n\n const handleCopy = (e: React.MouseEvent) => {\n e.stopPropagation();\n e.preventDefault();\n void navigator.clipboard?.writeText(resolved).then(() => {\n setCopied(true);\n setTimeout(() => setCopied(false), 1500);\n });\n };\n\n return (\n <div\n data-p0=\"catalog-card-copy-id\"\n className={cn(\n \"pz:flex pz:items-center pz:gap-2 pz:rounded-md pz:border pz:border-input pz:bg-background pz:px-2 pz:py-1\",\n classNames?.copyId,\n className,\n )}\n onClick={(e) => e.stopPropagation()}\n >\n <code className=\"pz:flex-1 pz:text-xs pz:text-muted-foreground pz:truncate pz:font-mono\">\n {resolved}\n </code>\n <button\n type=\"button\"\n onClick={handleCopy}\n aria-label=\"Copy\"\n className=\"pz:inline-flex pz:items-center pz:justify-center pz:size-6 pz:rounded pz:text-muted-foreground pz:hover:text-foreground pz:hover:bg-muted pz:transition-all\"\n >\n {copied ? <Check className=\"pz:size-3\" /> : <Copy className=\"pz:size-3\" />}\n </button>\n </div>\n );\n}\n\nfunction deriveCardId(card: AnyCardData | undefined): string | undefined {\n if (!card) return undefined;\n if (\"pipeId\" in card) return card.pipeId;\n if (\"searchId\" in card) return card.searchId;\n if (\"effectId\" in card) return card.effectId;\n return undefined;\n}\n"],"mappings":"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"}
@@ -13,8 +13,8 @@ interface CatalogCardProps extends ComponentProps<"div"> {
13
13
  * consumers can override paddings/colors/borders via `classNames.card` or
14
14
  * `className` without fighting the cascade.
15
15
  *
16
- * Most consumers use `<PipeCatalogCard>` / `<SearchCatalogCard>` /
17
- * `<SearchesCatalogCard>` instead, which provides the card context for
16
+ * Most consumers use `<PipeCatalogCard>` / `<SearchCatalogCard>` instead,
17
+ * which provides the card context for
18
18
  * self-binding child primitives.
19
19
  */
20
20
  declare function CatalogCard({
@@ -13,8 +13,8 @@ import { jsx } from "react/jsx-runtime";
13
13
  * consumers can override paddings/colors/borders via `classNames.card` or
14
14
  * `className` without fighting the cascade.
15
15
  *
16
- * Most consumers use `<PipeCatalogCard>` / `<SearchCatalogCard>` /
17
- * `<SearchesCatalogCard>` instead, which provides the card context for
16
+ * Most consumers use `<PipeCatalogCard>` / `<SearchCatalogCard>` instead,
17
+ * which provides the card context for
18
18
  * self-binding child primitives.
19
19
  */
20
20
  function CatalogCard({ className, onClick, children, ...rest }) {
@@ -1 +1 @@
1
- {"version":3,"file":"card-primitives.mjs","names":[],"sources":["../../../../src/components/defaults/catalog/card-primitives.tsx"],"sourcesContent":["import { mergeProps } from \"@base-ui/react/merge-props\";\nimport { useRender } from \"@base-ui/react/use-render\";\nimport { Children, type ComponentProps, type MouseEvent } from \"react\";\nimport { useAnyCatalogCardOptional } from \"../../../context/catalog-card-context.js\";\nimport { useCatalogConfig } from \"../../../context/catalog-config-context.js\";\nimport { cn } from \"../../../lib/utils.js\";\nimport { Button } from \"../../ui/button.js\";\n\n/* -------------------------------------------------------------------------- */\n/* Card root */\n/* -------------------------------------------------------------------------- */\n\nexport interface CatalogCardProps extends ComponentProps<\"div\"> {\n onClick?: (e: MouseEvent<HTMLDivElement>) => void;\n}\n\n/**\n * Bare flat card container. Defaults are structural only (flex column) so\n * consumers can override paddings/colors/borders via `classNames.card` or\n * `className` without fighting the cascade.\n *\n * Most consumers use `<PipeCatalogCard>` / `<SearchCatalogCard>` /\n * `<SearchesCatalogCard>` instead, which provides the card context for\n * self-binding child primitives.\n */\nexport function CatalogCard({ className, onClick, children, ...rest }: CatalogCardProps) {\n const { classNames } = useCatalogConfig();\n const interactive = !!onClick;\n return (\n <div\n data-p0=\"catalog-card\"\n role={interactive ? \"button\" : undefined}\n tabIndex={interactive ? 0 : undefined}\n onClick={onClick}\n onKeyDown={\n interactive\n ? (e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onClick?.(e as unknown as MouseEvent<HTMLDivElement>);\n }\n }\n : undefined\n }\n className={cn(\"pz:flex pz:flex-col\", classNames?.card, className)}\n {...rest}\n >\n {children}\n </div>\n );\n}\n\n/* -------------------------------------------------------------------------- */\n/* Card header */\n/* -------------------------------------------------------------------------- */\n\nexport type CatalogCardHeaderState = {};\n\nexport interface CatalogCardHeaderProps\n extends useRender.ComponentProps<\"div\", CatalogCardHeaderState> {}\n\nexport function CatalogCardHeader({ render, className, ...props }: CatalogCardHeaderProps) {\n const { classNames } = useCatalogConfig();\n return useRender({\n defaultTagName: \"div\",\n render,\n state: {} as CatalogCardHeaderState,\n props: mergeProps<\"div\">(\n {\n className: cn(\"pz:flex pz:items-start pz:gap-2\", classNames?.cardHeader, className),\n ...({ \"data-p0\": \"catalog-card-header\" } as Record<string, string>),\n },\n props,\n ),\n });\n}\n\n/* -------------------------------------------------------------------------- */\n/* Card title — self-binds to card.label */\n/* -------------------------------------------------------------------------- */\n\nexport interface CatalogCardTitleState {\n label: string;\n}\n\nexport interface CatalogCardTitleProps\n extends useRender.ComponentProps<\"h3\", CatalogCardTitleState> {}\n\nexport function CatalogCardTitle({ children, render, className, ...props }: CatalogCardTitleProps) {\n const { classNames } = useCatalogConfig();\n const card = useAnyCatalogCardOptional()?.card;\n const label = (card?.label ?? \"\") as string;\n return useRender({\n defaultTagName: \"h3\",\n render,\n state: { label },\n props: mergeProps<\"h3\">(\n {\n className: cn(\n \"pz:text-sm pz:font-semibold pz:leading-tight pz:m-0 pz:line-clamp-2 pz:flex-1\",\n classNames?.cardLabel,\n className,\n ),\n children: children ?? label,\n ...({ \"data-p0\": \"catalog-card-title\" } as Record<string, string>),\n },\n props,\n ),\n });\n}\n\n/* -------------------------------------------------------------------------- */\n/* Card description — self-binds to card.description */\n/* -------------------------------------------------------------------------- */\n\nexport interface CatalogCardDescriptionState {\n description: string;\n}\n\nexport interface CatalogCardDescriptionProps\n extends useRender.ComponentProps<\"p\", CatalogCardDescriptionState> {}\n\nexport function CatalogCardDescription({\n children,\n render,\n className,\n ...props\n}: CatalogCardDescriptionProps) {\n const { classNames } = useCatalogConfig();\n const card = useAnyCatalogCardOptional()?.card;\n const description = (card?.description ?? \"\") as string;\n return useRender({\n defaultTagName: \"p\",\n render,\n state: { description },\n props: mergeProps<\"p\">(\n {\n className: cn(\n \"pz:text-xs pz:text-muted-foreground pz:m-0 pz:line-clamp-2\",\n classNames?.cardDescription,\n className,\n ),\n children: children ?? description,\n ...({ \"data-p0\": \"catalog-card-description\" } as Record<string, string>),\n },\n props,\n ),\n });\n}\n\n/* -------------------------------------------------------------------------- */\n/* Card badges row + single badge button */\n/* -------------------------------------------------------------------------- */\n\nexport interface CatalogCardBadgesProps extends ComponentProps<\"div\"> {}\n\nexport function CatalogCardBadges({ className, children, ...rest }: CatalogCardBadgesProps) {\n const { classNames } = useCatalogConfig();\n const visible = Children.toArray(children);\n if (visible.length === 0) return null;\n return (\n <div\n data-p0=\"catalog-card-badges\"\n className={cn(\n \"pz:flex pz:flex-wrap pz:gap-1.5 pz:items-center\",\n classNames?.cardBadges,\n className,\n )}\n onClick={(e) => e.stopPropagation()}\n {...rest}\n >\n {visible}\n </div>\n );\n}\n\nexport interface CatalogCardBadgeProps extends Omit<ComponentProps<typeof Button>, \"size\"> {\n size?: \"xs\" | \"sm\";\n}\n\nexport function CatalogCardBadge({\n className,\n variant = \"outline\",\n size = \"xs\",\n onClick,\n ...rest\n}: CatalogCardBadgeProps) {\n const { classNames } = useCatalogConfig();\n return (\n <Button\n data-p0=\"catalog-card-badge\"\n variant={variant}\n size={size}\n className={cn(classNames?.badge, className)}\n onClick={(e) => {\n e.stopPropagation();\n onClick?.(e);\n }}\n {...rest}\n />\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAyBA,SAAgB,YAAY,EAAE,WAAW,SAAS,UAAU,GAAG,QAA0B;CACvF,MAAM,EAAE,eAAe,kBAAkB;CACzC,MAAM,cAAc,CAAC,CAAC;AACtB,QACE,oBAAC,OAAD;EACE,WAAQ;EACR,MAAM,cAAc,WAAW;EAC/B,UAAU,cAAc,IAAI;EACnB;EACT,WACE,eACK,MAAM;AACL,OAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;AACtC,MAAE,gBAAgB;AAClB,cAAU,EAA2C;;MAGzD;EAEN,WAAW,GAAG,uBAAuB,YAAY,MAAM,UAAU;EACjE,GAAI;EAEH;EACG;;AAaV,SAAgB,kBAAkB,EAAE,QAAQ,WAAW,GAAG,SAAiC;CACzF,MAAM,EAAE,eAAe,kBAAkB;AACzC,QAAO,UAAU;EACf,gBAAgB;EAChB;EACA,OAAO,EAAE;EACT,OAAO,WACL;GACE,WAAW,GAAG,mCAAmC,YAAY,YAAY,UAAU;GAC7E,WAAW;GAClB,EACD,MACD;EACF,CAAC;;AAcJ,SAAgB,iBAAiB,EAAE,UAAU,QAAQ,WAAW,GAAG,SAAgC;CACjG,MAAM,EAAE,eAAe,kBAAkB;CAEzC,MAAM,SADO,2BAA2B,EAAE,OACrB,SAAS;AAC9B,QAAO,UAAU;EACf,gBAAgB;EAChB;EACA,OAAO,EAAE,OAAO;EAChB,OAAO,WACL;GACE,WAAW,GACT,iFACA,YAAY,WACZ,UACD;GACD,UAAU,YAAY;GAChB,WAAW;GAClB,EACD,MACD;EACF,CAAC;;AAcJ,SAAgB,uBAAuB,EACrC,UACA,QACA,WACA,GAAG,SAC2B;CAC9B,MAAM,EAAE,eAAe,kBAAkB;CAEzC,MAAM,eADO,2BAA2B,EAAE,OACf,eAAe;AAC1C,QAAO,UAAU;EACf,gBAAgB;EAChB;EACA,OAAO,EAAE,aAAa;EACtB,OAAO,WACL;GACE,WAAW,GACT,8DACA,YAAY,iBACZ,UACD;GACD,UAAU,YAAY;GAChB,WAAW;GAClB,EACD,MACD;EACF,CAAC;;AASJ,SAAgB,kBAAkB,EAAE,WAAW,UAAU,GAAG,QAAgC;CAC1F,MAAM,EAAE,eAAe,kBAAkB;CACzC,MAAM,UAAU,SAAS,QAAQ,SAAS;AAC1C,KAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,QACE,oBAAC,OAAD;EACE,WAAQ;EACR,WAAW,GACT,mDACA,YAAY,YACZ,UACD;EACD,UAAU,MAAM,EAAE,iBAAiB;EACnC,GAAI;YAEH;EACG;;AAQV,SAAgB,iBAAiB,EAC/B,WACA,UAAU,WACV,OAAO,MACP,SACA,GAAG,QACqB;CACxB,MAAM,EAAE,eAAe,kBAAkB;AACzC,QACE,oBAAC,QAAD;EACE,WAAQ;EACC;EACH;EACN,WAAW,GAAG,YAAY,OAAO,UAAU;EAC3C,UAAU,MAAM;AACd,KAAE,iBAAiB;AACnB,aAAU,EAAE;;EAEd,GAAI;EACJ"}
1
+ {"version":3,"file":"card-primitives.mjs","names":[],"sources":["../../../../src/components/defaults/catalog/card-primitives.tsx"],"sourcesContent":["import { mergeProps } from \"@base-ui/react/merge-props\";\nimport { useRender } from \"@base-ui/react/use-render\";\nimport { Children, type ComponentProps, type MouseEvent } from \"react\";\nimport { useAnyCatalogCardOptional } from \"../../../context/catalog-card-context.js\";\nimport { useCatalogConfig } from \"../../../context/catalog-config-context.js\";\nimport { cn } from \"../../../lib/utils.js\";\nimport { Button } from \"../../ui/button.js\";\n\n/* -------------------------------------------------------------------------- */\n/* Card root */\n/* -------------------------------------------------------------------------- */\n\nexport interface CatalogCardProps extends ComponentProps<\"div\"> {\n onClick?: (e: MouseEvent<HTMLDivElement>) => void;\n}\n\n/**\n * Bare flat card container. Defaults are structural only (flex column) so\n * consumers can override paddings/colors/borders via `classNames.card` or\n * `className` without fighting the cascade.\n *\n * Most consumers use `<PipeCatalogCard>` / `<SearchCatalogCard>` instead,\n * which provides the card context for\n * self-binding child primitives.\n */\nexport function CatalogCard({ className, onClick, children, ...rest }: CatalogCardProps) {\n const { classNames } = useCatalogConfig();\n const interactive = !!onClick;\n return (\n <div\n data-p0=\"catalog-card\"\n role={interactive ? \"button\" : undefined}\n tabIndex={interactive ? 0 : undefined}\n onClick={onClick}\n onKeyDown={\n interactive\n ? (e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n onClick?.(e as unknown as MouseEvent<HTMLDivElement>);\n }\n }\n : undefined\n }\n className={cn(\"pz:flex pz:flex-col\", classNames?.card, className)}\n {...rest}\n >\n {children}\n </div>\n );\n}\n\n/* -------------------------------------------------------------------------- */\n/* Card header */\n/* -------------------------------------------------------------------------- */\n\nexport type CatalogCardHeaderState = {};\n\nexport interface CatalogCardHeaderProps\n extends useRender.ComponentProps<\"div\", CatalogCardHeaderState> {}\n\nexport function CatalogCardHeader({ render, className, ...props }: CatalogCardHeaderProps) {\n const { classNames } = useCatalogConfig();\n return useRender({\n defaultTagName: \"div\",\n render,\n state: {} as CatalogCardHeaderState,\n props: mergeProps<\"div\">(\n {\n className: cn(\"pz:flex pz:items-start pz:gap-2\", classNames?.cardHeader, className),\n ...({ \"data-p0\": \"catalog-card-header\" } as Record<string, string>),\n },\n props,\n ),\n });\n}\n\n/* -------------------------------------------------------------------------- */\n/* Card title — self-binds to card.label */\n/* -------------------------------------------------------------------------- */\n\nexport interface CatalogCardTitleState {\n label: string;\n}\n\nexport interface CatalogCardTitleProps\n extends useRender.ComponentProps<\"h3\", CatalogCardTitleState> {}\n\nexport function CatalogCardTitle({ children, render, className, ...props }: CatalogCardTitleProps) {\n const { classNames } = useCatalogConfig();\n const card = useAnyCatalogCardOptional()?.card;\n const label = (card?.label ?? \"\") as string;\n return useRender({\n defaultTagName: \"h3\",\n render,\n state: { label },\n props: mergeProps<\"h3\">(\n {\n className: cn(\n \"pz:text-sm pz:font-semibold pz:leading-tight pz:m-0 pz:line-clamp-2 pz:flex-1\",\n classNames?.cardLabel,\n className,\n ),\n children: children ?? label,\n ...({ \"data-p0\": \"catalog-card-title\" } as Record<string, string>),\n },\n props,\n ),\n });\n}\n\n/* -------------------------------------------------------------------------- */\n/* Card description — self-binds to card.description */\n/* -------------------------------------------------------------------------- */\n\nexport interface CatalogCardDescriptionState {\n description: string;\n}\n\nexport interface CatalogCardDescriptionProps\n extends useRender.ComponentProps<\"p\", CatalogCardDescriptionState> {}\n\nexport function CatalogCardDescription({\n children,\n render,\n className,\n ...props\n}: CatalogCardDescriptionProps) {\n const { classNames } = useCatalogConfig();\n const card = useAnyCatalogCardOptional()?.card;\n const description = (card?.description ?? \"\") as string;\n return useRender({\n defaultTagName: \"p\",\n render,\n state: { description },\n props: mergeProps<\"p\">(\n {\n className: cn(\n \"pz:text-xs pz:text-muted-foreground pz:m-0 pz:line-clamp-2\",\n classNames?.cardDescription,\n className,\n ),\n children: children ?? description,\n ...({ \"data-p0\": \"catalog-card-description\" } as Record<string, string>),\n },\n props,\n ),\n });\n}\n\n/* -------------------------------------------------------------------------- */\n/* Card badges row + single badge button */\n/* -------------------------------------------------------------------------- */\n\nexport interface CatalogCardBadgesProps extends ComponentProps<\"div\"> {}\n\nexport function CatalogCardBadges({ className, children, ...rest }: CatalogCardBadgesProps) {\n const { classNames } = useCatalogConfig();\n const visible = Children.toArray(children);\n if (visible.length === 0) return null;\n return (\n <div\n data-p0=\"catalog-card-badges\"\n className={cn(\n \"pz:flex pz:flex-wrap pz:gap-1.5 pz:items-center\",\n classNames?.cardBadges,\n className,\n )}\n onClick={(e) => e.stopPropagation()}\n {...rest}\n >\n {visible}\n </div>\n );\n}\n\nexport interface CatalogCardBadgeProps extends Omit<ComponentProps<typeof Button>, \"size\"> {\n size?: \"xs\" | \"sm\";\n}\n\nexport function CatalogCardBadge({\n className,\n variant = \"outline\",\n size = \"xs\",\n onClick,\n ...rest\n}: CatalogCardBadgeProps) {\n const { classNames } = useCatalogConfig();\n return (\n <Button\n data-p0=\"catalog-card-badge\"\n variant={variant}\n size={size}\n className={cn(classNames?.badge, className)}\n onClick={(e) => {\n e.stopPropagation();\n onClick?.(e);\n }}\n {...rest}\n />\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAyBA,SAAgB,YAAY,EAAE,WAAW,SAAS,UAAU,GAAG,QAA0B;CACvF,MAAM,EAAE,eAAe,kBAAkB;CACzC,MAAM,cAAc,CAAC,CAAC;AACtB,QACE,oBAAC,OAAD;EACE,WAAQ;EACR,MAAM,cAAc,WAAW;EAC/B,UAAU,cAAc,IAAI;EACnB;EACT,WACE,eACK,MAAM;AACL,OAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;AACtC,MAAE,gBAAgB;AAClB,cAAU,EAA2C;;MAGzD;EAEN,WAAW,GAAG,uBAAuB,YAAY,MAAM,UAAU;EACjE,GAAI;EAEH;EACG;;AAaV,SAAgB,kBAAkB,EAAE,QAAQ,WAAW,GAAG,SAAiC;CACzF,MAAM,EAAE,eAAe,kBAAkB;AACzC,QAAO,UAAU;EACf,gBAAgB;EAChB;EACA,OAAO,EAAE;EACT,OAAO,WACL;GACE,WAAW,GAAG,mCAAmC,YAAY,YAAY,UAAU;GAC7E,WAAW;GAClB,EACD,MACD;EACF,CAAC;;AAcJ,SAAgB,iBAAiB,EAAE,UAAU,QAAQ,WAAW,GAAG,SAAgC;CACjG,MAAM,EAAE,eAAe,kBAAkB;CAEzC,MAAM,SADO,2BAA2B,EAAE,OACrB,SAAS;AAC9B,QAAO,UAAU;EACf,gBAAgB;EAChB;EACA,OAAO,EAAE,OAAO;EAChB,OAAO,WACL;GACE,WAAW,GACT,iFACA,YAAY,WACZ,UACD;GACD,UAAU,YAAY;GAChB,WAAW;GAClB,EACD,MACD;EACF,CAAC;;AAcJ,SAAgB,uBAAuB,EACrC,UACA,QACA,WACA,GAAG,SAC2B;CAC9B,MAAM,EAAE,eAAe,kBAAkB;CAEzC,MAAM,eADO,2BAA2B,EAAE,OACf,eAAe;AAC1C,QAAO,UAAU;EACf,gBAAgB;EAChB;EACA,OAAO,EAAE,aAAa;EACtB,OAAO,WACL;GACE,WAAW,GACT,8DACA,YAAY,iBACZ,UACD;GACD,UAAU,YAAY;GAChB,WAAW;GAClB,EACD,MACD;EACF,CAAC;;AASJ,SAAgB,kBAAkB,EAAE,WAAW,UAAU,GAAG,QAAgC;CAC1F,MAAM,EAAE,eAAe,kBAAkB;CACzC,MAAM,UAAU,SAAS,QAAQ,SAAS;AAC1C,KAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,QACE,oBAAC,OAAD;EACE,WAAQ;EACR,WAAW,GACT,mDACA,YAAY,YACZ,UACD;EACD,UAAU,MAAM,EAAE,iBAAiB;EACnC,GAAI;YAEH;EACG;;AAQV,SAAgB,iBAAiB,EAC/B,WACA,UAAU,WACV,OAAO,MACP,SACA,GAAG,QACqB;CACxB,MAAM,EAAE,eAAe,kBAAkB;AACzC,QACE,oBAAC,QAAD;EACE,WAAQ;EACC;EACH;EACN,WAAW,GAAG,YAAY,OAAO,UAAU;EAC3C,UAAU,MAAM;AACd,KAAE,iBAAiB;AACnB,aAAU,EAAE;;EAEd,GAAI;EACJ"}
@@ -4,6 +4,7 @@ import { Switch } from "../../ui/switch.mjs";
4
4
  import { useFloatingElement } from "../../../hooks/use-floating-element.mjs";
5
5
  import { useEffect, useId, useMemo, useRef, useState } from "react";
6
6
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
7
+ import { TYPES_TO_FORMATS } from "@pipe0/base";
7
8
  import { Trash2 } from "lucide-react";
8
9
  import { offset, shift } from "@floating-ui/react";
9
10
 
@@ -11,14 +12,43 @@ import { offset, shift } from "@floating-ui/react";
11
12
  const SIMPLE_FIELD_RE = /^\{\{\s*([a-zA-Z_][a-zA-Z0-9_.]*)\s*(\|\s*default:\s*"")?\s*\}\}$/;
12
13
  const SECRET_RE = /^\{\{\s*SECRETS\.([A-Z][A-Z0-9_]*)\s*\}\}$/;
13
14
  const CONSTANT_RE = /^\{\{\s*CONSTANTS\.([A-Z][A-Z0-9_]*)\s*\}\}$/;
14
- const OUTPUT_BLOCK_RE = /^\{%\s*output\s+([A-Za-z_][A-Za-z0-9_]*)\s*,\s*type:\s*"(string|number|boolean|json|unknown)"\s*(?:,\s*schema:\s*"([^"]*)")?\s*(?:,\s*description:\s*"((?:[^"\\]|\\.)*)")?\s*%\}$/;
15
+ const OUTPUT_BLOCK_RE = /^\{%\s*output\s+([A-Za-z_][A-Za-z0-9_]*)\s*((?:,\s*[a-z_]+:\s*(?:"(?:[^"\\]|\\.)*"|true|false)\s*)*)%\}$/;
16
+ const OUTPUT_ARG_RE = /([a-z_]+):\s*("(?:[^"\\]|\\.)*"|true|false)/g;
17
+ const OUTPUT_KEYS = new Set([
18
+ "type",
19
+ "schema",
20
+ "description",
21
+ "format",
22
+ "required"
23
+ ]);
24
+ function parseOutputBlock(raw) {
25
+ const m = raw.match(OUTPUT_BLOCK_RE);
26
+ if (!m) return null;
27
+ const args = {};
28
+ for (const [, key, value] of (m[2] ?? "").matchAll(OUTPUT_ARG_RE)) {
29
+ if (!key || !value || !OUTPUT_KEYS.has(key)) return null;
30
+ args[key] = value === "true" || value === "false" ? value === "true" : value.slice(1, -1).replace(/\\"/g, "\"").replace(/\\\\/g, "\\");
31
+ }
32
+ const type = args.type;
33
+ if (typeof type !== "string" || !(type in TYPES_TO_FORMATS)) return null;
34
+ const format = args.format;
35
+ if (typeof format === "string" && type !== "json" && !TYPES_TO_FORMATS[type].includes(format)) return null;
36
+ return {
37
+ name: m[1] ?? "",
38
+ type,
39
+ schema: typeof args.schema === "string" ? args.schema : "",
40
+ description: typeof args.description === "string" ? args.description : "",
41
+ format: typeof args.format === "string" ? args.format : "",
42
+ required: typeof args.required === "boolean" ? args.required : void 0
43
+ };
44
+ }
15
45
  /**
16
46
  * Contextual popover anchored to a chip's DOM rect. Different content per
17
47
  * chip kind:
18
48
  * - field: switch for `| default: ""` (simple cases only), remove.
19
49
  * - secret: publicId header, manage/remove buttons. Power users still
20
50
  * edit by hand.
21
- * - block (output declaration): name / type / description editors.
51
+ * - block (output declaration): name / type / format / description editors.
22
52
  *
23
53
  * On any mutation, the popover dispatches a single replaceWith transaction
24
54
  * over the chip's range, then closes itself. The Liquid serialization
@@ -196,26 +226,19 @@ function ConstantChipBody({ raw, remove }) {
196
226
  })] });
197
227
  }
198
228
  function BlockChipBody({ raw, replaceWith, remove }) {
199
- const initial = useMemo(() => {
200
- const m = raw.match(OUTPUT_BLOCK_RE);
201
- if (!m) return null;
202
- const [, name, type, schema, description] = m;
203
- return {
204
- name,
205
- type,
206
- schema: schema ?? "",
207
- description: description ? description.replace(/\\"/g, "\"").replace(/\\\\/g, "\\") : ""
208
- };
209
- }, [raw]);
229
+ const initial = useMemo(() => parseOutputBlock(raw), [raw]);
210
230
  const [name, setName] = useState(initial?.name ?? "");
211
231
  const [type, setType] = useState(initial?.type ?? "string");
212
232
  const [schema, setSchema] = useState(initial?.schema ?? "");
213
233
  const [description, setDescription] = useState(initial?.description ?? "");
234
+ const [format, setFormat] = useState(initial?.format ?? "");
235
+ const formatOptions = TYPES_TO_FORMATS[type];
214
236
  const idPrefix = useId();
215
237
  const nameId = `${idPrefix}-name`;
216
238
  const typeId = `${idPrefix}-type`;
217
239
  const schemaId = `${idPrefix}-schema`;
218
240
  const descId = `${idPrefix}-desc`;
241
+ const formatId = `${idPrefix}-format`;
219
242
  if (!initial) return /* @__PURE__ */ jsxs(Fragment$1, { children: [
220
243
  /* @__PURE__ */ jsx("header", {
221
244
  className: "pz:text-xs pz:font-medium pz:text-muted-foreground",
@@ -242,7 +265,9 @@ function BlockChipBody({ raw, replaceWith, remove }) {
242
265
  const escaped = description.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
243
266
  const parts = [`{% output ${name.trim()}`, `type: "${type}"`];
244
267
  if (type === "json" && schema.trim()) parts.push(`schema: "${schema.trim()}"`);
268
+ if (format && formatOptions.includes(format)) parts.push(`format: "${format}"`);
245
269
  parts.push(`description: "${escaped}"`);
270
+ if (initial?.required !== void 0) parts.push(`required: ${initial.required}`);
246
271
  replaceWith(`${parts.join(", ")} %}`);
247
272
  }
248
273
  return /* @__PURE__ */ jsxs(Fragment$1, { children: [
@@ -266,7 +291,11 @@ function BlockChipBody({ raw, replaceWith, remove }) {
266
291
  children: [/* @__PURE__ */ jsx("span", { children: "Type" }), /* @__PURE__ */ jsxs("select", {
267
292
  id: typeId,
268
293
  value: type,
269
- onChange: (e) => setType(e.target.value),
294
+ onChange: (e) => {
295
+ const next = e.target.value;
296
+ setType(next);
297
+ if (!TYPES_TO_FORMATS[next].includes(format)) setFormat("");
298
+ },
270
299
  className: "pz:rounded-sm pz:border pz:border-input pz:bg-transparent pz:px-2 pz:py-1 pz:text-sm",
271
300
  children: [
272
301
  /* @__PURE__ */ jsx("option", {
@@ -302,6 +331,23 @@ function BlockChipBody({ raw, replaceWith, remove }) {
302
331
  placeholder: "SCHEMA_NAME"
303
332
  })]
304
333
  }),
334
+ type !== "json" && formatOptions.length > 0 && /* @__PURE__ */ jsxs("label", {
335
+ htmlFor: formatId,
336
+ className: "pz:flex pz:flex-col pz:gap-1 pz:text-xs",
337
+ children: [/* @__PURE__ */ jsx("span", { children: "Format" }), /* @__PURE__ */ jsxs("select", {
338
+ id: formatId,
339
+ value: format,
340
+ onChange: (e) => setFormat(e.target.value),
341
+ className: "pz:rounded-sm pz:border pz:border-input pz:bg-transparent pz:px-2 pz:py-1 pz:text-sm",
342
+ children: [/* @__PURE__ */ jsx("option", {
343
+ value: "",
344
+ children: "none"
345
+ }), formatOptions.map((f) => /* @__PURE__ */ jsx("option", {
346
+ value: f,
347
+ children: f
348
+ }, f))]
349
+ })]
350
+ }),
305
351
  /* @__PURE__ */ jsxs("label", {
306
352
  htmlFor: descId,
307
353
  className: "pz:flex pz:flex-col pz:gap-1 pz:text-xs",
@@ -1 +1 @@
1
- {"version":3,"file":"ChipEditPopover.mjs","names":[],"sources":["../../../../src/components/internal/LiquidEditor/ChipEditPopover.tsx"],"sourcesContent":["import { offset, shift } from \"@floating-ui/react\";\nimport type { Editor } from \"@tiptap/react\";\nimport { Trash2 } from \"lucide-react\";\nimport { useEffect, useId, useMemo, useRef, useState } from \"react\";\nimport { useFloatingElement } from \"../../../hooks/use-floating-element.js\";\nimport { Button } from \"../../ui/button.js\";\nimport { Input } from \"../../ui/input.js\";\nimport { Switch } from \"../../ui/switch.js\";\nimport type { ChipKind } from \"../tag-chip-decoration.js\";\n\nconst SIMPLE_FIELD_RE = /^\\{\\{\\s*([a-zA-Z_][a-zA-Z0-9_.]*)\\s*(\\|\\s*default:\\s*\"\")?\\s*\\}\\}$/;\nconst SECRET_RE = /^\\{\\{\\s*SECRETS\\.([A-Z][A-Z0-9_]*)\\s*\\}\\}$/;\nconst CONSTANT_RE = /^\\{\\{\\s*CONSTANTS\\.([A-Z][A-Z0-9_]*)\\s*\\}\\}$/;\n// Captures `name`, `type` (string|number|boolean|json|unknown), and `description`\n// from `{% output NAME, type: \"TYPE\", description: \"...\" %}` or with a `schema:`\n// arg between type and description for json. Tolerates whitespace and ordering.\nconst OUTPUT_BLOCK_RE =\n /^\\{%\\s*output\\s+([A-Za-z_][A-Za-z0-9_]*)\\s*,\\s*type:\\s*\"(string|number|boolean|json|unknown)\"\\s*(?:,\\s*schema:\\s*\"([^\"]*)\")?\\s*(?:,\\s*description:\\s*\"((?:[^\"\\\\]|\\\\.)*)\")?\\s*%\\}$/;\n\nexport interface ChipEditTarget {\n kind: ChipKind;\n raw: string;\n from: number;\n to: number;\n rect: DOMRect;\n}\n\n/**\n * Contextual popover anchored to a chip's DOM rect. Different content per\n * chip kind:\n * - field: switch for `| default: \"\"` (simple cases only), remove.\n * - secret: publicId header, manage/remove buttons. Power users still\n * edit by hand.\n * - block (output declaration): name / type / description editors.\n *\n * On any mutation, the popover dispatches a single replaceWith transaction\n * over the chip's range, then closes itself. The Liquid serialization\n * stays identical to what would have been authored by hand.\n */\nexport function ChipEditPopover({\n editor,\n target,\n onClose,\n}: {\n editor: Editor;\n target: ChipEditTarget;\n onClose: () => void;\n}) {\n const { ref, style, isMounted, getFloatingProps } = useFloatingElement(true, target.rect, 1100, {\n placement: \"bottom-start\",\n middleware: [offset(6), shift()],\n onOpenChange(open) {\n if (!open) onClose();\n },\n dismissOptions: { outsidePress: true, outsidePressEvent: \"mousedown\" },\n });\n\n const popupRef = useRef<HTMLDivElement | null>(null);\n\n useEffect(() => {\n function onKey(e: KeyboardEvent) {\n if (e.key === \"Escape\") onClose();\n }\n window.addEventListener(\"keydown\", onKey);\n return () => window.removeEventListener(\"keydown\", onKey);\n }, [onClose]);\n\n function replaceWith(next: string) {\n editor.chain().focus().insertContentAt({ from: target.from, to: target.to }, next).run();\n onClose();\n }\n\n function remove() {\n editor.chain().focus().deleteRange({ from: target.from, to: target.to }).run();\n onClose();\n }\n\n if (!isMounted) return null;\n\n return (\n <div\n ref={(el) => {\n popupRef.current = el;\n ref(el);\n }}\n style={style}\n {...getFloatingProps()}\n onMouseDown={(e) => e.stopPropagation()}\n className=\"pz:flex pz:flex-col pz:gap-2 pz:rounded-md pz:border pz:border-input pz:bg-popover pz:p-3 pz:text-popover-foreground pz:shadow-md pz:min-w-72\"\n role=\"dialog\"\n aria-label={`Edit ${target.kind} chip`}\n >\n {target.kind === \"field\" && (\n <FieldChipBody raw={target.raw} replaceWith={replaceWith} remove={remove} />\n )}\n {target.kind === \"secret\" && <SecretChipBody raw={target.raw} remove={remove} />}\n {target.kind === \"constant\" && <ConstantChipBody raw={target.raw} remove={remove} />}\n {target.kind === \"block\" && (\n <BlockChipBody raw={target.raw} replaceWith={replaceWith} remove={remove} />\n )}\n </div>\n );\n}\n\nfunction FieldChipBody({\n raw,\n replaceWith,\n remove,\n}: {\n raw: string;\n replaceWith: (next: string) => void;\n remove: () => void;\n}) {\n const match = raw.match(SIMPLE_FIELD_RE);\n const name = match?.[1];\n const allowEmpty = !!match?.[2];\n const isSimple = !!match;\n\n if (!isSimple || !name) {\n return (\n <>\n <header className=\"pz:text-xs pz:font-medium pz:text-muted-foreground\">\n Field reference (advanced)\n </header>\n <p className=\"pz:text-xs pz:text-muted-foreground\">\n This chip uses a custom Liquid filter chain. Edit the raw text in the editor to change it.\n </p>\n <pre className=\"pz:overflow-x-auto pz:rounded-sm pz:bg-muted pz:px-2 pz:py-1 pz:text-xs\">\n {raw}\n </pre>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={remove}>\n <Trash2 className=\"pz:size-3.5 pz:mr-1\" />\n Remove\n </Button>\n </>\n );\n }\n\n function toggleAllowEmpty() {\n replaceWith(allowEmpty ? `{{ ${name} }}` : `{{ ${name} | default: \"\" }}`);\n }\n\n return (\n <>\n <header className=\"pz:flex pz:items-center pz:justify-between pz:gap-2\">\n <span className=\"pz:text-xs pz:font-medium pz:text-muted-foreground\">Field reference</span>\n <code className=\"pz:text-xs pz:text-sky-700\">{name}</code>\n </header>\n <div className=\"pz:flex pz:items-center pz:justify-between pz:gap-3 pz:text-sm\">\n <span className=\"pz:flex pz:flex-col\">\n <span>Allow empty</span>\n <span className=\"pz:text-xs pz:text-muted-foreground\">\n Inserts <code>| default: \"\"</code> so missing values render as empty.\n </span>\n </span>\n <Switch checked={allowEmpty} onCheckedChange={toggleAllowEmpty} />\n </div>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={remove}>\n <Trash2 className=\"pz:size-3.5 pz:mr-1\" />\n Remove\n </Button>\n </>\n );\n}\n\nfunction SecretChipBody({ raw, remove }: { raw: string; remove: () => void }) {\n const publicId = raw.match(SECRET_RE)?.[1];\n\n return (\n <>\n <header className=\"pz:flex pz:items-center pz:justify-between pz:gap-2\">\n <span className=\"pz:text-xs pz:font-medium pz:text-muted-foreground\">Secret reference</span>\n <code className=\"pz:text-xs pz:text-amber-700\">{publicId ?? \"(unknown)\"}</code>\n </header>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={remove}>\n <Trash2 className=\"pz:size-3.5 pz:mr-1\" />\n Remove\n </Button>\n </>\n );\n}\n\nfunction ConstantChipBody({ raw, remove }: { raw: string; remove: () => void }) {\n const publicId = raw.match(CONSTANT_RE)?.[1];\n\n return (\n <>\n <header className=\"pz:flex pz:items-center pz:justify-between pz:gap-2\">\n <span className=\"pz:text-xs pz:font-medium pz:text-muted-foreground\">\n Constant reference\n </span>\n <code className=\"pz:text-xs pz:text-emerald-700\">{publicId ?? \"(unknown)\"}</code>\n </header>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={remove}>\n <Trash2 className=\"pz:size-3.5 pz:mr-1\" />\n Remove\n </Button>\n </>\n );\n}\n\nfunction BlockChipBody({\n raw,\n replaceWith,\n remove,\n}: {\n raw: string;\n replaceWith: (next: string) => void;\n remove: () => void;\n}) {\n const initial = useMemo(() => {\n const m = raw.match(OUTPUT_BLOCK_RE);\n if (!m) return null;\n const [, name, type, schema, description] = m;\n return {\n name,\n type: type as \"string\" | \"number\" | \"boolean\" | \"json\" | \"unknown\",\n schema: schema ?? \"\",\n description: description ? description.replace(/\\\\\"/g, '\"').replace(/\\\\\\\\/g, \"\\\\\") : \"\",\n };\n }, [raw]);\n\n const [name, setName] = useState(initial?.name ?? \"\");\n const [type, setType] = useState<\"string\" | \"number\" | \"boolean\" | \"json\" | \"unknown\">(\n initial?.type ?? \"string\",\n );\n const [schema, setSchema] = useState(initial?.schema ?? \"\");\n const [description, setDescription] = useState(initial?.description ?? \"\");\n const idPrefix = useId();\n const nameId = `${idPrefix}-name`;\n const typeId = `${idPrefix}-type`;\n const schemaId = `${idPrefix}-schema`;\n const descId = `${idPrefix}-desc`;\n\n if (!initial) {\n return (\n <>\n <header className=\"pz:text-xs pz:font-medium pz:text-muted-foreground\">\n Block (advanced)\n </header>\n <p className=\"pz:text-xs pz:text-muted-foreground\">\n This block uses a non-standard form. Edit the raw text in the editor.\n </p>\n <pre className=\"pz:overflow-x-auto pz:rounded-sm pz:bg-muted pz:px-2 pz:py-1 pz:text-xs\">\n {raw}\n </pre>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={remove}>\n <Trash2 className=\"pz:size-3.5 pz:mr-1\" />\n Remove\n </Button>\n </>\n );\n }\n\n function save() {\n if (!name.trim()) return;\n const escaped = description.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n const parts = [`{% output ${name.trim()}`, `type: \"${type}\"`];\n if (type === \"json\" && schema.trim()) parts.push(`schema: \"${schema.trim()}\"`);\n parts.push(`description: \"${escaped}\"`);\n replaceWith(`${parts.join(\", \")} %}`);\n }\n\n return (\n <>\n <header className=\"pz:text-xs pz:font-medium pz:text-muted-foreground\">\n Output declaration\n </header>\n <label htmlFor={nameId} className=\"pz:flex pz:flex-col pz:gap-1 pz:text-xs\">\n <span>Name</span>\n <Input\n id={nameId}\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder=\"FIELD_NAME\"\n />\n </label>\n <label htmlFor={typeId} className=\"pz:flex pz:flex-col pz:gap-1 pz:text-xs\">\n <span>Type</span>\n <select\n id={typeId}\n value={type}\n onChange={(e) =>\n setType(e.target.value as \"string\" | \"number\" | \"boolean\" | \"json\" | \"unknown\")\n }\n className=\"pz:rounded-sm pz:border pz:border-input pz:bg-transparent pz:px-2 pz:py-1 pz:text-sm\"\n >\n <option value=\"string\">string</option>\n <option value=\"number\">number</option>\n <option value=\"boolean\">boolean</option>\n <option value=\"json\">json</option>\n <option value=\"unknown\">unknown</option>\n </select>\n </label>\n {type === \"json\" && (\n <label htmlFor={schemaId} className=\"pz:flex pz:flex-col pz:gap-1 pz:text-xs\">\n <span>Schema</span>\n <Input\n id={schemaId}\n value={schema}\n onChange={(e) => setSchema(e.target.value)}\n placeholder=\"SCHEMA_NAME\"\n />\n </label>\n )}\n <label htmlFor={descId} className=\"pz:flex pz:flex-col pz:gap-1 pz:text-xs\">\n <span>Description</span>\n <Input id={descId} value={description} onChange={(e) => setDescription(e.target.value)} />\n </label>\n <div className=\"pz:flex pz:items-center pz:justify-between pz:gap-2 pz:pt-1\">\n <Button type=\"button\" variant=\"ghost\" size=\"sm\" onClick={remove}>\n <Trash2 className=\"pz:size-3.5 pz:mr-1\" />\n Remove\n </Button>\n <Button type=\"button\" size=\"sm\" onClick={save}>\n Save\n </Button>\n </div>\n </>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ChipEditPopover.mjs","names":[],"sources":["../../../../src/components/internal/LiquidEditor/ChipEditPopover.tsx"],"sourcesContent":["import { offset, shift } from \"@floating-ui/react\";\nimport { TYPES_TO_FORMATS } from \"@pipe0/base\";\nimport type { Editor } from \"@tiptap/react\";\nimport { Trash2 } from \"lucide-react\";\nimport { useEffect, useId, useMemo, useRef, useState } from \"react\";\nimport { useFloatingElement } from \"../../../hooks/use-floating-element.js\";\nimport { Button } from \"../../ui/button.js\";\nimport { Input } from \"../../ui/input.js\";\nimport { Switch } from \"../../ui/switch.js\";\nimport type { ChipKind } from \"../tag-chip-decoration.js\";\n\nconst SIMPLE_FIELD_RE = /^\\{\\{\\s*([a-zA-Z_][a-zA-Z0-9_.]*)\\s*(\\|\\s*default:\\s*\"\")?\\s*\\}\\}$/;\nconst SECRET_RE = /^\\{\\{\\s*SECRETS\\.([A-Z][A-Z0-9_]*)\\s*\\}\\}$/;\nconst CONSTANT_RE = /^\\{\\{\\s*CONSTANTS\\.([A-Z][A-Z0-9_]*)\\s*\\}\\}$/;\n// `{% output NAME, key: \"value\", key: true, ... %}` in any argument order. The\n// args are split out by OUTPUT_ARG_RE; BlockChipBody only edits the keys it\n// knows and falls back to the raw \"advanced\" view for anything else.\nconst OUTPUT_BLOCK_RE =\n /^\\{%\\s*output\\s+([A-Za-z_][A-Za-z0-9_]*)\\s*((?:,\\s*[a-z_]+:\\s*(?:\"(?:[^\"\\\\]|\\\\.)*\"|true|false)\\s*)*)%\\}$/;\nconst OUTPUT_ARG_RE = /([a-z_]+):\\s*(\"(?:[^\"\\\\]|\\\\.)*\"|true|false)/g;\nconst OUTPUT_KEYS = new Set([\"type\", \"schema\", \"description\", \"format\", \"required\"]);\n\ntype OutputType = \"string\" | \"number\" | \"boolean\" | \"json\" | \"unknown\";\n\nfunction parseOutputBlock(raw: string) {\n const m = raw.match(OUTPUT_BLOCK_RE);\n if (!m) return null;\n const args: Record<string, string | boolean> = {};\n for (const [, key, value] of (m[2] ?? \"\").matchAll(OUTPUT_ARG_RE)) {\n if (!key || !value || !OUTPUT_KEYS.has(key)) return null;\n args[key] =\n value === \"true\" || value === \"false\"\n ? value === \"true\"\n : value.slice(1, -1).replace(/\\\\\"/g, '\"').replace(/\\\\\\\\/g, \"\\\\\");\n }\n const type = args.type;\n if (typeof type !== \"string\" || !(type in TYPES_TO_FORMATS)) return null;\n // A hand-written format the type does not take has no option to show; keep\n // the raw view rather than silently dropping it on save.\n const format = args.format;\n if (\n typeof format === \"string\" &&\n type !== \"json\" &&\n !(TYPES_TO_FORMATS[type as OutputType] as readonly string[]).includes(format)\n ) {\n return null;\n }\n return {\n name: m[1] ?? \"\",\n type: type as OutputType,\n schema: typeof args.schema === \"string\" ? args.schema : \"\",\n description: typeof args.description === \"string\" ? args.description : \"\",\n format: typeof args.format === \"string\" ? args.format : \"\",\n required: typeof args.required === \"boolean\" ? args.required : undefined,\n };\n}\n\nexport interface ChipEditTarget {\n kind: ChipKind;\n raw: string;\n from: number;\n to: number;\n rect: DOMRect;\n}\n\n/**\n * Contextual popover anchored to a chip's DOM rect. Different content per\n * chip kind:\n * - field: switch for `| default: \"\"` (simple cases only), remove.\n * - secret: publicId header, manage/remove buttons. Power users still\n * edit by hand.\n * - block (output declaration): name / type / format / description editors.\n *\n * On any mutation, the popover dispatches a single replaceWith transaction\n * over the chip's range, then closes itself. The Liquid serialization\n * stays identical to what would have been authored by hand.\n */\nexport function ChipEditPopover({\n editor,\n target,\n onClose,\n}: {\n editor: Editor;\n target: ChipEditTarget;\n onClose: () => void;\n}) {\n const { ref, style, isMounted, getFloatingProps } = useFloatingElement(true, target.rect, 1100, {\n placement: \"bottom-start\",\n middleware: [offset(6), shift()],\n onOpenChange(open) {\n if (!open) onClose();\n },\n dismissOptions: { outsidePress: true, outsidePressEvent: \"mousedown\" },\n });\n\n const popupRef = useRef<HTMLDivElement | null>(null);\n\n useEffect(() => {\n function onKey(e: KeyboardEvent) {\n if (e.key === \"Escape\") onClose();\n }\n window.addEventListener(\"keydown\", onKey);\n return () => window.removeEventListener(\"keydown\", onKey);\n }, [onClose]);\n\n function replaceWith(next: string) {\n editor.chain().focus().insertContentAt({ from: target.from, to: target.to }, next).run();\n onClose();\n }\n\n function remove() {\n editor.chain().focus().deleteRange({ from: target.from, to: target.to }).run();\n onClose();\n }\n\n if (!isMounted) return null;\n\n return (\n <div\n ref={(el) => {\n popupRef.current = el;\n ref(el);\n }}\n style={style}\n {...getFloatingProps()}\n onMouseDown={(e) => e.stopPropagation()}\n className=\"pz:flex pz:flex-col pz:gap-2 pz:rounded-md pz:border pz:border-input pz:bg-popover pz:p-3 pz:text-popover-foreground pz:shadow-md pz:min-w-72\"\n role=\"dialog\"\n aria-label={`Edit ${target.kind} chip`}\n >\n {target.kind === \"field\" && (\n <FieldChipBody raw={target.raw} replaceWith={replaceWith} remove={remove} />\n )}\n {target.kind === \"secret\" && <SecretChipBody raw={target.raw} remove={remove} />}\n {target.kind === \"constant\" && <ConstantChipBody raw={target.raw} remove={remove} />}\n {target.kind === \"block\" && (\n <BlockChipBody raw={target.raw} replaceWith={replaceWith} remove={remove} />\n )}\n </div>\n );\n}\n\nfunction FieldChipBody({\n raw,\n replaceWith,\n remove,\n}: {\n raw: string;\n replaceWith: (next: string) => void;\n remove: () => void;\n}) {\n const match = raw.match(SIMPLE_FIELD_RE);\n const name = match?.[1];\n const allowEmpty = !!match?.[2];\n const isSimple = !!match;\n\n if (!isSimple || !name) {\n return (\n <>\n <header className=\"pz:text-xs pz:font-medium pz:text-muted-foreground\">\n Field reference (advanced)\n </header>\n <p className=\"pz:text-xs pz:text-muted-foreground\">\n This chip uses a custom Liquid filter chain. Edit the raw text in the editor to change it.\n </p>\n <pre className=\"pz:overflow-x-auto pz:rounded-sm pz:bg-muted pz:px-2 pz:py-1 pz:text-xs\">\n {raw}\n </pre>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={remove}>\n <Trash2 className=\"pz:size-3.5 pz:mr-1\" />\n Remove\n </Button>\n </>\n );\n }\n\n function toggleAllowEmpty() {\n replaceWith(allowEmpty ? `{{ ${name} }}` : `{{ ${name} | default: \"\" }}`);\n }\n\n return (\n <>\n <header className=\"pz:flex pz:items-center pz:justify-between pz:gap-2\">\n <span className=\"pz:text-xs pz:font-medium pz:text-muted-foreground\">Field reference</span>\n <code className=\"pz:text-xs pz:text-sky-700\">{name}</code>\n </header>\n <div className=\"pz:flex pz:items-center pz:justify-between pz:gap-3 pz:text-sm\">\n <span className=\"pz:flex pz:flex-col\">\n <span>Allow empty</span>\n <span className=\"pz:text-xs pz:text-muted-foreground\">\n Inserts <code>| default: \"\"</code> so missing values render as empty.\n </span>\n </span>\n <Switch checked={allowEmpty} onCheckedChange={toggleAllowEmpty} />\n </div>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={remove}>\n <Trash2 className=\"pz:size-3.5 pz:mr-1\" />\n Remove\n </Button>\n </>\n );\n}\n\nfunction SecretChipBody({ raw, remove }: { raw: string; remove: () => void }) {\n const publicId = raw.match(SECRET_RE)?.[1];\n\n return (\n <>\n <header className=\"pz:flex pz:items-center pz:justify-between pz:gap-2\">\n <span className=\"pz:text-xs pz:font-medium pz:text-muted-foreground\">Secret reference</span>\n <code className=\"pz:text-xs pz:text-amber-700\">{publicId ?? \"(unknown)\"}</code>\n </header>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={remove}>\n <Trash2 className=\"pz:size-3.5 pz:mr-1\" />\n Remove\n </Button>\n </>\n );\n}\n\nfunction ConstantChipBody({ raw, remove }: { raw: string; remove: () => void }) {\n const publicId = raw.match(CONSTANT_RE)?.[1];\n\n return (\n <>\n <header className=\"pz:flex pz:items-center pz:justify-between pz:gap-2\">\n <span className=\"pz:text-xs pz:font-medium pz:text-muted-foreground\">\n Constant reference\n </span>\n <code className=\"pz:text-xs pz:text-emerald-700\">{publicId ?? \"(unknown)\"}</code>\n </header>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={remove}>\n <Trash2 className=\"pz:size-3.5 pz:mr-1\" />\n Remove\n </Button>\n </>\n );\n}\n\nfunction BlockChipBody({\n raw,\n replaceWith,\n remove,\n}: {\n raw: string;\n replaceWith: (next: string) => void;\n remove: () => void;\n}) {\n const initial = useMemo(() => parseOutputBlock(raw), [raw]);\n\n const [name, setName] = useState(initial?.name ?? \"\");\n const [type, setType] = useState<OutputType>(initial?.type ?? \"string\");\n const [schema, setSchema] = useState(initial?.schema ?? \"\");\n const [description, setDescription] = useState(initial?.description ?? \"\");\n const [format, setFormat] = useState(initial?.format ?? \"\");\n const formatOptions: readonly string[] = TYPES_TO_FORMATS[type];\n const idPrefix = useId();\n const nameId = `${idPrefix}-name`;\n const typeId = `${idPrefix}-type`;\n const schemaId = `${idPrefix}-schema`;\n const descId = `${idPrefix}-desc`;\n const formatId = `${idPrefix}-format`;\n\n if (!initial) {\n return (\n <>\n <header className=\"pz:text-xs pz:font-medium pz:text-muted-foreground\">\n Block (advanced)\n </header>\n <p className=\"pz:text-xs pz:text-muted-foreground\">\n This block uses a non-standard form. Edit the raw text in the editor.\n </p>\n <pre className=\"pz:overflow-x-auto pz:rounded-sm pz:bg-muted pz:px-2 pz:py-1 pz:text-xs\">\n {raw}\n </pre>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={remove}>\n <Trash2 className=\"pz:size-3.5 pz:mr-1\" />\n Remove\n </Button>\n </>\n );\n }\n\n function save() {\n if (!name.trim()) return;\n const escaped = description.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\n const parts = [`{% output ${name.trim()}`, `type: \"${type}\"`];\n if (type === \"json\" && schema.trim()) parts.push(`schema: \"${schema.trim()}\"`);\n if (format && formatOptions.includes(format)) parts.push(`format: \"${format}\"`);\n parts.push(`description: \"${escaped}\"`);\n if (initial?.required !== undefined) parts.push(`required: ${initial.required}`);\n replaceWith(`${parts.join(\", \")} %}`);\n }\n\n return (\n <>\n <header className=\"pz:text-xs pz:font-medium pz:text-muted-foreground\">\n Output declaration\n </header>\n <label htmlFor={nameId} className=\"pz:flex pz:flex-col pz:gap-1 pz:text-xs\">\n <span>Name</span>\n <Input\n id={nameId}\n value={name}\n onChange={(e) => setName(e.target.value)}\n placeholder=\"FIELD_NAME\"\n />\n </label>\n <label htmlFor={typeId} className=\"pz:flex pz:flex-col pz:gap-1 pz:text-xs\">\n <span>Type</span>\n <select\n id={typeId}\n value={type}\n onChange={(e) => {\n const next = e.target.value as OutputType;\n setType(next);\n // A format that the new type does not take would fail validation.\n if (!(TYPES_TO_FORMATS[next] as readonly string[]).includes(format)) setFormat(\"\");\n }}\n className=\"pz:rounded-sm pz:border pz:border-input pz:bg-transparent pz:px-2 pz:py-1 pz:text-sm\"\n >\n <option value=\"string\">string</option>\n <option value=\"number\">number</option>\n <option value=\"boolean\">boolean</option>\n <option value=\"json\">json</option>\n <option value=\"unknown\">unknown</option>\n </select>\n </label>\n {type === \"json\" && (\n <label htmlFor={schemaId} className=\"pz:flex pz:flex-col pz:gap-1 pz:text-xs\">\n <span>Schema</span>\n <Input\n id={schemaId}\n value={schema}\n onChange={(e) => setSchema(e.target.value)}\n placeholder=\"SCHEMA_NAME\"\n />\n </label>\n )}\n {type !== \"json\" && formatOptions.length > 0 && (\n <label htmlFor={formatId} className=\"pz:flex pz:flex-col pz:gap-1 pz:text-xs\">\n <span>Format</span>\n <select\n id={formatId}\n value={format}\n onChange={(e) => setFormat(e.target.value)}\n className=\"pz:rounded-sm pz:border pz:border-input pz:bg-transparent pz:px-2 pz:py-1 pz:text-sm\"\n >\n <option value=\"\">none</option>\n {formatOptions.map((f) => (\n <option key={f} value={f}>\n {f}\n </option>\n ))}\n </select>\n </label>\n )}\n <label htmlFor={descId} className=\"pz:flex pz:flex-col pz:gap-1 pz:text-xs\">\n <span>Description</span>\n <Input id={descId} value={description} onChange={(e) => setDescription(e.target.value)} />\n </label>\n <div className=\"pz:flex pz:items-center pz:justify-between pz:gap-2 pz:pt-1\">\n <Button type=\"button\" variant=\"ghost\" size=\"sm\" onClick={remove}>\n <Trash2 className=\"pz:size-3.5 pz:mr-1\" />\n Remove\n </Button>\n <Button type=\"button\" size=\"sm\" onClick={save}>\n Save\n </Button>\n </div>\n </>\n );\n}\n"],"mappings":"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"}
@@ -3,8 +3,6 @@ import { PipeCatalogCardContext } from "./pipe-catalog-card-context.mjs";
3
3
  import { PipeCatalogContext } from "./pipe-catalog-context.mjs";
4
4
  import { SearchCatalogCardContext } from "./search-catalog-card-context.mjs";
5
5
  import { SearchCatalogContext } from "./search-catalog-context.mjs";
6
- import { SearchesCatalogCardContext } from "./searches-catalog-card-context.mjs";
7
- import { SearchesCatalogContext } from "./searches-catalog-context.mjs";
8
6
  import { useContext } from "react";
9
7
 
10
8
  //#region src/context/catalog-card-context.ts
@@ -12,20 +10,18 @@ import { useContext } from "react";
12
10
  function useAnyCatalogCardOptional() {
13
11
  const pipe = useContext(PipeCatalogCardContext);
14
12
  const search = useContext(SearchCatalogCardContext);
15
- const searches = useContext(SearchesCatalogCardContext);
16
13
  const effect = useContext(EffectCatalogCardContext);
17
- return pipe ?? search ?? searches ?? effect;
14
+ return pipe ?? search ?? effect;
18
15
  }
19
16
  /**
20
- * Returns whichever catalog root context is set (pipe / search / searches),
17
+ * Returns whichever catalog root context is set (pipe / search),
21
18
  * or null. Used by self-binding primitives that need access to mutators
22
19
  * (`addColumnFilter`) or reverse indexes from the catalog hook.
23
20
  */
24
21
  function useAnyCatalogContextOptional() {
25
22
  const pipe = useContext(PipeCatalogContext);
26
23
  const search = useContext(SearchCatalogContext);
27
- const searches = useContext(SearchesCatalogContext);
28
- return pipe ?? search ?? searches;
24
+ return pipe ?? search;
29
25
  }
30
26
 
31
27
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"catalog-card-context.mjs","names":[],"sources":["../../src/context/catalog-card-context.ts"],"sourcesContent":["import type { SyntheticEvent } from \"react\";\nimport { useContext } from \"react\";\nimport type {\n EffectCardData,\n PipeCardData,\n SearchCardData,\n SearchesCardData,\n} from \"../types/catalog-adapters.js\";\nimport { EffectCatalogCardContext } from \"./effect-catalog-card-context.js\";\nimport { PipeCatalogCardContext } from \"./pipe-catalog-card-context.js\";\nimport { PipeCatalogContext } from \"./pipe-catalog-context.js\";\nimport { SearchCatalogCardContext } from \"./search-catalog-card-context.js\";\nimport { SearchCatalogContext } from \"./search-catalog-context.js\";\nimport { SearchesCatalogCardContext } from \"./searches-catalog-card-context.js\";\nimport { SearchesCatalogContext } from \"./searches-catalog-context.js\";\n\nexport type AnyCardData = PipeCardData | SearchCardData | SearchesCardData | EffectCardData;\n\nexport interface AnyCardContextValue {\n card: AnyCardData;\n index: number;\n selected: boolean;\n onSelect: (e: SyntheticEvent) => void;\n}\n\n/**\n * Internal hook used by shared catalog card primitives. Reads whichever of the\n * three sibling card contexts is set; throws if rendered outside any catalog\n * card. The returned `card` is the union of the three variants — primitives\n * narrow via the discriminator (`pipeId` / `searchId` / `searchesId`).\n */\nexport function useAnyCatalogCard(): AnyCardContextValue {\n const pipe = useContext(PipeCatalogCardContext);\n const search = useContext(SearchCatalogCardContext);\n const searches = useContext(SearchesCatalogCardContext);\n const effect = useContext(EffectCatalogCardContext);\n const ctx = pipe ?? search ?? searches ?? effect;\n if (ctx == null) {\n throw new Error(\n \"Catalog card primitives must be rendered inside a <PipeCatalogCard>, <SearchCatalogCard>, <SearchesCatalogCard>, or <EffectCatalogCard>.\",\n );\n }\n return ctx as AnyCardContextValue;\n}\n\n/** Like {@link useAnyCatalogCard} but returns null when outside a card. */\nexport function useAnyCatalogCardOptional(): AnyCardContextValue | null {\n const pipe = useContext(PipeCatalogCardContext);\n const search = useContext(SearchCatalogCardContext);\n const searches = useContext(SearchesCatalogCardContext);\n const effect = useContext(EffectCatalogCardContext);\n return (pipe ?? search ?? searches ?? effect) as AnyCardContextValue | null;\n}\n\n/**\n * Returns whichever catalog root context is set (pipe / search / searches),\n * or null. Used by self-binding primitives that need access to mutators\n * (`addColumnFilter`) or reverse indexes from the catalog hook.\n */\nexport function useAnyCatalogContextOptional() {\n const pipe = useContext(PipeCatalogContext);\n const search = useContext(SearchCatalogContext);\n const searches = useContext(SearchesCatalogContext);\n return pipe ?? search ?? searches;\n}\n"],"mappings":";;;;;;;;;;;AA8CA,SAAgB,4BAAwD;CACtE,MAAM,OAAO,WAAW,uBAAuB;CAC/C,MAAM,SAAS,WAAW,yBAAyB;CACnD,MAAM,WAAW,WAAW,2BAA2B;CACvD,MAAM,SAAS,WAAW,yBAAyB;AACnD,QAAQ,QAAQ,UAAU,YAAY;;;;;;;AAQxC,SAAgB,+BAA+B;CAC7C,MAAM,OAAO,WAAW,mBAAmB;CAC3C,MAAM,SAAS,WAAW,qBAAqB;CAC/C,MAAM,WAAW,WAAW,uBAAuB;AACnD,QAAO,QAAQ,UAAU"}
1
+ {"version":3,"file":"catalog-card-context.mjs","names":[],"sources":["../../src/context/catalog-card-context.ts"],"sourcesContent":["import type { SyntheticEvent } from \"react\";\nimport { useContext } from \"react\";\nimport type { EffectCardData, PipeCardData, SearchCardData } from \"../types/catalog-adapters.js\";\nimport { EffectCatalogCardContext } from \"./effect-catalog-card-context.js\";\nimport { PipeCatalogCardContext } from \"./pipe-catalog-card-context.js\";\nimport { PipeCatalogContext } from \"./pipe-catalog-context.js\";\nimport { SearchCatalogCardContext } from \"./search-catalog-card-context.js\";\nimport { SearchCatalogContext } from \"./search-catalog-context.js\";\n\nexport type AnyCardData = PipeCardData | SearchCardData | EffectCardData;\n\nexport interface AnyCardContextValue {\n card: AnyCardData;\n index: number;\n selected: boolean;\n onSelect: (e: SyntheticEvent) => void;\n}\n\n/**\n * Internal hook used by shared catalog card primitives. Reads whichever of the\n * sibling card contexts is set; throws if rendered outside any catalog\n * card. The returned `card` is the union of the variants — primitives\n * narrow via the discriminator (`pipeId` / `searchId` / `effectId`).\n */\nexport function useAnyCatalogCard(): AnyCardContextValue {\n const pipe = useContext(PipeCatalogCardContext);\n const search = useContext(SearchCatalogCardContext);\n const effect = useContext(EffectCatalogCardContext);\n const ctx = pipe ?? search ?? effect;\n if (ctx == null) {\n throw new Error(\n \"Catalog card primitives must be rendered inside a <PipeCatalogCard>, <SearchCatalogCard>, or <EffectCatalogCard>.\",\n );\n }\n return ctx as AnyCardContextValue;\n}\n\n/** Like {@link useAnyCatalogCard} but returns null when outside a card. */\nexport function useAnyCatalogCardOptional(): AnyCardContextValue | null {\n const pipe = useContext(PipeCatalogCardContext);\n const search = useContext(SearchCatalogCardContext);\n const effect = useContext(EffectCatalogCardContext);\n return (pipe ?? search ?? effect) as AnyCardContextValue | null;\n}\n\n/**\n * Returns whichever catalog root context is set (pipe / search),\n * or null. Used by self-binding primitives that need access to mutators\n * (`addColumnFilter`) or reverse indexes from the catalog hook.\n */\nexport function useAnyCatalogContextOptional() {\n const pipe = useContext(PipeCatalogContext);\n const search = useContext(SearchCatalogContext);\n return pipe ?? search;\n}\n"],"mappings":";;;;;;;;;AAsCA,SAAgB,4BAAwD;CACtE,MAAM,OAAO,WAAW,uBAAuB;CAC/C,MAAM,SAAS,WAAW,yBAAyB;CACnD,MAAM,SAAS,WAAW,yBAAyB;AACnD,QAAQ,QAAQ,UAAU;;;;;;;AAQ5B,SAAgB,+BAA+B;CAC7C,MAAM,OAAO,WAAW,mBAAmB;CAC3C,MAAM,SAAS,WAAW,qBAAqB;AAC/C,QAAO,QAAQ"}
@@ -10,7 +10,7 @@ interface CatalogConfig {
10
10
  declare function useCatalogConfig(): CatalogConfig;
11
11
  /**
12
12
  * Root-level providers required by any catalog component tree (tooltips, etc.).
13
- * Always mounted by `<PipeCatalog>` / `<SearchCatalog>` / `<SearchesCatalog>`
13
+ * Always mounted by `<PipeCatalog>` / `<SearchCatalog>`
14
14
  * at the outermost layer.
15
15
  */
16
16
  declare function CatalogRoot({
@@ -9,7 +9,7 @@ function useCatalogConfig() {
9
9
  }
10
10
  /**
11
11
  * Root-level providers required by any catalog component tree (tooltips, etc.).
12
- * Always mounted by `<PipeCatalog>` / `<SearchCatalog>` / `<SearchesCatalog>`
12
+ * Always mounted by `<PipeCatalog>` / `<SearchCatalog>`
13
13
  * at the outermost layer.
14
14
  */
15
15
  function CatalogRoot({ children }) {
@@ -1 +1 @@
1
- {"version":3,"file":"catalog-config-context.mjs","names":[],"sources":["../../src/context/catalog-config-context.tsx"],"sourcesContent":["import { createContext, type ReactNode, useContext } from \"react\";\nimport { TooltipProvider } from \"../components/ui/tooltip.js\";\nimport type { CatalogClassNames, CatalogComponentOverrides } from \"../types/catalog-adapters.js\";\n\nexport interface CatalogConfig {\n classNames?: CatalogClassNames;\n components?: CatalogComponentOverrides;\n}\n\nconst CatalogConfigContext = createContext<CatalogConfig>({});\n\nexport function useCatalogConfig(): CatalogConfig {\n return useContext(CatalogConfigContext);\n}\n\n/**\n * Root-level providers required by any catalog component tree (tooltips, etc.).\n * Always mounted by `<PipeCatalog>` / `<SearchCatalog>` / `<SearchesCatalog>`\n * at the outermost layer.\n */\nexport function CatalogRoot({ children }: { children: ReactNode }) {\n return <TooltipProvider>{children}</TooltipProvider>;\n}\n\nexport interface CatalogProviderProps {\n classNames?: CatalogClassNames;\n components?: CatalogComponentOverrides;\n children: ReactNode;\n}\n\nexport function CatalogProvider({ classNames, components, children }: CatalogProviderProps) {\n const parent = useCatalogConfig();\n const merged: CatalogConfig = {\n classNames: { ...parent.classNames, ...classNames },\n components: { ...parent.components, ...components },\n };\n return <CatalogConfigContext.Provider value={merged}>{children}</CatalogConfigContext.Provider>;\n}\n"],"mappings":";;;;;AASA,MAAM,uBAAuB,cAA6B,EAAE,CAAC;AAE7D,SAAgB,mBAAkC;AAChD,QAAO,WAAW,qBAAqB;;;;;;;AAQzC,SAAgB,YAAY,EAAE,YAAqC;AACjE,QAAO,oBAAC,iBAAD,EAAkB,UAA2B;;AAStD,SAAgB,gBAAgB,EAAE,YAAY,YAAY,YAAkC;CAC1F,MAAM,SAAS,kBAAkB;CACjC,MAAM,SAAwB;EAC5B,YAAY;GAAE,GAAG,OAAO;GAAY,GAAG;GAAY;EACnD,YAAY;GAAE,GAAG,OAAO;GAAY,GAAG;GAAY;EACpD;AACD,QAAO,oBAAC,qBAAqB,UAAtB;EAA+B,OAAO;EAAS;EAAyC"}
1
+ {"version":3,"file":"catalog-config-context.mjs","names":[],"sources":["../../src/context/catalog-config-context.tsx"],"sourcesContent":["import { createContext, type ReactNode, useContext } from \"react\";\nimport { TooltipProvider } from \"../components/ui/tooltip.js\";\nimport type { CatalogClassNames, CatalogComponentOverrides } from \"../types/catalog-adapters.js\";\n\nexport interface CatalogConfig {\n classNames?: CatalogClassNames;\n components?: CatalogComponentOverrides;\n}\n\nconst CatalogConfigContext = createContext<CatalogConfig>({});\n\nexport function useCatalogConfig(): CatalogConfig {\n return useContext(CatalogConfigContext);\n}\n\n/**\n * Root-level providers required by any catalog component tree (tooltips, etc.).\n * Always mounted by `<PipeCatalog>` / `<SearchCatalog>`\n * at the outermost layer.\n */\nexport function CatalogRoot({ children }: { children: ReactNode }) {\n return <TooltipProvider>{children}</TooltipProvider>;\n}\n\nexport interface CatalogProviderProps {\n classNames?: CatalogClassNames;\n components?: CatalogComponentOverrides;\n children: ReactNode;\n}\n\nexport function CatalogProvider({ classNames, components, children }: CatalogProviderProps) {\n const parent = useCatalogConfig();\n const merged: CatalogConfig = {\n classNames: { ...parent.classNames, ...classNames },\n components: { ...parent.components, ...components },\n };\n return <CatalogConfigContext.Provider value={merged}>{children}</CatalogConfigContext.Provider>;\n}\n"],"mappings":";;;;;AASA,MAAM,uBAAuB,cAA6B,EAAE,CAAC;AAE7D,SAAgB,mBAAkC;AAChD,QAAO,WAAW,qBAAqB;;;;;;;AAQzC,SAAgB,YAAY,EAAE,YAAqC;AACjE,QAAO,oBAAC,iBAAD,EAAkB,UAA2B;;AAStD,SAAgB,gBAAgB,EAAE,YAAY,YAAY,YAAkC;CAC1F,MAAM,SAAS,kBAAkB;CACjC,MAAM,SAAwB;EAC5B,YAAY;GAAE,GAAG,OAAO;GAAY,GAAG;GAAY;EACnD,YAAY;GAAE,GAAG,OAAO;GAAY,GAAG;GAAY;EACpD;AACD,QAAO,oBAAC,qBAAqB,UAAtB;EAA+B,OAAO;EAAS;EAAyC"}