@compill/admin 1.0.115 → 1.0.116

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/index.js CHANGED
@@ -1,29 +1,31 @@
1
1
  import { jsx, jsxs, Fragment } from '@soperio/jsx-runtime';
2
2
  import { useApiQuery, useApiMutation, useMutate, useInvalidateMutation, useInvalidateQuery, useInvalidateParentMutation, useApiQueries } from '@compill/api';
3
- import { Shimmer, FlexCenter, QueryLoadingState, RetryOnError, TabContainer, ModalLoadingOverlay } from '@compill/components';
4
- import { mdiCircleSmall, mdiDatabaseRefreshOutline, mdiPost, mdiEye, mdiEyeOff, mdiCloudUpload, mdiOpenInNew, mdiArrowUpBoldBox, mdiArrowDownBoldBox, mdiPlusThick, mdiFilter, mdiRefresh, mdiPublish, mdiPublishOff, mdiDelete, mdiPencil, mdiCog, mdiDotsVertical, mdiLogout, mdiArrowLeft } from '@mdi/js';
5
- import { Icon, Button, Container, Tile, Popover, Collapse, Modal, Avatar, IconButton, Popup, Checkbox, Badge } from '@valerya/ui';
3
+ import { Shimmer, ButtonBarButton, FlexCenter, ButtonBar, TabContainer, ButtonBarDialogButton, DialogButton } from '@compill/components';
4
+ import { mdiCircleSmall, mdiDatabaseRefreshOutline, mdiPost, mdiEye, mdiEyeOff, mdiCloudUpload, mdiOpenInNew, mdiArrowUpBoldBox, mdiArrowDownBoldBox, mdiPlusThick, mdiFilter, mdiRefresh, mdiPublish, mdiPublishOff, mdiDelete, mdiPencil, mdiArrowLeft } from '@mdi/js';
5
+ import { Icon, Button, Container, Tile, Popover, Collapse, IconButton, Modal, Checkbox, Badge } from '@valerya/ui';
6
6
  import Link from 'next/link.js';
7
- import { useParams, useNavigate, Outlet, useLocation, useMatch, Link as Link$1 } from 'react-router-dom';
8
- import React from 'react';
7
+ import { useParams, useNavigate, Outlet } from 'react-router-dom';
9
8
  import { INVALIDATE_API, API, useInvalidatePage } from '@compill/admin-api';
10
- import { useFormikContext, Formik, Form } from 'formik';
9
+ import React from 'react';
11
10
  import { toast } from 'react-toastify';
11
+ import { ButtonBarSubmitButton, ItemEditDialog, ItemEditWrappedDialog, ItemEditMultiWrappedDialog, ItemDeleteDialog } from '@compill/form-components';
12
+ import { useFormikContext } from 'formik';
12
13
  import { useHotkeys } from 'react-hotkeys-hook';
13
14
  import { FormProvider, TextArea, FormRenderer, mergeInitialFormValues, FieldLabel, SubmitButton } from '@compill/form';
14
15
  import { createContext, runIfFn, isFunction } from '@soperio/react';
15
16
  import { FormEditor } from '@compill/form-editor';
16
17
  import { ImageExtension } from '@compill/editor';
18
+ import { QueryLoadingState, RetryOnError, ModalLoadingOverlay } from '@compill/components-state';
17
19
  import { createPortal } from 'react-dom';
18
20
  import { useRouter } from 'next/router.js';
19
21
  import { TableContextProvider, useTableContext, Table } from '@compill/table';
20
- import { isEqual, capitalize, sortBy } from 'es-toolkit';
22
+ import { isEqual, sortBy } from 'es-toolkit';
21
23
  import { useOpenLink, useBoolean } from '@compill/hooks';
22
24
  import { AppEnv } from '@compill/env';
23
25
  import { createColumnHelper } from '@tanstack/react-table';
24
26
  import { useQueryClient } from '@tanstack/react-query';
27
+ import { SidebarMenu, SidebarMenuUserBlock } from '@brikka/layout';
25
28
  import Image from 'next/image.js';
26
- import { useSessionUser, useSessionLogout } from '@compill/auth';
27
29
 
28
30
  function SectionTitle({ children, ...props }) {
29
31
  return /* @__PURE__ */ jsx("h2", { textSize: "xl", fontWeight: "600", textColor: "slate-800", ...props, children });
@@ -67,99 +69,6 @@ function BreadcrumbItem({ breadcrumb, showSeparator }) {
67
69
  ] });
