@btst/stack 2.5.6 → 2.6.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.
- package/README.md +23 -0
- package/dist/client/components/index.d.cts +9 -9
- package/dist/client/components/index.d.mts +9 -9
- package/dist/client/components/index.d.ts +9 -9
- package/dist/packages/stack/src/plugins/ai-chat/client/components/shared/default-error.cjs +1 -1
- package/dist/packages/stack/src/plugins/ai-chat/client/components/shared/default-error.mjs +1 -1
- package/dist/packages/stack/src/plugins/ai-chat/client/plugin.cjs +44 -35
- package/dist/packages/stack/src/plugins/ai-chat/client/plugin.mjs +44 -35
- package/dist/packages/stack/src/plugins/blog/client/components/shared/default-error.cjs +1 -1
- package/dist/packages/stack/src/plugins/blog/client/components/shared/default-error.mjs +1 -1
- package/dist/packages/stack/src/plugins/blog/client/hooks/use-debounce.cjs +22 -0
- package/dist/packages/stack/src/plugins/blog/client/hooks/use-debounce.mjs +23 -2
- package/dist/packages/stack/src/plugins/blog/client/plugin.cjs +12 -6
- package/dist/packages/stack/src/plugins/blog/client/plugin.mjs +12 -6
- package/dist/packages/stack/src/plugins/cms/client/components/shared/default-error.cjs +1 -1
- package/dist/packages/stack/src/plugins/cms/client/components/shared/default-error.mjs +1 -1
- package/dist/packages/stack/src/plugins/cms/client/plugin.cjs +38 -26
- package/dist/packages/stack/src/plugins/cms/client/plugin.mjs +38 -26
- package/dist/packages/stack/src/plugins/form-builder/client/components/shared/default-error.cjs +1 -1
- package/dist/packages/stack/src/plugins/form-builder/client/components/shared/default-error.mjs +1 -1
- package/dist/packages/stack/src/plugins/form-builder/client/plugin.cjs +32 -20
- package/dist/packages/stack/src/plugins/form-builder/client/plugin.mjs +32 -20
- package/dist/packages/stack/src/plugins/kanban/client/components/shared/default-error.cjs +1 -1
- package/dist/packages/stack/src/plugins/kanban/client/components/shared/default-error.mjs +1 -1
- package/dist/packages/stack/src/plugins/kanban/client/plugin.cjs +6 -3
- package/dist/packages/stack/src/plugins/kanban/client/plugin.mjs +6 -3
- package/dist/packages/stack/src/plugins/ui-builder/client/components/page-renderer.cjs +1 -1
- package/dist/packages/stack/src/plugins/ui-builder/client/components/page-renderer.mjs +1 -1
- package/dist/packages/stack/src/plugins/ui-builder/client/components/shared/default-error.cjs +1 -1
- package/dist/packages/stack/src/plugins/ui-builder/client/components/shared/default-error.mjs +1 -1
- package/dist/packages/stack/src/plugins/ui-builder/client/plugin.cjs +24 -15
- package/dist/packages/stack/src/plugins/ui-builder/client/plugin.mjs +24 -15
- package/dist/packages/ui/src/components/search-select.cjs +13 -3
- package/dist/packages/ui/src/components/search-select.mjs +14 -4
- package/dist/plugins/ai-chat/client/index.d.cts +17 -4
- package/dist/plugins/ai-chat/client/index.d.mts +17 -4
- package/dist/plugins/ai-chat/client/index.d.ts +17 -4
- package/dist/plugins/blog/client/hooks/index.cjs +3 -0
- package/dist/plugins/blog/client/hooks/index.d.cts +7 -226
- package/dist/plugins/blog/client/hooks/index.d.mts +7 -226
- package/dist/plugins/blog/client/hooks/index.d.ts +7 -226
- package/dist/plugins/blog/client/hooks/index.mjs +1 -0
- package/dist/plugins/blog/client/index.d.cts +45 -21
- package/dist/plugins/blog/client/index.d.mts +45 -21
- package/dist/plugins/blog/client/index.d.ts +45 -21
- package/dist/plugins/cms/client/index.d.cts +35 -14
- package/dist/plugins/cms/client/index.d.mts +35 -14
- package/dist/plugins/cms/client/index.d.ts +35 -14
- package/dist/plugins/form-builder/client/components/index.d.cts +1 -1
- package/dist/plugins/form-builder/client/components/index.d.mts +1 -1
- package/dist/plugins/form-builder/client/components/index.d.ts +1 -1
- package/dist/plugins/form-builder/client/index.d.cts +32 -14
- package/dist/plugins/form-builder/client/index.d.mts +32 -14
- package/dist/plugins/form-builder/client/index.d.ts +32 -14
- package/dist/plugins/kanban/api/index.d.cts +1 -1
- package/dist/plugins/kanban/api/index.d.mts +1 -1
- package/dist/plugins/kanban/api/index.d.ts +1 -1
- package/dist/plugins/kanban/client/components/index.d.cts +5 -5
- package/dist/plugins/kanban/client/components/index.d.mts +5 -5
- package/dist/plugins/kanban/client/components/index.d.ts +5 -5
- package/dist/plugins/kanban/client/index.d.cts +25 -10
- package/dist/plugins/kanban/client/index.d.mts +25 -10
- package/dist/plugins/kanban/client/index.d.ts +25 -10
- package/dist/plugins/kanban/query-keys.d.cts +1 -1
- package/dist/plugins/kanban/query-keys.d.mts +1 -1
- package/dist/plugins/kanban/query-keys.d.ts +1 -1
- package/dist/plugins/route-docs/client/index.d.cts +4 -4
- package/dist/plugins/route-docs/client/index.d.mts +4 -4
- package/dist/plugins/route-docs/client/index.d.ts +4 -4
- package/dist/plugins/ui-builder/client/components/index.d.cts +1 -1
- package/dist/plugins/ui-builder/client/components/index.d.mts +1 -1
- package/dist/plugins/ui-builder/client/components/index.d.ts +1 -1
- package/dist/plugins/ui-builder/client/index.d.cts +29 -15
- package/dist/plugins/ui-builder/client/index.d.mts +29 -15
- package/dist/plugins/ui-builder/client/index.d.ts +29 -15
- package/dist/shared/stack.CNLHlv7r.d.mts +228 -0
- package/dist/shared/stack.CQAZwXhV.d.cts +228 -0
- package/dist/shared/stack.D3BsrpAz.d.ts +228 -0
- package/package.json +19 -2
- package/src/__tests__/page-component-overrides.test.tsx +147 -0
- package/src/plugins/ai-chat/client/components/shared/default-error.tsx +1 -1
- package/src/plugins/ai-chat/client/plugin.tsx +60 -32
- package/src/plugins/blog/client/components/shared/default-error.tsx +2 -1
- package/src/plugins/blog/client/hooks/index.tsx +1 -0
- package/src/plugins/blog/client/plugin.tsx +41 -6
- package/src/plugins/cms/client/components/shared/default-error.tsx +3 -2
- package/src/plugins/cms/client/plugin.tsx +65 -32
- package/src/plugins/form-builder/client/components/shared/default-error.tsx +3 -2
- package/src/plugins/form-builder/client/plugin.tsx +56 -23
- package/src/plugins/kanban/client/components/shared/default-error.tsx +3 -2
- package/src/plugins/kanban/client/plugin.tsx +23 -3
- package/src/plugins/ui-builder/client/components/page-renderer.tsx +5 -3
- package/src/plugins/ui-builder/client/components/shared/default-error.tsx +3 -2
- package/src/plugins/ui-builder/client/plugin.tsx +41 -15
- package/dist/shared/{stack.CxNeGV2z.d.mts → stack.Ba_Ks8qi.d.mts} +9 -9
- package/dist/shared/{stack.DSxTDZBQ.d.cts → stack.CFqqZUes.d.cts} +9 -9
- package/dist/shared/{stack.BFcg0tDz.d.ts → stack.DMobugrZ.d.ts} +9 -9
package/README.md
CHANGED
|
@@ -115,6 +115,22 @@ Supports Prisma, Drizzle, MongoDB and Kysely SQL dialects.
|
|
|
115
115
|
|
|
116
116
|
---
|
|
117
117
|
|
|
118
|
+
## Shadcn Registry
|
|
119
|
+
|
|
120
|
+
Each plugin's UI layer is available as a [shadcn registry](https://ui.shadcn.com/docs/registry) block. Use it to **eject and fully customize** the page components while keeping all data-fetching and API logic from `@btst/stack`:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
# Install a single plugin's UI
|
|
124
|
+
npx shadcn@latest add https://github.com/better-stack-ai/better-stack/blob/main/packages/stack/registry/btst-blog.json
|
|
125
|
+
|
|
126
|
+
# Or install the full collection
|
|
127
|
+
npx shadcn@latest add https://github.com/better-stack-ai/better-stack/blob/main/packages/stack/registry/registry.json
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Components are copied into `src/components/btst/{plugin}/client/` — all relative imports remain valid and you can edit them freely.
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
118
134
|
## Examples
|
|
119
135
|
|
|
120
136
|
* [Next.js App Router](./examples/nextjs)
|
|
@@ -130,6 +146,13 @@ Full documentation, guides, and plugin development:
|
|
|
130
146
|
|
|
131
147
|
---
|
|
132
148
|
|
|
149
|
+
## Contributing
|
|
150
|
+
|
|
151
|
+
Bug reports, plugin PRs, and documentation improvements are welcome.
|
|
152
|
+
See **[CONTRIBUTING.md](./CONTRIBUTING.md)** for the plugin development guide, testing instructions, and submission checklist.
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
133
156
|
If this saves you time, a ⭐ helps others find it.
|
|
134
157
|
|
|
135
158
|
MIT © [olliethedev](https://github.com/olliethedev)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import
|
|
2
|
+
import React__default, { ErrorInfo } from 'react';
|
|
3
3
|
import { FallbackProps } from 'react-error-boundary';
|
|
4
4
|
export { FallbackProps } from 'react-error-boundary';
|
|
5
5
|
import { createRouter } from '@btst/yar';
|
|
@@ -8,9 +8,9 @@ import { createRouter } from '@btst/yar';
|
|
|
8
8
|
* Route type with optional components
|
|
9
9
|
*/
|
|
10
10
|
type RouteWithComponents = {
|
|
11
|
-
PageComponent?:
|
|
12
|
-
ErrorComponent?:
|
|
13
|
-
LoadingComponent?:
|
|
11
|
+
PageComponent?: React__default.ComponentType;
|
|
12
|
+
ErrorComponent?: React__default.ComponentType<FallbackProps>;
|
|
13
|
+
LoadingComponent?: React__default.ComponentType;
|
|
14
14
|
} | null | undefined;
|
|
15
15
|
/**
|
|
16
16
|
* Composes the route content with Suspense and Error Boundary
|
|
@@ -21,7 +21,7 @@ type RouteWithComponents = {
|
|
|
21
21
|
declare function RouteRenderer({ router, path, NotFoundComponent, onNotFound, onError, props, }: {
|
|
22
22
|
router: ReturnType<typeof createRouter>;
|
|
23
23
|
path: string;
|
|
24
|
-
NotFoundComponent?:
|
|
24
|
+
NotFoundComponent?: React__default.ComponentType<{
|
|
25
25
|
message: string;
|
|
26
26
|
}>;
|
|
27
27
|
onNotFound?: () => never;
|
|
@@ -43,11 +43,11 @@ declare function RouteRenderer({ router, path, NotFoundComponent, onNotFound, on
|
|
|
43
43
|
*/
|
|
44
44
|
declare function ComposedRoute({ path, PageComponent, ErrorComponent, LoadingComponent, onNotFound, NotFoundComponent, props, onError, }: {
|
|
45
45
|
path: string;
|
|
46
|
-
PageComponent:
|
|
47
|
-
ErrorComponent?:
|
|
48
|
-
LoadingComponent:
|
|
46
|
+
PageComponent: React__default.ComponentType<any>;
|
|
47
|
+
ErrorComponent?: React__default.ComponentType<FallbackProps>;
|
|
48
|
+
LoadingComponent: React__default.ComponentType;
|
|
49
49
|
onNotFound?: () => never;
|
|
50
|
-
NotFoundComponent?:
|
|
50
|
+
NotFoundComponent?: React__default.ComponentType<{
|
|
51
51
|
message: string;
|
|
52
52
|
}>;
|
|
53
53
|
props?: any;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import
|
|
2
|
+
import React__default, { ErrorInfo } from 'react';
|
|
3
3
|
import { FallbackProps } from 'react-error-boundary';
|
|
4
4
|
export { FallbackProps } from 'react-error-boundary';
|
|
5
5
|
import { createRouter } from '@btst/yar';
|
|
@@ -8,9 +8,9 @@ import { createRouter } from '@btst/yar';
|
|
|
8
8
|
* Route type with optional components
|
|
9
9
|
*/
|
|
10
10
|
type RouteWithComponents = {
|
|
11
|
-
PageComponent?:
|
|
12
|
-
ErrorComponent?:
|
|
13
|
-
LoadingComponent?:
|
|
11
|
+
PageComponent?: React__default.ComponentType;
|
|
12
|
+
ErrorComponent?: React__default.ComponentType<FallbackProps>;
|
|
13
|
+
LoadingComponent?: React__default.ComponentType;
|
|
14
14
|
} | null | undefined;
|
|
15
15
|
/**
|
|
16
16
|
* Composes the route content with Suspense and Error Boundary
|
|
@@ -21,7 +21,7 @@ type RouteWithComponents = {
|
|
|
21
21
|
declare function RouteRenderer({ router, path, NotFoundComponent, onNotFound, onError, props, }: {
|
|
22
22
|
router: ReturnType<typeof createRouter>;
|
|
23
23
|
path: string;
|
|
24
|
-
NotFoundComponent?:
|
|
24
|
+
NotFoundComponent?: React__default.ComponentType<{
|
|
25
25
|
message: string;
|
|
26
26
|
}>;
|
|
27
27
|
onNotFound?: () => never;
|
|
@@ -43,11 +43,11 @@ declare function RouteRenderer({ router, path, NotFoundComponent, onNotFound, on
|
|
|
43
43
|
*/
|
|
44
44
|
declare function ComposedRoute({ path, PageComponent, ErrorComponent, LoadingComponent, onNotFound, NotFoundComponent, props, onError, }: {
|
|
45
45
|
path: string;
|
|
46
|
-
PageComponent:
|
|
47
|
-
ErrorComponent?:
|
|
48
|
-
LoadingComponent:
|
|
46
|
+
PageComponent: React__default.ComponentType<any>;
|
|
47
|
+
ErrorComponent?: React__default.ComponentType<FallbackProps>;
|
|
48
|
+
LoadingComponent: React__default.ComponentType;
|
|
49
49
|
onNotFound?: () => never;
|
|
50
|
-
NotFoundComponent?:
|
|
50
|
+
NotFoundComponent?: React__default.ComponentType<{
|
|
51
51
|
message: string;
|
|
52
52
|
}>;
|
|
53
53
|
props?: any;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import
|
|
2
|
+
import React__default, { ErrorInfo } from 'react';
|
|
3
3
|
import { FallbackProps } from 'react-error-boundary';
|
|
4
4
|
export { FallbackProps } from 'react-error-boundary';
|
|
5
5
|
import { createRouter } from '@btst/yar';
|
|
@@ -8,9 +8,9 @@ import { createRouter } from '@btst/yar';
|
|
|
8
8
|
* Route type with optional components
|
|
9
9
|
*/
|
|
10
10
|
type RouteWithComponents = {
|
|
11
|
-
PageComponent?:
|
|
12
|
-
ErrorComponent?:
|
|
13
|
-
LoadingComponent?:
|
|
11
|
+
PageComponent?: React__default.ComponentType;
|
|
12
|
+
ErrorComponent?: React__default.ComponentType<FallbackProps>;
|
|
13
|
+
LoadingComponent?: React__default.ComponentType;
|
|
14
14
|
} | null | undefined;
|
|
15
15
|
/**
|
|
16
16
|
* Composes the route content with Suspense and Error Boundary
|
|
@@ -21,7 +21,7 @@ type RouteWithComponents = {
|
|
|
21
21
|
declare function RouteRenderer({ router, path, NotFoundComponent, onNotFound, onError, props, }: {
|
|
22
22
|
router: ReturnType<typeof createRouter>;
|
|
23
23
|
path: string;
|
|
24
|
-
NotFoundComponent?:
|
|
24
|
+
NotFoundComponent?: React__default.ComponentType<{
|
|
25
25
|
message: string;
|
|
26
26
|
}>;
|
|
27
27
|
onNotFound?: () => never;
|
|
@@ -43,11 +43,11 @@ declare function RouteRenderer({ router, path, NotFoundComponent, onNotFound, on
|
|
|
43
43
|
*/
|
|
44
44
|
declare function ComposedRoute({ path, PageComponent, ErrorComponent, LoadingComponent, onNotFound, NotFoundComponent, props, onError, }: {
|
|
45
45
|
path: string;
|
|
46
|
-
PageComponent:
|
|
47
|
-
ErrorComponent?:
|
|
48
|
-
LoadingComponent:
|
|
46
|
+
PageComponent: React__default.ComponentType<any>;
|
|
47
|
+
ErrorComponent?: React__default.ComponentType<FallbackProps>;
|
|
48
|
+
LoadingComponent: React__default.ComponentType;
|
|
49
49
|
onNotFound?: () => never;
|
|
50
|
-
NotFoundComponent?:
|
|
50
|
+
NotFoundComponent?: React__default.ComponentType<{
|
|
51
51
|
message: string;
|
|
52
52
|
}>;
|
|
53
53
|
props?: any;
|
|
@@ -11,7 +11,7 @@ function DefaultError({ error }) {
|
|
|
11
11
|
localization: index.AI_CHAT_LOCALIZATION
|
|
12
12
|
});
|
|
13
13
|
const title = localization?.CHAT_GENERIC_ERROR_TITLE ?? index.AI_CHAT_LOCALIZATION.CHAT_GENERIC_ERROR_TITLE;
|
|
14
|
-
const message = process.env.NODE_ENV === "production" ? localization?.CHAT_GENERIC_ERROR_MESSAGE ?? index.AI_CHAT_LOCALIZATION.CHAT_GENERIC_ERROR_MESSAGE : error
|
|
14
|
+
const message = process.env.NODE_ENV === "production" ? localization?.CHAT_GENERIC_ERROR_MESSAGE ?? index.AI_CHAT_LOCALIZATION.CHAT_GENERIC_ERROR_MESSAGE : (error instanceof Error ? error.message : void 0) ?? localization?.CHAT_GENERIC_ERROR_MESSAGE ?? index.AI_CHAT_LOCALIZATION.CHAT_GENERIC_ERROR_MESSAGE;
|
|
15
15
|
return /* @__PURE__ */ jsxRuntime.jsx(errorPlaceholder.ErrorPlaceholder, { title, message });
|
|
16
16
|
}
|
|
17
17
|
|
|
@@ -9,7 +9,7 @@ function DefaultError({ error }) {
|
|
|
9
9
|
localization: AI_CHAT_LOCALIZATION
|
|
10
10
|
});
|
|
11
11
|
const title = localization?.CHAT_GENERIC_ERROR_TITLE ?? AI_CHAT_LOCALIZATION.CHAT_GENERIC_ERROR_TITLE;
|
|
12
|
-
const message = process.env.NODE_ENV === "production" ? localization?.CHAT_GENERIC_ERROR_MESSAGE ?? AI_CHAT_LOCALIZATION.CHAT_GENERIC_ERROR_MESSAGE : error
|
|
12
|
+
const message = process.env.NODE_ENV === "production" ? localization?.CHAT_GENERIC_ERROR_MESSAGE ?? AI_CHAT_LOCALIZATION.CHAT_GENERIC_ERROR_MESSAGE : (error instanceof Error ? error.message : void 0) ?? localization?.CHAT_GENERIC_ERROR_MESSAGE ?? AI_CHAT_LOCALIZATION.CHAT_GENERIC_ERROR_MESSAGE;
|
|
13
13
|
return /* @__PURE__ */ jsx(ErrorPlaceholder, { title, message });
|
|
14
14
|
}
|
|
15
15
|
|
|
@@ -179,18 +179,21 @@ const aiChatClientPlugin = (config) => {
|
|
|
179
179
|
name: "ai-chat",
|
|
180
180
|
routes: () => ({
|
|
181
181
|
// Chat home - simple chat interface without history
|
|
182
|
-
chat: yar.createRoute("/chat", () =>
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
182
|
+
chat: yar.createRoute("/chat", () => {
|
|
183
|
+
const CustomChat = config.pageComponents?.chat;
|
|
184
|
+
return {
|
|
185
|
+
PageComponent: CustomChat ?? (() => /* @__PURE__ */ jsxRuntime.jsx(
|
|
186
|
+
chatLayout.ChatLayout,
|
|
187
|
+
{
|
|
188
|
+
apiBaseURL: config.apiBaseURL,
|
|
189
|
+
apiBasePath: config.apiBasePath,
|
|
190
|
+
showSidebar: false
|
|
191
|
+
}
|
|
192
|
+
)),
|
|
193
|
+
loader: createConversationsLoader(config),
|
|
194
|
+
meta: createChatHomeMeta(config)
|
|
195
|
+
};
|
|
196
|
+
})
|
|
194
197
|
}),
|
|
195
198
|
sitemap: async () => []
|
|
196
199
|
});
|
|
@@ -199,30 +202,36 @@ const aiChatClientPlugin = (config) => {
|
|
|
199
202
|
name: "ai-chat",
|
|
200
203
|
routes: () => ({
|
|
201
204
|
// Chat home - new conversation or list
|
|
202
|
-
chat: yar.createRoute("/chat", () =>
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
205
|
+
chat: yar.createRoute("/chat", () => {
|
|
206
|
+
const CustomChat = config.pageComponents?.chat;
|
|
207
|
+
return {
|
|
208
|
+
PageComponent: CustomChat ?? (() => /* @__PURE__ */ jsxRuntime.jsx(
|
|
209
|
+
chatLayout.ChatLayout,
|
|
210
|
+
{
|
|
211
|
+
apiBaseURL: config.apiBaseURL,
|
|
212
|
+
apiBasePath: config.apiBasePath
|
|
213
|
+
}
|
|
214
|
+
)),
|
|
215
|
+
loader: createConversationsLoader(config),
|
|
216
|
+
meta: createChatHomeMeta(config)
|
|
217
|
+
};
|
|
218
|
+
}),
|
|
213
219
|
// Existing conversation
|
|
214
|
-
chatConversation: yar.createRoute("/chat/:id", ({ params }) =>
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
{
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
220
|
+
chatConversation: yar.createRoute("/chat/:id", ({ params }) => {
|
|
221
|
+
const CustomConversation = config.pageComponents?.chatConversation;
|
|
222
|
+
return {
|
|
223
|
+
PageComponent: CustomConversation ? () => /* @__PURE__ */ jsxRuntime.jsx(CustomConversation, { conversationId: params.id }) : () => /* @__PURE__ */ jsxRuntime.jsx(
|
|
224
|
+
chatLayout.ChatLayout,
|
|
225
|
+
{
|
|
226
|
+
apiBaseURL: config.apiBaseURL,
|
|
227
|
+
apiBasePath: config.apiBasePath,
|
|
228
|
+
conversationId: params.id
|
|
229
|
+
}
|
|
230
|
+
),
|
|
231
|
+
loader: createConversationLoader(params.id, config),
|
|
232
|
+
meta: createConversationMeta(params.id, config)
|
|
233
|
+
};
|
|
234
|
+
})
|
|
226
235
|
}),
|
|
227
236
|
// Chat pages typically shouldn't be in sitemap, but we provide the option
|
|
228
237
|
sitemap: async () => {
|
|
@@ -177,18 +177,21 @@ const aiChatClientPlugin = (config) => {
|
|
|
177
177
|
name: "ai-chat",
|
|
178
178
|
routes: () => ({
|
|
179
179
|
// Chat home - simple chat interface without history
|
|
180
|
-
chat: createRoute("/chat", () =>
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
180
|
+
chat: createRoute("/chat", () => {
|
|
181
|
+
const CustomChat = config.pageComponents?.chat;
|
|
182
|
+
return {
|
|
183
|
+
PageComponent: CustomChat ?? (() => /* @__PURE__ */ jsx(
|
|
184
|
+
ChatLayout,
|
|
185
|
+
{
|
|
186
|
+
apiBaseURL: config.apiBaseURL,
|
|
187
|
+
apiBasePath: config.apiBasePath,
|
|
188
|
+
showSidebar: false
|
|
189
|
+
}
|
|
190
|
+
)),
|
|
191
|
+
loader: createConversationsLoader(config),
|
|
192
|
+
meta: createChatHomeMeta(config)
|
|
193
|
+
};
|
|
194
|
+
})
|
|
192
195
|
}),
|
|
193
196
|
sitemap: async () => []
|
|
194
197
|
});
|
|
@@ -197,30 +200,36 @@ const aiChatClientPlugin = (config) => {
|
|
|
197
200
|
name: "ai-chat",
|
|
198
201
|
routes: () => ({
|
|
199
202
|
// Chat home - new conversation or list
|
|
200
|
-
chat: createRoute("/chat", () =>
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
203
|
+
chat: createRoute("/chat", () => {
|
|
204
|
+
const CustomChat = config.pageComponents?.chat;
|
|
205
|
+
return {
|
|
206
|
+
PageComponent: CustomChat ?? (() => /* @__PURE__ */ jsx(
|
|
207
|
+
ChatLayout,
|
|
208
|
+
{
|
|
209
|
+
apiBaseURL: config.apiBaseURL,
|
|
210
|
+
apiBasePath: config.apiBasePath
|
|
211
|
+
}
|
|
212
|
+
)),
|
|
213
|
+
loader: createConversationsLoader(config),
|
|
214
|
+
meta: createChatHomeMeta(config)
|
|
215
|
+
};
|
|
216
|
+
}),
|
|
211
217
|
// Existing conversation
|
|
212
|
-
chatConversation: createRoute("/chat/:id", ({ params }) =>
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
{
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
218
|
+
chatConversation: createRoute("/chat/:id", ({ params }) => {
|
|
219
|
+
const CustomConversation = config.pageComponents?.chatConversation;
|
|
220
|
+
return {
|
|
221
|
+
PageComponent: CustomConversation ? () => /* @__PURE__ */ jsx(CustomConversation, { conversationId: params.id }) : () => /* @__PURE__ */ jsx(
|
|
222
|
+
ChatLayout,
|
|
223
|
+
{
|
|
224
|
+
apiBaseURL: config.apiBaseURL,
|
|
225
|
+
apiBasePath: config.apiBasePath,
|
|
226
|
+
conversationId: params.id
|
|
227
|
+
}
|
|
228
|
+
),
|
|
229
|
+
loader: createConversationLoader(params.id, config),
|
|
230
|
+
meta: createConversationMeta(params.id, config)
|
|
231
|
+
};
|
|
232
|
+
})
|
|
224
233
|
}),
|
|
225
234
|
// Chat pages typically shouldn't be in sitemap, but we provide the option
|
|
226
235
|
sitemap: async () => {
|
|
@@ -11,7 +11,7 @@ function DefaultError({ error }) {
|
|
|
11
11
|
localization: index.BLOG_LOCALIZATION
|
|
12
12
|
});
|
|
13
13
|
const title = localization.BLOG_GENERIC_ERROR_TITLE;
|
|
14
|
-
const message = process.env.NODE_ENV === "production" ? localization.BLOG_GENERIC_ERROR_MESSAGE : error
|
|
14
|
+
const message = process.env.NODE_ENV === "production" ? localization.BLOG_GENERIC_ERROR_MESSAGE : (error instanceof Error ? error.message : void 0) ?? localization.BLOG_GENERIC_ERROR_MESSAGE;
|
|
15
15
|
return /* @__PURE__ */ jsxRuntime.jsx(errorPlaceholder.ErrorPlaceholder, { title, message });
|
|
16
16
|
}
|
|
17
17
|
|
|
@@ -9,7 +9,7 @@ function DefaultError({ error }) {
|
|
|
9
9
|
localization: BLOG_LOCALIZATION
|
|
10
10
|
});
|
|
11
11
|
const title = localization.BLOG_GENERIC_ERROR_TITLE;
|
|
12
|
-
const message = process.env.NODE_ENV === "production" ? localization.BLOG_GENERIC_ERROR_MESSAGE : error
|
|
12
|
+
const message = process.env.NODE_ENV === "production" ? localization.BLOG_GENERIC_ERROR_MESSAGE : (error instanceof Error ? error.message : void 0) ?? localization.BLOG_GENERIC_ERROR_MESSAGE;
|
|
13
13
|
return /* @__PURE__ */ jsx(ErrorPlaceholder, { title, message });
|
|
14
14
|
}
|
|
15
15
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const utils = require('../../utils.cjs');
|
|
3
4
|
const React = require('react');
|
|
4
5
|
|
|
5
6
|
function useDebounce(value, delay) {
|
|
@@ -12,5 +13,26 @@ function useDebounce(value, delay) {
|
|
|
12
13
|
}, [value, delay]);
|
|
13
14
|
return debouncedValue;
|
|
14
15
|
}
|
|
16
|
+
function useThrottle(value, wait) {
|
|
17
|
+
const [throttledValue, setThrottledValue] = React.useState(value);
|
|
18
|
+
const valueRef = React.useRef(value);
|
|
19
|
+
valueRef.current = value;
|
|
20
|
+
const throttledSetter = React.useMemo(() => {
|
|
21
|
+
return utils.throttle((next) => {
|
|
22
|
+
setThrottledValue(next);
|
|
23
|
+
}, wait ?? 500);
|
|
24
|
+
}, [wait]);
|
|
25
|
+
React.useEffect(() => {
|
|
26
|
+
throttledSetter(valueRef.current);
|
|
27
|
+
return () => {
|
|
28
|
+
throttledSetter.cancel();
|
|
29
|
+
};
|
|
30
|
+
}, [throttledSetter]);
|
|
31
|
+
React.useEffect(() => {
|
|
32
|
+
throttledSetter(value);
|
|
33
|
+
}, [value, throttledSetter]);
|
|
34
|
+
return throttledValue;
|
|
35
|
+
}
|
|
15
36
|
|
|
16
37
|
exports.useDebounce = useDebounce;
|
|
38
|
+
exports.useThrottle = useThrottle;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { throttle } from '../../utils.mjs';
|
|
2
|
+
import { useState, useEffect, useRef, useMemo } from 'react';
|
|
2
3
|
|
|
3
4
|
function useDebounce(value, delay) {
|
|
4
5
|
const [debouncedValue, setDebouncedValue] = useState(value);
|
|
@@ -10,5 +11,25 @@ function useDebounce(value, delay) {
|
|
|
10
11
|
}, [value, delay]);
|
|
11
12
|
return debouncedValue;
|
|
12
13
|
}
|
|
14
|
+
function useThrottle(value, wait) {
|
|
15
|
+
const [throttledValue, setThrottledValue] = useState(value);
|
|
16
|
+
const valueRef = useRef(value);
|
|
17
|
+
valueRef.current = value;
|
|
18
|
+
const throttledSetter = useMemo(() => {
|
|
19
|
+
return throttle((next) => {
|
|
20
|
+
setThrottledValue(next);
|
|
21
|
+
}, wait ?? 500);
|
|
22
|
+
}, [wait]);
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
throttledSetter(valueRef.current);
|
|
25
|
+
return () => {
|
|
26
|
+
throttledSetter.cancel();
|
|
27
|
+
};
|
|
28
|
+
}, [throttledSetter]);
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
throttledSetter(value);
|
|
31
|
+
}, [value, throttledSetter]);
|
|
32
|
+
return throttledValue;
|
|
33
|
+
}
|
|
13
34
|
|
|
14
|
-
export { useDebounce };
|
|
35
|
+
export { useDebounce, useThrottle };
|
|
@@ -422,43 +422,49 @@ const blogClientPlugin = (config) => client.defineClientPlugin({
|
|
|
422
422
|
name: "blog",
|
|
423
423
|
routes: () => ({
|
|
424
424
|
posts: yar.createRoute("/blog", () => {
|
|
425
|
+
const CustomPosts = config.pageComponents?.posts;
|
|
425
426
|
return {
|
|
426
|
-
PageComponent: () => /* @__PURE__ */ jsxRuntime.jsx(homePage.HomePageComponent, { published: true }),
|
|
427
|
+
PageComponent: CustomPosts ?? (() => /* @__PURE__ */ jsxRuntime.jsx(homePage.HomePageComponent, { published: true })),
|
|
427
428
|
loader: createPostsLoader(true, config),
|
|
428
429
|
meta: createPostsListMeta(true, config)
|
|
429
430
|
};
|
|
430
431
|
}),
|
|
431
432
|
drafts: yar.createRoute("/blog/drafts", () => {
|
|
433
|
+
const CustomDrafts = config.pageComponents?.drafts;
|
|
432
434
|
return {
|
|
433
|
-
PageComponent: () => /* @__PURE__ */ jsxRuntime.jsx(homePage.HomePageComponent, { published: false }),
|
|
435
|
+
PageComponent: CustomDrafts ?? (() => /* @__PURE__ */ jsxRuntime.jsx(homePage.HomePageComponent, { published: false })),
|
|
434
436
|
loader: createPostsLoader(false, config),
|
|
435
437
|
meta: createPostsListMeta(false, config)
|
|
436
438
|
};
|
|
437
439
|
}),
|
|
438
440
|
newPost: yar.createRoute("/blog/new", () => {
|
|
441
|
+
const CustomNewPost = config.pageComponents?.newPost;
|
|
439
442
|
return {
|
|
440
|
-
PageComponent: newPostPage.NewPostPageComponent,
|
|
443
|
+
PageComponent: CustomNewPost ?? newPostPage.NewPostPageComponent,
|
|
441
444
|
loader: createNewPostLoader(config),
|
|
442
445
|
meta: createNewPostMeta(config)
|
|
443
446
|
};
|
|
444
447
|
}),
|
|
445
448
|
editPost: yar.createRoute("/blog/:slug/edit", ({ params: { slug } }) => {
|
|
449
|
+
const CustomEditPost = config.pageComponents?.editPost;
|
|
446
450
|
return {
|
|
447
|
-
PageComponent: () => /* @__PURE__ */ jsxRuntime.jsx(editPostPage.EditPostPageComponent, { slug }),
|
|
451
|
+
PageComponent: CustomEditPost ? () => /* @__PURE__ */ jsxRuntime.jsx(CustomEditPost, { slug }) : () => /* @__PURE__ */ jsxRuntime.jsx(editPostPage.EditPostPageComponent, { slug }),
|
|
448
452
|
loader: createPostLoader(slug, config, `/blog/${slug}/edit`),
|
|
449
453
|
meta: createEditPostMeta(slug, config)
|
|
450
454
|
};
|
|
451
455
|
}),
|
|
452
456
|
tag: yar.createRoute("/blog/tag/:tagSlug", ({ params: { tagSlug } }) => {
|
|
457
|
+
const CustomTag = config.pageComponents?.tag;
|
|
453
458
|
return {
|
|
454
|
-
PageComponent: () => /* @__PURE__ */ jsxRuntime.jsx(tagPage.TagPageComponent, { tagSlug }),
|
|
459
|
+
PageComponent: CustomTag ? () => /* @__PURE__ */ jsxRuntime.jsx(CustomTag, { tagSlug }) : () => /* @__PURE__ */ jsxRuntime.jsx(tagPage.TagPageComponent, { tagSlug }),
|
|
455
460
|
loader: createTagLoader(tagSlug, config),
|
|
456
461
|
meta: createTagMeta(tagSlug, config)
|
|
457
462
|
};
|
|
458
463
|
}),
|
|
459
464
|
post: yar.createRoute("/blog/:slug", ({ params: { slug } }) => {
|
|
465
|
+
const CustomPost = config.pageComponents?.post;
|
|
460
466
|
return {
|
|
461
|
-
PageComponent: () => /* @__PURE__ */ jsxRuntime.jsx(postPage.PostPageComponent, { slug }),
|
|
467
|
+
PageComponent: CustomPost ? () => /* @__PURE__ */ jsxRuntime.jsx(CustomPost, { slug }) : () => /* @__PURE__ */ jsxRuntime.jsx(postPage.PostPageComponent, { slug }),
|
|
462
468
|
loader: createPostLoader(slug, config),
|
|
463
469
|
meta: createPostMeta(slug, config)
|
|
464
470
|
};
|
|
@@ -420,43 +420,49 @@ const blogClientPlugin = (config) => defineClientPlugin({
|
|
|
420
420
|
name: "blog",
|
|
421
421
|
routes: () => ({
|
|
422
422
|
posts: createRoute("/blog", () => {
|
|
423
|
+
const CustomPosts = config.pageComponents?.posts;
|
|
423
424
|
return {
|
|
424
|
-
PageComponent: () => /* @__PURE__ */ jsx(HomePageComponent, { published: true }),
|
|
425
|
+
PageComponent: CustomPosts ?? (() => /* @__PURE__ */ jsx(HomePageComponent, { published: true })),
|
|
425
426
|
loader: createPostsLoader(true, config),
|
|
426
427
|
meta: createPostsListMeta(true, config)
|
|
427
428
|
};
|
|
428
429
|
}),
|
|
429
430
|
drafts: createRoute("/blog/drafts", () => {
|
|
431
|
+
const CustomDrafts = config.pageComponents?.drafts;
|
|
430
432
|
return {
|
|
431
|
-
PageComponent: () => /* @__PURE__ */ jsx(HomePageComponent, { published: false }),
|
|
433
|
+
PageComponent: CustomDrafts ?? (() => /* @__PURE__ */ jsx(HomePageComponent, { published: false })),
|
|
432
434
|
loader: createPostsLoader(false, config),
|
|
433
435
|
meta: createPostsListMeta(false, config)
|
|
434
436
|
};
|
|
435
437
|
}),
|
|
436
438
|
newPost: createRoute("/blog/new", () => {
|
|
439
|
+
const CustomNewPost = config.pageComponents?.newPost;
|
|
437
440
|
return {
|
|
438
|
-
PageComponent: NewPostPageComponent,
|
|
441
|
+
PageComponent: CustomNewPost ?? NewPostPageComponent,
|
|
439
442
|
loader: createNewPostLoader(config),
|
|
440
443
|
meta: createNewPostMeta(config)
|
|
441
444
|
};
|
|
442
445
|
}),
|
|
443
446
|
editPost: createRoute("/blog/:slug/edit", ({ params: { slug } }) => {
|
|
447
|
+
const CustomEditPost = config.pageComponents?.editPost;
|
|
444
448
|
return {
|
|
445
|
-
PageComponent: () => /* @__PURE__ */ jsx(EditPostPageComponent, { slug }),
|
|
449
|
+
PageComponent: CustomEditPost ? () => /* @__PURE__ */ jsx(CustomEditPost, { slug }) : () => /* @__PURE__ */ jsx(EditPostPageComponent, { slug }),
|
|
446
450
|
loader: createPostLoader(slug, config, `/blog/${slug}/edit`),
|
|
447
451
|
meta: createEditPostMeta(slug, config)
|
|
448
452
|
};
|
|
449
453
|
}),
|
|
450
454
|
tag: createRoute("/blog/tag/:tagSlug", ({ params: { tagSlug } }) => {
|
|
455
|
+
const CustomTag = config.pageComponents?.tag;
|
|
451
456
|
return {
|
|
452
|
-
PageComponent: () => /* @__PURE__ */ jsx(TagPageComponent, { tagSlug }),
|
|
457
|
+
PageComponent: CustomTag ? () => /* @__PURE__ */ jsx(CustomTag, { tagSlug }) : () => /* @__PURE__ */ jsx(TagPageComponent, { tagSlug }),
|
|
453
458
|
loader: createTagLoader(tagSlug, config),
|
|
454
459
|
meta: createTagMeta(tagSlug, config)
|
|
455
460
|
};
|
|
456
461
|
}),
|
|
457
462
|
post: createRoute("/blog/:slug", ({ params: { slug } }) => {
|
|
463
|
+
const CustomPost = config.pageComponents?.post;
|
|
458
464
|
return {
|
|
459
|
-
PageComponent: () => /* @__PURE__ */ jsx(PostPageComponent, { slug }),
|
|
465
|
+
PageComponent: CustomPost ? () => /* @__PURE__ */ jsx(CustomPost, { slug }) : () => /* @__PURE__ */ jsx(PostPageComponent, { slug }),
|
|
460
466
|
loader: createPostLoader(slug, config),
|
|
461
467
|
meta: createPostMeta(slug, config)
|
|
462
468
|
};
|
|
@@ -9,7 +9,7 @@ function DefaultError({ error, resetErrorBoundary }) {
|
|
|
9
9
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center py-12 px-4 text-center", children: [
|
|
10
10
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-full bg-destructive/10 p-4 mb-4", children: /* @__PURE__ */ jsxRuntime.jsx(LucideIcons.AlertCircle, { className: "h-8 w-8 text-destructive" }) }),
|
|
11
11
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-medium text-foreground mb-2", children: "Something went wrong" }),
|
|
12
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground mb-4 max-w-sm", children: error.message || "An unexpected error occurred" }),
|
|
12
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground mb-4 max-w-sm", children: (error instanceof Error ? error.message : void 0) || "An unexpected error occurred" }),
|
|
13
13
|
resetErrorBoundary && /* @__PURE__ */ jsxRuntime.jsx(button.Button, { variant: "outline", onClick: resetErrorBoundary, children: "Try again" })
|
|
14
14
|
] });
|
|
15
15
|
}
|
|
@@ -7,7 +7,7 @@ function DefaultError({ error, resetErrorBoundary }) {
|
|
|
7
7
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center py-12 px-4 text-center", children: [
|
|
8
8
|
/* @__PURE__ */ jsx("div", { className: "rounded-full bg-destructive/10 p-4 mb-4", children: /* @__PURE__ */ jsx(AlertCircle, { className: "h-8 w-8 text-destructive" }) }),
|
|
9
9
|
/* @__PURE__ */ jsx("h3", { className: "text-lg font-medium text-foreground mb-2", children: "Something went wrong" }),
|
|
10
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mb-4 max-w-sm", children: error.message || "An unexpected error occurred" }),
|
|
10
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground mb-4 max-w-sm", children: (error instanceof Error ? error.message : void 0) || "An unexpected error occurred" }),
|
|
11
11
|
resetErrorBoundary && /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: resetErrorBoundary, children: "Try again" })
|
|
12
12
|
] });
|
|
13
13
|
}
|