@carlonicora/nextjs-jsonapi 1.123.2 → 1.124.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 (30) hide show
  1. package/dist/{BlockNoteEditor-FMTBHYZB.mjs → BlockNoteEditor-LN6P5CEQ.mjs} +2 -2
  2. package/dist/{BlockNoteEditor-6NV6WSQH.js → BlockNoteEditor-YIZGXB5K.js} +9 -9
  3. package/dist/{BlockNoteEditor-6NV6WSQH.js.map → BlockNoteEditor-YIZGXB5K.js.map} +1 -1
  4. package/dist/billing/index.js +299 -299
  5. package/dist/billing/index.mjs +1 -1
  6. package/dist/{chunk-63FZJ7UK.js → chunk-FOKYS5QE.js} +840 -587
  7. package/dist/chunk-FOKYS5QE.js.map +1 -0
  8. package/dist/{chunk-J2ACFNKE.mjs → chunk-NXRUJIU2.mjs} +3132 -2879
  9. package/dist/chunk-NXRUJIU2.mjs.map +1 -0
  10. package/dist/client/index.js +2 -2
  11. package/dist/client/index.mjs +1 -1
  12. package/dist/components/index.d.mts +179 -123
  13. package/dist/components/index.d.ts +179 -123
  14. package/dist/components/index.js +12 -2
  15. package/dist/components/index.js.map +1 -1
  16. package/dist/components/index.mjs +11 -1
  17. package/dist/contexts/index.js +2 -2
  18. package/dist/contexts/index.mjs +1 -1
  19. package/dist/features/help/index.js +30 -30
  20. package/dist/features/help/index.mjs +1 -1
  21. package/package.json +1 -1
  22. package/src/components/containers/RoundPageContainer.tsx +20 -20
  23. package/src/components/forms/EntityMultiSelector.tsx +15 -3
  24. package/src/components/forms/EntitySelector.tsx +256 -0
  25. package/src/components/forms/FormLayout.tsx +58 -0
  26. package/src/components/forms/index.ts +10 -8
  27. package/src/components/forms/useEditorDialog.ts +21 -4
  28. package/dist/chunk-63FZJ7UK.js.map +0 -1
  29. package/dist/chunk-J2ACFNKE.mjs.map +0 -1
  30. /package/dist/{BlockNoteEditor-FMTBHYZB.mjs.map → BlockNoteEditor-LN6P5CEQ.mjs.map} +0 -0