68
70
  }
69
71
 
70
- function DialogButton({ buildDialog, ...props }) {
71
- const [showDialog, setShowDialog] = React.useState(false);
72
- const onShowDialog = React.useCallback((event) => {
73
- event?.preventDefault();
74
- event?.stopPropagation();
75
- setShowDialog(true);
76
- }, [setShowDialog]);
77
- const onCloseDialog = React.useCallback(() => {
78
- setShowDialog(false);
79
- }, [setShowDialog]);
80
- return /* @__PURE__ */ jsxs(Fragment, { children: [
81
- /* @__PURE__ */ jsx(Button, { onClick: onShowDialog, ...props }),
82
- showDialog && buildDialog(onCloseDialog)
83
- ] });
84
- }
85
-
86
- function ButtonBar({ children, ...props }) {
87
- return /* @__PURE__ */ jsx("div", { dflex: true, border: "1px", borderColor: "zinc-200", divideX: "1px", divideColor: "zinc-200", rounded: "lg", overflow: "hidden", ...props, children });
88
- }
89
- const ButtonBarButton = React.forwardRef(
90
- function({ icon, children, ...props }, ref) {
91
- return /* @__PURE__ */ jsxs(
92
- Button,
93
- {
94
- scheme: "dark",
95
- size: "sm",
96
- aspectRatio: icon && !children ? "square" : void 0,
97
- variant: "borderless",
98
- dflex: true,
99
- alignItems: "center",
100
- placeContent: "center",
101
- corners: "square",
102
- gap: "2",
103
- ...props,
104
- ref,
105
- children: [
106
- icon && /* @__PURE__ */ jsx(Icon, { path: icon }),
107
- children
108
- ]
109
- }
110
- );
111
- }
112
- );
113
- const ButtonBarSubmitButton = React.forwardRef(
114
- function({ useDirty, disabled, icon, children, ...props }, ref) {
115
- const { dirty, handleSubmit } = useFormikContext() ?? { dirty: false, handleSubmit: void 0};
116
- const onSubmit = React.useCallback(() => handleSubmit(), [handleSubmit]);
117
- return /* @__PURE__ */ jsxs(
118
- Button,
119
- {
120
- scheme: "dark",
121
- size: "sm",
122
- aspectRatio: icon && !children ? "square" : void 0,
123
- variant: "borderless",
124
- dflex: true,
125
- alignItems: "center",
126
- placeContent: "center",
127
- corners: "square",
128
- gap: "2",
129
- disabled: useDirty && !dirty || disabled,
130
- onClick: onSubmit,
131
- ...props,
132
- ref,
133
- children: [
134
- icon && /* @__PURE__ */ jsx(Icon, { path: icon }),
135
- children
136
- ]
137
- }
138
- );
139
- }
140
- );
141
- function ButtonBarDialogButton({ icon, children, ...props }) {
142
- return /* @__PURE__ */ jsxs(
143
- DialogButton,
144
- {
145
- scheme: "dark",
146
- size: "sm",
147
- aspectRatio: icon && !children ? "square" : void 0,
148
- variant: "borderless",
149
- dflex: true,
150
- alignItems: "center",
151
- placeContent: "center",
152
- corners: "square",
153
- gap: "2",
154
- ...props,
155
- children: [
156
- icon && /* @__PURE__ */ jsx(Icon, { path: icon }),
157
- children
158
- ]
159
- }
160
- );
161
- }
162
-
163
72
  function InvalidateButton({ pathOrPermalink, ...props }) {
164
73
  const api = INVALIDATE_API.new(pathOrPermalink);
165
74
  const mutation = useApiMutation(api.invalidate, api.queryKey);
@@ -739,172 +648,14 @@ function TableMassActions({ actions }) {
739
648
  return /* @__PURE__ */ jsx(Collapse, { in: showMassActions, style: { overflow: showMassActions ? "initial" : "hidden" }, children: /* @__PURE__ */ jsx("div", { dflex: true, gap: "3", flexWrap: true, alignItems: "center", px: "8", pt: "5", children: actions.map((action, index) => /* @__PURE__ */ jsx("div", { children: action.type == "button" && !action.showConfirmationDialog && /* @__PURE__ */ jsx(ActionButton$1, { label: action.label, queryFn: action.queryFn, queryKey: action.queryKey, buttonProps: action.buttonProps }) }, index)) }) });
740
649
  }
741
650
 
742
- const defaultErrorMsg$1 = "Oops, something went wrong...";
743
- function nonNullValues(data) {
744
- if (data) {
745
- const nonNullData = { ...data };
746
- for (const key in data)
747
- nonNullData[key] = nonNullData[key] ?? "";
748
- return nonNullData;
749
- }
750
- return data;
751
- }
752
- function ItemEditDialog({
753
- initialValues,
754
- itemLabel,
755
- queryId = "",
756
- api,
757
- queryFetchOptions,
758
- querySaveOptions,
759
- onSuccess,
760
- onFetchError,
761
- fetchErrorMsg = defaultErrorMsg$1,
762
- onSaveError,
763
- saveErrorMsg = defaultErrorMsg$1,
764
- fetchToFormData,
765
- formToQueryData,
766
- invalidateQueriesOnSuccess = true,
767
- invalidateQueryKey,
768
- retryText = "Retry",
769
- cancelLabel = "Cancel",
770
- saveLabel,
771
- size = "lg",
772
- title,
773
- form,
774
- show,
775
- onClose,
776
- formikProps,
777
- ...props
778
- }) {
779
- const { isInitialLoading, isFetching, data, isError, error, refetch } = useApiQuery(api.queryKey, api.get, queryId, {
780
- enabled: !/*queryId == 0 || */
781
- (queryId == "" || queryId == null || queryId == void 0),
782
- // means than this query is only enabled if the id is defined
783
- onError: onFetchError,
784
- ...queryFetchOptions
785
- });
786
- const mutation = invalidateQueriesOnSuccess ? useInvalidateParentMutation(api.upsert, invalidateQueryKey ?? api.queryKey, querySaveOptions) : useApiMutation(api.upsert, api.queryKey, queryId, querySaveOptions);
787
- const retry = React.useCallback(() => refetch(), [refetch]);
788
- const saveItem = React.useCallback(async (item, actions) => {
789
- mutation.reset();
790
- const formItem = formToQueryData ? formToQueryData(item) : { ...item };
791
- await mutation.mutateAsync(formItem).then((response) => {
792
- if (onSuccess)
793
- onSuccess(formItem, response);
794
- else
795
- toast.success(`${title ? title(formItem) : formItem.name ?? formItem.title} ${queryId ? "saved" : "created"}`);
796
- onClose?.();
797
- }).catch((error2) => {
798
- console.error("on error", error2);
799
- if (onSaveError)
800
- onSaveError(item);
801
- else
802
- toast.error(`Couldn't save ${title ? title(formItem) : formItem.name ?? formItem.title}`);
803
- actions.setSubmitting(false);
804
- });
805
- }, [mutation, formToQueryData, onSuccess, onSaveError, onClose]);
806
- return /* @__PURE__ */ jsxs(
807
- Modal,
808
- {
809
- size,
810
- show,
811
- onClose,
812
- scheme: "light",
813
- transition: true,
814
- ...props,
815
- children: [
816
- /* @__PURE__ */ jsxs(Modal.Header, { children: [
817
- !isInitialLoading && queryId && `Edit ${title ? title(data) : data?.["name"] ?? data?.["title"] ?? data?.["name"] ?? ""}`,
818
- !queryId && `Create new ${itemLabel ?? "item"}`,
819
- Array.isArray(form) && /* @__PURE__ */ jsx(Fragment, {})
820
- ] }),
821
- isInitialLoading && /* @__PURE__ */ jsx(Modal.Body, { children: /* @__PURE__ */ jsx(QueryLoadingState, { minW: "72" }) }),
822
- isError && /* @__PURE__ */ jsx(Modal.Body, { children: /* @__PURE__ */ jsx(RetryOnError, { label: `${fetchErrorMsg} ${error}`, onClick: retry }) }),
823
- !isInitialLoading && !isError && /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(
824
- Formik,
825
- {
826
- initialValues: fetchToFormData && queryId && data ? fetchToFormData(nonNullValues(data)) : nonNullValues(initialValues(data)) ?? {},
827
- onSubmit: saveItem,
828
- ...formikProps,
829
- children: ({ setFieldValue, dirty, handleSubmit, isValid, values }) => /* @__PURE__ */ jsxs(Fragment, { children: [
830
- /* @__PURE__ */ jsx(Modal.Body, { pb: "6", children: /* @__PURE__ */ jsxs(Form, { children: [
831
- React.isValidElement(form) && form,
832
- Array.isArray(form) && /* @__PURE__ */ jsx(FormRenderer, { form }),
833
- isFunction(form) && /* @__PURE__ */ jsx(FormRenderer, { form: form(data ?? values) })
834
- ] }) }),
835
- /* @__PURE__ */ jsxs(Modal.Footer, { dflex: true, placeContent: "end", spaceX: "3", children: [
836
- /* @__PURE__ */ jsx(
837
- Button,
838
- {
839
- disabled: mutation.isLoading,
840
- onClick: onClose,
841
- variant: "borderless",
842
- me: "2",
843
- children: cancelLabel
844
- }
845
- ),
846
- /* @__PURE__ */ jsx(
847
- Button,
848
- {
849
- type: "submit",
850
- disabled: !dirty || mutation.isLoading,
851
- onClick: () => handleSubmit(),
852
- children: saveLabel ? saveLabel : queryId ? "Update" : "Create"
853
- }
854
- )
855
- ] })
856
- ] })
857
- }
858
- ) }),
859
- mutation.isLoading && /* @__PURE__ */ jsx(ModalLoadingOverlay, {})
860
- ]
861
- }
862
- );
863
- }
864
-
865
- function QueryWrapperDialog({ api, fn, transformFn, config, onClose, queryId, invalidateQueryKey }) {
866
- const { data, isFetching } = useApiQuery(
867
- api.queryKey,
868
- fn === "get" || fn === "getTransformed" ? api.get : api.getAll,
869
- void 0,
870
- { retryOnMount: false, refetchOnMount: false, refetchOnWindowFocus: false }
871
- );
872
- const transformedData = React.useMemo(() => {
873
- if (data && (fn === "getTransformed" || fn === "getAllTransformed")) {
874
- if (!transformFn)
875
- console.warn(`QueryWrapperDialog: you forgot to pass transformFn as parameter for fn ${fn}`);
876
- return transformFn?.(data);
877
- }
878
- return data;
879
- }, [data, fn, transformFn]);
880
- if (isFetching)
881
- return null;
882
- return /* @__PURE__ */ jsx(ItemEditDialog, { ...config(transformedData), queryId, invalidateQueryKey, show: true, onClose });
883
- }
884
-
885
- function MultiQueryWrapperDialog({ queries, config, onClose, queryId, invalidateQueryKey }) {
886
- const { data, isFetching, isError } = useApiQueries(queries.map((q) => ({
887
- queryKey: q.api.queryKey,
888
- queryFn: q.fn == "get" ? q.api.get : q.api.getAll,
889
- queryOptions: {
890
- cacheTime: q.cache === false ? 0 : void 0,
891
- staleTime: q.cache === false ? 0 : void 0
892
- }
893
- })));
894
- const transformedData = React.useMemo(() => {
895
- return data?.map((d, index) => queries[index]?.transformFn ? queries[index]?.transformFn?.(d) : d);
896
- }, [data, queries]);
897
- return /* @__PURE__ */ jsx(ItemEditDialog, { isPreloading: isFetching, ...config(...transformedData), queryId, invalidateQueryKey, show: true, onClose });
898
- }
899
-
900
651
  function DialogRenderer({ config, onClose, invalidateQueryKey, queryId }) {
901
652
  const { type, ...props } = config;
902
653
  if (config.type === "dialog")
903
654
  return /* @__PURE__ */ jsx(ItemEditDialog, { ...props, queryId, invalidateQueryKey, show: true, onClose });
904
655
  if (config.type === "query")
905
- return /* @__PURE__ */ jsx(QueryWrapperDialog, { ...props, queryId, invalidateQueryKey, onClose });
656
+ return /* @__PURE__ */ jsx(ItemEditWrappedDialog, { ...props, queryId, invalidateQueryKey, onClose });
906
657
  if (config.type === "multiQuery")
907
- return /* @__PURE__ */ jsx(MultiQueryWrapperDialog, { ...props, queryId, invalidateQueryKey, onClose });
658
+ return /* @__PURE__ */ jsx(ItemEditMultiWrappedDialog, { ...props, queryId, invalidateQueryKey, onClose });
908
659
  return null;
909
660
  }
