zudoku 0.3.0-dev.96 → 0.3.0-dev.98

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 (38) hide show
  1. package/dist/app/main.js +4 -0
  2. package/dist/app/main.js.map +1 -1
  3. package/dist/config/validators/validate.d.ts +54 -0
  4. package/dist/config/validators/validate.js +8 -0
  5. package/dist/config/validators/validate.js.map +1 -1
  6. package/dist/lib/components/Header.js +3 -2
  7. package/dist/lib/components/Header.js.map +1 -1
  8. package/dist/lib/components/Search.d.ts +1 -0
  9. package/dist/lib/components/Search.js +37 -0
  10. package/dist/lib/components/Search.js.map +1 -0
  11. package/dist/lib/core/plugins.d.ts +8 -1
  12. package/dist/lib/core/plugins.js +1 -0
  13. package/dist/lib/core/plugins.js.map +1 -1
  14. package/dist/lib/plugins/search-inkeep/InkeepCustomTrigger.d.ts +2 -0
  15. package/dist/lib/plugins/search-inkeep/InkeepCustomTrigger.js +3 -0
  16. package/dist/lib/plugins/search-inkeep/InkeepCustomTrigger.js.map +1 -0
  17. package/dist/lib/plugins/search-inkeep/index.d.ts +6 -0
  18. package/dist/lib/plugins/search-inkeep/index.js +21 -0
  19. package/dist/lib/plugins/search-inkeep/index.js.map +1 -0
  20. package/dist/lib/plugins/search-inkeep/inkeep.d.ts +6 -0
  21. package/dist/lib/plugins/search-inkeep/inkeep.js +37 -0
  22. package/dist/lib/plugins/search-inkeep/inkeep.js.map +1 -0
  23. package/dist/vite/plugin-component.js +1 -0
  24. package/dist/vite/plugin-component.js.map +1 -1
  25. package/lib/InkeepCustomTrigger-CE5-K5ex.js +6 -0
  26. package/lib/InkeepCustomTrigger-CE5-K5ex.js.map +1 -0
  27. package/lib/zudoku.components.js +677 -632
  28. package/lib/zudoku.components.js.map +1 -1
  29. package/lib/zudoku.plugin-search-inkeep.js +56 -0
  30. package/lib/zudoku.plugin-search-inkeep.js.map +1 -0
  31. package/package.json +7 -2
  32. package/src/app/main.tsx +4 -0
  33. package/src/lib/components/Header.tsx +3 -10
  34. package/src/lib/components/Search.tsx +60 -0
  35. package/src/lib/core/plugins.ts +14 -1
  36. package/src/lib/plugins/search-inkeep/InkeepCustomTrigger.tsx +3 -0
  37. package/src/lib/plugins/search-inkeep/index.tsx +55 -0
  38. package/src/lib/plugins/search-inkeep/inkeep.ts +47 -0
