@seedprotocol/mapping 0.5.3 → 0.6.0

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 (49) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +202 -36
  3. package/dist/adapters/rss.d.ts +2 -1
  4. package/dist/adapters/rss.d.ts.map +1 -1
  5. package/dist/applyMapping.d.ts +14 -1
  6. package/dist/applyMapping.d.ts.map +1 -1
  7. package/dist/autoMap-PTFd4l-9.js +534 -0
  8. package/dist/autoMap-PTFd4l-9.js.map +1 -0
  9. package/dist/autoMap.d.ts +3 -3
  10. package/dist/autoMap.d.ts.map +1 -1
  11. package/dist/classifyUrl.d.ts +14 -0
  12. package/dist/classifyUrl.d.ts.map +1 -0
  13. package/dist/index.d.ts +7 -3
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +91 -402
  16. package/dist/index.js.map +1 -1
  17. package/dist/react/FieldMapper.d.ts +65 -5
  18. package/dist/react/FieldMapper.d.ts.map +1 -1
  19. package/dist/react/FieldMapperWires.d.ts +19 -0
  20. package/dist/react/FieldMapperWires.d.ts.map +1 -0
  21. package/dist/react/LookupEditor.d.ts +24 -0
  22. package/dist/react/LookupEditor.d.ts.map +1 -0
  23. package/dist/react/PropertyRows.d.ts +19 -0
  24. package/dist/react/PropertyRows.d.ts.map +1 -0
  25. package/dist/react/SourceRows.d.ts +18 -0
  26. package/dist/react/SourceRows.d.ts.map +1 -0
  27. package/dist/react/fieldMapperControls.d.ts +9 -0
  28. package/dist/react/fieldMapperControls.d.ts.map +1 -0
  29. package/dist/react/fieldMapperCore.d.ts +79 -0
  30. package/dist/react/fieldMapperCore.d.ts.map +1 -0
  31. package/dist/react/fieldMapperSlots.d.ts +69 -0
  32. package/dist/react/fieldMapperSlots.d.ts.map +1 -0
  33. package/dist/react/fieldMapperTheme.d.ts +34 -0
  34. package/dist/react/fieldMapperTheme.d.ts.map +1 -0
  35. package/dist/react/fieldMapperTypes.d.ts +63 -0
  36. package/dist/react/fieldMapperTypes.d.ts.map +1 -0
  37. package/dist/react/useFieldMapper.d.ts +8 -0
  38. package/dist/react/useFieldMapper.d.ts.map +1 -0
  39. package/dist/react.d.ts +10 -0
  40. package/dist/react.d.ts.map +1 -0
  41. package/dist/react.js +1617 -0
  42. package/dist/react.js.map +1 -0
  43. package/dist/relationLookup.d.ts +14 -0
  44. package/dist/relationLookup.d.ts.map +1 -0
  45. package/dist/resolvedSources.d.ts +32 -0
  46. package/dist/resolvedSources.d.ts.map +1 -0
  47. package/dist/types.d.ts +57 -2
  48. package/dist/types.d.ts.map +1 -1
  49. package/package.json +19 -1
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/applyMapping.ts","../src/autoMap.ts","../src/adapters/markdown.ts","../src/adapters/rss.ts","../src/react/FieldMapper.tsx"],"sourcesContent":["import type {\n FieldMapping,\n PropertyBag,\n SourceNode,\n TargetProperty,\n} from './types'\n\n/**\n * Coerce a raw string value to the Seed model property dataType.\n */\nexport function coerceValue(rawValue: string, dataType: string): unknown {\n if (dataType === 'Number') {\n return parseFloat(String(rawValue)) || 0\n }\n if (dataType === 'Boolean') {\n return (\n rawValue === 'true' ||\n rawValue === '1' ||\n String(rawValue).toLowerCase() === 'yes'\n )\n }\n if (dataType === 'Json') {\n try {\n return JSON.parse(rawValue)\n } catch {\n return rawValue\n }\n }\n if (dataType === 'Date') {\n const d = new Date(String(rawValue))\n return Number.isNaN(d.getTime()) ? rawValue : d.getTime()\n }\n return String(rawValue ?? '')\n}\n\n/**\n * Apply field mappings to produce a property bag for createItem / publish.\n * Missing sources or unknown target properties are skipped (no throw).\n */\nexport function applyMapping(\n sources: SourceNode[],\n mappings: FieldMapping[],\n targets: TargetProperty[],\n): PropertyBag {\n const byId = new Map(sources.map((s) => [s.id, s]))\n const byName = new Map(targets.map((t) => [t.name, t]))\n const properties: PropertyBag = {}\n\n for (const mapping of mappings) {\n const source = byId.get(mapping.sourceId)\n const target = byName.get(mapping.propertyName)\n if (!source || !target) continue\n\n const raw = source.value || source.label\n properties[mapping.propertyName] = coerceValue(raw, target.dataType)\n }\n\n return properties\n}\n","import type { FieldMapping, SourceNode, TargetProperty } from './types'\n\nconst FULL_DOC_PROP_NAMES = ['text', 'content', 'body', 'fulltext', 'markdown']\n\nfunction normalizeName(name: string): string {\n return name.toLowerCase().replace(/\\s+/g, '').replace(/[:_-]/g, '')\n}\n\nfunction namesMatch(a: string, b: string): boolean {\n const na = normalizeName(a)\n const nb = normalizeName(b)\n return na === nb || na.includes(nb) || nb.includes(na)\n}\n\n/**\n * Heuristic auto-map: full-document sources to body-like props,\n * then fuzzy name match for remaining sources ↔ targets.\n * Returns 1:1 mappings (each source and property used at most once).\n */\nexport function autoMap(\n sources: SourceNode[],\n targets: TargetProperty[],\n): FieldMapping[] {\n const mappings: FieldMapping[] = []\n const usedProps = new Set<string>()\n const usedSources = new Set<string>()\n\n const fullSource = sources.find((s) => s.kind === 'full')\n if (fullSource) {\n const fullDocMatch = targets.find((p) =>\n FULL_DOC_PROP_NAMES.includes(p.name.toLowerCase()),\n )\n if (fullDocMatch) {\n mappings.push({\n sourceId: fullSource.id,\n propertyName: fullDocMatch.name,\n })\n usedProps.add(fullDocMatch.name)\n usedSources.add(fullSource.id)\n }\n }\n\n // Prefer common RSS aliases before generic fuzzy match\n const rssAliases: Record<string, string[]> = {\n title: ['title', 'name', 'headline'],\n 'content:encoded': ['html', 'content', 'body', 'text'],\n content: ['html', 'content', 'body', 'text'],\n description: ['summary', 'description', 'excerpt'],\n summary: ['summary', 'description', 'excerpt'],\n featureimage: ['featureimage', 'feature_image', 'image', 'cover'],\n feature_image: ['featureimage', 'feature_image', 'image', 'cover'],\n link: ['url', 'link', 'permalink', 'slug'],\n creator: ['author', 'authors', 'creator', 'byline'],\n author: ['author', 'authors', 'creator', 'byline'],\n }\n\n for (const source of sources) {\n if (usedSources.has(source.id)) continue\n\n const labelKey = normalizeName(source.label)\n const idKey = source.id.replace(/^rss-/, '').replace(/^fm-/, '')\n const aliasKeys = [\n ...(rssAliases[source.label] ?? []),\n ...(rssAliases[idKey] ?? []),\n ...(rssAliases[labelKey] ?? []),\n ]\n\n let match: TargetProperty | undefined\n\n for (const alias of aliasKeys) {\n match = targets.find(\n (p) => !usedProps.has(p.name) && namesMatch(p.name, alias),\n )\n if (match) break\n }\n\n if (!match) {\n match = targets.find(\n (p) =>\n !usedProps.has(p.name) &&\n (namesMatch(p.name, source.label) || namesMatch(p.name, idKey)),\n )\n }\n\n if (match) {\n mappings.push({ sourceId: source.id, propertyName: match.name })\n usedProps.add(match.name)\n usedSources.add(source.id)\n }\n }\n\n return mappings\n}\n","import type { SourceNode } from '../types'\n\nexport const SECTION_FULL_ID = 'section-full'\n\ntype FrontmatterField = {\n id: string\n key: string\n value: string\n valueType: 'string' | 'boolean' | 'array'\n}\n\ntype ParsedMarkdown = {\n frontmatter: FrontmatterField[]\n body: string\n}\n\ntype MarkdownSection = {\n id: string\n heading: string\n level: number\n content: string\n}\n\n/**\n * Parse YAML-like frontmatter (flat keys only) and body.\n * Mirrors desktop MarkdownMapper limits: no nested YAML.\n */\nexport function parseMarkdownWithFrontmatter(\n markdownContent: string,\n): ParsedMarkdown {\n try {\n const match = markdownContent.match(\n /^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?([\\s\\S]*)$/,\n )\n if (!match) return { frontmatter: [], body: markdownContent }\n\n const yamlBlock = match[1] ?? ''\n const body = (match[2] ?? '').trimStart()\n const frontmatter: FrontmatterField[] = []\n const data: Record<string, unknown> = {}\n\n for (const line of yamlBlock.split('\\n')) {\n const keyMatch = line.match(/^([a-zA-Z_][a-zA-Z0-9_-]*):\\s*(.*)$/)\n if (!keyMatch) continue\n\n const key = keyMatch[1]!\n const raw = keyMatch[2]!.trim()\n let val: unknown = raw\n\n if (raw === 'true') val = true\n else if (raw === 'false') val = false\n else if (raw === 'null' || raw === '') val = null\n else if (raw.startsWith('[') && raw.endsWith(']')) {\n try {\n val = JSON.parse(raw.replace(/'/g, '\"'))\n } catch {\n val = raw\n .slice(1, -1)\n .split(',')\n .map((s: string) => s.trim().replace(/^['\"]|['\"]$/g, ''))\n }\n } else if (raw.startsWith('\"') || raw.startsWith(\"'\")) {\n val = raw.slice(1, -1).replace(/\\\\\"/g, '\"')\n }\n\n data[key] = val\n }\n\n for (const [key, val] of Object.entries(data)) {\n let valueType: 'string' | 'boolean' | 'array' = 'string'\n let value: string\n\n if (Array.isArray(val)) {\n valueType = 'array'\n value = val\n .map((v) => (typeof v === 'object' ? JSON.stringify(v) : String(v)))\n .join(', ')\n } else if (typeof val === 'boolean') {\n valueType = 'boolean'\n value = String(val)\n } else if (val != null && typeof val === 'object') {\n value = JSON.stringify(val)\n } else {\n value = val != null ? String(val) : ''\n }\n\n frontmatter.push({\n id: `fm-${key}`,\n key,\n value,\n valueType,\n })\n }\n\n return { frontmatter, body }\n } catch {\n return { frontmatter: [], body: markdownContent }\n }\n}\n\n/**\n * Split markdown body into H1/H2 sections (###+ ignored as section breaks).\n */\nexport function parseMarkdownSections(md: string): MarkdownSection[] {\n const lines = md.split('\\n')\n const sections: MarkdownSection[] = []\n let current: MarkdownSection | null = null\n\n for (const line of lines) {\n const h2Match = line.match(/^## (.+)/)\n const h1Match = line.match(/^# (.+)/)\n\n if (h1Match) {\n if (current) sections.push(current)\n current = {\n id: `section-${sections.length}`,\n heading: h1Match[1]!,\n level: 1,\n content: '',\n }\n } else if (h2Match) {\n if (current) sections.push(current)\n current = {\n id: `section-${sections.length}`,\n heading: h2Match[1]!,\n level: 2,\n content: '',\n }\n } else if (current) {\n current.content += (current.content ? '\\n' : '') + line\n }\n }\n if (current) sections.push(current)\n return sections\n}\n\n/**\n * Convert markdown into SourceNodes for FieldMapper / applyMapping.\n * Order: frontmatter fields, full document body, then H1/H2 sections.\n */\nexport function markdownToSources(markdown: string): SourceNode[] {\n const parsed = parseMarkdownWithFrontmatter(markdown)\n const sections = parseMarkdownSections(parsed.body)\n const sources: SourceNode[] = []\n\n for (const fm of parsed.frontmatter) {\n sources.push({\n id: fm.id,\n label: fm.key,\n kind: 'frontmatter',\n value: fm.value,\n meta: { valueType: fm.valueType },\n })\n }\n\n sources.push({\n id: SECTION_FULL_ID,\n label: 'Full document',\n kind: 'full',\n value: parsed.body,\n })\n\n for (const section of sections) {\n const value =\n section.content.trim().length > 0 ? section.content.trim() : section.heading\n sources.push({\n id: section.id,\n label: section.heading,\n kind: 'section',\n value,\n meta: { level: section.level },\n })\n }\n\n return sources\n}\n","import Parser from 'rss-parser'\nimport type { SourceNode } from '../types'\n\nexport type ParsedRssChannel = {\n title?: string\n link?: string\n description?: string\n /** Plain serializable item records (dates become ISO strings). */\n items: Record<string, unknown>[]\n}\n\nfunction toPlainItem(item: unknown): Record<string, unknown> {\n try {\n return JSON.parse(JSON.stringify(item)) as Record<string, unknown>\n } catch {\n return { ...(item as Record<string, unknown>) }\n }\n}\n\n/**\n * Same shape and customFields as @seedprotocol/feed `parseRssString`\n * so RSS mapping stays aligned without importing feed's heavy barrel.\n */\nconst parser = new Parser({\n customFields: {\n item: [\n 'featureImage',\n 'feature_image',\n 'content:encoded',\n 'seedUid',\n 'SeedUid',\n ],\n },\n})\n\nasync function parseRssString(xml: string): Promise<ParsedRssChannel> {\n const feed = await parser.parseString(xml)\n return {\n title: feed.title,\n link: feed.link,\n description: feed.description,\n items: (feed.items ?? []).map(toPlainItem),\n }\n}\n\nfunction coerceFieldValue(val: unknown): string | null {\n if (val == null) return null\n if (typeof val === 'string') {\n const t = val.trim()\n return t.length > 0 ? t : null\n }\n if (typeof val === 'number' || typeof val === 'boolean') {\n return String(val)\n }\n if (Array.isArray(val)) {\n try {\n return JSON.stringify(val)\n } catch {\n return null\n }\n }\n if (typeof val === 'object') {\n const obj = val as Record<string, unknown>\n if (typeof obj._ === 'string' && obj._.trim()) return obj._.trim()\n if (typeof obj.value === 'string' && obj.value.trim()) return obj.value.trim()\n try {\n return JSON.stringify(val)\n } catch {\n return null\n }\n }\n return null\n}\n\n/**\n * Flatten a parsed RSS/Atom item into SourceNodes (one per string-coercible key).\n * Stable ids: `rss-{key}`.\n */\nexport function rssItemToSources(item: Record<string, unknown>): SourceNode[] {\n const sources: SourceNode[] = []\n const seen = new Set<string>()\n\n for (const [key, raw] of Object.entries(item)) {\n if (key === 'items' || key.startsWith('$')) continue\n const value = coerceFieldValue(raw)\n if (value == null) continue\n if (seen.has(key)) continue\n seen.add(key)\n\n sources.push({\n id: `rss-${key}`,\n label: key,\n kind: 'rssField',\n value,\n })\n }\n\n return sources\n}\n\nexport type RssXmlSourcesResult = {\n channel: {\n title?: string\n link?: string\n description?: string\n }\n /** Source nodes for each feed item, in document order. */\n items: SourceNode[][]\n}\n\n/**\n * Parse RSS/Atom XML and map each item to SourceNodes via rssItemToSources.\n * Compatible with @seedprotocol/feed `parseRssString` field set.\n */\nexport async function rssXmlToSources(\n xml: string,\n): Promise<RssXmlSourcesResult> {\n const parsed = await parseRssString(xml)\n return {\n channel: {\n title: parsed.title,\n link: parsed.link,\n description: parsed.description,\n },\n items: parsed.items.map((item) => rssItemToSources(item)),\n }\n}\n","import React, {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react'\nimport { applyMapping } from '../applyMapping'\nimport { autoMap as defaultAutoMap } from '../autoMap'\nimport type { FieldMapping, SourceNode, TargetProperty } from '../types'\n\nconst CONNECTION_COLORS = [\n '#3b82f6',\n '#8b5cf6',\n '#ec4899',\n '#f59e0b',\n '#10b981',\n '#06b6d4',\n '#f97316',\n '#14b8a6',\n]\n\ntype ConnectorPoint = {\n x1: number\n y1: number\n x2: number\n y2: number\n color: string\n mapping: FieldMapping\n}\n\nexport type FieldMapperProps = {\n sources: SourceNode[]\n targets: TargetProperty[]\n mappings: FieldMapping[]\n onChange: (mappings: FieldMapping[]) => void\n /** Override default autoMap heuristics. */\n onAutoMap?: () => FieldMapping[]\n className?: string\n /** Show JSON preview of applyMapping result. Default true. */\n showPreview?: boolean\n}\n\nconst DATA_TYPE_COLORS: Record<\n string,\n { bg: string; border: string; text: string }\n> = {\n String: { bg: 'rgba(59,130,246,0.12)', border: '#3b82f6', text: '#93c5fd' },\n Text: { bg: 'rgba(59,130,246,0.12)', border: '#3b82f6', text: '#93c5fd' },\n Number: { bg: 'rgba(16,185,129,0.12)', border: '#10b981', text: '#6ee7b7' },\n Boolean: { bg: 'rgba(167,139,250,0.12)', border: '#a78bfa', text: '#c4b5fd' },\n Json: { bg: 'rgba(251,191,36,0.12)', border: '#fbbf24', text: '#fcd34d' },\n Date: { bg: 'rgba(244,114,182,0.12)', border: '#f472b6', text: '#f9a8d4' },\n Relation: { bg: 'rgba(34,211,238,0.12)', border: '#22d3ee', text: '#67e8f9' },\n}\n\nfunction getDataTypeStyle(dataType: string) {\n return (\n DATA_TYPE_COLORS[dataType] ?? {\n bg: 'rgba(148,163,184,0.12)',\n border: '#94a3b8',\n text: '#cbd5e1',\n }\n )\n}\n\nfunction truncate(s: string, n: number): string {\n const t = s.replace(/\\s+/g, ' ').trim()\n if (t.length <= n) return t\n return `${t.slice(0, n)}…`\n}\n\n/**\n * Generic two-pane field mapper. Props-driven; no Seed hooks or routing.\n */\nexport function FieldMapper({\n sources,\n targets,\n mappings,\n onChange,\n onAutoMap,\n className,\n showPreview = true,\n}: FieldMapperProps) {\n const [activeSource, setActiveSource] = useState<string | null>(null)\n const [hoveredProp, setHoveredProp] = useState<string | null>(null)\n const [hoveredSource, setHoveredSource] = useState<string | null>(null)\n const [previewOpen, setPreviewOpen] = useState(false)\n const [svgDimensions, setSvgDimensions] = useState({ width: 0, height: 0 })\n const [connectorPoints, setConnectorPoints] = useState<ConnectorPoint[]>([])\n\n const containerRef = useRef<HTMLDivElement>(null)\n const sourceRefs = useRef<Record<string, HTMLDivElement | null>>({})\n const propRefs = useRef<Record<string, HTMLDivElement | null>>({})\n\n const getConnectionColor = useCallback(\n (index: number) => CONNECTION_COLORS[index % CONNECTION_COLORS.length]!,\n [],\n )\n\n const getConnectorPoints = useCallback((): ConnectorPoint[] => {\n if (!containerRef.current) return []\n const containerRect = containerRef.current.getBoundingClientRect()\n return mappings\n .map((mapping, i) => {\n const sourceEl = sourceRefs.current[mapping.sourceId]\n const propEl = propRefs.current[mapping.propertyName]\n if (!sourceEl || !propEl) return null\n\n const sR = sourceEl.getBoundingClientRect()\n const pR = propEl.getBoundingClientRect()\n\n return {\n x1: sR.right - containerRect.left,\n y1: sR.top + sR.height / 2 - containerRect.top,\n x2: pR.left - containerRect.left,\n y2: pR.top + pR.height / 2 - containerRect.top,\n color: getConnectionColor(i),\n mapping,\n }\n })\n .filter((pt): pt is ConnectorPoint => pt !== null)\n }, [mappings, getConnectionColor])\n\n useEffect(() => {\n const update = () => {\n if (containerRef.current) {\n const rect = containerRef.current.getBoundingClientRect()\n setSvgDimensions({ width: rect.width, height: rect.height })\n }\n setConnectorPoints(getConnectorPoints())\n }\n update()\n window.addEventListener('resize', update)\n const timer = setInterval(update, 200)\n return () => {\n window.removeEventListener('resize', update)\n clearInterval(timer)\n }\n }, [getConnectorPoints, mappings, sources, targets])\n\n const handleSourceClick = (sourceId: string) => {\n setActiveSource((prev) => (prev === sourceId ? null : sourceId))\n }\n\n const handlePropClick = (propertyName: string) => {\n if (!activeSource) return\n let next = [...mappings]\n next = next.filter(\n (c) =>\n c.sourceId !== activeSource && c.propertyName !== propertyName,\n )\n next.push({ sourceId: activeSource, propertyName })\n onChange(next)\n setActiveSource(null)\n }\n\n const removeMapping = (sourceId: string) => {\n onChange(mappings.filter((c) => c.sourceId !== sourceId))\n }\n\n const mappingForSource = (sourceId: string) =>\n mappings.find((c) => c.sourceId === sourceId)\n const mappingForProp = (propName: string) =>\n mappings.find((c) => c.propertyName === propName)\n\n const highlightedPair = hoveredProp\n ? mappings.find((c) => c.propertyName === hoveredProp)\n : hoveredSource\n ? mappings.find((c) => c.sourceId === hoveredSource)\n : null\n\n const preview = useMemo(\n () => applyMapping(sources, mappings, targets),\n [sources, mappings, targets],\n )\n\n const runAutoMap = () => {\n const next = onAutoMap ? onAutoMap() : defaultAutoMap(sources, targets)\n onChange(next)\n }\n\n return (\n <div className={`seed-field-mapper ${className ?? ''}`.trim()}>\n <style>{`\n .seed-field-mapper {\n font-family: 'DM Sans', system-ui, sans-serif;\n color: #e2e8f0;\n background: #0f172a;\n border-radius: 12px;\n padding: 16px;\n }\n .seed-field-mapper * { box-sizing: border-box; }\n .seed-field-mapper .fm-toolbar {\n display: flex;\n gap: 8px;\n align-items: center;\n margin-bottom: 12px;\n flex-wrap: wrap;\n }\n .seed-field-mapper .fm-btn {\n background: #1e293b;\n border: 1px solid #334155;\n color: #e2e8f0;\n border-radius: 8px;\n padding: 6px 12px;\n cursor: pointer;\n font-size: 13px;\n }\n .seed-field-mapper .fm-btn:hover { border-color: #64748b; }\n .seed-field-mapper .fm-btn-primary {\n background: #2563eb;\n border-color: #3b82f6;\n }\n .seed-field-mapper .fm-meta {\n font-size: 12px;\n color: #94a3b8;\n margin-left: auto;\n }\n .seed-field-mapper .fm-grid {\n position: relative;\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 48px;\n min-height: 240px;\n }\n .seed-field-mapper .fm-col-title {\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: #64748b;\n margin-bottom: 8px;\n }\n .seed-field-mapper .fm-card {\n border: 1px solid #334155;\n border-radius: 8px;\n padding: 10px 12px;\n margin-bottom: 8px;\n background: #1e293b;\n cursor: pointer;\n transition: border-color 0.15s, box-shadow 0.15s;\n }\n .seed-field-mapper .fm-card.active {\n border-color: #3b82f6;\n box-shadow: 0 0 0 1px #3b82f6;\n }\n .seed-field-mapper .fm-card.mapped {\n border-color: #475569;\n }\n .seed-field-mapper .fm-card.highlight {\n border-color: #f59e0b;\n }\n .seed-field-mapper .fm-label {\n font-weight: 600;\n font-size: 13px;\n margin-bottom: 4px;\n }\n .seed-field-mapper .fm-value {\n font-family: 'JetBrains Mono', ui-monospace, monospace;\n font-size: 11px;\n color: #94a3b8;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n .seed-field-mapper .fm-kind {\n font-size: 10px;\n color: #64748b;\n margin-left: 6px;\n }\n .seed-field-mapper .fm-prop-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n }\n .seed-field-mapper .fm-dtype {\n font-size: 10px;\n padding: 2px 6px;\n border-radius: 4px;\n border: 1px solid;\n }\n .seed-field-mapper .fm-remove {\n background: transparent;\n border: none;\n color: #94a3b8;\n cursor: pointer;\n font-size: 14px;\n padding: 0 4px;\n }\n .seed-field-mapper .fm-remove:hover { color: #f87171; }\n .seed-field-mapper .fm-svg {\n position: absolute;\n inset: 0;\n pointer-events: none;\n overflow: visible;\n }\n .seed-field-mapper .fm-preview {\n margin-top: 12px;\n background: #020617;\n border: 1px solid #334155;\n border-radius: 8px;\n padding: 12px;\n font-family: 'JetBrains Mono', ui-monospace, monospace;\n font-size: 11px;\n white-space: pre-wrap;\n color: #cbd5e1;\n max-height: 200px;\n overflow: auto;\n }\n `}</style>\n\n <div className=\"fm-toolbar\">\n <button type=\"button\" className=\"fm-btn fm-btn-primary\" onClick={runAutoMap}>\n Auto-map\n </button>\n {showPreview && (\n <button\n type=\"button\"\n className=\"fm-btn\"\n onClick={() => setPreviewOpen((v) => !v)}\n >\n {previewOpen ? 'Hide preview' : 'Preview JSON'}\n </button>\n )}\n <span className=\"fm-meta\">\n {mappings.length} / {targets.length} mapped\n {activeSource ? ' · click a property' : ' · click a source'}\n </span>\n </div>\n\n <div className=\"fm-grid\" ref={containerRef}>\n <svg\n className=\"fm-svg\"\n width={svgDimensions.width}\n height={svgDimensions.height}\n >\n {connectorPoints.map((pt) => {\n const isHi =\n highlightedPair?.sourceId === pt.mapping.sourceId &&\n highlightedPair?.propertyName === pt.mapping.propertyName\n const midX = (pt.x1 + pt.x2) / 2\n return (\n <path\n key={`${pt.mapping.sourceId}-${pt.mapping.propertyName}`}\n d={`M ${pt.x1} ${pt.y1} C ${midX} ${pt.y1}, ${midX} ${pt.y2}, ${pt.x2} ${pt.y2}`}\n stroke={pt.color}\n strokeWidth={isHi ? 3 : 2}\n fill=\"none\"\n opacity={highlightedPair && !isHi ? 0.25 : 0.85}\n />\n )\n })}\n </svg>\n\n <div>\n <div className=\"fm-col-title\">Sources</div>\n {sources.map((source) => {\n const mapped = mappingForSource(source.id)\n const isActive = activeSource === source.id\n const isHi = highlightedPair?.sourceId === source.id\n return (\n <div\n key={source.id}\n ref={(el) => {\n sourceRefs.current[source.id] = el\n }}\n className={`fm-card${isActive ? ' active' : ''}${mapped ? ' mapped' : ''}${isHi ? ' highlight' : ''}`}\n onClick={() => handleSourceClick(source.id)}\n onMouseEnter={() => setHoveredSource(source.id)}\n onMouseLeave={() => setHoveredSource(null)}\n >\n <div className=\"fm-prop-row\">\n <div className=\"fm-label\">\n {source.label}\n <span className=\"fm-kind\">{source.kind}</span>\n </div>\n {mapped && (\n <button\n type=\"button\"\n className=\"fm-remove\"\n aria-label=\"Remove mapping\"\n onClick={(e) => {\n e.stopPropagation()\n removeMapping(source.id)\n }}\n >\n ×\n </button>\n )}\n </div>\n <div className=\"fm-value\">{truncate(source.value, 80)}</div>\n </div>\n )\n })}\n </div>\n\n <div>\n <div className=\"fm-col-title\">Model properties</div>\n {targets.map((prop) => {\n const mapped = mappingForProp(prop.name)\n const style = getDataTypeStyle(prop.dataType)\n const isHi = highlightedPair?.propertyName === prop.name\n return (\n <div\n key={prop.name}\n ref={(el) => {\n propRefs.current[prop.name] = el\n }}\n className={`fm-card${mapped ? ' mapped' : ''}${isHi ? ' highlight' : ''}${activeSource ? ' active' : ''}`}\n onClick={() => handlePropClick(prop.name)}\n onMouseEnter={() => setHoveredProp(prop.name)}\n onMouseLeave={() => setHoveredProp(null)}\n >\n <div className=\"fm-prop-row\">\n <div className=\"fm-label\">{prop.name}</div>\n <span\n className=\"fm-dtype\"\n style={{\n background: style.bg,\n borderColor: style.border,\n color: style.text,\n }}\n >\n {prop.dataType}\n </span>\n </div>\n {mapped && (\n <div className=\"fm-value\">← {mapped.sourceId}</div>\n )}\n </div>\n )\n })}\n </div>\n </div>\n\n {showPreview && previewOpen && (\n <pre className=\"fm-preview\">{JSON.stringify(preview, null, 2)}</pre>\n )}\n </div>\n )\n}\n\nexport default FieldMapper\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/adapters/markdown.ts","../src/adapters/rss.ts"],"sourcesContent":["import type { SourceNode } from '../types'\n\nexport const SECTION_FULL_ID = 'section-full'\n\ntype FrontmatterField = {\n id: string\n key: string\n value: string\n valueType: 'string' | 'boolean' | 'array'\n}\n\ntype ParsedMarkdown = {\n frontmatter: FrontmatterField[]\n body: string\n}\n\ntype MarkdownSection = {\n id: string\n heading: string\n level: number\n content: string\n}\n\n/**\n * Parse YAML-like frontmatter (flat keys only) and body.\n * Mirrors desktop MarkdownMapper limits: no nested YAML.\n */\nexport function parseMarkdownWithFrontmatter(\n markdownContent: string,\n): ParsedMarkdown {\n try {\n const match = markdownContent.match(\n /^---\\r?\\n([\\s\\S]*?)\\r?\\n---\\r?\\n?([\\s\\S]*)$/,\n )\n if (!match) return { frontmatter: [], body: markdownContent }\n\n const yamlBlock = match[1] ?? ''\n const body = (match[2] ?? '').trimStart()\n const frontmatter: FrontmatterField[] = []\n const data: Record<string, unknown> = {}\n\n for (const line of yamlBlock.split('\\n')) {\n const keyMatch = line.match(/^([a-zA-Z_][a-zA-Z0-9_-]*):\\s*(.*)$/)\n if (!keyMatch) continue\n\n const key = keyMatch[1]!\n const raw = keyMatch[2]!.trim()\n let val: unknown = raw\n\n if (raw === 'true') val = true\n else if (raw === 'false') val = false\n else if (raw === 'null' || raw === '') val = null\n else if (raw.startsWith('[') && raw.endsWith(']')) {\n try {\n val = JSON.parse(raw.replace(/'/g, '\"'))\n } catch {\n val = raw\n .slice(1, -1)\n .split(',')\n .map((s: string) => s.trim().replace(/^['\"]|['\"]$/g, ''))\n }\n } else if (raw.startsWith('\"') || raw.startsWith(\"'\")) {\n val = raw.slice(1, -1).replace(/\\\\\"/g, '\"')\n }\n\n data[key] = val\n }\n\n for (const [key, val] of Object.entries(data)) {\n let valueType: 'string' | 'boolean' | 'array' = 'string'\n let value: string\n\n if (Array.isArray(val)) {\n valueType = 'array'\n value = val\n .map((v) => (typeof v === 'object' ? JSON.stringify(v) : String(v)))\n .join(', ')\n } else if (typeof val === 'boolean') {\n valueType = 'boolean'\n value = String(val)\n } else if (val != null && typeof val === 'object') {\n value = JSON.stringify(val)\n } else {\n value = val != null ? String(val) : ''\n }\n\n frontmatter.push({\n id: `fm-${key}`,\n key,\n value,\n valueType,\n })\n }\n\n return { frontmatter, body }\n } catch {\n return { frontmatter: [], body: markdownContent }\n }\n}\n\n/**\n * Split markdown body into H1/H2 sections (###+ ignored as section breaks).\n */\nexport function parseMarkdownSections(md: string): MarkdownSection[] {\n const lines = md.split('\\n')\n const sections: MarkdownSection[] = []\n let current: MarkdownSection | null = null\n\n for (const line of lines) {\n const h2Match = line.match(/^## (.+)/)\n const h1Match = line.match(/^# (.+)/)\n\n if (h1Match) {\n if (current) sections.push(current)\n current = {\n id: `section-${sections.length}`,\n heading: h1Match[1]!,\n level: 1,\n content: '',\n }\n } else if (h2Match) {\n if (current) sections.push(current)\n current = {\n id: `section-${sections.length}`,\n heading: h2Match[1]!,\n level: 2,\n content: '',\n }\n } else if (current) {\n current.content += (current.content ? '\\n' : '') + line\n }\n }\n if (current) sections.push(current)\n return sections\n}\n\n/**\n * Convert markdown into SourceNodes for FieldMapper / applyMapping.\n * Order: frontmatter fields, full document body, then H1/H2 sections.\n */\nexport function markdownToSources(markdown: string): SourceNode[] {\n const parsed = parseMarkdownWithFrontmatter(markdown)\n const sections = parseMarkdownSections(parsed.body)\n const sources: SourceNode[] = []\n\n for (const fm of parsed.frontmatter) {\n sources.push({\n id: fm.id,\n label: fm.key,\n kind: 'frontmatter',\n value: fm.value,\n meta: { valueType: fm.valueType },\n })\n }\n\n sources.push({\n id: SECTION_FULL_ID,\n label: 'Full document',\n kind: 'full',\n value: parsed.body,\n })\n\n for (const section of sections) {\n const value =\n section.content.trim().length > 0 ? section.content.trim() : section.heading\n sources.push({\n id: section.id,\n label: section.heading,\n kind: 'section',\n value,\n meta: { level: section.level },\n })\n }\n\n return sources\n}\n","import Parser from 'rss-parser'\nimport { classifyUrl } from '../classifyUrl'\nimport type { SourceNode } from '../types'\n\nexport type ParsedRssChannel = {\n title?: string\n link?: string\n description?: string\n /** Plain serializable item records (dates become ISO strings). */\n items: Record<string, unknown>[]\n}\n\nfunction toPlainItem(item: unknown): Record<string, unknown> {\n try {\n return JSON.parse(JSON.stringify(item)) as Record<string, unknown>\n } catch {\n return { ...(item as Record<string, unknown>) }\n }\n}\n\n/**\n * Same shape and customFields as @seedprotocol/feed `parseRssString`\n * so RSS mapping stays aligned without importing feed's heavy barrel.\n * Also pulls enclosure / media:content for structured media nodes.\n */\nconst parser = new Parser({\n customFields: {\n item: [\n 'featureImage',\n 'feature_image',\n 'content:encoded',\n 'seedUid',\n 'SeedUid',\n ['media:content', 'mediaContent'],\n ['media:thumbnail', 'mediaThumbnail'],\n ],\n },\n})\n\nasync function parseRssString(xml: string): Promise<ParsedRssChannel> {\n const feed = await parser.parseString(xml)\n return {\n title: feed.title,\n link: feed.link,\n description: feed.description,\n items: (feed.items ?? []).map(toPlainItem),\n }\n}\n\nfunction coerceFieldValue(val: unknown): string | null {\n if (val == null) return null\n if (typeof val === 'string') {\n const t = val.trim()\n return t.length > 0 ? t : null\n }\n if (typeof val === 'number' || typeof val === 'boolean') {\n return String(val)\n }\n if (Array.isArray(val)) {\n try {\n return JSON.stringify(val)\n } catch {\n return null\n }\n }\n if (typeof val === 'object') {\n const obj = val as Record<string, unknown>\n if (typeof obj._ === 'string' && obj._.trim()) return obj._.trim()\n if (typeof obj.value === 'string' && obj.value.trim()) return obj.value.trim()\n try {\n return JSON.stringify(val)\n } catch {\n return null\n }\n }\n return null\n}\n\ntype MediaAttrs = {\n url: string\n contentType?: string\n length?: string\n}\n\nfunction pickMediaAttrs(raw: unknown): MediaAttrs | null {\n if (raw == null) return null\n if (typeof raw === 'string') {\n const url = raw.trim()\n return url ? { url } : null\n }\n if (typeof raw !== 'object') return null\n const obj = raw as Record<string, unknown>\n // rss-parser often nests attrs under `$`\n const dollar =\n obj.$ && typeof obj.$ === 'object'\n ? (obj.$ as Record<string, unknown>)\n : undefined\n const urlCandidate =\n (typeof obj.url === 'string' && obj.url) ||\n (typeof dollar?.url === 'string' && dollar.url) ||\n (typeof obj.link === 'string' && obj.link) ||\n null\n if (!urlCandidate || !String(urlCandidate).trim()) return null\n\n const typeRaw =\n (typeof obj.type === 'string' && obj.type) ||\n (typeof dollar?.type === 'string' && dollar.type) ||\n (typeof obj.medium === 'string' && obj.medium) ||\n undefined\n const lengthRaw =\n (typeof obj.length === 'string' && obj.length) ||\n (typeof obj.length === 'number' && String(obj.length)) ||\n (typeof dollar?.length === 'string' && dollar.length) ||\n (typeof dollar?.length === 'number' && String(dollar.length)) ||\n undefined\n\n return {\n url: String(urlCandidate).trim(),\n contentType: typeRaw ? String(typeRaw).trim() : undefined,\n length: lengthRaw ? String(lengthRaw).trim() : undefined,\n }\n}\n\nfunction mediaEntriesFromValue(raw: unknown): MediaAttrs[] {\n if (raw == null) return []\n if (Array.isArray(raw)) {\n return raw.map(pickMediaAttrs).filter((m): m is MediaAttrs => m != null)\n }\n const one = pickMediaAttrs(raw)\n return one ? [one] : []\n}\n\nconst MEDIA_KEYS = new Set([\n 'enclosure',\n 'enclosures',\n 'media:content',\n 'mediaContent',\n 'media:thumbnail',\n 'mediaThumbnail',\n])\n\nfunction pushMediaNode(\n sources: SourceNode[],\n seen: Set<string>,\n id: string,\n label: string,\n media: MediaAttrs,\n): void {\n if (seen.has(id)) return\n seen.add(id)\n const mediaClass = classifyUrl({\n url: media.url,\n contentType: media.contentType,\n })\n sources.push({\n id,\n label,\n kind: 'rssField',\n value: media.url,\n meta: {\n url: media.url,\n contentType: media.contentType,\n length: media.length,\n class: mediaClass,\n },\n })\n}\n\n/**\n * Flatten a parsed RSS/Atom item into SourceNodes (one per string-coercible key).\n * Enclosure / media:content become url + type in `meta` (not stringified objects).\n * Stable ids: `rss-{key}`, `rss-enclosure-0`, …\n */\nexport function rssItemToSources(item: Record<string, unknown>): SourceNode[] {\n const sources: SourceNode[] = []\n const seen = new Set<string>()\n\n let enclosureIndex = 0\n for (const [key, raw] of Object.entries(item)) {\n if (key === 'items' || key.startsWith('$')) continue\n\n if (MEDIA_KEYS.has(key)) {\n const entries = mediaEntriesFromValue(raw)\n for (const media of entries) {\n const id =\n key === 'enclosure' || key === 'enclosures'\n ? `rss-enclosure-${enclosureIndex}`\n : `rss-${key}-${enclosureIndex}`\n const label =\n key === 'enclosure' || key === 'enclosures'\n ? `enclosure[${enclosureIndex}]`\n : `${key}[${enclosureIndex}]`\n pushMediaNode(sources, seen, id, label, media)\n enclosureIndex += 1\n }\n continue\n }\n\n const value = coerceFieldValue(raw)\n if (value == null) continue\n if (seen.has(key)) continue\n seen.add(key)\n\n const node: SourceNode = {\n id: `rss-${key}`,\n label: key,\n kind: 'rssField',\n value,\n }\n\n // Feature image URLs: attach class hint when value looks like a URL\n if (\n (key === 'featureImage' || key === 'feature_image') &&\n /^https?:\\/\\//i.test(value)\n ) {\n node.meta = {\n url: value,\n class: classifyUrl({ url: value }),\n }\n }\n\n sources.push(node)\n }\n\n return sources\n}\n\nexport type RssXmlSourcesResult = {\n channel: {\n title?: string\n link?: string\n description?: string\n }\n /** Source nodes for each feed item, in document order. */\n items: SourceNode[][]\n}\n\n/**\n * Parse RSS/Atom XML and map each item to SourceNodes via rssItemToSources.\n * Compatible with @seedprotocol/feed `parseRssString` field set.\n */\nexport async function rssXmlToSources(\n xml: string,\n): Promise<RssXmlSourcesResult> {\n const parsed = await parseRssString(xml)\n return {\n channel: {\n title: parsed.title,\n link: parsed.link,\n description: parsed.description,\n },\n items: parsed.items.map((item) => rssItemToSources(item)),\n }\n}\n"],"mappings":"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"}
@@ -1,19 +1,79 @@
1
- import React from 'react';
2
- import type { FieldMapping, SourceNode, TargetProperty } from '../types';
1
+ import React, { type ReactNode } from 'react';
2
+ import type { FieldMapping, MappingLookups, SourceNode, TargetProperty } from '../types';
3
+ import type { FieldMapperComponents, FieldMapperSlot, FieldMapperSlots } from './fieldMapperSlots';
4
+ import type { FieldMapperDefaultRows, FieldMapperLayout, FieldMapperRow, FieldMapperRowKey } from './fieldMapperTypes';
5
+ import { type FieldMapperTheme } from './fieldMapperTheme';
6
+ export { connectionStrokeForIndex, FIELD_MAPPER_PAIR_SLOTS, resolveTheme, ensureThemeInjected, buildThemeCss, wrapInThemeLayer, DEFAULT_THEME_CSS, STRUCTURAL_THEME_CSS, PAINT_THEME_CSS, THEME_STYLE_ID, resetThemeInjectionForTests, type FieldMapperTheme, type ResolvedFieldMapperTheme, } from './fieldMapperTheme';
7
+ export { slotClass, resolveSlots, showRowPreview, showJsonPreview, SLOT_BASE_CLASS, type FieldMapperSlot, type FieldMapperSlots, type ResolvedFieldMapperSlots, type FieldMapperComponents, type ResolvedFieldMapperComponents, type FieldMapperSelectProps, type FieldMapperButtonProps, type FieldMapperPillProps, } from './fieldMapperSlots';
8
+ export type { FieldMapperLayout, FieldMapperRowKey, FieldMapperDefaultRows };
3
9
  export type FieldMapperProps = {
10
+ /**
11
+ * Source nodes to display. For `layout="rows"` (default), pass origin
12
+ * sources — transforms are chosen per row. For deprecated `layout="wires"`,
13
+ * pass `buildResolvedSourceNodes(sources)` to show extract/file candidates.
14
+ */
4
15
  sources: SourceNode[];
5
16
  targets: TargetProperty[];
6
17
  mappings: FieldMapping[];
7
18
  onChange: (mappings: FieldMapping[]) => void;
19
+ /**
20
+ * String → seed uid dictionaries for `resolve: 'lookup'` edges.
21
+ * Host should persist alongside `MappingDocument.lookups`.
22
+ */
23
+ lookups?: MappingLookups;
24
+ onLookupsChange?: (lookups: MappingLookups) => void;
8
25
  /** Override default autoMap heuristics. */
9
26
  onAutoMap?: () => FieldMapping[];
10
27
  className?: string;
11
- /** Show JSON preview of applyMapping result. Default true. */
28
+ /**
29
+ * `default` injects structural + paint CSS.
30
+ * `structural` injects layout/spacing only.
31
+ * `none` skips injection (host styles structural classes / CSS vars).
32
+ * `@deprecated` Prefer `none` — `unstyled` is a shim for `none`.
33
+ */
34
+ theme?: FieldMapperTheme;
35
+ /**
36
+ * Optional connector stroke colors (wires layout). When omitted, strokes use
37
+ * `var(--fm-map-N, var(--map-N, currentColor))` for N = 1…8.
38
+ * @deprecated Prefer CSS `--sfm-map-*` / `--fm-map-*` / `--map-*` tokens.
39
+ */
40
+ connectionColors?: string[];
41
+ /**
42
+ * Show JSON preview. Default true.
43
+ * @deprecated Prefer `slots.preview` (`'row' | 'json' | 'both' | false`).
44
+ */
12
45
  showPreview?: boolean;
46
+ /**
47
+ * Authoring surface. Defaults to `'rows'`.
48
+ * `@deprecated` Prefer `'rows'` — `'wires'` remains supported for one minor.
49
+ */
50
+ layout?: FieldMapperLayout;
51
+ /**
52
+ * Which side opens each row when `layout="rows"`.
53
+ * `'property'` (default) cannot represent an invalid state;
54
+ * `'source'` matches the edge list and surfaces conflicts + coverage banners.
55
+ */
56
+ rowKey?: FieldMapperRowKey;
57
+ /** Rows shown before the filter is widened (property mode). */
58
+ defaultRows?: FieldMapperDefaultRows;
59
+ /** Per-slot class injection; merged with package classes, never replacing them. */
60
+ classNames?: Partial<Record<FieldMapperSlot, string>>;
61
+ /** Host design-system controls. Defaults are dependency-free natives. */
62
+ components?: FieldMapperComponents;
63
+ /** Include / exclude structural pieces. Replaces `showPreview`. */
64
+ slots?: FieldMapperSlots;
65
+ /**
66
+ * Optional per-row host chrome (e.g. extract/file Preview). Rendered in
67
+ * `.fm-row-accessory` after the transform control and before remove.
68
+ * Return `null` when nothing to show. Package does not fetch or preview.
69
+ */
70
+ renderRowAccessory?: (row: FieldMapperRow) => ReactNode;
13
71
  };
14
72
  /**
15
- * Generic two-pane field mapper. Props-driven; no Seed hooks or routing.
73
+ * Generic field mapper. Props-driven; no Seed hooks or routing.
74
+ * Default layout is rows; pass `layout="wires"` only if you still need the
75
+ * two-pane connector UI (deprecated).
16
76
  */
17
- export declare function FieldMapper({ sources, targets, mappings, onChange, onAutoMap, className, showPreview, }: FieldMapperProps): React.JSX.Element;
77
+ export declare function FieldMapper({ sources, targets, mappings, onChange, lookups, onLookupsChange, onAutoMap, className, theme, connectionColors, showPreview, layout, rowKey, defaultRows, classNames, components, slots, renderRowAccessory, }: FieldMapperProps): React.JSX.Element;
18
78
  export default FieldMapper;
19
79
  //# sourceMappingURL=FieldMapper.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"FieldMapper.d.ts","sourceRoot":"","sources":["../../src/react/FieldMapper.tsx"],"names":[],"mappings":"AAAA,OAAO,KAMN,MAAM,OAAO,CAAA;AAGd,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAsBxE,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,UAAU,EAAE,CAAA;IACrB,OAAO,EAAE,cAAc,EAAE,CAAA;IACzB,QAAQ,EAAE,YAAY,EAAE,CAAA;IACxB,QAAQ,EAAE,CAAC,QAAQ,EAAE,YAAY,EAAE,KAAK,IAAI,CAAA;IAC5C,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,YAAY,EAAE,CAAA;IAChC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,8DAA8D;IAC9D,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB,CAAA;AA+BD;;GAEG;AACH,wBAAgB,WAAW,CAAC,EAC1B,OAAO,EACP,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,SAAS,EACT,WAAkB,GACnB,EAAE,gBAAgB,qBAsWlB;AAED,eAAe,WAAW,CAAA"}
1
+ {"version":3,"file":"FieldMapper.d.ts","sourceRoot":"","sources":["../../src/react/FieldMapper.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+ import type { FieldMapping, MappingLookups, SourceNode, TargetProperty } from '../types';
3
+ import type { FieldMapperSlot, ResolvedFieldMapperComponents, ResolvedFieldMapperSlots } from './fieldMapperSlots';
4
+ import type { UseFieldMapperResult } from './fieldMapperTypes';
5
+ export type FieldMapperWiresProps = {
6
+ sources: SourceNode[];
7
+ targets: TargetProperty[];
8
+ mappings: FieldMapping[];
9
+ mapper: UseFieldMapperResult;
10
+ lookups?: MappingLookups;
11
+ onLookupsChange?: (lookups: MappingLookups) => void;
12
+ /** @deprecated Prefer CSS map tokens. */
13
+ connectionColors?: string[];
14
+ slots: ResolvedFieldMapperSlots;
15
+ classNames?: Partial<Record<FieldMapperSlot, string>>;
16
+ ui?: ResolvedFieldMapperComponents;
17
+ };
18
+ export declare function FieldMapperWires({ sources, targets, mappings, mapper, lookups, onLookupsChange, connectionColors, slots, classNames, ui, }: FieldMapperWiresProps): React.JSX.Element;
19
+ //# sourceMappingURL=FieldMapperWires.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FieldMapperWires.d.ts","sourceRoot":"","sources":["../../src/react/FieldMapperWires.tsx"],"names":[],"mappings":"AAAA,OAAO,KAMN,MAAM,OAAO,CAAA;AAKd,OAAO,KAAK,EACV,YAAY,EACZ,cAAc,EACd,UAAU,EACV,cAAc,EACf,MAAM,UAAU,CAAA;AACjB,OAAO,KAAK,EACV,eAAe,EACf,6BAA6B,EAC7B,wBAAwB,EACzB,MAAM,oBAAoB,CAAA;AAQ3B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AAiC9D,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,EAAE,UAAU,EAAE,CAAA;IACrB,OAAO,EAAE,cAAc,EAAE,CAAA;IACzB,QAAQ,EAAE,YAAY,EAAE,CAAA;IACxB,MAAM,EAAE,oBAAoB,CAAA;IAC5B,OAAO,CAAC,EAAE,cAAc,CAAA;IACxB,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAA;IACnD,yCAAyC;IACzC,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC3B,KAAK,EAAE,wBAAwB,CAAA;IAC/B,UAAU,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,CAAA;IACrD,EAAE,CAAC,EAAE,6BAA6B,CAAA;CACnC,CAAA;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,OAAO,EACP,OAAO,EACP,QAAQ,EACR,MAAM,EACN,OAAY,EACZ,eAAe,EACf,gBAAgB,EAChB,KAAK,EACL,UAAU,EACV,EAIC,GACF,EAAE,qBAAqB,qBAiUvB"}
@@ -0,0 +1,24 @@
1
+ import React from 'react';
2
+ import type { FieldMapping, MappingLookups, SourceNode, TargetProperty } from '../types';
3
+ import type { FieldMapperSlot } from './fieldMapperSlots';
4
+ export declare function parseUidInput(raw: string): string | string[];
5
+ export declare function formatUidValue(value: string | string[] | undefined): string;
6
+ export declare function setLookupEntry(lookups: MappingLookups, propertyName: string, sourceKey: string, uidRaw: string): MappingLookups;
7
+ export type LookupEditorProps = {
8
+ mode: 'section' | 'row';
9
+ /** Lookup edges to edit. Section: all lookup mappings; row: one property. */
10
+ mappings: FieldMapping[];
11
+ sources: SourceNode[];
12
+ targets: TargetProperty[];
13
+ lookups: MappingLookups;
14
+ onLookupsChange: (lookups: MappingLookups) => void;
15
+ classNames?: Partial<Record<FieldMapperSlot, string>>;
16
+ /** Extra class on the root (e.g. nested-in-row modifier). */
17
+ className?: string;
18
+ };
19
+ /**
20
+ * Relation lookup string → uid editor.
21
+ * `section` lists every lookup edge; `row` edits a single property's table.
22
+ */
23
+ export declare function LookupEditor({ mode, mappings, sources, targets, lookups, onLookupsChange, classNames, className, }: LookupEditorProps): React.JSX.Element | null;
24
+ //# sourceMappingURL=LookupEditor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LookupEditor.d.ts","sourceRoot":"","sources":["../../src/react/LookupEditor.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAA;AAEtC,OAAO,KAAK,EACV,YAAY,EACZ,cAAc,EACd,UAAU,EACV,cAAc,EACf,MAAM,UAAU,CAAA;AACjB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAGzD,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,CAQ5D;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,GAAG,MAAM,CAI3E;AAED,wBAAgB,cAAc,CAC5B,OAAO,EAAE,cAAc,EACvB,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GACb,cAAc,CAehB;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,SAAS,GAAG,KAAK,CAAA;IACvB,6EAA6E;IAC7E,QAAQ,EAAE,YAAY,EAAE,CAAA;IACxB,OAAO,EAAE,UAAU,EAAE,CAAA;IACrB,OAAO,EAAE,cAAc,EAAE,CAAA;IACzB,OAAO,EAAE,cAAc,CAAA;IACvB,eAAe,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAA;IAClD,UAAU,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,CAAA;IACrD,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AA0ED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,EAC3B,IAAI,EACJ,QAAQ,EACR,OAAO,EACP,OAAO,EACP,OAAO,EACP,eAAe,EACf,UAAU,EACV,SAAS,GACV,EAAE,iBAAiB,4BAwCnB"}
@@ -0,0 +1,19 @@
1
+ import React, { type ReactNode } from 'react';
2
+ import type { FieldMapping, MappingLookups, SourceNode, TargetProperty } from '../types';
3
+ import type { FieldMapperSlot, ResolvedFieldMapperComponents, ResolvedFieldMapperSlots } from './fieldMapperSlots';
4
+ import type { FieldMapperDefaultRows, FieldMapperRow, UseFieldMapperResult } from './fieldMapperTypes';
5
+ export type PropertyRowsProps = {
6
+ sources: SourceNode[];
7
+ targets: TargetProperty[];
8
+ mappings: FieldMapping[];
9
+ mapper: UseFieldMapperResult;
10
+ defaultRows?: FieldMapperDefaultRows;
11
+ lookups?: MappingLookups;
12
+ onLookupsChange?: (lookups: MappingLookups) => void;
13
+ slots: ResolvedFieldMapperSlots;
14
+ classNames?: Partial<Record<FieldMapperSlot, string>>;
15
+ ui?: ResolvedFieldMapperComponents;
16
+ renderRowAccessory?: (row: FieldMapperRow) => ReactNode;
17
+ };
18
+ export declare function PropertyRows({ sources, targets, mappings, mapper, defaultRows, lookups, onLookupsChange, slots, classNames, ui, renderRowAccessory, }: PropertyRowsProps): React.JSX.Element;
19
+ //# sourceMappingURL=PropertyRows.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PropertyRows.d.ts","sourceRoot":"","sources":["../../src/react/PropertyRows.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAqB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAChE,OAAO,KAAK,EACV,YAAY,EACZ,cAAc,EAEd,UAAU,EACV,cAAc,EACf,MAAM,UAAU,CAAA;AACjB,OAAO,KAAK,EACV,eAAe,EACf,6BAA6B,EAC7B,wBAAwB,EACzB,MAAM,oBAAoB,CAAA;AAiB3B,OAAO,KAAK,EACV,sBAAsB,EACtB,cAAc,EACd,oBAAoB,EACrB,MAAM,oBAAoB,CAAA;AAU3B,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,UAAU,EAAE,CAAA;IACrB,OAAO,EAAE,cAAc,EAAE,CAAA;IACzB,QAAQ,EAAE,YAAY,EAAE,CAAA;IACxB,MAAM,EAAE,oBAAoB,CAAA;IAC5B,WAAW,CAAC,EAAE,sBAAsB,CAAA;IACpC,OAAO,CAAC,EAAE,cAAc,CAAA;IACxB,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAA;IACnD,KAAK,EAAE,wBAAwB,CAAA;IAC/B,UAAU,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,CAAA;IACrD,EAAE,CAAC,EAAE,6BAA6B,CAAA;IAClC,kBAAkB,CAAC,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,SAAS,CAAA;CACxD,CAAA;AAED,wBAAgB,YAAY,CAAC,EAC3B,OAAO,EACP,OAAO,EACP,QAAQ,EACR,MAAM,EACN,WAAiC,EACjC,OAAY,EACZ,eAAe,EACf,KAAK,EACL,UAAU,EACV,EAIC,EACD,kBAAkB,GACnB,EAAE,iBAAiB,qBA2SnB"}
@@ -0,0 +1,18 @@
1
+ import React, { type ReactNode } from 'react';
2
+ import type { FieldMapping, MappingLookups, SourceNode, TargetProperty } from '../types';
3
+ import type { FieldMapperSlot, ResolvedFieldMapperComponents, ResolvedFieldMapperSlots } from './fieldMapperSlots';
4
+ import type { FieldMapperRow, UseFieldMapperResult } from './fieldMapperTypes';
5
+ export type SourceRowsProps = {
6
+ sources: SourceNode[];
7
+ targets: TargetProperty[];
8
+ mappings: FieldMapping[];
9
+ mapper: UseFieldMapperResult;
10
+ lookups?: MappingLookups;
11
+ onLookupsChange?: (lookups: MappingLookups) => void;
12
+ slots: ResolvedFieldMapperSlots;
13
+ classNames?: Partial<Record<FieldMapperSlot, string>>;
14
+ ui?: ResolvedFieldMapperComponents;
15
+ renderRowAccessory?: (row: FieldMapperRow) => ReactNode;
16
+ };
17
+ export declare function SourceRows({ sources, targets, mappings, mapper, lookups, onLookupsChange, slots, classNames, ui, renderRowAccessory, }: SourceRowsProps): React.JSX.Element;
18
+ //# sourceMappingURL=SourceRows.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SourceRows.d.ts","sourceRoot":"","sources":["../../src/react/SourceRows.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAqB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAChE,OAAO,KAAK,EACV,YAAY,EACZ,cAAc,EAEd,UAAU,EACV,cAAc,EACf,MAAM,UAAU,CAAA;AACjB,OAAO,KAAK,EACV,eAAe,EACf,6BAA6B,EAC7B,wBAAwB,EACzB,MAAM,oBAAoB,CAAA;AAY3B,OAAO,KAAK,EACV,cAAc,EACd,oBAAoB,EACrB,MAAM,oBAAoB,CAAA;AAU3B,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,UAAU,EAAE,CAAA;IACrB,OAAO,EAAE,cAAc,EAAE,CAAA;IACzB,QAAQ,EAAE,YAAY,EAAE,CAAA;IACxB,MAAM,EAAE,oBAAoB,CAAA;IAC5B,OAAO,CAAC,EAAE,cAAc,CAAA;IACxB,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAA;IACnD,KAAK,EAAE,wBAAwB,CAAA;IAC/B,UAAU,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,CAAA;IACrD,EAAE,CAAC,EAAE,6BAA6B,CAAA;IAClC,kBAAkB,CAAC,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,SAAS,CAAA;CACxD,CAAA;AAED,wBAAgB,UAAU,CAAC,EACzB,OAAO,EACP,OAAO,EACP,QAAQ,EACR,MAAM,EACN,OAAY,EACZ,eAAe,EACf,KAAK,EACL,UAAU,EACV,EAIC,EACD,kBAAkB,GACnB,EAAE,eAAe,qBAmNjB"}
@@ -0,0 +1,9 @@
1
+ import React from 'react';
2
+ import type { FieldMapperButtonProps, FieldMapperPillProps, FieldMapperSelectProps } from './fieldMapperSlots';
3
+ /** Default native select used when no `components.Select` is provided. */
4
+ export declare function DefaultSelect({ className, value, onChange, children, disabled, 'aria-label': ariaLabel, }: FieldMapperSelectProps): React.JSX.Element;
5
+ /** Default native button used when no `components.Button` is provided. */
6
+ export declare function DefaultButton({ className, type, onClick, children, disabled, 'aria-label': ariaLabel, 'aria-pressed': ariaPressed, }: FieldMapperButtonProps): React.JSX.Element;
7
+ /** Default span pill used when no `components.Pill` is provided. */
8
+ export declare function DefaultPill({ className, children, }: FieldMapperPillProps): React.JSX.Element;
9
+ //# sourceMappingURL=fieldMapperControls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fieldMapperControls.d.ts","sourceRoot":"","sources":["../../src/react/fieldMapperControls.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,KAAK,EACV,sBAAsB,EACtB,oBAAoB,EACpB,sBAAsB,EACvB,MAAM,oBAAoB,CAAA;AAE3B,0EAA0E;AAC1E,wBAAgB,aAAa,CAAC,EAC5B,SAAS,EACT,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,YAAY,EAAE,SAAS,GACxB,EAAE,sBAAsB,qBAYxB;AAED,0EAA0E;AAC1E,wBAAgB,aAAa,CAAC,EAC5B,SAAS,EACT,IAAe,EACf,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,YAAY,EAAE,SAAS,EACvB,cAAc,EAAE,WAAW,GAC5B,EAAE,sBAAsB,qBAaxB;AAED,oEAAoE;AACpE,wBAAgB,WAAW,CAAC,EAC1B,SAAS,EACT,QAAQ,GACT,EAAE,oBAAoB,qBAEtB"}
@@ -0,0 +1,79 @@
1
+ import type { FieldMapping, MappingLookups, ResolveJob, SourceNode, TargetProperty } from '../types';
2
+ import type { FieldMapperCoverage, FieldMapperOption, FieldMapperRow, FieldMapperRowState } from './fieldMapperTypes';
3
+ export declare function truncateSample(s: string, n?: number): string;
4
+ export declare function formatSourceOptionLabel(source: SourceNode): string;
5
+ /** Origin sources only — rows UI does not list `@extract`/`@file` cards. */
6
+ export declare function originSources(sources: SourceNode[]): SourceNode[];
7
+ export declare function buildSourceOptions(sources: SourceNode[]): FieldMapperOption[];
8
+ export declare function buildPropertyOptions(targets: TargetProperty[]): FieldMapperOption[];
9
+ /**
10
+ * Transform required for a usable apply — mirrors autoMap / applyMapping rules.
11
+ */
12
+ export declare function computeRequiredResolve(source: SourceNode | undefined, target: TargetProperty | undefined): ResolveJob | null;
13
+ export type PreviewForEdgeOptions = {
14
+ target?: TargetProperty;
15
+ lookups?: MappingLookups;
16
+ propertyName?: string;
17
+ };
18
+ /**
19
+ * Sync row preview aligned with `applyMapping` / lookup tables.
20
+ * `extract`/`file` stay descriptive (sync apply skips them).
21
+ * `lookup` shows a table hit when present; otherwise a pending placeholder.
22
+ * Plain copy shows the coerced value when a target is known.
23
+ */
24
+ export declare function previewForEdge(source: SourceNode | undefined, resolve: ResolveJob | undefined, options?: PreviewForEdgeOptions): string;
25
+ /**
26
+ * JSON preview bag: sync `applyMapping` output plus `_pendingResolve` for
27
+ * edges that require a host resolver (matches wires layout).
28
+ */
29
+ export declare function buildSyncPreviewBag(sources: SourceNode[], mappings: FieldMapping[], targets: TargetProperty[]): Record<string, unknown>;
30
+ export declare function rowState(args: {
31
+ mapping?: FieldMapping;
32
+ requiredResolve: ResolveJob | null;
33
+ conflict?: boolean;
34
+ }): FieldMapperRowState;
35
+ export declare function computeCoverage(targets: TargetProperty[], mappings: FieldMapping[]): FieldMapperCoverage;
36
+ export declare function findConflicts(rows: {
37
+ id: string;
38
+ propertyName?: string;
39
+ }[]): Set<string>;
40
+ export declare function attachLookupIfNeeded(edge: FieldMapping, target: TargetProperty | undefined): FieldMapping;
41
+ export declare function upsertPropertyMapping(mappings: FieldMapping[], edge: FieldMapping): FieldMapping[];
42
+ export declare function clearLookupsForProperties(lookups: MappingLookups, propertyNames: string[]): MappingLookups | null;
43
+ export declare function connectSourceToProperty(mappings: FieldMapping[], sources: SourceNode[], targets: TargetProperty[], sourceId: string, propertyName: string): {
44
+ mappings: FieldMapping[];
45
+ clearedLookupProps: string[];
46
+ };
47
+ export declare function removeMappingsForSourceId(mappings: FieldMapping[], sourceId: string): {
48
+ mappings: FieldMapping[];
49
+ clearedLookupProps: string[];
50
+ };
51
+ export declare function buildPropertyModeRows(args: {
52
+ targets: TargetProperty[];
53
+ mappings: FieldMapping[];
54
+ sources: SourceNode[];
55
+ lookups?: MappingLookups;
56
+ /** When set, only these property names appear (add-flow extras). */
57
+ visiblePropertyNames?: Set<string> | null;
58
+ }): FieldMapperRow[];
59
+ export type SourceModeDraft = {
60
+ id: string;
61
+ sourceId?: string;
62
+ propertyName?: string;
63
+ resolve?: ResolveJob;
64
+ };
65
+ export declare function buildSourceModeRows(args: {
66
+ mappings: FieldMapping[];
67
+ edgeIds: string[];
68
+ drafts: SourceModeDraft[];
69
+ sources: SourceNode[];
70
+ targets: TargetProperty[];
71
+ lookups?: MappingLookups;
72
+ }): {
73
+ rows: FieldMapperRow[];
74
+ conflicts: Set<string>;
75
+ };
76
+ export declare function newRowId(prefix: string): string;
77
+ export declare function syncEdgeIds(prev: string[], mappingCount: number): string[];
78
+ export declare function filterPropertyNames(targets: TargetProperty[], mappings: FieldMapping[], mode: 'requiredAndMapped' | 'mapped' | 'all', extra: Set<string>): Set<string> | null;
79
+ //# sourceMappingURL=fieldMapperCore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fieldMapperCore.d.ts","sourceRoot":"","sources":["../../src/react/fieldMapperCore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ import type { ComponentType, MouseEvent, ReactNode } from 'react';
2
+ import type { FieldMapperLayout } from './fieldMapperTypes';
3
+ export type FieldMapperSlot = 'root' | 'toolbar' | 'filter' | 'coverage' | 'autoMapButton' | 'rowList' | 'row' | 'propertyLabel' | 'dataType' | 'sourceSelect' | 'transformSelect' | 'rowAccessory' | 'preview' | 'validation' | 'removeButton' | 'addButton' | 'inspector' | 'lookupEditor' | 'jsonPreview';
4
+ export type FieldMapperSlots = {
5
+ autoMap?: boolean;
6
+ filter?: boolean;
7
+ inspector?: boolean;
8
+ preview?: 'row' | 'json' | 'both' | false;
9
+ /**
10
+ * Lookup editor placement.
11
+ * Unspecified defaults to `'row'` when `layout === 'rows'`, otherwise `'section'`.
12
+ */
13
+ lookups?: 'row' | 'section' | false;
14
+ };
15
+ export type ResolvedFieldMapperSlots = {
16
+ autoMap: boolean;
17
+ filter: boolean;
18
+ inspector: boolean;
19
+ preview: 'row' | 'json' | 'both' | false;
20
+ lookups: 'row' | 'section' | false;
21
+ };
22
+ export type ResolveSlotsOptions = {
23
+ /** Used when `slots.lookups` is unspecified. */
24
+ layout?: FieldMapperLayout;
25
+ };
26
+ export type FieldMapperSelectProps = {
27
+ className?: string;
28
+ value: string;
29
+ onChange: (value: string) => void;
30
+ 'aria-label'?: string;
31
+ children: ReactNode;
32
+ disabled?: boolean;
33
+ };
34
+ export type FieldMapperButtonProps = {
35
+ className?: string;
36
+ type?: 'button' | 'submit' | 'reset';
37
+ onClick?: (e: MouseEvent<HTMLButtonElement>) => void;
38
+ children: ReactNode;
39
+ disabled?: boolean;
40
+ 'aria-label'?: string;
41
+ 'aria-pressed'?: boolean | 'true' | 'false';
42
+ };
43
+ export type FieldMapperPillProps = {
44
+ children: ReactNode;
45
+ className?: string;
46
+ };
47
+ export type FieldMapperComponents = {
48
+ Select?: ComponentType<FieldMapperSelectProps>;
49
+ Button?: ComponentType<FieldMapperButtonProps>;
50
+ Pill?: ComponentType<FieldMapperPillProps>;
51
+ };
52
+ export type ResolvedFieldMapperComponents = {
53
+ Select: ComponentType<FieldMapperSelectProps>;
54
+ Button: ComponentType<FieldMapperButtonProps>;
55
+ Pill: ComponentType<FieldMapperPillProps>;
56
+ };
57
+ /** Package class names per slot (merged with host `classNames`). */
58
+ export declare const SLOT_BASE_CLASS: Record<FieldMapperSlot, string>;
59
+ /** Merge package slot class with optional host classNames entry. */
60
+ export declare function slotClass(slot: FieldMapperSlot, classNames?: Partial<Record<FieldMapperSlot, string>>, extra?: string | null): string;
61
+ /**
62
+ * Resolve slots + deprecated `showPreview` shim.
63
+ * Default preview is `'both'` (row preview + JSON disclosure) when unspecified.
64
+ * Unspecified lookups: `'row'` for rows layout, `'section'` for wires.
65
+ */
66
+ export declare function resolveSlots(slots?: FieldMapperSlots, showPreview?: boolean, options?: ResolveSlotsOptions): ResolvedFieldMapperSlots;
67
+ export declare function showRowPreview(preview: ResolvedFieldMapperSlots['preview']): boolean;
68
+ export declare function showJsonPreview(preview: ResolvedFieldMapperSlots['preview']): boolean;
69
+ //# sourceMappingURL=fieldMapperSlots.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fieldMapperSlots.d.ts","sourceRoot":"","sources":["../../src/react/fieldMapperSlots.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACjE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAE3D,MAAM,MAAM,eAAe,GACvB,MAAM,GACN,SAAS,GACT,QAAQ,GACR,UAAU,GACV,eAAe,GACf,SAAS,GACT,KAAK,GACL,eAAe,GACf,UAAU,GACV,cAAc,GACd,iBAAiB,GACjB,cAAc,GACd,SAAS,GACT,YAAY,GACZ,cAAc,GACd,WAAW,GACX,WAAW,GACX,cAAc,GACd,aAAa,CAAA;AAEjB,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,OAAO,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAA;IACzC;;;OAGG;IACH,OAAO,CAAC,EAAE,KAAK,GAAG,SAAS,GAAG,KAAK,CAAA;CACpC,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG;IACrC,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,EAAE,OAAO,CAAA;IACf,SAAS,EAAE,OAAO,CAAA;IAClB,OAAO,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAA;IACxC,OAAO,EAAE,KAAK,GAAG,SAAS,GAAG,KAAK,CAAA;CACnC,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,gDAAgD;IAChD,MAAM,CAAC,EAAE,iBAAiB,CAAA;CAC3B,CAAA;AAED,MAAM,MAAM,sBAAsB,GAAG;IACnC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,QAAQ,EAAE,SAAS,CAAA;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,sBAAsB,GAAG;IACnC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,IAAI,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,OAAO,CAAA;IACpC,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAA;IACpD,QAAQ,EAAE,SAAS,CAAA;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,cAAc,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAA;CAC5C,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,EAAE,SAAS,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,CAAC,EAAE,aAAa,CAAC,sBAAsB,CAAC,CAAA;IAC9C,MAAM,CAAC,EAAE,aAAa,CAAC,sBAAsB,CAAC,CAAA;IAC9C,IAAI,CAAC,EAAE,aAAa,CAAC,oBAAoB,CAAC,CAAA;CAC3C,CAAA;AAED,MAAM,MAAM,6BAA6B,GAAG;IAC1C,MAAM,EAAE,aAAa,CAAC,sBAAsB,CAAC,CAAA;IAC7C,MAAM,EAAE,aAAa,CAAC,sBAAsB,CAAC,CAAA;IAC7C,IAAI,EAAE,aAAa,CAAC,oBAAoB,CAAC,CAAA;CAC1C,CAAA;AAED,oEAAoE;AACpE,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,eAAe,EAAE,MAAM,CAoB3D,CAAA;AAED,oEAAoE;AACpE,wBAAgB,SAAS,CACvB,IAAI,EAAE,eAAe,EACrB,UAAU,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC,EACrD,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GACpB,MAAM,CAIR;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,KAAK,CAAC,EAAE,gBAAgB,EACxB,WAAW,CAAC,EAAE,OAAO,EACrB,OAAO,CAAC,EAAE,mBAAmB,GAC5B,wBAAwB,CA0B1B;AAED,wBAAgB,cAAc,CAC5B,OAAO,EAAE,wBAAwB,CAAC,SAAS,CAAC,GAC3C,OAAO,CAET;AAED,wBAAgB,eAAe,CAC7B,OAAO,EAAE,wBAAwB,CAAC,SAAS,CAAC,GAC3C,OAAO,CAET"}
@@ -0,0 +1,34 @@
1
+ /** Number of cycling pair / map-color slots (`--fm-map-1` … `--fm-map-8`). */
2
+ export declare const FIELD_MAPPER_PAIR_SLOTS = 8;
3
+ /**
4
+ * Theme modes for FieldMapper.
5
+ * `'unstyled'` is a deprecated alias for `'none'` (kept for one minor).
6
+ */
7
+ export type FieldMapperTheme = 'default' | 'structural' | 'none' | 'unstyled';
8
+ export type ResolvedFieldMapperTheme = 'default' | 'structural' | 'none';
9
+ export declare const THEME_STYLE_ID = "seed-field-mapper-theme";
10
+ declare function pairSlot(index: number): number;
11
+ /** Stroke for mapping index `i` — CSS vars by default so hosts can theme. */
12
+ export declare function connectionStrokeForIndex(index: number, connectionColors?: string[]): string;
13
+ export { pairSlot };
14
+ /** Map public theme prop (including deprecated `unstyled`) to a resolved mode. */
15
+ export declare function resolveTheme(theme?: FieldMapperTheme): ResolvedFieldMapperTheme;
16
+ /** Layout / spacing / display rules — no color paint. */
17
+ export declare const STRUCTURAL_THEME_CSS = "\n.seed-field-mapper {\n\n --sfm-space-1: 4px;\n --sfm-space-2: 8px;\n --sfm-space-3: 12px;\n --sfm-space-4: 16px;\n --sfm-radius-sm: 4px;\n --sfm-radius-md: 8px;\n --sfm-radius-lg: 12px;\n --sfm-font-family: inherit;\n --sfm-font-mono: ui-monospace, monospace;\n --sfm-font-size-sm: 11px;\n --sfm-font-size-md: 13px;\n --sfm-control-height: 32px;\n --sfm-row-gap: var(--sfm-space-2);\n\n font-family: var(--sfm-font-family);\n border-radius: var(--sfm-radius-lg);\n padding: var(--sfm-space-4);\n}\n.seed-field-mapper * { box-sizing: border-box; }\n.seed-field-mapper .fm-toolbar {\n display: flex;\n gap: var(--sfm-space-2);\n align-items: center;\n margin-bottom: var(--sfm-space-3);\n flex-wrap: wrap;\n}\n.seed-field-mapper .fm-btn {\n border: 1px solid;\n border-radius: var(--sfm-radius-md);\n padding: 6px var(--sfm-space-3);\n cursor: pointer;\n font-size: var(--sfm-font-size-md);\n min-height: var(--sfm-control-height);\n}\n.seed-field-mapper .fm-meta {\n font-size: 12px;\n margin-left: auto;\n}\n.seed-field-mapper .fm-banner {\n font-size: 12px;\n padding: var(--sfm-space-2) 10px;\n border-radius: var(--sfm-radius-md);\n margin-bottom: 10px;\n border: 1px solid;\n}\n.seed-field-mapper .fm-grid {\n position: relative;\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 48px;\n min-height: 240px;\n}\n.seed-field-mapper .fm-col-title {\n font-size: var(--sfm-font-size-sm);\n text-transform: uppercase;\n letter-spacing: 0.06em;\n margin-bottom: var(--sfm-space-2);\n}\n.seed-field-mapper .fm-card {\n border: 1px solid;\n border-radius: var(--sfm-radius-md);\n padding: 10px var(--sfm-space-3);\n margin-bottom: var(--sfm-space-2);\n cursor: pointer;\n transition: border-color 0.15s, box-shadow 0.15s;\n}\n.seed-field-mapper .fm-label {\n font-weight: 600;\n font-size: var(--sfm-font-size-md);\n margin-bottom: var(--sfm-space-1);\n}\n.seed-field-mapper .fm-value {\n font-family: var(--sfm-font-mono);\n font-size: var(--sfm-font-size-sm);\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n.seed-field-mapper .fm-kind {\n font-size: 10px;\n margin-left: 6px;\n}\n.seed-field-mapper .fm-prop-row {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--sfm-space-2);\n}\n.seed-field-mapper .fm-dtype {\n font-size: 10px;\n padding: 2px 6px;\n border-radius: var(--sfm-radius-sm);\n border: 1px solid;\n}\n.seed-field-mapper .fm-remove {\n background: transparent;\n border: none;\n cursor: pointer;\n font-size: 14px;\n padding: 0 var(--sfm-space-1);\n}\n.seed-field-mapper .fm-svg {\n position: absolute;\n inset: 0;\n pointer-events: none;\n overflow: visible;\n}\n.seed-field-mapper .fm-preview {\n margin-top: var(--sfm-space-3);\n border: 1px solid;\n border-radius: var(--sfm-radius-md);\n padding: var(--sfm-space-3);\n font-family: var(--sfm-font-mono);\n font-size: var(--sfm-font-size-sm);\n white-space: pre-wrap;\n max-height: 200px;\n overflow: auto;\n}\n.seed-field-mapper details.fm-preview {\n font-family: var(--sfm-font-family);\n white-space: normal;\n max-height: none;\n overflow: visible;\n padding: var(--sfm-space-2) var(--sfm-space-3);\n}\n.seed-field-mapper details.fm-preview > summary {\n cursor: pointer;\n font-size: var(--sfm-font-size-sm);\n list-style: disclosure-closed;\n}\n.seed-field-mapper details.fm-preview[open] > summary {\n list-style: disclosure-open;\n margin-bottom: var(--sfm-space-2);\n}\n.seed-field-mapper .fm-preview-body {\n margin: 0;\n font-family: var(--sfm-font-mono);\n font-size: var(--sfm-font-size-sm);\n white-space: pre-wrap;\n max-height: 200px;\n overflow: auto;\n}\n.seed-field-mapper .fm-lookups {\n margin-top: var(--sfm-space-4);\n border-top: 1px solid;\n padding-top: var(--sfm-space-3);\n}\n.seed-field-mapper .fm-row .fm-lookups,\n.seed-field-mapper .fm-lookups--row {\n margin-top: var(--sfm-space-2);\n border-top: none;\n padding-top: 0;\n}\n.seed-field-mapper .fm-row .fm-lookup-block {\n margin-bottom: 0;\n padding: var(--sfm-space-2);\n}\n.seed-field-mapper .fm-lookups-title {\n font-size: var(--sfm-font-size-sm);\n text-transform: uppercase;\n letter-spacing: 0.06em;\n margin-bottom: var(--sfm-space-2);\n}\n.seed-field-mapper .fm-lookup-block {\n border: 1px solid;\n border-radius: var(--sfm-radius-md);\n padding: 10px var(--sfm-space-3);\n margin-bottom: var(--sfm-space-2);\n}\n.seed-field-mapper .fm-lookup-block h4 {\n margin: 0 0 var(--sfm-space-2);\n font-size: var(--sfm-font-size-md);\n font-weight: 600;\n}\n.seed-field-mapper .fm-lookup-hint {\n font-size: var(--sfm-font-size-sm);\n margin-bottom: var(--sfm-space-2);\n}\n.seed-field-mapper .fm-lookup-row {\n display: grid;\n grid-template-columns: 1fr 1.4fr;\n gap: var(--sfm-space-2);\n align-items: center;\n margin-bottom: 6px;\n}\n.seed-field-mapper .fm-lookup-key {\n font-family: var(--sfm-font-mono);\n font-size: var(--sfm-font-size-sm);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n.seed-field-mapper .fm-lookup-input {\n width: 100%;\n border: 1px solid;\n border-radius: 6px;\n font-family: var(--sfm-font-mono);\n font-size: var(--sfm-font-size-sm);\n padding: 6px var(--sfm-space-2);\n}\n.seed-field-mapper .fm-lookup-input:focus {\n outline: none;\n}\n.seed-field-mapper .fm-row-list {\n display: flex;\n flex-direction: column;\n gap: var(--sfm-row-gap);\n}\n.seed-field-mapper .fm-row {\n border: 1px solid;\n border-radius: var(--sfm-radius-md);\n padding: 10px var(--sfm-space-3);\n}\n.seed-field-mapper .fm-row-main {\n display: grid;\n grid-template-columns: minmax(100px, 140px) 1fr auto auto auto;\n gap: var(--sfm-space-2);\n align-items: center;\n}\n.seed-field-mapper .fm-row-main-source {\n grid-template-columns: 1fr auto auto 1fr auto auto;\n}\n.seed-field-mapper .fm-row-accessory {\n display: flex;\n align-items: center;\n min-width: 0;\n}\n.seed-field-mapper .fm-row-accessory:empty {\n display: none;\n}\n.seed-field-mapper .fm-row-prop {\n display: flex;\n flex-direction: column;\n gap: 2px;\n min-width: 0;\n}\n.seed-field-mapper .fm-row-prop-name {\n font-weight: 600;\n font-size: var(--sfm-font-size-md);\n}\n.seed-field-mapper .fm-row-preview {\n margin-top: 6px;\n font-family: var(--sfm-font-mono);\n font-size: var(--sfm-font-size-sm);\n}\n.seed-field-mapper .fm-row-flag {\n font-size: var(--sfm-font-size-sm);\n margin-top: var(--sfm-space-1);\n}\n.seed-field-mapper .fm-select {\n width: 100%;\n border: 1px solid;\n border-radius: 6px;\n font-size: 12px;\n padding: 6px var(--sfm-space-2);\n min-width: 0;\n min-height: var(--sfm-control-height);\n}\n.seed-field-mapper .fm-select:focus {\n outline: none;\n}\n.seed-field-mapper .fm-filter {\n display: flex;\n gap: 6px;\n margin-bottom: 10px;\n flex-wrap: wrap;\n}\n.seed-field-mapper .fm-inspector {\n margin-top: var(--sfm-space-3);\n border-top: 1px solid;\n padding-top: 10px;\n}\n.seed-field-mapper .fm-inspector summary {\n cursor: pointer;\n font-size: 12px;\n margin-bottom: var(--sfm-space-2);\n}\n.seed-field-mapper .fm-inspector-row {\n display: grid;\n grid-template-columns: 1fr 1.5fr auto;\n gap: var(--sfm-space-2);\n align-items: center;\n padding: 6px 0;\n border-bottom: 1px solid;\n font-size: 12px;\n}\n.seed-field-mapper .fm-into {\n font-size: var(--sfm-font-size-sm);\n}\n";
18
+ /** Color / background / border-color paint on top of structural layout. */
19
+ export declare const PAINT_THEME_CSS = "\n.seed-field-mapper {\n\n --sfm-color-ground: #0f172a;\n --sfm-color-ink: #e2e8f0;\n --sfm-color-well: #1e293b;\n --sfm-color-line: #334155;\n --sfm-color-muted: #94a3b8;\n --sfm-color-faint: #64748b;\n --sfm-color-selection: #3b82f6;\n --sfm-color-warning: #fbbf24;\n --sfm-color-danger: #f87171;\n --sfm-color-highlight: #f59e0b;\n --sfm-map-1: #3b82f6;\n --sfm-map-2: #8b5cf6;\n --sfm-map-3: #ec4899;\n --sfm-map-4: #f59e0b;\n --sfm-map-5: #10b981;\n --sfm-map-6: #06b6d4;\n --sfm-map-7: #f97316;\n --sfm-map-8: #14b8a6;\n --fm-ground: var(--sfm-color-ground);\n --fm-ink: var(--sfm-color-ink);\n --fm-well: var(--sfm-color-well);\n --fm-line: var(--sfm-color-line);\n --fm-muted: var(--sfm-color-muted);\n --fm-faint: var(--sfm-color-faint);\n --fm-selection: var(--sfm-color-selection);\n --fm-highlight: var(--sfm-color-highlight);\n --fm-danger: var(--sfm-color-danger);\n --fm-warning: var(--sfm-color-warning);\n --fm-map-1: var(--sfm-map-1);\n --fm-map-2: var(--sfm-map-2);\n --fm-map-3: var(--sfm-map-3);\n --fm-map-4: var(--sfm-map-4);\n --fm-map-5: var(--sfm-map-5);\n --fm-map-6: var(--sfm-map-6);\n --fm-map-7: var(--sfm-map-7);\n --fm-map-8: var(--sfm-map-8);\n\n color: var(--sfm-color-ink);\n background: var(--sfm-color-ground);\n}\n.seed-field-mapper .fm-btn {\n background: var(--sfm-color-well);\n border-color: var(--sfm-color-line);\n color: var(--sfm-color-ink);\n}\n.seed-field-mapper .fm-btn:hover { border-color: var(--sfm-color-faint); }\n.seed-field-mapper .fm-btn-primary {\n background: var(--sfm-color-selection);\n border-color: var(--sfm-color-selection);\n}\n.seed-field-mapper .fm-meta {\n color: var(--sfm-color-muted);\n}\n.seed-field-mapper .fm-banner {\n border-color: var(--sfm-color-line);\n background: var(--sfm-color-well);\n}\n.seed-field-mapper .fm-banner-warn {\n border-color: var(--sfm-color-warning);\n color: var(--sfm-color-warning);\n}\n.seed-field-mapper .fm-banner-danger {\n border-color: var(--sfm-color-danger);\n color: var(--sfm-color-danger);\n}\n.seed-field-mapper .fm-col-title {\n color: var(--sfm-color-faint);\n}\n.seed-field-mapper .fm-card {\n border-color: var(--sfm-color-line);\n background: var(--sfm-color-well);\n}\n.seed-field-mapper .fm-card.active,\n.seed-field-mapper .fm-card.pending {\n border-color: var(--sfm-color-selection);\n box-shadow: 0 0 0 1px var(--sfm-color-selection);\n}\n.seed-field-mapper .fm-card.mapped {\n border-color: var(--sfm-color-faint);\n}\n.seed-field-mapper .fm-card.highlight {\n border-color: var(--sfm-color-highlight);\n}\n.seed-field-mapper .fm-value {\n color: var(--sfm-color-muted);\n}\n.seed-field-mapper .fm-kind {\n color: var(--sfm-color-faint);\n}\n.seed-field-mapper .fm-dtype {\n border-color: var(--sfm-color-line);\n color: var(--sfm-color-muted);\n background: transparent;\n}\n.seed-field-mapper .fm-remove {\n color: var(--sfm-color-muted);\n}\n.seed-field-mapper .fm-remove:hover { color: var(--sfm-color-danger); }\n.seed-field-mapper .fm-preview {\n background: color-mix(in srgb, var(--sfm-color-ground) 80%, black);\n border-color: var(--sfm-color-line);\n color: var(--sfm-color-ink);\n}\n.seed-field-mapper details.fm-preview > summary {\n color: var(--sfm-color-muted);\n}\n.seed-field-mapper .fm-lookups {\n border-color: var(--sfm-color-line);\n}\n.seed-field-mapper .fm-lookups-title {\n color: var(--sfm-color-faint);\n}\n.seed-field-mapper .fm-lookup-block {\n border-color: var(--sfm-color-line);\n background: var(--sfm-color-well);\n}\n.seed-field-mapper .fm-lookup-hint {\n color: var(--sfm-color-muted);\n}\n.seed-field-mapper .fm-lookup-key {\n color: var(--sfm-color-muted);\n}\n.seed-field-mapper .fm-lookup-input {\n background: var(--sfm-color-ground);\n border-color: var(--sfm-color-line);\n color: var(--sfm-color-ink);\n}\n.seed-field-mapper .fm-lookup-input:focus {\n border-color: var(--sfm-color-selection);\n}\n.seed-field-mapper .fm-row {\n border-color: var(--sfm-color-line);\n background: var(--sfm-color-well);\n}\n.seed-field-mapper .fm-row[data-state=\"needsResolve\"] {\n border-color: var(--sfm-color-warning);\n}\n.seed-field-mapper .fm-row[data-state=\"conflict\"] {\n border-color: var(--sfm-color-danger);\n}\n.seed-field-mapper .fm-row-preview {\n color: var(--sfm-color-muted);\n}\n.seed-field-mapper .fm-row-flag {\n color: var(--sfm-color-warning);\n}\n.seed-field-mapper .fm-select {\n background: var(--sfm-color-ground);\n border-color: var(--sfm-color-line);\n color: var(--sfm-color-ink);\n}\n.seed-field-mapper .fm-select:focus {\n border-color: var(--sfm-color-selection);\n}\n.seed-field-mapper .fm-filter .fm-btn[aria-pressed=\"true\"] {\n border-color: var(--sfm-color-selection);\n color: var(--sfm-color-ink);\n}\n.seed-field-mapper .fm-inspector {\n border-color: var(--sfm-color-line);\n}\n.seed-field-mapper .fm-inspector summary {\n color: var(--sfm-color-muted);\n}\n.seed-field-mapper .fm-inspector-row {\n border-color: var(--sfm-color-line);\n}\n.seed-field-mapper .fm-into {\n color: var(--sfm-color-faint);\n}\n";
20
+ /** Wrap CSS in the package cascade layer so host rules win without specificity fights. */
21
+ export declare function wrapInThemeLayer(css: string): string;
22
+ /** Build the CSS string for a resolved theme mode (`none` → empty). */
23
+ export declare function buildThemeCss(theme: ResolvedFieldMapperTheme): string;
24
+ /** Full default theme CSS (structural + paint, layered). Exported for tests / hosts. */
25
+ export declare const DEFAULT_THEME_CSS: string;
26
+ /**
27
+ * Inject theme CSS once into `document.head`. Updates the existing style node
28
+ * when the resolved theme changes. No-op when `document` is unavailable (SSR)
29
+ * or when `theme === 'none'`.
30
+ */
31
+ export declare function ensureThemeInjected(theme: ResolvedFieldMapperTheme): void;
32
+ /** Test helper: reset document-once injection bookkeeping. */
33
+ export declare function resetThemeInjectionForTests(): void;
34
+ //# sourceMappingURL=fieldMapperTheme.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fieldMapperTheme.d.ts","sourceRoot":"","sources":["../../src/react/fieldMapperTheme.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,eAAO,MAAM,uBAAuB,IAAI,CAAA;AAExC;;;GAGG;AACH,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,YAAY,GAAG,MAAM,GAAG,UAAU,CAAA;AAE7E,MAAM,MAAM,wBAAwB,GAAG,SAAS,GAAG,YAAY,GAAG,MAAM,CAAA;AAExE,eAAO,MAAM,cAAc,4BAA4B,CAAA;AAEvD,iBAAS,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEvC;AAED,6EAA6E;AAC7E,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,MAAM,EACb,gBAAgB,CAAC,EAAE,MAAM,EAAE,GAC1B,MAAM,CAMR;AAED,OAAO,EAAE,QAAQ,EAAE,CAAA;AAEnB,kFAAkF;AAClF,wBAAgB,YAAY,CAC1B,KAAK,GAAE,gBAA4B,GAClC,wBAAwB,CAG1B;AAyDD,yDAAyD;AACzD,eAAO,MAAM,oBAAoB,0xOAsRhC,CAAA;AAED,2EAA2E;AAC3E,eAAO,MAAM,eAAe,q/JAwI3B,CAAA;AAED,0FAA0F;AAC1F,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,uEAAuE;AACvE,wBAAgB,aAAa,CAAC,KAAK,EAAE,wBAAwB,GAAG,MAAM,CAMrE;AAED,wFAAwF;AACxF,eAAO,MAAM,iBAAiB,QAA2B,CAAA;AAIzD;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,wBAAwB,GAAG,IAAI,CAsBzE;AAED,8DAA8D;AAC9D,wBAAgB,2BAA2B,IAAI,IAAI,CAUlD"}