910
661
 
@@ -914,67 +665,6 @@ function RefreshButton({ queryKey }) {
914
665
  return /* @__PURE__ */ jsx(ButtonBarButton, { scheme: "dark", size: "sm", aspectRatio: "square", variant: "borderless", onClick: invalidate, children: /* @__PURE__ */ jsx(Icon, { path: mdiRefresh }) });
915
666
  }
916
667
 
917
- function ItemDeleteDialog({
918
- title,
919
- actionButtonLabel,
920
- closeActionButtonLabel = "Cancel",
921
- itemLabel,
922
- queryId = "",
923
- api,
924
- apiFn,
925
- invalidateQueriesOnSuccess = true,
926
- invalidateQueryKey,
927
- size = "lg",
928
- md_boxSizing,
929
- msg,
930
- show,
931
- onClose,
932
- onSuccess,
933
- ...props
934
- }) {
935
- const fn = apiFn ? api[apiFn] : api.delete;
936
- const mutation = invalidateQueriesOnSuccess ? useInvalidateParentMutation(fn, invalidateQueryKey ?? api.queryKey) : useApiMutation(fn, api.queryKey);
937
- const mutate = useMutate(mutation, { onSuccess: () => {
938
- onClose?.();
939
- onSuccess?.();
940
- } });
941
- const handleDelete = React.useCallback(() => mutate(queryId), [mutate, queryId]);
942
- return /* @__PURE__ */ jsxs(
943
- Modal,
944
- {
945
- size,
946
- show,
947
- onClose,
948
- scheme: "danger",
949
- variant: "glass",
950
- transition: true,
951
- ...props,
952
- children: [
953
- /* @__PURE__ */ jsx(Modal.Header, { children: title || `Delete ${itemLabel}` }),
954
- /* @__PURE__ */ jsxs(Modal.Body, { pb: "6", children: [
955
- !msg && `Do you really want to delete ${itemLabel}?`,
956
- msg && runIfFn(msg, itemLabel)
957
- ] }),
958
- /* @__PURE__ */ jsxs(Modal.Footer, { dflex: true, placeContent: "end", spaceX: "3", children: [
959
- /* @__PURE__ */ jsx(
960
- Button,
961
- {
962
- disabled: mutation.isPending,
963
- onClick: onClose,
964
- variant: "borderless",
965
- scheme: "dark",
966
- me: "2",
967
- children: closeActionButtonLabel
968
- }
969
- ),
970
- /* @__PURE__ */ jsx(Button, { scheme: "danger", disabled: mutation.isPending, onClick: handleDelete, children: actionButtonLabel || "Delete" })
971
- ] }),
972
- mutation.isPending && /* @__PURE__ */ jsx(ModalLoadingOverlay, {})
973
- ]
974
- }
975
- );
976
- }
977
-
978
668
  const [provider, useContext] = createContext();
