@btst/stack 1.11.0 → 1.12.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/dist/node_modules/.pnpm/@dnd-kit_core@6.3.1_react-dom@19.2.0_react@19.2.0__react@19.2.0/node_modules/@dnd-kit/core/dist/core.esm.cjs +1 -1
- package/dist/node_modules/.pnpm/@dnd-kit_core@6.3.1_react-dom@19.2.0_react@19.2.0__react@19.2.0/node_modules/@dnd-kit/core/dist/core.esm.mjs +1 -1
- package/dist/node_modules/.pnpm/@dnd-kit_sortable@10.0.0_@dnd-kit_core@6.3.1_react-dom@19.2.0_react@19.2.0__react@19.2.0__react@19.2.0/node_modules/@dnd-kit/sortable/dist/sortable.esm.cjs +77 -0
- package/dist/node_modules/.pnpm/@dnd-kit_sortable@10.0.0_@dnd-kit_core@6.3.1_react-dom@19.2.0_react@19.2.0__react@19.2.0__react@19.2.0/node_modules/@dnd-kit/sortable/dist/sortable.esm.mjs +79 -3
- package/dist/node_modules/.pnpm/@radix-ui_react-avatar@1.1.11_@types_react-dom@19.2.3_@types_react@19.2.6__@types_react_850cfbef1935a6e49a6ad6c93c7ca70d/node_modules/@radix-ui/react-avatar/dist/index.cjs +140 -0
- package/dist/node_modules/.pnpm/@radix-ui_react-avatar@1.1.11_@types_react-dom@19.2.3_@types_react@19.2.6__@types_react_850cfbef1935a6e49a6ad6c93c7ca70d/node_modules/@radix-ui/react-avatar/dist/index.mjs +119 -0
- package/dist/node_modules/.pnpm/@radix-ui_react-context@1.1.3_@types_react@19.2.6_react@19.2.0/node_modules/@radix-ui/react-context/dist/index.cjs +80 -0
- package/dist/node_modules/.pnpm/@radix-ui_react-context@1.1.3_@types_react@19.2.6_react@19.2.0/node_modules/@radix-ui/react-context/dist/index.mjs +64 -0
- package/dist/node_modules/.pnpm/@radix-ui_react-use-is-hydrated@0.1.0_@types_react@19.2.6_react@19.2.0/node_modules/@radix-ui/react-use-is-hydrated/dist/index.cjs +18 -0
- package/dist/node_modules/.pnpm/@radix-ui_react-use-is-hydrated@0.1.0_@types_react@19.2.6_react@19.2.0/node_modules/@radix-ui/react-use-is-hydrated/dist/index.mjs +16 -0
- package/dist/packages/better-stack/src/plugins/kanban/api/plugin.cjs +846 -0
- package/dist/packages/better-stack/src/plugins/kanban/api/plugin.mjs +844 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/forms/board-form.cjs +85 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/forms/board-form.mjs +83 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/forms/column-form.cjs +72 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/forms/column-form.mjs +70 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/forms/task-form.cjs +200 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/forms/task-form.mjs +198 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/loading/board-skeleton.cjs +47 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/loading/board-skeleton.mjs +45 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/loading/boards-list-skeleton.cjs +30 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/loading/boards-list-skeleton.mjs +28 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/pages/404-page.cjs +27 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/pages/404-page.mjs +25 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/pages/board-page.cjs +31 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/pages/board-page.internal.cjs +458 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/pages/board-page.internal.mjs +456 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/pages/board-page.mjs +29 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/pages/boards-list-page.cjs +30 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/pages/boards-list-page.internal.cjs +72 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/pages/boards-list-page.internal.mjs +70 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/pages/boards-list-page.mjs +28 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/pages/new-board-page.cjs +30 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/pages/new-board-page.internal.cjs +51 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/pages/new-board-page.internal.mjs +49 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/pages/new-board-page.mjs +28 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/shared/column-content.cjs +76 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/shared/column-content.mjs +74 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/shared/default-error.cjs +27 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/shared/default-error.mjs +25 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/shared/empty-state.cjs +32 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/shared/empty-state.mjs +30 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/shared/kanban-board.cjs +78 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/shared/kanban-board.mjs +76 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/shared/page-wrapper.cjs +15 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/shared/page-wrapper.mjs +13 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/shared/task-card.cjs +68 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/shared/task-card.mjs +66 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/shared/user-avatar.cjs +32 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/components/shared/user-avatar.mjs +30 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/hooks/kanban-hooks.cjs +391 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/hooks/kanban-hooks.mjs +381 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/plugin.cjs +290 -0
- package/dist/packages/better-stack/src/plugins/kanban/client/plugin.mjs +288 -0
- package/dist/packages/better-stack/src/plugins/kanban/db.cjs +125 -0
- package/dist/packages/better-stack/src/plugins/kanban/db.mjs +123 -0
- package/dist/packages/better-stack/src/plugins/kanban/schemas.cjs +117 -0
- package/dist/packages/better-stack/src/plugins/kanban/schemas.mjs +102 -0
- package/dist/packages/better-stack/src/plugins/kanban/utils.cjs +49 -0
- package/dist/packages/better-stack/src/plugins/kanban/utils.mjs +45 -0
- package/dist/packages/ui/src/components/avatar.cjs +58 -0
- package/dist/packages/ui/src/components/avatar.mjs +54 -0
- package/dist/packages/ui/src/components/command.cjs +3 -3
- package/dist/packages/ui/src/components/command.mjs +3 -3
- package/dist/packages/ui/src/components/form-builder/index.mjs +2 -2
- package/dist/packages/ui/src/components/kanban.cjs +835 -0
- package/dist/packages/ui/src/components/kanban.mjs +805 -0
- package/dist/packages/ui/src/components/popover.cjs +8 -3
- package/dist/packages/ui/src/components/popover.mjs +9 -4
- package/dist/packages/ui/src/components/search-select.cjs +75 -0
- package/dist/packages/ui/src/components/search-select.mjs +73 -0
- package/dist/packages/ui/src/lib/compose-refs.cjs +56 -0
- package/dist/packages/ui/src/lib/compose-refs.mjs +39 -0
- package/dist/plugins/blog/api/index.d.cts +1 -1
- package/dist/plugins/blog/api/index.d.mts +1 -1
- package/dist/plugins/blog/api/index.d.ts +1 -1
- package/dist/plugins/blog/client/hooks/index.d.cts +2 -2
- package/dist/plugins/blog/client/hooks/index.d.mts +2 -2
- package/dist/plugins/blog/client/hooks/index.d.ts +2 -2
- package/dist/plugins/blog/client/index.d.cts +1 -1
- package/dist/plugins/blog/client/index.d.mts +1 -1
- package/dist/plugins/blog/client/index.d.ts +1 -1
- package/dist/plugins/blog/query-keys.d.cts +2 -2
- package/dist/plugins/blog/query-keys.d.mts +2 -2
- package/dist/plugins/blog/query-keys.d.ts +2 -2
- package/dist/plugins/kanban/api/index.cjs +7 -0
- package/dist/plugins/kanban/api/index.d.cts +403 -0
- package/dist/plugins/kanban/api/index.d.mts +403 -0
- package/dist/plugins/kanban/api/index.d.ts +403 -0
- package/dist/plugins/kanban/api/index.mjs +1 -0
- package/dist/plugins/kanban/client/components/index.cjs +35 -0
- package/dist/plugins/kanban/client/components/index.d.cts +102 -0
- package/dist/plugins/kanban/client/components/index.d.mts +102 -0
- package/dist/plugins/kanban/client/components/index.d.ts +102 -0
- package/dist/plugins/kanban/client/components/index.mjs +15 -0
- package/dist/plugins/kanban/client/hooks/index.cjs +15 -0
- package/dist/plugins/kanban/client/hooks/index.d.cts +143 -0
- package/dist/plugins/kanban/client/hooks/index.d.mts +143 -0
- package/dist/plugins/kanban/client/hooks/index.d.ts +143 -0
- package/dist/plugins/kanban/client/hooks/index.mjs +1 -0
- package/dist/plugins/kanban/client/index.cjs +7 -0
- package/dist/plugins/kanban/client/index.d.cts +196 -0
- package/dist/plugins/kanban/client/index.d.mts +196 -0
- package/dist/plugins/kanban/client/index.d.ts +196 -0
- package/dist/plugins/kanban/client/index.mjs +1 -0
- package/dist/plugins/kanban/client.css +68 -0
- package/dist/plugins/kanban/query-keys.cjs +105 -0
- package/dist/plugins/kanban/query-keys.d.cts +59 -0
- package/dist/plugins/kanban/query-keys.d.mts +59 -0
- package/dist/plugins/kanban/query-keys.d.ts +59 -0
- package/dist/plugins/kanban/query-keys.mjs +103 -0
- package/dist/plugins/kanban/style.css +7 -0
- package/dist/plugins/ui-builder/style.css +6 -0
- package/dist/shared/stack.DKDMI-QO.d.cts +70 -0
- package/dist/shared/stack.DKDMI-QO.d.mts +70 -0
- package/dist/shared/stack.DKDMI-QO.d.ts +70 -0
- package/dist/shared/stack.FeaWkglm.d.cts +190 -0
- package/dist/shared/stack.FeaWkglm.d.mts +190 -0
- package/dist/shared/stack.FeaWkglm.d.ts +190 -0
- package/package.json +56 -2
- package/src/plugins/kanban/api/index.ts +6 -0
- package/src/plugins/kanban/api/plugin.ts +1245 -0
- package/src/plugins/kanban/client/components/forms/board-form.tsx +108 -0
- package/src/plugins/kanban/client/components/forms/column-form.tsx +97 -0
- package/src/plugins/kanban/client/components/forms/task-form.tsx +274 -0
- package/src/plugins/kanban/client/components/index.tsx +21 -0
- package/src/plugins/kanban/client/components/loading/board-skeleton.tsx +49 -0
- package/src/plugins/kanban/client/components/loading/boards-list-skeleton.tsx +34 -0
- package/src/plugins/kanban/client/components/loading/index.tsx +2 -0
- package/src/plugins/kanban/client/components/pages/404-page.tsx +28 -0
- package/src/plugins/kanban/client/components/pages/board-page.internal.tsx +575 -0
- package/src/plugins/kanban/client/components/pages/board-page.tsx +31 -0
- package/src/plugins/kanban/client/components/pages/boards-list-page.internal.tsx +101 -0
- package/src/plugins/kanban/client/components/pages/boards-list-page.tsx +26 -0
- package/src/plugins/kanban/client/components/pages/new-board-page.internal.tsx +65 -0
- package/src/plugins/kanban/client/components/pages/new-board-page.tsx +26 -0
- package/src/plugins/kanban/client/components/shared/column-content.tsx +108 -0
- package/src/plugins/kanban/client/components/shared/default-error.tsx +32 -0
- package/src/plugins/kanban/client/components/shared/empty-state.tsx +37 -0
- package/src/plugins/kanban/client/components/shared/kanban-board.tsx +87 -0
- package/src/plugins/kanban/client/components/shared/page-wrapper.tsx +20 -0
- package/src/plugins/kanban/client/components/shared/task-card.tsx +79 -0
- package/src/plugins/kanban/client/components/shared/user-avatar.tsx +63 -0
- package/src/plugins/kanban/client/hooks/index.tsx +11 -0
- package/src/plugins/kanban/client/hooks/kanban-hooks.tsx +560 -0
- package/src/plugins/kanban/client/index.ts +8 -0
- package/src/plugins/kanban/client/localization/index.ts +28 -0
- package/src/plugins/kanban/client/localization/kanban-common.ts +69 -0
- package/src/plugins/kanban/client/localization/kanban-forms.ts +70 -0
- package/src/plugins/kanban/client/localization/kanban-list.ts +36 -0
- package/src/plugins/kanban/client/overrides.ts +145 -0
- package/src/plugins/kanban/client/plugin.tsx +463 -0
- package/src/plugins/kanban/client.css +68 -0
- package/src/plugins/kanban/db.ts +125 -0
- package/src/plugins/kanban/query-keys.ts +154 -0
- package/src/plugins/kanban/schemas.ts +143 -0
- package/src/plugins/kanban/style.css +7 -0
- package/src/plugins/kanban/types.ts +106 -0
- package/src/plugins/kanban/utils.ts +107 -0
- package/src/plugins/ui-builder/style.css +6 -0
- package/dist/shared/{stack.DLhzx1-D.d.cts → stack.CcI4sYJP.d.cts} +1 -1
- package/dist/shared/{stack.DLhzx1-D.d.mts → stack.CcI4sYJP.d.mts} +1 -1
- package/dist/shared/{stack.DLhzx1-D.d.ts → stack.CcI4sYJP.d.ts} +1 -1
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { ComponentType } from 'react';
|
|
2
|
+
|
|
3
|
+
interface KanbanCommonLocalization {
|
|
4
|
+
backToBoards: string;
|
|
5
|
+
actions: string;
|
|
6
|
+
create: string;
|
|
7
|
+
edit: string;
|
|
8
|
+
delete: string;
|
|
9
|
+
cancel: string;
|
|
10
|
+
save: string;
|
|
11
|
+
loading: string;
|
|
12
|
+
saving: string;
|
|
13
|
+
deleting: string;
|
|
14
|
+
board: string;
|
|
15
|
+
boards: string;
|
|
16
|
+
column: string;
|
|
17
|
+
columns: string;
|
|
18
|
+
task: string;
|
|
19
|
+
tasks: string;
|
|
20
|
+
priorityLow: string;
|
|
21
|
+
priorityMedium: string;
|
|
22
|
+
priorityHigh: string;
|
|
23
|
+
priorityUrgent: string;
|
|
24
|
+
noBoards: string;
|
|
25
|
+
noColumns: string;
|
|
26
|
+
noTasks: string;
|
|
27
|
+
errorGeneric: string;
|
|
28
|
+
errorNotFound: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
interface KanbanFormsLocalization {
|
|
32
|
+
boardName: string;
|
|
33
|
+
boardNamePlaceholder: string;
|
|
34
|
+
boardDescription: string;
|
|
35
|
+
boardDescriptionPlaceholder: string;
|
|
36
|
+
createBoard: string;
|
|
37
|
+
updateBoard: string;
|
|
38
|
+
deleteBoard: string;
|
|
39
|
+
deleteBoardConfirm: string;
|
|
40
|
+
columnTitle: string;
|
|
41
|
+
columnTitlePlaceholder: string;
|
|
42
|
+
createColumn: string;
|
|
43
|
+
updateColumn: string;
|
|
44
|
+
deleteColumn: string;
|
|
45
|
+
deleteColumnConfirm: string;
|
|
46
|
+
taskTitle: string;
|
|
47
|
+
taskTitlePlaceholder: string;
|
|
48
|
+
taskDescription: string;
|
|
49
|
+
taskDescriptionPlaceholder: string;
|
|
50
|
+
taskPriority: string;
|
|
51
|
+
taskColumn: string;
|
|
52
|
+
taskAssignee: string;
|
|
53
|
+
createTask: string;
|
|
54
|
+
updateTask: string;
|
|
55
|
+
deleteTask: string;
|
|
56
|
+
deleteTaskConfirm: string;
|
|
57
|
+
nameRequired: string;
|
|
58
|
+
titleRequired: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
interface KanbanListLocalization {
|
|
62
|
+
kanbanBoards: string;
|
|
63
|
+
manageProjects: string;
|
|
64
|
+
createNewBoard: string;
|
|
65
|
+
boardDetails: string;
|
|
66
|
+
newBoard: string;
|
|
67
|
+
addColumn: string;
|
|
68
|
+
addTask: string;
|
|
69
|
+
columnsCount: string;
|
|
70
|
+
noBoardsDescription: string;
|
|
71
|
+
noColumnsDescription: string;
|
|
72
|
+
noTasksDescription: string;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
type KanbanLocalization = Partial<KanbanCommonLocalization & KanbanFormsLocalization & KanbanListLocalization>;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* User information for assignee display/selection
|
|
79
|
+
* Framework-agnostic - consumers map their auth system to this shape
|
|
80
|
+
*/
|
|
81
|
+
interface KanbanUser {
|
|
82
|
+
id: string;
|
|
83
|
+
name: string;
|
|
84
|
+
avatarUrl?: string;
|
|
85
|
+
email?: string;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Context passed to lifecycle hooks
|
|
89
|
+
*/
|
|
90
|
+
interface RouteContext {
|
|
91
|
+
/** Current route path */
|
|
92
|
+
path: string;
|
|
93
|
+
/** Route parameters (e.g., { boardId: "abc123" }) */
|
|
94
|
+
params?: Record<string, string>;
|
|
95
|
+
/** Whether rendering on server (true) or client (false) */
|
|
96
|
+
isSSR: boolean;
|
|
97
|
+
/** Additional context properties */
|
|
98
|
+
[key: string]: unknown;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Overridable components and functions for the Kanban plugin
|
|
102
|
+
*
|
|
103
|
+
* External consumers can provide their own implementations of these
|
|
104
|
+
* to customize the behavior for their framework (Next.js, React Router, etc.)
|
|
105
|
+
*/
|
|
106
|
+
interface KanbanPluginOverrides {
|
|
107
|
+
/**
|
|
108
|
+
* Link component for navigation
|
|
109
|
+
*/
|
|
110
|
+
Link?: ComponentType<React.ComponentProps<"a"> & Record<string, unknown>>;
|
|
111
|
+
/**
|
|
112
|
+
* Navigation function for programmatic navigation
|
|
113
|
+
*/
|
|
114
|
+
navigate: (path: string) => void | Promise<void>;
|
|
115
|
+
/**
|
|
116
|
+
* Refresh function to invalidate server-side cache (e.g., Next.js router.refresh())
|
|
117
|
+
*/
|
|
118
|
+
refresh?: () => void | Promise<void>;
|
|
119
|
+
/**
|
|
120
|
+
* Image component for displaying images
|
|
121
|
+
*/
|
|
122
|
+
Image?: ComponentType<React.ImgHTMLAttributes<HTMLImageElement> & Record<string, unknown>>;
|
|
123
|
+
/**
|
|
124
|
+
* Localization object for the kanban plugin
|
|
125
|
+
*/
|
|
126
|
+
localization?: KanbanLocalization;
|
|
127
|
+
/**
|
|
128
|
+
* API base URL
|
|
129
|
+
*/
|
|
130
|
+
apiBaseURL: string;
|
|
131
|
+
/**
|
|
132
|
+
* API base path
|
|
133
|
+
*/
|
|
134
|
+
apiBasePath: string;
|
|
135
|
+
/**
|
|
136
|
+
* Whether to show the attribution
|
|
137
|
+
*/
|
|
138
|
+
showAttribution?: boolean;
|
|
139
|
+
/**
|
|
140
|
+
* Optional headers to pass with API requests (e.g., for SSR auth)
|
|
141
|
+
*/
|
|
142
|
+
headers?: HeadersInit;
|
|
143
|
+
/**
|
|
144
|
+
* Resolve user info from an assigneeId
|
|
145
|
+
* Called when rendering task cards/forms that have an assignee
|
|
146
|
+
* Return null for unknown users (will show fallback UI)
|
|
147
|
+
*/
|
|
148
|
+
resolveUser: (userId: string) => Promise<KanbanUser | null> | KanbanUser | null;
|
|
149
|
+
/**
|
|
150
|
+
* Search/list users available for assignment
|
|
151
|
+
* Called when user opens the assignee picker
|
|
152
|
+
* @param query - Search query (empty string for initial load)
|
|
153
|
+
* @param boardId - Optional board context for scoped user lists
|
|
154
|
+
*/
|
|
155
|
+
searchUsers: (query: string, boardId?: string) => Promise<KanbanUser[]> | KanbanUser[];
|
|
156
|
+
/**
|
|
157
|
+
* Called when a route is rendered
|
|
158
|
+
* @param routeName - Name of the route (e.g., 'boards', 'board', 'newBoard')
|
|
159
|
+
* @param context - Route context with path, params, etc.
|
|
160
|
+
*/
|
|
161
|
+
onRouteRender?: (routeName: string, context: RouteContext) => void | Promise<void>;
|
|
162
|
+
/**
|
|
163
|
+
* Called when a route encounters an error
|
|
164
|
+
* @param routeName - Name of the route
|
|
165
|
+
* @param error - The error that occurred
|
|
166
|
+
* @param context - Route context
|
|
167
|
+
*/
|
|
168
|
+
onRouteError?: (routeName: string, error: Error, context: RouteContext) => void | Promise<void>;
|
|
169
|
+
/**
|
|
170
|
+
* Called before the boards list page is rendered
|
|
171
|
+
* Return false to prevent rendering (e.g., for authorization)
|
|
172
|
+
* @param context - Route context
|
|
173
|
+
*/
|
|
174
|
+
onBeforeBoardsPageRendered?: (context: RouteContext) => boolean;
|
|
175
|
+
/**
|
|
176
|
+
* Called before a single board page is rendered
|
|
177
|
+
* Return false to prevent rendering (e.g., for authorization)
|
|
178
|
+
* @param boardId - The board ID
|
|
179
|
+
* @param context - Route context
|
|
180
|
+
*/
|
|
181
|
+
onBeforeBoardPageRendered?: (boardId: string, context: RouteContext) => boolean;
|
|
182
|
+
/**
|
|
183
|
+
* Called before the new board page is rendered
|
|
184
|
+
* Return false to prevent rendering (e.g., for authorization)
|
|
185
|
+
* @param context - Route context
|
|
186
|
+
*/
|
|
187
|
+
onBeforeNewBoardPageRendered?: (context: RouteContext) => boolean;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export type { KanbanPluginOverrides as K, KanbanUser as a };
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { ComponentType } from 'react';
|
|
2
|
+
|
|
3
|
+
interface KanbanCommonLocalization {
|
|
4
|
+
backToBoards: string;
|
|
5
|
+
actions: string;
|
|
6
|
+
create: string;
|
|
7
|
+
edit: string;
|
|
8
|
+
delete: string;
|
|
9
|
+
cancel: string;
|
|
10
|
+
save: string;
|
|
11
|
+
loading: string;
|
|
12
|
+
saving: string;
|
|
13
|
+
deleting: string;
|
|
14
|
+
board: string;
|
|
15
|
+
boards: string;
|
|
16
|
+
column: string;
|
|
17
|
+
columns: string;
|
|
18
|
+
task: string;
|
|
19
|
+
tasks: string;
|
|
20
|
+
priorityLow: string;
|
|
21
|
+
priorityMedium: string;
|
|
22
|
+
priorityHigh: string;
|
|
23
|
+
priorityUrgent: string;
|
|
24
|
+
noBoards: string;
|
|
25
|
+
noColumns: string;
|
|
26
|
+
noTasks: string;
|
|
27
|
+
errorGeneric: string;
|
|
28
|
+
errorNotFound: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
interface KanbanFormsLocalization {
|
|
32
|
+
boardName: string;
|
|
33
|
+
boardNamePlaceholder: string;
|
|
34
|
+
boardDescription: string;
|
|
35
|
+
boardDescriptionPlaceholder: string;
|
|
36
|
+
createBoard: string;
|
|
37
|
+
updateBoard: string;
|
|
38
|
+
deleteBoard: string;
|
|
39
|
+
deleteBoardConfirm: string;
|
|
40
|
+
columnTitle: string;
|
|
41
|
+
columnTitlePlaceholder: string;
|
|
42
|
+
createColumn: string;
|
|
43
|
+
updateColumn: string;
|
|
44
|
+
deleteColumn: string;
|
|
45
|
+
deleteColumnConfirm: string;
|
|
46
|
+
taskTitle: string;
|
|
47
|
+
taskTitlePlaceholder: string;
|
|
48
|
+
taskDescription: string;
|
|
49
|
+
taskDescriptionPlaceholder: string;
|
|
50
|
+
taskPriority: string;
|
|
51
|
+
taskColumn: string;
|
|
52
|
+
taskAssignee: string;
|
|
53
|
+
createTask: string;
|
|
54
|
+
updateTask: string;
|
|
55
|
+
deleteTask: string;
|
|
56
|
+
deleteTaskConfirm: string;
|
|
57
|
+
nameRequired: string;
|
|
58
|
+
titleRequired: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
interface KanbanListLocalization {
|
|
62
|
+
kanbanBoards: string;
|
|
63
|
+
manageProjects: string;
|
|
64
|
+
createNewBoard: string;
|
|
65
|
+
boardDetails: string;
|
|
66
|
+
newBoard: string;
|
|
67
|
+
addColumn: string;
|
|
68
|
+
addTask: string;
|
|
69
|
+
columnsCount: string;
|
|
70
|
+
noBoardsDescription: string;
|
|
71
|
+
noColumnsDescription: string;
|
|
72
|
+
noTasksDescription: string;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
type KanbanLocalization = Partial<KanbanCommonLocalization & KanbanFormsLocalization & KanbanListLocalization>;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* User information for assignee display/selection
|
|
79
|
+
* Framework-agnostic - consumers map their auth system to this shape
|
|
80
|
+
*/
|
|
81
|
+
interface KanbanUser {
|
|
82
|
+
id: string;
|
|
83
|
+
name: string;
|
|
84
|
+
avatarUrl?: string;
|
|
85
|
+
email?: string;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Context passed to lifecycle hooks
|
|
89
|
+
*/
|
|
90
|
+
interface RouteContext {
|
|
91
|
+
/** Current route path */
|
|
92
|
+
path: string;
|
|
93
|
+
/** Route parameters (e.g., { boardId: "abc123" }) */
|
|
94
|
+
params?: Record<string, string>;
|
|
95
|
+
/** Whether rendering on server (true) or client (false) */
|
|
96
|
+
isSSR: boolean;
|
|
97
|
+
/** Additional context properties */
|
|
98
|
+
[key: string]: unknown;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Overridable components and functions for the Kanban plugin
|
|
102
|
+
*
|
|
103
|
+
* External consumers can provide their own implementations of these
|
|
104
|
+
* to customize the behavior for their framework (Next.js, React Router, etc.)
|
|
105
|
+
*/
|
|
106
|
+
interface KanbanPluginOverrides {
|
|
107
|
+
/**
|
|
108
|
+
* Link component for navigation
|
|
109
|
+
*/
|
|
110
|
+
Link?: ComponentType<React.ComponentProps<"a"> & Record<string, unknown>>;
|
|
111
|
+
/**
|
|
112
|
+
* Navigation function for programmatic navigation
|
|
113
|
+
*/
|
|
114
|
+
navigate: (path: string) => void | Promise<void>;
|
|
115
|
+
/**
|
|
116
|
+
* Refresh function to invalidate server-side cache (e.g., Next.js router.refresh())
|
|
117
|
+
*/
|
|
118
|
+
refresh?: () => void | Promise<void>;
|
|
119
|
+
/**
|
|
120
|
+
* Image component for displaying images
|
|
121
|
+
*/
|
|
122
|
+
Image?: ComponentType<React.ImgHTMLAttributes<HTMLImageElement> & Record<string, unknown>>;
|
|
123
|
+
/**
|
|
124
|
+
* Localization object for the kanban plugin
|
|
125
|
+
*/
|
|
126
|
+
localization?: KanbanLocalization;
|
|
127
|
+
/**
|
|
128
|
+
* API base URL
|
|
129
|
+
*/
|
|
130
|
+
apiBaseURL: string;
|
|
131
|
+
/**
|
|
132
|
+
* API base path
|
|
133
|
+
*/
|
|
134
|
+
apiBasePath: string;
|
|
135
|
+
/**
|
|
136
|
+
* Whether to show the attribution
|
|
137
|
+
*/
|
|
138
|
+
showAttribution?: boolean;
|
|
139
|
+
/**
|
|
140
|
+
* Optional headers to pass with API requests (e.g., for SSR auth)
|
|
141
|
+
*/
|
|
142
|
+
headers?: HeadersInit;
|
|
143
|
+
/**
|
|
144
|
+
* Resolve user info from an assigneeId
|
|
145
|
+
* Called when rendering task cards/forms that have an assignee
|
|
146
|
+
* Return null for unknown users (will show fallback UI)
|
|
147
|
+
*/
|
|
148
|
+
resolveUser: (userId: string) => Promise<KanbanUser | null> | KanbanUser | null;
|
|
149
|
+
/**
|
|
150
|
+
* Search/list users available for assignment
|
|
151
|
+
* Called when user opens the assignee picker
|
|
152
|
+
* @param query - Search query (empty string for initial load)
|
|
153
|
+
* @param boardId - Optional board context for scoped user lists
|
|
154
|
+
*/
|
|
155
|
+
searchUsers: (query: string, boardId?: string) => Promise<KanbanUser[]> | KanbanUser[];
|
|
156
|
+
/**
|
|
157
|
+
* Called when a route is rendered
|
|
158
|
+
* @param routeName - Name of the route (e.g., 'boards', 'board', 'newBoard')
|
|
159
|
+
* @param context - Route context with path, params, etc.
|
|
160
|
+
*/
|
|
161
|
+
onRouteRender?: (routeName: string, context: RouteContext) => void | Promise<void>;
|
|
162
|
+
/**
|
|
163
|
+
* Called when a route encounters an error
|
|
164
|
+
* @param routeName - Name of the route
|
|
165
|
+
* @param error - The error that occurred
|
|
166
|
+
* @param context - Route context
|
|
167
|
+
*/
|
|
168
|
+
onRouteError?: (routeName: string, error: Error, context: RouteContext) => void | Promise<void>;
|
|
169
|
+
/**
|
|
170
|
+
* Called before the boards list page is rendered
|
|
171
|
+
* Return false to prevent rendering (e.g., for authorization)
|
|
172
|
+
* @param context - Route context
|
|
173
|
+
*/
|
|
174
|
+
onBeforeBoardsPageRendered?: (context: RouteContext) => boolean;
|
|
175
|
+
/**
|
|
176
|
+
* Called before a single board page is rendered
|
|
177
|
+
* Return false to prevent rendering (e.g., for authorization)
|
|
178
|
+
* @param boardId - The board ID
|
|
179
|
+
* @param context - Route context
|
|
180
|
+
*/
|
|
181
|
+
onBeforeBoardPageRendered?: (boardId: string, context: RouteContext) => boolean;
|
|
182
|
+
/**
|
|
183
|
+
* Called before the new board page is rendered
|
|
184
|
+
* Return false to prevent rendering (e.g., for authorization)
|
|
185
|
+
* @param context - Route context
|
|
186
|
+
*/
|
|
187
|
+
onBeforeNewBoardPageRendered?: (context: RouteContext) => boolean;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export type { KanbanPluginOverrides as K, KanbanUser as a };
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { ComponentType } from 'react';
|
|
2
|
+
|
|
3
|
+
interface KanbanCommonLocalization {
|
|
4
|
+
backToBoards: string;
|
|
5
|
+
actions: string;
|
|
6
|
+
create: string;
|
|
7
|
+
edit: string;
|
|
8
|
+
delete: string;
|
|
9
|
+
cancel: string;
|
|
10
|
+
save: string;
|
|
11
|
+
loading: string;
|
|
12
|
+
saving: string;
|
|
13
|
+
deleting: string;
|
|
14
|
+
board: string;
|
|
15
|
+
boards: string;
|
|
16
|
+
column: string;
|
|
17
|
+
columns: string;
|
|
18
|
+
task: string;
|
|
19
|
+
tasks: string;
|
|
20
|
+
priorityLow: string;
|
|
21
|
+
priorityMedium: string;
|
|
22
|
+
priorityHigh: string;
|
|
23
|
+
priorityUrgent: string;
|
|
24
|
+
noBoards: string;
|
|
25
|
+
noColumns: string;
|
|
26
|
+
noTasks: string;
|
|
27
|
+
errorGeneric: string;
|
|
28
|
+
errorNotFound: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
interface KanbanFormsLocalization {
|
|
32
|
+
boardName: string;
|
|
33
|
+
boardNamePlaceholder: string;
|
|
34
|
+
boardDescription: string;
|
|
35
|
+
boardDescriptionPlaceholder: string;
|
|
36
|
+
createBoard: string;
|
|
37
|
+
updateBoard: string;
|
|
38
|
+
deleteBoard: string;
|
|
39
|
+
deleteBoardConfirm: string;
|
|
40
|
+
columnTitle: string;
|
|
41
|
+
columnTitlePlaceholder: string;
|
|
42
|
+
createColumn: string;
|
|
43
|
+
updateColumn: string;
|
|
44
|
+
deleteColumn: string;
|
|
45
|
+
deleteColumnConfirm: string;
|
|
46
|
+
taskTitle: string;
|
|
47
|
+
taskTitlePlaceholder: string;
|
|
48
|
+
taskDescription: string;
|
|
49
|
+
taskDescriptionPlaceholder: string;
|
|
50
|
+
taskPriority: string;
|
|
51
|
+
taskColumn: string;
|
|
52
|
+
taskAssignee: string;
|
|
53
|
+
createTask: string;
|
|
54
|
+
updateTask: string;
|
|
55
|
+
deleteTask: string;
|
|
56
|
+
deleteTaskConfirm: string;
|
|
57
|
+
nameRequired: string;
|
|
58
|
+
titleRequired: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
interface KanbanListLocalization {
|
|
62
|
+
kanbanBoards: string;
|
|
63
|
+
manageProjects: string;
|
|
64
|
+
createNewBoard: string;
|
|
65
|
+
boardDetails: string;
|
|
66
|
+
newBoard: string;
|
|
67
|
+
addColumn: string;
|
|
68
|
+
addTask: string;
|
|
69
|
+
columnsCount: string;
|
|
70
|
+
noBoardsDescription: string;
|
|
71
|
+
noColumnsDescription: string;
|
|
72
|
+
noTasksDescription: string;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
type KanbanLocalization = Partial<KanbanCommonLocalization & KanbanFormsLocalization & KanbanListLocalization>;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* User information for assignee display/selection
|
|
79
|
+
* Framework-agnostic - consumers map their auth system to this shape
|
|
80
|
+
*/
|
|
81
|
+
interface KanbanUser {
|
|
82
|
+
id: string;
|
|
83
|
+
name: string;
|
|
84
|
+
avatarUrl?: string;
|
|
85
|
+
email?: string;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Context passed to lifecycle hooks
|
|
89
|
+
*/
|
|
90
|
+
interface RouteContext {
|
|
91
|
+
/** Current route path */
|
|
92
|
+
path: string;
|
|
93
|
+
/** Route parameters (e.g., { boardId: "abc123" }) */
|
|
94
|
+
params?: Record<string, string>;
|
|
95
|
+
/** Whether rendering on server (true) or client (false) */
|
|
96
|
+
isSSR: boolean;
|
|
97
|
+
/** Additional context properties */
|
|
98
|
+
[key: string]: unknown;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Overridable components and functions for the Kanban plugin
|
|
102
|
+
*
|
|
103
|
+
* External consumers can provide their own implementations of these
|
|
104
|
+
* to customize the behavior for their framework (Next.js, React Router, etc.)
|
|
105
|
+
*/
|
|
106
|
+
interface KanbanPluginOverrides {
|
|
107
|
+
/**
|
|
108
|
+
* Link component for navigation
|
|
109
|
+
*/
|
|
110
|
+
Link?: ComponentType<React.ComponentProps<"a"> & Record<string, unknown>>;
|
|
111
|
+
/**
|
|
112
|
+
* Navigation function for programmatic navigation
|
|
113
|
+
*/
|
|
114
|
+
navigate: (path: string) => void | Promise<void>;
|
|
115
|
+
/**
|
|
116
|
+
* Refresh function to invalidate server-side cache (e.g., Next.js router.refresh())
|
|
117
|
+
*/
|
|
118
|
+
refresh?: () => void | Promise<void>;
|
|
119
|
+
/**
|
|
120
|
+
* Image component for displaying images
|
|
121
|
+
*/
|
|
122
|
+
Image?: ComponentType<React.ImgHTMLAttributes<HTMLImageElement> & Record<string, unknown>>;
|
|
123
|
+
/**
|
|
124
|
+
* Localization object for the kanban plugin
|
|
125
|
+
*/
|
|
126
|
+
localization?: KanbanLocalization;
|
|
127
|
+
/**
|
|
128
|
+
* API base URL
|
|
129
|
+
*/
|
|
130
|
+
apiBaseURL: string;
|
|
131
|
+
/**
|
|
132
|
+
* API base path
|
|
133
|
+
*/
|
|
134
|
+
apiBasePath: string;
|
|
135
|
+
/**
|
|
136
|
+
* Whether to show the attribution
|
|
137
|
+
*/
|
|
138
|
+
showAttribution?: boolean;
|
|
139
|
+
/**
|
|
140
|
+
* Optional headers to pass with API requests (e.g., for SSR auth)
|
|
141
|
+
*/
|
|
142
|
+
headers?: HeadersInit;
|
|
143
|
+
/**
|
|
144
|
+
* Resolve user info from an assigneeId
|
|
145
|
+
* Called when rendering task cards/forms that have an assignee
|
|
146
|
+
* Return null for unknown users (will show fallback UI)
|
|
147
|
+
*/
|
|
148
|
+
resolveUser: (userId: string) => Promise<KanbanUser | null> | KanbanUser | null;
|
|
149
|
+
/**
|
|
150
|
+
* Search/list users available for assignment
|
|
151
|
+
* Called when user opens the assignee picker
|
|
152
|
+
* @param query - Search query (empty string for initial load)
|
|
153
|
+
* @param boardId - Optional board context for scoped user lists
|
|
154
|
+
*/
|
|
155
|
+
searchUsers: (query: string, boardId?: string) => Promise<KanbanUser[]> | KanbanUser[];
|
|
156
|
+
/**
|
|
157
|
+
* Called when a route is rendered
|
|
158
|
+
* @param routeName - Name of the route (e.g., 'boards', 'board', 'newBoard')
|
|
159
|
+
* @param context - Route context with path, params, etc.
|
|
160
|
+
*/
|
|
161
|
+
onRouteRender?: (routeName: string, context: RouteContext) => void | Promise<void>;
|
|
162
|
+
/**
|
|
163
|
+
* Called when a route encounters an error
|
|
164
|
+
* @param routeName - Name of the route
|
|
165
|
+
* @param error - The error that occurred
|
|
166
|
+
* @param context - Route context
|
|
167
|
+
*/
|
|
168
|
+
onRouteError?: (routeName: string, error: Error, context: RouteContext) => void | Promise<void>;
|
|
169
|
+
/**
|
|
170
|
+
* Called before the boards list page is rendered
|
|
171
|
+
* Return false to prevent rendering (e.g., for authorization)
|
|
172
|
+
* @param context - Route context
|
|
173
|
+
*/
|
|
174
|
+
onBeforeBoardsPageRendered?: (context: RouteContext) => boolean;
|
|
175
|
+
/**
|
|
176
|
+
* Called before a single board page is rendered
|
|
177
|
+
* Return false to prevent rendering (e.g., for authorization)
|
|
178
|
+
* @param boardId - The board ID
|
|
179
|
+
* @param context - Route context
|
|
180
|
+
*/
|
|
181
|
+
onBeforeBoardPageRendered?: (boardId: string, context: RouteContext) => boolean;
|
|
182
|
+
/**
|
|
183
|
+
* Called before the new board page is rendered
|
|
184
|
+
* Return false to prevent rendering (e.g., for authorization)
|
|
185
|
+
* @param context - Route context
|
|
186
|
+
*/
|
|
187
|
+
onBeforeNewBoardPageRendered?: (context: RouteContext) => boolean;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export type { KanbanPluginOverrides as K, KanbanUser as a };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@btst/stack",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.12.0",
|
|
4
4
|
"description": "A composable, plugin-based library for building full-stack applications.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -298,6 +298,47 @@
|
|
|
298
298
|
"default": "./dist/plugins/open-api/api/index.cjs"
|
|
299
299
|
}
|
|
300
300
|
},
|
|
301
|
+
"./plugins/kanban/api": {
|
|
302
|
+
"import": {
|
|
303
|
+
"types": "./dist/plugins/kanban/api/index.d.ts",
|
|
304
|
+
"default": "./dist/plugins/kanban/api/index.mjs"
|
|
305
|
+
},
|
|
306
|
+
"require": {
|
|
307
|
+
"types": "./dist/plugins/kanban/api/index.d.cts",
|
|
308
|
+
"default": "./dist/plugins/kanban/api/index.cjs"
|
|
309
|
+
}
|
|
310
|
+
},
|
|
311
|
+
"./plugins/kanban/client": {
|
|
312
|
+
"import": {
|
|
313
|
+
"types": "./dist/plugins/kanban/client/index.d.ts",
|
|
314
|
+
"default": "./dist/plugins/kanban/client/index.mjs"
|
|
315
|
+
},
|
|
316
|
+
"require": {
|
|
317
|
+
"types": "./dist/plugins/kanban/client/index.d.cts",
|
|
318
|
+
"default": "./dist/plugins/kanban/client/index.cjs"
|
|
319
|
+
}
|
|
320
|
+
},
|
|
321
|
+
"./plugins/kanban/client/components": {
|
|
322
|
+
"import": {
|
|
323
|
+
"types": "./dist/plugins/kanban/client/components/index.d.ts",
|
|
324
|
+
"default": "./dist/plugins/kanban/client/components/index.mjs"
|
|
325
|
+
},
|
|
326
|
+
"require": {
|
|
327
|
+
"types": "./dist/plugins/kanban/client/components/index.d.cts",
|
|
328
|
+
"default": "./dist/plugins/kanban/client/components/index.cjs"
|
|
329
|
+
}
|
|
330
|
+
},
|
|
331
|
+
"./plugins/kanban/client/hooks": {
|
|
332
|
+
"import": {
|
|
333
|
+
"types": "./dist/plugins/kanban/client/hooks/index.d.ts",
|
|
334
|
+
"default": "./dist/plugins/kanban/client/hooks/index.mjs"
|
|
335
|
+
},
|
|
336
|
+
"require": {
|
|
337
|
+
"types": "./dist/plugins/kanban/client/hooks/index.d.cts",
|
|
338
|
+
"default": "./dist/plugins/kanban/client/hooks/index.cjs"
|
|
339
|
+
}
|
|
340
|
+
},
|
|
341
|
+
"./plugins/kanban/css": "./dist/plugins/kanban/style.css",
|
|
301
342
|
"./plugins/route-docs/client": {
|
|
302
343
|
"import": {
|
|
303
344
|
"types": "./dist/plugins/route-docs/client/index.d.ts",
|
|
@@ -390,6 +431,18 @@
|
|
|
390
431
|
"plugins/open-api/api": [
|
|
391
432
|
"./dist/plugins/open-api/api/index.d.ts"
|
|
392
433
|
],
|
|
434
|
+
"plugins/kanban/api": [
|
|
435
|
+
"./dist/plugins/kanban/api/index.d.ts"
|
|
436
|
+
],
|
|
437
|
+
"plugins/kanban/client": [
|
|
438
|
+
"./dist/plugins/kanban/client/index.d.ts"
|
|
439
|
+
],
|
|
440
|
+
"plugins/kanban/client/components": [
|
|
441
|
+
"./dist/plugins/kanban/client/components/index.d.ts"
|
|
442
|
+
],
|
|
443
|
+
"plugins/kanban/client/hooks": [
|
|
444
|
+
"./dist/plugins/kanban/client/hooks/index.d.ts"
|
|
445
|
+
],
|
|
393
446
|
"plugins/route-docs/client": [
|
|
394
447
|
"./dist/plugins/route-docs/client/index.d.ts"
|
|
395
448
|
]
|
|
@@ -426,7 +479,7 @@
|
|
|
426
479
|
"react-error-boundary": ">=4.0.0",
|
|
427
480
|
"react-hook-form": ">=7.55.0",
|
|
428
481
|
"react-intersection-observer": ">=9.0.0",
|
|
429
|
-
"react-markdown": ">=
|
|
482
|
+
"react-markdown": ">=9.1.0",
|
|
430
483
|
"rehype-highlight": ">=7.0.0",
|
|
431
484
|
"rehype-katex": ">=7.0.0",
|
|
432
485
|
"rehype-raw": ">=7.0.0",
|
|
@@ -435,6 +488,7 @@
|
|
|
435
488
|
"sonner": ">=2.0.0",
|
|
436
489
|
"tailwind-merge": ">=2.6.0",
|
|
437
490
|
"tailwindcss": ">=3.0.0",
|
|
491
|
+
"@tailwindcss/typography": ">=0.5.0",
|
|
438
492
|
"zod": ">=4.2.0"
|
|
439
493
|
},
|
|
440
494
|
"devDependencies": {
|