@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.
- package/dist/{BlockNoteEditor-FMTBHYZB.mjs → BlockNoteEditor-LN6P5CEQ.mjs} +2 -2
- package/dist/{BlockNoteEditor-6NV6WSQH.js → BlockNoteEditor-YIZGXB5K.js} +9 -9
- package/dist/{BlockNoteEditor-6NV6WSQH.js.map → BlockNoteEditor-YIZGXB5K.js.map} +1 -1
- package/dist/billing/index.js +299 -299
- package/dist/billing/index.mjs +1 -1
- package/dist/{chunk-63FZJ7UK.js → chunk-FOKYS5QE.js} +840 -587
- package/dist/chunk-FOKYS5QE.js.map +1 -0
- package/dist/{chunk-J2ACFNKE.mjs → chunk-NXRUJIU2.mjs} +3132 -2879
- package/dist/chunk-NXRUJIU2.mjs.map +1 -0
- package/dist/client/index.js +2 -2
- package/dist/client/index.mjs +1 -1
- package/dist/components/index.d.mts +179 -123
- package/dist/components/index.d.ts +179 -123
- package/dist/components/index.js +12 -2
- package/dist/components/index.js.map +1 -1
- package/dist/components/index.mjs +11 -1
- package/dist/contexts/index.js +2 -2
- package/dist/contexts/index.mjs +1 -1
- package/dist/features/help/index.js +30 -30
- package/dist/features/help/index.mjs +1 -1
- package/package.json +1 -1
- package/src/components/containers/RoundPageContainer.tsx +20 -20
- package/src/components/forms/EntityMultiSelector.tsx +15 -3
- package/src/components/forms/EntitySelector.tsx +256 -0
- package/src/components/forms/FormLayout.tsx +58 -0
- package/src/components/forms/index.ts +10 -8
- package/src/components/forms/useEditorDialog.ts +21 -4
- package/dist/chunk-63FZJ7UK.js.map +0 -1
- package/dist/chunk-J2ACFNKE.mjs.map +0 -1
- /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-
|
|
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,
|
package/dist/contexts/index.js
CHANGED
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
|
|
34
|
-
var
|
|
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 =
|
|
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
|
package/dist/contexts/index.mjs
CHANGED
|
@@ -21,7 +21,7 @@ var _chunkYBZVWLPHjs = require('../../chunk-YBZVWLPH.js');
|
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
var
|
|
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,
|
|
77
|
-
|
|
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,
|
|
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 =
|
|
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,
|
|
93
|
-
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
94
|
-
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
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,
|
|
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
|
-
|
|
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,
|
|
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 } =
|
|
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,
|
|
123
|
-
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
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,
|
|
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,
|
|
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 } =
|
|
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,
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
-
|
|
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,
|
|
388
|
-
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
389
|
-
/* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
|
|
390
|
-
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
391
|
-
/* @__PURE__ */ _jsxruntime.jsx.call(void 0,
|
|
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 =
|
|
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
|
-
|
|
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,
|
|
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}` }),
|
package/package.json
CHANGED
|
@@ -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
|
|
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
|
|
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
|
+
}
|