@carlonicora/nextjs-jsonapi 1.116.0 → 1.117.1

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 (52) hide show
  1. package/dist/{AssistantMessageInterface-Ca0G0vZw.d.mts → AssistantMessageInterface-DH1QwtC_.d.mts} +1 -0
  2. package/dist/{AssistantMessageInterface-DEZ5AnVl.d.ts → AssistantMessageInterface-giWvsOrX.d.ts} +1 -0
  3. package/dist/{BlockNoteEditor-R6U4PCQ7.js → BlockNoteEditor-CEWZCORH.js} +9 -9
  4. package/dist/{BlockNoteEditor-R6U4PCQ7.js.map → BlockNoteEditor-CEWZCORH.js.map} +1 -1
  5. package/dist/{BlockNoteEditor-RFRK3STN.mjs → BlockNoteEditor-K4T6QOJO.mjs} +2 -2
  6. package/dist/billing/index.js +299 -299
  7. package/dist/billing/index.mjs +1 -1
  8. package/dist/{chunk-SPRFCAQI.js → chunk-56QAXZKI.js} +470 -328
  9. package/dist/chunk-56QAXZKI.js.map +1 -0
  10. package/dist/{chunk-RKUUGCYB.mjs → chunk-6D4GJHLK.mjs} +526 -384
  11. package/dist/chunk-6D4GJHLK.mjs.map +1 -0
  12. package/dist/client/index.js +2 -2
  13. package/dist/client/index.mjs +1 -1
  14. package/dist/components/index.d.mts +69 -22
  15. package/dist/components/index.d.ts +69 -22
  16. package/dist/components/index.js +4 -2
  17. package/dist/components/index.js.map +1 -1
  18. package/dist/components/index.mjs +3 -1
  19. package/dist/contexts/index.d.mts +1 -1
  20. package/dist/contexts/index.d.ts +1 -1
  21. package/dist/contexts/index.js +2 -2
  22. package/dist/contexts/index.mjs +1 -1
  23. package/dist/core/index.d.mts +2 -2
  24. package/dist/core/index.d.ts +2 -2
  25. package/dist/features/help/index.js +30 -30
  26. package/dist/features/help/index.mjs +1 -1
  27. package/dist/index.d.mts +1 -1
  28. package/dist/index.d.ts +1 -1
  29. package/package.json +1 -1
  30. package/src/components/forms/CommonDeleter.tsx +49 -18
  31. package/src/components/forms/CommonEditorButtons.tsx +4 -2
  32. package/src/components/forms/CommonEditorHeader.tsx +20 -14
  33. package/src/components/forms/CommonEditorTrigger.tsx +18 -4
  34. package/src/components/forms/DateRangeSelector.tsx +55 -19
  35. package/src/components/forms/EditorSheet.tsx +36 -9
  36. package/src/components/forms/FileUploader.tsx +51 -21
  37. package/src/components/forms/FormDate.tsx +6 -2
  38. package/src/components/forms/FormDateTime.tsx +11 -2
  39. package/src/components/forms/FormFieldWrapper.tsx +3 -1
  40. package/src/components/forms/FormInput.tsx +3 -1
  41. package/src/components/forms/FormPassword.tsx +10 -1
  42. package/src/components/forms/FormPlaceAutocomplete.tsx +8 -3
  43. package/src/components/forms/FormSelect.tsx +3 -0
  44. package/src/components/forms/FormSlider.tsx +3 -1
  45. package/src/components/forms/FormTextarea.tsx +15 -1
  46. package/src/components/navigations/Breadcrumb.tsx +31 -5
  47. package/src/hooks/useSocket.ts +12 -1
  48. package/src/interfaces/breadcrumb.item.data.interface.ts +1 -0
  49. package/src/shadcnui/ui/badge.tsx +15 -0
  50. package/dist/chunk-RKUUGCYB.mjs.map +0 -1
  51. package/dist/chunk-SPRFCAQI.js.map +0 -1
  52. /package/dist/{BlockNoteEditor-RFRK3STN.mjs.map → BlockNoteEditor-K4T6QOJO.mjs.map} +0 -0
@@ -21,7 +21,7 @@ var _chunkYBZVWLPHjs = require('../../chunk-YBZVWLPH.js');
21
21
 
22
22
 
23
23
 
24
- var _chunkSPRFCAQIjs = require('../../chunk-SPRFCAQI.js');
24
+ var _chunk56QAXZKIjs = require('../../chunk-56QAXZKI.js');
25
25
 
26
26
 
27
27
  var _chunk6KLR3WJQjs = require('../../chunk-6KLR3WJQ.js');
@@ -73,29 +73,29 @@ var _lucidereact = require('lucide-react');
73
73
 
74
74
 
75
75
  function HelpAssistantSheet({ open, onOpenChange }) {
76
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkSPRFCAQIjs.Sheet, { open, onOpenChange, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
77
- _chunkSPRFCAQIjs.SheetContent,
76
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk56QAXZKIjs.Sheet, { open, onOpenChange, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
77
+ _chunk56QAXZKIjs.SheetContent,
78
78
  {
79
79
  side: "right",
80
80
  className: "flex w-full flex-col data-[side=right]:sm:max-w-2xl data-[side=right]:lg:max-w-3xl",
81
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkSPRFCAQIjs.AssistantProvider, { manageUrl: false, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, HelpAssistantSheetBody, {}) })
81
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk56QAXZKIjs.AssistantProvider, { manageUrl: false, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, HelpAssistantSheetBody, {}) })
82
82
  }
83
83
  ) });
84
84
  }
85
85
  _chunk7QVYU63Ejs.__name.call(void 0, HelpAssistantSheet, "HelpAssistantSheet");