@@ -0,0 +1,56 @@
1
+ import { j as n } from "./jsx-runtime-B6kdoens.js";
2
+ import { lazy as a } from "react";
3
+ const r = {
4
+ apiKey: "499c156cf7a9798343949c8bb5665ac95e48132c6d68c42e",
5
+ integrationId: "clot3asdz0000s601nc8jwnzx",
6
+ organizationId: "org_dDOlt2uJlMWM8oIS",
7
+ primaryBrandColor: "#ff00bd",
8
+ organizationDisplayName: "Zuplo",
9
+ theme: {
10
+ components: {
11
+ AIChatPageWrapper: {
12
+ defaultProps: {
13
+ size: "shrink-vertically",
14
+ variant: "no-shadow"
15
+ }
16
+ },
17
+ SearchBarTrigger: {
18
+ defaultProps: {
19
+ size: "expand",
20
+ variant: "subtle"
21
+ // Choose from 'emphasized' or 'subtle'
22
+ }
23
+ }
24
+ }
25
+ }
26
+ }, s = {
27
+ shareChatUrlBasePath: `${process.env.NODE_ENV === "development" ? "http://localhost:3000" : "https://zuplo.com"}/docs/ask`,
28
+ isChatSharingEnabled: !0,
29
+ quickQuestions: [
30
+ "How do I create a custom policy?",
31
+ "What is the difference between production and preview environments?",
32
+ "How do I set a custom domain?",
33
+ "How do I use environment variables?"
34
+ ]
35
+ }, i = a(() => import("./InkeepCustomTrigger-CE5-K5ex.js")), c = ({
36
+ prefilledQuery: t,
37
+ isOpen: e,
38
+ onClose: o
39
+ }) => /* @__PURE__ */ n.jsx(
40
+ i,
41
+ {
42
+ isOpen: e,
43
+ onClose: o,
44
+ baseSettings: r,
45
+ aiChatSettings: s,
46
+ searchSettings: {
47
+ prefilledQuery: t || void 0
48
+ }
49
+ }
50
+ ), d = (t) => ({
51
+ onRequestSearch: (e) => typeof window > "u" ? null : /* @__PURE__ */ n.jsx(c, { isOpen: e.isOpen, onClose: e.onClose, ...t })
52
+ });
53
+ export {
54
+ d as inkeepSearchPlugin
55
+ };
56
+ //# sourceMappingURL=zudoku.plugin-search-inkeep.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zudoku.plugin-search-inkeep.js","sources":["../src/lib/plugins/search-inkeep/inkeep.ts","../src/lib/plugins/search-inkeep/index.tsx"],"sourcesContent":["import {\n InkeepAIChatSettings,\n InkeepModalSettings,\n InkeepSearchSettings,\n InkeepWidgetBaseSettings,\n} from \"@inkeep/widgets\";\n\nconst baseSettings: InkeepWidgetBaseSettings = {\n apiKey: \"499c156cf7a9798343949c8bb5665ac95e48132c6d68c42e\",\n integrationId: \"clot3asdz0000s601nc8jwnzx\",\n organizationId: \"org_dDOlt2uJlMWM8oIS\",\n primaryBrandColor: \"#ff00bd\",\n organizationDisplayName: \"Zuplo\",\n theme: {\n components: {\n AIChatPageWrapper: {\n defaultProps: {\n size: \"shrink-vertically\",\n variant: \"no-shadow\",\n },\n },\n SearchBarTrigger: {\n defaultProps: {\n size: \"expand\",\n variant: \"subtle\", // Choose from 'emphasized' or 'subtle'\n },\n },\n },\n },\n};\n\nconst modalSettings: InkeepModalSettings = {};\n\nconst searchSettings: InkeepSearchSettings = {};\n\nconst aiChatSettings: InkeepAIChatSettings = {\n shareChatUrlBasePath: `${process.env.NODE_ENV === \"development\" ? \"http://localhost:3000\" : \"https://zuplo.com\"}/docs/ask`,\n isChatSharingEnabled: true,\n quickQuestions: [\n \"How do I create a custom policy?\",\n \"What is the difference between production and preview environments?\",\n \"How do I set a custom domain?\",\n \"How do I use environment variables?\",\n ],\n};\n\nexport { aiChatSettings, baseSettings, modalSettings, searchSettings };\n","import type { InkeepWidgetBaseSettings } from \"@inkeep/widgets\";\nimport { lazy } from \"react\";\nimport type { DevPortalPlugin } from \"../../core/plugins.js\";\nimport { aiChatSettings, baseSettings } from \"./inkeep.js\";\n\ntype PickedPluginInkeepBaseSettings =\n | \"apiKey\"\n | \"integrationId\"\n | \"organizationId\"\n | \"primaryBrandColor\"\n | \"organizationDisplayName\";\n\ntype PluginInkeepBaseSettings = Pick<\n InkeepWidgetBaseSettings,\n PickedPluginInkeepBaseSettings\n>;\n\nconst Inkeep = lazy(() => import(\"./InkeepCustomTrigger.js\"));\n//.then((module) => module.InkeepCustomTrigger)\nconst InkeepSearch = ({\n prefilledQuery,\n isOpen,\n onClose,\n}: {\n isOpen: boolean;\n onClose: () => void;\n prefilledQuery?: string | null;\n} & PluginInkeepBaseSettings) => {\n return (\n <Inkeep\n isOpen={isOpen}\n onClose={onClose}\n baseSettings={baseSettings}\n aiChatSettings={aiChatSettings}\n searchSettings={{\n prefilledQuery: prefilledQuery || undefined,\n }}\n />\n );\n};\n\nexport const inkeepSearchPlugin = (\n settings: PluginInkeepBaseSettings,\n): DevPortalPlugin => {\n return {\n onRequestSearch: (o: { isOpen: boolean; onClose: () => void }) => {\n if (typeof window === \"undefined\") {\n return null;\n }\n return (\n <InkeepSearch isOpen={o.isOpen} onClose={o.onClose} {...settings} />\n );\n },\n };\n};\n"],"names":["baseSettings","aiChatSettings","Inkeep","lazy","InkeepSearch","prefilledQuery","isOpen","onClose","jsx","inkeepSearchPlugin","settings","o"],"mappings":";;AAOA,MAAMA,IAAyC;AAAA,EAC7C,QAAQ;AAAA,EACR,eAAe;AAAA,EACf,gBAAgB;AAAA,EAChB,mBAAmB;AAAA,EACnB,yBAAyB;AAAA,EACzB,OAAO;AAAA,IACL,YAAY;AAAA,MACV,mBAAmB;AAAA,QACjB,cAAc;AAAA,UACZ,MAAM;AAAA,UACN,SAAS;AAAA,QACX;AAAA,MACF;AAAA,MACA,kBAAkB;AAAA,QAChB,cAAc;AAAA,UACZ,MAAM;AAAA,UACN,SAAS;AAAA;AAAA,QACX;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF,GAMMC,IAAuC;AAAA,EAC3C,sBAAsB,GAAG,QAAQ,IAAI,aAAa,gBAAgB,0BAA0B,mBAAmB;AAAA,EAC/G,sBAAsB;AAAA,EACtB,gBAAgB;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF,GC3BMC,IAASC,EAAK,MAAM,OAAO,mCAA0B,CAAC,GAEtDC,IAAe,CAAC;AAAA,EACpB,gBAAAC;AAAA,EACA,QAAAC;AAAA,EACA,SAAAC;AACF,MAMIC,gBAAAA,EAAA;AAAA,EAACN;AAAA,EAAA;AAAA,IACC,QAAAI;AAAA,IACA,SAAAC;AAAA,IACA,cAAAP;AAAA,IACA,gBAAAC;AAAA,IACA,gBAAgB;AAAA,MACd,gBAAgBI,KAAkB;AAAA,IACpC;AAAA,EAAA;AAAA,GAKOI,IAAqB,CAChCC,OAEO;AAAA,EACL,iBAAiB,CAACC,MACZ,OAAO,SAAW,MACb,OAGPH,gBAAAA,MAACJ,KAAa,QAAQO,EAAE,QAAQ,SAASA,EAAE,SAAU,GAAGD,EAAU,CAAA;AAEtE;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zudoku",
3
- "version": "0.3.0-dev.96",
3
+ "version": "0.3.0-dev.98",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",
@@ -54,6 +54,10 @@
54
54
  "import": "./lib/zudoku.plugin-custom-page.js",
