@carlonicora/nextjs-jsonapi 1.108.0 → 1.110.0

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 (144) hide show
  1. package/dist/{AssistantInterface-BYgI5z1-.d.mts → AssistantInterface-B1c8FhGA.d.mts} +2 -0
  2. package/dist/{AssistantInterface-DfDcz0gJ.d.ts → AssistantInterface-BBUHxOCd.d.ts} +2 -0
  3. package/dist/{AssistantMessageInterface-BpEhx2pC.d.ts → AssistantMessageInterface-BNzf1etU.d.ts} +16 -1
  4. package/dist/{AssistantMessageInterface-DJ3Me16Y.d.mts → AssistantMessageInterface-DrgHDjZ5.d.mts} +16 -1
  5. package/dist/{AuthComponent-B6DIk8Vf.d.ts → AuthComponent-Cd7lcYif.d.ts} +1 -1
  6. package/dist/{AuthComponent-BKI0ZbtD.d.mts → AuthComponent-DdxCFgUZ.d.mts} +1 -1
  7. package/dist/{BlockNoteEditor-2AXSTGGG.js → BlockNoteEditor-7OKW6HHN.js} +19 -19
  8. package/dist/{BlockNoteEditor-2AXSTGGG.js.map → BlockNoteEditor-7OKW6HHN.js.map} +1 -1
  9. package/dist/{BlockNoteEditor-XVIBGXHF.mjs → BlockNoteEditor-K7IIWM3S.mjs} +4 -4
  10. package/dist/BlockNoteViewer-OPSCTHKJ.mjs +31 -0
  11. package/dist/BlockNoteViewer-OPSCTHKJ.mjs.map +1 -0
  12. package/dist/BlockNoteViewer-UW5VZ5UF.js +31 -0
  13. package/dist/BlockNoteViewer-UW5VZ5UF.js.map +1 -0
  14. package/dist/{auth.interface-BBUgMZzs.d.ts → auth.interface-8b601idJ.d.ts} +1 -1
  15. package/dist/{auth.interface-XYEREOD6.d.mts → auth.interface-CXBF8Mhi.d.mts} +1 -1
  16. package/dist/billing/index.d.mts +41 -41
  17. package/dist/billing/index.d.ts +41 -41
  18. package/dist/billing/index.js +346 -346
  19. package/dist/billing/index.mjs +3 -3
  20. package/dist/{chunk-VLDLERJN.js → chunk-6XWW67F2.js} +29 -9
  21. package/dist/chunk-6XWW67F2.js.map +1 -0
  22. package/dist/{chunk-HC3JFN3C.js → chunk-AKXUNE3A.js} +1004 -862
  23. package/dist/chunk-AKXUNE3A.js.map +1 -0
  24. package/dist/{chunk-CFECWLHH.mjs → chunk-CWVYU4YZ.mjs} +23 -3
  25. package/dist/chunk-CWVYU4YZ.mjs.map +1 -0
  26. package/dist/{chunk-56XBGQGU.mjs → chunk-TXVVZLUQ.mjs} +1422 -1280
  27. package/dist/chunk-TXVVZLUQ.mjs.map +1 -0
  28. package/dist/{chunk-RXXZGPC3.js → chunk-U2HR57MY.js} +265 -113
  29. package/dist/chunk-U2HR57MY.js.map +1 -0
  30. package/dist/chunk-WPAQRB5Q.mjs +7 -0
  31. package/dist/chunk-WPAQRB5Q.mjs.map +1 -0
  32. package/dist/chunk-YBZVWLPH.js +7 -0
  33. package/dist/chunk-YBZVWLPH.js.map +1 -0
  34. package/dist/{chunk-N3NVIPSU.mjs → chunk-ZYPNVEHB.mjs} +235 -83
  35. package/dist/{chunk-N3NVIPSU.mjs.map → chunk-ZYPNVEHB.mjs.map} +1 -1
  36. package/dist/client/index.d.mts +9 -18
  37. package/dist/client/index.d.ts +9 -18
  38. package/dist/client/index.js +4 -4
  39. package/dist/client/index.mjs +3 -3
  40. package/dist/components/index.d.mts +421 -417
  41. package/dist/components/index.d.ts +421 -417
  42. package/dist/components/index.js +6 -4
  43. package/dist/components/index.js.map +1 -1
  44. package/dist/components/index.mjs +5 -3
  45. package/dist/{config-CLQynoaa.d.ts → config-BrkU_Ynz.d.ts} +4 -1
  46. package/dist/{config-k61pe_o2.d.mts → config-snd2ToEB.d.mts} +4 -1
  47. package/dist/contexts/index.d.mts +31 -20
  48. package/dist/contexts/index.d.ts +31 -20
  49. package/dist/contexts/index.js +4 -4
  50. package/dist/contexts/index.mjs +3 -3
  51. package/dist/core/index.d.mts +75 -11
  52. package/dist/core/index.d.ts +75 -11
  53. package/dist/core/index.js +2 -2
  54. package/dist/core/index.mjs +1 -1
  55. package/dist/features/help/index.css +29 -0
  56. package/dist/features/help/index.css.map +1 -0
  57. package/dist/features/help/index.d.mts +74 -0
  58. package/dist/features/help/index.d.ts +74 -0
  59. package/dist/features/help/index.js +522 -0
  60. package/dist/features/help/index.js.map +1 -0
  61. package/dist/features/help/index.mjs +522 -0
  62. package/dist/features/help/index.mjs.map +1 -0
  63. package/dist/features/help/server.d.mts +33 -0
  64. package/dist/features/help/server.d.ts +33 -0
  65. package/dist/features/help/server.js +8 -0
  66. package/dist/features/help/server.js.map +1 -0
  67. package/dist/features/help/server.mjs +8 -0
  68. package/dist/features/help/server.mjs.map +1 -0
  69. package/dist/help-content-config.interface-C5ESIod9.d.mts +13 -0
  70. package/dist/help-content-config.interface-C5ESIod9.d.ts +13 -0
  71. package/dist/index.d.mts +10 -8
  72. package/dist/index.d.ts +10 -8
  73. package/dist/index.js +3 -3
  74. package/dist/index.mjs +2 -2
  75. package/dist/{notification.interface-aLEJbA_g.d.ts → notification.interface-C1T1C2ee.d.ts} +1 -100
  76. package/dist/{notification.interface-DLZGtV7Z.d.mts → notification.interface-DIxR23eS.d.mts} +1 -100
  77. package/dist/{s3.service-CVgLWaDc.d.mts → s3.service-0BTClOYO.d.mts} +2 -2
  78. package/dist/{s3.service-SLlX0Zbz.d.ts → s3.service-CT27Fm1s.d.ts} +2 -2
  79. package/dist/server/index.d.mts +4 -3
  80. package/dist/server/index.d.ts +4 -3
  81. package/dist/server/index.js +3 -3
  82. package/dist/server/index.mjs +1 -1
  83. package/dist/testing/index.d.mts +1 -2
  84. package/dist/testing/index.d.ts +1 -2
  85. package/dist/types-CQSjy7et.d.mts +101 -0
  86. package/dist/types-DHOxe8rc.d.ts +101 -0
  87. package/dist/usePageUrlGenerator-tjq2mlDV.d.ts +14 -0
  88. package/dist/usePageUrlGenerator-uOnyJ6j2.d.mts +14 -0
  89. package/dist/{useSocket-BkxHHujj.d.mts → useSocket-B1fMIr17.d.mts} +1 -1
  90. package/dist/{useSocket-CMDjWFYm.d.ts → useSocket-BdJTBXKv.d.ts} +1 -1
  91. package/package.json +15 -1
  92. package/src/client/config.ts +9 -1
  93. package/src/components/index.ts +1 -0
  94. package/src/components/viewers/BlockNoteViewer.tsx +27 -0
  95. package/src/components/viewers/BlockNoteViewerContainer.tsx +10 -0
  96. package/src/core/registry/helpStore.ts +28 -0
  97. package/src/features/assistant/contexts/AssistantContext.tsx +35 -19
  98. package/src/features/assistant/contexts/__tests__/AssistantContext.spec.tsx +66 -6
  99. package/src/features/assistant/data/Assistant.ts +2 -0
  100. package/src/features/assistant/data/AssistantInterface.ts +2 -0
  101. package/src/features/assistant/data/AssistantService.ts +18 -8
  102. package/src/features/assistant-message/components/parts/MessageSourcesContainer.tsx +4 -0
  103. package/src/features/assistant-message/components/parts/MessageSourcesPanel.tsx +6 -4
  104. package/src/features/assistant-message/components/parts/tabs/ContentsTab.tsx +5 -1
  105. package/src/features/assistant-message/components/parts/tabs/ReferencesTab.tsx +3 -1
  106. package/src/features/assistant-message/data/AssistantMessage.ts +27 -1
  107. package/src/features/assistant-message/data/AssistantMessageInterface.ts +1 -0
  108. package/src/features/assistant-message/data/__tests__/AssistantMessage.spec.ts +7 -3
  109. package/src/features/help/components/HelpArticleBody.tsx +62 -0
  110. package/src/features/help/components/HelpAskAi.tsx +36 -0
  111. package/src/features/help/components/HelpAssistantSheet.tsx +53 -0
  112. package/src/features/help/components/HelpHeader.tsx +40 -0
  113. package/src/features/help/components/HelpHint.tsx +86 -0
  114. package/src/features/help/components/HelpSearchResultRow.tsx +61 -0
  115. package/src/features/help/components/HelpSideNav.tsx +119 -0
  116. package/src/features/help/components/HelpTOC.tsx +49 -0
  117. package/src/features/help/components/__tests__/HelpAskAi.spec.tsx +68 -0
  118. package/src/features/help/components/__tests__/HelpAssistantSheet.spec.tsx +36 -0
  119. package/src/features/help/components/__tests__/HelpHint.spec.tsx +50 -0
  120. package/src/features/help/components/__tests__/HelpSearchResultRow.spec.tsx +58 -0
  121. package/src/features/help/components/__tests__/HelpSideNav.spec.tsx +50 -0
  122. package/src/features/help/contexts/HelpContext.spec.tsx +26 -0
  123. package/src/features/help/contexts/HelpContext.tsx +24 -0
  124. package/src/features/help/hooks/useHelp.ts +1 -0
  125. package/src/features/help/hooks/useHelpFilter.ts +27 -0
  126. package/src/features/help/i18n-keys.ts +34 -0
  127. package/src/features/help/index.ts +24 -0
  128. package/src/features/help/interfaces/help-content-config.interface.ts +12 -0
  129. package/src/features/help/server-entry.ts +11 -0
  130. package/src/features/help/types/help-article.types.ts +35 -0
  131. package/src/features/help/utils/articleUrl.ts +13 -0
  132. package/src/features/how-to/HowToModule.ts +14 -1
  133. package/src/features/how-to/components/forms/HowToEditor.tsx +108 -4
  134. package/src/features/how-to/data/HowTo.spec.ts +43 -0
  135. package/src/features/how-to/data/HowTo.ts +64 -3
  136. package/src/features/how-to/data/HowToInterface.ts +14 -0
  137. package/src/features/how-to/data/HowToService.ts +61 -0
  138. package/src/index.ts +4 -0
  139. package/dist/chunk-56XBGQGU.mjs.map +0 -1
  140. package/dist/chunk-CFECWLHH.mjs.map +0 -1
  141. package/dist/chunk-HC3JFN3C.js.map +0 -1
  142. package/dist/chunk-RXXZGPC3.js.map +0 -1
  143. package/dist/chunk-VLDLERJN.js.map +0 -1
  144. /package/dist/{BlockNoteEditor-XVIBGXHF.mjs.map → BlockNoteEditor-K7IIWM3S.mjs.map} +0 -0