86
86
  function HelpAssistantSheetBody() {
87
87
  const t = _nextintl.useTranslations.call(void 0, );
88
- const ctx = _chunkSPRFCAQIjs.useAssistantContext.call(void 0, );
88
+ const ctx = _chunk56QAXZKIjs.useAssistantContext.call(void 0, );
89
89
  const showThread = !!ctx.assistant || ctx.sending || ctx.messages.length > 0;
90
90
  const send = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, (content) => ctx.sendMessage(content, { howToMode: true }), "send");
91
91
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
92
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkSPRFCAQIjs.SheetHeader, { children: [
93
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkSPRFCAQIjs.SheetTitle, { children: t("help.askAi.sheet.title") }),
94
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkSPRFCAQIjs.SheetDescription, { children: t("help.askAi.sheet.subtitle") })
92
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunk56QAXZKIjs.SheetHeader, { children: [
93
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk56QAXZKIjs.SheetTitle, { children: t("help.askAi.sheet.title") }),
94
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk56QAXZKIjs.SheetDescription, { children: t("help.askAi.sheet.subtitle") })
95
95
  ] }),
96
- !showThread ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkSPRFCAQIjs.AssistantEmptyState, { onSend: send }) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
96
+ !showThread ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk56QAXZKIjs.AssistantEmptyState, { onSend: send }) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
97
97
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
98
- _chunkSPRFCAQIjs.AssistantThread,
98
+ _chunk56QAXZKIjs.AssistantThread,
99
99
  {
100
100
  messages: ctx.messages,
101
101
  sending: ctx.sending,
@@ -105,7 +105,7 @@ function HelpAssistantSheetBody() {
105
105
  onRetry: ctx.retrySend
106
106
  }
107
107
  ),
108
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkSPRFCAQIjs.AssistantComposer, { onSend: send, disabled: ctx.sending })
108
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk56QAXZKIjs.AssistantComposer, { onSend: send, disabled: ctx.sending })
109
109
  ] })
110
110
  ] });
111
111
  }
@@ -115,20 +115,20 @@ _chunk7QVYU63Ejs.__name.call(void 0, HelpAssistantSheetBody, "HelpAssistantSheet
115
115
 
116
116
  function HelpAskAi() {
117
117
  const t = _nextintl.useTranslations.call(void 0, );
118
- const { currentUser } = _chunkSPRFCAQIjs.useCurrentUserContext.call(void 0, );
118
+ const { currentUser } = _chunk56QAXZKIjs.useCurrentUserContext.call(void 0, );
119
119
  const [open, setOpen] = _react.useState.call(void 0, false);
120
120
  const disabled = !currentUser;
121
121
  if (disabled) {
122
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkSPRFCAQIjs.Tooltip, { children: [
123
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkSPRFCAQIjs.TooltipTrigger, { render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkSPRFCAQIjs.Button, { variant: "outline", size: "sm", disabled: true }), children: [
122
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunk56QAXZKIjs.Tooltip, { children: [
123
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunk56QAXZKIjs.TooltipTrigger, { render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk56QAXZKIjs.Button, { variant: "outline", size: "sm", disabled: true }), children: [
124
124
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.SparklesIcon, { className: "h-4 w-4" }),
125
125
  t("help.askAi.button")
126
126
  ] }),
127
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkSPRFCAQIjs.TooltipContent, { children: t("help.askAi.loginTooltip") })
127
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk56QAXZKIjs.TooltipContent, { children: t("help.askAi.loginTooltip") })
128
128
  ] });
129
129
  }
130
130
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
131
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkSPRFCAQIjs.Button, { variant: "outline", size: "sm", onClick: () => setOpen(true), children: [
131
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunk56QAXZKIjs.Button, { variant: "outline", size: "sm", onClick: () => setOpen(true), children: [
132
132
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.SparklesIcon, { className: "h-4 w-4" }),
133
133
  t("help.askAi.button")
134
134
  ] }),
@@ -141,7 +141,7 @@ _chunk7QVYU63Ejs.__name.call(void 0, HelpAskAi, "HelpAskAi");
141
141
 
142
142
  function HelpHeader() {
143
143
  const t = _nextintl.useTranslations.call(void 0, );
144
- const { currentUser } = _chunkSPRFCAQIjs.useCurrentUserContext.call(void 0, );
144
+ const { currentUser } = _chunk56QAXZKIjs.useCurrentUserContext.call(void 0, );
145
145
  const { brand } = useHelp();
146
146
  const logo = _optionalChain([brand, 'optionalAccess', _ => _.logo]);
147
147
  const label = _nullishCoalesce(_optionalChain([brand, 'optionalAccess', _2 => _2.label]), () => ( "Help"));
@@ -157,7 +157,7 @@ function HelpHeader() {
157
157
  ] }),
158
158
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-2", children: [
159
159
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, HelpAskAi, {}),
160
- currentUser ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkSPRFCAQIjs.Button, { render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _link2.default, { href: appHref }), nativeButton: false, variant: "outline", size: "sm", children: t("help.header.openApp") }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkSPRFCAQIjs.Button, { render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _link2.default, { href: "/login" }), nativeButton: false, variant: "outline", size: "sm", children: t("help.header.login") })
160
+ currentUser ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk56QAXZKIjs.Button, { render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _link2.default, { href: appHref }), nativeButton: false, variant: "outline", size: "sm", children: t("help.header.openApp") }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk56QAXZKIjs.Button, { render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _link2.default, { href: "/login" }), nativeButton: false, variant: "outline", size: "sm", children: t("help.header.login") })
161
161
  ] })
162
162
  ] });