979
669
  function TableViewProvider({ editView, deleteItem, queryKey, children }) {
980
670
  const openLink = useOpenLink();
@@ -1323,283 +1013,6 @@ function Content({ ...props }) {
1323
1013
  return /* @__PURE__ */ jsx("div", { w: "100%", h: "100%", overflowY: "auto", ...props, children: /* @__PURE__ */ jsx(Outlet, {}) });
1324
1014
  }
1325
1015
 
1326
- function SelectedIndicator({ darkMode }) {
1327
- return /* @__PURE__ */ jsx(
1328
- "div",
1329
- {
1330
- position: "absolute",
1331
- bgColor: darkMode ? "white" : "black",
1332
- bgOpacity: "90",
1333
- w: "0.5",
1334
- h: "6",
1335
- top: "1.5",
1336
- start: "-4"
1337
- }
1338
- );
1339
- }
1340
-
1341
- function MenuButton({ depth, darkMode, icon, selected, children, ...props }) {
1342
- return /* @__PURE__ */ jsxs(
1343
- Button,
1344
- {
1345
- as: "li",
1346
- minH: "8",
1347
- ms: `${(depth ?? 0) * 2}`,
1348
- p: "2",
1349
- font: "title",
1350
- textColor: darkMode ? "white" : "black",
1351
- fontWeight: "600",
1352
- rounded: "lg",
1353
- textSize: "sm",
1354
- variant: "borderless",
1355
- hover_bgColor: darkMode ? "white" : "black",
1356
- hover_bgOpacity: "10",
1357
- hover_textColor: darkMode ? "white" : "zinc-800",
1358
- cursor: "pointer",
1359
- dflex: true,
1360
- alignItems: "center",
1361
- gap: "3",
1362
- ...props,
1363
- children: [
1364
- icon && /* @__PURE__ */ jsx(Icon, { path: icon, opacity: selected ? "100" : "60" }),
1365
- children
1366
- ]
1367
- }
1368
- );
1369
- }
1370
-
1371
- function MenuItem$1({ icon, path, depth, darkMode, subMenu, ...props }) {
1372
- const location = useLocation();
1373
- const selected = path == "/" ? location.pathname == "/" : location.pathname.startsWith(path.startsWith("/") ? path : `/${path}`);
1374
- const match = useMatch("/" + path) != null;
1375
- return /* @__PURE__ */ jsxs(Fragment, { children: [
1376
- /* @__PURE__ */ jsxs(Link$1, { to: path, style: { position: "relative" }, children: [
1377
- /* @__PURE__ */ jsx(
1378
- MenuButton,
1379
- {
1380
- depth,
1381
- darkMode,
1382
- icon,
1383
- selected,
1384
- ...props
1385
- }
1386
- ),
1387
- match && /* @__PURE__ */ jsx(SelectedIndicator, { darkMode })
1388
- ] }),
1389
- subMenu?.map((item, index) => /* @__PURE__ */ jsx(
1390
- MenuItem$1,
1391
- {
1392
- icon: item.icon,
1393
- path: item.path,
1394
- depth: (depth ?? 0) + 1,
1395
- darkMode,
1396
- subMenu: item.children,
1397
- children: item.label
1398
- },
1399
- index
1400
- ))
1401
- ] });
1402
- }
1403
-
1404
- function NextMenuItem({ icon, path, depth, darkMode, subMenu, ...props }) {
1405
- const { pathname } = useRouter();
1406
- const selected = path == "/" ? pathname == "/" : pathname.startsWith(path.startsWith("/") ? path : `/${path}`);
1407
- const match = path == "/" ? pathname == "/" : pathname == (path.startsWith("/") ? path : `/${path}`);
1408
- return /* @__PURE__ */ jsxs(Fragment, { children: [
1409
- /* @__PURE__ */ jsxs(Link, { href: path, style: { position: "relative" }, children: [
1410
- /* @__PURE__ */ jsx(
1411
- MenuButton,
1412
- {
1413
- depth,
1414
- darkMode,
1415
- icon,
1416
- selected,
1417
- ...props
1418
- }
1419
- ),
1420
- match && /* @__PURE__ */ jsx(SelectedIndicator, { darkMode })
1421
- ] }),
1422
- subMenu?.map((item, index) => /* @__PURE__ */ jsx(
1423
- NextMenuItem,
1424
- {
1425
- icon: item.icon,
1426
- path: item.path,
1427
- depth: (depth ?? 0) + 1,
1428
- darkMode,
1429
- subMenu: item.children,
1430
- children: item.label
1431
- },
1432
- index
1433
- ))
1434
- ] });
1435
- }
1436
-
1437
- function Menu({ darkMode, config, useNextRouter, ...props }) {
1438
- const Comp = useNextRouter ? NextMenuItem : MenuItem$1;
1439
- return /* @__PURE__ */ jsx("ul", { ...props, children: config.map((item, index) => {
1440
- if (item.type == "divider")
1441
- return /* @__PURE__ */ jsx(Divider, { title: item.label }, index);
1442
- if (item.type == "item") {
1443
- return /* @__PURE__ */ jsx(
1444
- Comp,
1445
- {
1446
- icon: item.icon,
1447
- path: item.path,
1448
- depth: 0,
1449
- darkMode,
1450
- subMenu: item.children,
1451
- children: item.label
1452
- },
1453
- index
1454
- );
1455
- }
1456
- }) });
1457
- }
1458
- function Divider({ title }) {
1459
- return /* @__PURE__ */ jsx(
1460
- "div",
1461
- {
1462
- px: "2",
1463
- mt: "5",
1464
- mb: "2",
1465
- opacity: "75",
1466
- textTransform: "capitalize",
1467
- letterSpacing: "widest",
1468
- fontWeight: "700",
1469
- textSize: "xs",
1470
- children: title
1471
- }
1472
- );
1473
- }
1474
-
1475
- function UserBlock({ color, darkMode, menuConfig, path }) {
1476
- const { isLoading, user } = useSessionUser();
1477
- const navigate = useNavigate();
1478
- const handleClick = React.useCallback(() => navigate(path), [navigate, path]);
1479
- if (isLoading)
1480
- return null;
1481
- return /* @__PURE__ */ jsxs(
1482
- "div",
1483
- {
1484
- dflex: true,
1485
- alignItems: "center",
1486
- border: "0.5",
1487
- borderColor: `${color}-${darkMode ? "800" : "200"}`,
1488
- ps: "3",
1489
- py: "1.5",
1490
- textSize: "md",
1491
- rounded: "lg",
1492
- hover_bgColor: `${color}-${darkMode ? "800" : "200"}`,
1493
- cursor: "pointer",
1494
- textColor: darkMode ? "white" : "slate-800",
1495
- onClick: handleClick,
1496
- children: [
1497
- /* @__PURE__ */ jsx(Avatar, { size: "sm", src: user?.media?.url ?? "", name: `${user?.firstname} ${user?.lastname}` }),
1498
- /* @__PURE__ */ jsx("span", { flexGrow: true, ms: "2", children: `${capitalize(user?.firstname || user?.lastname || "")}` }),
1499
- /* @__PURE__ */ jsx(
1500
- IconButton,
1501
- {
1502
- variant: "borderless",
1503
- corners: "pill",
1504
- scheme: "dark",
1505
- textColor: darkMode ? "white" : "slate-800",
1506
- hover_textColor: darkMode ? "white" : "slate-800",
1507
- hover_bgColor: `${color}-${darkMode ? "900" : "200"}`,
1508
- icon: mdiCog,
1509
- onClick: handleClick
1510
- }
1511
- ),
1512
- /* @__PURE__ */ jsx(OverflowMenu, { color, darkMode, menuConfig })
1513
- ]
1514
- }
1515
- );
1516
- }
1517
- function OverflowMenu({ color, darkMode, menuConfig }) {
1518
- const [showPopup, setShowPopup] = React.useState(false);
1519
- const navigate = useNavigate();
1520
- const logout = useSessionLogout(false);
1521
- return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(
1522
- Popup,
1523
- {
1524
- show: showPopup,
1525
- position: "relative",
1526
- side: "bottom-end",
1527
- onClick: (e) => {
1528
- e.preventDefault();
1529
- e.stopPropagation();
1530
- setShowPopup((show) => !show);
1531
- },
1532
- onHide: () => setShowPopup(false),
1533
- children: [
1534
- /* @__PURE__ */ jsx(
1535
- IconButton,
1536
- {
1537
- icon: mdiDotsVertical,
1538
- variant: "borderless",
1539
- corners: "pill",
1540
- scheme: "dark",
1541
- textColor: darkMode ? "white" : "slate-800",
1542
- hover_textColor: darkMode ? "white" : "slate-800",
1543
- hover_bgColor: `${color}-${darkMode ? "900" : "200"}`
1544
- }
1545
- ),
1546
- /* @__PURE__ */ jsxs(
1547
- "div",
1548
- {
1549
- bgColor: "white",
1550
- rounded: "sm",
1551
- overflow: "hidden",
1552
- shadow: true,
1553
- mt: "1",
1554
- border: "px",
1555
- borderColor: "gray-200",
1556
- divideColor: "gray-200",
1557
- divideY: "px",
1558
- minW: "40",
1559
- children: [
1560
- menuConfig && menuConfig.length > 0 && menuConfig.map((item, index) => {
1561
- if (item.type == "item") {
1562
- return /* @__PURE__ */ jsx(MenuItem, { icon: item.icon, onClick: () => navigate(item.path), children: item.label }, index);
1563
- }
1564
- return null;
1565
- }),
1566
- /* @__PURE__ */ jsx(MenuItem, { icon: mdiLogout, onClick: logout, children: "Logout" })
1567
- ]
1568
- }
1569
- )
1570
- ]
1571
- }
1572
- ) });
1573
- }
1574
- function MenuItem({ icon, onClick, children, ...props }) {
1575
- const handleClick = React.useCallback((e) => {
1576
- e.preventDefault();
1577
- e.stopPropagation();
1578
- onClick?.(e);
1579
- }, []);
1580
- return /* @__PURE__ */ jsxs(
1581
- Button,
1582
- {
1583
- variant: "borderless",
1584
- scheme: "dark",
1585
- size: "sm",
1586
- alignItems: "center",
1587
- dflex: true,
1588
- gap: "2",
1589
- px: "2",
1590
- py: "1.5",
1591
- w: "full",
1592
- onClick: handleClick,
1593
- textColor: "slate-700",
1594
- ...props,
1595
- children: [
1596
- icon && /* @__PURE__ */ jsx(Icon, { path: icon, size: "md" }),
1597
- children
1598
- ]
1599
- }
1600
- );
1601
- }
1602
-
1603
1016
  function Sidebar({ show, logo, title, menuConfig, userMenuConfig, userSettingsPath, color, darkMode, ...props }) {
1604
1017
  return /* @__PURE__ */ jsxs(
1605
1018
  "div",
@@ -1629,8 +1042,8 @@ function Sidebar({ show, logo, title, menuConfig, userMenuConfig, userSettingsPa
1629
1042
  ]
1630
1043
  }
1631
1044
  ),
1632
- /* @__PURE__ */ jsx(Menu, { overflowY: "auto", flexGrow: "1", p: "4", darkMode, config: menuConfig }),
1633
- /* @__PURE__ */ jsx("div", { p: "2", children: /* @__PURE__ */ jsx(UserBlock, { darkMode, color, menuConfig: userMenuConfig, path: userSettingsPath }) })
1045
+ /* @__PURE__ */ jsx(SidebarMenu, { overflowY: "auto", flexGrow: "1", p: "4", darkMode, config: menuConfig }),
1046
+ /* @__PURE__ */ jsx("div", { p: "2", children: /* @__PURE__ */ jsx(SidebarMenuUserBlock, { darkMode, color, menuConfig: userMenuConfig, path: userSettingsPath }) })
1634
1047
  ]
