@fluid-app/portal-sdk 0.1.322 → 0.1.324

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 (59) hide show
  1. package/dist/{AddressAutocompleteInput-BpbBARKk.mjs → AddressAutocompleteInput-CYWqjVql.mjs} +2 -2
  2. package/dist/{AddressAutocompleteInput-BpbBARKk.mjs.map → AddressAutocompleteInput-CYWqjVql.mjs.map} +1 -1
  3. package/dist/{AddressAutocompleteInput-DkFs_leA.cjs → AddressAutocompleteInput-DfwaaK0l.cjs} +2 -2
  4. package/dist/{AddressAutocompleteInput-DkFs_leA.cjs.map → AddressAutocompleteInput-DfwaaK0l.cjs.map} +1 -1
  5. package/dist/{ContactsScreen-DiGrOlwx.cjs → ContactsScreen-BYrRJ55W.cjs} +2 -2
  6. package/dist/{ContactsScreen-FELUSAZ_.mjs → ContactsScreen-D3_LQj6x.mjs} +2 -2
  7. package/dist/{ContactsScreen-FELUSAZ_.mjs.map → ContactsScreen-D3_LQj6x.mjs.map} +1 -1
  8. package/dist/{ContactsScreen-Cf0ShCew.cjs → ContactsScreen-Dm8b4SyY.cjs} +2 -2
  9. package/dist/{ContactsScreen-Cf0ShCew.cjs.map → ContactsScreen-Dm8b4SyY.cjs.map} +1 -1
  10. package/dist/{FluidProvider-BIeO1i4r.cjs → FluidProvider-BQjPCP_2.cjs} +4 -4
  11. package/dist/{FluidProvider-BIeO1i4r.cjs.map → FluidProvider-BQjPCP_2.cjs.map} +1 -1
  12. package/dist/{FluidProvider-LqejfvZ-.mjs → FluidProvider-DU-sFsZV.mjs} +4 -4
  13. package/dist/{FluidProvider-LqejfvZ-.mjs.map → FluidProvider-DU-sFsZV.mjs.map} +1 -1
  14. package/dist/{MessagingScreen-CQNNI4RN.cjs → MessagingScreen-CqxyLDp0.cjs} +4 -4
  15. package/dist/{MessagingScreen-BRcAo9ux.mjs → MessagingScreen-D33O66bU.mjs} +2 -2
  16. package/dist/{MessagingScreen-BRcAo9ux.mjs.map → MessagingScreen-D33O66bU.mjs.map} +1 -1
  17. package/dist/{MessagingScreen-BBkqLkcx.cjs → MessagingScreen-XtYpo1RQ.cjs} +2 -2
  18. package/dist/{MessagingScreen-BBkqLkcx.cjs.map → MessagingScreen-XtYpo1RQ.cjs.map} +1 -1
  19. package/dist/{MessagingScreen-y3AG96Gi.mjs → MessagingScreen-a58Uccvz.mjs} +4 -4
  20. package/dist/{OrdersScreen-BgcQi5Re.cjs → OrdersScreen-BAvQ38bA.cjs} +4 -4
  21. package/dist/{OrdersScreen-Do7YtBiu.mjs → OrdersScreen-BIjN8-_y.mjs} +2 -2
  22. package/dist/{OrdersScreen-Do7YtBiu.mjs.map → OrdersScreen-BIjN8-_y.mjs.map} +1 -1
  23. package/dist/{OrdersScreen-DISwVljS.mjs → OrdersScreen-BmwgXoqb.mjs} +4 -4
  24. package/dist/{OrdersScreen-CZIlrF_M.cjs → OrdersScreen-CgYMIsbc.cjs} +2 -2
  25. package/dist/{OrdersScreen-CZIlrF_M.cjs.map → OrdersScreen-CgYMIsbc.cjs.map} +1 -1
  26. package/dist/{ProfileScreen-Chk8YkMW.mjs → ProfileScreen--fDK5YsG.mjs} +3 -3
  27. package/dist/{ProfileScreen-Chk8YkMW.mjs.map → ProfileScreen--fDK5YsG.mjs.map} +1 -1
  28. package/dist/{ProfileScreen-DZFMc4E9.mjs → ProfileScreen-BIb54IBH.mjs} +5 -5
  29. package/dist/{ProfileScreen-C3zOvEhX.cjs → ProfileScreen-Bhl7VJj1.cjs} +3 -3
  30. package/dist/{ProfileScreen-C3zOvEhX.cjs.map → ProfileScreen-Bhl7VJj1.cjs.map} +1 -1
  31. package/dist/{ProfileScreen-CxOJ1D3H.cjs → ProfileScreen-DsYyPXQj.cjs} +5 -5
  32. package/dist/{ShopScreen-uOMi-jFD.mjs → ShopScreen-B4_2T5Nd.mjs} +2 -2
  33. package/dist/{ShopScreen-uOMi-jFD.mjs.map → ShopScreen-B4_2T5Nd.mjs.map} +1 -1
  34. package/dist/{ShopScreen-CjrEStJc.cjs → ShopScreen-CPTXTr7p.cjs} +2 -2
  35. package/dist/{ShopScreen-CjrEStJc.cjs.map → ShopScreen-CPTXTr7p.cjs.map} +1 -1
  36. package/dist/{ShopScreen-C4vXayCp.mjs → ShopScreen-CvZGzOUd.mjs} +4 -4
  37. package/dist/{ShopScreen-DM9jxl3w.cjs → ShopScreen-DVLxDFpf.cjs} +4 -4
  38. package/dist/{SubscriptionsScreen-CyL91O4w.cjs → SubscriptionsScreen-7ZH1s3eK.cjs} +21 -20
  39. package/dist/SubscriptionsScreen-7ZH1s3eK.cjs.map +1 -0
  40. package/dist/{SubscriptionsScreen-u_q5j115.mjs → SubscriptionsScreen-BcIUZf50.mjs} +21 -20
  41. package/dist/SubscriptionsScreen-BcIUZf50.mjs.map +1 -0
  42. package/dist/{SubscriptionsScreen-93eTwtFE.cjs → SubscriptionsScreen-CVHJ08si.cjs} +5 -5
  43. package/dist/{SubscriptionsScreen-8cPR9vpX.mjs → SubscriptionsScreen-CwseYMy5.mjs} +5 -5
  44. package/dist/{ToDoWidget-sLWwJJ_g.mjs → ToDoWidget-CShnzkw4.mjs} +3 -3
  45. package/dist/ToDoWidget-CShnzkw4.mjs.map +1 -0
  46. package/dist/{ToDoWidget-C9qX7raE.cjs → ToDoWidget-CevskOb8.cjs} +2 -2
  47. package/dist/{ToDoWidget-CImAWF3O.cjs → ToDoWidget-DA_kLqvP.cjs} +3 -3
  48. package/dist/ToDoWidget-DA_kLqvP.cjs.map +1 -0
  49. package/dist/index.cjs +22 -22
  50. package/dist/index.mjs +22 -22
  51. package/dist/{task-composer-form-ChwUNk1I.mjs → task-composer-form-CHyQZUCo.mjs} +3 -2
  52. package/dist/{task-composer-form-ChwUNk1I.mjs.map → task-composer-form-CHyQZUCo.mjs.map} +1 -1
  53. package/dist/{task-composer-form-DnRjQmkv.cjs → task-composer-form-D9KhWUI1.cjs} +3 -2
  54. package/dist/{task-composer-form-DnRjQmkv.cjs.map → task-composer-form-D9KhWUI1.cjs.map} +1 -1
  55. package/package.json +14 -14
  56. package/dist/SubscriptionsScreen-CyL91O4w.cjs.map +0 -1
  57. package/dist/SubscriptionsScreen-u_q5j115.mjs.map +0 -1
  58. package/dist/ToDoWidget-CImAWF3O.cjs.map +0 -1
  59. package/dist/ToDoWidget-sLWwJJ_g.mjs.map +0 -1
@@ -1,11 +1,11 @@
1
1
  require("./chunk-9hOWP6kD.cjs");
2
- require("./FluidProvider-BIeO1i4r.cjs");
2
+ require("./FluidProvider-BQjPCP_2.cjs");
3
3
  require("./ScreenRenderer-D_eEc6S4.cjs");
4
4
  require("./PortalTenantClientProvider-D-QE-YzB.cjs");
5
5
  require("./store-api-context-D1gZn22Z.cjs");
6
6
  require("./mysite-api-context-CilZcDS4.cjs");
7
7
  require("./countries-api-context-G-NW4BoH.cjs");
8
- require("./task-composer-form-DnRjQmkv.cjs");
8
+ require("./task-composer-form-D9KhWUI1.cjs");
9
9
  require("./registry-context-DJ5xiVnt.cjs");
10
10
  require("./WidgetInteractionContext-BhkusA95.cjs");
11
11
  require("./EmbedWidget-C3ZJCcHD.cjs");
@@ -40,13 +40,13 @@ require("./RecentActivityWidget-Cy9957Sq.cjs");
40
40
  require("./SeparatorWidget-LQ97EZd5.cjs");
41
41
  require("./SpacerWidget-CYHjTF38.cjs");
42
42
  require("./TableWidget-DfKZhS1Y.cjs");
43
- require("./ToDoWidget-CImAWF3O.cjs");
43
+ require("./ToDoWidget-DA_kLqvP.cjs");
44
44
  require("./VideoWidget-Ddt85ZZg.cjs");
45
45
  require("./SearchSort-Bi9QWJQQ.cjs");
46
46
  require("./ShopWidget-BRx2rblg.cjs");
47
47
  require("./ScreenHeaderContext-DWDN0-mb.cjs");
48
- require("./AddressAutocompleteInput-DkFs_leA.cjs");
48
+ require("./AddressAutocompleteInput-DfwaaK0l.cjs");
49
49
  require("./Combobox-D9lqcqeg.cjs");
50
- const require_SubscriptionsScreen = require("./SubscriptionsScreen-CyL91O4w.cjs");
50
+ const require_SubscriptionsScreen = require("./SubscriptionsScreen-7ZH1s3eK.cjs");
51
51
  exports.SubscriptionsScreen = require_SubscriptionsScreen.SubscriptionsScreen;
52
52
  exports.subscriptionsScreenPropertySchema = require_SubscriptionsScreen.subscriptionsScreenPropertySchema;
@@ -1,10 +1,10 @@
1
1
  import "./PortalTenantClientProvider-CqW6ae2M.mjs";
2
- import "./FluidProvider-LqejfvZ-.mjs";
2
+ import "./FluidProvider-DU-sFsZV.mjs";
3
3
  import "./ScreenRenderer-BszshjZg.mjs";
4
4
  import "./store-api-context-DViwxyG4.mjs";
5
5
  import "./mysite-api-context-kUTM3GNG.mjs";
6
6
  import "./countries-api-context-DScC_39w.mjs";
7
- import "./task-composer-form-ChwUNk1I.mjs";
7
+ import "./task-composer-form-CHyQZUCo.mjs";
8
8
  import "./registry-context-BKvTiuXB.mjs";
9
9
  import "./WidgetInteractionContext-BWH7njU7.mjs";
10
10
  import "./EmbedWidget-Be16VTGq.mjs";
