{"version":3,"file":"CatchUpWidget-CbjUugyJ.cjs","names":["useWidgetsApi","useWidgetPreviewContext","useDataSourceRegistryConfig","ShoppingCart","Package","Star","CalendarClock","PlayCircle","MessageCircle","Sparkles","useWidgetPreviewContext","useWidgetInteraction","borderWidthClasses","borderColorClasses","WidgetLoadingSkeleton","ErrorState","Check","ArrowRight","Loader2","X","ChevronDown","getFontSizeField","getColorField","getPaddingField","getBorderRadiusField","getBorderWidthField","getBorderColorField"],"sources":["../../widgets/src/hooks/use-catchups.preview.ts","../../widgets/src/hooks/use-catchups.ts","../../widgets/src/widgets/CatchUpWidget.tsx"],"sourcesContent":["import type { CatchUp } from \"@fluid-app/portal-core/widgets-api-types\";\n\nexport const PREVIEW_DATA: CatchUp[] = [\n  {\n    id: 1,\n    suggestionTitle: \"Check in with Sarah about her recent order\",\n    description:\n      \"Her last order shipped 5 days ago — a quick thank-you goes a long way.\",\n    category: \"left_a_review\",\n    status: \"pending\",\n    actionCount: 1,\n    actions: [\n      {\n        id: 11,\n        actionType: \"SendDirectMessageCatchUpAction\",\n        status: \"pending\",\n        contact: { id: 501, name: \"Sarah Chen\" },\n        destination: { kind: \"contact\", id: 501 },\n      },\n    ],\n  },\n  {\n    id: 2,\n    suggestionTitle: \"Follow up with Mike on product samples\",\n    description: \"Mike asked about samples last week and hasn't heard back.\",\n    category: \"unread_messages\",\n    status: \"pending\",\n    actionCount: 1,\n    actions: [\n      {\n        id: 21,\n        actionType: \"UnreadMessagesCatchUpAction\",\n        status: \"pending\",\n        contact: { id: 502, name: \"Mike Ross\" },\n        destination: { kind: \"conversation\", id: 9001 },\n      },\n    ],\n  },\n  {\n    id: 3,\n    suggestionTitle: \"New arrivals just dropped\",\n    description: \"Fresh products your customers will love — take a look.\",\n    category: \"new_product\",\n    status: \"pending\",\n    actionCount: 1,\n    actions: [\n      {\n        id: 31,\n        actionType: \"NewProductCatchUpAction\",\n        status: \"pending\",\n        contact: null,\n        destination: { kind: \"product\", id: 7001 },\n      },\n    ],\n  },\n  {\n    id: 4,\n    suggestionTitle: \"Thank Alex for their referral last week\",\n    description: null,\n    category: null,\n    status: \"resolved\",\n    actionCount: 0,\n    actions: [],\n  },\n  {\n    id: 5,\n    suggestionTitle: \"New training video posted\",\n    description: \"A new video was just added to your library.\",\n    category: \"new_media_added\",\n    status: \"pending\",\n    actionCount: 1,\n    actions: [\n      {\n        id: 51,\n        actionType: \"ViewMediaCatchUpAction\",\n        status: \"pending\",\n        contact: null,\n        destination: { kind: \"media\", id: 3001 },\n      },\n    ],\n  },\n];\n","import {\n  useMutation,\n  useQuery,\n  useQueryClient,\n  type UseMutationResult,\n  type UseQueryResult,\n} from \"@tanstack/react-query\";\nimport { fluidToast } from \"@fluid-app/ui-primitives\";\nimport { useWidgetsApi } from \"@fluid-app/portal-core/widgets-api-context\";\nimport { useWidgetPreviewContext } from \"@fluid-app/portal-react/data-sources/preview-context\";\nimport { useDataSourceRegistryConfig } from \"@fluid-app/portal-react/data-sources/registry-context\";\nimport { PREVIEW_DATA } from \"./use-catchups.preview\";\nimport type { CatchUp } from \"@fluid-app/portal-core/widgets-api-types\";\n\nexport type { CatchUp } from \"@fluid-app/portal-core/widgets-api-types\";\n\n// The live (non-preview) query key. Kept as a helper so the query and the\n// mutation that mutates its cache can never drift apart.\nfunction catchUpsQueryKey(baseUrl: string | undefined) {\n  return [\"portal-widget-use\", \"catchups\", baseUrl] as const;\n}\n\nexport function useCatchUps(): UseQueryResult<CatchUp[], Error> {\n  const widgetsApi = useWidgetsApi();\n  const { isPreview } = useWidgetPreviewContext();\n  const { baseUrl } = useDataSourceRegistryConfig();\n\n  return useQuery({\n    queryKey: [\n      \"portal-widget-use\",\n      \"catchups\",\n      isPreview ? \"preview\" : baseUrl,\n    ] as const,\n    queryFn: ({ signal }) => widgetsApi.fetchCatchUps(signal),\n    enabled: !isPreview,\n    ...(isPreview && { placeholderData: PREVIEW_DATA }),\n  });\n}\n\nexport type DismissCatchUpActionVars = {\n  catchUpId: number;\n  actionId: number;\n};\n\n/**\n * Dismisses one of a catch-up's pending actions through the BFF (a safe resolve\n * with no external side effects), then removes it from the cached list.\n *\n * The cache is edited only on confirmed success — never optimistically and\n * without a refetch. So there is nothing to roll back if it fails (a failed\n * dismiss just leaves the row), nothing a concurrent dismiss can clobber (each\n * success applies an independent, idempotent removal to the current cache), and\n * no invalidation whose failure could turn a successful dismiss into an error.\n * The button shows a pending spinner until the request resolves.\n *\n * A failed dismiss (e.g. the BFF endpoint isn't deployed yet) leaves the row in\n * place and surfaces a toast, rather than silently stopping the spinner with no\n * feedback.\n */\nexport function useDismissCatchUpAction(): UseMutationResult<\n  void,\n  Error,\n  DismissCatchUpActionVars\n> {\n  const widgetsApi = useWidgetsApi();\n  const { baseUrl } = useDataSourceRegistryConfig();\n  const queryClient = useQueryClient();\n  const queryKey = catchUpsQueryKey(baseUrl);\n\n  return useMutation({\n    mutationFn: ({ catchUpId, actionId }: DismissCatchUpActionVars) =>\n      widgetsApi.dismissCatchUpAction(catchUpId, actionId),\n    onSuccess: (_data, { catchUpId, actionId }) => {\n      queryClient.setQueryData<CatchUp[]>(queryKey, (old) =>\n        (old ?? [])\n          .map((catchUp) =>\n            catchUp.id === catchUpId\n              ? {\n                  ...catchUp,\n                  actions: catchUp.actions.map((action) =>\n                    action.id === actionId\n                      ? { ...action, status: \"resolved\" as const }\n                      : action,\n                  ),\n                }\n              : catchUp,\n          )\n          // Only the just-dismissed catch-up may need removing — drop it once\n          // none of its actions remain pending. Every other row is left exactly\n          // as it was, so an unrelated catch-up with no pending actions (the\n          // widget can render resolved rows) doesn't vanish on this dismiss.\n          .filter(\n            (catchUp) =>\n              catchUp.id !== catchUpId ||\n              catchUp.actions.some((action) => action.status === \"pending\"),\n          ),\n      );\n    },\n    onError: (error, { catchUpId, actionId }) => {\n      console.error(\"[portal-widgets] Failed to dismiss catch-up action\", {\n        error,\n        catchUpId,\n        actionId,\n      });\n      fluidToast({ title: \"Couldn't dismiss catch-up\", type: \"error\" });\n    },\n  });\n}\n","import type { ComponentProps } from \"react\";\nimport type React from \"react\";\nimport { useState } from \"react\";\nimport type {\n  BackgroundValue,\n  BorderRadiusOptions,\n  BorderWidthOptions,\n  ColorOptions,\n  FontSizeOptions,\n  PaddingOptions,\n} from \"@fluid-app/portal-core/types\";\nimport type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport type { CatchUpActionDestination } from \"@fluid-app/portal-core/widgets-api-types\";\nimport {\n  getBorderRadiusField,\n  getBorderWidthField,\n  getBorderColorField,\n  getColorField,\n  getFontSizeField,\n  getPaddingField,\n  borderWidthClasses,\n  borderColorClasses,\n} from \"../core/fields\";\nimport { useCatchUps, useDismissCatchUpAction } from \"../hooks/use-catchups\";\nimport { useWidgetPreviewContext } from \"@fluid-app/portal-react/data-sources/preview-context\";\nimport { useWidgetInteraction } from \"../contexts/WidgetInteractionContext\";\nimport {\n  ArrowRight,\n  CalendarClock,\n  Check,\n  ChevronDown,\n  Loader2,\n  MessageCircle,\n  Package,\n  PlayCircle,\n  ShoppingCart,\n  Sparkles,\n  Star,\n  X,\n  type LucideIcon,\n} from \"lucide-react\";\nimport { ErrorState } from \"../components/error-state\";\nimport { WidgetLoadingSkeleton } from \"../components/WidgetLoadingSkeleton\";\n\n// Font size mapping for title\nconst fontSizeClasses: Record<FontSizeOptions, string> = {\n  \"2xl\": \"text-2xl\",\n  xl: \"text-xl\",\n  lg: \"text-lg\",\n  md: \"text-base\",\n  sm: \"text-sm\",\n  xs: \"text-xs\",\n};\n\n// Maps a catch-up's trigger category (catch_up_class on the BFF) to an icon.\n// Unknown or null categories fall back to the generic Sparkles icon.\nconst categoryIcons: Record<string, LucideIcon> = {\n  cart_abandoned: ShoppingCart,\n  new_product: Package,\n  left_a_review: Star,\n  add_review: Star,\n  upcoming_subscription_orders: CalendarClock,\n  upcoming_event: CalendarClock,\n  video_viewed: PlayCircle,\n  new_media_added: PlayCircle,\n  unread_messages: MessageCircle,\n  unresolved_media_comment: MessageCircle,\n};\n\nfunction getCategoryIcon(category: string | null): LucideIcon {\n  return (category && categoryIcons[category]) || Sparkles;\n}\n\n// Verb shown on a catch-up's primary action button, keyed on the BFF's STI\n// action class. Unknown types fall back to a generic label so a new backend\n// action type still renders a working button.\nconst actionLabels: Record<string, string> = {\n  ResolveConversationCatchUpAction: \"Resolve\",\n  UnreadMessagesCatchUpAction: \"Reply\",\n  SendDirectMessageCatchUpAction: \"Message\",\n  SendSmsCatchUpAction: \"Text\",\n  AddReviewCatchUpAction: \"Leave review\",\n  AddCommentReactionCatchUpAction: \"React\",\n  RsvpCatchUpAction: \"RSVP\",\n  ShareSmartLinkCatchUpAction: \"Share\",\n  LinkRedirectionCatchUpAction: \"Open\",\n  ViewMediaCatchUpAction: \"View\",\n  NewProductCatchUpAction: \"View product\",\n  MarkAsDoneCatchUpAction: \"Mark done\",\n  ToDoCatchUpAction: \"View task\",\n  ConfirmSliderValueCatchUpAction: \"Confirm\",\n  UpdateContactGroupCatchUpAction: \"Update\",\n};\n\nfunction getActionLabel(actionType: string): string {\n  return actionLabels[actionType] ?? \"Do it\";\n}\n\ntype ScreenSlugs = {\n  contact: string;\n  messaging: string;\n  shop: string;\n  shareables: string;\n};\n\n// Map a normalized BFF destination to a portal navigation slug. Returns null\n// for kinds the portal can't deep-link (the widget then offers a dismiss).\nfunction buildDestinationSlug(\n  destination: CatchUpActionDestination,\n  slugs: ScreenSlugs,\n): string | null {\n  switch (destination.kind) {\n    case \"contact\":\n      return `${slugs.contact}/${destination.id}`;\n    case \"conversation\":\n      return `${slugs.messaging}/conversation/${destination.id}`;\n    case \"product\":\n      return `${slugs.shop}/${destination.id}`;\n    case \"media\":\n      // Shareables deep-links a specific medium at \"<share>/media/<id>\".\n      return `${slugs.shareables}/media/${destination.id}`;\n    default:\n      return null;\n  }\n}\n\n// Only these semantic colors ship a paired `-foreground` token. For any other\n// ColorOptions (background, foreground, border, transparent) `text-*-foreground`\n// is a class that does not exist, so the filled button's label would fall back\n// to inherited colour. Resolve a legible contrast token instead.\nconst PAIRED_FOREGROUND_COLORS: ReadonlySet<ColorOptions> = new Set([\n  \"primary\",\n  \"secondary\",\n  \"accent\",\n  \"muted\",\n  \"destructive\",\n]);\n\nfunction accentForegroundClass(accent: ColorOptions): string {\n  if (PAIRED_FOREGROUND_COLORS.has(accent)) return `text-${accent}-foreground`;\n  return accent === \"foreground\" ? \"text-background\" : \"text-foreground\";\n}\n\ntype CatchUpWidgetProps = ComponentProps<\"div\"> & {\n  // Title settings\n  titleEnabled?: boolean;\n  titleText?: string;\n  titleFontSize?: FontSizeOptions;\n  titleColor?: ColorOptions;\n  // Design settings\n  background?: BackgroundValue;\n  textColor?: ColorOptions;\n  accentColor?: ColorOptions;\n  padding?: PaddingOptions;\n  borderRadius?: BorderRadiusOptions;\n  borderWidth?: BorderWidthOptions;\n  borderColor?: ColorOptions;\n  // Display settings\n  maxItems?: number;\n  // Slugs of the screens a catch-up routes to, by destination kind.\n  contactScreenSlug?: string;\n  messagingScreenSlug?: string;\n  shopScreenSlug?: string;\n  shareablesScreenSlug?: string;\n};\n\nexport function CatchUpWidget({\n  // Title settings with defaults\n  titleEnabled = true,\n  titleText = \"Catch Ups\",\n  titleFontSize = \"xl\",\n  titleColor = \"foreground\",\n  // Design settings with defaults\n  background = {\n    type: \"solid\",\n    color: \"background\",\n  },\n  textColor = \"foreground\",\n  accentColor = \"primary\",\n  padding = 4,\n  borderRadius = \"md\",\n  borderWidth = \"none\",\n  borderColor = \"muted\",\n  // Display settings with defaults\n  maxItems = 5,\n  contactScreenSlug = \"contacts\",\n  messagingScreenSlug = \"messages\",\n  shopScreenSlug = \"shop\",\n  shareablesScreenSlug = \"share\",\n  className,\n  ...props\n}: CatchUpWidgetProps): React.JSX.Element {\n  const backgroundColor = background.color || \"background\";\n  const backgroundImage =\n    (background.resource?.image_url || background.resource?.imageUrl) &&\n    background.type === \"image\"\n      ? `url(${background.resource.image_url || background.resource.imageUrl})`\n      : \"none\";\n  const { data = [], isLoading, isError } = useCatchUps();\n  const dismissAction = useDismissCatchUpAction();\n  const { isPreview } = useWidgetPreviewContext();\n  const { onNavigate, canNavigateTo } = useWidgetInteraction();\n  const [expanded, setExpanded] = useState(false);\n  // The dismiss mutation is shared by every row, so its `variables`/`isPending`\n  // only reflect the most recent click. Track in-flight actions ourselves so a\n  // second dismiss can't clear an earlier row's spinner or re-enable it mid-flight.\n  const [dismissingActionIds, setDismissingActionIds] = useState<\n    ReadonlySet<number>\n  >(() => new Set());\n\n  const screenSlugs: ScreenSlugs = {\n    contact: contactScreenSlug,\n    messaging: messagingScreenSlug,\n    shop: shopScreenSlug,\n    shareables: shareablesScreenSlug,\n  };\n\n  // Collapsed shows the first `maxItems`; expanded shows everything. The toggle\n  // count is independent of `expanded` so the control stays visible to collapse.\n  const catchUpsToShow = expanded ? data : data.slice(0, maxItems);\n  const hiddenCount = Math.max(0, data.length - maxItems);\n\n  return (\n    <div\n      className={`flex flex-col rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} bg-${backgroundColor} p-${padding} text-${textColor} ${className || \"\"}`}\n      style={{ backgroundImage }}\n      {...props}\n    >\n      {/* Header */}\n      <div className=\"flex items-center justify-between gap-3\">\n        {titleEnabled && (\n          <h3\n            className={`${fontSizeClasses[titleFontSize]} font-header font-bold tracking-[-0.01em] text-${titleColor}`}\n          >\n            {titleText}\n          </h3>\n        )}\n        {!isLoading && !isError && data.length > 0 && (\n          <span\n            className={`inline-flex min-w-[1.5rem] items-center justify-center rounded-full bg-${accentColor}/10 px-2 py-0.5 text-xs font-bold tabular-nums text-${accentColor}`}\n          >\n            {data.length}\n          </span>\n        )}\n      </div>\n\n      {/* Loading state */}\n      {isLoading ? (\n        <div className=\"mt-3 flex-1\">\n          <WidgetLoadingSkeleton minHeight={150} rows={3} />\n        </div>\n      ) : isError ? (\n        /* Error state */\n        <div className=\"mt-3 flex-1\">\n          <ErrorState />\n        </div>\n      ) : data.length === 0 ? (\n        /* Empty state */\n        <div className=\"flex min-h-[150px] flex-1 flex-col items-center justify-center gap-3 py-6\">\n          <div\n            className={`flex size-12 items-center justify-center rounded-full bg-${accentColor}/10`}\n          >\n            <Sparkles className={`size-5 text-${accentColor}`} aria-hidden />\n          </div>\n          <div className=\"text-center\">\n            <p className={`text-sm font-semibold text-${textColor}`}>\n              You&apos;re all caught up\n            </p>\n            <p className={`mt-0.5 text-xs text-${textColor}/55`}>\n              Nothing needs your attention right now.\n            </p>\n          </div>\n        </div>\n      ) : (\n        /* Default state with catch ups */\n        <div className=\"mt-3 flex flex-1 flex-col gap-2\">\n          {catchUpsToShow.map((catchUp, index: number) => {\n            const Icon = getCategoryIcon(catchUp.category);\n            const isResolved = catchUp.status === \"resolved\";\n            // The row's primary action is the first still-actionable one.\n            const primaryAction = catchUp.actions.find(\n              (action) => action.status === \"pending\",\n            );\n            const resolvedSlug = primaryAction?.destination\n              ? buildDestinationSlug(primaryAction.destination, screenSlugs)\n              : null;\n            // Suppress the deep-link when it would dead-end on \"Page Not Found\"\n            // (an opt-in screen like a contact/conversation the portal hasn't\n            // added to its nav). The row then falls back to the dismiss control.\n            const destinationSlug =\n              resolvedSlug && (!canNavigateTo || canNavigateTo(resolvedSlug))\n                ? resolvedSlug\n                : null;\n            const isDismissing = primaryAction\n              ? dismissingActionIds.has(primaryAction.id)\n              : false;\n            return (\n              <div\n                key={catchUp.id || index}\n                className={`flex items-start gap-3 rounded-lg border border-${textColor}/10 p-3 transition-colors ${isResolved ? \"opacity-55\" : `hover:border-${accentColor}/30`}`}\n              >\n                <div\n                  className={`flex size-9 shrink-0 items-center justify-center rounded-full ${isResolved ? `bg-${textColor}/10 text-${textColor}/50` : `bg-${accentColor}/10 text-${accentColor}`}`}\n                >\n                  {isResolved ? (\n                    <Check className=\"size-4\" aria-hidden />\n                  ) : (\n                    <Icon className=\"size-4\" aria-hidden />\n                  )}\n                </div>\n                <div className=\"min-w-0 flex-1\">\n                  <p\n                    className={`text-sm leading-snug font-semibold tracking-[-0.01em] text-${textColor} ${isResolved ? \"line-through\" : \"\"}`}\n                  >\n                    {catchUp.suggestionTitle}\n                  </p>\n                  {catchUp.description && (\n                    <p\n                      className={`mt-0.5 line-clamp-2 text-xs leading-snug text-${textColor}/60`}\n                    >\n                      {catchUp.description}\n                    </p>\n                  )}\n                  {/* Primary action: route the member to where they act on it.\n                      Resolution follows once the member acts and the BFF\n                      regenerates the list. Rows with no destination rely on the\n                      dismiss control alone. */}\n                  {destinationSlug && !isResolved && (\n                    <button\n                      type=\"button\"\n                      disabled={isPreview}\n                      onClick={() => onNavigate?.(destinationSlug)}\n                      className={`mt-2 inline-flex items-center gap-1.5 rounded-full bg-${accentColor} px-3 py-1 text-xs font-semibold ${accentForegroundClass(accentColor)} transition-opacity hover:opacity-90 disabled:cursor-default disabled:opacity-50`}\n                    >\n                      {getActionLabel(primaryAction!.actionType)}\n                      <ArrowRight className=\"size-3.5\" aria-hidden />\n                    </button>\n                  )}\n                </div>\n                {/* Universal dismiss — clears any catch-up without side effects,\n                    so a nudge the member won't act on can still be cleared. */}\n                {primaryAction && !isResolved && (\n                  <button\n                    type=\"button\"\n                    aria-label=\"Dismiss\"\n                    title=\"Dismiss\"\n                    disabled={isPreview || isDismissing}\n                    onClick={() => {\n                      const actionId = primaryAction.id;\n                      setDismissingActionIds((prev) =>\n                        new Set(prev).add(actionId),\n                      );\n                      dismissAction.mutate(\n                        { catchUpId: catchUp.id, actionId },\n                        {\n                          onSettled: () =>\n                            setDismissingActionIds((prev) => {\n                              const next = new Set(prev);\n                              next.delete(actionId);\n                              return next;\n                            }),\n                        },\n                      );\n                    }}\n                    className={`-m-1 shrink-0 rounded-md p-1 text-${textColor}/40 transition-colors hover:bg-${textColor}/5 hover:text-${textColor}/70 disabled:cursor-default disabled:opacity-50`}\n                  >\n                    {isDismissing ? (\n                      <Loader2 className=\"size-4 animate-spin\" aria-hidden />\n                    ) : (\n                      <X className=\"size-4\" aria-hidden />\n                    )}\n                  </button>\n                )}\n              </div>\n            );\n          })}\n\n          {/* Expand / collapse the overflow */}\n          {hiddenCount > 0 && (\n            <button\n              type=\"button\"\n              onClick={() => setExpanded((value) => !value)}\n              className={`mt-1 inline-flex items-center justify-center gap-1 rounded-md py-1.5 text-xs font-semibold text-${accentColor} transition-colors hover:bg-${accentColor}/10`}\n            >\n              {expanded ? \"Show less\" : `Show ${hiddenCount} more`}\n              <ChevronDown\n                className={`size-3.5 transition-transform ${expanded ? \"rotate-180\" : \"\"}`}\n                aria-hidden\n              />\n            </button>\n          )}\n        </div>\n      )}\n    </div>\n  );\n}\n\n// Property schema for the widget editor\nexport const catchUpWidgetPropertySchema: WidgetPropertySchema = {\n  widgetType: \"CatchUpWidget\",\n  displayName: \"Catch Up Widget\",\n  tabsConfig: [{ id: \"styling\", label: \"Styling\" }],\n  fields: [\n    // Styling Tab - Title Group\n    {\n      key: \"titleEnabled\",\n      label: \"Widget Title\",\n      type: \"boolean\",\n      description: \"Enable the title displayed above the catch ups\",\n      defaultValue: true,\n      tab: \"styling\",\n      group: \"Title\",\n    },\n    {\n      key: \"titleText\",\n      label: \"Title\",\n      type: \"text\",\n      description: \"Title text displayed above the catch ups\",\n      defaultValue: \"Catch Ups\",\n      tab: \"styling\",\n      group: \"Title\",\n      requiresKeyToBeTrue: \"titleEnabled\",\n    },\n    getFontSizeField({\n      key: \"titleFontSize\",\n      label: \"Title Font Size\",\n      description: \"Font size for the widget title\",\n      defaultValue: \"xl\",\n      tab: \"styling\",\n      group: \"Title\",\n      requiresKeyToBeTrue: \"titleEnabled\",\n    }),\n    getColorField({\n      key: \"titleColor\",\n      label: \"Title Color\",\n      description: \"Color for the widget title\",\n      defaultValue: \"foreground\",\n      tab: \"styling\",\n      group: \"Title\",\n      requiresKeyToBeTrue: \"titleEnabled\",\n    }),\n\n    // Styling Tab - Design Group\n    {\n      type: \"background\",\n      key: \"background\",\n      label: \"Background\",\n      description: \"Background for the container\",\n      defaultValue: { type: \"solid\", color: \"background\" },\n      tab: \"styling\",\n      group: \"Design\",\n    },\n    getColorField({\n      key: \"textColor\",\n      label: \"Text Color\",\n      description: \"Default text color for catch up items\",\n      defaultValue: \"foreground\",\n      tab: \"styling\",\n      group: \"Design\",\n    }),\n    getColorField({\n      key: \"accentColor\",\n      label: \"Accent Color\",\n      description: \"Color used for count display and icons\",\n      defaultValue: \"primary\",\n      tab: \"styling\",\n      group: \"Design\",\n    }),\n    {\n      key: \"separator\",\n      type: \"separator\",\n      label: \"Separator\",\n      tab: \"styling\",\n      group: \"Design\",\n    },\n    {\n      key: \"maxItems\",\n      label: \"Max Items\",\n      type: \"number\",\n      description: \"Maximum number of catch ups to display\",\n      defaultValue: 5,\n      min: 1,\n      max: 10,\n      tab: \"styling\",\n      group: \"Design\",\n    },\n    {\n      key: \"contactScreenSlug\",\n      label: \"Contacts Screen\",\n      type: \"screenPicker\",\n      description:\n        \"Screen to open when a catch-up targets a contact (e.g. reply, message).\",\n      defaultValue: \"contacts\",\n      includeSystemItems: true,\n      tab: \"styling\",\n      group: \"Navigation\",\n    },\n    {\n      key: \"messagingScreenSlug\",\n      label: \"Messaging Screen\",\n      type: \"screenPicker\",\n      description: \"Screen to open when a catch-up targets a conversation.\",\n      defaultValue: \"messages\",\n      includeSystemItems: true,\n      tab: \"styling\",\n      group: \"Navigation\",\n    },\n    {\n      key: \"shopScreenSlug\",\n      label: \"Shop Screen\",\n      type: \"screenPicker\",\n      description: \"Screen to open when a catch-up targets a product.\",\n      defaultValue: \"shop\",\n      includeSystemItems: true,\n      tab: \"styling\",\n      group: \"Navigation\",\n    },\n    {\n      key: \"shareablesScreenSlug\",\n      label: \"Media Screen\",\n      type: \"screenPicker\",\n      description: \"Screen to open when a catch-up targets media.\",\n      defaultValue: \"share\",\n      includeSystemItems: true,\n      tab: \"styling\",\n      group: \"Navigation\",\n    },\n    getPaddingField({\n      key: \"padding\",\n      label: \"Padding\",\n      description: \"Padding around the container\",\n      defaultValue: 4,\n      tab: \"styling\",\n      group: \"Design\",\n    }),\n    getBorderRadiusField({\n      key: \"borderRadius\",\n      label: \"Border Radius\",\n      description: \"Border radius for the container\",\n      defaultValue: \"md\",\n      tab: \"styling\",\n      group: \"Design\",\n    }),\n    getBorderWidthField({\n      key: \"borderWidth\",\n      label: \"Border Width\",\n      description: \"Border width for the widget\",\n      defaultValue: \"none\",\n      tab: \"styling\",\n      group: \"Design\",\n    }),\n    getBorderColorField({\n      key: \"borderColor\",\n      label: \"Border Color\",\n      description: \"Border color for the widget\",\n      defaultValue: \"muted\",\n      tab: \"styling\",\n      group: \"Design\",\n    }),\n  ],\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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,KAAK;GACL,OAAO;GACP,qBAAqB;GACtB,CAAC;EAGF;GACE,MAAM;GACN,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;IAAE,MAAM;IAAS,OAAO;IAAc;GACpD,KAAK;GACL,OAAO;GACR;EACDA,mBAAAA,cAAc;GACZ,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACFA,mBAAAA,cAAc;GACZ,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACF;GACE,KAAK;GACL,MAAM;GACN,OAAO;GACP,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,KAAK;GACL,KAAK;GACL,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aACE;GACF,cAAc;GACd,oBAAoB;GACpB,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,oBAAoB;GACpB,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,oBAAoB;GACpB,KAAK;GACL,OAAO;GACR;EACD;GACE,KAAK;GACL,OAAO;GACP,MAAM;GACN,aAAa;GACb,cAAc;GACd,oBAAoB;GACpB,KAAK;GACL,OAAO;GACR;EACDC,mBAAAA,gBAAgB;GACd,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACFC,mBAAAA,qBAAqB;GACnB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACFC,mBAAAA,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACFC,mBAAAA,oBAAoB;GAClB,KAAK;GACL,OAAO;GACP,aAAa;GACb,cAAc;GACd,KAAK;GACL,OAAO;GACR,CAAC;EACH;CACF"}