@open-mercato/ui 0.4.6-develop-ce2a0728a5 → 0.4.6-develop-77fa3b7ed8

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 (48) hide show
  1. package/AGENTS.md +16 -0
  2. package/dist/backend/CrudForm.js +138 -17
  3. package/dist/backend/CrudForm.js.map +3 -3
  4. package/dist/backend/DataTable.js +297 -24
  5. package/dist/backend/DataTable.js.map +3 -3
  6. package/dist/backend/detail/ActivitiesSection.js +11 -1
  7. package/dist/backend/detail/ActivitiesSection.js.map +2 -2
  8. package/dist/backend/detail/AddressesSection.js +11 -1
  9. package/dist/backend/detail/AddressesSection.js.map +2 -2
  10. package/dist/backend/detail/AttachmentsSection.js +11 -1
  11. package/dist/backend/detail/AttachmentsSection.js.map +2 -2
  12. package/dist/backend/detail/CustomDataSection.js +11 -1
  13. package/dist/backend/detail/CustomDataSection.js.map +2 -2
  14. package/dist/backend/detail/DetailFieldsSection.js +11 -1
  15. package/dist/backend/detail/DetailFieldsSection.js.map +2 -2
  16. package/dist/backend/detail/NotesSection.js +11 -1
  17. package/dist/backend/detail/NotesSection.js.map +2 -2
  18. package/dist/backend/detail/TagsSection.js +11 -1
  19. package/dist/backend/detail/TagsSection.js.map +2 -2
  20. package/dist/backend/injection/ComponentOverrideProvider.js +54 -0
  21. package/dist/backend/injection/ComponentOverrideProvider.js.map +7 -0
  22. package/dist/backend/injection/InjectedField.js +166 -0
  23. package/dist/backend/injection/InjectedField.js.map +7 -0
  24. package/dist/backend/injection/spotIds.js +5 -1
  25. package/dist/backend/injection/spotIds.js.map +2 -2
  26. package/dist/backend/injection/useRegisteredComponent.js +89 -0
  27. package/dist/backend/injection/useRegisteredComponent.js.map +7 -0
  28. package/dist/backend/injection/visibility-utils.js +29 -0
  29. package/dist/backend/injection/visibility-utils.js.map +7 -0
  30. package/package.json +2 -2
  31. package/src/backend/AGENTS.md +7 -0
  32. package/src/backend/CrudForm.tsx +144 -16
  33. package/src/backend/DataTable.tsx +342 -22
  34. package/src/backend/__tests__/DataTable.extensions.test.tsx +115 -0
  35. package/src/backend/__tests__/DataTable.namespaces.test.ts +32 -0
  36. package/src/backend/__tests__/component-replacement.test.tsx +232 -0
  37. package/src/backend/detail/ActivitiesSection.tsx +17 -1
  38. package/src/backend/detail/AddressesSection.tsx +17 -1
  39. package/src/backend/detail/AttachmentsSection.tsx +17 -1
  40. package/src/backend/detail/CustomDataSection.tsx +17 -1
  41. package/src/backend/detail/DetailFieldsSection.tsx +17 -1
  42. package/src/backend/detail/NotesSection.tsx +17 -1
  43. package/src/backend/detail/TagsSection.tsx +17 -1
  44. package/src/backend/injection/ComponentOverrideProvider.tsx +65 -0
  45. package/src/backend/injection/InjectedField.tsx +194 -0
  46. package/src/backend/injection/spotIds.ts +4 -0
  47. package/src/backend/injection/useRegisteredComponent.tsx +106 -0
  48. package/src/backend/injection/visibility-utils.ts +31 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/backend/detail/NotesSection.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport dynamic from 'next/dynamic'\nimport type { PluggableList } from 'unified'\nimport type { AppearanceSelectorLabels } from '@open-mercato/core/modules/dictionaries/components/AppearanceSelector'\nimport { AppearanceDialog } from '@open-mercato/core/modules/customers/components/detail/AppearanceDialog'\nimport type { IconOption } from '@open-mercato/core/modules/dictionaries/components/dictionaryAppearance'\nimport { ArrowUpRightSquare, FileCode, Loader2, Palette, Pencil, Plus, Trash2 } from 'lucide-react'\nimport { formatRelativeTime } from '@open-mercato/shared/lib/time'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { flash } from '../FlashMessages'\nimport { SwitchableMarkdownInput } from '../inputs/SwitchableMarkdownInput'\nimport { ErrorMessage } from './ErrorMessage'\nimport { LoadingMessage } from './LoadingMessage'\nimport { TabEmptyState } from './TabEmptyState'\nimport { useConfirmDialog } from '../confirm-dialog'\nimport { formatDateTime } from '@open-mercato/shared/lib/time'\ntype Translator = (key: string, fallback?: string, params?: Record<string, string | number>) => string\n\nexport type SectionAction = {\n label: React.ReactNode\n onClick: () => void\n disabled?: boolean\n icon?: React.ReactNode\n}\n\nexport type TabEmptyStateConfig = {\n title: string\n actionLabel: string\n description?: string\n}\n\nexport type CommentSummary = {\n id: string\n body: string\n createdAt: string\n authorUserId?: string | null\n authorName?: string | null\n authorEmail?: string | null\n dealId?: string | null\n dealTitle?: string | null\n appearanceIcon?: string | null\n appearanceColor?: string | null\n}\n\nexport type NotesCreatePayload = {\n entityId: string\n body: string\n appearanceIcon: string | null\n appearanceColor: string | null\n dealId?: string | null\n}\n\nexport type NotesUpdatePayload = {\n body?: string\n appearanceIcon?: string | null\n appearanceColor?: string | null\n}\n\nexport type NotesDataAdapter<C = unknown> = {\n list: (params: { entityId: string | null; dealId: string | null; context?: C }) => Promise<CommentSummary[]>\n create: (params: NotesCreatePayload & { context?: C }) => Promise<Partial<CommentSummary> | void>\n update: (params: { id: string; patch: NotesUpdatePayload; context?: C }) => Promise<void>\n delete: (params: { id: string; context?: C }) => Promise<void>\n}\n\ntype RenderIconFn = (icon: string, className?: string) => React.ReactNode\ntype RenderColorFn = (color: string, className?: string) => React.ReactNode\n\ntype MarkdownPreviewProps = { children: string; className?: string; remarkPlugins?: PluggableList }\n\nconst isTestEnv = typeof process !== 'undefined' && process.env.NODE_ENV === 'test'\n\nconst MarkdownPreviewComponent: React.ComponentType<MarkdownPreviewProps> = isTestEnv\n ? ({ children, className }) => <div className={className}>{children}</div>\n : (dynamic(() => import('react-markdown').then((mod) => mod.default as React.ComponentType<MarkdownPreviewProps>), {\n ssr: false,\n loading: () => null,\n }) as unknown as React.ComponentType<MarkdownPreviewProps>)\n\nlet markdownPluginsPromise: Promise<PluggableList> | null = null\n\nasync function loadMarkdownPlugins(): Promise<PluggableList> {\n if (isTestEnv) return []\n if (!markdownPluginsPromise) {\n markdownPluginsPromise = import('remark-gfm')\n .then((mod) => [mod.default ?? mod] as PluggableList)\n .catch(() => [])\n }\n return markdownPluginsPromise\n}\n\nfunction generateTempId() {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') return crypto.randomUUID()\n return `tmp_${Math.random().toString(36).slice(2)}`\n}\n\n\n\ntype TimelineItemHeaderProps = {\n title: React.ReactNode\n subtitle?: React.ReactNode\n timestamp?: string | Date | null\n fallbackTimestampLabel?: React.ReactNode\n icon?: string | null\n color?: string | null\n iconSize?: 'sm' | 'md'\n className?: string\n renderIcon?: RenderIconFn\n renderColor?: RenderColorFn\n}\n\nfunction TimelineItemHeader({\n title,\n subtitle,\n timestamp,\n fallbackTimestampLabel,\n icon,\n color,\n iconSize = 'md',\n className,\n renderIcon,\n renderColor,\n}: TimelineItemHeaderProps) {\n const wrapperSize = iconSize === 'sm' ? 'h-6 w-6' : 'h-8 w-8'\n const iconSizeClass = iconSize === 'sm' ? 'h-3.5 w-3.5' : 'h-4 w-4'\n const resolvedTimestamp = React.useMemo(() => {\n if (subtitle) return subtitle\n if (!timestamp) return fallbackTimestampLabel ?? null\n const value = typeof timestamp === 'string' ? timestamp : timestamp.toISOString()\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) return fallbackTimestampLabel ?? null\n const now = Date.now()\n const diff = Math.abs(now - date.getTime())\n const THIRTY_DAYS_MS = 30 * 24 * 60 * 60 * 1000\n const relativeLabel = diff <= THIRTY_DAYS_MS ? formatRelativeTime(value) : null\n const absoluteLabel = formatDateTime(value)\n if (relativeLabel) {\n return (\n <span title={absoluteLabel ?? undefined}>\n {relativeLabel}\n </span>\n )\n }\n return absoluteLabel ?? fallbackTimestampLabel ?? null\n }, [fallbackTimestampLabel, subtitle, timestamp])\n\n return (\n <div className={['flex items-start gap-3', className].filter(Boolean).join(' ')}>\n {icon && renderIcon ? (\n <span className={['inline-flex items-center justify-center rounded border border-border bg-muted/40', wrapperSize].join(' ')}>\n {renderIcon(icon, iconSizeClass)}\n </span>\n ) : null}\n <div className=\"space-y-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"text-sm font-semibold text-foreground\">{title}</span>\n {color && renderColor ? renderColor(color, 'h-3 w-3 rounded-full border border-border') : null}\n </div>\n {resolvedTimestamp ? <div className=\"text-xs text-muted-foreground\">{resolvedTimestamp}</div> : null}\n </div>\n </div>\n )\n}\n\nexport type NotesSectionProps<C = unknown> = {\n entityId: string | null\n dealId?: string | null\n emptyLabel: string\n viewerUserId: string | null\n viewerName?: string | null\n viewerEmail?: string | null\n addActionLabel: string\n emptyState: TabEmptyStateConfig\n onActionChange?: (action: SectionAction | null) => void\n translator?: Translator\n labelPrefix?: string\n inlineLabelPrefix?: string\n onLoadingChange?: (isLoading: boolean) => void\n dealOptions?: Array<{ id: string; label: string }>\n entityOptions?: Array<{ id: string; label: string }>\n dataAdapter: NotesDataAdapter<C>\n dataContext?: C\n renderIcon?: RenderIconFn\n renderColor?: RenderColorFn\n iconSuggestions?: IconOption[]\n readMarkdownPreference?: () => boolean | null\n writeMarkdownPreference?: (value: boolean) => void\n disableMarkdown?: boolean\n}\n\nexport function sanitizeHexColor(value: string | null): string | null {\n if (!value) return null\n const trimmed = value.trim()\n return /^#([0-9a-f]{6})$/i.test(trimmed) ? trimmed.toLowerCase() : null\n}\n\nexport function mapCommentSummary(input: unknown): CommentSummary {\n const data = (typeof input === 'object' && input !== null ? input : {}) as Record<string, unknown>\n const id = typeof data.id === 'string' ? data.id : generateTempId()\n const body = typeof data.body === 'string' ? data.body : ''\n const createdAt =\n typeof data.createdAt === 'string'\n ? data.createdAt\n : typeof data.created_at === 'string'\n ? data.created_at\n : new Date().toISOString()\n const authorUserId =\n typeof data.authorUserId === 'string'\n ? data.authorUserId\n : typeof data.author_user_id === 'string'\n ? data.author_user_id\n : null\n const authorName =\n typeof data.authorName === 'string'\n ? data.authorName\n : typeof data.author_name === 'string'\n ? data.author_name\n : null\n const authorEmail =\n typeof data.authorEmail === 'string'\n ? data.authorEmail\n : typeof data.author_email === 'string'\n ? data.author_email\n : null\n const dealId =\n typeof data.dealId === 'string'\n ? data.dealId\n : typeof data.deal_id === 'string'\n ? data.deal_id\n : null\n const dealTitle =\n typeof data.dealTitle === 'string'\n ? data.dealTitle\n : typeof data.deal_title === 'string'\n ? data.deal_title\n : null\n const appearanceIcon =\n typeof data.appearanceIcon === 'string'\n ? data.appearanceIcon\n : typeof data.appearance_icon === 'string'\n ? data.appearance_icon\n : null\n const appearanceColor =\n typeof data.appearanceColor === 'string'\n ? data.appearanceColor\n : typeof data.appearance_color === 'string'\n ? data.appearance_color\n : null\n return {\n id,\n body,\n createdAt,\n authorUserId,\n authorName,\n authorEmail,\n dealId,\n dealTitle,\n appearanceIcon,\n appearanceColor,\n }\n}\n\nexport function NotesSection<C = unknown>({\n entityId,\n dealId,\n emptyLabel,\n viewerUserId,\n viewerName,\n viewerEmail,\n addActionLabel,\n emptyState,\n onActionChange,\n translator,\n labelPrefix = 'customers.people.detail.notes',\n inlineLabelPrefix = 'customers.people.detail.inline',\n onLoadingChange,\n dealOptions,\n entityOptions,\n dataAdapter,\n dataContext,\n renderIcon,\n renderColor,\n iconSuggestions,\n readMarkdownPreference,\n writeMarkdownPreference,\n disableMarkdown,\n}: NotesSectionProps<C>) {\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const t = React.useMemo<Translator>(() => translator ?? ((key, fallback) => fallback ?? key), [translator])\n const label = React.useCallback(\n (suffix: string, fallback?: string, params?: Record<string, string | number>) =>\n t(`${labelPrefix}.${suffix}`, fallback, params),\n [labelPrefix, t],\n )\n const inlineLabel = React.useCallback(\n (suffix: string, fallback?: string, params?: Record<string, string | number>) =>\n t(`${inlineLabelPrefix}.${suffix}`, fallback, params),\n [inlineLabelPrefix, t],\n )\n const [markdownPlugins, setMarkdownPlugins] = React.useState<PluggableList>([])\n React.useEffect(() => {\n if (isTestEnv) return\n let mounted = true\n void loadMarkdownPlugins().then((plugins) => {\n if (!mounted) return\n setMarkdownPlugins(plugins)\n })\n return () => {\n mounted = false\n }\n }, [])\n\n const normalizedDealOptions = React.useMemo(() => {\n if (!Array.isArray(dealOptions)) return []\n const seen = new Set<string>()\n return dealOptions\n .map((option) => {\n if (!option || typeof option !== 'object') return null\n const id = typeof option.id === 'string' ? option.id.trim() : ''\n if (!id || seen.has(id)) return null\n const label =\n typeof option.label === 'string' && option.label.trim().length\n ? option.label.trim()\n : id\n seen.add(id)\n return { id, label }\n })\n .filter((option): option is { id: string; label: string } => !!option)\n }, [dealOptions])\n\n const dealLabelMap = React.useMemo(() => {\n const map = new Map<string, string>()\n normalizedDealOptions.forEach((option) => {\n map.set(option.id, option.label)\n })\n return map\n }, [normalizedDealOptions])\n\n const normalizedEntityOptions = React.useMemo(() => {\n if (!Array.isArray(entityOptions)) return []\n const seen = new Set<string>()\n return entityOptions\n .map((option) => {\n if (!option || typeof option !== 'object') return null\n const id = typeof option.id === 'string' ? option.id.trim() : ''\n if (!id || seen.has(id)) return null\n const label =\n typeof option.label === 'string' && option.label.trim().length\n ? option.label.trim()\n : id\n seen.add(id)\n return { id, label }\n })\n .filter((option): option is { id: string; label: string } => !!option)\n }, [entityOptions])\n\n const [selectedDealId, setSelectedDealId] = React.useState<string>(() => {\n const initial = typeof dealId === 'string' ? dealId.trim() : ''\n return initial\n })\n React.useEffect(() => {\n const initial = typeof dealId === 'string' ? dealId.trim() : ''\n if (initial !== selectedDealId) {\n setSelectedDealId(initial)\n }\n }, [dealId, selectedDealId])\n\n const [selectedEntityId, setSelectedEntityId] = React.useState<string>(() => {\n if (normalizedEntityOptions.length) return normalizedEntityOptions[0].id\n return typeof entityId === 'string' ? entityId : ''\n })\n React.useEffect(() => {\n if (normalizedEntityOptions.length) {\n if (!normalizedEntityOptions.some((option) => option.id === selectedEntityId)) {\n setSelectedEntityId(normalizedEntityOptions[0].id)\n }\n } else {\n const initial = typeof entityId === 'string' ? entityId : ''\n if (initial !== selectedEntityId) {\n setSelectedEntityId(initial)\n }\n }\n }, [entityId, normalizedEntityOptions, selectedEntityId])\n\n const resolvedEntityId = React.useMemo(() => {\n if (normalizedEntityOptions.length) return selectedEntityId\n return typeof entityId === 'string' ? entityId : ''\n }, [entityId, normalizedEntityOptions, selectedEntityId])\n\n const resolvedDealId = React.useMemo(() => {\n const trimmed = typeof selectedDealId === 'string' ? selectedDealId.trim() : ''\n return trimmed\n }, [selectedDealId])\n\n const hasEntity = resolvedEntityId.length > 0\n\n const [notes, setNotes] = React.useState<CommentSummary[]>([])\n const [isLoading, setIsLoading] = React.useState<boolean>(() => Boolean(entityId || dealId))\n const [isSubmitting, setIsSubmitting] = React.useState(false)\n const [loadError, setLoadError] = React.useState<string | null>(null)\n const pendingCounterRef = React.useRef(0)\n\n const pushLoading = React.useCallback(() => {\n pendingCounterRef.current += 1\n if (pendingCounterRef.current === 1) {\n onLoadingChange?.(true)\n }\n }, [onLoadingChange])\n\n const popLoading = React.useCallback(() => {\n pendingCounterRef.current = Math.max(0, pendingCounterRef.current - 1)\n if (pendingCounterRef.current === 0) {\n onLoadingChange?.(false)\n }\n }, [onLoadingChange])\n\n const [composerOpen, setComposerOpen] = React.useState(false)\n const [draftBody, setDraftBody] = React.useState('')\n const [draftIcon, setDraftIcon] = React.useState<string | null>(null)\n const [draftColor, setDraftColor] = React.useState<string | null>(null)\n const [isMarkdownEnabled, setIsMarkdownEnabled] = React.useState(false)\n const textareaRef = React.useRef<HTMLTextAreaElement | null>(null)\n const formRef = React.useRef<HTMLFormElement | null>(null)\n const focusComposer = React.useCallback(() => {\n if (!hasEntity) return\n setComposerOpen(true)\n window.requestAnimationFrame(() => {\n if (isMarkdownEnabled) {\n const markdownTextarea = formRef.current?.querySelector('textarea')\n if (markdownTextarea instanceof HTMLTextAreaElement) {\n markdownTextarea.focus()\n markdownTextarea.scrollIntoView({ behavior: 'smooth', block: 'center' })\n return\n }\n }\n const element = textareaRef.current\n if (!element) return\n element.focus()\n element.scrollIntoView({ behavior: 'smooth', block: 'center' })\n })\n }, [formRef, hasEntity, isMarkdownEnabled])\n const [appearanceDialogState, setAppearanceDialogState] = React.useState<\n | { mode: 'create'; icon: string | null; color: string | null }\n | { mode: 'edit'; noteId: string; icon: string | null; color: string | null }\n | null\n >(null)\n const [appearanceDialogSaving, setAppearanceDialogSaving] = React.useState(false)\n const [appearanceDialogError, setAppearanceDialogError] = React.useState<string | null>(null)\n const [contentEditor, setContentEditor] = React.useState<{ id: string; value: string }>({ id: '', value: '' })\n const [contentSavingId, setContentSavingId] = React.useState<string | null>(null)\n const [contentError, setContentError] = React.useState<string | null>(null)\n const contentTextareaRef = React.useRef<HTMLTextAreaElement | null>(null)\n const [visibleCount, setVisibleCount] = React.useState(0)\n const [deletingNoteId, setDeletingNoteId] = React.useState<string | null>(null)\n\n React.useEffect(() => {\n const queryEntityId = typeof entityId === 'string' ? entityId : ''\n const queryDealId = typeof dealId === 'string' ? dealId : ''\n if (!queryEntityId && !queryDealId) {\n setNotes([])\n setLoadError(null)\n setIsLoading(false)\n return\n }\n let cancelled = false\n setIsLoading(true)\n setLoadError(null)\n pushLoading()\n async function loadNotes() {\n try {\n const mapped = await dataAdapter.list({\n entityId: queryEntityId || null,\n dealId: queryDealId || null,\n context: dataContext,\n })\n if (cancelled) return\n setNotes(mapped)\n } catch (err) {\n if (cancelled) return\n const message =\n err instanceof Error ? err.message : label('loadError', 'Failed to load notes.')\n setNotes([])\n setLoadError(message)\n flash(message, 'error')\n } finally {\n if (!cancelled) setIsLoading(false)\n popLoading()\n }\n }\n loadNotes().catch(() => {})\n return () => {\n cancelled = true\n }\n }, [dataAdapter, dataContext, dealId, entityId, popLoading, pushLoading, t])\n\n const youLabel = label('you', 'You')\n const viewerLabel = React.useMemo(() => viewerName ?? viewerEmail ?? null, [viewerEmail, viewerName])\n\n const handleMarkdownToggle = React.useCallback(() => {\n setIsMarkdownEnabled((prev) => {\n const next = !prev\n if (writeMarkdownPreference) {\n writeMarkdownPreference(next)\n }\n return next\n })\n }, [writeMarkdownPreference])\n\n React.useEffect(() => {\n if (!onActionChange) return\n if (!notes.length) {\n onActionChange(null)\n return\n }\n onActionChange({\n label: addActionLabel,\n onClick: focusComposer,\n disabled: isSubmitting || isLoading || !hasEntity,\n icon: <Plus className=\"mr-2 h-4 w-4\" />,\n })\n return () => onActionChange(null)\n }, [onActionChange, addActionLabel, focusComposer, hasEntity, isLoading, isSubmitting, notes.length])\n\n const adjustTextareaSize = React.useCallback((element: HTMLTextAreaElement | null) => {\n if (!element) return\n element.style.height = 'auto'\n element.style.height = `${element.scrollHeight}px`\n }, [])\n\n React.useEffect(() => {\n adjustTextareaSize(textareaRef.current)\n }, [adjustTextareaSize, draftBody, isMarkdownEnabled, composerOpen])\n\n React.useEffect(() => {\n const preference = readMarkdownPreference ? readMarkdownPreference() : null\n if (preference !== null) {\n setIsMarkdownEnabled(preference)\n }\n }, [readMarkdownPreference])\n\n React.useEffect(() => {\n if (!notes.length) {\n setVisibleCount(0)\n return\n }\n const baseline = Math.min(5, notes.length)\n setVisibleCount((prev) => {\n if (prev >= notes.length) return prev\n return Math.min(Math.max(prev, baseline), notes.length)\n })\n }, [notes.length])\n\n React.useEffect(() => {\n if (hasEntity) return\n setComposerOpen(false)\n setDraftBody('')\n setDraftIcon(null)\n setDraftColor(null)\n }, [hasEntity])\n\n const visibleNotes = React.useMemo(() => notes.slice(0, visibleCount), [notes, visibleCount])\n const hasVisibleNotes = React.useMemo(() => visibleCount > 0, [visibleCount])\n\n const loadMoreLabel = label('loadMore')\n\n const handleCreateNote = React.useCallback(\n async (input: { body: string; appearanceIcon: string | null; appearanceColor: string | null }) => {\n if (!hasEntity || !resolvedEntityId) {\n flash(label('entityMissing', 'Unable to determine current person.'), 'error')\n return false\n }\n const body = input.body.trim()\n if (!body) {\n focusComposer()\n return false\n }\n const icon = input.appearanceIcon && input.appearanceIcon.trim().length ? input.appearanceIcon.trim() : null\n const color = sanitizeHexColor(input.appearanceColor)\n const targetDealId = resolvedDealId.length ? resolvedDealId : null\n const dealLabel = targetDealId ? dealLabelMap.get(targetDealId) ?? null : null\n setIsSubmitting(true)\n pushLoading()\n try {\n const responseBody =\n (await dataAdapter.create({\n entityId: resolvedEntityId,\n body,\n appearanceIcon: icon,\n appearanceColor: color,\n dealId: targetDealId,\n context: dataContext,\n })) ?? {}\n setNotes((prev) => {\n const viewerId = viewerUserId ?? null\n const resolvedAuthorId =\n typeof responseBody?.authorUserId === 'string' ? responseBody.authorUserId : viewerId ?? null\n const resolvedAuthorName = (() => {\n if (resolvedAuthorId && viewerId && resolvedAuthorId === viewerId) {\n return youLabel\n }\n return typeof responseBody?.authorName === 'string' ? responseBody.authorName : viewerLabel\n })()\n const resolvedAuthorEmail = (() => {\n if (resolvedAuthorId && viewerId && resolvedAuthorId === viewerId) {\n return viewerEmail ?? null\n }\n return typeof responseBody?.authorEmail === 'string' ? responseBody.authorEmail : null\n })()\n const newNote: CommentSummary = {\n id: typeof responseBody?.id === 'string' ? responseBody.id : generateTempId(),\n body,\n createdAt: new Date().toISOString(),\n authorUserId: resolvedAuthorId,\n authorName: resolvedAuthorName,\n authorEmail: resolvedAuthorEmail,\n dealId: targetDealId,\n dealTitle: dealLabel,\n appearanceIcon: icon,\n appearanceColor: color,\n }\n return [newNote, ...prev]\n })\n flash(label('success'), 'success')\n return true\n } catch (err) {\n const message = err instanceof Error ? err.message : label('error')\n flash(message, 'error')\n return false\n } finally {\n setIsSubmitting(false)\n popLoading()\n }\n },\n [dataAdapter, dataContext, dealLabelMap, focusComposer, hasEntity, popLoading, pushLoading, resolvedDealId, resolvedEntityId, t, viewerEmail, viewerLabel, viewerUserId, youLabel],\n )\n\n const handleUpdateNote = React.useCallback(\n async (noteId: string, patch: { body?: string; appearanceIcon?: string | null; appearanceColor?: string | null }) => {\n const sanitizedBody = patch.body\n const sanitizedIcon =\n patch.appearanceIcon !== undefined && patch.appearanceIcon !== null && patch.appearanceIcon.trim().length\n ? patch.appearanceIcon.trim()\n : patch.appearanceIcon === null\n ? null\n : undefined\n const sanitizedColor =\n patch.appearanceColor !== undefined ? sanitizeHexColor(patch.appearanceColor ?? null) : undefined\n try {\n await dataAdapter.update({\n id: noteId,\n patch: {\n body: sanitizedBody,\n appearanceIcon: sanitizedIcon,\n appearanceColor: sanitizedColor,\n },\n context: dataContext,\n })\n setNotes((prev) => {\n const nextComments = prev.map((comment) => {\n if (comment.id !== noteId) return comment\n const next = { ...comment }\n if (sanitizedBody !== undefined) next.body = sanitizedBody\n if (sanitizedIcon !== undefined) next.appearanceIcon = sanitizedIcon ?? null\n if (sanitizedColor !== undefined) next.appearanceColor = sanitizedColor ?? null\n return next\n })\n return nextComments\n })\n flash(label('updateSuccess'), 'success')\n } catch (error) {\n const message = error instanceof Error ? error.message : label('updateError')\n flash(message, 'error')\n throw error instanceof Error ? error : new Error(message)\n }\n },\n [dataAdapter, dataContext, t],\n )\n\n const handleDeleteNote = React.useCallback(\n async (note: CommentSummary) => {\n const confirmed = await confirm({\n title: label('deleteConfirm', 'Delete this note?'),\n text: 'This action cannot be undone.',\n variant: 'destructive',\n })\n if (!confirmed) return\n setDeletingNoteId(note.id)\n pushLoading()\n try {\n await dataAdapter.delete({ id: note.id, context: dataContext })\n setNotes((prev) => prev.filter((existing) => existing.id !== note.id))\n flash(label('deleteSuccess', 'Note deleted'), 'success')\n } catch (err) {\n const message = err instanceof Error ? err.message : label('deleteError', 'Failed to delete note')\n flash(message, 'error')\n } finally {\n setDeletingNoteId(null)\n popLoading()\n }\n },\n [confirm, dataAdapter, dataContext, label, popLoading, pushLoading],\n )\n\n const handleSubmit = React.useCallback(\n async (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault()\n const created = await handleCreateNote({\n body: draftBody,\n appearanceIcon: draftIcon,\n appearanceColor: draftColor,\n })\n if (created) {\n setDraftBody('')\n setDraftIcon(null)\n setDraftColor(null)\n }\n },\n [draftBody, draftColor, draftIcon, handleCreateNote],\n )\n\n const handleLoadMore = React.useCallback(() => {\n setVisibleCount((prev) => {\n if (prev >= notes.length) return prev\n return Math.min(prev + 5, notes.length)\n })\n }, [notes.length])\n\n const handleAppearanceDialogSubmit = React.useCallback(async () => {\n if (!appearanceDialogState) return\n setAppearanceDialogError(null)\n const sanitizedIcon =\n appearanceDialogState.icon && appearanceDialogState.icon.trim().length\n ? appearanceDialogState.icon.trim()\n : null\n const sanitizedColor = sanitizeHexColor(appearanceDialogState.color ?? null)\n if (appearanceDialogState.mode === 'create') {\n setDraftIcon(sanitizedIcon)\n setDraftColor(sanitizedColor)\n setAppearanceDialogState(null)\n return\n }\n setAppearanceDialogSaving(true)\n try {\n await handleUpdateNote(appearanceDialogState.noteId, {\n appearanceIcon: sanitizedIcon,\n appearanceColor: sanitizedColor,\n })\n setAppearanceDialogState(null)\n } catch (err) {\n const message =\n err instanceof Error\n ? err.message\n : label('appearance.error', 'Failed to update appearance.')\n setAppearanceDialogError(message)\n } finally {\n setAppearanceDialogSaving(false)\n }\n }, [appearanceDialogState, handleUpdateNote, t])\n\n const handleAppearanceDialogClose = React.useCallback(() => {\n if (appearanceDialogSaving) return\n setAppearanceDialogState(null)\n setAppearanceDialogError(null)\n }, [appearanceDialogSaving])\n\n const handleContentSave = React.useCallback(async () => {\n if (!contentEditor.id) return\n const trimmed = contentEditor.value.trim()\n if (!trimmed) {\n setContentError(label('updateError', 'Failed to update note'))\n return\n }\n setContentSavingId(contentEditor.id)\n setContentError(null)\n try {\n await handleUpdateNote(contentEditor.id, { body: trimmed })\n setContentEditor({ id: '', value: '' })\n } catch (err) {\n const message =\n err instanceof Error ? err.message : label('updateError', 'Failed to update note')\n setContentError(message)\n } finally {\n setContentSavingId(null)\n }\n }, [contentEditor, handleUpdateNote, t])\n\n const handleContentEditorKeyDown = React.useCallback(\n (event: React.KeyboardEvent) => {\n if (!contentEditor.id) return\n if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') {\n event.preventDefault()\n if (!contentSavingId) void handleContentSave()\n return\n }\n if (event.key === 'Escape') {\n event.preventDefault()\n setContentEditor({ id: '', value: '' })\n setContentError(null)\n }\n },\n [contentEditor.id, contentSavingId, handleContentSave],\n )\n\n const handleComposerKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLFormElement>) => {\n if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') {\n event.preventDefault()\n formRef.current?.requestSubmit()\n }\n },\n [],\n )\n\n const handleContentKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>, note: CommentSummary) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n setContentEditor({ id: note.id, value: note.body })\n }\n },\n [],\n )\n\n const noteAuthorLabel = React.useCallback(\n (note: CommentSummary) => {\n if (note.authorUserId && viewerUserId && note.authorUserId === viewerUserId) {\n return youLabel\n }\n return note.authorName ?? note.authorEmail ?? youLabel\n },\n [viewerUserId, youLabel],\n )\n\n const noteAppearanceLabels = React.useMemo<AppearanceSelectorLabels>(\n () => ({\n colorLabel: label('appearance.colorLabel'),\n colorHelp: label('appearance.colorHelp'),\n colorClearLabel: label('appearance.clearColor'),\n iconLabel: label('appearance.iconLabel'),\n iconPlaceholder: label('appearance.iconPlaceholder'),\n iconPickerTriggerLabel: label('appearance.iconPicker'),\n iconSearchPlaceholder: label('appearance.iconSearchPlaceholder'),\n iconSearchEmptyLabel: label('appearance.iconSearchEmpty'),\n iconSuggestionsLabel: label('appearance.iconSuggestions'),\n iconClearLabel: label('appearance.iconClear'),\n previewEmptyLabel: label('appearance.previewEmpty'),\n }),\n [label],\n )\n\n const composerAuthor = React.useMemo(\n () => youLabel,\n [youLabel],\n )\n const composerHasAppearance = Boolean(draftIcon) || Boolean(draftColor)\n const appearanceDialogOpen = appearanceDialogState !== null\n const editingAppearanceNoteId =\n appearanceDialogState?.mode === 'edit' ? appearanceDialogState.noteId : null\n const addNoteShortcutLabel = label('addShortcut', 'Add note \u2318\u23CE / Ctrl+Enter')\n const saveAppearanceShortcutLabel = label('appearance.saveShortcut', 'Save appearance \u2318\u23CE / Ctrl+Enter')\n const composerSubmitLabel = addNoteShortcutLabel\n const appearanceDialogPrimaryLabel = saveAppearanceShortcutLabel\n const appearanceDialogSavingLabel =\n appearanceDialogState?.mode === 'edit'\n ? label('appearance.saving')\n : label('saving', 'Saving note\u2026')\n\n return (\n <div className=\"mt-0 space-y-2\">\n <div\n className={[\n 'overflow-hidden rounded-xl transition-all duration-300 ease-out',\n composerOpen ? 'max-h-[1200px] bg-muted/10 p-4 opacity-100' : 'pointer-events-none max-h-0 p-0 opacity-0',\n ].join(' ')}\n aria-hidden={!composerOpen}\n >\n {composerOpen ? (\n <form\n ref={formRef}\n onSubmit={handleSubmit}\n onKeyDown={handleComposerKeyDown}\n className=\"space-y-3\"\n >\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <h3 className=\"text-sm font-medium\">{label('addLabel')}</h3>\n <div className=\"flex flex-wrap items-center gap-1\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => {\n setAppearanceDialogError(null)\n setAppearanceDialogState({ mode: 'create', icon: draftIcon, color: draftColor })\n }}\n disabled={isSubmitting || isLoading || !hasEntity}\n >\n <span className=\"sr-only\">{label('appearance.toggleOpen', 'Customize appearance')}</span>\n <Palette className=\"h-4 w-4\" />\n </Button>\n {disableMarkdown ? null : (\n <Button\n type=\"button\"\n variant={isMarkdownEnabled ? 'secondary' : 'ghost'}\n size=\"icon\"\n onClick={handleMarkdownToggle}\n aria-pressed={isMarkdownEnabled}\n disabled={isSubmitting || isLoading}\n >\n <FileCode className=\"h-4 w-4\" />\n </Button>\n )}\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"ghost\"\n onClick={() => {\n setComposerOpen(false)\n setDraftBody('')\n setDraftIcon(null)\n setDraftColor(null)\n }}\n disabled={isSubmitting || isLoading}\n >\n {inlineLabel('cancel')}\n </Button>\n </div>\n </div>\n {(normalizedEntityOptions.length || normalizedDealOptions.length) ? (\n <div className=\"grid gap-3 sm:grid-cols-2\">\n {normalizedEntityOptions.length ? (\n <div className=\"flex flex-col gap-1\">\n <label\n htmlFor=\"note-entity-select\"\n className=\"text-xs font-medium text-muted-foreground\"\n >\n {label('fields.entity', 'Assign to customer')}\n </label>\n <select\n id=\"note-entity-select\"\n className=\"h-9 rounded border border-muted-foreground/40 bg-background px-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary\"\n value={selectedEntityId}\n onChange={(event) => setSelectedEntityId(event.target.value)}\n disabled={isSubmitting || isLoading || !normalizedEntityOptions.length}\n >\n {normalizedEntityOptions.map((option) => (\n <option key={option.id} value={option.id}>\n {option.label}\n </option>\n ))}\n </select>\n </div>\n ) : null}\n {normalizedDealOptions.length ? (\n <div className=\"flex flex-col gap-1\">\n <label\n htmlFor=\"note-deal-select\"\n className=\"text-xs font-medium text-muted-foreground\"\n >\n {label('fields.deal', 'Link to deal (optional)')}\n </label>\n <select\n id=\"note-deal-select\"\n className=\"h-9 rounded border border-muted-foreground/40 bg-background px-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary\"\n value={selectedDealId}\n onChange={(event) => setSelectedDealId(event.target.value)}\n disabled={isSubmitting || isLoading}\n >\n <option value=\"\">\n {label('fields.dealPlaceholder', 'No linked deal')}\n </option>\n {normalizedDealOptions.map((option) => (\n <option key={option.id} value={option.id}>\n {option.label}\n </option>\n ))}\n </select>\n </div>\n ) : null}\n </div>\n ) : null}\n <SwitchableMarkdownInput\n value={draftBody}\n onChange={setDraftBody}\n isMarkdownEnabled={isMarkdownEnabled}\n disableMarkdown={disableMarkdown}\n rows={1}\n placeholder={label('placeholder')}\n textareaRef={textareaRef}\n onTextareaInput={(event) => adjustTextareaSize(event.currentTarget)}\n disabled={isSubmitting || isLoading || !hasEntity}\n remarkPlugins={markdownPlugins}\n />\n {composerHasAppearance ? (\n <div className=\"flex flex-wrap items-center justify-between gap-3 rounded-lg border border-dashed border-muted-foreground/40 px-3 py-2\">\n <div className=\"flex flex-wrap items-center gap-3 text-sm\">\n {draftIcon && renderIcon ? (\n <span className=\"inline-flex h-7 w-7 items-center justify-center rounded border border-border bg-muted/40\">\n {renderIcon(draftIcon, 'h-4 w-4')}\n </span>\n ) : null}\n <span className=\"font-semibold text-foreground\">{composerAuthor}</span>\n {draftColor && renderColor ? (\n <span className=\"flex items-center gap-2\">\n {renderColor(draftColor, 'h-3.5 w-3.5 rounded-full border border-border')}\n <span className=\"text-xs font-medium uppercase text-muted-foreground\">{draftColor}</span>\n </span>\n ) : null}\n </div>\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"ghost\"\n onClick={() => {\n setDraftIcon(null)\n setDraftColor(null)\n }}\n disabled={isSubmitting}\n >\n {label('appearance.clearAll', 'Clear')}\n </Button>\n </div>\n ) : null}\n <div className=\"flex justify-end\">\n <Button\n type=\"submit\"\n size=\"sm\"\n disabled={isSubmitting || isLoading || !hasEntity}\n >\n {isSubmitting ? <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" /> : null}\n {composerSubmitLabel}\n </Button>\n </div>\n </form>\n ) : null}\n </div>\n\n {loadError ? <ErrorMessage label={loadError} className=\"mt-3\" /> : null}\n\n <div className=\"space-y-3\">\n {isLoading ? (\n <LoadingMessage\n label={label('loading', 'Loading notes\u2026')}\n className=\"border-0 bg-transparent p-0 py-8 justify-center\"\n />\n ) : hasVisibleNotes ? (\n visibleNotes.map((note) => {\n const author = noteAuthorLabel(note)\n const isAppearanceSaving = appearanceDialogSaving && editingAppearanceNoteId === note.id\n const isEditingContent = contentEditor.id === note.id\n const displayIcon = note.appearanceIcon ?? null\n const displayColor = note.appearanceColor ?? null\n const timestampValue = note.createdAt\n const fallbackTimestampLabel = formatDateTime(note.createdAt) ?? emptyLabel\n return (\n <div key={note.id} className=\"group space-y-2 rounded-lg border bg-card p-4\">\n <div className=\"flex flex-wrap items-start justify-between gap-3\">\n <div className=\"space-y-1\">\n <TimelineItemHeader\n title={author}\n timestamp={timestampValue}\n fallbackTimestampLabel={fallbackTimestampLabel}\n icon={displayIcon}\n color={displayColor}\n renderIcon={renderIcon}\n renderColor={renderColor}\n />\n {note.dealId ? (\n <div className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <ArrowUpRightSquare className=\"h-3.5 w-3.5\" />\n <a\n href={`/backend/customers/deals/${encodeURIComponent(note.dealId)}`}\n className=\"font-medium text-foreground hover:underline\"\n >\n {note.dealTitle && note.dealTitle.length\n ? note.dealTitle\n : label('linkedDeal', 'Linked deal')}\n </a>\n </div>\n ) : null}\n </div>\n <div\n className={`flex items-center gap-2 transition-opacity ${\n isEditingContent ? 'opacity-100' : 'opacity-100 md:opacity-0 md:group-hover:opacity-100 focus-within:opacity-100'\n }`}\n >\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => setContentEditor({ id: note.id, value: note.body })}\n >\n <Pencil className=\"h-4 w-4\" />\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={(event) => {\n event.stopPropagation()\n setAppearanceDialogError(null)\n setAppearanceDialogState({\n mode: 'edit',\n noteId: note.id,\n icon: note.appearanceIcon ?? null,\n color: note.appearanceColor ?? null,\n })\n }}\n disabled={appearanceDialogSaving && editingAppearanceNoteId === note.id}\n >\n {isAppearanceSaving ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <Palette className=\"h-4 w-4\" />}\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={(event) => {\n event.stopPropagation()\n void handleDeleteNote(note)\n }}\n disabled={deletingNoteId === note.id}\n >\n {deletingNoteId === note.id ? (\n <span className=\"relative flex h-4 w-4 items-center justify-center text-destructive\">\n <span className=\"absolute h-4 w-4 animate-spin rounded-full border border-destructive border-t-transparent\" />\n </span>\n ) : (\n <Trash2 className=\"h-4 w-4\" />\n )}\n </Button>\n </div>\n </div>\n {isEditingContent ? (\n <div className=\"space-y-2\" onKeyDown={handleContentEditorKeyDown}>\n <SwitchableMarkdownInput\n value={contentEditor.value}\n onChange={(nextValue) => setContentEditor((prev) => ({ ...prev, value: nextValue }))}\n isMarkdownEnabled={isMarkdownEnabled}\n disableMarkdown={disableMarkdown}\n rows={3}\n textareaRef={contentTextareaRef}\n onTextareaInput={(event) => adjustTextareaSize(event.currentTarget)}\n textareaClassName=\"w-full resize-none overflow-hidden rounded-md border border-border px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary\"\n editorWrapperClassName=\"w-full rounded-md border border-muted-foreground/20 bg-background p-2\"\n remarkPlugins={markdownPlugins}\n />\n {contentError ? <p className=\"text-xs text-red-600\">{contentError}</p> : null}\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button type=\"button\" size=\"sm\" onClick={handleContentSave} disabled={contentSavingId === note.id}>\n {contentSavingId === note.id ? (\n <>\n <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" />\n {label('saving')}\n </>\n ) : (\n inlineLabel('saveShortcut')\n )}\n </Button>\n {disableMarkdown ? null : (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={handleMarkdownToggle}\n aria-pressed={isMarkdownEnabled}\n className={isMarkdownEnabled ? 'text-primary' : undefined}\n disabled={contentSavingId === note.id}\n >\n <FileCode className=\"h-4 w-4\" />\n </Button>\n )}\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"ghost\"\n onClick={() => setContentEditor({ id: '', value: '' })}\n disabled={contentSavingId === note.id}\n >\n {inlineLabel('cancel')}\n </Button>\n </div>\n </div>\n ) : (\n <div\n role=\"button\"\n tabIndex={0}\n className=\"cursor-pointer text-sm\"\n onClick={() => setContentEditor({ id: note.id, value: note.body })}\n onKeyDown={(event) => handleContentKeyDown(event, note)}\n >\n <MarkdownPreviewComponent\n remarkPlugins={markdownPlugins}\n className=\"break-words text-foreground [&>*]:mb-2 [&>*:last-child]:mb-0 [&_ul]:ml-4 [&_ul]:list-disc [&_ol]:ml-4 [&_ol]:list-decimal [&_code]:rounded [&_code]:bg-muted [&_code]:px-1 [&_code]:py-0.5 [&_pre]:rounded-md [&_pre]:bg-muted [&_pre]:p-3 [&_pre]:text-xs\"\n >\n {note.body}\n </MarkdownPreviewComponent>\n </div>\n )}\n </div>\n )\n })\n ) : composerOpen ? null : (\n <TabEmptyState\n title={emptyState.title}\n description={emptyState.description}\n action={{\n label: emptyState.actionLabel,\n onClick: focusComposer,\n disabled: isSubmitting || !hasEntity,\n }}\n />\n )}\n {isLoading || visibleCount >= notes.length ? null : (\n <div className=\"flex justify-center\">\n <Button variant=\"outline\" size=\"sm\" onClick={handleLoadMore}>\n {loadMoreLabel}\n </Button>\n </div>\n )}\n </div>\n <AppearanceDialog\n open={appearanceDialogOpen}\n title={\n appearanceDialogState?.mode === 'edit'\n ? label('appearance.edit')\n : label('appearance.toggleOpen', 'Customize appearance')\n }\n icon={appearanceDialogState?.icon ?? null}\n color={appearanceDialogState?.color ?? null}\n labels={noteAppearanceLabels}\n iconSuggestions={iconSuggestions}\n onIconChange={(value) => setAppearanceDialogState((prev) => (prev ? { ...prev, icon: value ?? null } : prev))}\n onColorChange={(value) => setAppearanceDialogState((prev) => (prev ? { ...prev, color: value ?? null } : prev))}\n onSubmit={() => {\n void handleAppearanceDialogSubmit()\n }}\n onClose={handleAppearanceDialogClose}\n isSaving={appearanceDialogSaving}\n errorMessage={appearanceDialogError}\n primaryLabel={appearanceDialogPrimaryLabel}\n savingLabel={appearanceDialogSavingLabel}\n cancelLabel={label('appearance.cancel')}\n />\n {ConfirmDialogElement}\n </div>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport dynamic from 'next/dynamic'\nimport type { PluggableList } from 'unified'\nimport type { AppearanceSelectorLabels } from '@open-mercato/core/modules/dictionaries/components/AppearanceSelector'\nimport { AppearanceDialog } from '@open-mercato/core/modules/customers/components/detail/AppearanceDialog'\nimport type { IconOption } from '@open-mercato/core/modules/dictionaries/components/dictionaryAppearance'\nimport { ArrowUpRightSquare, FileCode, Loader2, Palette, Pencil, Plus, Trash2 } from 'lucide-react'\nimport { formatRelativeTime } from '@open-mercato/shared/lib/time'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { flash } from '../FlashMessages'\nimport { SwitchableMarkdownInput } from '../inputs/SwitchableMarkdownInput'\nimport { ErrorMessage } from './ErrorMessage'\nimport { LoadingMessage } from './LoadingMessage'\nimport { TabEmptyState } from './TabEmptyState'\nimport { useConfirmDialog } from '../confirm-dialog'\nimport { formatDateTime } from '@open-mercato/shared/lib/time'\nimport { ComponentReplacementHandles } from '@open-mercato/shared/modules/widgets/component-registry'\nimport { useRegisteredComponent } from '../injection/useRegisteredComponent'\ntype Translator = (key: string, fallback?: string, params?: Record<string, string | number>) => string\n\nexport type SectionAction = {\n label: React.ReactNode\n onClick: () => void\n disabled?: boolean\n icon?: React.ReactNode\n}\n\nexport type TabEmptyStateConfig = {\n title: string\n actionLabel: string\n description?: string\n}\n\nexport type CommentSummary = {\n id: string\n body: string\n createdAt: string\n authorUserId?: string | null\n authorName?: string | null\n authorEmail?: string | null\n dealId?: string | null\n dealTitle?: string | null\n appearanceIcon?: string | null\n appearanceColor?: string | null\n}\n\nexport type NotesCreatePayload = {\n entityId: string\n body: string\n appearanceIcon: string | null\n appearanceColor: string | null\n dealId?: string | null\n}\n\nexport type NotesUpdatePayload = {\n body?: string\n appearanceIcon?: string | null\n appearanceColor?: string | null\n}\n\nexport type NotesDataAdapter<C = unknown> = {\n list: (params: { entityId: string | null; dealId: string | null; context?: C }) => Promise<CommentSummary[]>\n create: (params: NotesCreatePayload & { context?: C }) => Promise<Partial<CommentSummary> | void>\n update: (params: { id: string; patch: NotesUpdatePayload; context?: C }) => Promise<void>\n delete: (params: { id: string; context?: C }) => Promise<void>\n}\n\ntype RenderIconFn = (icon: string, className?: string) => React.ReactNode\ntype RenderColorFn = (color: string, className?: string) => React.ReactNode\n\ntype MarkdownPreviewProps = { children: string; className?: string; remarkPlugins?: PluggableList }\n\nconst isTestEnv = typeof process !== 'undefined' && process.env.NODE_ENV === 'test'\n\nconst MarkdownPreviewComponent: React.ComponentType<MarkdownPreviewProps> = isTestEnv\n ? ({ children, className }) => <div className={className}>{children}</div>\n : (dynamic(() => import('react-markdown').then((mod) => mod.default as React.ComponentType<MarkdownPreviewProps>), {\n ssr: false,\n loading: () => null,\n }) as unknown as React.ComponentType<MarkdownPreviewProps>)\n\nlet markdownPluginsPromise: Promise<PluggableList> | null = null\n\nasync function loadMarkdownPlugins(): Promise<PluggableList> {\n if (isTestEnv) return []\n if (!markdownPluginsPromise) {\n markdownPluginsPromise = import('remark-gfm')\n .then((mod) => [mod.default ?? mod] as PluggableList)\n .catch(() => [])\n }\n return markdownPluginsPromise\n}\n\nfunction generateTempId() {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') return crypto.randomUUID()\n return `tmp_${Math.random().toString(36).slice(2)}`\n}\n\n\n\ntype TimelineItemHeaderProps = {\n title: React.ReactNode\n subtitle?: React.ReactNode\n timestamp?: string | Date | null\n fallbackTimestampLabel?: React.ReactNode\n icon?: string | null\n color?: string | null\n iconSize?: 'sm' | 'md'\n className?: string\n renderIcon?: RenderIconFn\n renderColor?: RenderColorFn\n}\n\nfunction TimelineItemHeader({\n title,\n subtitle,\n timestamp,\n fallbackTimestampLabel,\n icon,\n color,\n iconSize = 'md',\n className,\n renderIcon,\n renderColor,\n}: TimelineItemHeaderProps) {\n const wrapperSize = iconSize === 'sm' ? 'h-6 w-6' : 'h-8 w-8'\n const iconSizeClass = iconSize === 'sm' ? 'h-3.5 w-3.5' : 'h-4 w-4'\n const resolvedTimestamp = React.useMemo(() => {\n if (subtitle) return subtitle\n if (!timestamp) return fallbackTimestampLabel ?? null\n const value = typeof timestamp === 'string' ? timestamp : timestamp.toISOString()\n const date = new Date(value)\n if (Number.isNaN(date.getTime())) return fallbackTimestampLabel ?? null\n const now = Date.now()\n const diff = Math.abs(now - date.getTime())\n const THIRTY_DAYS_MS = 30 * 24 * 60 * 60 * 1000\n const relativeLabel = diff <= THIRTY_DAYS_MS ? formatRelativeTime(value) : null\n const absoluteLabel = formatDateTime(value)\n if (relativeLabel) {\n return (\n <span title={absoluteLabel ?? undefined}>\n {relativeLabel}\n </span>\n )\n }\n return absoluteLabel ?? fallbackTimestampLabel ?? null\n }, [fallbackTimestampLabel, subtitle, timestamp])\n\n return (\n <div className={['flex items-start gap-3', className].filter(Boolean).join(' ')}>\n {icon && renderIcon ? (\n <span className={['inline-flex items-center justify-center rounded border border-border bg-muted/40', wrapperSize].join(' ')}>\n {renderIcon(icon, iconSizeClass)}\n </span>\n ) : null}\n <div className=\"space-y-1\">\n <div className=\"flex flex-wrap items-center gap-2\">\n <span className=\"text-sm font-semibold text-foreground\">{title}</span>\n {color && renderColor ? renderColor(color, 'h-3 w-3 rounded-full border border-border') : null}\n </div>\n {resolvedTimestamp ? <div className=\"text-xs text-muted-foreground\">{resolvedTimestamp}</div> : null}\n </div>\n </div>\n )\n}\n\nexport type NotesSectionProps<C = unknown> = {\n entityId: string | null\n dealId?: string | null\n emptyLabel: string\n viewerUserId: string | null\n viewerName?: string | null\n viewerEmail?: string | null\n addActionLabel: string\n emptyState: TabEmptyStateConfig\n onActionChange?: (action: SectionAction | null) => void\n translator?: Translator\n labelPrefix?: string\n inlineLabelPrefix?: string\n onLoadingChange?: (isLoading: boolean) => void\n dealOptions?: Array<{ id: string; label: string }>\n entityOptions?: Array<{ id: string; label: string }>\n dataAdapter: NotesDataAdapter<C>\n dataContext?: C\n renderIcon?: RenderIconFn\n renderColor?: RenderColorFn\n iconSuggestions?: IconOption[]\n readMarkdownPreference?: () => boolean | null\n writeMarkdownPreference?: (value: boolean) => void\n disableMarkdown?: boolean\n}\n\nexport function sanitizeHexColor(value: string | null): string | null {\n if (!value) return null\n const trimmed = value.trim()\n return /^#([0-9a-f]{6})$/i.test(trimmed) ? trimmed.toLowerCase() : null\n}\n\nexport function mapCommentSummary(input: unknown): CommentSummary {\n const data = (typeof input === 'object' && input !== null ? input : {}) as Record<string, unknown>\n const id = typeof data.id === 'string' ? data.id : generateTempId()\n const body = typeof data.body === 'string' ? data.body : ''\n const createdAt =\n typeof data.createdAt === 'string'\n ? data.createdAt\n : typeof data.created_at === 'string'\n ? data.created_at\n : new Date().toISOString()\n const authorUserId =\n typeof data.authorUserId === 'string'\n ? data.authorUserId\n : typeof data.author_user_id === 'string'\n ? data.author_user_id\n : null\n const authorName =\n typeof data.authorName === 'string'\n ? data.authorName\n : typeof data.author_name === 'string'\n ? data.author_name\n : null\n const authorEmail =\n typeof data.authorEmail === 'string'\n ? data.authorEmail\n : typeof data.author_email === 'string'\n ? data.author_email\n : null\n const dealId =\n typeof data.dealId === 'string'\n ? data.dealId\n : typeof data.deal_id === 'string'\n ? data.deal_id\n : null\n const dealTitle =\n typeof data.dealTitle === 'string'\n ? data.dealTitle\n : typeof data.deal_title === 'string'\n ? data.deal_title\n : null\n const appearanceIcon =\n typeof data.appearanceIcon === 'string'\n ? data.appearanceIcon\n : typeof data.appearance_icon === 'string'\n ? data.appearance_icon\n : null\n const appearanceColor =\n typeof data.appearanceColor === 'string'\n ? data.appearanceColor\n : typeof data.appearance_color === 'string'\n ? data.appearance_color\n : null\n return {\n id,\n body,\n createdAt,\n authorUserId,\n authorName,\n authorEmail,\n dealId,\n dealTitle,\n appearanceIcon,\n appearanceColor,\n }\n}\n\nfunction NotesSectionImpl<C = unknown>({\n entityId,\n dealId,\n emptyLabel,\n viewerUserId,\n viewerName,\n viewerEmail,\n addActionLabel,\n emptyState,\n onActionChange,\n translator,\n labelPrefix = 'customers.people.detail.notes',\n inlineLabelPrefix = 'customers.people.detail.inline',\n onLoadingChange,\n dealOptions,\n entityOptions,\n dataAdapter,\n dataContext,\n renderIcon,\n renderColor,\n iconSuggestions,\n readMarkdownPreference,\n writeMarkdownPreference,\n disableMarkdown,\n}: NotesSectionProps<C>) {\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const t = React.useMemo<Translator>(() => translator ?? ((key, fallback) => fallback ?? key), [translator])\n const label = React.useCallback(\n (suffix: string, fallback?: string, params?: Record<string, string | number>) =>\n t(`${labelPrefix}.${suffix}`, fallback, params),\n [labelPrefix, t],\n )\n const inlineLabel = React.useCallback(\n (suffix: string, fallback?: string, params?: Record<string, string | number>) =>\n t(`${inlineLabelPrefix}.${suffix}`, fallback, params),\n [inlineLabelPrefix, t],\n )\n const [markdownPlugins, setMarkdownPlugins] = React.useState<PluggableList>([])\n React.useEffect(() => {\n if (isTestEnv) return\n let mounted = true\n void loadMarkdownPlugins().then((plugins) => {\n if (!mounted) return\n setMarkdownPlugins(plugins)\n })\n return () => {\n mounted = false\n }\n }, [])\n\n const normalizedDealOptions = React.useMemo(() => {\n if (!Array.isArray(dealOptions)) return []\n const seen = new Set<string>()\n return dealOptions\n .map((option) => {\n if (!option || typeof option !== 'object') return null\n const id = typeof option.id === 'string' ? option.id.trim() : ''\n if (!id || seen.has(id)) return null\n const label =\n typeof option.label === 'string' && option.label.trim().length\n ? option.label.trim()\n : id\n seen.add(id)\n return { id, label }\n })\n .filter((option): option is { id: string; label: string } => !!option)\n }, [dealOptions])\n\n const dealLabelMap = React.useMemo(() => {\n const map = new Map<string, string>()\n normalizedDealOptions.forEach((option) => {\n map.set(option.id, option.label)\n })\n return map\n }, [normalizedDealOptions])\n\n const normalizedEntityOptions = React.useMemo(() => {\n if (!Array.isArray(entityOptions)) return []\n const seen = new Set<string>()\n return entityOptions\n .map((option) => {\n if (!option || typeof option !== 'object') return null\n const id = typeof option.id === 'string' ? option.id.trim() : ''\n if (!id || seen.has(id)) return null\n const label =\n typeof option.label === 'string' && option.label.trim().length\n ? option.label.trim()\n : id\n seen.add(id)\n return { id, label }\n })\n .filter((option): option is { id: string; label: string } => !!option)\n }, [entityOptions])\n\n const [selectedDealId, setSelectedDealId] = React.useState<string>(() => {\n const initial = typeof dealId === 'string' ? dealId.trim() : ''\n return initial\n })\n React.useEffect(() => {\n const initial = typeof dealId === 'string' ? dealId.trim() : ''\n if (initial !== selectedDealId) {\n setSelectedDealId(initial)\n }\n }, [dealId, selectedDealId])\n\n const [selectedEntityId, setSelectedEntityId] = React.useState<string>(() => {\n if (normalizedEntityOptions.length) return normalizedEntityOptions[0].id\n return typeof entityId === 'string' ? entityId : ''\n })\n React.useEffect(() => {\n if (normalizedEntityOptions.length) {\n if (!normalizedEntityOptions.some((option) => option.id === selectedEntityId)) {\n setSelectedEntityId(normalizedEntityOptions[0].id)\n }\n } else {\n const initial = typeof entityId === 'string' ? entityId : ''\n if (initial !== selectedEntityId) {\n setSelectedEntityId(initial)\n }\n }\n }, [entityId, normalizedEntityOptions, selectedEntityId])\n\n const resolvedEntityId = React.useMemo(() => {\n if (normalizedEntityOptions.length) return selectedEntityId\n return typeof entityId === 'string' ? entityId : ''\n }, [entityId, normalizedEntityOptions, selectedEntityId])\n\n const resolvedDealId = React.useMemo(() => {\n const trimmed = typeof selectedDealId === 'string' ? selectedDealId.trim() : ''\n return trimmed\n }, [selectedDealId])\n\n const hasEntity = resolvedEntityId.length > 0\n\n const [notes, setNotes] = React.useState<CommentSummary[]>([])\n const [isLoading, setIsLoading] = React.useState<boolean>(() => Boolean(entityId || dealId))\n const [isSubmitting, setIsSubmitting] = React.useState(false)\n const [loadError, setLoadError] = React.useState<string | null>(null)\n const pendingCounterRef = React.useRef(0)\n\n const pushLoading = React.useCallback(() => {\n pendingCounterRef.current += 1\n if (pendingCounterRef.current === 1) {\n onLoadingChange?.(true)\n }\n }, [onLoadingChange])\n\n const popLoading = React.useCallback(() => {\n pendingCounterRef.current = Math.max(0, pendingCounterRef.current - 1)\n if (pendingCounterRef.current === 0) {\n onLoadingChange?.(false)\n }\n }, [onLoadingChange])\n\n const [composerOpen, setComposerOpen] = React.useState(false)\n const [draftBody, setDraftBody] = React.useState('')\n const [draftIcon, setDraftIcon] = React.useState<string | null>(null)\n const [draftColor, setDraftColor] = React.useState<string | null>(null)\n const [isMarkdownEnabled, setIsMarkdownEnabled] = React.useState(false)\n const textareaRef = React.useRef<HTMLTextAreaElement | null>(null)\n const formRef = React.useRef<HTMLFormElement | null>(null)\n const focusComposer = React.useCallback(() => {\n if (!hasEntity) return\n setComposerOpen(true)\n window.requestAnimationFrame(() => {\n if (isMarkdownEnabled) {\n const markdownTextarea = formRef.current?.querySelector('textarea')\n if (markdownTextarea instanceof HTMLTextAreaElement) {\n markdownTextarea.focus()\n markdownTextarea.scrollIntoView({ behavior: 'smooth', block: 'center' })\n return\n }\n }\n const element = textareaRef.current\n if (!element) return\n element.focus()\n element.scrollIntoView({ behavior: 'smooth', block: 'center' })\n })\n }, [formRef, hasEntity, isMarkdownEnabled])\n const [appearanceDialogState, setAppearanceDialogState] = React.useState<\n | { mode: 'create'; icon: string | null; color: string | null }\n | { mode: 'edit'; noteId: string; icon: string | null; color: string | null }\n | null\n >(null)\n const [appearanceDialogSaving, setAppearanceDialogSaving] = React.useState(false)\n const [appearanceDialogError, setAppearanceDialogError] = React.useState<string | null>(null)\n const [contentEditor, setContentEditor] = React.useState<{ id: string; value: string }>({ id: '', value: '' })\n const [contentSavingId, setContentSavingId] = React.useState<string | null>(null)\n const [contentError, setContentError] = React.useState<string | null>(null)\n const contentTextareaRef = React.useRef<HTMLTextAreaElement | null>(null)\n const [visibleCount, setVisibleCount] = React.useState(0)\n const [deletingNoteId, setDeletingNoteId] = React.useState<string | null>(null)\n\n React.useEffect(() => {\n const queryEntityId = typeof entityId === 'string' ? entityId : ''\n const queryDealId = typeof dealId === 'string' ? dealId : ''\n if (!queryEntityId && !queryDealId) {\n setNotes([])\n setLoadError(null)\n setIsLoading(false)\n return\n }\n let cancelled = false\n setIsLoading(true)\n setLoadError(null)\n pushLoading()\n async function loadNotes() {\n try {\n const mapped = await dataAdapter.list({\n entityId: queryEntityId || null,\n dealId: queryDealId || null,\n context: dataContext,\n })\n if (cancelled) return\n setNotes(mapped)\n } catch (err) {\n if (cancelled) return\n const message =\n err instanceof Error ? err.message : label('loadError', 'Failed to load notes.')\n setNotes([])\n setLoadError(message)\n flash(message, 'error')\n } finally {\n if (!cancelled) setIsLoading(false)\n popLoading()\n }\n }\n loadNotes().catch(() => {})\n return () => {\n cancelled = true\n }\n }, [dataAdapter, dataContext, dealId, entityId, popLoading, pushLoading, t])\n\n const youLabel = label('you', 'You')\n const viewerLabel = React.useMemo(() => viewerName ?? viewerEmail ?? null, [viewerEmail, viewerName])\n\n const handleMarkdownToggle = React.useCallback(() => {\n setIsMarkdownEnabled((prev) => {\n const next = !prev\n if (writeMarkdownPreference) {\n writeMarkdownPreference(next)\n }\n return next\n })\n }, [writeMarkdownPreference])\n\n React.useEffect(() => {\n if (!onActionChange) return\n if (!notes.length) {\n onActionChange(null)\n return\n }\n onActionChange({\n label: addActionLabel,\n onClick: focusComposer,\n disabled: isSubmitting || isLoading || !hasEntity,\n icon: <Plus className=\"mr-2 h-4 w-4\" />,\n })\n return () => onActionChange(null)\n }, [onActionChange, addActionLabel, focusComposer, hasEntity, isLoading, isSubmitting, notes.length])\n\n const adjustTextareaSize = React.useCallback((element: HTMLTextAreaElement | null) => {\n if (!element) return\n element.style.height = 'auto'\n element.style.height = `${element.scrollHeight}px`\n }, [])\n\n React.useEffect(() => {\n adjustTextareaSize(textareaRef.current)\n }, [adjustTextareaSize, draftBody, isMarkdownEnabled, composerOpen])\n\n React.useEffect(() => {\n const preference = readMarkdownPreference ? readMarkdownPreference() : null\n if (preference !== null) {\n setIsMarkdownEnabled(preference)\n }\n }, [readMarkdownPreference])\n\n React.useEffect(() => {\n if (!notes.length) {\n setVisibleCount(0)\n return\n }\n const baseline = Math.min(5, notes.length)\n setVisibleCount((prev) => {\n if (prev >= notes.length) return prev\n return Math.min(Math.max(prev, baseline), notes.length)\n })\n }, [notes.length])\n\n React.useEffect(() => {\n if (hasEntity) return\n setComposerOpen(false)\n setDraftBody('')\n setDraftIcon(null)\n setDraftColor(null)\n }, [hasEntity])\n\n const visibleNotes = React.useMemo(() => notes.slice(0, visibleCount), [notes, visibleCount])\n const hasVisibleNotes = React.useMemo(() => visibleCount > 0, [visibleCount])\n\n const loadMoreLabel = label('loadMore')\n\n const handleCreateNote = React.useCallback(\n async (input: { body: string; appearanceIcon: string | null; appearanceColor: string | null }) => {\n if (!hasEntity || !resolvedEntityId) {\n flash(label('entityMissing', 'Unable to determine current person.'), 'error')\n return false\n }\n const body = input.body.trim()\n if (!body) {\n focusComposer()\n return false\n }\n const icon = input.appearanceIcon && input.appearanceIcon.trim().length ? input.appearanceIcon.trim() : null\n const color = sanitizeHexColor(input.appearanceColor)\n const targetDealId = resolvedDealId.length ? resolvedDealId : null\n const dealLabel = targetDealId ? dealLabelMap.get(targetDealId) ?? null : null\n setIsSubmitting(true)\n pushLoading()\n try {\n const responseBody =\n (await dataAdapter.create({\n entityId: resolvedEntityId,\n body,\n appearanceIcon: icon,\n appearanceColor: color,\n dealId: targetDealId,\n context: dataContext,\n })) ?? {}\n setNotes((prev) => {\n const viewerId = viewerUserId ?? null\n const resolvedAuthorId =\n typeof responseBody?.authorUserId === 'string' ? responseBody.authorUserId : viewerId ?? null\n const resolvedAuthorName = (() => {\n if (resolvedAuthorId && viewerId && resolvedAuthorId === viewerId) {\n return youLabel\n }\n return typeof responseBody?.authorName === 'string' ? responseBody.authorName : viewerLabel\n })()\n const resolvedAuthorEmail = (() => {\n if (resolvedAuthorId && viewerId && resolvedAuthorId === viewerId) {\n return viewerEmail ?? null\n }\n return typeof responseBody?.authorEmail === 'string' ? responseBody.authorEmail : null\n })()\n const newNote: CommentSummary = {\n id: typeof responseBody?.id === 'string' ? responseBody.id : generateTempId(),\n body,\n createdAt: new Date().toISOString(),\n authorUserId: resolvedAuthorId,\n authorName: resolvedAuthorName,\n authorEmail: resolvedAuthorEmail,\n dealId: targetDealId,\n dealTitle: dealLabel,\n appearanceIcon: icon,\n appearanceColor: color,\n }\n return [newNote, ...prev]\n })\n flash(label('success'), 'success')\n return true\n } catch (err) {\n const message = err instanceof Error ? err.message : label('error')\n flash(message, 'error')\n return false\n } finally {\n setIsSubmitting(false)\n popLoading()\n }\n },\n [dataAdapter, dataContext, dealLabelMap, focusComposer, hasEntity, popLoading, pushLoading, resolvedDealId, resolvedEntityId, t, viewerEmail, viewerLabel, viewerUserId, youLabel],\n )\n\n const handleUpdateNote = React.useCallback(\n async (noteId: string, patch: { body?: string; appearanceIcon?: string | null; appearanceColor?: string | null }) => {\n const sanitizedBody = patch.body\n const sanitizedIcon =\n patch.appearanceIcon !== undefined && patch.appearanceIcon !== null && patch.appearanceIcon.trim().length\n ? patch.appearanceIcon.trim()\n : patch.appearanceIcon === null\n ? null\n : undefined\n const sanitizedColor =\n patch.appearanceColor !== undefined ? sanitizeHexColor(patch.appearanceColor ?? null) : undefined\n try {\n await dataAdapter.update({\n id: noteId,\n patch: {\n body: sanitizedBody,\n appearanceIcon: sanitizedIcon,\n appearanceColor: sanitizedColor,\n },\n context: dataContext,\n })\n setNotes((prev) => {\n const nextComments = prev.map((comment) => {\n if (comment.id !== noteId) return comment\n const next = { ...comment }\n if (sanitizedBody !== undefined) next.body = sanitizedBody\n if (sanitizedIcon !== undefined) next.appearanceIcon = sanitizedIcon ?? null\n if (sanitizedColor !== undefined) next.appearanceColor = sanitizedColor ?? null\n return next\n })\n return nextComments\n })\n flash(label('updateSuccess'), 'success')\n } catch (error) {\n const message = error instanceof Error ? error.message : label('updateError')\n flash(message, 'error')\n throw error instanceof Error ? error : new Error(message)\n }\n },\n [dataAdapter, dataContext, t],\n )\n\n const handleDeleteNote = React.useCallback(\n async (note: CommentSummary) => {\n const confirmed = await confirm({\n title: label('deleteConfirm', 'Delete this note?'),\n text: 'This action cannot be undone.',\n variant: 'destructive',\n })\n if (!confirmed) return\n setDeletingNoteId(note.id)\n pushLoading()\n try {\n await dataAdapter.delete({ id: note.id, context: dataContext })\n setNotes((prev) => prev.filter((existing) => existing.id !== note.id))\n flash(label('deleteSuccess', 'Note deleted'), 'success')\n } catch (err) {\n const message = err instanceof Error ? err.message : label('deleteError', 'Failed to delete note')\n flash(message, 'error')\n } finally {\n setDeletingNoteId(null)\n popLoading()\n }\n },\n [confirm, dataAdapter, dataContext, label, popLoading, pushLoading],\n )\n\n const handleSubmit = React.useCallback(\n async (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault()\n const created = await handleCreateNote({\n body: draftBody,\n appearanceIcon: draftIcon,\n appearanceColor: draftColor,\n })\n if (created) {\n setDraftBody('')\n setDraftIcon(null)\n setDraftColor(null)\n }\n },\n [draftBody, draftColor, draftIcon, handleCreateNote],\n )\n\n const handleLoadMore = React.useCallback(() => {\n setVisibleCount((prev) => {\n if (prev >= notes.length) return prev\n return Math.min(prev + 5, notes.length)\n })\n }, [notes.length])\n\n const handleAppearanceDialogSubmit = React.useCallback(async () => {\n if (!appearanceDialogState) return\n setAppearanceDialogError(null)\n const sanitizedIcon =\n appearanceDialogState.icon && appearanceDialogState.icon.trim().length\n ? appearanceDialogState.icon.trim()\n : null\n const sanitizedColor = sanitizeHexColor(appearanceDialogState.color ?? null)\n if (appearanceDialogState.mode === 'create') {\n setDraftIcon(sanitizedIcon)\n setDraftColor(sanitizedColor)\n setAppearanceDialogState(null)\n return\n }\n setAppearanceDialogSaving(true)\n try {\n await handleUpdateNote(appearanceDialogState.noteId, {\n appearanceIcon: sanitizedIcon,\n appearanceColor: sanitizedColor,\n })\n setAppearanceDialogState(null)\n } catch (err) {\n const message =\n err instanceof Error\n ? err.message\n : label('appearance.error', 'Failed to update appearance.')\n setAppearanceDialogError(message)\n } finally {\n setAppearanceDialogSaving(false)\n }\n }, [appearanceDialogState, handleUpdateNote, t])\n\n const handleAppearanceDialogClose = React.useCallback(() => {\n if (appearanceDialogSaving) return\n setAppearanceDialogState(null)\n setAppearanceDialogError(null)\n }, [appearanceDialogSaving])\n\n const handleContentSave = React.useCallback(async () => {\n if (!contentEditor.id) return\n const trimmed = contentEditor.value.trim()\n if (!trimmed) {\n setContentError(label('updateError', 'Failed to update note'))\n return\n }\n setContentSavingId(contentEditor.id)\n setContentError(null)\n try {\n await handleUpdateNote(contentEditor.id, { body: trimmed })\n setContentEditor({ id: '', value: '' })\n } catch (err) {\n const message =\n err instanceof Error ? err.message : label('updateError', 'Failed to update note')\n setContentError(message)\n } finally {\n setContentSavingId(null)\n }\n }, [contentEditor, handleUpdateNote, t])\n\n const handleContentEditorKeyDown = React.useCallback(\n (event: React.KeyboardEvent) => {\n if (!contentEditor.id) return\n if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') {\n event.preventDefault()\n if (!contentSavingId) void handleContentSave()\n return\n }\n if (event.key === 'Escape') {\n event.preventDefault()\n setContentEditor({ id: '', value: '' })\n setContentError(null)\n }\n },\n [contentEditor.id, contentSavingId, handleContentSave],\n )\n\n const handleComposerKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLFormElement>) => {\n if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') {\n event.preventDefault()\n formRef.current?.requestSubmit()\n }\n },\n [],\n )\n\n const handleContentKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>, note: CommentSummary) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n setContentEditor({ id: note.id, value: note.body })\n }\n },\n [],\n )\n\n const noteAuthorLabel = React.useCallback(\n (note: CommentSummary) => {\n if (note.authorUserId && viewerUserId && note.authorUserId === viewerUserId) {\n return youLabel\n }\n return note.authorName ?? note.authorEmail ?? youLabel\n },\n [viewerUserId, youLabel],\n )\n\n const noteAppearanceLabels = React.useMemo<AppearanceSelectorLabels>(\n () => ({\n colorLabel: label('appearance.colorLabel'),\n colorHelp: label('appearance.colorHelp'),\n colorClearLabel: label('appearance.clearColor'),\n iconLabel: label('appearance.iconLabel'),\n iconPlaceholder: label('appearance.iconPlaceholder'),\n iconPickerTriggerLabel: label('appearance.iconPicker'),\n iconSearchPlaceholder: label('appearance.iconSearchPlaceholder'),\n iconSearchEmptyLabel: label('appearance.iconSearchEmpty'),\n iconSuggestionsLabel: label('appearance.iconSuggestions'),\n iconClearLabel: label('appearance.iconClear'),\n previewEmptyLabel: label('appearance.previewEmpty'),\n }),\n [label],\n )\n\n const composerAuthor = React.useMemo(\n () => youLabel,\n [youLabel],\n )\n const composerHasAppearance = Boolean(draftIcon) || Boolean(draftColor)\n const appearanceDialogOpen = appearanceDialogState !== null\n const editingAppearanceNoteId =\n appearanceDialogState?.mode === 'edit' ? appearanceDialogState.noteId : null\n const addNoteShortcutLabel = label('addShortcut', 'Add note \u2318\u23CE / Ctrl+Enter')\n const saveAppearanceShortcutLabel = label('appearance.saveShortcut', 'Save appearance \u2318\u23CE / Ctrl+Enter')\n const composerSubmitLabel = addNoteShortcutLabel\n const appearanceDialogPrimaryLabel = saveAppearanceShortcutLabel\n const appearanceDialogSavingLabel =\n appearanceDialogState?.mode === 'edit'\n ? label('appearance.saving')\n : label('saving', 'Saving note\u2026')\n\n return (\n <div className=\"mt-0 space-y-2\">\n <div\n className={[\n 'overflow-hidden rounded-xl transition-all duration-300 ease-out',\n composerOpen ? 'max-h-[1200px] bg-muted/10 p-4 opacity-100' : 'pointer-events-none max-h-0 p-0 opacity-0',\n ].join(' ')}\n aria-hidden={!composerOpen}\n >\n {composerOpen ? (\n <form\n ref={formRef}\n onSubmit={handleSubmit}\n onKeyDown={handleComposerKeyDown}\n className=\"space-y-3\"\n >\n <div className=\"flex flex-wrap items-center justify-between gap-2\">\n <h3 className=\"text-sm font-medium\">{label('addLabel')}</h3>\n <div className=\"flex flex-wrap items-center gap-1\">\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => {\n setAppearanceDialogError(null)\n setAppearanceDialogState({ mode: 'create', icon: draftIcon, color: draftColor })\n }}\n disabled={isSubmitting || isLoading || !hasEntity}\n >\n <span className=\"sr-only\">{label('appearance.toggleOpen', 'Customize appearance')}</span>\n <Palette className=\"h-4 w-4\" />\n </Button>\n {disableMarkdown ? null : (\n <Button\n type=\"button\"\n variant={isMarkdownEnabled ? 'secondary' : 'ghost'}\n size=\"icon\"\n onClick={handleMarkdownToggle}\n aria-pressed={isMarkdownEnabled}\n disabled={isSubmitting || isLoading}\n >\n <FileCode className=\"h-4 w-4\" />\n </Button>\n )}\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"ghost\"\n onClick={() => {\n setComposerOpen(false)\n setDraftBody('')\n setDraftIcon(null)\n setDraftColor(null)\n }}\n disabled={isSubmitting || isLoading}\n >\n {inlineLabel('cancel')}\n </Button>\n </div>\n </div>\n {(normalizedEntityOptions.length || normalizedDealOptions.length) ? (\n <div className=\"grid gap-3 sm:grid-cols-2\">\n {normalizedEntityOptions.length ? (\n <div className=\"flex flex-col gap-1\">\n <label\n htmlFor=\"note-entity-select\"\n className=\"text-xs font-medium text-muted-foreground\"\n >\n {label('fields.entity', 'Assign to customer')}\n </label>\n <select\n id=\"note-entity-select\"\n className=\"h-9 rounded border border-muted-foreground/40 bg-background px-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary\"\n value={selectedEntityId}\n onChange={(event) => setSelectedEntityId(event.target.value)}\n disabled={isSubmitting || isLoading || !normalizedEntityOptions.length}\n >\n {normalizedEntityOptions.map((option) => (\n <option key={option.id} value={option.id}>\n {option.label}\n </option>\n ))}\n </select>\n </div>\n ) : null}\n {normalizedDealOptions.length ? (\n <div className=\"flex flex-col gap-1\">\n <label\n htmlFor=\"note-deal-select\"\n className=\"text-xs font-medium text-muted-foreground\"\n >\n {label('fields.deal', 'Link to deal (optional)')}\n </label>\n <select\n id=\"note-deal-select\"\n className=\"h-9 rounded border border-muted-foreground/40 bg-background px-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary\"\n value={selectedDealId}\n onChange={(event) => setSelectedDealId(event.target.value)}\n disabled={isSubmitting || isLoading}\n >\n <option value=\"\">\n {label('fields.dealPlaceholder', 'No linked deal')}\n </option>\n {normalizedDealOptions.map((option) => (\n <option key={option.id} value={option.id}>\n {option.label}\n </option>\n ))}\n </select>\n </div>\n ) : null}\n </div>\n ) : null}\n <SwitchableMarkdownInput\n value={draftBody}\n onChange={setDraftBody}\n isMarkdownEnabled={isMarkdownEnabled}\n disableMarkdown={disableMarkdown}\n rows={1}\n placeholder={label('placeholder')}\n textareaRef={textareaRef}\n onTextareaInput={(event) => adjustTextareaSize(event.currentTarget)}\n disabled={isSubmitting || isLoading || !hasEntity}\n remarkPlugins={markdownPlugins}\n />\n {composerHasAppearance ? (\n <div className=\"flex flex-wrap items-center justify-between gap-3 rounded-lg border border-dashed border-muted-foreground/40 px-3 py-2\">\n <div className=\"flex flex-wrap items-center gap-3 text-sm\">\n {draftIcon && renderIcon ? (\n <span className=\"inline-flex h-7 w-7 items-center justify-center rounded border border-border bg-muted/40\">\n {renderIcon(draftIcon, 'h-4 w-4')}\n </span>\n ) : null}\n <span className=\"font-semibold text-foreground\">{composerAuthor}</span>\n {draftColor && renderColor ? (\n <span className=\"flex items-center gap-2\">\n {renderColor(draftColor, 'h-3.5 w-3.5 rounded-full border border-border')}\n <span className=\"text-xs font-medium uppercase text-muted-foreground\">{draftColor}</span>\n </span>\n ) : null}\n </div>\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"ghost\"\n onClick={() => {\n setDraftIcon(null)\n setDraftColor(null)\n }}\n disabled={isSubmitting}\n >\n {label('appearance.clearAll', 'Clear')}\n </Button>\n </div>\n ) : null}\n <div className=\"flex justify-end\">\n <Button\n type=\"submit\"\n size=\"sm\"\n disabled={isSubmitting || isLoading || !hasEntity}\n >\n {isSubmitting ? <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" /> : null}\n {composerSubmitLabel}\n </Button>\n </div>\n </form>\n ) : null}\n </div>\n\n {loadError ? <ErrorMessage label={loadError} className=\"mt-3\" /> : null}\n\n <div className=\"space-y-3\">\n {isLoading ? (\n <LoadingMessage\n label={label('loading', 'Loading notes\u2026')}\n className=\"border-0 bg-transparent p-0 py-8 justify-center\"\n />\n ) : hasVisibleNotes ? (\n visibleNotes.map((note) => {\n const author = noteAuthorLabel(note)\n const isAppearanceSaving = appearanceDialogSaving && editingAppearanceNoteId === note.id\n const isEditingContent = contentEditor.id === note.id\n const displayIcon = note.appearanceIcon ?? null\n const displayColor = note.appearanceColor ?? null\n const timestampValue = note.createdAt\n const fallbackTimestampLabel = formatDateTime(note.createdAt) ?? emptyLabel\n return (\n <div key={note.id} className=\"group space-y-2 rounded-lg border bg-card p-4\">\n <div className=\"flex flex-wrap items-start justify-between gap-3\">\n <div className=\"space-y-1\">\n <TimelineItemHeader\n title={author}\n timestamp={timestampValue}\n fallbackTimestampLabel={fallbackTimestampLabel}\n icon={displayIcon}\n color={displayColor}\n renderIcon={renderIcon}\n renderColor={renderColor}\n />\n {note.dealId ? (\n <div className=\"flex items-center gap-2 text-xs text-muted-foreground\">\n <ArrowUpRightSquare className=\"h-3.5 w-3.5\" />\n <a\n href={`/backend/customers/deals/${encodeURIComponent(note.dealId)}`}\n className=\"font-medium text-foreground hover:underline\"\n >\n {note.dealTitle && note.dealTitle.length\n ? note.dealTitle\n : label('linkedDeal', 'Linked deal')}\n </a>\n </div>\n ) : null}\n </div>\n <div\n className={`flex items-center gap-2 transition-opacity ${\n isEditingContent ? 'opacity-100' : 'opacity-100 md:opacity-0 md:group-hover:opacity-100 focus-within:opacity-100'\n }`}\n >\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={() => setContentEditor({ id: note.id, value: note.body })}\n >\n <Pencil className=\"h-4 w-4\" />\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={(event) => {\n event.stopPropagation()\n setAppearanceDialogError(null)\n setAppearanceDialogState({\n mode: 'edit',\n noteId: note.id,\n icon: note.appearanceIcon ?? null,\n color: note.appearanceColor ?? null,\n })\n }}\n disabled={appearanceDialogSaving && editingAppearanceNoteId === note.id}\n >\n {isAppearanceSaving ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : <Palette className=\"h-4 w-4\" />}\n </Button>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={(event) => {\n event.stopPropagation()\n void handleDeleteNote(note)\n }}\n disabled={deletingNoteId === note.id}\n >\n {deletingNoteId === note.id ? (\n <span className=\"relative flex h-4 w-4 items-center justify-center text-destructive\">\n <span className=\"absolute h-4 w-4 animate-spin rounded-full border border-destructive border-t-transparent\" />\n </span>\n ) : (\n <Trash2 className=\"h-4 w-4\" />\n )}\n </Button>\n </div>\n </div>\n {isEditingContent ? (\n <div className=\"space-y-2\" onKeyDown={handleContentEditorKeyDown}>\n <SwitchableMarkdownInput\n value={contentEditor.value}\n onChange={(nextValue) => setContentEditor((prev) => ({ ...prev, value: nextValue }))}\n isMarkdownEnabled={isMarkdownEnabled}\n disableMarkdown={disableMarkdown}\n rows={3}\n textareaRef={contentTextareaRef}\n onTextareaInput={(event) => adjustTextareaSize(event.currentTarget)}\n textareaClassName=\"w-full resize-none overflow-hidden rounded-md border border-border px-3 py-2 text-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary\"\n editorWrapperClassName=\"w-full rounded-md border border-muted-foreground/20 bg-background p-2\"\n remarkPlugins={markdownPlugins}\n />\n {contentError ? <p className=\"text-xs text-red-600\">{contentError}</p> : null}\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button type=\"button\" size=\"sm\" onClick={handleContentSave} disabled={contentSavingId === note.id}>\n {contentSavingId === note.id ? (\n <>\n <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" />\n {label('saving')}\n </>\n ) : (\n inlineLabel('saveShortcut')\n )}\n </Button>\n {disableMarkdown ? null : (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={handleMarkdownToggle}\n aria-pressed={isMarkdownEnabled}\n className={isMarkdownEnabled ? 'text-primary' : undefined}\n disabled={contentSavingId === note.id}\n >\n <FileCode className=\"h-4 w-4\" />\n </Button>\n )}\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"ghost\"\n onClick={() => setContentEditor({ id: '', value: '' })}\n disabled={contentSavingId === note.id}\n >\n {inlineLabel('cancel')}\n </Button>\n </div>\n </div>\n ) : (\n <div\n role=\"button\"\n tabIndex={0}\n className=\"cursor-pointer text-sm\"\n onClick={() => setContentEditor({ id: note.id, value: note.body })}\n onKeyDown={(event) => handleContentKeyDown(event, note)}\n >\n <MarkdownPreviewComponent\n remarkPlugins={markdownPlugins}\n className=\"break-words text-foreground [&>*]:mb-2 [&>*:last-child]:mb-0 [&_ul]:ml-4 [&_ul]:list-disc [&_ol]:ml-4 [&_ol]:list-decimal [&_code]:rounded [&_code]:bg-muted [&_code]:px-1 [&_code]:py-0.5 [&_pre]:rounded-md [&_pre]:bg-muted [&_pre]:p-3 [&_pre]:text-xs\"\n >\n {note.body}\n </MarkdownPreviewComponent>\n </div>\n )}\n </div>\n )\n })\n ) : composerOpen ? null : (\n <TabEmptyState\n title={emptyState.title}\n description={emptyState.description}\n action={{\n label: emptyState.actionLabel,\n onClick: focusComposer,\n disabled: isSubmitting || !hasEntity,\n }}\n />\n )}\n {isLoading || visibleCount >= notes.length ? null : (\n <div className=\"flex justify-center\">\n <Button variant=\"outline\" size=\"sm\" onClick={handleLoadMore}>\n {loadMoreLabel}\n </Button>\n </div>\n )}\n </div>\n <AppearanceDialog\n open={appearanceDialogOpen}\n title={\n appearanceDialogState?.mode === 'edit'\n ? label('appearance.edit')\n : label('appearance.toggleOpen', 'Customize appearance')\n }\n icon={appearanceDialogState?.icon ?? null}\n color={appearanceDialogState?.color ?? null}\n labels={noteAppearanceLabels}\n iconSuggestions={iconSuggestions}\n onIconChange={(value) => setAppearanceDialogState((prev) => (prev ? { ...prev, icon: value ?? null } : prev))}\n onColorChange={(value) => setAppearanceDialogState((prev) => (prev ? { ...prev, color: value ?? null } : prev))}\n onSubmit={() => {\n void handleAppearanceDialogSubmit()\n }}\n onClose={handleAppearanceDialogClose}\n isSaving={appearanceDialogSaving}\n errorMessage={appearanceDialogError}\n primaryLabel={appearanceDialogPrimaryLabel}\n savingLabel={appearanceDialogSavingLabel}\n cancelLabel={label('appearance.cancel')}\n />\n {ConfirmDialogElement}\n </div>\n )\n}\n\nexport function NotesSection<C = unknown>(props: NotesSectionProps<C>) {\n const handle = ComponentReplacementHandles.section('ui.detail', 'NotesSection')\n const Resolved = useRegisteredComponent<NotesSectionProps<C>>(\n handle,\n NotesSectionImpl as React.ComponentType<NotesSectionProps<C>>,\n )\n\n return (\n <div data-component-handle={handle}>\n <Resolved {...props} />\n </div>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["label"]
7
7
  }
@@ -6,7 +6,9 @@ import { Button } from "@open-mercato/ui/primitives/button";
6
6
  import { TagsInput } from "@open-mercato/ui/backend/inputs/TagsInput";
7
7
  import { DataLoader } from "@open-mercato/ui/primitives/DataLoader";
8
8
  import { flash } from "@open-mercato/ui/backend/FlashMessages";
9
- function TagsSection({
9
+ import { ComponentReplacementHandles } from "@open-mercato/shared/modules/widgets/component-registry";
10
+ import { useRegisteredComponent } from "../injection/useRegisteredComponent.js";
11
+ function TagsSectionImpl({
10
12
  title,
11
13
  tags,
12
14
  onChange,
@@ -246,6 +248,14 @@ function TagsSection({
246
248
  )
247
249
  ] });
248
250
  }
251
+ function TagsSection(props) {
252
+ const handle = ComponentReplacementHandles.section("ui.detail", "TagsSection");
253
+ const Resolved = useRegisteredComponent(
254
+ handle,
255
+ TagsSectionImpl
256
+ );
257
+ return /* @__PURE__ */ jsx("div", { "data-component-handle": handle, children: /* @__PURE__ */ jsx(Resolved, { ...props }) });
258
+ }
249
259
  var TagsSection_default = TagsSection;
250
260
  export {
251
261
  TagsSection,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/backend/detail/TagsSection.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Pencil, X } from 'lucide-react'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { TagsInput } from '@open-mercato/ui/backend/inputs/TagsInput'\nimport { DataLoader } from '@open-mercato/ui/primitives/DataLoader'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\n\nexport type TagOption = {\n id: string\n label: string\n color?: string | null\n}\n\nexport type TagsSectionLabels = {\n loading: string\n placeholder: string\n empty: string\n loadError: string\n createError: string\n updateError: string\n labelRequired: string\n saveShortcut: string\n cancelShortcut: string\n edit?: string\n cancel?: string\n success?: string\n}\n\nexport type TagsSectionProps = {\n title: string\n tags: TagOption[]\n onChange?: (next: TagOption[]) => void\n isSubmitting?: boolean\n canEdit?: boolean\n loadOptions: (query?: string) => Promise<TagOption[]>\n createTag: (label: string) => Promise<TagOption>\n onSave: (params: {\n next: TagOption[]\n added: TagOption[]\n removed: TagOption[]\n }) => Promise<void>\n labels: TagsSectionLabels\n}\n\nexport function TagsSection({\n title,\n tags,\n onChange,\n isSubmitting = false,\n canEdit = true,\n loadOptions,\n createTag,\n onSave,\n labels,\n}: TagsSectionProps) {\n const [editing, setEditing] = React.useState(false)\n const [draft, setDraft] = React.useState<string[]>([])\n const [saving, setSaving] = React.useState(false)\n const [options, setOptions] = React.useState<Map<string, TagOption>>(() => new Map())\n const [loadingOptions, setLoadingOptions] = React.useState(false)\n const [error, setError] = React.useState<string | null>(null)\n\n React.useEffect(() => {\n setOptions((prev) => {\n const next = new Map(prev)\n for (const tag of tags) {\n next.set(tag.label.toLowerCase(), tag)\n }\n return next\n })\n }, [tags])\n\n const syncFetchedOptions = React.useCallback((fetched: TagOption[]) => {\n if (!fetched.length) return\n setOptions((prev) => {\n const next = new Map(prev)\n for (const tag of fetched) {\n next.set(tag.label.toLowerCase(), tag)\n }\n return next\n })\n }, [])\n\n const loadSuggestions = React.useCallback(\n async (query?: string) => {\n try {\n const fetched = await loadOptions(query)\n syncFetchedOptions(fetched)\n return fetched.map((tag) => tag.label)\n } catch (err) {\n console.error('tags.section.loadSuggestions', err)\n return []\n }\n },\n [loadOptions, syncFetchedOptions],\n )\n\n const startEditing = React.useCallback(async () => {\n if (editing || isSubmitting || !canEdit) return\n setError(null)\n setDraft(tags.map((tag) => tag.label))\n setEditing(true)\n setLoadingOptions(true)\n try {\n const fetched = await loadOptions()\n syncFetchedOptions(fetched)\n } catch (err) {\n const message = err instanceof Error ? err.message : labels.loadError\n setError(message)\n flash(message, 'error')\n } finally {\n setLoadingOptions(false)\n }\n }, [canEdit, editing, isSubmitting, labels.loadError, loadOptions, syncFetchedOptions, tags])\n\n const cancelEditing = React.useCallback(() => {\n setEditing(false)\n setDraft([])\n setError(null)\n }, [])\n\n const ensureTagOption = React.useCallback(\n async (label: string): Promise<TagOption> => {\n const normalized = label.trim()\n if (!normalized.length) {\n throw new Error(labels.labelRequired)\n }\n const existing = options.get(normalized.toLowerCase())\n if (existing) return existing\n try {\n const created = await createTag(normalized)\n setOptions((prev) => {\n const next = new Map(prev)\n next.set(created.label.toLowerCase(), created)\n return next\n })\n return created\n } catch (err) {\n const message = err instanceof Error ? err.message : labels.createError\n throw new Error(message)\n }\n },\n [createTag, labels.createError, labels.labelRequired, options],\n )\n\n const handleSave = React.useCallback(async () => {\n if (saving) return\n const trimmed = draft.map((label) => label.trim()).filter((label) => label.length > 0)\n const uniqueLabels = Array.from(new Set(trimmed.map((label) => label.toLowerCase())))\n\n const currentIds = new Set(tags.map((tag) => tag.id))\n const finalTagOptions: TagOption[] = []\n\n setSaving(true)\n setError(null)\n try {\n for (const normalized of uniqueLabels) {\n const existing = options.get(normalized)\n if (existing) {\n finalTagOptions.push(existing)\n continue\n }\n const matchingLabel = trimmed.find((label) => label.toLowerCase() === normalized) ?? normalized\n const created = await ensureTagOption(matchingLabel)\n finalTagOptions.push(created)\n }\n\n const finalIds = new Set(finalTagOptions.map((tag) => tag.id))\n const added = finalTagOptions.filter((tag) => !currentIds.has(tag.id))\n const removed = tags.filter((tag) => !finalIds.has(tag.id))\n\n await onSave({ next: finalTagOptions, added, removed })\n\n onChange?.(finalTagOptions)\n setEditing(false)\n setDraft([])\n if (labels.success) flash(labels.success, 'success')\n } catch (err) {\n const message = err instanceof Error ? err.message : labels.updateError\n setError(message)\n flash(message, 'error')\n } finally {\n setSaving(false)\n }\n }, [draft, ensureTagOption, labels.success, labels.updateError, onChange, onSave, options, saving, tags])\n\n const activeTags = editing ? draft : tags.map((tag) => tag.label)\n\n const handleEditingKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (!editing) return\n if (event.key === 'Escape') {\n event.preventDefault()\n cancelEditing()\n return\n }\n if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') {\n event.preventDefault()\n if (saving || isSubmitting) return\n void handleSave()\n }\n },\n [cancelEditing, editing, handleSave, isSubmitting, saving],\n )\n\n const disableInteraction = isSubmitting || !canEdit\n\n return (\n <div className=\"space-y-3\">\n <div className=\"flex items-center justify-between group\">\n <h2 className=\"text-sm font-semibold\">\n {title}\n </h2>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={editing ? cancelEditing : startEditing}\n disabled={disableInteraction || saving}\n className={\n editing\n ? 'opacity-100 transition-opacity duration-150'\n : 'opacity-100 md:opacity-0 transition-opacity duration-150 md:group-hover:opacity-100 focus-visible:opacity-100'\n }\n >\n {editing ? <X className=\"h-4 w-4\" /> : <Pencil className=\"h-4 w-4\" />}\n <span className=\"sr-only\">\n {editing ? labels.cancel ?? 'Cancel' : labels.edit ?? 'Edit'}\n </span>\n </Button>\n </div>\n\n {editing ? (\n <div className=\"rounded-lg border bg-card p-4 space-y-3\">\n <DataLoader\n isLoading={loadingOptions}\n loadingMessage={labels.loading}\n spinnerSize=\"sm\"\n >\n <div className=\"space-y-3\" onKeyDown={handleEditingKeyDown}>\n <TagsInput\n value={activeTags}\n onChange={(values) => setDraft(values)}\n placeholder={labels.placeholder}\n loadSuggestions={loadSuggestions}\n autoFocus\n />\n {error ? <p className=\"text-xs text-red-600\">{error}</p> : null}\n <div className=\"flex items-center gap-2 mt-3 mb-2\">\n <Button type=\"button\" size=\"sm\" onClick={handleSave} disabled={saving || isSubmitting}>\n {saving ? (\n <span className=\"mr-2 h-4 w-4 animate-spin rounded-full border border-background border-t-primary\" />\n ) : null}\n {labels.saveShortcut}\n </Button>\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"ghost\"\n onClick={cancelEditing}\n disabled={saving || isSubmitting}\n >\n {labels.cancelShortcut}\n </Button>\n </div>\n </div>\n </DataLoader>\n </div>\n ) : (\n <div\n className=\"group/tags relative rounded-lg border bg-muted/20 p-4 transition-colors hover:border-primary/40 focus-visible:border-primary focus-visible:outline-none\"\n role={disableInteraction ? undefined : 'button'}\n tabIndex={disableInteraction ? -1 : 0}\n onClick={disableInteraction ? undefined : startEditing}\n onKeyDown={(event) => {\n if (disableInteraction) return\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n void startEditing()\n }\n }}\n >\n <span\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute right-3 top-3 text-muted-foreground opacity-0 transition-opacity duration-150 group-hover/tags:opacity-100 group-focus-within/tags:opacity-100\"\n >\n <Pencil className=\"h-4 w-4\" />\n </span>\n {tags.length === 0 ? (\n <p className=\"text-sm text-muted-foreground\">\n {labels.empty}\n </p>\n ) : (\n <div className=\"flex flex-wrap gap-2\">\n {tags.map((tag) => (\n <span\n key={tag.id}\n className=\"inline-flex items-center rounded-full border px-3 py-1 text-xs font-medium\"\n style={tag.color ? { borderColor: tag.color, color: tag.color } : undefined}\n >\n {tag.label}\n </span>\n ))}\n </div>\n )}\n </div>\n )}\n </div>\n )\n}\n\nexport default TagsSection\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Pencil, X } from 'lucide-react'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { TagsInput } from '@open-mercato/ui/backend/inputs/TagsInput'\nimport { DataLoader } from '@open-mercato/ui/primitives/DataLoader'\nimport { flash } from '@open-mercato/ui/backend/FlashMessages'\nimport { ComponentReplacementHandles } from '@open-mercato/shared/modules/widgets/component-registry'\nimport { useRegisteredComponent } from '../injection/useRegisteredComponent'\n\nexport type TagOption = {\n id: string\n label: string\n color?: string | null\n}\n\nexport type TagsSectionLabels = {\n loading: string\n placeholder: string\n empty: string\n loadError: string\n createError: string\n updateError: string\n labelRequired: string\n saveShortcut: string\n cancelShortcut: string\n edit?: string\n cancel?: string\n success?: string\n}\n\nexport type TagsSectionProps = {\n title: string\n tags: TagOption[]\n onChange?: (next: TagOption[]) => void\n isSubmitting?: boolean\n canEdit?: boolean\n loadOptions: (query?: string) => Promise<TagOption[]>\n createTag: (label: string) => Promise<TagOption>\n onSave: (params: {\n next: TagOption[]\n added: TagOption[]\n removed: TagOption[]\n }) => Promise<void>\n labels: TagsSectionLabels\n}\n\nfunction TagsSectionImpl({\n title,\n tags,\n onChange,\n isSubmitting = false,\n canEdit = true,\n loadOptions,\n createTag,\n onSave,\n labels,\n}: TagsSectionProps) {\n const [editing, setEditing] = React.useState(false)\n const [draft, setDraft] = React.useState<string[]>([])\n const [saving, setSaving] = React.useState(false)\n const [options, setOptions] = React.useState<Map<string, TagOption>>(() => new Map())\n const [loadingOptions, setLoadingOptions] = React.useState(false)\n const [error, setError] = React.useState<string | null>(null)\n\n React.useEffect(() => {\n setOptions((prev) => {\n const next = new Map(prev)\n for (const tag of tags) {\n next.set(tag.label.toLowerCase(), tag)\n }\n return next\n })\n }, [tags])\n\n const syncFetchedOptions = React.useCallback((fetched: TagOption[]) => {\n if (!fetched.length) return\n setOptions((prev) => {\n const next = new Map(prev)\n for (const tag of fetched) {\n next.set(tag.label.toLowerCase(), tag)\n }\n return next\n })\n }, [])\n\n const loadSuggestions = React.useCallback(\n async (query?: string) => {\n try {\n const fetched = await loadOptions(query)\n syncFetchedOptions(fetched)\n return fetched.map((tag) => tag.label)\n } catch (err) {\n console.error('tags.section.loadSuggestions', err)\n return []\n }\n },\n [loadOptions, syncFetchedOptions],\n )\n\n const startEditing = React.useCallback(async () => {\n if (editing || isSubmitting || !canEdit) return\n setError(null)\n setDraft(tags.map((tag) => tag.label))\n setEditing(true)\n setLoadingOptions(true)\n try {\n const fetched = await loadOptions()\n syncFetchedOptions(fetched)\n } catch (err) {\n const message = err instanceof Error ? err.message : labels.loadError\n setError(message)\n flash(message, 'error')\n } finally {\n setLoadingOptions(false)\n }\n }, [canEdit, editing, isSubmitting, labels.loadError, loadOptions, syncFetchedOptions, tags])\n\n const cancelEditing = React.useCallback(() => {\n setEditing(false)\n setDraft([])\n setError(null)\n }, [])\n\n const ensureTagOption = React.useCallback(\n async (label: string): Promise<TagOption> => {\n const normalized = label.trim()\n if (!normalized.length) {\n throw new Error(labels.labelRequired)\n }\n const existing = options.get(normalized.toLowerCase())\n if (existing) return existing\n try {\n const created = await createTag(normalized)\n setOptions((prev) => {\n const next = new Map(prev)\n next.set(created.label.toLowerCase(), created)\n return next\n })\n return created\n } catch (err) {\n const message = err instanceof Error ? err.message : labels.createError\n throw new Error(message)\n }\n },\n [createTag, labels.createError, labels.labelRequired, options],\n )\n\n const handleSave = React.useCallback(async () => {\n if (saving) return\n const trimmed = draft.map((label) => label.trim()).filter((label) => label.length > 0)\n const uniqueLabels = Array.from(new Set(trimmed.map((label) => label.toLowerCase())))\n\n const currentIds = new Set(tags.map((tag) => tag.id))\n const finalTagOptions: TagOption[] = []\n\n setSaving(true)\n setError(null)\n try {\n for (const normalized of uniqueLabels) {\n const existing = options.get(normalized)\n if (existing) {\n finalTagOptions.push(existing)\n continue\n }\n const matchingLabel = trimmed.find((label) => label.toLowerCase() === normalized) ?? normalized\n const created = await ensureTagOption(matchingLabel)\n finalTagOptions.push(created)\n }\n\n const finalIds = new Set(finalTagOptions.map((tag) => tag.id))\n const added = finalTagOptions.filter((tag) => !currentIds.has(tag.id))\n const removed = tags.filter((tag) => !finalIds.has(tag.id))\n\n await onSave({ next: finalTagOptions, added, removed })\n\n onChange?.(finalTagOptions)\n setEditing(false)\n setDraft([])\n if (labels.success) flash(labels.success, 'success')\n } catch (err) {\n const message = err instanceof Error ? err.message : labels.updateError\n setError(message)\n flash(message, 'error')\n } finally {\n setSaving(false)\n }\n }, [draft, ensureTagOption, labels.success, labels.updateError, onChange, onSave, options, saving, tags])\n\n const activeTags = editing ? draft : tags.map((tag) => tag.label)\n\n const handleEditingKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n if (!editing) return\n if (event.key === 'Escape') {\n event.preventDefault()\n cancelEditing()\n return\n }\n if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') {\n event.preventDefault()\n if (saving || isSubmitting) return\n void handleSave()\n }\n },\n [cancelEditing, editing, handleSave, isSubmitting, saving],\n )\n\n const disableInteraction = isSubmitting || !canEdit\n\n return (\n <div className=\"space-y-3\">\n <div className=\"flex items-center justify-between group\">\n <h2 className=\"text-sm font-semibold\">\n {title}\n </h2>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n onClick={editing ? cancelEditing : startEditing}\n disabled={disableInteraction || saving}\n className={\n editing\n ? 'opacity-100 transition-opacity duration-150'\n : 'opacity-100 md:opacity-0 transition-opacity duration-150 md:group-hover:opacity-100 focus-visible:opacity-100'\n }\n >\n {editing ? <X className=\"h-4 w-4\" /> : <Pencil className=\"h-4 w-4\" />}\n <span className=\"sr-only\">\n {editing ? labels.cancel ?? 'Cancel' : labels.edit ?? 'Edit'}\n </span>\n </Button>\n </div>\n\n {editing ? (\n <div className=\"rounded-lg border bg-card p-4 space-y-3\">\n <DataLoader\n isLoading={loadingOptions}\n loadingMessage={labels.loading}\n spinnerSize=\"sm\"\n >\n <div className=\"space-y-3\" onKeyDown={handleEditingKeyDown}>\n <TagsInput\n value={activeTags}\n onChange={(values) => setDraft(values)}\n placeholder={labels.placeholder}\n loadSuggestions={loadSuggestions}\n autoFocus\n />\n {error ? <p className=\"text-xs text-red-600\">{error}</p> : null}\n <div className=\"flex items-center gap-2 mt-3 mb-2\">\n <Button type=\"button\" size=\"sm\" onClick={handleSave} disabled={saving || isSubmitting}>\n {saving ? (\n <span className=\"mr-2 h-4 w-4 animate-spin rounded-full border border-background border-t-primary\" />\n ) : null}\n {labels.saveShortcut}\n </Button>\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"ghost\"\n onClick={cancelEditing}\n disabled={saving || isSubmitting}\n >\n {labels.cancelShortcut}\n </Button>\n </div>\n </div>\n </DataLoader>\n </div>\n ) : (\n <div\n className=\"group/tags relative rounded-lg border bg-muted/20 p-4 transition-colors hover:border-primary/40 focus-visible:border-primary focus-visible:outline-none\"\n role={disableInteraction ? undefined : 'button'}\n tabIndex={disableInteraction ? -1 : 0}\n onClick={disableInteraction ? undefined : startEditing}\n onKeyDown={(event) => {\n if (disableInteraction) return\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault()\n void startEditing()\n }\n }}\n >\n <span\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute right-3 top-3 text-muted-foreground opacity-0 transition-opacity duration-150 group-hover/tags:opacity-100 group-focus-within/tags:opacity-100\"\n >\n <Pencil className=\"h-4 w-4\" />\n </span>\n {tags.length === 0 ? (\n <p className=\"text-sm text-muted-foreground\">\n {labels.empty}\n </p>\n ) : (\n <div className=\"flex flex-wrap gap-2\">\n {tags.map((tag) => (\n <span\n key={tag.id}\n className=\"inline-flex items-center rounded-full border px-3 py-1 text-xs font-medium\"\n style={tag.color ? { borderColor: tag.color, color: tag.color } : undefined}\n >\n {tag.label}\n </span>\n ))}\n </div>\n )}\n </div>\n )}\n </div>\n )\n}\n\nexport function TagsSection(props: TagsSectionProps) {\n const handle = ComponentReplacementHandles.section('ui.detail', 'TagsSection')\n const Resolved = useRegisteredComponent<TagsSectionProps>(\n handle,\n TagsSectionImpl as React.ComponentType<TagsSectionProps>,\n )\n\n return (\n <div data-component-handle={handle}>\n <Resolved {...props} />\n </div>\n )\n}\n\nexport default TagsSection\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,54 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { registerComponentOverrides } from "@open-mercato/shared/modules/widgets/component-registry";
5
+ import { apiCall } from "../utils/apiCall.js";
6
+ const OverrideUserFeaturesContext = React.createContext([]);
7
+ function useOverrideUserFeatures() {
8
+ return React.useContext(OverrideUserFeaturesContext);
9
+ }
10
+ function ComponentOverrideProvider({
11
+ overrides,
12
+ children
13
+ }) {
14
+ const [userFeatures, setUserFeatures] = React.useState([]);
15
+ React.useEffect(() => {
16
+ registerComponentOverrides(overrides);
17
+ return () => {
18
+ registerComponentOverrides([]);
19
+ };
20
+ }, [overrides]);
21
+ React.useEffect(() => {
22
+ const requiredFeatures = /* @__PURE__ */ new Set();
23
+ for (const override of overrides) {
24
+ for (const feature of override.features ?? []) {
25
+ if (feature && feature.trim().length > 0) requiredFeatures.add(feature);
26
+ }
27
+ }
28
+ if (requiredFeatures.size === 0) return;
29
+ let cancelled = false;
30
+ const fetchFeatures = async () => {
31
+ const call = await apiCall("/api/auth/feature-check", {
32
+ method: "POST",
33
+ headers: { "content-type": "application/json" },
34
+ body: JSON.stringify({ features: Array.from(requiredFeatures) })
35
+ });
36
+ if (cancelled) return;
37
+ if (call.ok && call.result?.granted) {
38
+ setUserFeatures(call.result.granted);
39
+ }
40
+ };
41
+ void fetchFeatures();
42
+ return () => {
43
+ cancelled = true;
44
+ };
45
+ }, [overrides]);
46
+ return /* @__PURE__ */ jsx(OverrideUserFeaturesContext.Provider, { value: userFeatures, children });
47
+ }
48
+ var ComponentOverrideProvider_default = ComponentOverrideProvider;
49
+ export {
50
+ ComponentOverrideProvider,
51
+ ComponentOverrideProvider_default as default,
52
+ useOverrideUserFeatures
53
+ };
54
+ //# sourceMappingURL=ComponentOverrideProvider.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/backend/injection/ComponentOverrideProvider.tsx"],
4
+ "sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport type { ComponentOverride } from '@open-mercato/shared/modules/widgets/component-registry'\nimport { registerComponentOverrides } from '@open-mercato/shared/modules/widgets/component-registry'\nimport { apiCall } from '../utils/apiCall'\n\ntype FeatureCheckResponse = { granted: string[] }\n\nconst OverrideUserFeaturesContext = React.createContext<readonly string[]>([])\n\nexport function useOverrideUserFeatures(): readonly string[] {\n return React.useContext(OverrideUserFeaturesContext)\n}\n\nexport function ComponentOverrideProvider({\n overrides,\n children,\n}: {\n overrides: ComponentOverride[]\n children: React.ReactNode\n}) {\n const [userFeatures, setUserFeatures] = React.useState<readonly string[]>([])\n\n React.useEffect(() => {\n registerComponentOverrides(overrides)\n return () => {\n registerComponentOverrides([])\n }\n }, [overrides])\n\n React.useEffect(() => {\n const requiredFeatures = new Set<string>()\n for (const override of overrides) {\n for (const feature of override.features ?? []) {\n if (feature && feature.trim().length > 0) requiredFeatures.add(feature)\n }\n }\n if (requiredFeatures.size === 0) return\n let cancelled = false\n const fetchFeatures = async () => {\n const call = await apiCall<FeatureCheckResponse>('/api/auth/feature-check', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ features: Array.from(requiredFeatures) }),\n })\n if (cancelled) return\n if (call.ok && call.result?.granted) {\n setUserFeatures(call.result.granted)\n }\n }\n void fetchFeatures()\n return () => {\n cancelled = true\n }\n }, [overrides])\n\n return (\n <OverrideUserFeaturesContext.Provider value={userFeatures}>\n {children}\n </OverrideUserFeaturesContext.Provider>\n )\n}\n\nexport default ComponentOverrideProvider\n"],
5
+ "mappings": ";AA0DI;AAxDJ,YAAY,WAAW;AAEvB,SAAS,kCAAkC;AAC3C,SAAS,eAAe;AAIxB,MAAM,8BAA8B,MAAM,cAAiC,CAAC,CAAC;AAEtE,SAAS,0BAA6C;AAC3D,SAAO,MAAM,WAAW,2BAA2B;AACrD;AAEO,SAAS,0BAA0B;AAAA,EACxC;AAAA,EACA;AACF,GAGG;AACD,QAAM,CAAC,cAAc,eAAe,IAAI,MAAM,SAA4B,CAAC,CAAC;AAE5E,QAAM,UAAU,MAAM;AACpB,+BAA2B,SAAS;AACpC,WAAO,MAAM;AACX,iCAA2B,CAAC,CAAC;AAAA,IAC/B;AAAA,EACF,GAAG,CAAC,SAAS,CAAC;AAEd,QAAM,UAAU,MAAM;AACpB,UAAM,mBAAmB,oBAAI,IAAY;AACzC,eAAW,YAAY,WAAW;AAChC,iBAAW,WAAW,SAAS,YAAY,CAAC,GAAG;AAC7C,YAAI,WAAW,QAAQ,KAAK,EAAE,SAAS,EAAG,kBAAiB,IAAI,OAAO;AAAA,MACxE;AAAA,IACF;AACA,QAAI,iBAAiB,SAAS,EAAG;AACjC,QAAI,YAAY;AAChB,UAAM,gBAAgB,YAAY;AAChC,YAAM,OAAO,MAAM,QAA8B,2BAA2B;AAAA,QAC1E,QAAQ;AAAA,QACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,QAC9C,MAAM,KAAK,UAAU,EAAE,UAAU,MAAM,KAAK,gBAAgB,EAAE,CAAC;AAAA,MACjE,CAAC;AACD,UAAI,UAAW;AACf,UAAI,KAAK,MAAM,KAAK,QAAQ,SAAS;AACnC,wBAAgB,KAAK,OAAO,OAAO;AAAA,MACrC;AAAA,IACF;AACA,SAAK,cAAc;AACnB,WAAO,MAAM;AACX,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,SAAS,CAAC;AAEd,SACE,oBAAC,4BAA4B,UAA5B,EAAqC,OAAO,cAC1C,UACH;AAEJ;AAEA,IAAO,oCAAQ;",
6
+ "names": []
7
+ }