@@ -25,7 +25,7 @@ import "./MediaRenderer-CLmBOrvK.mjs";
25
25
  import "./CarouselWidget-2fu0NYxd.mjs";
26
26
  import "./CatchUpWidget-DxeBgueZ.mjs";
27
27
  import "./src-DC5QoBhR.mjs";
28
- import { n as subscriptionsScreenPropertySchema, t as SubscriptionsScreen } from "./SubscriptionsScreen-u_q5j115.mjs";
28
+ import { n as subscriptionsScreenPropertySchema, t as SubscriptionsScreen } from "./SubscriptionsScreen-BcIUZf50.mjs";
29
29
  import "./ChartWidget-DfQQU2w2.mjs";
30
30
  import "./ContainerWidget-CPacdtRy.mjs";
31
31
  import "./ImageWidget-BOFNCjT1.mjs";
@@ -40,11 +40,11 @@ import "./RecentActivityWidget-D15aOkXL.mjs";
40
40
  import "./SeparatorWidget-DugZ8ukt.mjs";
41
41
  import "./SpacerWidget-CCpCGUjM.mjs";
42
42
  import "./TableWidget-Cef29Su9.mjs";
43
- import "./ToDoWidget-sLWwJJ_g.mjs";
43
+ import "./ToDoWidget-CShnzkw4.mjs";
44
44
  import "./VideoWidget-CjOhc8KW.mjs";
45
45
  import "./SearchSort-BeYMXXIi.mjs";
46
46
  import "./ShopWidget-BKTYcwx_.mjs";
47
47
  import "./ScreenHeaderContext-Dn12BZyj.mjs";
48
- import "./AddressAutocompleteInput-BpbBARKk.mjs";
48
+ import "./AddressAutocompleteInput-CYWqjVql.mjs";
49
49
  import "./Combobox-B-rNFLTr.mjs";
50
50
  export { SubscriptionsScreen, subscriptionsScreenPropertySchema };
@@ -1,5 +1,5 @@
1
1
  import { vt as __exportAll } from "./PortalTenantClientProvider-CqW6ae2M.mjs";
2
- import { c as useContactsTranslation, o as parseTaskBody, r as useInfiniteContacts, t as TaskComposerForm } from "./task-composer-form-ChwUNk1I.mjs";
2
+ import { c as useContactsTranslation, o as parseTaskBody, r as useInfiniteContacts, t as TaskComposerForm } from "./task-composer-form-CHyQZUCo.mjs";
3
3
  import { n as useDataSourceRegistryConfig } from "./registry-context-BKvTiuXB.mjs";
4
4
  import { r as useWidgetsApi, t as ErrorState } from "./error-state-Djgt-RGW.mjs";
5
5
  import { i as getBorderColorField, l as getColorField, m as getPaddingField, n as borderWidthClasses, o as getBorderRadiusField, s as getBorderWidthField, t as borderColorClasses, u as getFontSizeField } from "./registries-BtCYIu-b.mjs";
@@ -177,7 +177,7 @@ function ContactPicker({ value, onSelect }) {
177
177
  return () => window.clearTimeout(handle);
178
178
  }, [searchInput]);