163
163
  }
@@ -199,7 +199,7 @@ _chunk7QVYU63Ejs.__name.call(void 0, useHelpFilter, "useHelpFilter");
199
199
 
200
200
  function HelpSideNav() {
201
201
  const t = _nextintl.useTranslations.call(void 0, );
202
- const generateUrl = _chunkSPRFCAQIjs.usePageUrlGenerator.call(void 0, );
202
+ const generateUrl = _chunk56QAXZKIjs.usePageUrlGenerator.call(void 0, );
203
203
  const pathname = _navigation.usePathname.call(void 0, );
204
204
  const [articles, setArticles] = _react.useState.call(void 0, []);
205
205
  _react.useEffect.call(void 0, () => {
@@ -280,7 +280,7 @@ _chunk7QVYU63Ejs.__name.call(void 0, HelpSideNav, "HelpSideNav");
280
280
  function HelpArticleBody(props) {
281
281
  const t = _nextintl.useTranslations.call(void 0, );
282
282
  const format = _nextintl.useFormatter.call(void 0, );
283
- const generateUrl = _chunkSPRFCAQIjs.usePageUrlGenerator.call(void 0, );
283
+ const generateUrl = _chunk56QAXZKIjs.usePageUrlGenerator.call(void 0, );
284
284
  const { howToType, title, summary, updatedAt, prev, next, children } = props;
285
285
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "article", { className: "prose dark:prose-invert max-w-none", children: [
286
286
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "nav", { className: "text-muted-foreground mb-2 text-xs", children: [
@@ -358,7 +358,7 @@ _chunk7QVYU63Ejs.__name.call(void 0, HelpTOC, "HelpTOC");
358
358
 
359
359
  function HelpHint({ contextKey }) {
360
360
  const t = _nextintl.useTranslations.call(void 0, );
361
- const generateUrl = _chunkSPRFCAQIjs.usePageUrlGenerator.call(void 0, );
361
+ const generateUrl = _chunk56QAXZKIjs.usePageUrlGenerator.call(void 0, );
362
362
  const [open, setOpen] = _react.useState.call(void 0, false);
363
363
  const [picked, setPicked] = _react.useState.call(void 0, null);
364
364
  const [articles, setArticles] = _react.useState.call(void 0, []);
@@ -376,7 +376,7 @@ function HelpHint({ contextKey }) {
376
376
  if (matches.length === 0) return null;
377
377
  const active = _nullishCoalesce(picked, () => ( (matches.length === 1 ? matches[0] : null)));
378
378
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
379
- _chunkSPRFCAQIjs.Sheet,
379
+ _chunk56QAXZKIjs.Sheet,
380
380
  {
381
381
  open,
382
382
  onOpenChange: (o) => {
@@ -384,11 +384,11 @@ function HelpHint({ contextKey }) {
384
384
  if (!o) setPicked(null);
385
385
  },
386
386
  children: [
387
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkSPRFCAQIjs.SheetTrigger, { render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkSPRFCAQIjs.Button, { variant: "ghost", size: "icon-sm", "aria-label": t("help.hint.trigger") }), children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.HelpCircleIcon, { className: "h-4 w-4" }) }),
388
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkSPRFCAQIjs.SheetContent, { side: "right", className: "w-full max-w-md sm:max-w-lg", children: [
389
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkSPRFCAQIjs.SheetHeader, { children: [
390
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkSPRFCAQIjs.SheetTitle, { children: active ? active.name : t("help.hint.pickArticle") }),
391
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkSPRFCAQIjs.SheetDescription, { children: _nullishCoalesce(_optionalChain([active, 'optionalAccess', _4 => _4.summary]), () => ( "")) })
387
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk56QAXZKIjs.SheetTrigger, { render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk56QAXZKIjs.Button, { variant: "ghost", size: "icon-sm", "aria-label": t("help.hint.trigger") }), children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.HelpCircleIcon, { className: "h-4 w-4" }) }),
388
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunk56QAXZKIjs.SheetContent, { side: "right", className: "w-full max-w-md sm:max-w-lg", children: [
389
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunk56QAXZKIjs.SheetHeader, { children: [
390
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk56QAXZKIjs.SheetTitle, { children: active ? active.name : t("help.hint.pickArticle") }),
391
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk56QAXZKIjs.SheetDescription, { children: _nullishCoalesce(_optionalChain([active, 'optionalAccess', _4 => _4.summary]), () => ( "")) })
392
392
  ] }),
393
393
  active ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "mt-4 space-y-3", children: [
394
394
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-muted-foreground text-sm", children: active.summary }),
@@ -420,7 +420,7 @@ _chunk7QVYU63Ejs.__name.call(void 0, HelpHint, "HelpHint");
420
420
 
421
421
  function HelpSearchResultRow({ result, onSelect }) {
422
422
  const t = _nextintl.useTranslations.call(void 0, );
423
- const generateUrl = _chunkSPRFCAQIjs.usePageUrlGenerator.call(void 0, );
423
+ const generateUrl = _chunk56QAXZKIjs.usePageUrlGenerator.call(void 0, );
424
424
  const [article, setArticle] = _react.useState.call(void 0, null);
425
425
  _react.useEffect.call(void 0, () => {
426
426
  let active = true;
@@ -431,7 +431,7 @@ function HelpSearchResultRow({ result, onSelect }) {
431
431
  }, [result.id]);
432
432
  if (!article) {
433
433
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
434
- _chunkSPRFCAQIjs.CommandItem,
434
+ _chunk56QAXZKIjs.CommandItem,
435
435
  {
436
436
  value: result.id,
437
437
  disabled: true,
@@ -440,7 +440,7 @@ function HelpSearchResultRow({ result, onSelect }) {
440
440
  }
441
441
  );
442
442
  }
443
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkSPRFCAQIjs.CommandItem, { value: result.id, onSelect, className: "cursor-pointer p-0", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
443
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk56QAXZKIjs.CommandItem, { value: result.id, onSelect, className: "cursor-pointer p-0", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
444
444
  _link2.default,
445
445
  {
446
446
  href: generateUrl({ page: `/help/${article.howToType}/${article.slug}` }),
@@ -21,7 +21,7 @@ import {
21
21
  useAssistantContext,
22
22
  useCurrentUserContext,
23
23
  usePageUrlGenerator
24
- } from "../../chunk-RKUUGCYB.mjs";
24
+ } from "../../chunk-6D4GJHLK.mjs";
25
25
  import {
26
26
  _getStaticHelpContent
27
27
  } from "../../chunk-WEPQD5MP.mjs";
package/dist/index.d.mts CHANGED
@@ -6,7 +6,7 @@ import { AbstractApiData } from './core/index.mjs';
6
6
  export { AppModuleDefinitions, Assistant, AssistantMessage, AssistantMessageModule, AssistantMessageService, AssistantModule, AssistantService, AuditLog, AuditLogInterface, AuditLogModule, AuditLogService, Auth, AuthModule, AuthorModule, BackupCodeVerify, BackupCodeVerifyInput, BackupCodeVerifyModule, Billing, BillingModule, BillingService, BlockDiffOptions, BlockNoteDiffUtil, BlockNoteWordDiffRendererUtil, Chunk, ChunkInput, ChunkModule, ClientAbstractService, ClientHttpMethod, ClientNextRef, ClientPreviousRef, ClientSelfRef, ClientTotalRef, Company, CompanyFields, CompanyModule, Content, ContentModule, DataClass, DataClass as DataClassRegistry, DiffBlock, DiffResult, EndpointCreator, EndpointQuery, EntityObject, Feature, FeatureModule, FormatOption, FoundationModuleDefinitions, HowTo, HowToFields, HowToModule, HowToService, InviteValidation, JsonApiDataFactory, Module, ModuleDefinitions, ModuleModule, ModulePathsModule, ModuleRegistrar, ModuleRegistry, Modules, Notification, NotificationFields, NotificationModule, OAuthClient, OAuthModule, OAuthService, Passkey, PasskeyAuthenticationOptions, PasskeyAuthenticationOptionsInput, PasskeyAuthenticationOptionsInterface, PasskeyAuthenticationOptionsModule, PasskeyModule, PasskeyRegistrationOptions, PasskeyRegistrationOptionsInput, PasskeyRegistrationOptionsInterface, PasskeyRegistrationOptionsModule, PasskeyRegistrationVerify, PasskeyRegistrationVerifyInput, PasskeyRegistrationVerifyModule, PasskeyRename, PasskeyRenameInput, PasskeyRenameModule, PasskeyVerifyLogin, PasskeyVerifyLoginInput, PasskeyVerifyLoginModule, PaymentMethod, PermissionMappingModule, Push, PushInput, PushInterface, PushModule, RbacMatrixModule, ReferralModule, ReferralService, ReferralStats, ReferralStatsModule, RehydrationFactory, Role, RoleModule, S3, S3Module, SearchResultInterface, StripeCustomer, StripeCustomerModule, StripeCustomerService, StripeInvoice, StripeInvoiceModule, StripeInvoiceService, StripePaymentMethodModule, StripePrice, StripePriceModule, StripePriceService, StripeProduct, StripeProductModule, StripeProductService, StripePromotionCode, StripePromotionCodeModule, StripePromotionCodeService, StripeSubscription, StripeSubscriptionModule, StripeSubscriptionService, StripeUsage, StripeUsageModule, StripeUsageService, TableOptions, ToastOptions, TotpAuthenticator, TotpAuthenticatorModule, TotpSetup, TotpSetupInput, TotpSetupInterface, TotpSetupModule, TotpVerify, TotpVerifyInput, TotpVerifyLogin, TotpVerifyLoginInput, TotpVerifyLoginModule, TotpVerifyModule, TwoFactorChallenge, TwoFactorChallengeInput, TwoFactorChallengeModule, TwoFactorEnable, TwoFactorEnableInput, TwoFactorEnableModule, TwoFactorService, TwoFactorStatus, TwoFactorStatusInterface, TwoFactorStatusModule, User, UserModule, UserObject, Waitlist, WaitlistInput, WaitlistInterface, WaitlistModule, WaitlistService, WaitlistStats, WaitlistStatsInterface, WaitlistStatsModule, WaitlistStatus, WordDiff, checkPermissions, checkPermissionsFromServer, cn, composeRefs, dismissToast, entityObjectSchema, exists, formatDate, formatLocalDate, getBootstrapper, getClientGlobalErrorHandler, getTableComponents, getTableOptions, getValueFromPath, hasBootstrapper, rehydrate, rehydrateList, resetBootstrapStore, setBootstrapper, setClientGlobalErrorHandler, showCustomToast, showError, showToast, translateData, translateResponse, tryBootstrap, useComposedRefs, useIsMobile, userObjectSchema } from './core/index.mjs';
7
7
  import { b as AbstractService } from './s3.service-CihgBy97.mjs';
8
8
  export { A as AuthService, C as CompanyService, a as ContentService, F as FeatureService, H as HttpMethod, c as NextRef, N as NotificationService, d as PreviousRef, P as PushService, R as RoleService, j as S3Input, k as S3Interface, S as S3Service, e as SelfRef, T as TotalRef, i as TwoFactorChallengeInterface, U as UserService, f as clearLastApiTotal, h as getGlobalErrorHandler, g as getLastApiTotal, s as setGlobalErrorHandler } from './s3.service-CihgBy97.mjs';
9
- export { c as AssistantMessageInput, d as AssistantMessageInterface, A as AssistantMessageRole, b as AssistantMessageType, B as BreadcrumbItemData, e as ChunkInterface, C as ChunkRelationshipMeta, H as HowToInput, a as HowToInterface } from './AssistantMessageInterface-Ca0G0vZw.mjs';
9
+ export { c as AssistantMessageInput, d as AssistantMessageInterface, A as AssistantMessageRole, b as AssistantMessageType, B as BreadcrumbItemData, e as ChunkInterface, C as ChunkRelationshipMeta, H as HowToInput, a as HowToInterface } from './AssistantMessageInterface-DH1QwtC_.mjs';
10
10
  export { C as ContentFields, D as D3Link, a as D3Node, R as RoleFields, U as UserFields } from './content.fields-xH3TGvVk.mjs';
11
11
  export { ClassValue } from 'clsx';
12
12
  export { A as AuthComponent, P as PasskeyInterface, T as TotpAuthenticatorInterface, b as getIcon, a as getIconByModule, c as getIconByModuleName, g as getInitials, d as getLucideIcon, e as getLucideIconByModule, f as getLucideIconByModuleName } from './AuthComponent-DdxCFgUZ.mjs';
package/dist/index.d.ts CHANGED
@@ -6,7 +6,7 @@ import { AbstractApiData } from './core/index.js';
6
6
  export { AppModuleDefinitions, Assistant, AssistantMessage, AssistantMessageModule, AssistantMessageService, AssistantModule, AssistantService, AuditLog, AuditLogInterface, AuditLogModule, AuditLogService, Auth, AuthModule, AuthorModule, BackupCodeVerify, BackupCodeVerifyInput, BackupCodeVerifyModule, Billing, BillingModule, BillingService, BlockDiffOptions, BlockNoteDiffUtil, BlockNoteWordDiffRendererUtil, Chunk, ChunkInput, ChunkModule, ClientAbstractService, ClientHttpMethod, ClientNextRef, ClientPreviousRef, ClientSelfRef, ClientTotalRef, Company, CompanyFields, CompanyModule, Content, ContentModule, DataClass, DataClass as DataClassRegistry, DiffBlock, DiffResult, EndpointCreator, EndpointQuery, EntityObject, Feature, FeatureModule, FormatOption, FoundationModuleDefinitions, HowTo, HowToFields, HowToModule, HowToService, InviteValidation, JsonApiDataFactory, Module, ModuleDefinitions, ModuleModule, ModulePathsModule, ModuleRegistrar, ModuleRegistry, Modules, Notification, NotificationFields, NotificationModule, OAuthClient, OAuthModule, OAuthService, Passkey, PasskeyAuthenticationOptions, PasskeyAuthenticationOptionsInput, PasskeyAuthenticationOptionsInterface, PasskeyAuthenticationOptionsModule, PasskeyModule, PasskeyRegistrationOptions, PasskeyRegistrationOptionsInput, PasskeyRegistrationOptionsInterface, PasskeyRegistrationOptionsModule, PasskeyRegistrationVerify, PasskeyRegistrationVerifyInput, PasskeyRegistrationVerifyModule, PasskeyRename, PasskeyRenameInput, PasskeyRenameModule, PasskeyVerifyLogin, PasskeyVerifyLoginInput, PasskeyVerifyLoginModule, PaymentMethod, PermissionMappingModule, Push, PushInput, PushInterface, PushModule, RbacMatrixModule, ReferralModule, ReferralService, ReferralStats, ReferralStatsModule, RehydrationFactory, Role, RoleModule, S3, S3Module, SearchResultInterface, StripeCustomer, StripeCustomerModule, StripeCustomerService, StripeInvoice, StripeInvoiceModule, StripeInvoiceService, StripePaymentMethodModule, StripePrice, StripePriceModule, StripePriceService, StripeProduct, StripeProductModule, StripeProductService, StripePromotionCode, StripePromotionCodeModule, StripePromotionCodeService, StripeSubscription, StripeSubscriptionModule, StripeSubscriptionService, StripeUsage, StripeUsageModule, StripeUsageService, TableOptions, ToastOptions, TotpAuthenticator, TotpAuthenticatorModule, TotpSetup, TotpSetupInput, TotpSetupInterface, TotpSetupModule, TotpVerify, TotpVerifyInput, TotpVerifyLogin, TotpVerifyLoginInput, TotpVerifyLoginModule, TotpVerifyModule, TwoFactorChallenge, TwoFactorChallengeInput, TwoFactorChallengeModule, TwoFactorEnable, TwoFactorEnableInput, TwoFactorEnableModule, TwoFactorService, TwoFactorStatus, TwoFactorStatusInterface, TwoFactorStatusModule, User, UserModule, UserObject, Waitlist, WaitlistInput, WaitlistInterface, WaitlistModule, WaitlistService, WaitlistStats, WaitlistStatsInterface, WaitlistStatsModule, WaitlistStatus, WordDiff, checkPermissions, checkPermissionsFromServer, cn, composeRefs, dismissToast, entityObjectSchema, exists, formatDate, formatLocalDate, getBootstrapper, getClientGlobalErrorHandler, getTableComponents, getTableOptions, getValueFromPath, hasBootstrapper, rehydrate, rehydrateList, resetBootstrapStore, setBootstrapper, setClientGlobalErrorHandler, showCustomToast, showError, showToast, translateData, translateResponse, tryBootstrap, useComposedRefs, useIsMobile, userObjectSchema } from './core/index.js';
7
7
  import { b as AbstractService } from './s3.service-Cyvfk3qV.js';
8
8
  export { A as AuthService, C as CompanyService, a as ContentService, F as FeatureService, H as HttpMethod, c as NextRef, N as NotificationService, d as PreviousRef, P as PushService, R as RoleService, j as S3Input, k as S3Interface, S as S3Service, e as SelfRef, T as TotalRef, i as TwoFactorChallengeInterface, U as UserService, f as clearLastApiTotal, h as getGlobalErrorHandler, g as getLastApiTotal, s as setGlobalErrorHandler } from './s3.service-Cyvfk3qV.js';
9
- export { c as AssistantMessageInput, d as AssistantMessageInterface, A as AssistantMessageRole, b as AssistantMessageType, B as BreadcrumbItemData, e as ChunkInterface, C as ChunkRelationshipMeta, H as HowToInput, a as HowToInterface } from './AssistantMessageInterface-DEZ5AnVl.js';
9
+ export { c as AssistantMessageInput, d as AssistantMessageInterface, A as AssistantMessageRole, b as AssistantMessageType, B as BreadcrumbItemData, e as ChunkInterface, C as ChunkRelationshipMeta, H as HowToInput, a as HowToInterface } from './AssistantMessageInterface-giWvsOrX.js';
10
10
  export { C as ContentFields, D as D3Link, a as D3Node, R as RoleFields, U as UserFields } from './content.fields-xH3TGvVk.js';
11
11
  export { ClassValue } from 'clsx';
12
12
  export { A as AuthComponent, P as PasskeyInterface, T as TotpAuthenticatorInterface, b as getIcon, a as getIconByModule, c as getIconByModuleName, g as getInitials, d as getLucideIcon, e as getLucideIconByModule, f as getLucideIconByModuleName } from './AuthComponent-Cd7lcYif.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@carlonicora/nextjs-jsonapi",
3
- "version": "1.116.0",
3
+ "version": "1.117.1",
4
4
  "description": "Next.js JSON:API client with server/client support and caching",
5
5
  "author": "Carlo Nicora",
6
6
  "license": "GPL-3.0-or-later",
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
 
3
3
  import { LoaderCircleIcon, Trash2Icon } from "lucide-react";
4
- import { useState } from "react";
4
+ import { ReactNode, useState } from "react";
5
5
  import { useI18nRouter, useI18nTranslations } from "../../i18n";
6
6
  import {
7
7
  AlertDialog,
@@ -15,15 +15,37 @@ import {
15
15
  import { errorToast } from "../errors";
16
16
 
17
17
  type CommonDeleterProps = {
18
- type: string;
18
+ type?: string;
19
+ /** Override the type-derived dialog title. */
20
+ title?: string;
21
+ /** Override the type-derived dialog subtitle. */
22
+ subtitle?: string;
23
+ /** Override the type-derived dialog body; rendered as-is. */
24
+ description?: ReactNode;
19
25
  deleteFunction: () => Promise<void>;
20
26
  redirectTo?: string;
21
27
  forceShow?: boolean;
22
28
  testId?: string;
29
+ /** Custom trigger element replacing the default trash button. */
30
+ trigger?: ReactNode;
23
31
  onSuccess?: () => void | Promise<void>;
32
+ /** Fired after a successful delete, in addition to redirect/onSuccess. */
33
+ propagateChanges?: () => void;
24
34
  };
25
35
 
26
- export function CommonDeleter({ deleteFunction, redirectTo, type, forceShow, testId, onSuccess }: CommonDeleterProps) {
36
+ export function CommonDeleter({
37
+ deleteFunction,
38
+ redirectTo,
39
+ type,
40
+ title,
41
+ subtitle,
42
+ description,
43
+ forceShow,
44
+ testId,
45
+ trigger,
46
+ onSuccess,
47
+ propagateChanges,
48
+ }: CommonDeleterProps) {
27
49
  const t = useI18nTranslations();
28
50
  const router = useI18nRouter();
29
51
  const [open, setOpen] = useState<boolean>(forceShow || false);
@@ -37,6 +59,7 @@ export function CommonDeleter({ deleteFunction, redirectTo, type, forceShow, tes
37
59
  setOpen(false);
38
60
  if (onSuccess) await onSuccess();
39
61
  else if (redirectTo) router.push(redirectTo);
62
+ if (propagateChanges) propagateChanges();
40
63
  } catch (error) {
41
64
  errorToast({ title: t(`common.errors.delete`), error: error });
42
65
  }
@@ -47,28 +70,36 @@ export function CommonDeleter({ deleteFunction, redirectTo, type, forceShow, tes
47
70
  <AlertDialog open={open} onOpenChange={setOpen}>
48
71
  {forceShow ? null : (
49
72
  <AlertDialogTrigger>
50
- <Button
51
- render={<div />}
52
- nativeButton={false}
53
- size="sm"
54
- variant={"ghost"}
55
- className="text-muted-foreground hover:text-destructive"
56
- data-testid={testId}
57
- >
58
- <Trash2Icon />
59
- </Button>
73
+ {trigger || (
74
+ <Button
75
+ render={<div />}
76
+ nativeButton={false}
77
+ size="sm"
78
+ variant={"ghost"}
79
+ className="text-muted-foreground hover:text-destructive"
80
+ data-testid={testId}
81
+ >
82
+ <Trash2Icon />
83
+ </Button>
84
+ )}
60
85
  </AlertDialogTrigger>
61
86
  )}
62
87
  <AlertDialogContent className={`flex max-h-[70vh] max-w-3xl flex-col overflow-y-auto`}>
63
88
  <AlertDialogHeader>
64
- <AlertDialogTitle>{t(`common.delete.title`, { type: t(`entities.${type}`, { count: 1 }) })}</AlertDialogTitle>
89
+ <AlertDialogTitle>
90
+ {title ?? t(`common.delete.title`, { type: t(`entities.${type}`, { count: 1 }) })}
91
+ </AlertDialogTitle>
65
92
  <AlertDialogDescription>
66
- {t(`common.delete.subtitle`, { type: t(`entities.${type}`, { count: 1 }) })}
93
+ {subtitle ?? t(`common.delete.subtitle`, { type: t(`entities.${type}`, { count: 1 }) })}
67
94
  </AlertDialogDescription>
68
95
  </AlertDialogHeader>
69
- <div className="text-destructive p-4 text-sm">
70
- {t(`common.delete.description`, { type: t(`entities.${type}`, { count: 1 }) })}
71
- </div>
96
+ {description !== undefined ? (
97
+ description
98
+ ) : (
99
+ <div className="text-destructive p-4 text-sm">
100
+ {t(`common.delete.description`, { type: t(`entities.${type}`, { count: 1 }) })}
101
+ </div>
102
+ )}
72
103
  <div className="flex justify-end">
73
104
  <Button
74
105
  className="mr-2"
@@ -9,6 +9,7 @@ type CommonEditorButtonsProps = {
9
9
  setOpen: (open: boolean) => void;
10
10
  hideSubmit?: boolean;
11
11
  centerButtons?: ReactNode;
12
+ buttonTitle?: string;
12
13
  };
13
14
  export function CommonEditorButtons({
14
15
  isEdit,
@@ -17,6 +18,7 @@ export function CommonEditorButtons({
17
18
  setOpen,
18
19
  hideSubmit,
19
20
  centerButtons,
21
+ buttonTitle,
20
22
  }: CommonEditorButtonsProps) {
21
23
  const t = useTranslations();
22
24
 
@@ -31,7 +33,7 @@ export function CommonEditorButtons({
31
33
 
32
34
  {!hideSubmit ? (
33
35
  <Button type="submit" disabled={form.formState.isSubmitting || disabled} data-testid={`modal-button-create`}>
34
- {isEdit ? t(`ui.buttons.confirm_update`) : t(`ui.buttons.confirm_create`)}
36
+ {buttonTitle ? buttonTitle : isEdit ? t(`ui.buttons.confirm_update`) : t(`ui.buttons.confirm_create`)}
35
37
  </Button>
36
38
  ) : (
37
39
  <div />
@@ -54,7 +56,7 @@ export function CommonEditorButtons({
54
56
 
55
57
  {!hideSubmit && (
56
58
  <Button type="submit" disabled={form.formState.isSubmitting || disabled} data-testid={`modal-button-create`}>
57
- {isEdit ? t(`ui.buttons.confirm_update`) : t(`ui.buttons.confirm_create`)}
59
+ {buttonTitle ? buttonTitle : isEdit ? t(`ui.buttons.confirm_update`) : t(`ui.buttons.confirm_create`)}
58
60
  </Button>
59
61
  )}
60
62
  </div>
@@ -6,29 +6,35 @@ import { DialogDescription, DialogHeader, DialogTitle } from "../../shadcnui";
6
6
  type CommonEditorHeaderProps = {
7
7
  type: string;
8
8
  name?: string;
9
+ title?: string;
10
+ description?: string;
9
11
  };
10
12
 
11
- export function CommonEditorHeader({ type, name }: CommonEditorHeaderProps) {
13
+ export function CommonEditorHeader({ type, name, title, description }: CommonEditorHeaderProps) {
12
14
  const t = useTranslations();
13
15
 
14
16
  return (
15
17
  <DialogHeader>
16
18
  <DialogTitle>
17
- {name
18
- ? t(`common.edit.update.title`, {
19
- type: type,
20
- })
21
- : t(`common.edit.create.title`, { type: type })}
19
+ {title
20
+ ? title
21
+ : name
22
+ ? t(`common.edit.update.title`, {
23
+ type: type,
24
+ })
25
+ : t(`common.edit.create.title`, { type: type })}
22
26
  </DialogTitle>
23
27
  <DialogDescription>
24
- {name
25
- ? t(`common.edit.update.description`, {
26
- type: type,
27
- name: name,
28
- })
29
- : t(`common.edit.create.description`, {
30
- type: type,
31
- })}
28
+ {description
29
+ ? description
30
+ : name
31
+ ? t(`common.edit.update.description`, {
32
+ type: type,
33
+ name: name,
34
+ })
35
+ : t(`common.edit.create.description`, {
36
+ type: type,
37
+ })}
32
38
  </DialogDescription>
33
39
  </DialogHeader>
34
40
  );
@@ -1,18 +1,23 @@
1
1
  "use client";
2
2
 
3
- import { PencilIcon } from "lucide-react";
3
+ import { PencilIcon, PlusCircleIcon } from "lucide-react";
4
4
 
5
5
  import { useTranslations } from "next-intl";
6
+ import React from "react";
6
7
  import { Button, DialogTrigger } from "../../shadcnui";
7
8
 
8
- type CommonEditorTriggerProps = { isEdit: boolean; edit?: string; create?: string; testId?: string };
9
+ type CommonEditorTriggerProps = { isEdit: boolean; edit?: string; create?: string; testId?: string; title?: string };
9
10
 
10
- export function CommonEditorTrigger({ isEdit, edit: _edit, create, testId }: CommonEditorTriggerProps) {
11
+ export function CommonEditorTrigger({ isEdit, edit: _edit, create, testId, title }: CommonEditorTriggerProps) {
11
12
  const t = useTranslations();
12
13
 
13
14
  return (
14
15
  <DialogTrigger>
15
- {isEdit ? (
16
+ {title ? (
17
+ <Button render={<div />} nativeButton={false} size="sm" variant={`outline`} data-testid={testId}>
18
+ {title}
19
+ </Button>
20
+ ) : isEdit ? (
16
21
  <Button
17
22
  render={<div />}
18
23
  nativeButton={false}
@@ -31,3 +36,12 @@ export function CommonEditorTrigger({ isEdit, edit: _edit, create, testId }: Com
31
36
  </DialogTrigger>
32
37
  );
33
38
  }
39
+
40
+ export const CommonAddTrigger = React.forwardRef<HTMLButtonElement, React.ComponentPropsWithoutRef<typeof Button>>(
41
+ (props, ref) => (
42
+ <Button ref={ref} variant="ghost" size="sm" className="text-muted-foreground" {...props}>
43
+ <PlusCircleIcon />
44
+ </Button>
45
+ ),
46
+ );
47
+ CommonAddTrigger.displayName = "CommonAddTrigger";
@@ -2,6 +2,7 @@
2
2
 
3
3
  import { format } from "date-fns";
4
4
  import { CalendarIcon } from "lucide-react";
5
+ import { useTranslations } from "next-intl";
5
6
  import { useEffect, useState } from "react";
6
7
  import { DateRange } from "react-day-picker";
7
8
  import { Button, Calendar, Popover, PopoverContent, PopoverTrigger } from "../../shadcnui";
@@ -14,6 +15,7 @@ type DateRangeSelectorProps = {
14
15
  };
15
16
 
16
17
  export function DateRangeSelector({ onDateChange, avoidSettingDates, showPreviousMonth }: DateRangeSelectorProps) {
18
+ const t = useTranslations();
17
19
  const [date, setDate] = useState<DateRange | undefined>(
18
20
  avoidSettingDates
19
21
  ? undefined
@@ -24,6 +26,12 @@ export function DateRangeSelector({ onDateChange, avoidSettingDates, showPreviou
24
26
  );
25
27
 
26
28
  const [open, setOpen] = useState(false);
29
+ const [mounted, setMounted] = useState(false);
30
+
31
+ // Prevent hydration mismatch by only rendering Popover after mount
32
+ useEffect(() => {
33
+ setMounted(true);
34
+ }, []);
27
35
 
28
36
  const [prevRange, setPrevRange] = useState<DateRange | undefined>(date);
29
37
  useEffect(() => {
@@ -53,28 +61,56 @@ export function DateRangeSelector({ onDateChange, avoidSettingDates, showPreviou
53
61
  }
54
62
  };
55
63
 
64
+ // Show placeholder button during SSR to prevent hydration mismatch
65
+ if (!mounted) {
66
+ return (
67
+ <div className={cn("grid gap-2")}>
68
+ <Button
69
+ id="date"
70
+ variant={"outline"}
71
+ className={cn("w-[300px] justify-start text-left font-normal", !date && "text-muted-foreground")}
72
+ >
73
+ <CalendarIcon />
74
+ {date?.from ? (
75
+ date.to ? (
76
+ <>
77
+ {format(date.from, "LLL dd, y")} - {format(date.to, "LLL dd, y")}
78
+ </>
79
+ ) : (
80
+ format(date.from, "LLL dd, y")
81
+ )
82
+ ) : (
83
+ <span>{t("ui.labels.pick_a_date")}</span>
84
+ )}
85
+ </Button>
86
+ </div>
87
+ );
88
+ }
89
+
56
90
  return (
57
91
  <div className={cn("grid gap-2")}>
58
92
  <Popover open={open} onOpenChange={setOpen}>
59
- <PopoverTrigger>
60
- <Button
61
- id="date"
62
- variant={"outline"}
63
- className={cn("w-[300px] justify-start text-left font-normal", !date && "text-muted-foreground")}
64
- >
65
- <CalendarIcon />
66
- {date?.from ? (
67
- date.to ? (
68
- <>
69
- {format(date.from, "LLL dd, y")} - {format(date.to, "LLL dd, y")}
70
- </>
71
- ) : (
72
- format(date.from, "LLL dd, y")
73
- )
93
+ <PopoverTrigger
94
+ render={
95
+ <Button
96
+ id="date"
97
+ variant={"outline"}
98
+ className={cn("w-[300px] justify-start text-left font-normal", !date && "text-muted-foreground")}
99
+ />
100
+ }
101
+ >
102
+ <CalendarIcon />
103
+ {date?.from ? (
104
+ date.to ? (
105
+ <>
106
+ {format(date.from, "LLL dd, y")} - {format(date.to, "LLL dd, y")}
107
+ </>
74
108
  ) : (
75
- <span>Pick a date</span>
76
- )}
77
- </Button>
109
+ format(date.from, "LLL dd, y")
110
+ )
111
+ ) : (
112
+ <span>{t("ui.labels.pick_a_date")}</span>
113
+ )}
78
114
  </PopoverTrigger>
79
115
  <PopoverContent className="w-auto p-0" align="start">
80
116
  <div className="flex flex-col gap-2 p-2">
@@ -100,7 +136,7 @@ export function DateRangeSelector({ onDateChange, avoidSettingDates, showPreviou
100
136
  className="cursor-pointer"
101
137
  disabled={!date}
102
138
  >
103
- Clear
139
+ {t("ui.buttons.clear")}
104
140
  </Button>
105
141
  </div>
106
142
  </PopoverContent>