55
55
  "types": "./dist/lib/plugins/custom-page/index.d.ts"
56
56
  },
57
+ "./plugins/search-inkeep": {
58
+ "import": "./lib/zudoku.plugin-search-inkeep.js",
59
+ "types": "./dist/lib/plugins/search-inkeep/index.d.ts"
60
+ },
57
61
  "./openapi-worker": {
58
62
  "import": "./lib/zudoku.openapi-worker.js",
59
63
  "types": "./dist/lib/plugins/openapi-worker.d.ts"
@@ -180,7 +184,8 @@
180
184
  "react-dom": ">18.0.0"
181
185
  },
182
186
  "optionalDependencies": {
183
- "@clerk/clerk-js": "5.11.0"
187
+ "@clerk/clerk-js": "5.11.0",
188
+ "@inkeep/widgets": "^0.2.289"
184
189
  },
185
190
  "scripts": {
186
191
  "build": "tsc --project tsconfig.json",
package/src/app/main.tsx CHANGED
@@ -11,6 +11,7 @@ import { isNavigationPlugin } from "zudoku/internal";
11
11
  import { customPagePlugin } from "zudoku/plugins/custom-page";
12
12
  import type { ZudokuConfig } from "../config/config.js";
13
13
  import type { ZudokuContextOptions } from "../lib/core/DevPortalContext.js";
14
+ import { inkeepSearchPlugin } from "../lib/plugins/search-inkeep/index.js";
14
15
 
15
16
  export const convertZudokuConfigToOptions = (
16
17
  config: ZudokuConfig,
@@ -41,6 +42,9 @@ export const convertZudokuConfigToOptions = (
41
42
  mdx: config.mdx,
42
43
  authentication: configuredAuthProvider,
43
44
  plugins: [
45
+ ...(config.search?.type === "inkeep"
46
+ ? [inkeepSearchPlugin(config.search)]
47
+ : []),
44
48
  ...configuredDocsPlugins,
45
49
  ...configuredApiPlugins,
46
50
  ...(configuredRedirectPlugin ? [configuredRedirectPlugin] : []),
@@ -18,9 +18,10 @@ import {
18
18
  DropdownMenuTrigger,
19
19
  } from "../ui/DropdownMenu.js";
20
20
  import { cn } from "../util/cn.js";
21
- import { TopNavigation } from "./TopNavigation.js";
22
21
  import { useTheme } from "./context/ThemeContext.js";
23
22
  import { useZudoku } from "./context/ZudokuContext.js";
23
+ import { Search } from "./Search.js";
24
+ import { TopNavigation } from "./TopNavigation.js";
24
25
 
25
26
  const RecursiveMenu = ({ item }: { item: ProfileNavigationItem }) => {
26
27
  return item.children ? (
@@ -89,15 +90,7 @@ export const Header = memo(function HeaderInner() {
89
90
  </div>
90
91
  <div className="grid grid-cols-[--sidecar-grid-cols] items-center gap-8">
91
92
  <div className="w-full max-w-prose">
92
- {/*<button className="flex items-center border border-input hover:bg-accent hover:text-accent-foreground p-4 relative h-8 justify-start rounded-lg bg-background text-sm text-muted-foreground shadow-none w-40 sm:w-72">
93
- <div className="flex items-center gap-2 flex-grow">
94
- <SearchIcon size={14} />
95
- Search
96
- </div>
97
- <kbd className="absolute right-[0.3rem] top-[0.3rem] hidden h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[11px] font-medium opacity-100 sm:flex">
98
- ⌘K
99
- </kbd>
100
- </button>*/}
93
+ <Search />
101
94
  </div>
102
95
 
103
96
  <div className="items-center justify-self-end text-sm hidden lg:flex gap-2">
@@ -0,0 +1,60 @@
1
+ import { SearchIcon } from "lucide-react";
2
+ import { useCallback, useEffect, useState } from "react";
3
+ import { isSearchPlugin } from "../core/plugins.js";
4
+ import { useZudoku } from "./context/ZudokuContext.js";
5
+
6
+ export const Search = () => {
7
+ const ctx = useZudoku();
8
+ const [isOpen, setIsOpen] = useState(true);
9
+
10
+ const onClose = useCallback(() => {
11
+ setIsOpen(false);
12
+ }, []);
13
+
14
+ useEffect(() => {
15
+ if (isOpen) {
16
+ return;
17
+ }
18
+
19
+ function onKeyDown(event: KeyboardEvent) {
20
+ if (event.key === "k" && (event.metaKey || event.ctrlKey)) {
21
+ event.preventDefault();
22
+ setIsOpen(true);
23
+ }
24
+ }
25
+
26
+ window.addEventListener("keydown", onKeyDown);
27
+
28
+ return () => {
29
+ window.removeEventListener("keydown", onKeyDown);
30
+ };
31
+ }, [isOpen, setIsOpen]);
32
+
33
+ const searchPlugin = ctx.plugins.find(isSearchPlugin);
34
+
35
+ if (!searchPlugin) {
36
+ return null;
37
+ }
38
+
39
+ return (
40
+ <>
41
+ <button
42
+ type="button"
43
+ className="flex items-center border border-input hover:bg-accent hover:text-accent-foreground p-4 relative h-8 justify-start rounded-lg bg-background text-sm text-muted-foreground shadow-none w-40 sm:w-72"
44
+ >
45
+ <div className="flex items-center gap-2 flex-grow">
46
+ <SearchIcon size={14} />
47
+ Search
48
+ </div>
49
+ <kbd className="absolute right-[0.3rem] top-[0.3rem] hidden h-5 select-none items-center gap-1 rounded border bg-muted px-1.5 font-mono text-[11px] font-medium opacity-100 sm:flex">
50
+ ⌘K
51
+ </kbd>
52
+ </button>
53
+ {isOpen &&
54
+ searchPlugin.onRequestSearch({
55
+ isOpen,
56
+ onClose,
57
+ })}
58
+ </>
59
+ );
60
+ };
@@ -8,7 +8,8 @@ export type DevPortalPlugin =
8
8
  | CommonPlugin
9
9
  | ProfileMenuPlugin
10
10
  | NavigationPlugin
11
- | ApiIdentityPlugin;
11
+ | ApiIdentityPlugin
12
+ | SearchProviderPlugin;
12
13
 
13
14
  export interface NavigationPlugin {
14
15
  getRoutes: () => RouteObject[];
@@ -19,6 +20,13 @@ export interface ApiIdentityPlugin {
19
20
  getIdentities: (context: DevPortalContext) => Promise<ApiIdentity[]>;
20
21
  }
21
22
 
23
+ export interface SearchProviderPlugin {
24
+ onRequestSearch: (o: {
25
+ isOpen: boolean;
26
+ onClose: () => void;
27
+ }) => React.JSX.Element | null;
28
+ }
29
+
22
30
  export interface ProfileMenuPlugin {
23
31
  getProfileMenuItems: (context: DevPortalContext) => ProfileNavigationItem[];
24
32
  }
@@ -48,6 +56,11 @@ export const isNavigationPlugin = (
48
56
  ): obj is NavigationPlugin =>
49
57
  "getRoutes" in obj && typeof obj.getRoutes === "function";
50
58
 
59
+ export const isSearchPlugin = (
60
+ obj: DevPortalPlugin,
61
+ ): obj is SearchProviderPlugin =>
62
+ "onRequestSearch" in obj && typeof obj.onRequestSearch === "function";
63
+
51
64
  export const needsInitialization = (
52
65
  obj: DevPortalPlugin,
53
66
  ): obj is CommonPlugin =>
@@ -0,0 +1,3 @@
1
+ import { InkeepCustomTrigger } from "@inkeep/widgets";
2
+
3
+ export default InkeepCustomTrigger;
@@ -0,0 +1,55 @@
1
+ import type { InkeepWidgetBaseSettings } from "@inkeep/widgets";
2
+ import { lazy } from "react";
3
+ import type { DevPortalPlugin } from "../../core/plugins.js";
4
+ import { aiChatSettings, baseSettings } from "./inkeep.js";
5
+
6
+ type PickedPluginInkeepBaseSettings =
7
+ | "apiKey"
8
+ | "integrationId"
9
+ | "organizationId"
10
+ | "primaryBrandColor"
11
+ | "organizationDisplayName";
12
+
13
+ type PluginInkeepBaseSettings = Pick<
14
+ InkeepWidgetBaseSettings,
15
+ PickedPluginInkeepBaseSettings
16
+ >;
17
+
18
+ const Inkeep = lazy(() => import("./InkeepCustomTrigger.js"));
19
+ //.then((module) => module.InkeepCustomTrigger)
20
+ const InkeepSearch = ({
21
+ prefilledQuery,
22
+ isOpen,
23
+ onClose,
24
+ }: {
25
+ isOpen: boolean;
26
+ onClose: () => void;
27
+ prefilledQuery?: string | null;
28
+ } & PluginInkeepBaseSettings) => {
29
+ return (
30
+ <Inkeep
31
+ isOpen={isOpen}
32
+ onClose={onClose}
33
+ baseSettings={baseSettings}
34
+ aiChatSettings={aiChatSettings}
35
+ searchSettings={{
36
+ prefilledQuery: prefilledQuery || undefined,
37
+ }}
38
+ />
39
+ );
40
+ };
41
+
42
+ export const inkeepSearchPlugin = (
43
+ settings: PluginInkeepBaseSettings,
44
+ ): DevPortalPlugin => {
45
+ return {
46
+ onRequestSearch: (o: { isOpen: boolean; onClose: () => void }) => {
47
+ if (typeof window === "undefined") {
48
+ return null;
49
+ }
50
+ return (
51
+ <InkeepSearch isOpen={o.isOpen} onClose={o.onClose} {...settings} />
52
+ );
53
+ },
54
+ };
55
+ };
@@ -0,0 +1,47 @@
1
+ import {
2
+ InkeepAIChatSettings,
3
+ InkeepModalSettings,
4
+ InkeepSearchSettings,
5
+ InkeepWidgetBaseSettings,
6
+ } from "@inkeep/widgets";
7
+
8
+ const baseSettings: InkeepWidgetBaseSettings = {
9
+ apiKey: "499c156cf7a9798343949c8bb5665ac95e48132c6d68c42e",
10
+ integrationId: "clot3asdz0000s601nc8jwnzx",
11
+ organizationId: "org_dDOlt2uJlMWM8oIS",
12
+ primaryBrandColor: "#ff00bd",
13
+ organizationDisplayName: "Zuplo",
14
+ theme: {
15
+ components: {
16
+ AIChatPageWrapper: {
17
+ defaultProps: {
18
+ size: "shrink-vertically",
19
+ variant: "no-shadow",
20
+ },
21
+ },
22
+ SearchBarTrigger: {
23
+ defaultProps: {
24
+ size: "expand",
25
+ variant: "subtle", // Choose from 'emphasized' or 'subtle'
26
+ },
27
+ },
28
+ },
29
+ },
30
+ };
31
+
32
+ const modalSettings: InkeepModalSettings = {};
33
+
34
+ const searchSettings: InkeepSearchSettings = {};
35
+
36
+ const aiChatSettings: InkeepAIChatSettings = {
37
+ shareChatUrlBasePath: `${process.env.NODE_ENV === "development" ? "http://localhost:3000" : "https://zuplo.com"}/docs/ask`,
38
+ isChatSharingEnabled: true,
39
+ quickQuestions: [
40
+ "How do I create a custom policy?",
41
+ "What is the difference between production and preview environments?",
42
+ "How do I set a custom domain?",
43
+ "How do I use environment variables?",
44
+ ],
45
+ };
46
+
47
+ export { aiChatSettings, baseSettings, modalSettings, searchSettings };