179
179
  const { data, isLoading, isError, hasNextPage, isFetchingNextPage, fetchNextPage } = useInfiniteContacts(useMemo(() => ({
180
- search_query: debouncedSearch || void 0,
180
+ ...debouncedSearch ? { search_query: debouncedSearch } : {},
181
181
  sort_by: "full_name",
182
182
  sort_direction: "asc",
183
183
  per_page: 25
@@ -541,4 +541,4 @@ const toDoWidgetPropertySchema = {
541
541
  //#endregion
542
542
  export { ToDoWidget_exports as n, toDoWidgetPropertySchema as r, ToDoWidget as t };
543
543
 
544
- //# sourceMappingURL=ToDoWidget-sLWwJJ_g.mjs.map
544
+ //# sourceMappingURL=ToDoWidget-CShnzkw4.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToDoWidget-CShnzkw4.mjs","names":[],"sources":["../../widgets/src/hooks/use-todos.preview.ts","../../widgets/src/hooks/use-todos.ts","../../widgets/src/hooks/use-update-todo.ts","../../widgets/src/widgets/CreateTodoDialog.tsx","../../widgets/src/widgets/ToDoWidget.tsx"],"sourcesContent":["import type { Todo } from \"@fluid-app/portal-core/widgets-api-types\";\n\nconst now = new Date();\n\nfunction daysFromNow(days: number): string {\n const d = new Date(now);\n d.setDate(d.getDate() + days);\n return d.toISOString();\n}\n\nexport const PREVIEW_DATA: Todo[] = [\n {\n id: 1,\n body: \"Send follow-up email to new leads\",\n dueAt: daysFromNow(1),\n completedAt: null,\n createdAt: daysFromNow(-2),\n contactId: 101,\n contactName: \"Sarah Johnson\",\n },\n {\n id: 2,\n body: \"Prepare slides for team training\",\n dueAt: daysFromNow(3),\n completedAt: null,\n createdAt: daysFromNow(-1),\n contactId: null,\n contactName: null,\n },\n {\n id: 3,\n body: \"Review monthly sales report\",\n dueAt: daysFromNow(-1),\n completedAt: null,\n createdAt: daysFromNow(-5),\n contactId: 102,\n contactName: \"Mike Chen\",\n },\n];\n","import { useQuery, type UseQueryResult } from \"@tanstack/react-query\";\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-todos.preview\";\nimport type { Todo } from \"@fluid-app/portal-core/widgets-api-types\";\n\nexport type { Todo } from \"@fluid-app/portal-core/widgets-api-types\";\n\n/**\n * Shared cache key for the todos list. Both useTodos (read) and\n * useUpdateTodo (write) use this — drift would silently break optimistic\n * updates.\n */\nexport function todosQueryKey(args: {\n baseUrl: string | undefined;\n isPreview: boolean;\n}) {\n return [\n \"portal-widget-use\",\n \"todos\",\n args.isPreview ? \"preview\" : args.baseUrl,\n ] as const;\n}\n\nexport function useTodos(): UseQueryResult<Todo[], Error> {\n const widgetsApi = useWidgetsApi();\n const { isPreview } = useWidgetPreviewContext();\n const { baseUrl } = useDataSourceRegistryConfig();\n\n return useQuery({\n queryKey: todosQueryKey({ baseUrl, isPreview }),\n queryFn: ({ signal }) => widgetsApi.fetchTodos(signal),\n enabled: !isPreview,\n ...(isPreview && { placeholderData: PREVIEW_DATA }),\n });\n}\n","import { useMutation, useQueryClient } 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 type { Todo } from \"@fluid-app/portal-core/widgets-api-types\";\nimport { todosQueryKey } from \"./use-todos\";\n\ntype UpdateVariables = { id: number; completed: boolean };\n\nexport function useUpdateTodo() {\n const widgetsApi = useWidgetsApi();\n const queryClient = useQueryClient();\n const { isPreview } = useWidgetPreviewContext();\n const { baseUrl } = useDataSourceRegistryConfig();\n\n const queryKey = todosQueryKey({ baseUrl, isPreview });\n\n return useMutation({\n mutationFn: ({ id, completed }: UpdateVariables) => {\n // Defense in depth: ToDoWidget already disables the checkbox in\n // preview mode, but if any other caller fires this mutation while\n // previewing we'd PATCH demo data on the real backend. Fail closed.\n if (isPreview) {\n return Promise.reject(\n new Error(\"Todo updates are disabled in preview mode\"),\n );\n }\n return widgetsApi.updateTodo(id, completed);\n },\n onMutate: async ({ id, completed }) => {\n await queryClient.cancelQueries({ queryKey });\n const previous = queryClient.getQueryData<Todo[]>(queryKey);\n queryClient.setQueryData<Todo[]>(queryKey, (current) =>\n (current ?? []).map((todo) =>\n todo.id === id\n ? {\n ...todo,\n completedAt: completed ? new Date().toISOString() : null,\n }\n : todo,\n ),\n );\n return { previous };\n },\n onSuccess: (updated, { completed }) => {\n queryClient.setQueryData<Todo[]>(queryKey, (current) =>\n (current ?? []).map((todo) =>\n todo.id === updated.id ? updated : todo,\n ),\n );\n // Match the documented test plan: completing toasts, un-completing\n // is silent. The widget today only ever fires completed=true, but\n // gating here keeps the contract honest for any future caller that\n // toggles either direction.\n if (completed) {\n fluidToast({ title: \"Todo completed\", type: \"success\" });\n }\n },\n onError: (_error, _variables, context) => {\n if (context?.previous) {\n queryClient.setQueryData(queryKey, context.previous);\n }\n fluidToast({ title: \"Failed to update todo\", type: \"error\" });\n },\n // Belt-and-suspenders refetch to reconcile any race we couldn't see\n // (e.g., a different tab mutated the same todo). Cheap — one GET per\n // toggle.\n onSettled: () => {\n queryClient.invalidateQueries({ queryKey });\n },\n });\n}\n","\"use client\";\n\nimport React, { useEffect, useMemo, useRef, useState } from \"react\";\nimport { Check, ChevronsUpDown, Search } from \"lucide-react\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport {\n cn,\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n Input,\n Popover,\n PopoverContent,\n PopoverTrigger,\n PortalContainerProvider,\n} from \"@fluid-app/ui-primitives\";\nimport { useInfiniteContacts } from \"@fluid-app/contacts-core/hooks/use-infinite-contacts\";\nimport { useContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\nimport type { Contact } from \"@fluid-app/contacts-core/types\";\nimport { TaskComposerForm } from \"@fluid-app/contacts-ui/portal/components/tasks/task-composer-form\";\nimport { useWidgetPreviewContext } from \"@fluid-app/portal-react/data-sources/preview-context\";\nimport { useDataSourceRegistryConfig } from \"@fluid-app/portal-react/data-sources/registry-context\";\nimport { todosQueryKey } from \"../hooks/use-todos\";\n\nconst SEARCH_DEBOUNCE_MS = 200;\n\nexport interface CreateTodoDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n}\n\nexport function CreateTodoDialog({\n open,\n onOpenChange,\n}: CreateTodoDialogProps): React.JSX.Element {\n const queryClient = useQueryClient();\n const { isPreview } = useWidgetPreviewContext();\n const { baseUrl } = useDataSourceRegistryConfig();\n const [selectedContact, setSelectedContact] = useState<Contact | null>(null);\n // Anchor the popover's portal inside the dialog. Dialog applies\n // pointer-events: none to the body while open, which kills clicks and\n // scroll on a body-portaled popover in WebKit. See edit-bill-date-dialog\n // for the canonical pattern.\n const [popoverContainer, setPopoverContainer] =\n useState<HTMLDivElement | null>(null);\n\n // Reset state when the dialog closes so the next open starts fresh.\n useEffect(() => {\n if (!open) setSelectedContact(null);\n }, [open]);\n\n const handleDone = () => {\n queryClient.invalidateQueries({\n queryKey: todosQueryKey({ baseUrl, isPreview }),\n });\n onOpenChange(false);\n };\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"sm:max-w-md\">\n <DialogHeader>\n <DialogTitle>Add a to-do</DialogTitle>\n </DialogHeader>\n\n <PortalContainerProvider container={popoverContainer}>\n <div className=\"mt-2 flex flex-col gap-3\">\n <ContactPicker\n value={selectedContact}\n onSelect={setSelectedContact}\n />\n\n {selectedContact && (\n <TaskComposerForm\n key={selectedContact.id}\n contactId={String(selectedContact.id)}\n onDone={handleDone}\n />\n )}\n </div>\n </PortalContainerProvider>\n {/* Portal target for the popover. Must live INSIDE DialogContent so\n it ends up in the dialog's body-level portal — otherwise it\n renders inline next to the widget, and any transformed ancestor\n (builder canvas zoom, etc.) would break `position: fixed`.\n Intentionally NOT aria-hidden — the popover content portaled\n into this container has its own listbox/option semantics that\n screen readers need to reach. `pointer-events-none` keeps the\n empty overlay from capturing clicks; the popover content sets\n `pointer-events-auto` so it remains interactive. */}\n <div\n ref={setPopoverContainer}\n className=\"pointer-events-none fixed inset-0 z-[9998]\"\n />\n </DialogContent>\n </Dialog>\n );\n}\n\ninterface ContactPickerProps {\n value: Contact | null;\n onSelect: (contact: Contact) => void;\n}\n\nfunction ContactPicker({\n value,\n onSelect,\n}: ContactPickerProps): React.JSX.Element {\n const { t } = useContactsTranslation();\n const [open, setOpen] = useState(false);\n const [searchInput, setSearchInput] = useState(\"\");\n const [debouncedSearch, setDebouncedSearch] = useState(\"\");\n const sentinelRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const handle = window.setTimeout(() => {\n setDebouncedSearch(searchInput.trim());\n }, SEARCH_DEBOUNCE_MS);\n return () => window.clearTimeout(handle);\n }, [searchInput]);\n\n const queryParams = useMemo(\n () => ({\n ...(debouncedSearch ? { search_query: debouncedSearch } : {}),\n sort_by: \"full_name\",\n sort_direction: \"asc\",\n per_page: 25,\n }),\n [debouncedSearch],\n );\n\n const {\n data,\n isLoading,\n isError,\n hasNextPage,\n isFetchingNextPage,\n fetchNextPage,\n } = useInfiniteContacts(queryParams);\n\n const contacts: Contact[] = useMemo(\n () => data?.pages.flatMap((page) => page.contacts ?? []) ?? [],\n [data],\n );\n\n // Auto-load the next page when the sentinel scrolls into view, so reps\n // with many contacts can reach all of them without typing a precise\n // search query.\n useEffect(() => {\n const sentinel = sentinelRef.current;\n if (!sentinel || !hasNextPage) return;\n\n const observer = new IntersectionObserver((entries) => {\n const entry = entries[0];\n if (entry?.isIntersecting && !isFetchingNextPage) {\n fetchNextPage();\n }\n });\n\n observer.observe(sentinel);\n return () => observer.disconnect();\n }, [hasNextPage, isFetchingNextPage, fetchNextPage]);\n\n return (\n <div className=\"flex flex-col gap-1\">\n <label className=\"text-muted-foreground text-xs font-medium\">\n {t(\"contact_label\")}\n </label>\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n aria-haspopup=\"listbox\"\n aria-expanded={open}\n className=\"border-input bg-background hover:bg-muted/40 flex w-full items-center justify-between gap-2 rounded-md border px-3 py-2 text-left text-sm transition-colors\"\n >\n <span\n className={cn(\n \"truncate\",\n !value && \"text-muted-foreground font-normal\",\n )}\n >\n {value ? value.full_name : t(\"empty_select_contact\")}\n </span>\n <ChevronsUpDown\n className=\"text-muted-foreground size-4 shrink-0\"\n aria-hidden=\"true\"\n />\n </button>\n </PopoverTrigger>\n <PopoverContent\n align=\"start\"\n className=\"bg-popover text-popover-foreground pointer-events-auto z-[9999] w-(--radix-popover-trigger-width) overflow-hidden rounded-md border p-0 shadow-md\"\n >\n <div className=\"border-border flex items-center gap-2 border-b px-3 py-2\">\n <Search\n className=\"text-muted-foreground size-4 shrink-0\"\n aria-hidden=\"true\"\n />\n <Input\n value={searchInput}\n onChange={(e) => setSearchInput(e.target.value)}\n placeholder={t(\"search_placeholder\")}\n aria-label={t(\"search_placeholder\")}\n className=\"h-7 border-0 px-0 shadow-none focus-visible:ring-0\"\n />\n </div>\n <div className=\"max-h-64 overflow-y-auto py-1\" role=\"listbox\">\n {isLoading ? (\n <div className=\"text-muted-foreground px-3 py-6 text-center text-xs\">\n {t(\"loading\")}\n </div>\n ) : isError ? (\n <div className=\"text-destructive px-3 py-6 text-center text-xs\">\n {t(\"error_loading_list\")}\n </div>\n ) : contacts.length === 0 ? (\n <div className=\"text-muted-foreground px-3 py-6 text-center text-xs\">\n {debouncedSearch\n ? t(\"no_contacts_search\", { term: debouncedSearch })\n : t(\"no_contacts_yet\")}\n </div>\n ) : (\n <>\n {contacts.map((contact) => {\n const isSelected = value?.id === contact.id;\n return (\n <button\n key={contact.id}\n type=\"button\"\n role=\"option\"\n aria-selected={isSelected}\n onClick={() => {\n onSelect(contact);\n setOpen(false);\n }}\n className=\"hover:bg-muted/50 flex w-full items-center justify-between gap-2 px-3 py-1.5 text-left text-sm transition-colors\"\n >\n <span className=\"truncate\">{contact.full_name}</span>\n {isSelected && (\n <Check\n className=\"text-primary size-4 shrink-0\"\n aria-hidden=\"true\"\n />\n )}\n </button>\n );\n })}\n {hasNextPage && (\n <div ref={sentinelRef} aria-hidden=\"true\" className=\"h-4\" />\n )}\n {isFetchingNextPage && (\n <div className=\"text-muted-foreground px-3 py-2 text-center text-xs\">\n {t(\"loading_more\")}\n </div>\n )}\n </>\n )}\n </div>\n </PopoverContent>\n </Popover>\n </div>\n );\n}\n","import { useState, type ComponentProps } from \"react\";\nimport type React 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 {\n getBorderRadiusField,\n getBorderWidthField,\n getBorderColorField,\n borderWidthClasses,\n borderColorClasses,\n getColorField,\n getFontSizeField,\n getPaddingField,\n} from \"../core/fields\";\nimport { ListChecks, Plus } from \"lucide-react\";\nimport { useWidgetPreviewContext } from \"@fluid-app/portal-react/data-sources/preview-context\";\nimport { parseTaskBody } from \"@fluid-app/contacts-core/parse-task-body\";\nimport { useTodos } from \"../hooks/use-todos\";\nimport { useUpdateTodo } from \"../hooks/use-update-todo\";\nimport { ErrorState } from \"../components/error-state\";\nimport { CreateTodoDialog } from \"./CreateTodoDialog\";\n\ntype ToDoWidgetProps = ComponentProps<\"div\"> & {\n // Title\n titleEnabled?: boolean;\n titleText?: string;\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n\n // Styling\n background?: BackgroundValue;\n textColor?: ColorOptions;\n accentColor?: ColorOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n\n // Content\n maxItems?: number;\n};\n\nexport function ToDoWidget({\n // Title defaults\n titleEnabled = true,\n titleText = \"To-Do\",\n titleFontSize = \"lg\",\n titleColor = \"foreground\",\n\n // Styling 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\n // Content defaults\n maxItems = 5,\n\n className,\n ...props\n}: ToDoWidgetProps): 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: todos = [], isLoading, isError } = useTodos();\n const updateTodo = useUpdateTodo();\n const { isPreview } = useWidgetPreviewContext();\n const [pendingIds, setPendingIds] = useState<Set<number>>(new Set());\n const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false);\n\n const toggleTodo = (id: number, completed: boolean) => {\n if (isPreview || pendingIds.has(id)) return;\n setPendingIds((prev) => new Set(prev).add(id));\n updateTodo.mutate(\n { id, completed },\n {\n onSettled: () =>\n setPendingIds((prev) => {\n const next = new Set(prev);\n next.delete(id);\n return next;\n }),\n },\n );\n };\n\n const activeTodos = todos.filter((todo) => !todo.completedAt);\n const todosToShow = activeTodos.slice(0, maxItems);\n const remainingCount = activeTodos.length - todosToShow.length;\n const isEmpty = activeTodos.length === 0;\n\n // Group todos by contactId so same-named contacts stay separate.\n const groupedTodos = todosToShow.reduce<\n {\n contactId: number | null;\n contactName: string | null;\n todos: typeof todosToShow;\n }[]\n >((groups, todo) => {\n const existing = groups.find((g) => g.contactId === todo.contactId);\n if (existing) {\n existing.todos.push(todo);\n } else {\n groups.push({\n contactId: todo.contactId,\n contactName: todo.contactName,\n todos: [todo],\n });\n }\n return groups;\n }, []);\n\n return (\n <div\n className={`overflow-hidden rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} bg-${backgroundColor} text-${textColor} p-${padding} ${className ?? \"\"}`}\n style={{ backgroundImage }}\n {...props}\n >\n {/* Header */}\n <div className=\"mb-3 flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n {titleEnabled && titleText && (\n <h2\n className={`text-${titleFontSize} font-header font-bold text-${titleColor}`}\n >\n {titleText}\n </h2>\n )}\n </div>\n <div className=\"flex items-center gap-2\">\n {!isEmpty && !isLoading && (\n <span className={`text-2xl font-bold text-${accentColor}`}>\n {activeTodos.length}\n </span>\n )}\n <div\n className={`flex h-10 w-10 shrink-0 items-center justify-center`}\n >\n <ListChecks className={`h-5 w-5 text-${accentColor}-foreground`} />\n </div>\n </div>\n </div>\n\n {/* Loading state */}\n {isLoading ? (\n <div className=\"flex min-h-[120px] items-center justify-center\">\n <div className=\"h-6 w-6 animate-spin rounded-full border-2 border-current border-t-transparent\" />\n </div>\n ) : isError ? (\n /* Error state */\n <ErrorState />\n ) : isEmpty ? (\n /* Empty state */\n <div className=\"flex flex-col items-center justify-center gap-3 py-8\">\n <p className={`text-center text-${textColor}/60`}>\n You&apos;ve got nothing else To-Do!\n </p>\n {!isPreview && (\n <button\n type=\"button\"\n onClick={() => setIsCreateDialogOpen(true)}\n className={`inline-flex items-center gap-1.5 rounded-full bg-${accentColor} text-${accentColor}-foreground hover:bg-${accentColor}/90 px-4 py-1.5 text-xs font-semibold transition-colors`}\n >\n <Plus className=\"h-3.5 w-3.5\" aria-hidden=\"true\" />\n Add to-do\n </button>\n )}\n </div>\n ) : (\n /* Todo List */\n <>\n <div className=\"flex flex-col gap-3\">\n {groupedTodos.map((group) => (\n <div\n key={group.contactId ?? \"__unassigned__\"}\n className=\"flex flex-col\"\n >\n {group.contactName && (\n <div\n className={`mb-1 text-xs font-semibold tracking-wide uppercase text-${textColor}/60`}\n >\n {group.contactName}\n </div>\n )}\n {group.todos.map((todo, index) => (\n <div\n key={todo.id}\n className={`flex items-center gap-3 py-2 ${\n index !== group.todos.length - 1\n ? `border-b border-${textColor}/10`\n : \"\"\n }`}\n >\n <input\n type=\"checkbox\"\n className={`h-5 w-5 rounded-full border-2 border-${textColor}/30 bg-transparent not-disabled:cursor-pointer disabled:cursor-not-allowed disabled:opacity-60`}\n checked={!!todo.completedAt}\n disabled={isPreview || pendingIds.has(todo.id)}\n onChange={(event) =>\n toggleTodo(todo.id, event.target.checked)\n }\n />\n <span className=\"line-clamp-1 flex-1 text-sm\">\n {parseTaskBody(todo.body).title}\n </span>\n </div>\n ))}\n </div>\n ))}\n </div>\n\n {/* Footer */}\n <div className=\"mt-2 flex items-center justify-between\">\n {remainingCount > 0 && (\n <span className={`text-sm text-${textColor}/50 underline`}>\n {remainingCount} more task{remainingCount > 1 ? \"s\" : \"\"}\n </span>\n )}\n <div className=\"ml-auto\">\n <button\n type=\"button\"\n onClick={() => setIsCreateDialogOpen(true)}\n disabled={isPreview}\n aria-label=\"Add to-do\"\n className={`flex h-8 w-8 items-center justify-center rounded-full transition-colors not-disabled:cursor-pointer hover:bg-${textColor}/10 disabled:opacity-60`}\n >\n <Plus className={`h-5 w-5 text-${textColor}/50`} />\n </button>\n </div>\n </div>\n </>\n )}\n\n {!isPreview && (\n <CreateTodoDialog\n open={isCreateDialogOpen}\n onOpenChange={setIsCreateDialogOpen}\n />\n )}\n </div>\n );\n}\n\nexport const toDoWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"ToDoWidget\",\n displayName: \"To-Do 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 todo list\",\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 todo list\",\n defaultValue: \"To-Do\",\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 widget container\",\n defaultValue: \"background\",\n tab: \"styling\",\n group: \"Design\",\n },\n getColorField({\n key: \"textColor\",\n label: \"Text Color\",\n description: \"Default text color for todo 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 badge and icon\",\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 todo items to display\",\n min: 1,\n max: 20,\n step: 1,\n defaultValue: 5,\n tab: \"styling\",\n group: \"Design\",\n },\n getPaddingField({\n key: \"padding\",\n label: \"Padding\",\n description: \"Padding around the widget 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 widget 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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"}
@@ -1,5 +1,5 @@
1
1
  require("./chunk-9hOWP6kD.cjs");
2
- require("./task-composer-form-DnRjQmkv.cjs");
2
+ require("./task-composer-form-D9KhWUI1.cjs");
3
3
  require("./registry-context-DJ5xiVnt.cjs");
4
4
  require("./error-state-BI3jxWlb.cjs");
5
5
  require("./translation-api-context-factory-6jtyJm6d.cjs");
@@ -7,5 +7,5 @@ require("./registries-ClaAtpiG.cjs");
7
7
  require("./fields-D4qgIZ7Y.cjs");
8
8
  require("./preview-context-B4-iZOzd.cjs");
9
9
  require("./src-DoVMGOoV.cjs");
10
- const require_ToDoWidget = require("./ToDoWidget-CImAWF3O.cjs");
10
+ const require_ToDoWidget = require("./ToDoWidget-DA_kLqvP.cjs");
11
11
  exports.toDoWidgetPropertySchema = require_ToDoWidget.toDoWidgetPropertySchema;
@@ -1,5 +1,5 @@
1
1
  const require_chunk = require("./chunk-9hOWP6kD.cjs");
2
- const require_task_composer_form = require("./task-composer-form-DnRjQmkv.cjs");
2
+ const require_task_composer_form = require("./task-composer-form-D9KhWUI1.cjs");
3
3
  const require_registry_context = require("./registry-context-DJ5xiVnt.cjs");
4
4
  const require_error_state = require("./error-state-BI3jxWlb.cjs");
5
5
  const require_registries = require("./registries-ClaAtpiG.cjs");
@@ -178,7 +178,7 @@ function ContactPicker({ value, onSelect }) {
178
178
  return () => window.clearTimeout(handle);
179
179
  }, [searchInput]);
180
180
  const { data, isLoading, isError, hasNextPage, isFetchingNextPage, fetchNextPage } = require_task_composer_form.useInfiniteContacts((0, react.useMemo)(() => ({
181
- search_query: debouncedSearch || void 0,
181
+ ...debouncedSearch ? { search_query: debouncedSearch } : {},
182
182
  sort_by: "full_name",
183
183
  sort_direction: "asc",
184
184
  per_page: 25
@@ -549,4 +549,4 @@ Object.defineProperty(exports, "toDoWidgetPropertySchema", {
549
549
  }
550
550
  });
551
551
 
552
- //# sourceMappingURL=ToDoWidget-CImAWF3O.cjs.map
552
+ //# sourceMappingURL=ToDoWidget-DA_kLqvP.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ToDoWidget-DA_kLqvP.cjs","names":["useWidgetsApi","useWidgetPreviewContext","useDataSourceRegistryConfig","useWidgetsApi","useWidgetPreviewContext","useDataSourceRegistryConfig","useWidgetPreviewContext","useDataSourceRegistryConfig","Dialog","DialogContent","DialogHeader","DialogTitle","PortalContainerProvider","TaskComposerForm","useContactsTranslation","useInfiniteContacts","Popover","PopoverTrigger","cn","ChevronsUpDown","PopoverContent","Search","Input","Check","useWidgetPreviewContext","borderWidthClasses","borderColorClasses","ListChecks","ErrorState","Plus","parseTaskBody","getFontSizeField","getColorField","getPaddingField","getBorderRadiusField","getBorderWidthField","getBorderColorField"],"sources":["../../widgets/src/hooks/use-todos.preview.ts","../../widgets/src/hooks/use-todos.ts","../../widgets/src/hooks/use-update-todo.ts","../../widgets/src/widgets/CreateTodoDialog.tsx","../../widgets/src/widgets/ToDoWidget.tsx"],"sourcesContent":["import type { Todo } from \"@fluid-app/portal-core/widgets-api-types\";\n\nconst now = new Date();\n\nfunction daysFromNow(days: number): string {\n const d = new Date(now);\n d.setDate(d.getDate() + days);\n return d.toISOString();\n}\n\nexport const PREVIEW_DATA: Todo[] = [\n {\n id: 1,\n body: \"Send follow-up email to new leads\",\n dueAt: daysFromNow(1),\n completedAt: null,\n createdAt: daysFromNow(-2),\n contactId: 101,\n contactName: \"Sarah Johnson\",\n },\n {\n id: 2,\n body: \"Prepare slides for team training\",\n dueAt: daysFromNow(3),\n completedAt: null,\n createdAt: daysFromNow(-1),\n contactId: null,\n contactName: null,\n },\n {\n id: 3,\n body: \"Review monthly sales report\",\n dueAt: daysFromNow(-1),\n completedAt: null,\n createdAt: daysFromNow(-5),\n contactId: 102,\n contactName: \"Mike Chen\",\n },\n];\n","import { useQuery, type UseQueryResult } from \"@tanstack/react-query\";\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-todos.preview\";\nimport type { Todo } from \"@fluid-app/portal-core/widgets-api-types\";\n\nexport type { Todo } from \"@fluid-app/portal-core/widgets-api-types\";\n\n/**\n * Shared cache key for the todos list. Both useTodos (read) and\n * useUpdateTodo (write) use this — drift would silently break optimistic\n * updates.\n */\nexport function todosQueryKey(args: {\n baseUrl: string | undefined;\n isPreview: boolean;\n}) {\n return [\n \"portal-widget-use\",\n \"todos\",\n args.isPreview ? \"preview\" : args.baseUrl,\n ] as const;\n}\n\nexport function useTodos(): UseQueryResult<Todo[], Error> {\n const widgetsApi = useWidgetsApi();\n const { isPreview } = useWidgetPreviewContext();\n const { baseUrl } = useDataSourceRegistryConfig();\n\n return useQuery({\n queryKey: todosQueryKey({ baseUrl, isPreview }),\n queryFn: ({ signal }) => widgetsApi.fetchTodos(signal),\n enabled: !isPreview,\n ...(isPreview && { placeholderData: PREVIEW_DATA }),\n });\n}\n","import { useMutation, useQueryClient } 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 type { Todo } from \"@fluid-app/portal-core/widgets-api-types\";\nimport { todosQueryKey } from \"./use-todos\";\n\ntype UpdateVariables = { id: number; completed: boolean };\n\nexport function useUpdateTodo() {\n const widgetsApi = useWidgetsApi();\n const queryClient = useQueryClient();\n const { isPreview } = useWidgetPreviewContext();\n const { baseUrl } = useDataSourceRegistryConfig();\n\n const queryKey = todosQueryKey({ baseUrl, isPreview });\n\n return useMutation({\n mutationFn: ({ id, completed }: UpdateVariables) => {\n // Defense in depth: ToDoWidget already disables the checkbox in\n // preview mode, but if any other caller fires this mutation while\n // previewing we'd PATCH demo data on the real backend. Fail closed.\n if (isPreview) {\n return Promise.reject(\n new Error(\"Todo updates are disabled in preview mode\"),\n );\n }\n return widgetsApi.updateTodo(id, completed);\n },\n onMutate: async ({ id, completed }) => {\n await queryClient.cancelQueries({ queryKey });\n const previous = queryClient.getQueryData<Todo[]>(queryKey);\n queryClient.setQueryData<Todo[]>(queryKey, (current) =>\n (current ?? []).map((todo) =>\n todo.id === id\n ? {\n ...todo,\n completedAt: completed ? new Date().toISOString() : null,\n }\n : todo,\n ),\n );\n return { previous };\n },\n onSuccess: (updated, { completed }) => {\n queryClient.setQueryData<Todo[]>(queryKey, (current) =>\n (current ?? []).map((todo) =>\n todo.id === updated.id ? updated : todo,\n ),\n );\n // Match the documented test plan: completing toasts, un-completing\n // is silent. The widget today only ever fires completed=true, but\n // gating here keeps the contract honest for any future caller that\n // toggles either direction.\n if (completed) {\n fluidToast({ title: \"Todo completed\", type: \"success\" });\n }\n },\n onError: (_error, _variables, context) => {\n if (context?.previous) {\n queryClient.setQueryData(queryKey, context.previous);\n }\n fluidToast({ title: \"Failed to update todo\", type: \"error\" });\n },\n // Belt-and-suspenders refetch to reconcile any race we couldn't see\n // (e.g., a different tab mutated the same todo). Cheap — one GET per\n // toggle.\n onSettled: () => {\n queryClient.invalidateQueries({ queryKey });\n },\n });\n}\n","\"use client\";\n\nimport React, { useEffect, useMemo, useRef, useState } from \"react\";\nimport { Check, ChevronsUpDown, Search } from \"lucide-react\";\nimport { useQueryClient } from \"@tanstack/react-query\";\nimport {\n cn,\n Dialog,\n DialogContent,\n DialogHeader,\n DialogTitle,\n Input,\n Popover,\n PopoverContent,\n PopoverTrigger,\n PortalContainerProvider,\n} from \"@fluid-app/ui-primitives\";\nimport { useInfiniteContacts } from \"@fluid-app/contacts-core/hooks/use-infinite-contacts\";\nimport { useContactsTranslation } from \"@fluid-app/contacts-core/translation-api-context\";\nimport type { Contact } from \"@fluid-app/contacts-core/types\";\nimport { TaskComposerForm } from \"@fluid-app/contacts-ui/portal/components/tasks/task-composer-form\";\nimport { useWidgetPreviewContext } from \"@fluid-app/portal-react/data-sources/preview-context\";\nimport { useDataSourceRegistryConfig } from \"@fluid-app/portal-react/data-sources/registry-context\";\nimport { todosQueryKey } from \"../hooks/use-todos\";\n\nconst SEARCH_DEBOUNCE_MS = 200;\n\nexport interface CreateTodoDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n}\n\nexport function CreateTodoDialog({\n open,\n onOpenChange,\n}: CreateTodoDialogProps): React.JSX.Element {\n const queryClient = useQueryClient();\n const { isPreview } = useWidgetPreviewContext();\n const { baseUrl } = useDataSourceRegistryConfig();\n const [selectedContact, setSelectedContact] = useState<Contact | null>(null);\n // Anchor the popover's portal inside the dialog. Dialog applies\n // pointer-events: none to the body while open, which kills clicks and\n // scroll on a body-portaled popover in WebKit. See edit-bill-date-dialog\n // for the canonical pattern.\n const [popoverContainer, setPopoverContainer] =\n useState<HTMLDivElement | null>(null);\n\n // Reset state when the dialog closes so the next open starts fresh.\n useEffect(() => {\n if (!open) setSelectedContact(null);\n }, [open]);\n\n const handleDone = () => {\n queryClient.invalidateQueries({\n queryKey: todosQueryKey({ baseUrl, isPreview }),\n });\n onOpenChange(false);\n };\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent className=\"sm:max-w-md\">\n <DialogHeader>\n <DialogTitle>Add a to-do</DialogTitle>\n </DialogHeader>\n\n <PortalContainerProvider container={popoverContainer}>\n <div className=\"mt-2 flex flex-col gap-3\">\n <ContactPicker\n value={selectedContact}\n onSelect={setSelectedContact}\n />\n\n {selectedContact && (\n <TaskComposerForm\n key={selectedContact.id}\n contactId={String(selectedContact.id)}\n onDone={handleDone}\n />\n )}\n </div>\n </PortalContainerProvider>\n {/* Portal target for the popover. Must live INSIDE DialogContent so\n it ends up in the dialog's body-level portal — otherwise it\n renders inline next to the widget, and any transformed ancestor\n (builder canvas zoom, etc.) would break `position: fixed`.\n Intentionally NOT aria-hidden — the popover content portaled\n into this container has its own listbox/option semantics that\n screen readers need to reach. `pointer-events-none` keeps the\n empty overlay from capturing clicks; the popover content sets\n `pointer-events-auto` so it remains interactive. */}\n <div\n ref={setPopoverContainer}\n className=\"pointer-events-none fixed inset-0 z-[9998]\"\n />\n </DialogContent>\n </Dialog>\n );\n}\n\ninterface ContactPickerProps {\n value: Contact | null;\n onSelect: (contact: Contact) => void;\n}\n\nfunction ContactPicker({\n value,\n onSelect,\n}: ContactPickerProps): React.JSX.Element {\n const { t } = useContactsTranslation();\n const [open, setOpen] = useState(false);\n const [searchInput, setSearchInput] = useState(\"\");\n const [debouncedSearch, setDebouncedSearch] = useState(\"\");\n const sentinelRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const handle = window.setTimeout(() => {\n setDebouncedSearch(searchInput.trim());\n }, SEARCH_DEBOUNCE_MS);\n return () => window.clearTimeout(handle);\n }, [searchInput]);\n\n const queryParams = useMemo(\n () => ({\n ...(debouncedSearch ? { search_query: debouncedSearch } : {}),\n sort_by: \"full_name\",\n sort_direction: \"asc\",\n per_page: 25,\n }),\n [debouncedSearch],\n );\n\n const {\n data,\n isLoading,\n isError,\n hasNextPage,\n isFetchingNextPage,\n fetchNextPage,\n } = useInfiniteContacts(queryParams);\n\n const contacts: Contact[] = useMemo(\n () => data?.pages.flatMap((page) => page.contacts ?? []) ?? [],\n [data],\n );\n\n // Auto-load the next page when the sentinel scrolls into view, so reps\n // with many contacts can reach all of them without typing a precise\n // search query.\n useEffect(() => {\n const sentinel = sentinelRef.current;\n if (!sentinel || !hasNextPage) return;\n\n const observer = new IntersectionObserver((entries) => {\n const entry = entries[0];\n if (entry?.isIntersecting && !isFetchingNextPage) {\n fetchNextPage();\n }\n });\n\n observer.observe(sentinel);\n return () => observer.disconnect();\n }, [hasNextPage, isFetchingNextPage, fetchNextPage]);\n\n return (\n <div className=\"flex flex-col gap-1\">\n <label className=\"text-muted-foreground text-xs font-medium\">\n {t(\"contact_label\")}\n </label>\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n aria-haspopup=\"listbox\"\n aria-expanded={open}\n className=\"border-input bg-background hover:bg-muted/40 flex w-full items-center justify-between gap-2 rounded-md border px-3 py-2 text-left text-sm transition-colors\"\n >\n <span\n className={cn(\n \"truncate\",\n !value && \"text-muted-foreground font-normal\",\n )}\n >\n {value ? value.full_name : t(\"empty_select_contact\")}\n </span>\n <ChevronsUpDown\n className=\"text-muted-foreground size-4 shrink-0\"\n aria-hidden=\"true\"\n />\n </button>\n </PopoverTrigger>\n <PopoverContent\n align=\"start\"\n className=\"bg-popover text-popover-foreground pointer-events-auto z-[9999] w-(--radix-popover-trigger-width) overflow-hidden rounded-md border p-0 shadow-md\"\n >\n <div className=\"border-border flex items-center gap-2 border-b px-3 py-2\">\n <Search\n className=\"text-muted-foreground size-4 shrink-0\"\n aria-hidden=\"true\"\n />\n <Input\n value={searchInput}\n onChange={(e) => setSearchInput(e.target.value)}\n placeholder={t(\"search_placeholder\")}\n aria-label={t(\"search_placeholder\")}\n className=\"h-7 border-0 px-0 shadow-none focus-visible:ring-0\"\n />\n </div>\n <div className=\"max-h-64 overflow-y-auto py-1\" role=\"listbox\">\n {isLoading ? (\n <div className=\"text-muted-foreground px-3 py-6 text-center text-xs\">\n {t(\"loading\")}\n </div>\n ) : isError ? (\n <div className=\"text-destructive px-3 py-6 text-center text-xs\">\n {t(\"error_loading_list\")}\n </div>\n ) : contacts.length === 0 ? (\n <div className=\"text-muted-foreground px-3 py-6 text-center text-xs\">\n {debouncedSearch\n ? t(\"no_contacts_search\", { term: debouncedSearch })\n : t(\"no_contacts_yet\")}\n </div>\n ) : (\n <>\n {contacts.map((contact) => {\n const isSelected = value?.id === contact.id;\n return (\n <button\n key={contact.id}\n type=\"button\"\n role=\"option\"\n aria-selected={isSelected}\n onClick={() => {\n onSelect(contact);\n setOpen(false);\n }}\n className=\"hover:bg-muted/50 flex w-full items-center justify-between gap-2 px-3 py-1.5 text-left text-sm transition-colors\"\n >\n <span className=\"truncate\">{contact.full_name}</span>\n {isSelected && (\n <Check\n className=\"text-primary size-4 shrink-0\"\n aria-hidden=\"true\"\n />\n )}\n </button>\n );\n })}\n {hasNextPage && (\n <div ref={sentinelRef} aria-hidden=\"true\" className=\"h-4\" />\n )}\n {isFetchingNextPage && (\n <div className=\"text-muted-foreground px-3 py-2 text-center text-xs\">\n {t(\"loading_more\")}\n </div>\n )}\n </>\n )}\n </div>\n </PopoverContent>\n </Popover>\n </div>\n );\n}\n","import { useState, type ComponentProps } from \"react\";\nimport type React 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 {\n getBorderRadiusField,\n getBorderWidthField,\n getBorderColorField,\n borderWidthClasses,\n borderColorClasses,\n getColorField,\n getFontSizeField,\n getPaddingField,\n} from \"../core/fields\";\nimport { ListChecks, Plus } from \"lucide-react\";\nimport { useWidgetPreviewContext } from \"@fluid-app/portal-react/data-sources/preview-context\";\nimport { parseTaskBody } from \"@fluid-app/contacts-core/parse-task-body\";\nimport { useTodos } from \"../hooks/use-todos\";\nimport { useUpdateTodo } from \"../hooks/use-update-todo\";\nimport { ErrorState } from \"../components/error-state\";\nimport { CreateTodoDialog } from \"./CreateTodoDialog\";\n\ntype ToDoWidgetProps = ComponentProps<\"div\"> & {\n // Title\n titleEnabled?: boolean;\n titleText?: string;\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n\n // Styling\n background?: BackgroundValue;\n textColor?: ColorOptions;\n accentColor?: ColorOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n\n // Content\n maxItems?: number;\n};\n\nexport function ToDoWidget({\n // Title defaults\n titleEnabled = true,\n titleText = \"To-Do\",\n titleFontSize = \"lg\",\n titleColor = \"foreground\",\n\n // Styling 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\n // Content defaults\n maxItems = 5,\n\n className,\n ...props\n}: ToDoWidgetProps): 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: todos = [], isLoading, isError } = useTodos();\n const updateTodo = useUpdateTodo();\n const { isPreview } = useWidgetPreviewContext();\n const [pendingIds, setPendingIds] = useState<Set<number>>(new Set());\n const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false);\n\n const toggleTodo = (id: number, completed: boolean) => {\n if (isPreview || pendingIds.has(id)) return;\n setPendingIds((prev) => new Set(prev).add(id));\n updateTodo.mutate(\n { id, completed },\n {\n onSettled: () =>\n setPendingIds((prev) => {\n const next = new Set(prev);\n next.delete(id);\n return next;\n }),\n },\n );\n };\n\n const activeTodos = todos.filter((todo) => !todo.completedAt);\n const todosToShow = activeTodos.slice(0, maxItems);\n const remainingCount = activeTodos.length - todosToShow.length;\n const isEmpty = activeTodos.length === 0;\n\n // Group todos by contactId so same-named contacts stay separate.\n const groupedTodos = todosToShow.reduce<\n {\n contactId: number | null;\n contactName: string | null;\n todos: typeof todosToShow;\n }[]\n >((groups, todo) => {\n const existing = groups.find((g) => g.contactId === todo.contactId);\n if (existing) {\n existing.todos.push(todo);\n } else {\n groups.push({\n contactId: todo.contactId,\n contactName: todo.contactName,\n todos: [todo],\n });\n }\n return groups;\n }, []);\n\n return (\n <div\n className={`overflow-hidden rounded-${borderRadius} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} bg-${backgroundColor} text-${textColor} p-${padding} ${className ?? \"\"}`}\n style={{ backgroundImage }}\n {...props}\n >\n {/* Header */}\n <div className=\"mb-3 flex items-center justify-between\">\n <div className=\"flex items-center gap-3\">\n {titleEnabled && titleText && (\n <h2\n className={`text-${titleFontSize} font-header font-bold text-${titleColor}`}\n >\n {titleText}\n </h2>\n )}\n </div>\n <div className=\"flex items-center gap-2\">\n {!isEmpty && !isLoading && (\n <span className={`text-2xl font-bold text-${accentColor}`}>\n {activeTodos.length}\n </span>\n )}\n <div\n className={`flex h-10 w-10 shrink-0 items-center justify-center`}\n >\n <ListChecks className={`h-5 w-5 text-${accentColor}-foreground`} />\n </div>\n </div>\n </div>\n\n {/* Loading state */}\n {isLoading ? (\n <div className=\"flex min-h-[120px] items-center justify-center\">\n <div className=\"h-6 w-6 animate-spin rounded-full border-2 border-current border-t-transparent\" />\n </div>\n ) : isError ? (\n /* Error state */\n <ErrorState />\n ) : isEmpty ? (\n /* Empty state */\n <div className=\"flex flex-col items-center justify-center gap-3 py-8\">\n <p className={`text-center text-${textColor}/60`}>\n You&apos;ve got nothing else To-Do!\n </p>\n {!isPreview && (\n <button\n type=\"button\"\n onClick={() => setIsCreateDialogOpen(true)}\n className={`inline-flex items-center gap-1.5 rounded-full bg-${accentColor} text-${accentColor}-foreground hover:bg-${accentColor}/90 px-4 py-1.5 text-xs font-semibold transition-colors`}\n >\n <Plus className=\"h-3.5 w-3.5\" aria-hidden=\"true\" />\n Add to-do\n </button>\n )}\n </div>\n ) : (\n /* Todo List */\n <>\n <div className=\"flex flex-col gap-3\">\n {groupedTodos.map((group) => (\n <div\n key={group.contactId ?? \"__unassigned__\"}\n className=\"flex flex-col\"\n >\n {group.contactName && (\n <div\n className={`mb-1 text-xs font-semibold tracking-wide uppercase text-${textColor}/60`}\n >\n {group.contactName}\n </div>\n )}\n {group.todos.map((todo, index) => (\n <div\n key={todo.id}\n className={`flex items-center gap-3 py-2 ${\n index !== group.todos.length - 1\n ? `border-b border-${textColor}/10`\n : \"\"\n }`}\n >\n <input\n type=\"checkbox\"\n className={`h-5 w-5 rounded-full border-2 border-${textColor}/30 bg-transparent not-disabled:cursor-pointer disabled:cursor-not-allowed disabled:opacity-60`}\n checked={!!todo.completedAt}\n disabled={isPreview || pendingIds.has(todo.id)}\n onChange={(event) =>\n toggleTodo(todo.id, event.target.checked)\n }\n />\n <span className=\"line-clamp-1 flex-1 text-sm\">\n {parseTaskBody(todo.body).title}\n </span>\n </div>\n ))}\n </div>\n ))}\n </div>\n\n {/* Footer */}\n <div className=\"mt-2 flex items-center justify-between\">\n {remainingCount > 0 && (\n <span className={`text-sm text-${textColor}/50 underline`}>\n {remainingCount} more task{remainingCount > 1 ? \"s\" : \"\"}\n </span>\n )}\n <div className=\"ml-auto\">\n <button\n type=\"button\"\n onClick={() => setIsCreateDialogOpen(true)}\n disabled={isPreview}\n aria-label=\"Add to-do\"\n className={`flex h-8 w-8 items-center justify-center rounded-full transition-colors not-disabled:cursor-pointer hover:bg-${textColor}/10 disabled:opacity-60`}\n >\n <Plus className={`h-5 w-5 text-${textColor}/50`} />\n </button>\n </div>\n </div>\n </>\n )}\n\n {!isPreview && (\n <CreateTodoDialog\n open={isCreateDialogOpen}\n onOpenChange={setIsCreateDialogOpen}\n />\n )}\n </div>\n );\n}\n\nexport const toDoWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"ToDoWidget\",\n displayName: \"To-Do 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 todo list\",\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 todo list\",\n defaultValue: \"To-Do\",\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 widget container\",\n defaultValue: \"background\",\n tab: \"styling\",\n group: \"Design\",\n },\n getColorField({\n key: \"textColor\",\n label: \"Text Color\",\n description: \"Default text color for todo 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 badge and icon\",\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 todo items to display\",\n min: 1,\n max: 20,\n step: 1,\n defaultValue: 5,\n tab: \"styling\",\n group: \"Design\",\n },\n getPaddingField({\n key: \"padding\",\n label: \"Padding\",\n description: \"Padding around the widget 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 widget 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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CL,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,KAAK;GACL,KAAK;GACL,MAAM;GACN,cAAc;GACd,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"}
package/dist/index.cjs CHANGED
@@ -1,12 +1,12 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_chunk = require("./chunk-9hOWP6kD.cjs");
3
- const require_FluidProvider = require("./FluidProvider-BIeO1i4r.cjs");
3
+ const require_FluidProvider = require("./FluidProvider-BQjPCP_2.cjs");
4
4
  const require_ScreenRenderer = require("./ScreenRenderer-D_eEc6S4.cjs");
5
5
  const require_PortalTenantClientProvider = require("./PortalTenantClientProvider-D-QE-YzB.cjs");
6
6
  require("./store-api-context-D1gZn22Z.cjs");
7
7
  require("./mysite-api-context-CilZcDS4.cjs");
8
8
  require("./countries-api-context-G-NW4BoH.cjs");
9
- require("./task-composer-form-DnRjQmkv.cjs");
9
+ require("./task-composer-form-D9KhWUI1.cjs");
10
10
  require("./registry-context-DJ5xiVnt.cjs");
11
11
  const require_WidgetInteractionContext = require("./WidgetInteractionContext-BhkusA95.cjs");
12
12
  const require_EmbedWidget = require("./EmbedWidget-C3ZJCcHD.cjs");
@@ -41,7 +41,7 @@ const require_RecentActivityWidget = require("./RecentActivityWidget-Cy9957Sq.cj
41
41
  const require_SeparatorWidget = require("./SeparatorWidget-LQ97EZd5.cjs");
42
42
  const require_SpacerWidget = require("./SpacerWidget-CYHjTF38.cjs");
43
43
  const require_TableWidget = require("./TableWidget-DfKZhS1Y.cjs");
44
- const require_ToDoWidget = require("./ToDoWidget-CImAWF3O.cjs");
44
+ const require_ToDoWidget = require("./ToDoWidget-DA_kLqvP.cjs");
45
45
  const require_VideoWidget = require("./VideoWidget-Ddt85ZZg.cjs");
46
46
  const require_SearchSort = require("./SearchSort-Bi9QWJQQ.cjs");
47
47
  const require_ShopWidget = require("./ShopWidget-BRx2rblg.cjs");
@@ -50,21 +50,21 @@ const require_CustomersScreen = require("./CustomersScreen-DtDU7jkB.cjs");
50
50
  const require_use_store = require("./use-store-D2S1FywW.cjs");
51
51
  const require_use_account = require("./use-account-BS0vV-sW.cjs");
52
52
  const require_AppNavigationContext = require("./AppNavigationContext-CDowN9gd.cjs");
53
- const require_MessagingScreen = require("./MessagingScreen-BBkqLkcx.cjs");
54
- require("./AddressAutocompleteInput-DkFs_leA.cjs");
53
+ const require_MessagingScreen = require("./MessagingScreen-XtYpo1RQ.cjs");
54
+ require("./AddressAutocompleteInput-DfwaaK0l.cjs");
55
55
  require("./Combobox-D9lqcqeg.cjs");
56
56
  require("./use-mysite-portal-BmrDScmS.cjs");
57
- const require_ProfileScreen = require("./ProfileScreen-C3zOvEhX.cjs");
58
- const require_SubscriptionsScreen = require("./SubscriptionsScreen-CyL91O4w.cjs");
57
+ const require_ProfileScreen = require("./ProfileScreen-Bhl7VJj1.cjs");
58
+ const require_SubscriptionsScreen = require("./SubscriptionsScreen-7ZH1s3eK.cjs");
59
59
  require("./dist-BPZPs7SF.cjs");
60
60
  require("./es-CtTr3tb5.cjs");
61
- const require_ContactsScreen = require("./ContactsScreen-Cf0ShCew.cjs");
61
+ const require_ContactsScreen = require("./ContactsScreen-Dm8b4SyY.cjs");
62
62
  require("./dist-C-U7FKrp.cjs");
63
- const require_OrdersScreen = require("./OrdersScreen-CZIlrF_M.cjs");
63
+ const require_OrdersScreen = require("./OrdersScreen-CgYMIsbc.cjs");
64
64
  const require_MySiteScreen = require("./MySiteScreen-D95Kir2t.cjs");
65
65
  require("./dist-DSufwDW6.cjs");
66
66
  const require_ShareablesScreen = require("./ShareablesScreen-HHPFsN7t.cjs");
67
- const require_ShopScreen = require("./ShopScreen-CjrEStJc.cjs");
67
+ const require_ShopScreen = require("./ShopScreen-CPTXTr7p.cjs");
68
68
  require("./UpgradeScreen-B8G83QW_.cjs");
69
69
  require("./AppDownloadScreen-Cn1gi2aM.cjs");
70
70
  let react = require("react");
@@ -2131,12 +2131,12 @@ function BuilderScreenViewImpl({ screen, className }) {
2131
2131
  const BuilderScreenView = (0, react.memo)(BuilderScreenViewImpl);
2132
2132
  //#endregion
2133
2133
  //#region src/shell/system-screen-map.ts
2134
- const ProfileScreen$1 = (0, react.lazy)(() => Promise.resolve().then(() => require("./ProfileScreen-CxOJ1D3H.cjs")).then((m) => ({ default: m.ProfileScreen })));
2135
- const OrdersScreen$1 = (0, react.lazy)(() => Promise.resolve().then(() => require("./OrdersScreen-BgcQi5Re.cjs")).then((m) => ({ default: m.OrdersScreen })));
2136
- const SubscriptionsScreen$1 = (0, react.lazy)(() => Promise.resolve().then(() => require("./SubscriptionsScreen-93eTwtFE.cjs")).then((m) => ({ default: m.SubscriptionsScreen })));
2137
- const MessagingScreen$1 = (0, react.lazy)(() => Promise.resolve().then(() => require("./MessagingScreen-CQNNI4RN.cjs")).then((m) => ({ default: m.MessagingScreen })));
2138
- const ContactsScreen$1 = (0, react.lazy)(() => Promise.resolve().then(() => require("./ContactsScreen-DiGrOlwx.cjs")).then((m) => ({ default: m.ContactsScreen })));
2139
- const ShopScreen$1 = (0, react.lazy)(() => Promise.resolve().then(() => require("./ShopScreen-DM9jxl3w.cjs")).then((m) => ({ default: m.ShopScreen })));
2134
+ const ProfileScreen$1 = (0, react.lazy)(() => Promise.resolve().then(() => require("./ProfileScreen-DsYyPXQj.cjs")).then((m) => ({ default: m.ProfileScreen })));
2135
+ const OrdersScreen$1 = (0, react.lazy)(() => Promise.resolve().then(() => require("./OrdersScreen-BAvQ38bA.cjs")).then((m) => ({ default: m.OrdersScreen })));
2136
+ const SubscriptionsScreen$1 = (0, react.lazy)(() => Promise.resolve().then(() => require("./SubscriptionsScreen-CVHJ08si.cjs")).then((m) => ({ default: m.SubscriptionsScreen })));
2137
+ const MessagingScreen$1 = (0, react.lazy)(() => Promise.resolve().then(() => require("./MessagingScreen-CqxyLDp0.cjs")).then((m) => ({ default: m.MessagingScreen })));
2138
+ const ContactsScreen$1 = (0, react.lazy)(() => Promise.resolve().then(() => require("./ContactsScreen-BYrRJ55W.cjs")).then((m) => ({ default: m.ContactsScreen })));
2139
+ const ShopScreen$1 = (0, react.lazy)(() => Promise.resolve().then(() => require("./ShopScreen-DVLxDFpf.cjs")).then((m) => ({ default: m.ShopScreen })));
2140
2140
  const CustomersScreen$1 = (0, react.lazy)(() => Promise.resolve().then(() => require("./CustomersScreen-DtDU7jkB.cjs")).then((n) => n.CustomersScreen_exports).then((m) => ({ default: m.CustomersScreen })));
2141
2141
  const ShareablesScreen$1 = (0, react.lazy)(() => Promise.resolve().then(() => require("./ShareablesScreen-D91gLWOB.cjs")).then((m) => ({ default: m.ShareablesScreen })));
2142
2142
  const MySiteScreen$1 = (0, react.lazy)(() => Promise.resolve().then(() => require("./MySiteScreen-f8zAVWT-.cjs")).then((m) => ({ default: m.MySiteScreen })));
@@ -4041,15 +4041,15 @@ zod.z.object({
4041
4041
  //#endregion
4042
4042
  //#region src/screens/index.ts
4043
4043
  const screenPropertySchemas = {
4044
- ProfileScreen: () => Promise.resolve().then(() => require("./ProfileScreen-CxOJ1D3H.cjs")).then((m) => m.profileScreenPropertySchema),
4045
- MessagingScreen: () => Promise.resolve().then(() => require("./MessagingScreen-CQNNI4RN.cjs")).then((m) => m.messagingScreenPropertySchema),
4046
- ContactsScreen: () => Promise.resolve().then(() => require("./ContactsScreen-DiGrOlwx.cjs")).then((m) => m.contactsScreenPropertySchema),
4047
- OrdersScreen: () => Promise.resolve().then(() => require("./OrdersScreen-BgcQi5Re.cjs")).then((m) => m.ordersScreenPropertySchema),
4048
- SubscriptionsScreen: () => Promise.resolve().then(() => require("./SubscriptionsScreen-93eTwtFE.cjs")).then((m) => m.subscriptionsScreenPropertySchema),
4044
+ ProfileScreen: () => Promise.resolve().then(() => require("./ProfileScreen-DsYyPXQj.cjs")).then((m) => m.profileScreenPropertySchema),
4045
+ MessagingScreen: () => Promise.resolve().then(() => require("./MessagingScreen-CqxyLDp0.cjs")).then((m) => m.messagingScreenPropertySchema),
4046
+ ContactsScreen: () => Promise.resolve().then(() => require("./ContactsScreen-BYrRJ55W.cjs")).then((m) => m.contactsScreenPropertySchema),
4047
+ OrdersScreen: () => Promise.resolve().then(() => require("./OrdersScreen-BAvQ38bA.cjs")).then((m) => m.ordersScreenPropertySchema),
4048
+ SubscriptionsScreen: () => Promise.resolve().then(() => require("./SubscriptionsScreen-CVHJ08si.cjs")).then((m) => m.subscriptionsScreenPropertySchema),
4049
4049
  CustomersScreen: () => Promise.resolve().then(() => require("./CustomersScreen-DtDU7jkB.cjs")).then((n) => n.CustomersScreen_exports).then((m) => m.customersScreenPropertySchema),
4050
4050
  MySiteScreen: () => Promise.resolve().then(() => require("./MySiteScreen-f8zAVWT-.cjs")).then((m) => m.mySiteScreenPropertySchema),
4051
4051
  ShareablesScreen: () => Promise.resolve().then(() => require("./ShareablesScreen-D91gLWOB.cjs")).then((m) => m.shareablesScreenPropertySchema),
4052
- ShopScreen: () => Promise.resolve().then(() => require("./ShopScreen-DM9jxl3w.cjs")).then((m) => m.shopScreenPropertySchema),
4052
+ ShopScreen: () => Promise.resolve().then(() => require("./ShopScreen-DVLxDFpf.cjs")).then((m) => m.shopScreenPropertySchema),
4053
4053
  UpgradeScreen: () => Promise.resolve().then(() => require("./UpgradeScreen-ayWak9W9.cjs")).then((m) => m.upgradeScreenPropertySchema),
4054
4054
  AppDownloadScreen: () => Promise.resolve().then(() => require("./AppDownloadScreen-Cn1gi2aM.cjs")).then((n) => n.AppDownloadScreen_exports).then((m) => m.appDownloadScreenPropertySchema)
4055
4055
  };
package/dist/index.mjs CHANGED
@@ -1,10 +1,10 @@
1
1
  import { $ as products_search, Q as products_media_list, X as product_by_visits, Y as product_by_shares, Z as products_list, et as products_show, n as usePortalTenantClient } from "./PortalTenantClientProvider-CqW6ae2M.mjs";
2
- import { A as mergeDarkOverrides, C as DEFAULT_SPACING, D as generateThemeCSS, E as getDefaultThemeDefinition, F as RADIUS_KEYS, H as useAppDefinitionApi, I as SEMANTIC_COLOR_NAMES, M as resolveTheme, N as FONT_FAMILY_KEYS, O as deriveDarkVariant, P as FONT_SIZE_KEYS, S as DEFAULT_RADII, T as DEFAULT_THEME_NAME, U as createPersister, W as deleteDatabase, _ as deserialiseTheme, a as widgetPropertySchemas, b as DEFAULT_FONT_FAMILIES, c as createWidgetRegistry, d as applyTheme, f as removeAllThemes, g as transformThemes, h as getActiveThemeId, i as DEFAULT_SDK_WIDGET_REGISTRY, j as parseColor, k as getForegroundColor, l as FluidThemeProvider, m as buildThemeDefinition, n as useFluidContext, o as createScreen, p as removeTheme, r as SUPPORTED_LANGUAGES, s as createWidgetFromShareable, t as FluidProvider, u as useThemeContext, v as serialiseTheme, w as DEFAULT_THEME_ID, x as DEFAULT_FONT_SIZES, y as DEFAULT_COLORS } from "./FluidProvider-LqejfvZ-.mjs";
2
+ import { A as mergeDarkOverrides, C as DEFAULT_SPACING, D as generateThemeCSS, E as getDefaultThemeDefinition, F as RADIUS_KEYS, H as useAppDefinitionApi, I as SEMANTIC_COLOR_NAMES, M as resolveTheme, N as FONT_FAMILY_KEYS, O as deriveDarkVariant, P as FONT_SIZE_KEYS, S as DEFAULT_RADII, T as DEFAULT_THEME_NAME, U as createPersister, W as deleteDatabase, _ as deserialiseTheme, a as widgetPropertySchemas, b as DEFAULT_FONT_FAMILIES, c as createWidgetRegistry, d as applyTheme, f as removeAllThemes, g as transformThemes, h as getActiveThemeId, i as DEFAULT_SDK_WIDGET_REGISTRY, j as parseColor, k as getForegroundColor, l as FluidThemeProvider, m as buildThemeDefinition, n as useFluidContext, o as createScreen, p as removeTheme, r as SUPPORTED_LANGUAGES, s as createWidgetFromShareable, t as FluidProvider, u as useThemeContext, v as serialiseTheme, w as DEFAULT_THEME_ID, x as DEFAULT_FONT_SIZES, y as DEFAULT_COLORS } from "./FluidProvider-DU-sFsZV.mjs";
3
3
  import { a as assertNever, i as assertDefined, n as DataAwareWidget, o as isWidgetType, r as WIDGET_TYPE_NAMES, s as isWidgetTypeName, u as useRegistry } from "./ScreenRenderer-BszshjZg.mjs";
4
4
  import "./store-api-context-DViwxyG4.mjs";
5
5
  import "./mysite-api-context-kUTM3GNG.mjs";
6
6
  import "./countries-api-context-DScC_39w.mjs";
7
- import "./task-composer-form-ChwUNk1I.mjs";
7
+ import "./task-composer-form-CHyQZUCo.mjs";
8
8
  import "./registry-context-BKvTiuXB.mjs";
9
9
  import { t as WidgetInteractionProvider } from "./WidgetInteractionContext-BWH7njU7.mjs";
10
10
  import { a as useRepUser, i as RepUserProvider, r as embedWidgetPropertySchema, t as EmbedWidget } from "./EmbedWidget-Be16VTGq.mjs";
@@ -25,8 +25,8 @@ import "./MediaRenderer-CLmBOrvK.mjs";
25
25
  import { r as carouselWidgetPropertySchema, t as CarouselWidget } from "./CarouselWidget-2fu0NYxd.mjs";
26
26
  import { r as catchUpWidgetPropertySchema, t as CatchUpWidget } from "./CatchUpWidget-DxeBgueZ.mjs";
27
27
  import { Dt as CardHeader, Et as CardFooter, Ot as CardTitle, St as Card, Tt as CardDescription, at as Popover, ct as PopoverTrigger, gt as CollapsibleTrigger, h as Skeleton$1, ht as CollapsibleContent, kn as cn$1, mt as Collapsible, p as Toaster, st as PopoverContent, wn as Button } from "./src-DC5QoBhR.mjs";
28
- import { a as useMessagingAuth, i as useMessagingConfig, n as messagingScreenPropertySchema, r as createFluidFileUploader, t as MessagingScreen } from "./MessagingScreen-BRcAo9ux.mjs";
29
- import { n as subscriptionsScreenPropertySchema, t as SubscriptionsScreen } from "./SubscriptionsScreen-u_q5j115.mjs";
28
+ import { a as useMessagingAuth, i as useMessagingConfig, n as messagingScreenPropertySchema, r as createFluidFileUploader, t as MessagingScreen } from "./MessagingScreen-D33O66bU.mjs";
29
+ import { n as subscriptionsScreenPropertySchema, t as SubscriptionsScreen } from "./SubscriptionsScreen-BcIUZf50.mjs";
30
30
  import { r as chartWidgetPropertySchema, t as ChartWidget } from "./ChartWidget-DfQQU2w2.mjs";
31
31
  import { r as containerWidgetPropertySchema, t as ContainerWidget } from "./ContainerWidget-CPacdtRy.mjs";
32
32
  import { r as imageWidgetPropertySchema, t as ImageWidget } from "./ImageWidget-BOFNCjT1.mjs";
@@ -41,7 +41,7 @@ import { r as recentActivityWidgetPropertySchema, t as RecentActivityWidget } fr
41
41
  import { r as separatorWidgetPropertySchema, t as SeparatorWidget } from "./SeparatorWidget-DugZ8ukt.mjs";
42
42
  import { r as spacerWidgetPropertySchema, t as SpacerWidget } from "./SpacerWidget-CCpCGUjM.mjs";
43
43
  import { r as tableWidgetPropertySchema, t as TableWidget } from "./TableWidget-Cef29Su9.mjs";
44
- import { r as toDoWidgetPropertySchema, t as ToDoWidget } from "./ToDoWidget-sLWwJJ_g.mjs";
44
+ import { r as toDoWidgetPropertySchema, t as ToDoWidget } from "./ToDoWidget-CShnzkw4.mjs";
45
45
  import { r as videoWidgetPropertySchema, t as VideoWidget } from "./VideoWidget-CjOhc8KW.mjs";
46
46
  import { o as PortalProductsCoreProvider } from "./SearchSort-BeYMXXIi.mjs";
47
47
  import { o as ShopTranslationProvider } from "./ShopWidget-BKTYcwx_.mjs";
@@ -50,19 +50,19 @@ import { a as ShellTranslationContext, i as CoreScreenPlaceholder, o as ShellTra
50
50
  import { t as useStore } from "./use-store-fLSf5hUc.mjs";
51
51
  import { t as useAccount } from "./use-account-BqNRv6m6.mjs";
52
52
  import { n as useAppNavigation, t as AppNavigationProvider } from "./AppNavigationContext-DNomMUij.mjs";
53
- import "./AddressAutocompleteInput-BpbBARKk.mjs";
53
+ import "./AddressAutocompleteInput-CYWqjVql.mjs";
54
54
  import "./Combobox-B-rNFLTr.mjs";
55
55
  import "./use-mysite-portal-DyB9666K.mjs";
56
- import { n as profileScreenPropertySchema, t as ProfileScreen } from "./ProfileScreen-Chk8YkMW.mjs";
56
+ import { n as profileScreenPropertySchema, t as ProfileScreen } from "./ProfileScreen--fDK5YsG.mjs";
57
57
  import "./dist-PbA1vxAz.mjs";
58
58
  import "./es-C5E79_gn.mjs";
59
- import { r as contactsScreenPropertySchema, t as ContactsScreen } from "./ContactsScreen-FELUSAZ_.mjs";
59
+ import { r as contactsScreenPropertySchema, t as ContactsScreen } from "./ContactsScreen-D3_LQj6x.mjs";
60
60
  import "./dist-o2cjwzIa.mjs";
61
- import { n as ordersScreenPropertySchema, t as OrdersScreen } from "./OrdersScreen-Do7YtBiu.mjs";
61
+ import { n as ordersScreenPropertySchema, t as OrdersScreen } from "./OrdersScreen-BIjN8-_y.mjs";
62
62
  import { r as mySiteScreenPropertySchema, t as MySiteScreen } from "./MySiteScreen-D57JrpWL.mjs";
63
63
  import "./sortable.esm-BdhSkRKn.mjs";
64
64
  import { n as shareablesScreenPropertySchema, t as ShareablesScreen } from "./ShareablesScreen-BFQDn8Kt.mjs";
65
- import { n as shopScreenPropertySchema, t as ShopScreen } from "./ShopScreen-uOMi-jFD.mjs";
65
+ import { n as shopScreenPropertySchema, t as ShopScreen } from "./ShopScreen-B4_2T5Nd.mjs";
66
66
  import "./UpgradeScreen-3tMWotmq.mjs";
67
67
  import "./AppDownloadScreen-CUSgeG2w.mjs";
68
68
  import * as React$1 from "react";
@@ -2129,12 +2129,12 @@ function BuilderScreenViewImpl({ screen, className }) {
2129
2129
  const BuilderScreenView = memo(BuilderScreenViewImpl);
2130
2130
  //#endregion
2131
2131
  //#region src/shell/system-screen-map.ts
2132
- const ProfileScreen$1 = lazy(() => import("./ProfileScreen-DZFMc4E9.mjs").then((m) => ({ default: m.ProfileScreen })));
2133
- const OrdersScreen$1 = lazy(() => import("./OrdersScreen-DISwVljS.mjs").then((m) => ({ default: m.OrdersScreen })));
2134
- const SubscriptionsScreen$1 = lazy(() => import("./SubscriptionsScreen-8cPR9vpX.mjs").then((m) => ({ default: m.SubscriptionsScreen })));
2135
- const MessagingScreen$1 = lazy(() => import("./MessagingScreen-y3AG96Gi.mjs").then((m) => ({ default: m.MessagingScreen })));
2136
- const ContactsScreen$1 = lazy(() => import("./ContactsScreen-FELUSAZ_.mjs").then((n) => n.n).then((m) => ({ default: m.ContactsScreen })));
2137
- const ShopScreen$1 = lazy(() => import("./ShopScreen-C4vXayCp.mjs").then((m) => ({ default: m.ShopScreen })));
2132
+ const ProfileScreen$1 = lazy(() => import("./ProfileScreen-BIb54IBH.mjs").then((m) => ({ default: m.ProfileScreen })));
2133
+ const OrdersScreen$1 = lazy(() => import("./OrdersScreen-BmwgXoqb.mjs").then((m) => ({ default: m.OrdersScreen })));
2134
+ const SubscriptionsScreen$1 = lazy(() => import("./SubscriptionsScreen-CwseYMy5.mjs").then((m) => ({ default: m.SubscriptionsScreen })));
2135
+ const MessagingScreen$1 = lazy(() => import("./MessagingScreen-a58Uccvz.mjs").then((m) => ({ default: m.MessagingScreen })));
2136
+ const ContactsScreen$1 = lazy(() => import("./ContactsScreen-D3_LQj6x.mjs").then((n) => n.n).then((m) => ({ default: m.ContactsScreen })));
2137
+ const ShopScreen$1 = lazy(() => import("./ShopScreen-CvZGzOUd.mjs").then((m) => ({ default: m.ShopScreen })));
2138
2138
  const CustomersScreen$1 = lazy(() => import("./CustomersScreen-D4KRUhQz.mjs").then((n) => n.n).then((m) => ({ default: m.CustomersScreen })));
2139
2139
  const ShareablesScreen$1 = lazy(() => import("./ShareablesScreen-Bex7UIm5.mjs").then((m) => ({ default: m.ShareablesScreen })));
2140
2140
  const MySiteScreen$1 = lazy(() => import("./MySiteScreen-D57JrpWL.mjs").then((n) => n.n).then((m) => ({ default: m.MySiteScreen })));
@@ -4039,15 +4039,15 @@ z.object({
4039
4039
  //#endregion
4040
4040
  //#region src/screens/index.ts
4041
4041
  const screenPropertySchemas = {
4042
- ProfileScreen: () => import("./ProfileScreen-DZFMc4E9.mjs").then((m) => m.profileScreenPropertySchema),
4043
- MessagingScreen: () => import("./MessagingScreen-y3AG96Gi.mjs").then((m) => m.messagingScreenPropertySchema),
4044
- ContactsScreen: () => import("./ContactsScreen-FELUSAZ_.mjs").then((n) => n.n).then((m) => m.contactsScreenPropertySchema),
4045
- OrdersScreen: () => import("./OrdersScreen-DISwVljS.mjs").then((m) => m.ordersScreenPropertySchema),
4046
- SubscriptionsScreen: () => import("./SubscriptionsScreen-8cPR9vpX.mjs").then((m) => m.subscriptionsScreenPropertySchema),
4042
+ ProfileScreen: () => import("./ProfileScreen-BIb54IBH.mjs").then((m) => m.profileScreenPropertySchema),
4043
+ MessagingScreen: () => import("./MessagingScreen-a58Uccvz.mjs").then((m) => m.messagingScreenPropertySchema),
4044
+ ContactsScreen: () => import("./ContactsScreen-D3_LQj6x.mjs").then((n) => n.n).then((m) => m.contactsScreenPropertySchema),
4045
+ OrdersScreen: () => import("./OrdersScreen-BmwgXoqb.mjs").then((m) => m.ordersScreenPropertySchema),
4046
+ SubscriptionsScreen: () => import("./SubscriptionsScreen-CwseYMy5.mjs").then((m) => m.subscriptionsScreenPropertySchema),
4047
4047
  CustomersScreen: () => import("./CustomersScreen-D4KRUhQz.mjs").then((n) => n.n).then((m) => m.customersScreenPropertySchema),
4048
4048
  MySiteScreen: () => import("./MySiteScreen-D57JrpWL.mjs").then((n) => n.n).then((m) => m.mySiteScreenPropertySchema),
4049
4049
  ShareablesScreen: () => import("./ShareablesScreen-Bex7UIm5.mjs").then((m) => m.shareablesScreenPropertySchema),
4050
- ShopScreen: () => import("./ShopScreen-C4vXayCp.mjs").then((m) => m.shopScreenPropertySchema),
4050
+ ShopScreen: () => import("./ShopScreen-CvZGzOUd.mjs").then((m) => m.shopScreenPropertySchema),
4051
4051
  UpgradeScreen: () => import("./UpgradeScreen-3tMWotmq.mjs").then((n) => n.t).then((m) => m.upgradeScreenPropertySchema),
4052
4052
  AppDownloadScreen: () => import("./AppDownloadScreen-CUSgeG2w.mjs").then((n) => n.t).then((m) => m.appDownloadScreenPropertySchema)
4053
4053
  };
@@ -243,10 +243,11 @@ function useCreateContactTask(contactId, options) {
243
243
  options?.onSuccess?.();
244
244
  },
245
245
  onError: (error) => {
246
+ const description = parseApiErrors(error);
246
247
  fluidToast({
247
248
  title: "Failed to create task",
248
249
  type: "error",
249
- description: parseApiErrors(error)
250
+ ...description ? { description } : {}
250
251
  });
251
252
  }
252
253
  });
@@ -360,4 +361,4 @@ function TaskComposerForm({ contactId, onDone, onClose, autoFocus = true }) {
360
361
  //#endregion
361
362
  export { contactsKeys as a, useContactsTranslation as c, useGroupsApi as d, useNotesApi as f, CONTACTS_QUERY_KEYS as i, ContactsApiProvider as l, parseApiErrors as m, startOfLocalDay as n, parseTaskBody as o, useTasksApi as p, useInfiniteContacts as r, ContactsTranslationProvider as s, TaskComposerForm as t, useContactsCrud as u };
362
363
 
363
- //# sourceMappingURL=task-composer-form-ChwUNk1I.mjs.map
364
+ //# sourceMappingURL=task-composer-form-CHyQZUCo.mjs.map