@@ -183,6 +183,7 @@ import {
183
183
  EmptyState,
184
184
  EntityAvatar,
185
185
  EntityMultiSelector,
186
+ EntitySelector,
186
187
  ErrorDetails,
187
188
  Field,
188
189
  FieldContent,
@@ -202,7 +203,9 @@ import {
202
203
  ForgotPassword,
203
204
  Form,
204
205
  FormBlockNote,
206
+ FormBody,
205
207
  FormCheckbox,
208
+ FormCol,
206
209
  FormDate,
207
210
  FormDateTime,
208
211
  FormFeatures,
@@ -211,6 +214,8 @@ import {
211
214
  FormPassword,
212
215
  FormPlaceAutocomplete,
213
216
  FormRoles,
217
+ FormRow,
218
+ FormSection,
214
219
  FormSelect,
215
220
  FormSlider,
216
221
  FormSwitch,
@@ -464,7 +469,7 @@ import {
464
469
  useFileUpload,
465
470
  useMentionInsert,
466
471
  useSidebar
467
- } from "../chunk-J2ACFNKE.mjs";
472
+ } from "../chunk-NXRUJIU2.mjs";
468
473
  import "../chunk-6VNRUTZR.mjs";
469
474
  import {
470
475
  getIcon,
@@ -664,6 +669,7 @@ export {
664
669
  EmptyState,
665
670
  EntityAvatar,
666
671
  EntityMultiSelector,
672
+ EntitySelector,
667
673
  ErrorDetails,
668
674
  Field,
669
675
  FieldContent,
@@ -683,7 +689,9 @@ export {
683
689
  ForgotPassword,
684
690
  Form,
685
691
  FormBlockNote,
692
+ FormBody,
686
693
  FormCheckbox,
694
+ FormCol,
687
695
  FormDate,
688
696
  FormDateTime,
689
697
  FormFeatures,
@@ -692,6 +700,8 @@ export {
692
700
  FormPassword,
693
701
  FormPlaceAutocomplete,
694
702
  FormRoles,
703
+ FormRow,
704
+ FormSection,
695
705
  FormSelect,
696
706
  FormSlider,
697
707
  FormSwitch,
@@ -31,7 +31,7 @@
31
31
 
32
32
 
33
33
 
34
- var _chunk63FZJ7UKjs = require('../chunk-63FZJ7UK.js');
34
+ var _chunkFOKYS5QEjs = require('../chunk-FOKYS5QE.js');
35
35
  require('../chunk-JO5BLONK.js');
36
36
  require('../chunk-PQBKPWBY.js');
37
37
  require('../chunk-LXKSUWAV.js');
@@ -71,5 +71,5 @@ require('../chunk-7QVYU63E.js');
71
71
 
72
72
 
73
73
 
74
- exports.AssistantProvider = _chunk63FZJ7UKjs.AssistantProvider; exports.CommonProvider = _chunk63FZJ7UKjs.CommonProvider; exports.CompanyProvider = _chunk63FZJ7UKjs.CompanyProvider; exports.CurrentUserProvider = _chunk63FZJ7UKjs.CurrentUserProvider; exports.DEFAULT_ONBOARDING_LABELS = _chunk63FZJ7UKjs.DEFAULT_ONBOARDING_LABELS; exports.HeaderChildrenProvider = _chunk63FZJ7UKjs.HeaderChildrenProvider; exports.HeaderLeftContentProvider = _chunk63FZJ7UKjs.HeaderLeftContentProvider; exports.HowToProvider = _chunk63FZJ7UKjs.HowToProvider; exports.NotificationContextProvider = _chunk63FZJ7UKjs.NotificationContextProvider; exports.OnboardingProvider = _chunk63FZJ7UKjs.OnboardingProvider; exports.RbacProvider = _chunk63FZJ7UKjs.RbacProvider; exports.RoleProvider = _chunk63FZJ7UKjs.RoleProvider; exports.SharedProvider = _chunk63FZJ7UKjs.SharedProvider; exports.SocketContext = _chunk63FZJ7UKjs.SocketContext; exports.SocketProvider = _chunk63FZJ7UKjs.SocketProvider; exports.UserProvider = _chunk63FZJ7UKjs.UserProvider; exports.recentPagesAtom = _chunk63FZJ7UKjs.recentPagesAtom; exports.useAssistantContext = _chunk63FZJ7UKjs.useAssistantContext; exports.useCommonContext = _chunk63FZJ7UKjs.useCommonContext; exports.useCompanyContext = _chunk63FZJ7UKjs.useCompanyContext; exports.useCurrentUserContext = _chunk63FZJ7UKjs.useCurrentUserContext; exports.useHeaderChildren = _chunk63FZJ7UKjs.useHeaderChildren; exports.useHeaderLeftContent = _chunk63FZJ7UKjs.useHeaderLeftContent; exports.useHowToContext = _chunk63FZJ7UKjs.useHowToContext; exports.useNotificationContext = _chunk63FZJ7UKjs.useNotificationContext; exports.useOnboarding = _chunk63FZJ7UKjs.useOnboarding; exports.useRbacContext = _chunk63FZJ7UKjs.useRbacContext; exports.useRoleContext = _chunk63FZJ7UKjs.useRoleContext; exports.useSharedContext = _chunk63FZJ7UKjs.useSharedContext; exports.useSocketContext = _chunk63FZJ7UKjs.useSocketContext; exports.useUserContext = _chunk63FZJ7UKjs.useUserContext;
74
+ exports.AssistantProvider = _chunkFOKYS5QEjs.AssistantProvider; exports.CommonProvider = _chunkFOKYS5QEjs.CommonProvider; exports.CompanyProvider = _chunkFOKYS5QEjs.CompanyProvider; exports.CurrentUserProvider = _chunkFOKYS5QEjs.CurrentUserProvider; exports.DEFAULT_ONBOARDING_LABELS = _chunkFOKYS5QEjs.DEFAULT_ONBOARDING_LABELS; exports.HeaderChildrenProvider = _chunkFOKYS5QEjs.HeaderChildrenProvider; exports.HeaderLeftContentProvider = _chunkFOKYS5QEjs.HeaderLeftContentProvider; exports.HowToProvider = _chunkFOKYS5QEjs.HowToProvider; exports.NotificationContextProvider = _chunkFOKYS5QEjs.NotificationContextProvider; exports.OnboardingProvider = _chunkFOKYS5QEjs.OnboardingProvider; exports.RbacProvider = _chunkFOKYS5QEjs.RbacProvider; exports.RoleProvider = _chunkFOKYS5QEjs.RoleProvider; exports.SharedProvider = _chunkFOKYS5QEjs.SharedProvider; exports.SocketContext = _chunkFOKYS5QEjs.SocketContext; exports.SocketProvider = _chunkFOKYS5QEjs.SocketProvider; exports.UserProvider = _chunkFOKYS5QEjs.UserProvider; exports.recentPagesAtom = _chunkFOKYS5QEjs.recentPagesAtom; exports.useAssistantContext = _chunkFOKYS5QEjs.useAssistantContext; exports.useCommonContext = _chunkFOKYS5QEjs.useCommonContext; exports.useCompanyContext = _chunkFOKYS5QEjs.useCompanyContext; exports.useCurrentUserContext = _chunkFOKYS5QEjs.useCurrentUserContext; exports.useHeaderChildren = _chunkFOKYS5QEjs.useHeaderChildren; exports.useHeaderLeftContent = _chunkFOKYS5QEjs.useHeaderLeftContent; exports.useHowToContext = _chunkFOKYS5QEjs.useHowToContext; exports.useNotificationContext = _chunkFOKYS5QEjs.useNotificationContext; exports.useOnboarding = _chunkFOKYS5QEjs.useOnboarding; exports.useRbacContext = _chunkFOKYS5QEjs.useRbacContext; exports.useRoleContext = _chunkFOKYS5QEjs.useRoleContext; exports.useSharedContext = _chunkFOKYS5QEjs.useSharedContext; exports.useSocketContext = _chunkFOKYS5QEjs.useSocketContext; exports.useUserContext = _chunkFOKYS5QEjs.useUserContext;
75
75
  //# sourceMappingURL=index.js.map
@@ -31,7 +31,7 @@ import {
31
31
  useSharedContext,
32
32
  useSocketContext,
33
33
  useUserContext
34
- } from "../chunk-J2ACFNKE.mjs";
34
+ } from "../chunk-NXRUJIU2.mjs";
35
35
  import "../chunk-6VNRUTZR.mjs";
36
36
  import "../chunk-T2FFT7JT.mjs";
37
37
  import "../chunk-AUXK7QSA.mjs";
@@ -21,7 +21,7 @@ var _chunkYBZVWLPHjs = require('../../chunk-YBZVWLPH.js');
21
21
 
22
22
 
23
23
 
24
- var _chunk63FZJ7UKjs = require('../../chunk-63FZJ7UK.js');
24
+ var _chunkFOKYS5QEjs = require('../../chunk-FOKYS5QE.js');
25
25
 
26
26
 
27
27
  var _chunkJO5BLONKjs = require('../../chunk-JO5BLONK.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, _chunk63FZJ7UKjs.Sheet, { open, onOpenChange, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
77
- _chunk63FZJ7UKjs.SheetContent,
76
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkFOKYS5QEjs.Sheet, { open, onOpenChange, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
77
+ _chunkFOKYS5QEjs.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, _chunk63FZJ7UKjs.AssistantProvider, { manageUrl: false, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, HelpAssistantSheetBody, {}) })
81
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkFOKYS5QEjs.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 = _chunk63FZJ7UKjs.useAssistantContext.call(void 0, );
88
+ const ctx = _chunkFOKYS5QEjs.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, _chunk63FZJ7UKjs.SheetHeader, { children: [
93
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk63FZJ7UKjs.SheetTitle, { children: t("help.askAi.sheet.title") }),
94
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk63FZJ7UKjs.SheetDescription, { children: t("help.askAi.sheet.subtitle") })
92
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkFOKYS5QEjs.SheetHeader, { children: [
93
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkFOKYS5QEjs.SheetTitle, { children: t("help.askAi.sheet.title") }),
94
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkFOKYS5QEjs.SheetDescription, { children: t("help.askAi.sheet.subtitle") })
95
95
  ] }),
96
- !showThread ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk63FZJ7UKjs.AssistantEmptyState, { onSend: send }) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
96
+ !showThread ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkFOKYS5QEjs.AssistantEmptyState, { onSend: send }) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
97
97
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
98
- _chunk63FZJ7UKjs.AssistantThread,
98
+ _chunkFOKYS5QEjs.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, _chunk63FZJ7UKjs.AssistantComposer, { onSend: send, disabled: ctx.sending })
108
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkFOKYS5QEjs.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 } = _chunk63FZJ7UKjs.useCurrentUserContext.call(void 0, );
118
+ const { currentUser } = _chunkFOKYS5QEjs.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, _chunk63FZJ7UKjs.Tooltip, { children: [
123
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunk63FZJ7UKjs.TooltipTrigger, { render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk63FZJ7UKjs.Button, { variant: "outline", size: "sm", disabled: true }), children: [
122
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkFOKYS5QEjs.Tooltip, { children: [
123
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkFOKYS5QEjs.TooltipTrigger, { render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkFOKYS5QEjs.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, _chunk63FZJ7UKjs.TooltipContent, { children: t("help.askAi.loginTooltip") })
127
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkFOKYS5QEjs.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, _chunk63FZJ7UKjs.Button, { variant: "outline", size: "sm", onClick: () => setOpen(true), children: [
131
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkFOKYS5QEjs.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 } = _chunk63FZJ7UKjs.useCurrentUserContext.call(void 0, );
144
+ const { currentUser } = _chunkFOKYS5QEjs.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, _chunk63FZJ7UKjs.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, _chunk63FZJ7UKjs.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, _chunkFOKYS5QEjs.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, _chunkFOKYS5QEjs.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 = _chunk63FZJ7UKjs.usePageUrlGenerator.call(void 0, );
202
+ const generateUrl = _chunkFOKYS5QEjs.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 = _chunk63FZJ7UKjs.usePageUrlGenerator.call(void 0, );
283
+ const generateUrl = _chunkFOKYS5QEjs.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 = _chunk63FZJ7UKjs.usePageUrlGenerator.call(void 0, );
361
+ const generateUrl = _chunkFOKYS5QEjs.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
- _chunk63FZJ7UKjs.Sheet,
379
+ _chunkFOKYS5QEjs.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, _chunk63FZJ7UKjs.SheetTrigger, { render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk63FZJ7UKjs.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, _chunk63FZJ7UKjs.SheetContent, { side: "right", className: "w-full max-w-md sm:max-w-lg", children: [
389
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunk63FZJ7UKjs.SheetHeader, { children: [
390
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk63FZJ7UKjs.SheetTitle, { children: active ? active.name : t("help.hint.pickArticle") }),
391
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunk63FZJ7UKjs.SheetDescription, { children: _nullishCoalesce(_optionalChain([active, 'optionalAccess', _4 => _4.summary]), () => ( "")) })
387
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkFOKYS5QEjs.SheetTrigger, { render: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkFOKYS5QEjs.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, _chunkFOKYS5QEjs.SheetContent, { side: "right", className: "w-full max-w-md sm:max-w-lg", children: [
389
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkFOKYS5QEjs.SheetHeader, { children: [
390
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkFOKYS5QEjs.SheetTitle, { children: active ? active.name : t("help.hint.pickArticle") }),
391
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkFOKYS5QEjs.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 = _chunk63FZJ7UKjs.usePageUrlGenerator.call(void 0, );
423
+ const generateUrl = _chunkFOKYS5QEjs.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
- _chunk63FZJ7UKjs.CommandItem,
434
+ _chunkFOKYS5QEjs.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, _chunk63FZJ7UKjs.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, _chunkFOKYS5QEjs.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-J2ACFNKE.mjs";
24
+ } from "../../chunk-NXRUJIU2.mjs";
25
25
  import {
26
26
  _getStaticHelpContent
27
27
  } from "../../chunk-6VNRUTZR.mjs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@carlonicora/nextjs-jsonapi",
3
- "version": "1.123.2",
3
+ "version": "1.124.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",
@@ -335,28 +335,28 @@ export function RoundPageContainer({
335
335
  </div>
336
336
  </div>
337
337
  )}
338
- {details &&
339
- (isMobile ? (
340
- <Sheet open={showDetails} onOpenChange={setShowDetails}>
341
- <SheetContent side="right">
342
- <SheetHeader>
343
- <SheetTitle>Details</SheetTitle>
344
- </SheetHeader>
345
- <div className="overflow-y-auto p-6 pt-0">{details}</div>
346
- </SheetContent>
347
- </Sheet>
348
- ) : (
349
- <div
350
- className={cn(
351
- "h-full shrink-0 overflow-hidden overflow-y-auto transition-all duration-300 ease-in-out",
352
- showDetails ? "w-96 border-l p-4 opacity-100" : "ml-0 w-0 border-l-0 p-0 opacity-0",
353
- )}
354
- >
355
- {details}
356
- </div>
357
- ))}
358
338
  </div>
359
339
  </div>
340
+ {details &&
341
+ (isMobile ? (
342
+ <Sheet open={showDetails} onOpenChange={setShowDetails}>
343
+ <SheetContent side="right">
344
+ <SheetHeader>
345
+ <SheetTitle>Details</SheetTitle>
346
+ </SheetHeader>
347
+ <div className="overflow-y-auto p-6 pt-0">{details}</div>
348
+ </SheetContent>
349
+ </Sheet>
350
+ ) : (
351
+ <div
352
+ className={cn(
353
+ "h-full shrink-0 overflow-hidden overflow-y-auto transition-all duration-300 ease-in-out",
354
+ showDetails ? "w-96 border-l p-4 opacity-100" : "ml-0 w-0 border-l-0 p-0 opacity-0",
355
+ )}
356
+ >
357
+ {details}
358
+ </div>
359
+ ))}
360
360
  </div>
361
361
  </div>
362
362
  </>
@@ -26,6 +26,9 @@ type EntityMultiSelectorProps<T extends { id: string }> = {
26
26
  excludeId?: string;
27
27
  onChange?: (entities?: T[]) => void;
28
28
  renderOption?: (entity: T, isSelected: boolean) => ReactNode;
29
+ ready?: boolean;
30
+ description?: string;
31
+ disabled?: boolean;
29
32
  };
30
33
 
31
34
  type OptionData<T> = {
@@ -52,6 +55,9 @@ export function EntityMultiSelector<T extends { id: string }>({
52
55
  excludeId,
53
56
  onChange,
54
57
  renderOption,
58
+ ready = true,
59
+ description,
60
+ disabled = false,
55
61
  }: EntityMultiSelectorProps<T>) {
56
62
  const [open, setOpen] = useState(false);
57
63
  const [searchTerm, setSearchTerm] = useState("");
@@ -94,10 +100,14 @@ export function EntityMultiSelector<T extends { id: string }>({
94
100
  const data: DataListRetriever<T> = useDataListRetriever({
95
101
  retriever: (params) => retriever(params),
96
102
  retrieverParams,
97
- ready: true,
103
+ ready,
98
104
  module,
99
105
  });
100
106
 
107
+ useEffect(() => {
108
+ if (ready) data.setReady(true);
109
+ }, [ready]);
110
+
101
111
  const updateSearch = useCallback(
102
112
  (searchedTerm: string) => {
103
113
  if (searchedTerm.trim()) {
@@ -211,12 +221,14 @@ export function EntityMultiSelector<T extends { id: string }>({
211
221
 
212
222
  return (
213
223
  <div className="flex w-full flex-col">
214
- <FormFieldWrapper form={form} name={id} label={label} isRequired={isRequired}>
224
+ <FormFieldWrapper form={form} name={id} label={label} isRequired={isRequired} description={description}>
215
225
  {() => (
216
226
  <div className="flex flex-col gap-2">
217
227
  <Popover open={open} onOpenChange={setOpen} modal>
218
228
  <PopoverTrigger className="w-full">
219
- <div className="bg-input/20 dark:bg-input/30 border-input flex min-h-7 w-full items-center gap-2 rounded-md border px-2 text-sm md:text-xs/relaxed">
229
+ <div
230
+ className={`bg-input/20 dark:bg-input/30 border-input focus-visible:border-ring focus-visible:ring-ring/30 focus-visible:ring-[2px] flex min-h-7 w-full items-center gap-2 rounded-md border px-2 text-sm md:text-xs/relaxed`}
231
+ >
220
232
  {selectedValues.length > 0 ? (
221
233
  <>
222
234
  <span className="text-foreground min-w-0 flex-1 truncate text-left">{triggerSummary}</span>
@@ -0,0 +1,256 @@
1
+ "use client";
2
+
3
+ import { ReactNode, useCallback, useEffect, useRef, useState } from "react";
4
+ import { CircleX, Plus, RefreshCwIcon, SearchIcon, XIcon } from "lucide-react";
5
+ import { Command, CommandItem, CommandList } from "../../shadcnui/ui/command";
6
+ import { Input } from "../../shadcnui/ui/input";
7
+ import { Popover, PopoverContent, PopoverTrigger } from "../../shadcnui/ui/popover";
8
+ import { FormFieldWrapper } from "./FormFieldWrapper";
9
+ import { type DataListRetriever, useDataListRetriever } from "../../hooks/useDataListRetriever";
10
+ import { useDebounce } from "../../hooks/useDebounce";
11
+
12
+ type BaseEntity = { id: string };
13
+
14
+ type EntitySelectorProps<T extends BaseEntity> = {
15
+ id: string;
16
+ form: any;
17
+ module: any;
18
+ retriever: (params: any) => Promise<T[]>;
19
+ retrieverParams?: Record<string, any>;
20
+ getLabel?: (entity: T) => string;
21
+ label?: string;
22
+ placeholder?: string;
23
+ emptyText?: string;
24
+ isRequired?: boolean;
25
+ disabled?: boolean;
26
+ description?: string;
27
+ ready?: boolean;
28
+ onChange?: (entity?: T) => void;
29
+ onCreateNew?: (name: string) => Promise<T | undefined>;
30
+ createNewLabel?: (searchTerm: string) => string;
31
+ toFormValue?: (entity: T) => Record<string, any>;
32
+ getSelectedItemDisplay?: (value: Record<string, any>) => ReactNode;
33
+ renderOption?: (entity: T, onSelect: () => void) => ReactNode;
34
+ filterData?: (data: T[]) => T[];
35
+ renderAfter?: (props: { form: any; selectedEntity?: T }) => ReactNode;
36
+ autoSelectSingle?: boolean;
37
+ useFormWatch?: boolean;
38
+ };
39
+
40
+ export default function EntitySelector<T extends BaseEntity>({
41
+ id,
42
+ form,
43
+ module,
44
+ retriever,
45
+ retrieverParams,
46
+ ready = true,
47
+ getLabel = (entity: T) => (entity as any).name,
48
+ label,
49
+ placeholder = "Search...",
50
+ emptyText,
51
+ isRequired = false,
52
+ disabled = false,
53
+ description,
54
+ onChange,
55
+ onCreateNew,
56
+ createNewLabel,
57
+ toFormValue = (entity: T) => ({ id: entity.id, name: (entity as any).name }),
58
+ getSelectedItemDisplay,
59
+ renderOption,
60
+ filterData,
61
+ renderAfter,
62
+ autoSelectSingle = false,
63
+ useFormWatch: shouldUseFormWatch = false,
64
+ }: EntitySelectorProps<T>) {
65
+ const [open, setOpen] = useState<boolean>(false);
66
+ const searchTermRef = useRef<string>("");
67
+ const [searchTerm, setSearchTerm] = useState<string>("");
68
+ const [isSearching, setIsSearching] = useState<boolean>(false);
69
+ const [isCreating, setIsCreating] = useState<boolean>(false);
70
+ const [selectedEntity, setSelectedEntity] = useState<T | undefined>(undefined);
71
+
72
+ const watchedValue = shouldUseFormWatch ? form.watch(id) : undefined;
73
+
74
+ const data: DataListRetriever<T> = useDataListRetriever<T>({
75
+ retriever: (params) => retriever(params),
76
+ retrieverParams: retrieverParams ?? {},
77
+ ready,
78
+ module,
79
+ });
80
+
81
+ useEffect(() => {
82
+ if (ready) data.setReady(true);
83
+ }, [ready]);
84
+
85
+ const search = useCallback(
86
+ async (searchedTerm: string) => {
87
+ try {
88
+ if (searchedTerm === searchTermRef.current) return;
89
+ setIsSearching(true);
90
+ searchTermRef.current = searchedTerm;
91
+ await data.search(searchedTerm);
92
+ } finally {
93
+ setIsSearching(false);
94
+ }
95
+ },
96
+ [searchTermRef, data],
97
+ );
98
+
99
+ const updateSearchTerm = useDebounce(search, 500);
100
+
101
+ useEffect(() => {
102
+ setIsSearching(true);
103
+ updateSearchTerm(searchTerm);
104
+ }, [updateSearchTerm, searchTerm]);
105
+
106
+ useEffect(() => {
107
+ if (
108
+ autoSelectSingle &&
109
+ data.isLoaded &&
110
+ data.data &&
111
+ data.data.length === 1 &&
112
+ searchTerm === "" &&
113
+ !form.getValues(id)
114
+ ) {
115
+ const entity = data.data[0];
116
+ form.setValue(id, toFormValue(entity));
117
+ setSelectedEntity(entity);
118
+ }
119
+ }, [data.isLoaded, data.data, searchTerm, form, id, autoSelectSingle, toFormValue]);
120
+
121
+ const handleSelect = (entity?: T) => {
122
+ setSelectedEntity(entity);
123
+ if (onChange) onChange(entity);
124
+ if (!entity) {
125
+ form.setValue(id, undefined);
126
+ setOpen(false);
127
+ return;
128
+ }
129
+ form.setValue(id, toFormValue(entity));
130
+ setOpen(false);
131
+ setTimeout(() => setOpen(false), 0);
132
+ };
133
+
134
+ const handleCreateNew = async () => {
135
+ if (!onCreateNew) return;
136
+ const trimmed = searchTerm.trim();
137
+ if (!trimmed || isCreating) return;
138
+ setIsCreating(true);
139
+ try {
140
+ const created = await onCreateNew(trimmed);
141
+ if (created) {
142
+ handleSelect(created);
143
+ setSearchTerm("");
144
+ searchTermRef.current = "";
145
+ }
146
+ } finally {
147
+ setIsCreating(false);
148
+ }
149
+ };
150
+
151
+ const displayData = filterData ? filterData((data.data as T[]) ?? []) : ((data.data as T[]) ?? []);
152
+
153
+ const hasValue = (value: any) => {
154
+ if (value == null) return false;
155
+ if (typeof value === "object") return !!value.id;
156
+ return !!value;
157
+ };
158
+
159
+ return (
160
+ <div className="flex w-full flex-col">
161
+ <FormFieldWrapper form={form} name={id} label={label} isRequired={isRequired} description={description}>
162
+ {(field) => {
163
+ const effectiveValue = shouldUseFormWatch ? watchedValue : field.value;
164
+ return (
165
+ <Popover open={disabled ? false : open} onOpenChange={disabled ? undefined : setOpen} modal={true}>
166
+ <PopoverTrigger className="w-full" disabled={disabled}>
167
+ <div
168
+ className={`bg-input/20 dark:bg-input/30 border-input focus-visible:border-ring focus-visible:ring-ring/30 focus-visible:ring-[2px] flex min-h-7 w-full items-center gap-2 rounded-md border px-2 py-0.5 text-sm md:text-xs/relaxed ${
169
+ hasValue(effectiveValue) ? "" : "text-muted-foreground"
170
+ } ${disabled ? "cursor-not-allowed opacity-50" : ""}`}
171
+ >
172
+ <span className="min-w-0 flex-1 truncate text-left">
173
+ {hasValue(effectiveValue)
174
+ ? getSelectedItemDisplay
175
+ ? getSelectedItemDisplay(effectiveValue)
176
+ : (effectiveValue?.name ?? "")
177
+ : placeholder}
178
+ </span>
179
+ {hasValue(effectiveValue) && !disabled && (
180
+ <CircleX
181
+ className="text-muted hover:text-destructive ml-auto h-4 w-4 shrink-0 cursor-pointer"
182
+ onClick={(e) => {
183
+ e.stopPropagation();
184
+ e.preventDefault();
185
+ handleSelect();
186
+ }}
187
+ />
188
+ )}
189
+ </div>
190
+ </PopoverTrigger>
191
+ <PopoverContent align="start" className="w-(--anchor-width) pointer-events-auto">
192
+ <Command shouldFilter={false}>
193
+ <div className="relative mb-2 w-full">
194
+ <SearchIcon className="text-muted-foreground absolute top-2.5 left-2.5 h-4 w-4" />
195
+ <Input
196
+ placeholder={placeholder}
197
+ type="text"
198
+ className="w-full pr-8 pl-8"
199
+ onChange={(e) => setSearchTerm(e.target.value)}
200
+ value={searchTerm}
201
+ />
202
+ {isSearching ? (
203
+ <RefreshCwIcon className="text-muted-foreground absolute top-2.5 right-2.5 h-4 w-4 animate-spin" />
204
+ ) : searchTermRef.current ? (
205
+ <XIcon
206
+ className="absolute top-2.5 right-2.5 h-4 w-4 cursor-pointer"
207
+ onClick={() => {
208
+ setSearchTerm("");
209
+ search("");
210
+ }}
211
+ />
212
+ ) : null}
213
+ </div>
214
+ <CommandList>
215
+ {onCreateNew && (
216
+ <CommandItem
217
+ key="__create_new__"
218
+ value="__create_new__"
219
+ className={`cursor-pointer ${!searchTerm.trim() || isCreating ? "opacity-50 pointer-events-none" : ""}`}
220
+ disabled={!searchTerm.trim() || isCreating}
221
+ onSelect={handleCreateNew}
222
+ >
223
+ {isCreating ? (
224
+ <RefreshCwIcon className="mr-2 h-4 w-4 animate-spin" />
225
+ ) : (
226
+ <Plus className="mr-2 h-4 w-4" />
227
+ )}
228
+ <span>{createNewLabel ? createNewLabel(searchTerm) : searchTerm.trim() || ""}</span>
229
+ </CommandItem>
230
+ )}
231
+ {renderOption
232
+ ? displayData.map((entity: T) => renderOption(entity, () => handleSelect(entity)))
233
+ : displayData.map((entity: T) => (
234
+ <CommandItem
235
+ className="cursor-pointer bg-transparent data-selected:bg-transparent hover:bg-muted data-selected:hover:bg-muted"
236
+ key={entity.id}
237
+ value={entity.id}
238
+ onSelect={() => handleSelect(entity)}
239
+ >
240
+ <span>{getLabel(entity)}</span>
241
+ </CommandItem>
242
+ ))}
243
+ {emptyText && displayData.length === 0 && !onCreateNew && (
244
+ <div className="text-muted-foreground py-6 text-center text-xs">{emptyText}</div>
245
+ )}
246
+ </CommandList>
247
+ </Command>
248
+ </PopoverContent>
249
+ </Popover>
250
+ );
251
+ }}
252
+ </FormFieldWrapper>
253
+ {renderAfter && renderAfter({ form, selectedEntity })}
254
+ </div>
255
+ );
256
+ }