UNPKG

@ucheeddev/refine-antd

Version:

Custom Ant Design components for Refine framework

1,609 lines (1,561 loc) 148 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var index_exports = {}; __export(index_exports, { AccountDropdown: () => AccountDropdown, AvatarGroup: () => AvatarGroup, BackButton: () => BackButton, Bootstrap: () => Bootstrap, CircleIconButtonAction: () => CircleIconButtonAction, CurrentUser: () => CurrentUser, CustomAvatar: () => CustomAvatar, CustomDatePicker: () => CustomDatePicker, CustomTabs: () => CustomTabs, CustomTimePicker: () => CustomTimePicker, DEFAULT_THEME_CONFIG: () => DEFAULT_THEME_CONFIG, EmailLink: () => EmailLink, Fallback: () => Fallback, FieldFormTitle: () => FieldFormTitle, FilterDropdown: () => FilterDropdown, FormLoadingSkeleton: () => FormLoadingSkeleton, FormattedNumberField: () => FormattedNumberField, FullScreenLoading: () => FullScreenLoading, FullWidthLayout: () => FullWidthLayout, HeaderWithSearch: () => HeaderWithSearch, IconInvoicerLogo: () => IconInvoicerLogo, IconMoon: () => IconMoon, IconSun: () => IconSun, ImageUpload: () => ImageUpload, ImportButton: () => ImportButton, ImportModal: () => ImportModal, Layout: () => Layout5, LayoutContext: () => LayoutContext, LayoutContextProvider: () => LayoutContextProvider, LeftHeader: () => LeftHeader, ListPage: () => ListPage, ListTitleButton: () => ListTitleButton, Logo: () => Logo, OwnerDropdown: () => OwnerDropdown, PaginationTotal: () => PaginationTotal, PhoneNumberLink: () => PhoneNumberLink, ProfileMeta: () => ProfileMeta, ProfileMetaEdit: () => ProfileMetaEdit, RecordQuickActions: () => RecordQuickActions, SelectOptionWithAvatar: () => SelectOptionWithAvatar, ShowLinkButton: () => ShowLinkButton, Sider: () => Sider, SingleElementForm: () => SingleElementForm, SpreadThreeColumns: () => SpreadThreeColumns, SpreadsTwoColumn: () => SpreadsTwoColumn, Text: () => Text, TextIcon: () => TextIcon, Title: () => Title, Unauthorized: () => Unauthorized, UploadButton: () => UploadButton, UserPhotoUpload: () => UserPhotoUpload, isUrl: () => isUrl, lightenHexColor: () => lightenHexColor, useAccountSelect: () => useAccountSelect, useImportModal: () => useImportModal, useIsUrlButton: () => useIsUrlButton, useLayoutContext: () => useLayoutContext, useOwnership: () => useOwnership, usePhoneinput: () => usePhoneinput, useStyles: () => useStyles, useThemeConfig: () => useThemeConfig, useUserSelect: () => useUserSelect }); module.exports = __toCommonJS(index_exports); // src/components/account-dropdown/account-dropdown.tsx var import_core2 = require("@refinedev/core"); var import_antd8 = require("antd"); // src/hooks/import-modal/import-modal.ts var import_react = require("react"); var import_antd = require("@refinedev/antd"); var import_refine_core = require("@ucheeddev/refine-core"); var useImportModal = ({ resource, args }) => { const parseArgs = args?.parseArgs; const [isOpen, setIsOpen] = (0, import_react.useState)(false); const { isLoading, triggerImport, canAccess } = (0, import_refine_core.useAsyncImport)({ resource }); const { modalProps, formProps } = (0, import_antd.useModalForm)({ action: "create" }); const openModal = (0, import_react.useCallback)(() => setIsOpen(true), []); const onCancel = (0, import_react.useCallback)(() => setIsOpen(false), []); const onFinish = (0, import_react.useCallback)( (values) => { const parsedArgs = parseArgs ? parseArgs(values) : values; setIsOpen(false); return triggerImport(parsedArgs); }, [parseArgs, triggerImport] ); return { modalProps, isLoading, formProps, onCancel, isOpen, onFinish, openModal, canAccess }; }; // src/hooks/is-url-button/is-url-button.ts var import_react2 = require("react"); // src/utils/is-url/is-url.ts var isUrl = (url) => { try { new URL(url || ""); return true; } catch (e) { return false; } }; // src/utils/lighten-hex-color/lighten-hex-color.ts var lightenHexColor = (color, amount) => { amount = amount || 20; if (!color) { return ""; } if (color[0] === "#") { color = color.slice(1); } let r = parseInt(color.substring(0, 2), 16); let g = parseInt(color.substring(2, 4), 16); let b = parseInt(color.substring(4, 6), 16); r = Math.min(255, r + amount); g = Math.min(255, g + amount); b = Math.min(255, b + amount); r = r < 0 ? 0 : r; g = g < 0 ? 0 : g; b = b < 0 ? 0 : b; const newColor = "#" + ("0" + r.toString(16)).slice(-2) + ("0" + g.toString(16)).slice(-2) + ("0" + b.toString(16)).slice(-2); return newColor; }; // src/hooks/is-url-button/is-url-button.ts var useIsUrlButton = ({ url }) => { const __isUrl = (0, import_react2.useMemo)(() => isUrl(url), [url]); const onClick = (0, import_react2.useCallback)(() => { if (!__isUrl) { return; } window.open(url, "_blank"); }, [url, __isUrl]); return { isUrl: __isUrl, onClick }; }; // src/hooks/ownership/ownership.tsx var import_react3 = require("react"); var import_core = require("@refinedev/core"); var import_icons = require("@ant-design/icons"); var import_jsx_runtime = require("react/jsx-runtime"); var useOwnership = (resource) => { const { data: canViewOthers } = (0, import_core.useCan)({ resource, action: "view_others" }); const { data: canEditOthers } = (0, import_core.useCan)({ resource, action: "edit_others" }); const { data: canEditOwnership } = (0, import_core.useCan)({ resource, action: "edit_ownership" }); const { data: canDeleteOthers } = (0, import_core.useCan)({ resource, action: "delete_others" }); const { data: canListUsers } = (0, import_core.useCan)({ resource: "users", action: "list" }); const appendOwnerTableColumns = (0, import_react3.useCallback)( (columns, args) => { const title = args?.title || "Owner"; const viewType = args?.viewType || "selectOptionWithAvatar"; const roleFilters = args?.role ? [ { field: "role", operator: "eq", value: args.role } ] : void 0; if (!canViewOthers?.can) { return; } columns.push({ title, dataIndex: "owner", filterIcon: args?.hideFilter ? false : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.FilterOutlined, {}), filterDropdown: args?.hideFilter ? void 0 : !!canListUsers?.can ? (props) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FilterDropdown, { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(OwnerDropdown, { width: 200, filters: roleFilters }) }) : void 0, render: (owner) => { return owner ? viewType === "selectOptionWithAvatar" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)( SelectOptionWithAvatar, { name: owner.full_name, avatarUrl: owner.photo, shape: "square" } ) : owner.full_name : "--"; } }); }, [canListUsers?.can, canViewOthers?.can] ); const renderOwnerEditField = (0, import_react3.useCallback)( ({ getFormProps, owner, hideIcon, selectProps, label, viewType = "selectOptionWithAvatar", role }) => { if (!canViewOthers?.can) { return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, {}); } const roleFilters = role ? [ { field: "role", operator: "eq", value: role } ] : void 0; return /* @__PURE__ */ (0, import_jsx_runtime.jsx)( SingleElementForm, { icon: hideIcon ? void 0 : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_icons.UserOutlined, { className: "colorPrimary" }), ...getFormProps({ name: "owner", label: label || "Owner", initialValue: owner?.id }), view: owner ? viewType === "selectOptionWithAvatar" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)( SelectOptionWithAvatar, { name: owner.full_name, avatarUrl: owner.photo, shape: "square" } ) : owner.full_name : "--", isDisabled: !canEditOwnership?.can, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( OwnerDropdown, { ...selectProps || {}, filters: selectProps?.filters ?? roleFilters } ) } ); }, [canEditOwnership?.can, canViewOthers?.can] ); return { canViewOthers: !!canViewOthers?.can, canEditOthers: !!canEditOthers?.can, canEditOwnership: !!canEditOwnership?.can, canDeleteOthers: !!canDeleteOthers?.can, canListUsers: !!canListUsers?.can, appendOwnerTableColumns, renderOwnerEditField }; }; // src/hooks/theme-config/use-theme-config.ts var import_react4 = require("react"); var import_refine_core2 = require("@ucheeddev/refine-core"); var import_antd2 = require("antd"); // src/constants/theme-config.ts var DEFAULT_THEME_CONFIG = { // token: { // colorPrimaryText: 'rgba(0, 0, 0, 0.85)', // colorTextSecondary: 'rgba(0, 0, 0, 0.65)', // colorTextTertiary: 'rgba(0, 0, 0, 0.45)', // colorPrimary: '#6eb2cc', // colorBgContainer: '#FFFFFF', // colorBgLayout: '#F0F2F5', // colorBorderBg: '#E8E9EA', // fontFamily: // "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', 'Arial', 'Noto Sans', 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'", // }, // components: { // Typography: { // colorText: 'rgba(0, 0, 0, 0.85)', // colorTextDescription: 'rgba(0, 0, 0, 0.65)', // colorTextDisabled: 'rgba(0, 0, 0, 0.45)', // }, // Card: { // colorBgContainer: '#FFFFFF', // headerBg: '#FFFFFF', // boxShadowTertiary: // '0px 1px 2px 0px #00000008,0px 1px 6px -1px #000000050px,2px 4px 0px #00000005', // }, // Table: { // colorBgContainer: '#fff', // }, // Input: { // colorBgContainer: '#fff', // }, // InputNumber: { // colorBgContainer: '#fff', // }, // Calendar: { // colorBgContainer: '#FFFFFF', // }, // Radio: { // colorBgContainer: '#fff', // }, // Select: { // colorBgContainer: '#fff', // }, // }, }; // src/hooks/theme-config/use-theme-config.ts var useThemeConfig = (props) => { const { overrides, mode } = props; const { token: tokenOverrides, ...overridesRest } = overrides || {}; const settings = (0, import_refine_core2.useServerSettingsStore)((state) => state.settings); const colorPrimary = settings?.primary_color || ""; const colorPrimaryDark = settings?.primary_color_dark || lightenHexColor(colorPrimary); const token = (0, import_react4.useMemo)(() => { const _token = { ...DEFAULT_THEME_CONFIG.token || {}, ...tokenOverrides || {} }; if (colorPrimary) { _token.colorPrimary = mode === "light" ? colorPrimary : colorPrimaryDark; } return _token; }, [tokenOverrides, colorPrimary, colorPrimaryDark, mode]); const themeConfig = (0, import_react4.useMemo)( () => ({ ...DEFAULT_THEME_CONFIG, token, ...overridesRest || {} }), [token, overridesRest] ); const customTheme = (0, import_react4.useMemo)(() => { const { darkAlgorithm, defaultAlgorithm } = import_antd2.theme; const algorithm = mode === "light" ? defaultAlgorithm : darkAlgorithm; const customTheme2 = { ...themeConfig, cssVar: true, algorithm, components: { Card: { headerBg: mode === "dark" ? "#1F1F1F" : "#FAFAFA" } } }; return customTheme2; }, [mode, themeConfig]); return customTheme; }; // src/hooks/use-account-select/use-account-select.ts var import_antd3 = require("@refinedev/antd"); var useAccountSelect = (params) => { const { filters } = params || {}; return (0, import_antd3.useSelect)({ resource: "accounts", optionLabel: "name", optionValue: "id", filters, onSearch: (value) => [ { field: "search", operator: "eq", value } ] }); }; // src/hooks/use-phone-input/use-phone-input.ts var import_react5 = require("react"); var usePhoneinput = () => { const validator = (0, import_react5.useCallback)( (_, value) => { if (value?.valid?.(true)) { return Promise.resolve(); } return Promise.reject("Invalid phone number"); }, [] ); const fieldProps = { rules: [ { validator } ], enableSearch: true, enableArrow: true }; const parsePhoneNumber = (0, import_react5.useCallback)((value) => { if (!value?.valid?.(true)) return ""; const fullPhoneNumber = `+${value?.countryCode || ""}${value?.areaCode || ""}${value?.phoneNumber || ""}`; return fullPhoneNumber; }, []); return { fieldProps, parsePhoneNumber }; }; // src/hooks/use-user-select/use-user-select.ts var import_antd4 = require("@refinedev/antd"); var useUserSelect = (params) => { const { filters } = params || {}; return (0, import_antd4.useSelect)({ resource: "users", optionLabel: "full_name", optionValue: "id", filters, onSearch: (value) => [ { field: "search", operator: "eq", value } ] }); }; // src/components/select-option-with-avatar/select-option-with-avatar.tsx var import_antd7 = require("antd"); // src/components/custom-avatar/custom-avatar.tsx var import_react6 = require("react"); var import_antd5 = require("antd"); var import_jsx_runtime2 = require("react/jsx-runtime"); var getRandomColorFromString = (text) => { const colors = [ "#ff9c6e", "#ff7875", "#ffc069", "#ffd666", "#fadb14", "#95de64", "#5cdbd3", "#69c0ff", "#85a5ff", "#b37feb", "#ff85c0" ]; let hash = 0; for (let i = 0; i < text.length; i++) { hash = text.charCodeAt(i) + ((hash << 5) - hash); hash = hash & hash; } hash = (hash % colors.length + colors.length) % colors.length; return colors[hash]; }; var getNameInitials = (name, count = 2) => { const initials = name.split(" ").map((n) => n[0]).join(""); const filtered = initials.replace(/[^a-zA-Z]/g, ""); return filtered.slice(0, count).toUpperCase(); }; var CustomAvatarComponent = ({ name, style, ...rest }) => { return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)( import_antd5.Avatar, { alt: name, size: "small", style: { backgroundColor: rest?.src ? "transparent" : getRandomColorFromString(name || ""), display: "flex", alignItems: "center", border: "none", ...style }, ...rest, children: getNameInitials(name || "") } ); }; var CustomAvatar = (0, import_react6.memo)( CustomAvatarComponent, (prevProps, nextProps) => { return prevProps.name === nextProps.name && prevProps.src === nextProps.src; } ); // src/components/text/text.tsx var import_antd6 = require("antd"); // src/components/text/sizes.ts var sizes = { xs: { fontSize: 12, lineHeight: 20 / 12 }, sm: { fontSize: 14, lineHeight: 22 / 14 }, md: { fontSize: 16, lineHeight: 24 / 16 }, lg: { fontSize: 20, lineHeight: 28 / 20 }, xl: { fontSize: 24, lineHeight: 32 / 24 }, xxl: { fontSize: 30, lineHeight: 38 / 30 }, xxxl: { fontSize: 38, lineHeight: 46 / 38 }, huge: { fontSize: 46, lineHeight: 54 / 46 }, xhuge: { fontSize: 56, lineHeight: 64 / 56 }, xxhuge: { fontSize: 68, lineHeight: 76 / 68 } }; // src/components/text/text.tsx var import_jsx_runtime3 = require("react/jsx-runtime"); var Text = ({ size = "sm", children, ...rest }) => { return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)( import_antd6.ConfigProvider, { theme: { token: { ...sizes[size] } }, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_antd6.Typography.Text, { ...rest, children }) } ); }; // src/components/select-option-with-avatar/select-option-with-avatar.tsx var import_jsx_runtime4 = require("react/jsx-runtime"); var SelectOptionWithAvatar = ({ avatarUrl, name, shape }) => { return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_antd7.Space, { children: [ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CustomAvatar, { shape, name, src: avatarUrl }), /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { children: name }) ] }); }; // src/components/account-dropdown/account-dropdown.tsx var import_jsx_runtime5 = require("react/jsx-runtime"); var __AccountSelect = ({ width, ...props }) => { const { selectProps: accountSelectProps, query: accountQuery } = useAccountSelect(); return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)( import_antd8.Select, { ...props, ...accountSelectProps, filterSort: void 0, allowClear: true, options: accountQuery?.data?.data?.map(({ id, name, logo }) => ({ value: id, label: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(SelectOptionWithAvatar, { name, avatarUrl: logo }) })), placeholder: "Please select account", style: { width: width || "100%" } } ); }; var AccountDropdown = ({ width, ...props }) => { const { data: canListAccount } = (0, import_core2.useCan)({ resource: "accounts", action: "list" }); if (!canListAccount?.can) { return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, {}); } return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(__AccountSelect, { ...props, width }); }; // src/components/avatar-group/avatar-group.tsx var import_antd9 = require("antd"); var import_jsx_runtime6 = require("react/jsx-runtime"); var AvatarGroup = ({ avatars, size, overlap, maxCount = 3, gap = "8px", containerStyle, avatarStyle }) => { const visibleAvatars = avatars.slice(0, maxCount); const remainingAvatars = avatars.slice(maxCount); const hasRemainingAvatars = remainingAvatars.length > 0; const shouldOverlap = overlap && avatars.length > 3; const getImageSize = (size2) => { if (typeof size2 === "number") { return shouldOverlap ? `${size2 + 4}px` : `${size2}px`; } switch (size2) { case "large": return shouldOverlap ? "44px" : "40px"; case "small": return shouldOverlap ? "28px" : "24px"; default: return shouldOverlap ? "36px" : "32px"; } }; return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)( "div", { style: { display: "flex", alignItems: "center", justifyContent: "flex-start", gap: shouldOverlap ? "0" : gap, ...containerStyle }, children: [ visibleAvatars.map((avatar, index) => { const transform = shouldOverlap ? `translateX(-${index * 8}px)` : void 0; return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_antd9.Tooltip, { title: avatar.name, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)( CustomAvatar, { style: { cursor: "pointer", transform, zIndex: index, border: shouldOverlap ? "2px solid #fff" : "none", width: getImageSize(size), height: getImageSize(size), ...avatarStyle }, name: avatar?.name, src: avatar?.src, size } ) }, index); }), hasRemainingAvatars && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)( import_antd9.Tooltip, { destroyTooltipOnHide: true, title: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_antd9.Space, { direction: "vertical", children: remainingAvatars.map((avatar, index) => { return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_antd9.Space, { children: [ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)( CustomAvatar, { name: avatar.name, src: avatar.src, size: "small" } ), /* @__PURE__ */ (0, import_jsx_runtime6.jsx)( Text, { style: { color: "#fff" }, children: avatar.name }, avatar.name ) ] }, index); }) }), children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)( Text, { className: "tertiary", style: { userSelect: "none", cursor: "pointer", fontSize: "10px", lineHeight: "22px", letterSpacing: "0.5px", fontWeight: 600, display: "flex", alignItems: "center", justifyContent: "center", borderRadius: "50%", width: getImageSize(size), height: getImageSize(size), transform: shouldOverlap ? `translateX(-${visibleAvatars.length * 8}px)` : void 0, zIndex: shouldOverlap ? visibleAvatars.length : 1, backgroundColor: "#D9D9D9", border: overlap ? "2px solid #fff" : "none" }, children: [ "+", remainingAvatars.length ] } ) } ) ] } ); }; // src/components/back-button/back-button.tsx var import_icons2 = require("@ant-design/icons"); var import_antd10 = require("antd"); var import_jsx_runtime7 = require("react/jsx-runtime"); var BackButton = ({ onClick, label }) => { return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_antd10.Space, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)( import_antd10.Button, { variant: "link", onClick, icon: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_icons2.LeftOutlined, {}), color: "primary", style: { fontSize: 17, fontWeight: "bold" }, children: label } ) }); }; // src/components/bootstrap/bootstrap.tsx var import_antd13 = require("@refinedev/antd"); var import_refine_core3 = require("@ucheeddev/refine-core"); var import_antd14 = require("antd"); // src/providers/config/config-provider.tsx var import_react7 = require("react"); var import_antd11 = require("antd"); var import_antd_style = require("antd-style"); var import_jsx_runtime8 = require("react/jsx-runtime"); var ConfigProviderContext = (0, import_react7.createContext)( {} ); var ConfigProvider2 = ({ children, theme: themeFromProps, forceLightTheme, ...rest }) => { const colorModeFromLocalStorage = localStorage.getItem("colorMode"); const isSystemPreferenceDark = window.matchMedia( "(prefers-color-scheme: dark)" ).matches; const systemPreference = isSystemPreferenceDark ? "dark" : "light"; const [mode, setMode] = (0, import_react7.useState)( forceLightTheme ? "light" : colorModeFromLocalStorage || systemPreference ); const themeConfig = useThemeConfig({ overrides: themeFromProps, mode }); const toggleMode = (0, import_react7.useCallback)(() => { if (forceLightTheme) { setMode("light"); return; } setMode((prev) => prev === "light" ? "dark" : "light"); }, [forceLightTheme]); (0, import_react7.useEffect)(() => { window.localStorage.setItem("colorMode", mode); }, [mode]); return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)( ConfigProviderContext.Provider, { value: { toggleMode, mode, isDarkMode: mode === "dark" }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_antd11.ConfigProvider, { theme: themeConfig, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_antd_style.ThemeProvider, { theme: themeConfig, appearance: mode, ...rest, children }) }) } ); }; var useConfigProvider = () => { const context = (0, import_react7.useContext)(ConfigProviderContext); if (!context) { throw new Error("useConfigProvider must be used within a ConfigProvider"); } return context; }; // src/components/full-screen-loading/full-screen-loading.tsx var import_antd12 = require("antd"); var import_jsx_runtime9 = require("react/jsx-runtime"); var FullScreenLoading = () => { return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)( import_antd12.Spin, { size: "large", style: { height: "100vh", width: "100%", display: "flex", alignItems: "center", justifyContent: "center" } } ); }; // src/components/bootstrap/bootstrap.tsx var import_jsx_runtime10 = require("react/jsx-runtime"); var Bootstrap = ({ theme: theme6, forceLightTheme, configProviderProps, children, notificationProvider: notificationProviderFromProps, ...rest }) => { return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)( ConfigProvider2, { theme: theme6, forceLightTheme, ...configProviderProps || {}, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_antd14.App, { children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)( import_refine_core3.Bootstrap, { ...rest, notificationProvider: notificationProviderFromProps || import_antd13.useNotificationProvider, Loading: FullScreenLoading, Error: ({ error }) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_antd14.Alert, { type: "error", message: error, showIcon: true }), children } ) }) } ); }; // src/components/circle-icon-btn-action/circle-icon-btn-action.tsx var import_antd15 = require("antd"); var import_jsx_runtime11 = require("react/jsx-runtime"); var CircleIconButtonAction = ({ icon, label, onClick }) => { return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_antd15.Flex, { vertical: true, align: "center", children: [ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)( import_antd15.Button, { shape: "circle", type: "default", size: "large", icon, onClick } ), /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Text, { type: "secondary", style: { marginTop: 4, fontSize: 12 }, children: label }) ] }); }; // src/components/current-user/current-user.tsx var import_core3 = require("@refinedev/core"); var import_icons3 = require("@ant-design/icons"); var import_antd16 = require("antd"); var import_jsx_runtime12 = require("react/jsx-runtime"); var CurrentUser = ({ beforeLogout }) => { const { data: user } = (0, import_core3.useGetIdentity)(); const { mutate: logout } = (0, import_core3.useLogout)(); const content = /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)( "div", { style: { display: "flex", flexDirection: "column" }, children: [ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)( "div", { style: { padding: "12px 20px" }, children: [ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_antd16.Space, { size: 8, children: [ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_icons3.UserOutlined, { className: "md colorPrimary" }), /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { strong: true, children: user?.display_name || "" }) ] }) }), /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { style: { paddingTop: 7 }, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_antd16.Space, { size: 12, children: [ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_icons3.MailOutlined, { className: "md colorPrimary" }), /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Text, { style: { fontSize: 14, color: "#000" }, children: user?.email || "" }) ] }) }) ] } ), /* @__PURE__ */ (0, import_jsx_runtime12.jsx)( "div", { style: { borderTop: "1px solid #d9d9d9", padding: "4px", display: "flex", flexDirection: "column", gap: "4px" }, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)( "div", { style: { padding: "8px", display: "flex", flexDirection: "column", gap: "4px" }, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)( "div", { style: { display: "flex", flexDirection: "column", gap: "4px" }, children: [ beforeLogout, /* @__PURE__ */ (0, import_jsx_runtime12.jsx)( import_antd16.Button, { style: { textAlign: "left" }, icon: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_icons3.LogoutOutlined, {}), type: "text", danger: true, block: true, onClick: () => logout(), children: "Logout" } ) ] } ) } ) } ) ] } ); return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)( import_antd16.Popover, { placement: "bottomRight", content, trigger: "click", overlayInnerStyle: { padding: 0 }, overlayStyle: { zIndex: 999 }, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)( CustomAvatar, { name: user?.display_name || "", src: user?.avatar_url || "", size: "default", style: { cursor: "pointer" } } ) } ); }; // src/components/custom-date-picker/custom-date-picker.tsx var import_react8 = require("react"); var import_antd17 = require("antd"); var import_dayjs = __toESM(require("dayjs")); var import_jsx_runtime13 = require("react/jsx-runtime"); var CustomDatePicker = ({ value, onChange, onOk, format, needConfirm, showTime, showNow, allowClear, style }) => { showNow = showNow === void 0 ? false : true; allowClear = allowClear === void 0 ? false : true; needConfirm = needConfirm === void 0 ? true : false; showTime = showTime === void 0 ? false : true; format = format === void 0 ? showTime ? "DD/MM/YYYY hh:mm a" : "DD/MM/YYYY" : format; const [_value, _setValue] = (0, import_react8.useState)(void 0); (0, import_react8.useEffect)(() => { if (!value) { _setValue(void 0); return; } _setValue((0, import_dayjs.default)(value)); }, [value]); return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)( import_antd17.DatePicker, { value: _value, onChange, onOk, allowClear, needConfirm, showNow, showTime, format, style } ); }; // src/components/custom-tabs/custom-tabs.tsx var import_antd18 = require("antd"); var import_jsx_runtime14 = require("react/jsx-runtime"); var CustomTabs = ({ items, defaultActiveKey = "1", onChange, style }) => { return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)( import_antd18.Tabs, { defaultActiveKey, items, onChange, style } ); }; // src/components/custom-time-picker/custom-time-picker.tsx var import_react9 = require("react"); var import_antd19 = require("antd"); var import_dayjs2 = __toESM(require("dayjs")); var import_jsx_runtime15 = require("react/jsx-runtime"); var CustomTimePicker = ({ value, onChange, onOk, format, needConfirm, allowClear, style }) => { needConfirm = needConfirm === void 0 ? true : false; allowClear = allowClear === void 0 ? false : true; format = format === void 0 ? "hh:mm a" : format; const [_value, _setValue] = (0, import_react9.useState)(void 0); (0, import_react9.useEffect)(() => { if (!value) { _setValue(void 0); return; } _setValue((0, import_dayjs2.default)(value)); }, [value]); return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)( import_antd19.DatePicker.TimePicker, { value: _value, onChange, onOk, allowClear, needConfirm, format, style } ); }; // src/components/email-link/email-link.tsx var import_antd20 = require("antd"); var import_jsx_runtime16 = require("react/jsx-runtime"); var { Link } = import_antd20.Typography; var EmailLink = ({ email, style }) => { return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Link, { href: `mailto:${email}`, target: "_blank", style, children: email }); }; // src/components/field-form-title/field-form-title.tsx var import_antd21 = require("antd"); var import_jsx_runtime17 = require("react/jsx-runtime"); var FieldFormTitle = ({ title, Icon: Icon2, iconProps, titleStyle, ...props }) => { return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_antd21.Space, { size: 11, ...props, children: [ Icon2 && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Icon2, { className: "md colorPrimary", ...iconProps }), /* @__PURE__ */ (0, import_jsx_runtime17.jsx)( import_antd21.Typography.Text, { style: { fontSize: "15px", color: "darkslategray", ...titleStyle }, children: title } ) ] }); }; // src/components/filter-dropdown/filter-dropdown.tsx var import_react10 = __toESM(require("react")); var import_core4 = require("@refinedev/core"); var import_icons4 = require("@ant-design/icons"); var import_antd22 = require("antd"); var import_dayjs3 = __toESM(require("dayjs")); var import_jsx_runtime18 = require("react/jsx-runtime"); var FilterDropdown = (props) => { const { setSelectedKeys, confirm, clearFilters, mapValue = (value) => value, selectedKeys, children } = props; const translate = (0, import_core4.useTranslate)(); const clearFilter = (0, import_react10.useCallback)(() => { if (clearFilters) { clearFilters(); confirm?.(); } }, [clearFilters, confirm]); const onFilter = (0, import_react10.useCallback)(() => { let keys; if (typeof selectedKeys === "number") { keys = `${selectedKeys}`; } else if (import_dayjs3.default.isDayjs(selectedKeys)) { keys = [selectedKeys.toISOString()]; } else { keys = selectedKeys; } setSelectedKeys(keys); confirm?.(); }, [selectedKeys, setSelectedKeys, confirm]); const onChange = (0, import_react10.useCallback)( (e) => { if (typeof e === "object") { if (Array.isArray(e)) { const mappedValue3 = mapValue(e, "onChange"); setSelectedKeys(mappedValue3); confirm?.(); return; } const changeEvent = !e || !e.target || import_dayjs3.default.isDayjs(e) ? { target: { value: e } } : e; const { target } = changeEvent; const mappedValue2 = mapValue(target.value, "onChange"); setSelectedKeys(mappedValue2); return; } const mappedValue = mapValue(e, "onChange"); if (typeof mappedValue === "number") { setSelectedKeys(`${mappedValue}`); } else { setSelectedKeys(mappedValue); } confirm?.(); }, [confirm, mapValue, setSelectedKeys] ); const childrenWithProps = (0, import_react10.useMemo)(() => { return import_react10.default.Children.map(children, (child) => { if (import_react10.default.isValidElement(child)) { return import_react10.default.cloneElement(child, { onChange, value: mapValue(selectedKeys, "value") }); } return child; }); }, [children, mapValue, onChange, selectedKeys]); return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)( "div", { style: { padding: 10, display: "flex", flexDirection: "column", alignItems: "flex-end" }, children: [ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { style: { marginBottom: 12 }, children: childrenWithProps }), /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_antd22.Space, { children: [ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)( import_antd22.Button, { style: { backgroundColor: "#ffff" }, danger: true, size: "small", onClick: () => clearFilter(), children: [ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_icons4.ClearOutlined, {}), translate("buttons.clear", "Clear") ] } ), /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_antd22.Button, { type: "primary", size: "small", onClick: () => onFilter(), children: [ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_icons4.FilterOutlined, {}), " ", translate("buttons.filter", "Filter") ] }) ] }) ] } ); }; // src/components/form-loading-skeleton/form-loading-skeleton.tsx var import_antd23 = require("antd"); var import_jsx_runtime19 = require("react/jsx-runtime"); var FormLoadingSkeleton = () => { return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_jsx_runtime19.Fragment, { children: [...Array(4)].map((_, rowIndex) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_antd23.Row, { gutter: 24, style: { marginBottom: 16 }, children: [...Array(2)].map((_2, colIndex) => /* @__PURE__ */ (0, import_jsx_runtime19.jsx)( import_antd23.Col, { span: 12, style: { display: "flex", flexDirection: "column", padding: 4 }, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_antd23.Skeleton.Input, { active: true, style: { width: "100%" }, size: "small" }) }, colIndex )) }, rowIndex)) }); }; // src/components/formatted-number-field/formatted-number-field.tsx var import_antd24 = require("@refinedev/antd"); var import_jsx_runtime20 = require("react/jsx-runtime"); var FormattedNumberField = ({ value, currency = "USD", ...rest }) => { return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)( import_antd24.NumberField, { ...rest, value, options: { style: "currency", currency }, prefix: "2" } ); }; // src/components/full-width-layout/full-width-layout.tsx var import_antd27 = require("@refinedev/antd"); // src/components/header-with-menu/header-with-menu.tsx var import_core6 = require("@refinedev/core"); var import_antd26 = require("antd"); var import_classnames = __toESM(require("classnames")); // src/components/icons/icon-invoicer.tsx var import_jsx_runtime21 = require("react/jsx-runtime"); var IconInvoicerLogo = (props) => { const { mode } = useConfigProvider(); const isDarkMode = mode === "dark"; return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)( "svg", { xmlns: "http://www.w3.org/2000/svg", width: 24, height: 20, viewBox: "0 0 24 20", fill: "none", ...props, children: [ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("title", { children: "Invoicer" }), /* @__PURE__ */ (0, import_jsx_runtime21.jsx)( "path", { fill: isDarkMode ? "#3E2069" : "#EFDBFF", d: "m0 0 24 4v12L0 20V0Z" } ), /* @__PURE__ */ (0, import_jsx_runtime21.jsx)( "path", { fill: isDarkMode ? "#CDA8F0" : "#531DAB", d: "M4.5 14.015 7.54 20 24 0 4.5 14.015Z" } ), /* @__PURE__ */ (0, import_jsx_runtime21.jsx)( "path", { fill: isDarkMode ? "#EBD7FA" : "#22075E", d: "M7.54 20v-4l2.681 1.267L7.541 20Z" } ), /* @__PURE__ */ (0, import_jsx_runtime21.jsx)( "path", { fill: isDarkMode ? "#AB7AE0" : "#9254DE", d: "m0 11 4.5 3.015L24 0 7.54 16 16 20l8-20L0 11Z" } ) ] } ); }; // src/components/icons/icon-moon.tsx var import_jsx_runtime22 = require("react/jsx-runtime"); var IconMoon = () => /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)( "svg", { xmlns: "http://www.w3.org/2000/svg", className: "icon icon-tabler icon-tabler-moon-stars", width: 20, height: 20, viewBox: "0 0 24 24", strokeWidth: 2, stroke: "currentColor", fill: "none", strokeLinecap: "round", strokeLinejoin: "round", children: [ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("path", { stroke: "none", d: "M0 0h24v24H0z", fill: "none" }), /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("path", { d: "M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z" }), /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("path", { d: "M17 4a2 2 0 0 0 2 2a2 2 0 0 0 -2 2a2 2 0 0 0 -2 -2a2 2 0 0 0 2 -2" }), /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("path", { d: "M19 11h2m-1 -1v2" }) ] } ); // src/components/icons/icon-sun.tsx var import_jsx_runtime23 = require("react/jsx-runtime"); var IconSun = () => /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)( "svg", { xmlns: "http://www.w3.org/2000/svg", className: "icon icon-tabler icon-tabler-sun", width: 20, height: 20, viewBox: "0 0 24 24", strokeWidth: "2", stroke: "currentColor", fill: "none", strokeLinecap: "round", strokeLinejoin: "round", children: [ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("path", { stroke: "none", d: "M0 0h24v24H0z", fill: "none" }), /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("circle", { cx: 12, cy: 12, r: 4 }), /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("path", { d: "M3 12h1m8 -9v1m8 8h1m-9 8v1m-6.4 -15.4l.7 .7m12.1 -.7l-.7 .7m0 11.4l.7 .7m-12.1 -.7l-.7 .7" }) ] } ); // src/components/logo/logo.tsx var import_jsx_runtime24 = require("react/jsx-runtime"); var WIDTH = 120; var HEIGHT = 120; var Logo = ({ height, width, src, alt }) => { height = height || HEIGHT; width = width || WIDTH; if (!src) { return; } return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)( "img", { alt, src, width, height, style: { maxWidth: "100%", maxHeight: "100%" } } ); }; // src/components/sider/menu-items.tsx var import_core5 = require("@refinedev/core"); var import_icons5 = require("@ant-design/icons"); var import_antd25 = require("antd"); var import_jsx_runtime25 = require("react/jsx-runtime"); var renderMenuItems = ({ tree, selectedKey, Link: Link5, siderCollapsed }) => { return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_jsx_runtime25.Fragment, { children: tree.map((item) => { const { icon, label, route, key, name, children, parentName, meta, options } = item; if (children.length > 0) { return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)( import_core5.CanAccess, { resource: name.toLowerCase(), action: "list", params: { resource: item }, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)( import_antd25.Menu.SubMenu, { icon: icon ?? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_icons5.UnorderedListOutlined, {}), title: label, children: renderMenuItems({ tree: children, selectedKey, Link: Link5, siderCollapsed }) } ) }, key ); } const isSelected = key === selectedKey; const isRoute = !((0, import_core5.pickNotDeprecated)(meta?.parent, options?.parent, parentName) !== void 0 && children.length === 0); return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)( import_core5.CanAccess, { resource: name.toLowerCase(), action: "list", params: { resource: item }, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)( import_antd25.Menu.Item, { icon: icon ?? (isRoute && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_icons5.UnorderedListOutlined, {})), children: [ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Link5, { to: route ?? "", children: label }), !siderCollapsed && isSelected && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "ant-menu-tree-arrow" }) ] }, key ) }, key ); }) }); }; // src/components/header-with-menu/styled.tsx var import_antd_style2 = require("antd-style"); var useStyles = (0, import_antd_style2.createStyles)(({ css, token, isDarkMode, responsive }) => { return { headerContainer: { backgroundColor: token.colorBgElevated, padding: "0 16px", minHeight: "48px", height: "max-content" }, flexContainer: { width: "100%", maxWidth: "1440px", margin: "0 auto", height: "100%" }, headerTitleRefine: { fontFamily: "Bricolage Grotesque, sans-serif", color: isDarkMode ? token["purple-10"] : token["purple-8"] }, headerTitleInvoicer: { fontFamily: "Bricolage Grotesque, sans-serif", color: isDarkMode ? token["purple-10"] : token["purple-8"], fontWeight: 700 }, tabs: css` margin-left: auto; margin-right: auto; width: 600px; ${responsive.mobile} { width: 320px; } `, inputSuffix: { width: "20px", height: "20px", display: "flex", alignItems: "center", justifyContent: "center", backgroundColor: token.colorBgTextHover, color: token.colorTextDisabled, borderRadius: "4px", fontSize: "12px" }, inputPrefix: { color: token.colorTextPlaceholder, marginRight: "4px" }, languageSwitchText: { color: token.colorTextSecondary }, languageSwitchIcon: { color: token.colorTextTertiary, width: "10px" }, themeSwitch: { display: "flex", alignItems: "center", justifyContent: "center", height: "32px", width: "32px", borderRadius: "50%", cursor: "pointer", flexShrink: 0, backgroundColor: isDarkMode ? token.colorBgLayout : token.colorBgTextHover }, rightSlot: { marginLeft: "auto", "@media (max-width: 1000px)": { padding: "16px" } } }; }); // src/components/header-with-menu/header-with-menu.tsx var import_jsx_runtime26 = require("react/jsx-runtime"); var HeaderWithMenu = ({ Search, logo, logoWidth, logoHeight, hideThemeButton, beforeLogout, disabledOverflow, overflowedIndicator, style, className }) => { const { menuItems, selectedKey, defaultOpenKeys } = (0, import_core6.useMenu)(); const { styles: styles2 } = useStyles(); const { isDarkMode, toggleMode } = useConfigProvider(); return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)( import_antd26.Layout.Header, { className: (0, import_classnames.default)("print-hidden", styles2.headerContainer, className), style, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)( import_antd26.Flex, { align: "center", justify: "space-between", wrap: "wrap", className: styles2.flexContainer, children: [ /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(import_antd26.Flex, { align: "center", wrap: "wrap", children: [ logo ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)( import_core6.Link, { go: { to: "/"