@tulip-systems/drive 0.7.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 (70) hide show
  1. package/LICENSE +662 -0
  2. package/package.json +113 -0
  3. package/src/components/content.tsx +13 -0
  4. package/src/components/context.client.tsx +12 -0
  5. package/src/components/dnd.client.tsx +47 -0
  6. package/src/components/grid-card.client.tsx +252 -0
  7. package/src/components/grid.client.tsx +96 -0
  8. package/src/components/navigation/breadcrumbs.client.tsx +125 -0
  9. package/src/components/navigation/header.client.tsx +45 -0
  10. package/src/components/navigation/toolbar.client.tsx +35 -0
  11. package/src/components/navigation/view-switcher.client.tsx +32 -0
  12. package/src/components/selection.client.tsx +48 -0
  13. package/src/components/view.client.tsx +67 -0
  14. package/src/config/filters.ts +14 -0
  15. package/src/config/types.tsx +90 -0
  16. package/src/entry.client.ts +7 -0
  17. package/src/entry.server.ts +4 -0
  18. package/src/entry.ts +10 -0
  19. package/src/lib/constants.ts +19 -0
  20. package/src/lib/contracts.ts +121 -0
  21. package/src/lib/dto.ts +83 -0
  22. package/src/lib/helpers.server.ts +14 -0
  23. package/src/lib/helpers.ts +32 -0
  24. package/src/lib/search-params.ts +5 -0
  25. package/src/lib/validators.ts +89 -0
  26. package/src/providers/google/components/command-file-update.tsx +100 -0
  27. package/src/providers/google/components/command-folder-create.tsx +104 -0
  28. package/src/providers/google/components/command-folder-update.tsx +100 -0
  29. package/src/providers/google/components/content.client.tsx +6 -0
  30. package/src/providers/google/components/navigation.client.tsx +21 -0
  31. package/src/providers/google/components/provider.client.tsx +60 -0
  32. package/src/providers/google/components/view.client.tsx +158 -0
  33. package/src/providers/google/config/columns-data.tsx +81 -0
  34. package/src/providers/google/config/filters.ts +3 -0
  35. package/src/providers/google/entry.client.ts +10 -0
  36. package/src/providers/google/entry.server.ts +5 -0
  37. package/src/providers/google/entry.ts +12 -0
  38. package/src/providers/google/lib/constants.ts +10 -0
  39. package/src/providers/google/lib/dto.ts +104 -0
  40. package/src/providers/google/lib/helpers.ts +37 -0
  41. package/src/providers/google/lib/router.server.ts +62 -0
  42. package/src/providers/google/lib/schema.ts +9 -0
  43. package/src/providers/google/lib/search-params.ts +7 -0
  44. package/src/providers/google/lib/service.server.ts +792 -0
  45. package/src/providers/google/lib/validators.ts +148 -0
  46. package/src/providers/local/components/command-file-update.tsx +93 -0
  47. package/src/providers/local/components/command-file-upload.tsx +29 -0
  48. package/src/providers/local/components/command-folder-create.tsx +100 -0
  49. package/src/providers/local/components/command-folder-update.tsx +93 -0
  50. package/src/providers/local/components/content.client.tsx +3 -0
  51. package/src/providers/local/components/navigation.client.tsx +23 -0
  52. package/src/providers/local/components/provider.client.tsx +90 -0
  53. package/src/providers/local/components/upload-zone-context.client.tsx +43 -0
  54. package/src/providers/local/components/upload-zone.client.tsx +182 -0
  55. package/src/providers/local/components/view.client.tsx +145 -0
  56. package/src/providers/local/config/columns-data.tsx +81 -0
  57. package/src/providers/local/config/filters.ts +14 -0
  58. package/src/providers/local/entry.client.ts +18 -0
  59. package/src/providers/local/entry.server.ts +7 -0
  60. package/src/providers/local/entry.ts +14 -0
  61. package/src/providers/local/lib/constants.ts +23 -0
  62. package/src/providers/local/lib/helpers.ts +105 -0
  63. package/src/providers/local/lib/route-handler.server.ts +153 -0
  64. package/src/providers/local/lib/router.server.ts +137 -0
  65. package/src/providers/local/lib/schema.ts +104 -0
  66. package/src/providers/local/lib/search-params.ts +4 -0
  67. package/src/providers/local/lib/service.server.ts +1116 -0
  68. package/src/providers/local/lib/upload.client.ts +177 -0
  69. package/src/providers/local/lib/validators.ts +154 -0
  70. package/src/styles.css +1 -0