@@ -0,0 +1,522 @@
1
+ "use client";
2
+ import {
3
+ HELP_MODES
4
+ } from "../../chunk-WPAQRB5Q.mjs";
5
+ import {
6
+ AssistantComposer,
7
+ AssistantEmptyState,
8
+ AssistantProvider,
9
+ AssistantThread,
10
+ Button,
11
+ CommandItem,
12
+ Sheet,
13
+ SheetContent,
14
+ SheetDescription,
15
+ SheetHeader,
16
+ SheetTitle,
17
+ SheetTrigger,
18
+ Tooltip,
19
+ TooltipContent,
20
+ TooltipTrigger,
21
+ useAssistantContext,
22
+ useCurrentUserContext,
23
+ usePageUrlGenerator
24
+ } from "../../chunk-TXVVZLUQ.mjs";
25
+ import {
26
+ _getStaticHelpContent
27
+ } from "../../chunk-CWVYU4YZ.mjs";
28
+ import {
29
+ HowToService
30
+ } from "../../chunk-ZYPNVEHB.mjs";
31
+ import "../../chunk-AUXK7QSA.mjs";
32
+ import "../../chunk-C7C7VY4F.mjs";
33
+ import "../../chunk-KK7PYKVI.mjs";
34
+ import "../../chunk-VOXD3ZLY.mjs";
35
+ import {
36
+ __name
37
+ } from "../../chunk-PAWJFY3S.mjs";
38
+
39
+ // src/features/help/contexts/HelpContext.tsx
40
+ import { createContext, useContext } from "react";
41
+ import { jsx } from "react/jsx-runtime";
42
+ var HelpContext = createContext(null);
43
+ function HelpProvider({ children }) {
44
+ const cfg = _getStaticHelpContent();
45
+ if (!cfg) {
46
+ throw new Error(
47
+ "Help content not configured \u2014 call configureJsonApi({ helpContent: {...} }) before importing help components."
48
+ );
49
+ }
50
+ return /* @__PURE__ */ jsx(HelpContext.Provider, { value: cfg, children });
51
+ }
52
+ __name(HelpProvider, "HelpProvider");
53
+ function useHelp() {
54
+ const ctx = useContext(HelpContext);
55
+ if (!ctx) {
56
+ throw new Error("useHelp() called outside <HelpProvider>. Wrap your help route group with <HelpProvider>.");
57
+ }
58
+ return ctx;
59
+ }
60
+ __name(useHelp, "useHelp");
61
+
62
+ // src/features/help/components/HelpHeader.tsx
63
+ import Link from "next/link";
64
+ import Image from "next/image";
65
+ import { useTranslations as useTranslations3 } from "next-intl";
66
+
67
+ // src/features/help/components/HelpAskAi.tsx
68
+ import { useState } from "react";
69
+ import { SparklesIcon } from "lucide-react";
70
+ import { useTranslations as useTranslations2 } from "next-intl";
71
+
72
+ // src/features/help/components/HelpAssistantSheet.tsx
73
+ import { useTranslations } from "next-intl";
74
+ import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
75
+ function HelpAssistantSheet({ open, onOpenChange }) {
76
+ return /* @__PURE__ */ jsx2(Sheet, { open, onOpenChange, children: /* @__PURE__ */ jsx2(
77
+ SheetContent,
78
+ {
79
+ side: "right",
80
+ className: "flex w-full flex-col data-[side=right]:sm:max-w-2xl data-[side=right]:lg:max-w-3xl",
81
+ children: /* @__PURE__ */ jsx2(AssistantProvider, { manageUrl: false, children: /* @__PURE__ */ jsx2(HelpAssistantSheetBody, {}) })
82
+ }
83
+ ) });
84
+ }
85
+ __name(HelpAssistantSheet, "HelpAssistantSheet");
86
+ function HelpAssistantSheetBody() {
87
+ const t = useTranslations();
88
+ const ctx = useAssistantContext();
89
+ const showThread = !!ctx.assistant || ctx.sending || ctx.messages.length > 0;
90
+ const send = /* @__PURE__ */ __name((content) => ctx.sendMessage(content, { howToMode: true }), "send");
91
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
92
+ /* @__PURE__ */ jsxs(SheetHeader, { children: [
93
+ /* @__PURE__ */ jsx2(SheetTitle, { children: t("help.askAi.sheet.title") }),
94
+ /* @__PURE__ */ jsx2(SheetDescription, { children: t("help.askAi.sheet.subtitle") })
95
+ ] }),
96
+ !showThread ? /* @__PURE__ */ jsx2(AssistantEmptyState, { onSend: send }) : /* @__PURE__ */ jsxs(Fragment, { children: [
97
+ /* @__PURE__ */ jsx2(
98
+ AssistantThread,
99
+ {
100
+ messages: ctx.messages,
101
+ sending: ctx.sending,
102
+ status: ctx.status,
103
+ onSelectFollowUp: send,
104
+ failedMessageIds: ctx.failedMessageIds,
105
+ onRetry: ctx.retrySend
106
+ }
107
+ ),
108
+ /* @__PURE__ */ jsx2(AssistantComposer, { onSend: send, disabled: ctx.sending })
109
+ ] })
110
+ ] });
111
+ }
112
+ __name(HelpAssistantSheetBody, "HelpAssistantSheetBody");
113
+
114
+ // src/features/help/components/HelpAskAi.tsx
115
+ import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
116
+ function HelpAskAi() {
117
+ const t = useTranslations2();
118
+ const { currentUser } = useCurrentUserContext();
119
+ const [open, setOpen] = useState(false);
120
+ const disabled = !currentUser;
121
+ if (disabled) {
122
+ return /* @__PURE__ */ jsxs2(Tooltip, { children: [
123
+ /* @__PURE__ */ jsxs2(TooltipTrigger, { render: /* @__PURE__ */ jsx3(Button, { variant: "outline", size: "sm", disabled: true }), children: [
124
+ /* @__PURE__ */ jsx3(SparklesIcon, { className: "h-4 w-4" }),
125
+ t("help.askAi.button")
126
+ ] }),
127
+ /* @__PURE__ */ jsx3(TooltipContent, { children: t("help.askAi.loginTooltip") })
128
+ ] });
129
+ }
130
+ return /* @__PURE__ */ jsxs2(Fragment2, { children: [
131
+ /* @__PURE__ */ jsxs2(Button, { variant: "outline", size: "sm", onClick: () => setOpen(true), children: [
132
+ /* @__PURE__ */ jsx3(SparklesIcon, { className: "h-4 w-4" }),
133
+ t("help.askAi.button")
134
+ ] }),
135
+ /* @__PURE__ */ jsx3(HelpAssistantSheet, { open, onOpenChange: setOpen })
136
+ ] });
137
+ }
138
+ __name(HelpAskAi, "HelpAskAi");
139
+
140
+ // src/features/help/components/HelpHeader.tsx
141
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
142
+ function HelpHeader() {
143
+ const t = useTranslations3();
144
+ const { currentUser } = useCurrentUserContext();
145
+ const { brand } = useHelp();
146
+ const logo = brand?.logo;
147
+ const label = brand?.label ?? "Help";
148
+ const appHref = brand?.appHref ?? "/";
149
+ return /* @__PURE__ */ jsxs3("header", { className: "border-border bg-background flex items-center justify-between border-b px-4 py-3", children: [
150
+ /* @__PURE__ */ jsxs3(Link, { href: "/help", className: "flex items-center gap-2", children: [
151
+ logo ? /* @__PURE__ */ jsx4(Image, { src: logo, alt: label, width: 28, height: 28 }) : null,
152
+ /* @__PURE__ */ jsxs3("span", { className: "text-base font-semibold", children: [
153
+ label,
154
+ " \xB7 ",
155
+ t("help.footerLink")
156
+ ] })
157
+ ] }),
158
+ /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2", children: [
159
+ /* @__PURE__ */ jsx4(HelpAskAi, {}),
160
+ currentUser ? /* @__PURE__ */ jsx4(Button, { render: /* @__PURE__ */ jsx4(Link, { href: appHref }), nativeButton: false, variant: "outline", size: "sm", children: t("help.header.openApp") }) : /* @__PURE__ */ jsx4(Button, { render: /* @__PURE__ */ jsx4(Link, { href: "/login" }), nativeButton: false, variant: "outline", size: "sm", children: t("help.header.login") })
161
+ ] })
162
+ ] });
163
+ }
164
+ __name(HelpHeader, "HelpHeader");
165
+
166
+ // src/features/help/components/HelpSideNav.tsx
167
+ import { useEffect, useMemo as useMemo2, useState as useState3 } from "react";
168
+ import { useTranslations as useTranslations4 } from "next-intl";
169
+ import Link2 from "next/link";
170
+ import { usePathname } from "next/navigation";
171
+
172
+ // src/features/help/hooks/useHelpFilter.ts
173
+ import { useMemo, useState as useState2 } from "react";
174
+ import Fuse from "fuse.js";
175
+ function useHelpFilter(articles) {
176
+ const [query, setQuery] = useState2("");
177
+ const fuse = useMemo(
178
+ () => new Fuse([...articles], {
179
+ keys: [
180
+ { name: "title", weight: 0.5 },
181
+ { name: "summary", weight: 0.3 },
182
+ { name: "tags", weight: 0.1 },
183
+ { name: "headings.text", weight: 0.1 }
184
+ ],
185
+ threshold: 0.4,
186
+ ignoreLocation: true
187
+ }),
188
+ [articles]
189
+ );
190
+ const filtered = useMemo(() => {
191
+ if (!query.trim()) return [...articles];
192
+ return fuse.search(query).map((r) => r.item);
193
+ }, [query, articles, fuse]);
194
+ return { query, setQuery, filtered };
195
+ }
196
+ __name(useHelpFilter, "useHelpFilter");
197
+
198
+ // src/features/help/components/HelpSideNav.tsx
199
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
200
+ function HelpSideNav() {
201
+ const t = useTranslations4();
202
+ const generateUrl = usePageUrlGenerator();
203
+ const pathname = usePathname();
204
+ const [articles, setArticles] = useState3([]);
205
+ useEffect(() => {
206
+ let active = true;
207
+ HowToService.findPublished().then((list) => active && setArticles(list)).catch(() => active && setArticles([]));
208
+ return () => {
209
+ active = false;
210
+ };
211
+ }, []);
212
+ const indexable = useMemo2(
213
+ () => articles.map((a) => ({
214
+ id: a.id,
215
+ title: a.name,
216
+ summary: a.summary ?? "",
217
+ tags: a.tags,
218
+ mode: a.howToType ?? "",
219
+ slug: a.slug ?? ""
220
+ })),
221
+ [articles]
222
+ );
223
+ const { query, setQuery, filtered } = useHelpFilter(indexable);
224
+ const filtering = query.trim().length > 0;
225
+ const groups = useMemo2(
226
+ () => HELP_MODES.map((mode) => ({
227
+ mode,
228
+ articles: articles.filter((a) => a.howToType === mode && !a.draft).sort((x, y) => (x.order ?? 0) - (y.order ?? 0))
229
+ })),
230
+ [articles]
231
+ );
232
+ const isActive = /* @__PURE__ */ __name((mode, slug) => pathname.endsWith(`/help/${mode}/${slug}`), "isActive");
233
+ return /* @__PURE__ */ jsxs4("nav", { "aria-label": "Help navigation", className: "flex h-full flex-col gap-3 overflow-y-auto p-4", children: [
234
+ /* @__PURE__ */ jsx5(
235
+ "input",
236
+ {
237
+ type: "search",
238
+ value: query,
239
+ onChange: (e) => setQuery(e.target.value),
240
+ placeholder: t("help.sideNav.filterPlaceholder"),
241
+ className: "border-input bg-background w-full rounded-md border px-3 py-2 text-sm"
242
+ }
243
+ ),
244
+ filtering ? filtered.length === 0 ? /* @__PURE__ */ jsx5("p", { className: "text-muted-foreground text-sm", children: t("help.sideNav.noMatches") }) : /* @__PURE__ */ jsx5("ul", { className: "space-y-1", children: filtered.map((a) => /* @__PURE__ */ jsx5("li", { children: /* @__PURE__ */ jsx5(
245
+ Link2,
246
+ {
247
+ href: generateUrl({ page: `/help/${a.mode}/${a.slug}` }),
248
+ className: "hover:bg-muted block rounded px-2 py-1 text-sm " + (isActive(a.mode, a.slug) ? "bg-muted font-medium" : ""),
249
+ children: a.title
250
+ }
251
+ ) }, a.id)) }) : groups.map((group) => {
252
+ if (group.articles.length === 0) return null;
253
+ return /* @__PURE__ */ jsxs4("div", { children: [
254
+ /* @__PURE__ */ jsx5(
255
+ Link2,
256
+ {
257
+ href: generateUrl({ page: `/help/${group.mode}` }),
258
+ className: "text-muted-foreground hover:text-foreground mb-1 block text-xs font-semibold tracking-wider uppercase",
259
+ children: t(`help.modes.${group.mode}`)
260
+ }
261
+ ),
262
+ /* @__PURE__ */ jsx5("ul", { className: "space-y-0.5", children: group.articles.map((a) => /* @__PURE__ */ jsx5("li", { children: /* @__PURE__ */ jsx5(
263
+ Link2,
264
+ {
265
+ href: generateUrl({ page: `/help/${a.howToType}/${a.slug}` }),
266
+ className: "hover:bg-muted block rounded px-2 py-1 text-sm " + (isActive(a.howToType ?? "", a.slug ?? "") ? "bg-muted font-medium" : ""),
267
+ children: a.name
268
+ }
269
+ ) }, a.id)) })
270
+ ] }, group.mode);
271
+ })
272
+ ] });
273
+ }
274
+ __name(HelpSideNav, "HelpSideNav");
275
+
276
+ // src/features/help/components/HelpArticleBody.tsx
277
+ import Link3 from "next/link";
278
+ import { useFormatter, useTranslations as useTranslations5 } from "next-intl";
279
+ import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
280
+ function HelpArticleBody(props) {
281
+ const t = useTranslations5();
282
+ const format = useFormatter();
283
+ const generateUrl = usePageUrlGenerator();
284
+ const { howToType, title, summary, updatedAt, prev, next, children } = props;
285
+ return /* @__PURE__ */ jsxs5("article", { className: "prose dark:prose-invert max-w-none", children: [
286
+ /* @__PURE__ */ jsxs5("nav", { className: "text-muted-foreground mb-2 text-xs", children: [
287
+ /* @__PURE__ */ jsx6(Link3, { href: generateUrl({ page: "/help" }), children: "Help" }),
288
+ " \xB7 ",
289
+ /* @__PURE__ */ jsx6(Link3, { href: generateUrl({ page: `/help/${howToType}` }), children: t(`help.modes.${howToType}`) })
290
+ ] }),
291
+ /* @__PURE__ */ jsx6("h1", { children: title }),
292
+ summary ? /* @__PURE__ */ jsx6("p", { className: "text-muted-foreground !mt-0 text-base", children: summary }) : null,
293
+ children,
294
+ /* @__PURE__ */ jsx6("hr", { className: "my-6" }),
295
+ updatedAt ? /* @__PURE__ */ jsx6("div", { className: "text-muted-foreground text-xs", children: /* @__PURE__ */ jsx6("span", { children: t("help.article.lastUpdated", {
296
+ date: format.dateTime(new Date(updatedAt), { dateStyle: "short" })
297
+ }) }) }) : null,
298
+ /* @__PURE__ */ jsxs5("div", { className: "mt-4 flex justify-between text-sm", children: [
299
+ prev ? /* @__PURE__ */ jsxs5(Link3, { href: generateUrl({ page: `/help/${prev.howToType}/${prev.slug}` }), className: "hover:underline", children: [
300
+ "\u2190 ",
301
+ t("help.article.previous"),
302
+ ": ",
303
+ prev.title
304
+ ] }) : /* @__PURE__ */ jsx6("span", {}),
305
+ next ? /* @__PURE__ */ jsxs5(Link3, { href: generateUrl({ page: `/help/${next.howToType}/${next.slug}` }), className: "hover:underline", children: [
306
+ t("help.article.next"),
307
+ ": ",
308
+ next.title,
309
+ " \u2192"
310
+ ] }) : /* @__PURE__ */ jsx6("span", {})
311
+ ] })
312
+ ] });
313
+ }
314
+ __name(HelpArticleBody, "HelpArticleBody");
315
+
316
+ // src/features/help/components/HelpTOC.tsx
317
+ import { useEffect as useEffect2, useState as useState4 } from "react";
318
+ import { useTranslations as useTranslations6 } from "next-intl";
319
+ import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
320
+ function HelpTOC({ headings }) {
321
+ const t = useTranslations6();
322
+ const [active, setActive] = useState4(null);
323
+ useEffect2(() => {
324
+ const observer = new IntersectionObserver(
325
+ (entries) => {
326
+ for (const e of entries) {
327
+ if (e.isIntersecting) setActive(e.target.id);
328
+ }
329
+ },
330
+ { rootMargin: "0px 0px -70% 0px", threshold: 0 }
331
+ );
332
+ headings.forEach((h) => {
333
+ const el = document.getElementById(h.slug);
334
+ if (el) observer.observe(el);
335
+ });
336
+ return () => observer.disconnect();
337
+ }, [headings]);
338
+ if (headings.length === 0) return null;
339
+ return /* @__PURE__ */ jsxs6("nav", { "aria-label": t("help.toc.title"), className: "hidden lg:block", children: [
340
+ /* @__PURE__ */ jsx7("div", { className: "text-muted-foreground mb-2 text-xs font-semibold tracking-wider uppercase", children: t("help.toc.title") }),
341
+ /* @__PURE__ */ jsx7("ul", { className: "space-y-1 text-sm", children: headings.map((h) => /* @__PURE__ */ jsx7("li", { style: { paddingLeft: `${(h.depth - 2) * 0.75}rem` }, children: /* @__PURE__ */ jsx7(
342
+ "a",
343
+ {
344
+ href: `#${h.slug}`,
345
+ className: "block truncate hover:text-foreground " + (active === h.slug ? "text-foreground font-medium" : "text-muted-foreground"),
346
+ children: h.text
347
+ }
348
+ ) }, h.slug)) })
349
+ ] });
350
+ }
351
+ __name(HelpTOC, "HelpTOC");
352
+
353
+ // src/features/help/components/HelpHint.tsx
354
+ import { useEffect as useEffect3, useMemo as useMemo3, useState as useState5 } from "react";
355
+ import { useTranslations as useTranslations7 } from "next-intl";
356
+ import Link4 from "next/link";
357
+ import { HelpCircleIcon } from "lucide-react";
358
+ import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
359
+ function HelpHint({ contextKey }) {
360
+ const t = useTranslations7();
361
+ const generateUrl = usePageUrlGenerator();
362
+ const [open, setOpen] = useState5(false);
363
+ const [picked, setPicked] = useState5(null);
364
+ const [articles, setArticles] = useState5([]);
365
+ useEffect3(() => {
366
+ let active2 = true;
367
+ HowToService.findPublished().then((list) => active2 && setArticles(list)).catch(() => active2 && setArticles([]));
368
+ return () => {
369
+ active2 = false;
370
+ };
371
+ }, []);
372
+ const matches = useMemo3(
373
+ () => articles.filter((a) => a.contextualKeys.includes(contextKey) && !a.draft),
374
+ [articles, contextKey]
375
+ );
376
+ if (matches.length === 0) return null;
377
+ const active = picked ?? (matches.length === 1 ? matches[0] : null);
378
+ return /* @__PURE__ */ jsxs7(
379
+ Sheet,
380
+ {
381
+ open,
382
+ onOpenChange: (o) => {
383
+ setOpen(o);
384
+ if (!o) setPicked(null);
385
+ },
386
+ children: [
387
+ /* @__PURE__ */ jsx8(SheetTrigger, { render: /* @__PURE__ */ jsx8(Button, { variant: "ghost", size: "icon-sm", "aria-label": t("help.hint.trigger") }), children: /* @__PURE__ */ jsx8(HelpCircleIcon, { className: "h-4 w-4" }) }),
388
+ /* @__PURE__ */ jsxs7(SheetContent, { side: "right", className: "w-full max-w-md sm:max-w-lg", children: [
389
+ /* @__PURE__ */ jsxs7(SheetHeader, { children: [
390
+ /* @__PURE__ */ jsx8(SheetTitle, { children: active ? active.name : t("help.hint.pickArticle") }),
391
+ /* @__PURE__ */ jsx8(SheetDescription, { children: active?.summary ?? "" })
392
+ ] }),
393
+ active ? /* @__PURE__ */ jsxs7("div", { className: "mt-4 space-y-3", children: [
394
+ /* @__PURE__ */ jsx8("p", { className: "text-muted-foreground text-sm", children: active.summary }),
395
+ /* @__PURE__ */ jsx8(Link4, { href: generateUrl({ page: `/help/${active.howToType}/${active.slug}` }), className: "text-sm", children: t("help.hint.viewArticle") })
396
+ ] }) : /* @__PURE__ */ jsx8("ul", { className: "mt-4 space-y-1", children: matches.map((a) => /* @__PURE__ */ jsx8("li", { children: /* @__PURE__ */ jsxs7(
397
+ "button",
398
+ {
399
+ type: "button",
400
+ onClick: () => setPicked(a),
401
+ className: "hover:bg-muted block w-full rounded px-2 py-1 text-left text-sm",
402
+ children: [
403
+ /* @__PURE__ */ jsx8("div", { className: "font-medium", children: a.name }),
404
+ /* @__PURE__ */ jsx8("div", { className: "text-muted-foreground text-xs", children: a.summary })
405
+ ]
406
+ }
407
+ ) }, a.id)) })
408
+ ] })
409
+ ]
410
+ }
411
+ );
412
+ }
413
+ __name(HelpHint, "HelpHint");
414
+
415
+ // src/features/help/components/HelpSearchResultRow.tsx
416
+ import Link5 from "next/link";
417
+ import { useTranslations as useTranslations8 } from "next-intl";
418
+ import { useEffect as useEffect4, useState as useState6 } from "react";
419
+ import { LifeBuoyIcon, ArrowUpRightIcon } from "lucide-react";
420
+ import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
421
+ function HelpSearchResultRow({ result, onSelect }) {
422
+ const t = useTranslations8();
423
+ const generateUrl = usePageUrlGenerator();
424
+ const [article, setArticle] = useState6(null);
425
+ useEffect4(() => {
426
+ let active = true;
427
+ HowToService.findOne({ id: result.id }).then((a) => active && setArticle(a)).catch(() => active && setArticle(null));
428
+ return () => {
429
+ active = false;
430
+ };
431
+ }, [result.id]);
432
+ if (!article) {
433
+ return /* @__PURE__ */ jsx9(
434
+ CommandItem,
435
+ {
436
+ value: result.id,
437
+ disabled: true,
438
+ className: "text-muted-foreground cursor-not-allowed px-3 py-1.5 text-sm italic",
439
+ children: t("help.search.removed")
440
+ }
441
+ );
442
+ }
443
+ return /* @__PURE__ */ jsx9(CommandItem, { value: result.id, onSelect, className: "cursor-pointer p-0", children: /* @__PURE__ */ jsxs8(
444
+ Link5,
445
+ {
446
+ href: generateUrl({ page: `/help/${article.howToType}/${article.slug}` }),
447
+ className: "hover:bg-muted flex w-full items-center gap-3 rounded px-3 py-2",
448
+ children: [
449
+ /* @__PURE__ */ jsx9("div", { className: "bg-muted text-muted-foreground flex h-10 w-10 shrink-0 items-center justify-center rounded-full", children: /* @__PURE__ */ jsx9(LifeBuoyIcon, { className: "h-5 w-5" }) }),
450
+ /* @__PURE__ */ jsxs8("div", { className: "flex min-w-0 flex-1 flex-col", children: [
451
+ /* @__PURE__ */ jsx9("span", { className: "text-foreground truncate text-sm font-semibold", children: article.name }),
452
+ /* @__PURE__ */ jsxs8("span", { className: "text-muted-foreground truncate text-xs", children: [
453
+ t(`help.modes.${article.howToType}`),
454
+ " \xB7 ",
455
+ article.summary
456
+ ] })
457
+ ] }),
458
+ /* @__PURE__ */ jsx9(ArrowUpRightIcon, { className: "text-muted-foreground h-5 w-5 shrink-0" })
459
+ ]
460
+ }
461
+ ) });
462
+ }
463
+ __name(HelpSearchResultRow, "HelpSearchResultRow");
464
+
465
+ // src/features/help/utils/articleUrl.ts
466
+ function articleUrl(generateUrl, article) {
467
+ return generateUrl({ page: `/help/${article.mode}/${article.slug}` });
468
+ }
469
+ __name(articleUrl, "articleUrl");
470
+ function modeUrl(generateUrl, mode) {
471
+ return generateUrl({ page: `/help/${mode}` });
472
+ }
473
+ __name(modeUrl, "modeUrl");
474
+
475
+ // src/features/help/i18n-keys.ts
476
+ var HELP_I18N_KEYS = [
477
+ "help.modes.tutorial",
478
+ "help.modes.how-to",
479
+ "help.modes.reference",
480
+ "help.modes.explanation",
481
+ "help.sideNav.filterPlaceholder",
482
+ "help.sideNav.noMatches",
483
+ "help.toc.title",
484
+ "help.article.lastUpdated",
485
+ "help.article.previous",
486
+ "help.article.next",
487
+ "help.article.related",
488
+ "help.askAi.button",
489
+ "help.askAi.loginTooltip",
490
+ "help.askAi.sheet.title",
491
+ "help.askAi.sheet.subtitle",
492
+ "help.header.search",
493
+ "help.header.login",
494
+ "help.header.openApp",
495
+ "help.hint.trigger",
496
+ "help.hint.viewArticle",
497
+ "help.hint.pickArticle",
498
+ "help.landing.heading",
499
+ "help.landing.subheading",
500
+ "help.landing.featuredTutorials",
501
+ "help.landing.browseByMode",
502
+ "help.modeIndex.empty",
503
+ "help.search.removed",
504
+ "help.footerLink"
505
+ ];
506
+ export {
507
+ HELP_I18N_KEYS,
508
+ HELP_MODES,
509
+ HelpArticleBody,
510
+ HelpAskAi,
511
+ HelpHeader,
512
+ HelpHint,
513
+ HelpProvider,
514
+ HelpSearchResultRow,
515
+ HelpSideNav,
516
+ HelpTOC,
517
+ articleUrl,
518
+ modeUrl,
519
+ useHelp,
520
+ useHelpFilter
521
+ };
522
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/features/help/contexts/HelpContext.tsx","../../../src/features/help/components/HelpHeader.tsx","../../../src/features/help/components/HelpAskAi.tsx","../../../src/features/help/components/HelpAssistantSheet.tsx","../../../src/features/help/components/HelpSideNav.tsx","../../../src/features/help/hooks/useHelpFilter.ts","../../../src/features/help/components/HelpArticleBody.tsx","../../../src/features/help/components/HelpTOC.tsx","../../../src/features/help/components/HelpHint.tsx","../../../src/features/help/components/HelpSearchResultRow.tsx","../../../src/features/help/utils/articleUrl.ts","../../../src/features/help/i18n-keys.ts"],"sourcesContent":["\"use client\";\nimport { createContext, useContext, ReactNode } from \"react\";\nimport { _getStaticHelpContent } from \"../../../core/registry/helpStore\";\nimport type { HelpContentConfig } from \"../interfaces/help-content-config.interface\";\n\nconst HelpContext = createContext<HelpContentConfig | null>(null);\n\nexport function HelpProvider({ children }: { children: ReactNode }) {\n const cfg = _getStaticHelpContent<HelpContentConfig>();\n if (!cfg) {\n throw new Error(\n \"Help content not configured — call configureJsonApi({ helpContent: {...} }) before importing help components.\",\n );\n }\n return <HelpContext.Provider value={cfg}>{children}</HelpContext.Provider>;\n}\n\nexport function useHelp(): HelpContentConfig {\n const ctx = useContext(HelpContext);\n if (!ctx) {\n throw new Error(\"useHelp() called outside <HelpProvider>. Wrap your help route group with <HelpProvider>.\");\n }\n return ctx;\n}\n","\"use client\";\nimport Link from \"next/link\";\nimport Image from \"next/image\";\nimport { useTranslations } from \"next-intl\";\nimport { useCurrentUserContext } from \"../../user/contexts/CurrentUserContext\";\nimport { Button } from \"../../../shadcnui\";\nimport { useHelp } from \"../contexts/HelpContext\";\nimport { HelpAskAi } from \"./HelpAskAi\";\n\nexport function HelpHeader() {\n const t = useTranslations();\n const { currentUser } = useCurrentUserContext();\n const { brand } = useHelp();\n const logo = brand?.logo;\n const label = brand?.label ?? \"Help\";\n const appHref = brand?.appHref ?? \"/\";\n\n return (\n <header className=\"border-border bg-background flex items-center justify-between border-b px-4 py-3\">\n <Link href=\"/help\" className=\"flex items-center gap-2\">\n {logo ? <Image src={logo} alt={label} width={28} height={28} /> : null}\n <span className=\"text-base font-semibold\">\n {label} · {t(\"help.footerLink\")}\n </span>\n </Link>\n <div className=\"flex items-center gap-2\">\n <HelpAskAi />\n {currentUser ? (\n <Button render={<Link href={appHref} />} nativeButton={false} variant=\"outline\" size=\"sm\">\n {t(\"help.header.openApp\")}\n </Button>\n ) : (\n <Button render={<Link href=\"/login\" />} nativeButton={false} variant=\"outline\" size=\"sm\">\n {t(\"help.header.login\")}\n </Button>\n )}\n </div>\n </header>\n );\n}\n","\"use client\";\nimport { useState } from \"react\";\nimport { SparklesIcon } from \"lucide-react\";\nimport { useTranslations } from \"next-intl\";\nimport { useCurrentUserContext } from \"../../user/contexts/CurrentUserContext\";\nimport { Button, Tooltip, TooltipTrigger, TooltipContent } from \"../../../shadcnui\";\nimport { HelpAssistantSheet } from \"./HelpAssistantSheet\";\n\nexport function HelpAskAi() {\n const t = useTranslations();\n const { currentUser } = useCurrentUserContext();\n const [open, setOpen] = useState(false);\n const disabled = !currentUser;\n\n if (disabled) {\n return (\n <Tooltip>\n <TooltipTrigger render={<Button variant=\"outline\" size=\"sm\" disabled />}>\n <SparklesIcon className=\"h-4 w-4\" />\n {t(\"help.askAi.button\")}\n </TooltipTrigger>\n <TooltipContent>{t(\"help.askAi.loginTooltip\")}</TooltipContent>\n </Tooltip>\n );\n }\n\n return (\n <>\n <Button variant=\"outline\" size=\"sm\" onClick={() => setOpen(true)}>\n <SparklesIcon className=\"h-4 w-4\" />\n {t(\"help.askAi.button\")}\n </Button>\n <HelpAssistantSheet open={open} onOpenChange={setOpen} />\n </>\n );\n}\n","\"use client\";\nimport { useTranslations } from \"next-intl\";\nimport { Sheet, SheetContent, SheetHeader, SheetTitle, SheetDescription } from \"../../../shadcnui\";\nimport { AssistantProvider, useAssistantContext } from \"../../assistant/contexts/AssistantContext\";\nimport { AssistantThread } from \"../../assistant/components/parts/AssistantThread\";\nimport { AssistantComposer } from \"../../assistant/components/parts/AssistantComposer\";\nimport { AssistantEmptyState } from \"../../assistant/components/parts/AssistantEmptyState\";\n\nexport function HelpAssistantSheet({ open, onOpenChange }: { open: boolean; onOpenChange: (o: boolean) => void }) {\n return (\n <Sheet open={open} onOpenChange={onOpenChange}>\n <SheetContent\n side=\"right\"\n className=\"flex w-full flex-col data-[side=right]:sm:max-w-2xl data-[side=right]:lg:max-w-3xl\"\n >\n <AssistantProvider manageUrl={false}>\n <HelpAssistantSheetBody />\n </AssistantProvider>\n </SheetContent>\n </Sheet>\n );\n}\n\nfunction HelpAssistantSheetBody() {\n const t = useTranslations();\n const ctx = useAssistantContext();\n const showThread = !!ctx.assistant || ctx.sending || ctx.messages.length > 0;\n const send = (content: string) => ctx.sendMessage(content, { howToMode: true });\n\n return (\n <>\n <SheetHeader>\n <SheetTitle>{t(\"help.askAi.sheet.title\")}</SheetTitle>\n <SheetDescription>{t(\"help.askAi.sheet.subtitle\")}</SheetDescription>\n </SheetHeader>\n {!showThread ? (\n <AssistantEmptyState onSend={send} />\n ) : (\n <>\n <AssistantThread\n messages={ctx.messages}\n sending={ctx.sending}\n status={ctx.status}\n onSelectFollowUp={send}\n failedMessageIds={ctx.failedMessageIds}\n onRetry={ctx.retrySend}\n />\n <AssistantComposer onSend={send} disabled={ctx.sending} />\n </>\n )}\n </>\n );\n}\n","\"use client\";\n\nimport { useEffect, useMemo, useState } from \"react\";\nimport { useTranslations } from \"next-intl\";\nimport Link from \"next/link\";\nimport { usePathname } from \"next/navigation\";\nimport { HELP_MODES } from \"../types/help-article.types\";\nimport { usePageUrlGenerator } from \"../../../client\";\nimport { useHelpFilter } from \"../hooks/useHelpFilter\";\nimport { HowToService } from \"../../how-to/data/HowToService\";\nimport type { HowToInterface } from \"../../how-to/data/HowToInterface\";\n\nexport function HelpSideNav() {\n const t = useTranslations();\n const generateUrl = usePageUrlGenerator();\n const pathname = usePathname();\n const [articles, setArticles] = useState<HowToInterface[]>([]);\n\n useEffect(() => {\n let active = true;\n HowToService.findPublished()\n .then((list) => active && setArticles(list))\n .catch(() => active && setArticles([]));\n return () => {\n active = false;\n };\n }, []);\n\n // useHelpFilter indexes by title/summary/tags — map HowTo getters into the shape it expects.\n const indexable = useMemo(\n () =>\n articles.map((a) => ({\n id: a.id,\n title: a.name,\n summary: a.summary ?? \"\",\n tags: a.tags,\n mode: a.howToType ?? \"\",\n slug: a.slug ?? \"\",\n })),\n [articles],\n );\n const { query, setQuery, filtered } = useHelpFilter(indexable as any);\n const filtering = query.trim().length > 0;\n\n const groups = useMemo(\n () =>\n HELP_MODES.map((mode) => ({\n mode,\n articles: articles\n .filter((a) => a.howToType === mode && !a.draft)\n .sort((x, y) => (x.order ?? 0) - (y.order ?? 0)),\n })),\n [articles],\n );\n\n const isActive = (mode: string, slug: string) => pathname.endsWith(`/help/${mode}/${slug}`);\n\n return (\n <nav aria-label=\"Help navigation\" className=\"flex h-full flex-col gap-3 overflow-y-auto p-4\">\n <input\n type=\"search\"\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n placeholder={t(\"help.sideNav.filterPlaceholder\")}\n className=\"border-input bg-background w-full rounded-md border px-3 py-2 text-sm\"\n />\n {filtering ? (\n (filtered as any[]).length === 0 ? (\n <p className=\"text-muted-foreground text-sm\">{t(\"help.sideNav.noMatches\")}</p>\n ) : (\n <ul className=\"space-y-1\">\n {(filtered as any[]).map((a) => (\n <li key={a.id}>\n <Link\n href={generateUrl({ page: `/help/${a.mode}/${a.slug}` })}\n className={\n \"hover:bg-muted block rounded px-2 py-1 text-sm \" +\n (isActive(a.mode, a.slug) ? \"bg-muted font-medium\" : \"\")\n }\n >\n {a.title}\n </Link>\n </li>\n ))}\n </ul>\n )\n ) : (\n groups.map((group) => {\n if (group.articles.length === 0) return null;\n return (\n <div key={group.mode}>\n <Link\n href={generateUrl({ page: `/help/${group.mode}` })}\n className=\"text-muted-foreground hover:text-foreground mb-1 block text-xs font-semibold tracking-wider uppercase\"\n >\n {t(`help.modes.${group.mode}`)}\n </Link>\n <ul className=\"space-y-0.5\">\n {group.articles.map((a) => (\n <li key={a.id}>\n <Link\n href={generateUrl({ page: `/help/${a.howToType}/${a.slug}` })}\n className={\n \"hover:bg-muted block rounded px-2 py-1 text-sm \" +\n (isActive(a.howToType ?? \"\", a.slug ?? \"\") ? \"bg-muted font-medium\" : \"\")\n }\n >\n {a.name}\n </Link>\n </li>\n ))}\n </ul>\n </div>\n );\n })\n )}\n </nav>\n );\n}\n","\"use client\";\nimport { useMemo, useState } from \"react\";\nimport Fuse from \"fuse.js\";\nimport type { HelpArticle } from \"../types/help-article.types\";\n\nexport function useHelpFilter(articles: readonly HelpArticle[]) {\n const [query, setQuery] = useState(\"\");\n const fuse = useMemo(\n () =>\n new Fuse([...articles], {\n keys: [\n { name: \"title\", weight: 0.5 },\n { name: \"summary\", weight: 0.3 },\n { name: \"tags\", weight: 0.1 },\n { name: \"headings.text\", weight: 0.1 },\n ],\n threshold: 0.4,\n ignoreLocation: true,\n }),\n [articles],\n );\n const filtered = useMemo(() => {\n if (!query.trim()) return [...articles];\n return fuse.search(query).map((r) => r.item);\n }, [query, articles, fuse]);\n return { query, setQuery, filtered };\n}\n","\"use client\";\n\nimport { ReactNode } from \"react\";\nimport Link from \"next/link\";\nimport { useFormatter, useTranslations } from \"next-intl\";\nimport { usePageUrlGenerator } from \"../../../client\";\n\ntype Sibling = { howToType: string; slug: string; title: string };\n\nexport function HelpArticleBody(props: {\n howToType: string;\n title: string;\n summary?: string;\n updatedAt?: string;\n prev?: Sibling | null;\n next?: Sibling | null;\n children: ReactNode;\n}) {\n const t = useTranslations();\n const format = useFormatter();\n const generateUrl = usePageUrlGenerator();\n const { howToType, title, summary, updatedAt, prev, next, children } = props;\n\n return (\n <article className=\"prose dark:prose-invert max-w-none\">\n <nav className=\"text-muted-foreground mb-2 text-xs\">\n <Link href={generateUrl({ page: \"/help\" })}>Help</Link>\n {\" · \"}\n <Link href={generateUrl({ page: `/help/${howToType}` })}>{t(`help.modes.${howToType}`)}</Link>\n </nav>\n <h1>{title}</h1>\n {summary ? <p className=\"text-muted-foreground !mt-0 text-base\">{summary}</p> : null}\n {children}\n <hr className=\"my-6\" />\n {updatedAt ? (\n <div className=\"text-muted-foreground text-xs\">\n <span>\n {t(\"help.article.lastUpdated\", {\n date: format.dateTime(new Date(updatedAt), { dateStyle: \"short\" }),\n })}\n </span>\n </div>\n ) : null}\n <div className=\"mt-4 flex justify-between text-sm\">\n {prev ? (\n <Link href={generateUrl({ page: `/help/${prev.howToType}/${prev.slug}` })} className=\"hover:underline\">\n ← {t(\"help.article.previous\")}: {prev.title}\n </Link>\n ) : (\n <span />\n )}\n {next ? (\n <Link href={generateUrl({ page: `/help/${next.howToType}/${next.slug}` })} className=\"hover:underline\">\n {t(\"help.article.next\")}: {next.title} →\n </Link>\n ) : (\n <span />\n )}\n </div>\n </article>\n );\n}\n","\"use client\";\nimport { useEffect, useState } from \"react\";\nimport { useTranslations } from \"next-intl\";\nimport type { HelpHeading } from \"../types/help-article.types\";\n\nexport function HelpTOC({ headings }: { headings: readonly HelpHeading[] }) {\n const t = useTranslations();\n const [active, setActive] = useState<string | null>(null);\n\n useEffect(() => {\n const observer = new IntersectionObserver(\n (entries) => {\n for (const e of entries) {\n if (e.isIntersecting) setActive(e.target.id);\n }\n },\n { rootMargin: \"0px 0px -70% 0px\", threshold: 0 },\n );\n headings.forEach((h) => {\n const el = document.getElementById(h.slug);\n if (el) observer.observe(el);\n });\n return () => observer.disconnect();\n }, [headings]);\n\n if (headings.length === 0) return null;\n return (\n <nav aria-label={t(\"help.toc.title\")} className=\"hidden lg:block\">\n <div className=\"text-muted-foreground mb-2 text-xs font-semibold tracking-wider uppercase\">\n {t(\"help.toc.title\")}\n </div>\n <ul className=\"space-y-1 text-sm\">\n {headings.map((h) => (\n <li key={h.slug} style={{ paddingLeft: `${(h.depth - 2) * 0.75}rem` }}>\n <a\n href={`#${h.slug}`}\n className={\n \"block truncate hover:text-foreground \" +\n (active === h.slug ? \"text-foreground font-medium\" : \"text-muted-foreground\")\n }\n >\n {h.text}\n </a>\n </li>\n ))}\n </ul>\n </nav>\n );\n}\n","\"use client\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport { useTranslations } from \"next-intl\";\nimport Link from \"next/link\";\nimport { HelpCircleIcon } from \"lucide-react\";\nimport {\n Button,\n Sheet,\n SheetContent,\n SheetTrigger,\n SheetHeader,\n SheetTitle,\n SheetDescription,\n} from \"../../../shadcnui\";\nimport { usePageUrlGenerator } from \"../../../client\";\nimport { HowToService } from \"../../how-to/data/HowToService\";\nimport type { HowToInterface } from \"../../how-to/data/HowToInterface\";\n\nexport function HelpHint({ contextKey }: { contextKey: string }) {\n const t = useTranslations();\n const generateUrl = usePageUrlGenerator();\n const [open, setOpen] = useState(false);\n const [picked, setPicked] = useState<HowToInterface | null>(null);\n\n const [articles, setArticles] = useState<HowToInterface[]>([]);\n useEffect(() => {\n let active = true;\n HowToService.findPublished()\n .then((list) => active && setArticles(list))\n .catch(() => active && setArticles([]));\n return () => {\n active = false;\n };\n }, []);\n\n const matches = useMemo(\n () => articles.filter((a) => a.contextualKeys.includes(contextKey) && !a.draft),\n [articles, contextKey],\n );\n\n if (matches.length === 0) return null;\n const active = picked ?? (matches.length === 1 ? matches[0] : null);\n\n return (\n <Sheet\n open={open}\n onOpenChange={(o) => {\n setOpen(o);\n if (!o) setPicked(null);\n }}\n >\n <SheetTrigger render={<Button variant=\"ghost\" size=\"icon-sm\" aria-label={t(\"help.hint.trigger\")} />}>\n <HelpCircleIcon className=\"h-4 w-4\" />\n </SheetTrigger>\n <SheetContent side=\"right\" className=\"w-full max-w-md sm:max-w-lg\">\n <SheetHeader>\n <SheetTitle>{active ? active.name : t(\"help.hint.pickArticle\")}</SheetTitle>\n <SheetDescription>{active?.summary ?? \"\"}</SheetDescription>\n </SheetHeader>\n {active ? (\n <div className=\"mt-4 space-y-3\">\n <p className=\"text-muted-foreground text-sm\">{active.summary}</p>\n <Link href={generateUrl({ page: `/help/${active.howToType}/${active.slug}` })} className=\"text-sm\">\n {t(\"help.hint.viewArticle\")}\n </Link>\n </div>\n ) : (\n <ul className=\"mt-4 space-y-1\">\n {matches.map((a) => (\n <li key={a.id}>\n <button\n type=\"button\"\n onClick={() => setPicked(a)}\n className=\"hover:bg-muted block w-full rounded px-2 py-1 text-left text-sm\"\n >\n <div className=\"font-medium\">{a.name}</div>\n <div className=\"text-muted-foreground text-xs\">{a.summary}</div>\n </button>\n </li>\n ))}\n </ul>\n )}\n </SheetContent>\n </Sheet>\n );\n}\n","\"use client\";\nimport Link from \"next/link\";\nimport { useTranslations } from \"next-intl\";\nimport { useEffect, useState } from \"react\";\nimport { LifeBuoyIcon, ArrowUpRightIcon } from \"lucide-react\";\nimport { CommandItem } from \"../../../shadcnui\";\nimport { usePageUrlGenerator } from \"../../../client\";\nimport { HowToService } from \"../../how-to/data/HowToService\";\nimport type { HowToInterface } from \"../../how-to/data/HowToInterface\";\n\nexport interface HelpSearchResultRowProps {\n result: { id: string; name: string; entityType: string };\n onSelect?: () => void;\n}\n\nexport function HelpSearchResultRow({ result, onSelect }: HelpSearchResultRowProps) {\n const t = useTranslations();\n const generateUrl = usePageUrlGenerator();\n const [article, setArticle] = useState<HowToInterface | null>(null);\n useEffect(() => {\n let active = true;\n HowToService.findOne({ id: result.id })\n .then((a) => active && setArticle(a))\n .catch(() => active && setArticle(null));\n return () => {\n active = false;\n };\n }, [result.id]);\n\n if (!article) {\n return (\n <CommandItem\n value={result.id}\n disabled\n className=\"text-muted-foreground cursor-not-allowed px-3 py-1.5 text-sm italic\"\n >\n {t(\"help.search.removed\")}\n </CommandItem>\n );\n }\n\n return (\n <CommandItem value={result.id} onSelect={onSelect} className=\"cursor-pointer p-0\">\n <Link\n href={generateUrl({ page: `/help/${article.howToType}/${article.slug}` })}\n className=\"hover:bg-muted flex w-full items-center gap-3 rounded px-3 py-2\"\n >\n <div className=\"bg-muted text-muted-foreground flex h-10 w-10 shrink-0 items-center justify-center rounded-full\">\n <LifeBuoyIcon className=\"h-5 w-5\" />\n </div>\n <div className=\"flex min-w-0 flex-1 flex-col\">\n <span className=\"text-foreground truncate text-sm font-semibold\">{article.name}</span>\n <span className=\"text-muted-foreground truncate text-xs\">\n {t(`help.modes.${article.howToType}`)} · {article.summary}\n </span>\n </div>\n <ArrowUpRightIcon className=\"text-muted-foreground h-5 w-5 shrink-0\" />\n </Link>\n </CommandItem>\n );\n}\n","import type { HelpMode } from \"../types/help-article.types\";\nimport type { usePageUrlGenerator } from \"../../../client\";\n\nexport function articleUrl(\n generateUrl: ReturnType<typeof usePageUrlGenerator>,\n article: { mode: HelpMode; slug: string },\n): string {\n return generateUrl({ page: `/help/${article.mode}/${article.slug}` });\n}\n\nexport function modeUrl(generateUrl: ReturnType<typeof usePageUrlGenerator>, mode: HelpMode): string {\n return generateUrl({ page: `/help/${mode}` });\n}\n","/**\n * The fixed namespace of i18n keys this feature reads via useTranslations/getTranslations.\n * Consuming apps must define each entry in their messages/<locale>.json.\n */\nexport const HELP_I18N_KEYS = [\n \"help.modes.tutorial\",\n \"help.modes.how-to\",\n \"help.modes.reference\",\n \"help.modes.explanation\",\n \"help.sideNav.filterPlaceholder\",\n \"help.sideNav.noMatches\",\n \"help.toc.title\",\n \"help.article.lastUpdated\",\n \"help.article.previous\",\n \"help.article.next\",\n \"help.article.related\",\n \"help.askAi.button\",\n \"help.askAi.loginTooltip\",\n \"help.askAi.sheet.title\",\n \"help.askAi.sheet.subtitle\",\n \"help.header.search\",\n \"help.header.login\",\n \"help.header.openApp\",\n \"help.hint.trigger\",\n \"help.hint.viewArticle\",\n \"help.hint.pickArticle\",\n \"help.landing.heading\",\n \"help.landing.subheading\",\n \"help.landing.featuredTutorials\",\n \"help.landing.browseByMode\",\n \"help.modeIndex.empty\",\n \"help.search.removed\",\n \"help.footerLink\",\n] as const;\n"],"mappings":"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","names":["useTranslations","useTranslations","jsx","Fragment","jsx","jsxs","useTranslations","jsx","jsxs","useTranslations","useMemo","useState","useTranslations","Link","useState","useState","jsx","jsxs","useTranslations","useState","useMemo","Link","Link","useTranslations","jsx","jsxs","useTranslations","Link","useEffect","useState","useTranslations","jsx","jsxs","useTranslations","useState","useEffect","useEffect","useMemo","useState","useTranslations","Link","jsx","jsxs","useTranslations","useState","useEffect","active","useMemo","Link","Link","useTranslations","useEffect","useState","jsx","jsxs","useTranslations","useState","useEffect","Link"]}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Help-article types for the frontend help feature. Self-contained — the
3
+ * published frontend library stays decoupled from `@carlonicora/nestjs-neo4jsonapi`.
4
+ */
5
+ declare const HELP_MODES: readonly ["tutorial", "how-to", "reference", "explanation"];
6
+ type HelpMode = (typeof HELP_MODES)[number];
7
+ interface HelpHeading {
8
+ depth: 2 | 3;
9
+ slug: string;
10
+ text: string;
11
+ }
12
+ interface HelpArticle {
13
+ id: string;
14
+ slug: string;
15
+ mode: HelpMode;
16
+ title: string;
17
+ summary: string;
18
+ order: number;
19
+ tags: readonly string[];
20
+ contextualKeys: readonly string[];
21
+ aiIndexed: boolean;
22
+ draft: boolean;
23
+ path: string;
24
+ headings: readonly HelpHeading[];
25
+ relatedSlugs: readonly string[];
26
+ lastUpdated: string;
27
+ }
28
+ interface HelpRedirect {
29
+ from: string;
30
+ to: string;
31
+ }
32
+
33
+ export { HELP_MODES, type HelpArticle, type HelpHeading, type HelpMode, type HelpRedirect };