1635
1048
  }
1636
1049
  );
@@ -2064,4 +1477,4 @@ function TableRowPublishPostButton({ id, api, status, invalidateQueryKey, ...pro
2064
1477
  return /* @__PURE__ */ jsx(TableRowActionButton, { icon: isDraft ? mdiPublish : mdiPublishOff, onClick: publish, ...props });
2065
1478
  }
2066
1479
 
2067
- export { AdminLayout, AttachDialog, Breadcrumbs, ButtonBar, ButtonBarButton, ButtonBarDialogButton, ButtonBarSubmitButton, DialogButton, FormActionDialog, InvalidateButton, ItemDeleteDialog, ItemEditDialog, Menu, NavigateButton, OrderCell, PageContainer, PageContentEditor, PageMain, PageQueryStateContainer, PageSectionTitle, PageSidebar, PageSidebarSection, PageStateContainer, PageSubSectionTitle, PageTabbedTopBar, PageTabbedTopBarProvider, PageTitle, PageTopBar, PageTopBarToolbar, PublishButton, ScreenRenderer, SectionTitle, StatusBadge, TableContainer, TableCreateButton, TableFilterButton, TableRowActionBar, TableRowActionButton, TableRowActionDialogButton, TableRowDeleteButton, TableRowEditButton, TableRowNavigateButton, TableRowPublishPostButton, TableRowViewButton, TableTopBar, UpdateButton, ViewButton };
1480
+ export { AdminLayout, AttachDialog, Breadcrumbs, FormActionDialog, InvalidateButton, NavigateButton, OrderCell, PageContainer, PageContentEditor, PageMain, PageQueryStateContainer, PageSectionTitle, PageSidebar, PageSidebarSection, PageStateContainer, PageSubSectionTitle, PageTabbedTopBar, PageTabbedTopBarProvider, PageTitle, PageTopBar, PageTopBarToolbar, PublishButton, ScreenRenderer, SectionTitle, StatusBadge, TableContainer, TableCreateButton, TableFilterButton, TableRowActionBar, TableRowActionButton, TableRowActionDialogButton, TableRowDeleteButton, TableRowEditButton, TableRowNavigateButton, TableRowPublishPostButton, TableRowViewButton, TableTopBar, UpdateButton, ViewButton };
@@ -1,4 +1,4 @@
1
- import { ButtonBarButtonProps } from "../layout/ButtonBar";
1
+ import { ButtonBarButtonProps } from "@compill/components";
2
2
  interface InvalidateButtonProps extends ButtonBarButtonProps {
3
3
  pathOrPermalink: string;
4
4
  }
@@ -1,4 +1,4 @@
1
- import { ButtonBarButtonProps } from "../layout/ButtonBar";
1
+ import { ButtonBarButtonProps } from "@compill/components";
2
2
  export declare function ViewButton({ label, path, icon, ...props }: ButtonBarButtonProps & {
3
3
  label?: string;
4
4
  path: string;