@@ -0,0 +1,89 @@
1
+ import { resolveFiltersSchema, tableQuerySchema } from "@tulip-systems/core/data-tables";
2
+ import { z } from "zod";
3
+ import { driveTreeFilters } from "@/config/filters";
4
+
5
+ /**
6
+ * Create drive folder input schema
7
+ * @description zod schema for validating the input of the create drive folder command
8
+ */
9
+ export const createDriveFolderInputSchema = z.object({
10
+ name: z.string(),
11
+ namespace: z.string(),
12
+ parentId: z.string().nullable().optional(),
13
+ });
14
+ export type CreateDriveFolderInput = z.input<typeof createDriveFolderInputSchema>;
15
+ export type CreateDriveFolderSchema = z.infer<typeof createDriveFolderInputSchema>;
16
+
17
+ /**
18
+ * Update drive node input schema
19
+ */
20
+ export const updateDriveNodeInputSchema = z.object({
21
+ name: z.string().optional(),
22
+ });
23
+ export type UpdateDriveNodeInput = z.input<typeof updateDriveNodeInputSchema>;
24
+ export type UpdateDriveNodeSchema = z.infer<typeof updateDriveNodeInputSchema>;
25
+
26
+ /**
27
+ * Upload drive file input schema
28
+ * @description zod schema for validating the input of the upload drive file command
29
+ */
30
+ export const uploadDriveFileInputSchema = z.object({
31
+ name: z.string(),
32
+ namespace: z.string(),
33
+ parentId: z.string().nullable().optional(),
34
+ contentType: z.string().nullable().optional(),
35
+ size: z.number().nullable().optional(),
36
+ });
37
+ export type UploadDriveFileInput = z.input<typeof uploadDriveFileInputSchema>;
38
+ export type UploadDriveFileSchema = z.infer<typeof uploadDriveFileInputSchema>;
39
+
40
+ /**
41
+ * Presign drive file input schema
42
+ * @description zod schema for validating the input of the presign drive file command
43
+ */
44
+ export const presignDriveFileInputSchema = z.object({
45
+ name: z.string(),
46
+ namespace: z.string(),
47
+ parentId: z.string().nullable().optional(),
48
+ contentType: z.string().nullable().optional(),
49
+ size: z.number().nullable().optional(),
50
+ });
51
+
52
+ export type PresignDriveFileInput = z.input<typeof presignDriveFileInputSchema>;
53
+ export type PresignDriveFileSchema = z.infer<typeof presignDriveFileInputSchema>;
54
+
55
+ /**
56
+ * Table filters
57
+ */
58
+ export const driveTableFiltersSchema = resolveFiltersSchema(driveTreeFilters)
59
+ .partial()
60
+ .extend({
61
+ namespace: z.string(),
62
+ parentId: z.string().nullable(),
63
+ })
64
+ .transform((input) => ({
65
+ ...input,
66
+ isArchived: input?.isArchived ?? false,
67
+ }));
68
+
69
+ export type NodesTableFilters = z.infer<typeof driveTableFiltersSchema>;
70
+
71
+ /**
72
+ * List tree input schema
73
+ */
74
+ export const listDriveTreeInputSchema = tableQuerySchema.extend({
75
+ filters: driveTableFiltersSchema,
76
+ });
77
+
78
+ export type ListDriveTreeInput = z.input<typeof listDriveTreeInputSchema>;
79
+ export type ListDriveTreeSchema = z.infer<typeof listDriveTreeInputSchema>;
80
+
81
+ /**
82
+ * Get nodes by parent id input schema
83
+ */
84
+ export const getNodesByParentIdInputSchema = tableQuerySchema
85
+ .pick({ order: true, sort: true, search: true })
86
+ .extend({ filters: driveTableFiltersSchema });
87
+
88
+ export type GetDriveNodesByParentIdInput = z.input<typeof getNodesByParentIdInputSchema>;
89
+ export type GetDriveNodesByParentIdSchema = z.infer<typeof getNodesByParentIdInputSchema>;
@@ -0,0 +1,100 @@
1
+ "use client";
2
+
3
+ import { zodResolver } from "@hookform/resolvers/zod";
4
+ import type { DefaultError, MutationOptions } from "@tanstack/react-query";
5
+ import {
6
+ CommandFormDialog,
7
+ CommandFormDialogCancel,
8
+ CommandFormDialogContent,
9
+ CommandFormDialogFields,
10
+ CommandFormDialogFooter,
11
+ CommandFormDialogHeader,
12
+ CommandFormDialogSubmit,
13
+ CommandFormDialogTitle,
14
+ CommandFormDialogTrigger,
15
+ CommandLabel,
16
+ } from "@tulip-systems/core/commands/client";
17
+ import { Input } from "@tulip-systems/core/components";
18
+ import {
19
+ Form,
20
+ FormControl,
21
+ FormField,
22
+ FormItem,
23
+ FormLabel,
24
+ FormMessage,
25
+ } from "@tulip-systems/core/components/client";
26
+ import { FilePen } from "lucide-react";
27
+ import { useForm } from "react-hook-form";
28
+ import {
29
+ type UpdateGoogleDriveNodeInput,
30
+ updateGoogleDriveNodeInputSchema,
31
+ } from "../lib/validators";
32
+
33
+ export type GoogleDriveFileUpdateCommandProps<
34
+ TData = unknown,
35
+ TError = DefaultError,
36
+ TVariables = unknown,
37
+ TOnMutateResult = unknown,
38
+ > = {
39
+ defaultValues: Partial<UpdateGoogleDriveNodeInput>;
40
+ variables: (values: UpdateGoogleDriveNodeInput) => TVariables;
41
+ mutation: MutationOptions<TData, TError, TVariables, TOnMutateResult>;
42
+ };
43
+
44
+ /**
45
+ * File update command
46
+ * @description command to update a Google Drive file
47
+ */
48
+ export function GoogleDriveFileUpdateCommand<
49
+ TData = unknown,
50
+ TError = DefaultError,
51
+ TVariables = unknown,
52
+ TOnMutateResult = unknown,
53
+ >({
54
+ defaultValues,
55
+ variables,
56
+ mutation,
57
+ }: GoogleDriveFileUpdateCommandProps<TData, TError, TVariables, TOnMutateResult>) {
58
+ const form = useForm<UpdateGoogleDriveNodeInput>({
59
+ resolver: zodResolver(updateGoogleDriveNodeInputSchema),
60
+ defaultValues,
61
+ });
62
+
63
+ return (
64
+ <Form {...form}>
65
+ <CommandFormDialog>
66
+ <CommandFormDialogTrigger label="Wijzigen">
67
+ <FilePen className="size-4" />
68
+ <CommandLabel />
69
+ </CommandFormDialogTrigger>
70
+
71
+ <CommandFormDialogContent variables={variables} mutation={mutation}>
72
+ <CommandFormDialogHeader>
73
+ <CommandFormDialogTitle>Bestand wijzigen</CommandFormDialogTitle>
74
+ </CommandFormDialogHeader>
75
+
76
+ <CommandFormDialogFields>
77
+ <FormField
78
+ control={form.control}
79
+ name="name"
80
+ render={({ field }) => (
81
+ <FormItem>
82
+ <FormLabel>Naam</FormLabel>
83
+ <FormControl>
84
+ <Input {...field} value={field.value ?? ""} />
85
+ </FormControl>
86
+ <FormMessage />
87
+ </FormItem>
88
+ )}
89
+ />
90
+ </CommandFormDialogFields>
91
+
92
+ <CommandFormDialogFooter>
93
+ <CommandFormDialogCancel>Annuleren</CommandFormDialogCancel>
94
+ <CommandFormDialogSubmit>Opslaan</CommandFormDialogSubmit>
95
+ </CommandFormDialogFooter>
96
+ </CommandFormDialogContent>
97
+ </CommandFormDialog>
98
+ </Form>
99
+ );
100
+ }
@@ -0,0 +1,104 @@
1
+ "use client";
2
+
3
+ import { zodResolver } from "@hookform/resolvers/zod";
4
+ import type { DefaultError, MutationOptions } from "@tanstack/react-query";
5
+ import {
6
+ CommandFormDialog,
7
+ CommandFormDialogCancel,
8
+ CommandFormDialogContent,
9
+ CommandFormDialogFields,
10
+ CommandFormDialogFooter,
11
+ CommandFormDialogHeader,
12
+ CommandFormDialogSubmit,
13
+ CommandFormDialogTitle,
14
+ CommandFormDialogTrigger,
15
+ CommandLabel,
16
+ } from "@tulip-systems/core/commands/client";
17
+ import { Input } from "@tulip-systems/core/components";
18
+ import {
19
+ Form,
20
+ FormControl,
21
+ FormField,
22
+ FormItem,
23
+ FormLabel,
24
+ FormMessage,
25
+ } from "@tulip-systems/core/components/client";
26
+ import { FolderPlus } from "lucide-react";
27
+ import { useQueryStates } from "nuqs";
28
+ import { useForm } from "react-hook-form";
29
+ import { driveTreeSearchParams } from "@/lib/search-params";
30
+ import {
31
+ type CreateGoogleDriveFolderInput,
32
+ createGoogleDriveFolderInputSchema,
33
+ } from "../lib/validators";
34
+
35
+ export type GoogleDriveFoldersCreateCommandProps<
36
+ TData = unknown,
37
+ TError = DefaultError,
38
+ TVariables = unknown,
39
+ TOnMutateResult = unknown,
40
+ > = {
41
+ defaultValues?: Partial<CreateGoogleDriveFolderInput>;
42
+ variables: (values: CreateGoogleDriveFolderInput) => TVariables;
43
+ mutation: MutationOptions<TData, TError, TVariables, TOnMutateResult>;
44
+ };
45
+
46
+ /**
47
+ * Folders create command
48
+ * @description command to create a Google Drive folder
49
+ */
50
+ export function GoogleDriveFoldersCreateCommand<
51
+ TData = unknown,
52
+ TError = DefaultError,
53
+ TVariables = unknown,
54
+ TOnMutateResult = unknown,
55
+ >({
56
+ defaultValues,
57
+ variables,
58
+ mutation,
59
+ }: GoogleDriveFoldersCreateCommandProps<TData, TError, TVariables, TOnMutateResult>) {
60
+ const [{ parentId }] = useQueryStates(driveTreeSearchParams);
61
+
62
+ const form = useForm<CreateGoogleDriveFolderInput>({
63
+ resolver: zodResolver(createGoogleDriveFolderInputSchema),
64
+ defaultValues: { ...defaultValues, parentId },
65
+ });
66
+
67
+ return (
68
+ <Form {...form}>
69
+ <CommandFormDialog>
70
+ <CommandFormDialogTrigger label="Folder toevoegen" hotkey="mod+i">
71
+ <FolderPlus className="size-4" />
72
+ <CommandLabel />
73
+ </CommandFormDialogTrigger>
74
+
75
+ <CommandFormDialogContent variables={variables} mutation={mutation}>
76
+ <CommandFormDialogHeader>
77
+ <CommandFormDialogTitle>Folder toevoegen</CommandFormDialogTitle>
78
+ </CommandFormDialogHeader>
79
+
80
+ <CommandFormDialogFields>
81
+ <FormField
82
+ control={form.control}
83
+ name="name"
84
+ render={({ field }) => (
85
+ <FormItem>
86
+ <FormLabel>Naam</FormLabel>
87
+ <FormControl>
88
+ <Input {...field} value={field.value ?? ""} />
89
+ </FormControl>
90
+ <FormMessage />
91
+ </FormItem>
92
+ )}
93
+ />
94
+ </CommandFormDialogFields>
95
+
96
+ <CommandFormDialogFooter>
97
+ <CommandFormDialogCancel>Annuleren</CommandFormDialogCancel>
98
+ <CommandFormDialogSubmit>Toevoegen</CommandFormDialogSubmit>
99
+ </CommandFormDialogFooter>
100
+ </CommandFormDialogContent>
101
+ </CommandFormDialog>
102
+ </Form>
103
+ );
104
+ }
@@ -0,0 +1,100 @@
1
+ "use client";
2
+
3
+ import { zodResolver } from "@hookform/resolvers/zod";
4
+ import type { DefaultError, MutationOptions } from "@tanstack/react-query";
5
+ import {
6
+ CommandFormDialog,
7
+ CommandFormDialogCancel,
8
+ CommandFormDialogContent,
9
+ CommandFormDialogFields,
10
+ CommandFormDialogFooter,
11
+ CommandFormDialogHeader,
12
+ CommandFormDialogSubmit,
13
+ CommandFormDialogTitle,
14
+ CommandFormDialogTrigger,
15
+ CommandLabel,
16
+ } from "@tulip-systems/core/commands/client";
17
+ import { Input } from "@tulip-systems/core/components";
18
+ import {
19
+ Form,
20
+ FormControl,
21
+ FormField,
22
+ FormItem,
23
+ FormLabel,
24
+ FormMessage,
25
+ } from "@tulip-systems/core/components/client";
26
+ import { FolderPen } from "lucide-react";
27
+ import { useForm } from "react-hook-form";
28
+ import {
29
+ type UpdateGoogleDriveNodeInput,
30
+ updateGoogleDriveNodeInputSchema,
31
+ } from "../lib/validators";
32
+
33
+ export type GoogleDriveFoldersUpdateCommandProps<
34
+ TData = unknown,
35
+ TError = DefaultError,
36
+ TVariables = unknown,
37
+ TOnMutateResult = unknown,
38
+ > = {
39
+ defaultValues: Partial<UpdateGoogleDriveNodeInput>;
40
+ variables: (values: UpdateGoogleDriveNodeInput) => TVariables;
41
+ mutation: MutationOptions<TData, TError, TVariables, TOnMutateResult>;
42
+ };
43
+
44
+ /**
45
+ * Folders update command
46
+ * @description command to update a Google Drive folder
47
+ */
48
+ export function GoogleDriveFoldersUpdateCommand<
49
+ TData = unknown,
50
+ TError = DefaultError,
51
+ TVariables = unknown,
52
+ TOnMutateResult = unknown,
53
+ >({
54
+ defaultValues,
55
+ variables,
56
+ mutation,
57
+ }: GoogleDriveFoldersUpdateCommandProps<TData, TError, TVariables, TOnMutateResult>) {
58
+ const form = useForm<UpdateGoogleDriveNodeInput>({
59
+ resolver: zodResolver(updateGoogleDriveNodeInputSchema),
60
+ defaultValues,
61
+ });
62
+
63
+ return (
64
+ <Form {...form}>
65
+ <CommandFormDialog>
66
+ <CommandFormDialogTrigger label="Wijzigen">
67
+ <FolderPen className="size-4" />
68
+ <CommandLabel />
69
+ </CommandFormDialogTrigger>
70
+
71
+ <CommandFormDialogContent variables={variables} mutation={mutation}>
72
+ <CommandFormDialogHeader>
73
+ <CommandFormDialogTitle>Folder wijzigen</CommandFormDialogTitle>
74
+ </CommandFormDialogHeader>
75
+
76
+ <CommandFormDialogFields>
77
+ <FormField
78
+ control={form.control}
79
+ name="name"
80
+ render={({ field }) => (
81
+ <FormItem>
82
+ <FormLabel>Naam</FormLabel>
83
+ <FormControl>
84
+ <Input {...field} value={field.value ?? ""} />
85
+ </FormControl>
86
+ <FormMessage />
87
+ </FormItem>
88
+ )}
89
+ />
90
+ </CommandFormDialogFields>
91
+
92
+ <CommandFormDialogFooter>
93
+ <CommandFormDialogCancel>Annuleren</CommandFormDialogCancel>
94
+ <CommandFormDialogSubmit>Opslaan</CommandFormDialogSubmit>
95
+ </CommandFormDialogFooter>
96
+ </CommandFormDialogContent>
97
+ </CommandFormDialog>
98
+ </Form>
99
+ );
100
+ }
@@ -0,0 +1,6 @@
1
+ import { DriveContent } from "@/components/content";
2
+
3
+ /**
4
+ * GoogleDriveContent
5
+ */
6
+ export const GoogleDriveContent = DriveContent;
@@ -0,0 +1,21 @@
1
+ "use client";
2
+
3
+ import {
4
+ DriveHeader,
5
+ DriveHeaderBreadcrumbs,
6
+ DriveHeaderTools,
7
+ } from "@/components/navigation/header.client";
8
+ import {
9
+ DriveToolbar,
10
+ DriveToolbarBreadcrumbs,
11
+ DriveToolbarTools,
12
+ } from "@/components/navigation/toolbar.client";
13
+ import { DriveViewSwitcher } from "@/components/navigation/view-switcher.client";
14
+
15
+ export const GoogleDriveHeader = DriveHeader;
16
+ export const GoogleDriveHeaderBreadcrumbs = DriveHeaderBreadcrumbs;
17
+ export const GoogleDriveHeaderTools = DriveHeaderTools;
18
+ export const GoogleDriveToolbar = DriveToolbar;
19
+ export const GoogleDriveToolbarBreadcrumbs = DriveToolbarBreadcrumbs;
20
+ export const GoogleDriveToolbarTools = DriveToolbarTools;
21
+ export const GoogleDriveViewSwitcher = DriveViewSwitcher;
@@ -0,0 +1,60 @@
1
+ "use client";
2
+
3
+ import { Allowed } from "@tulip-systems/core/auth/client";
4
+ import { createContext, type PropsWithChildren, use } from "react";
5
+ import type { DriveContextValue } from "@/components/context.client";
6
+ import { DriveDragDropProvider } from "@/components/dnd.client";
7
+ import {
8
+ type DriveSelectionContextValue,
9
+ DriveSelectionProvider,
10
+ } from "@/components/selection.client";
11
+ import { DriveViewProvider, type DriveViewProviderProps } from "@/components/view.client";
12
+
13
+ /**
14
+ * GoogleDriveContextValue
15
+ */
16
+ export type GoogleDriveContextValue = DriveContextValue;
17
+
18
+ export const GoogleDriveContext = createContext({} as GoogleDriveContextValue);
19
+
20
+ /**
21
+ * useDriveContext
22
+ */
23
+ export function useGoogleDriveContext() {
24
+ const context = use(GoogleDriveContext);
25
+ if (!context) throw new Error("DriveContext not found!");
26
+ return context;
27
+ }
28
+
29
+ /**
30
+ * DriveContextProvider
31
+ */
32
+ type GoogleDriveProviderProps = PropsWithChildren<
33
+ GoogleDriveContextValue &
34
+ Partial<DriveSelectionContextValue> &
35
+ Pick<DriveViewProviderProps, "initialView">
36
+ >;
37
+
38
+ export function GoogleDriveProvider({
39
+ initialView = "grid",
40
+ namespace,
41
+ permission,
42
+ meta,
43
+ selection,
44
+ selectionConditions,
45
+ children,
46
+ }: GoogleDriveProviderProps) {
47
+ return (
48
+ <Allowed permission={permission}>
49
+ <DriveSelectionProvider selection={selection} selectionConditions={selectionConditions}>
50
+ <DriveViewProvider initialView={initialView}>
51
+ <DriveDragDropProvider>
52
+ <GoogleDriveContext value={{ namespace, permission, meta }}>
53
+ {children}
54
+ </GoogleDriveContext>
55
+ </DriveDragDropProvider>
56
+ </DriveViewProvider>
57
+ </DriveSelectionProvider>
58
+ </Allowed>
59
+ );
60
+ }
@@ -0,0 +1,158 @@
1
+ "use client";
2
+
3
+ import type { VisibilityState } from "@tanstack/react-table";
4
+ import type { CommandDef } from "@tulip-systems/core/commands";
5
+ import { FloatingCommandMenu } from "@tulip-systems/core/commands/client";
6
+ import { type TableColumnDef, TableLayout, TableSkeleton } from "@tulip-systems/core/data-tables";
7
+ import {
8
+ createTableConfig,
9
+ DataTable,
10
+ type InfiniteStrategyMeta,
11
+ TableConfigProvider,
12
+ type useInfiniteStrategy,
13
+ useTableConfigContext,
14
+ } from "@tulip-systems/core/data-tables/client";
15
+ import { type ComponentProps, useMemo } from "react";
16
+ import {
17
+ DriveGrid,
18
+ DriveGridBottombar,
19
+ DriveGridEmpty,
20
+ DriveGridLoading,
21
+ } from "@/components/grid.client";
22
+ import { DriveGridCard, DriveGridCardSkeleton } from "@/components/grid-card.client";
23
+ import { useDriveSelectionContext } from "@/components/selection.client";
24
+ import { useDriveViewContext } from "@/components/view.client";
25
+ import { googleDriveColumns } from "../config/columns-data";
26
+ import type { GoogleDriveNode } from "../lib/validators";
27
+ import { useGoogleDriveContext } from "./provider.client";
28
+
29
+ /**
30
+ * GoogleDriveContent
31
+ */
32
+ type GoogleDriveViewProviderProps<TData extends GoogleDriveNode = GoogleDriveNode> =
33
+ ComponentProps<"div"> & {
34
+ queryData: TData[];
35
+ columns?: TableColumnDef<TData>[];
36
+ strategy: ReturnType<typeof useInfiniteStrategy>;
37
+ commands?: CommandDef<TData>[];
38
+ columnVisibility?: VisibilityState;
39
+ };
40
+
41
+ export function GoogleDriveViewProvider<TData extends GoogleDriveNode = GoogleDriveNode>({
42
+ queryData,
43
+ columns = googleDriveColumns as TableColumnDef<TData>[],
44
+ strategy,
45
+ commands,
46
+ columnVisibility,
47
+ children,
48
+ ...props
49
+ }: GoogleDriveViewProviderProps<TData>) {
50
+ const { meta } = useGoogleDriveContext();
51
+ const { selection } = useDriveSelectionContext();
52
+
53
+ /**
54
+ * Table
55
+ */
56
+ const config = createTableConfig<TData>({
57
+ queryData,
58
+ columns,
59
+ strategy,
60
+ commands,
61
+ meta,
62
+ columnVisibility,
63
+ selection,
64
+ });
65
+
66
+ return (
67
+ <TableConfigProvider config={config}>
68
+ <TableLayout {...props}>{children}</TableLayout>
69
+ </TableConfigProvider>
70
+ );
71
+ }
72
+
73
+ /**
74
+ * GoogleDriveView
75
+ */
76
+ export function GoogleDriveView() {
77
+ const { view } = useDriveViewContext();
78
+
79
+ if (view === "grid") {
80
+ return <GoogleDriveGrid />;
81
+ }
82
+
83
+ if (view === "list") {
84
+ return <GoogleDriveList />;
85
+ }
86
+
87
+ return null;
88
+ }
89
+
90
+ /**
91
+ * GoogleDriveGrid
92
+ */
93
+ function GoogleDriveGrid(props: ComponentProps<"div">) {
94
+ const { queryData, strategy, commands, selection, meta } =
95
+ useTableConfigContext<GoogleDriveNode>();
96
+ const { rowCount, paginationState } = strategy;
97
+ const { isFetching, isFetchingNextPage, fetchNextPage } = strategy.meta as InfiniteStrategyMeta;
98
+
99
+ const hasNextPage = rowCount == null ? false : queryData.length < rowCount;
100
+
101
+ const selectedData = useMemo(
102
+ () => queryData.filter((node) => selection?.rowSelection?.[node.id] === true),
103
+ [queryData, selection?.rowSelection],
104
+ );
105
+
106
+ return (
107
+ <DriveGrid {...props}>
108
+ {queryData.length > 0 ? (
109
+ queryData.map((node) => <DriveGridCard key={node.id} node={node} commands={commands} />)
110
+ ) : (
111
+ <DriveGridEmpty title="Geen resultaten gevonden" />
112
+ )}
113
+
114
+ {isFetchingNextPage &&
115
+ Array.from({ length: paginationState?.pageSize ?? 0 }).map((_, index) => (
116
+ <DriveGridCardSkeleton key={index} />
117
+ ))}
118
+
119
+ <DriveGridBottombar
120
+ hasNextPage={hasNextPage}
121
+ fetchNextPage={fetchNextPage}
122
+ isFetching={isFetching}
123
+ isFetchingNextPage={isFetchingNextPage}
124
+ />
125
+
126
+ {commands && commands.length > 0 && (
127
+ <FloatingCommandMenu
128
+ data={selectedData as never}
129
+ commands={commands as never}
130
+ meta={meta}
131
+ state={selectedData.length > 0 ? "open" : "closed"}
132
+ onSuccess={() => selection?.setRowSelection?.({})}
133
+ />
134
+ )}
135
+ </DriveGrid>
136
+ );
137
+ }
138
+
139
+ /**
140
+ * GoogleDriveList
141
+ */
142
+ function GoogleDriveList(props: ComponentProps<typeof DataTable>) {
143
+ return <DataTable {...props} />;
144
+ }
145
+
146
+ /**
147
+ * GoogleDriveViewLoading
148
+ */
149
+ export function GoogleDriveViewLoading({ ...props }: ComponentProps<"div">) {
150
+ const { view } = useDriveViewContext();
151
+
152
+ return (
153
+ <div {...props}>
154
+ {view === "grid" && <DriveGridLoading {...props} />}
155
+ {view === "list" && <TableSkeleton {...props} />}
156
+ </div>
157
+ );
158
+ }