@martinsura/ui 0.1.2 → 0.1.3
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.cjs +265 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.cts +61 -3
- package/dist/index.d.ts +61 -3
- package/dist/index.js +263 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { cva } from 'class-variance-authority';
|
|
2
2
|
import { twMerge } from 'tailwind-merge';
|
|
3
|
-
import { IconDownload, IconPaperclip, IconFileSpreadsheet, IconX, IconTrashX, IconPlus, IconPencil, IconDotsVertical,
|
|
3
|
+
import { IconEyeOff, IconEye, IconDownload, IconPaperclip, IconFileSpreadsheet, IconX, IconTrashX, IconPlus, IconPencil, IconDotsVertical, IconCheck, IconDroplet, IconDatabaseOff, IconChevronUp, IconChevronDown, IconSelector, IconCalendar, IconUsers, IconInfoCircle, IconAlertTriangle, IconCircleX, IconBold, IconItalic, IconUnderline, IconList, IconListNumbers, IconLink, IconUnlink, IconClearFormatting, IconUpload, IconAlertCircle, IconTrash, IconLoader2, IconChevronLeft, IconChevronRight, IconSearch } from '@tabler/icons-react';
|
|
4
4
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
5
|
-
import { createContext,
|
|
5
|
+
import { createContext, forwardRef, useState, useContext, useRef, useLayoutEffect, useEffect, useMemo, useCallback, useId } from 'react';
|
|
6
6
|
import { createPortal } from 'react-dom';
|
|
7
7
|
import dayjs from 'dayjs';
|
|
8
8
|
|
|
@@ -411,12 +411,12 @@ var ErrorContext = createContext({
|
|
|
411
411
|
var ErrorProvider = ({ resolveInputError, resolveServerError, children }) => /* @__PURE__ */ jsx(ErrorContext.Provider, { value: { resolveInputError, resolveServerError }, children });
|
|
412
412
|
var useErrorResolver = () => useContext(ErrorContext).resolveInputError;
|
|
413
413
|
var useServerError = () => useContext(ErrorContext).resolveServerError;
|
|
414
|
-
var TextInput = ({
|
|
414
|
+
var TextInput = forwardRef(({
|
|
415
415
|
size = "middle",
|
|
416
416
|
password = false,
|
|
417
417
|
newPassword = false,
|
|
418
418
|
...props
|
|
419
|
-
}) => {
|
|
419
|
+
}, ref) => {
|
|
420
420
|
const [showPassword, setShowPassword] = useState(false);
|
|
421
421
|
const resolveError = useErrorResolver();
|
|
422
422
|
const resolvedErrors = props.errorName ? resolveError(props.errorName) : [];
|
|
@@ -437,6 +437,7 @@ var TextInput = ({
|
|
|
437
437
|
/* @__PURE__ */ jsx(
|
|
438
438
|
"input",
|
|
439
439
|
{
|
|
440
|
+
ref,
|
|
440
441
|
type: inputType,
|
|
441
442
|
autoComplete: newPassword ? "new-password" : void 0,
|
|
442
443
|
placeholder: props.placeholder,
|
|
@@ -470,7 +471,8 @@ var TextInput = ({
|
|
|
470
471
|
] }),
|
|
471
472
|
errorDisplay && /* @__PURE__ */ jsx(InputError, { error: String(errorDisplay), className: props.classNames?.error })
|
|
472
473
|
] });
|
|
473
|
-
};
|
|
474
|
+
});
|
|
475
|
+
TextInput.displayName = "TextInput";
|
|
474
476
|
var numberInputClass = inputBaseClass + " [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none";
|
|
475
477
|
var NumberInput = ({
|
|
476
478
|
size = "middle",
|
|
@@ -645,7 +647,7 @@ var SwitchInput = ({
|
|
|
645
647
|
|
|
646
648
|
// src/floating/layerStack.ts
|
|
647
649
|
var FLOATING_ROOT_SELECTOR = "[data-ui-floating-root]";
|
|
648
|
-
var
|
|
650
|
+
var LAYER_ROOT_SELECTOR = "[data-ui-layer-root]";
|
|
649
651
|
function getTopmostElement(selector) {
|
|
650
652
|
const elements = document.querySelectorAll(selector);
|
|
651
653
|
return elements.length > 0 ? elements[elements.length - 1] : null;
|
|
@@ -656,8 +658,8 @@ function hasFloatingRootOpen() {
|
|
|
656
658
|
function isTopmostFloatingRoot(element) {
|
|
657
659
|
return element !== null && getTopmostElement(FLOATING_ROOT_SELECTOR) === element;
|
|
658
660
|
}
|
|
659
|
-
function
|
|
660
|
-
return element !== null && getTopmostElement(
|
|
661
|
+
function isTopmostLayerRoot(element) {
|
|
662
|
+
return element !== null && getTopmostElement(LAYER_ROOT_SELECTOR) === element;
|
|
661
663
|
}
|
|
662
664
|
function isTargetInsideFloatingRoot(target) {
|
|
663
665
|
return target instanceof Element && target.closest(FLOATING_ROOT_SELECTOR) !== null;
|
|
@@ -2888,7 +2890,7 @@ var Drawer = ({ placement = "top", ...props }) => {
|
|
|
2888
2890
|
if (isTargetInsideFloatingRoot(e.target)) {
|
|
2889
2891
|
return;
|
|
2890
2892
|
}
|
|
2891
|
-
if (!
|
|
2893
|
+
if (!isTopmostLayerRoot(panelRef.current)) {
|
|
2892
2894
|
return;
|
|
2893
2895
|
}
|
|
2894
2896
|
props.onClose(false);
|
|
@@ -2929,7 +2931,7 @@ var Drawer = ({ placement = "top", ...props }) => {
|
|
|
2929
2931
|
"div",
|
|
2930
2932
|
{
|
|
2931
2933
|
ref: panelRef,
|
|
2932
|
-
"data-ui-
|
|
2934
|
+
"data-ui-layer-root": "",
|
|
2933
2935
|
className: twMerge(
|
|
2934
2936
|
panelBase[placement],
|
|
2935
2937
|
"bg-white shadow-xl transition-transform duration-220 ease-out",
|
|
@@ -3041,6 +3043,256 @@ var DrawerContent = ({ loading = false, children }) => {
|
|
|
3041
3043
|
}
|
|
3042
3044
|
return /* @__PURE__ */ jsx(Fragment, { children });
|
|
3043
3045
|
};
|
|
3046
|
+
var ModalContext = createContext(null);
|
|
3047
|
+
function useModal() {
|
|
3048
|
+
const ctx = useContext(ModalContext);
|
|
3049
|
+
if (!ctx) {
|
|
3050
|
+
throw new Error("useModal must be used inside Modal");
|
|
3051
|
+
}
|
|
3052
|
+
return ctx;
|
|
3053
|
+
}
|
|
3054
|
+
var TRANSITION_MS2 = 220;
|
|
3055
|
+
var sizeClass = {
|
|
3056
|
+
small: "w-full max-w-lg",
|
|
3057
|
+
middle: "w-full max-w-3xl",
|
|
3058
|
+
large: "w-full max-w-5xl",
|
|
3059
|
+
auto: "w-auto"
|
|
3060
|
+
};
|
|
3061
|
+
var Modal = ({
|
|
3062
|
+
placement = "center",
|
|
3063
|
+
size = "middle",
|
|
3064
|
+
width,
|
|
3065
|
+
maxWidth,
|
|
3066
|
+
closeOnEscape = true,
|
|
3067
|
+
closeOnOverlayClick = true,
|
|
3068
|
+
showCloseButton = true,
|
|
3069
|
+
hideHeader = false,
|
|
3070
|
+
destroyOnClose = true,
|
|
3071
|
+
preventClose = false,
|
|
3072
|
+
beforeClose,
|
|
3073
|
+
initialFocusRef,
|
|
3074
|
+
...props
|
|
3075
|
+
}) => {
|
|
3076
|
+
const [rendered, setRendered] = useState(props.isOpen);
|
|
3077
|
+
const [visible, setVisible] = useState(false);
|
|
3078
|
+
const [title, setTitle] = useState("");
|
|
3079
|
+
const [footer, setFooter] = useState(null);
|
|
3080
|
+
const [loading, setLoading] = useState(false);
|
|
3081
|
+
const frameRef = useRef(0);
|
|
3082
|
+
const panelRef = useRef(null);
|
|
3083
|
+
useEffect(() => {
|
|
3084
|
+
if (props.isOpen) {
|
|
3085
|
+
setRendered(true);
|
|
3086
|
+
frameRef.current = requestAnimationFrame(() => {
|
|
3087
|
+
frameRef.current = requestAnimationFrame(() => setVisible(true));
|
|
3088
|
+
});
|
|
3089
|
+
} else {
|
|
3090
|
+
setVisible(false);
|
|
3091
|
+
if (!destroyOnClose) {
|
|
3092
|
+
return () => cancelAnimationFrame(frameRef.current);
|
|
3093
|
+
}
|
|
3094
|
+
const t = setTimeout(() => setRendered(false), TRANSITION_MS2);
|
|
3095
|
+
return () => clearTimeout(t);
|
|
3096
|
+
}
|
|
3097
|
+
return () => cancelAnimationFrame(frameRef.current);
|
|
3098
|
+
}, [destroyOnClose, props.isOpen]);
|
|
3099
|
+
useEffect(() => {
|
|
3100
|
+
if (!props.isOpen) {
|
|
3101
|
+
return;
|
|
3102
|
+
}
|
|
3103
|
+
const focusTarget = initialFocusRef?.current;
|
|
3104
|
+
if (!focusTarget) {
|
|
3105
|
+
return;
|
|
3106
|
+
}
|
|
3107
|
+
const timeout = window.setTimeout(() => focusTarget.focus(), TRANSITION_MS2 / 2);
|
|
3108
|
+
return () => window.clearTimeout(timeout);
|
|
3109
|
+
}, [initialFocusRef, props.isOpen]);
|
|
3110
|
+
useEffect(() => {
|
|
3111
|
+
if (!props.isOpen) {
|
|
3112
|
+
return;
|
|
3113
|
+
}
|
|
3114
|
+
const handleKeyDown = (e) => {
|
|
3115
|
+
if (!closeOnEscape || e.key !== "Escape" || e.defaultPrevented) {
|
|
3116
|
+
return;
|
|
3117
|
+
}
|
|
3118
|
+
if (hasFloatingRootOpen() || isTargetInsideFloatingRoot(e.target)) {
|
|
3119
|
+
return;
|
|
3120
|
+
}
|
|
3121
|
+
if (!isTopmostLayerRoot(panelRef.current)) {
|
|
3122
|
+
return;
|
|
3123
|
+
}
|
|
3124
|
+
void requestClose();
|
|
3125
|
+
};
|
|
3126
|
+
document.body.style.overflow = "hidden";
|
|
3127
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
3128
|
+
return () => {
|
|
3129
|
+
document.body.style.overflow = "";
|
|
3130
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
3131
|
+
};
|
|
3132
|
+
}, [closeOnEscape, props.isOpen]);
|
|
3133
|
+
if (!rendered) {
|
|
3134
|
+
return null;
|
|
3135
|
+
}
|
|
3136
|
+
const requestClose = async () => {
|
|
3137
|
+
if (preventClose) {
|
|
3138
|
+
return;
|
|
3139
|
+
}
|
|
3140
|
+
const canClose = await beforeClose?.();
|
|
3141
|
+
if (canClose === false) {
|
|
3142
|
+
return;
|
|
3143
|
+
}
|
|
3144
|
+
props.onClose(false);
|
|
3145
|
+
};
|
|
3146
|
+
const close = () => {
|
|
3147
|
+
void requestClose();
|
|
3148
|
+
};
|
|
3149
|
+
const saveAndClose = (message) => {
|
|
3150
|
+
if (message) {
|
|
3151
|
+
notification.success(message);
|
|
3152
|
+
}
|
|
3153
|
+
props.onClose(true);
|
|
3154
|
+
};
|
|
3155
|
+
const hasFooter = footer !== null;
|
|
3156
|
+
const isFullscreen = placement === "fullscreen";
|
|
3157
|
+
return createPortal(
|
|
3158
|
+
/* @__PURE__ */ jsxs(ModalContext.Provider, { value: { close, saveAndClose, setTitle, setFooter, setLoading }, children: [
|
|
3159
|
+
/* @__PURE__ */ jsx(
|
|
3160
|
+
"div",
|
|
3161
|
+
{
|
|
3162
|
+
className: twMerge(
|
|
3163
|
+
"fixed inset-0 z-1000 bg-black/40 transition-opacity duration-220",
|
|
3164
|
+
visible ? "opacity-100" : "opacity-0",
|
|
3165
|
+
!props.isOpen && "pointer-events-none",
|
|
3166
|
+
props.classNames?.overlay
|
|
3167
|
+
),
|
|
3168
|
+
onClick: () => closeOnOverlayClick && close()
|
|
3169
|
+
}
|
|
3170
|
+
),
|
|
3171
|
+
/* @__PURE__ */ jsx(
|
|
3172
|
+
"div",
|
|
3173
|
+
{
|
|
3174
|
+
className: twMerge(
|
|
3175
|
+
"fixed inset-0 z-1001 flex p-4 transition-all duration-220",
|
|
3176
|
+
isFullscreen ? "items-stretch justify-stretch p-0" : "items-center justify-center",
|
|
3177
|
+
!props.isOpen && "pointer-events-none"
|
|
3178
|
+
),
|
|
3179
|
+
children: /* @__PURE__ */ jsxs(
|
|
3180
|
+
"div",
|
|
3181
|
+
{
|
|
3182
|
+
ref: panelRef,
|
|
3183
|
+
"data-ui-layer-root": "",
|
|
3184
|
+
role: "dialog",
|
|
3185
|
+
"aria-modal": "true",
|
|
3186
|
+
"aria-hidden": !props.isOpen,
|
|
3187
|
+
style: !isFullscreen ? { width, maxWidth } : void 0,
|
|
3188
|
+
className: twMerge(
|
|
3189
|
+
"bg-white shadow-xl flex flex-col transition-all duration-220 ease-out",
|
|
3190
|
+
isFullscreen ? "h-full w-full rounded-none" : `${sizeClass[size]} max-h-[calc(100dvh-32px)] rounded-(--ui-radius-lg)`,
|
|
3191
|
+
visible ? "scale-100 opacity-100" : "scale-95 opacity-0",
|
|
3192
|
+
props.className,
|
|
3193
|
+
props.classNames?.panel
|
|
3194
|
+
),
|
|
3195
|
+
onClick: (e) => e.stopPropagation(),
|
|
3196
|
+
children: [
|
|
3197
|
+
!hideHeader && /* @__PURE__ */ jsxs(
|
|
3198
|
+
"div",
|
|
3199
|
+
{
|
|
3200
|
+
className: twMerge(
|
|
3201
|
+
"flex items-center justify-between gap-2 bg-(--ui-primary) shrink-0 rounded-t-(--ui-radius-lg)",
|
|
3202
|
+
isFullscreen && "rounded-none",
|
|
3203
|
+
drawerLayoutClasses.header,
|
|
3204
|
+
props.classNames?.header
|
|
3205
|
+
),
|
|
3206
|
+
children: [
|
|
3207
|
+
/* @__PURE__ */ jsx("span", { className: twMerge(componentTitleClasses.inverse, "truncate", props.classNames?.title), children: title }),
|
|
3208
|
+
showCloseButton && /* @__PURE__ */ jsx(
|
|
3209
|
+
"button",
|
|
3210
|
+
{
|
|
3211
|
+
type: "button",
|
|
3212
|
+
onClick: close,
|
|
3213
|
+
className: twMerge(
|
|
3214
|
+
"shrink-0 text-(--ui-primary-text)/70 hover:text-(--ui-primary-text) cursor-pointer transition-colors",
|
|
3215
|
+
props.classNames?.closeButton
|
|
3216
|
+
),
|
|
3217
|
+
children: /* @__PURE__ */ jsx(IconX, { size: 18, strokeWidth: 1.5 })
|
|
3218
|
+
}
|
|
3219
|
+
)
|
|
3220
|
+
]
|
|
3221
|
+
}
|
|
3222
|
+
),
|
|
3223
|
+
/* @__PURE__ */ jsx(
|
|
3224
|
+
"div",
|
|
3225
|
+
{
|
|
3226
|
+
className: twMerge(
|
|
3227
|
+
"overflow-y-auto flex-1",
|
|
3228
|
+
isFullscreen ? "min-h-0" : "max-h-[calc(100dvh-120px)]",
|
|
3229
|
+
drawerLayoutClasses.body,
|
|
3230
|
+
props.classNames?.body
|
|
3231
|
+
),
|
|
3232
|
+
children: loading ? /* @__PURE__ */ jsx("div", { className: twMerge("flex items-center justify-center py-16", props.classNames?.loading), children: /* @__PURE__ */ jsx(Spinner, { size: "large", color: "primary" }) }) : props.children
|
|
3233
|
+
}
|
|
3234
|
+
),
|
|
3235
|
+
hasFooter && /* @__PURE__ */ jsx(
|
|
3236
|
+
"div",
|
|
3237
|
+
{
|
|
3238
|
+
className: twMerge(
|
|
3239
|
+
"border-t border-(--ui-border) shrink-0 bg-white",
|
|
3240
|
+
isFullscreen ? "rounded-none" : "rounded-b-(--ui-radius-lg)",
|
|
3241
|
+
drawerLayoutClasses.footer,
|
|
3242
|
+
props.classNames?.footer
|
|
3243
|
+
),
|
|
3244
|
+
children: footer
|
|
3245
|
+
}
|
|
3246
|
+
)
|
|
3247
|
+
]
|
|
3248
|
+
}
|
|
3249
|
+
)
|
|
3250
|
+
}
|
|
3251
|
+
)
|
|
3252
|
+
] }),
|
|
3253
|
+
document.body
|
|
3254
|
+
);
|
|
3255
|
+
};
|
|
3256
|
+
var ModalTitle = ({ children }) => {
|
|
3257
|
+
const { setTitle } = useModal();
|
|
3258
|
+
useEffect(() => {
|
|
3259
|
+
setTitle(String(children));
|
|
3260
|
+
return () => setTitle("");
|
|
3261
|
+
}, [children]);
|
|
3262
|
+
return null;
|
|
3263
|
+
};
|
|
3264
|
+
var alignClass2 = {
|
|
3265
|
+
left: "justify-start",
|
|
3266
|
+
center: "justify-center",
|
|
3267
|
+
right: "justify-end"
|
|
3268
|
+
};
|
|
3269
|
+
var ModalFooter = ({ children, align = "right" }) => {
|
|
3270
|
+
const { setFooter } = useModal();
|
|
3271
|
+
useEffect(() => {
|
|
3272
|
+
setFooter(
|
|
3273
|
+
/* @__PURE__ */ jsx("div", { className: twMerge("flex items-center gap-2", alignClass2[align]), children })
|
|
3274
|
+
);
|
|
3275
|
+
return () => setFooter(null);
|
|
3276
|
+
}, [align, children]);
|
|
3277
|
+
return null;
|
|
3278
|
+
};
|
|
3279
|
+
var ModalSkeleton = () => /* @__PURE__ */ jsxs("div", { className: "animate-pulse space-y-3", children: [
|
|
3280
|
+
/* @__PURE__ */ jsx("div", { className: "h-4 bg-(--ui-surface-muted) rounded w-1/3" }),
|
|
3281
|
+
/* @__PURE__ */ jsx("div", { className: "h-8 bg-(--ui-surface-muted) rounded" }),
|
|
3282
|
+
/* @__PURE__ */ jsx("div", { className: "h-4 bg-(--ui-surface-muted) rounded w-1/3 mt-5" }),
|
|
3283
|
+
/* @__PURE__ */ jsx("div", { className: "h-8 bg-(--ui-surface-muted) rounded" }),
|
|
3284
|
+
/* @__PURE__ */ jsx("div", { className: "h-4 bg-(--ui-surface-muted) rounded w-1/3 mt-5" }),
|
|
3285
|
+
/* @__PURE__ */ jsx("div", { className: "h-8 bg-(--ui-surface-muted) rounded" })
|
|
3286
|
+
] });
|
|
3287
|
+
var ModalContent = ({ loading = false, children }) => {
|
|
3288
|
+
if (loading) {
|
|
3289
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-5", children: [
|
|
3290
|
+
/* @__PURE__ */ jsx(ModalSkeleton, {}),
|
|
3291
|
+
/* @__PURE__ */ jsx(Skeleton, { active: true, title: false, paragraph: { rows: 2 } })
|
|
3292
|
+
] });
|
|
3293
|
+
}
|
|
3294
|
+
return /* @__PURE__ */ jsx(Fragment, { children });
|
|
3295
|
+
};
|
|
3044
3296
|
var Alert = ({ type = "info", message, description, closable = false, className, classNames }) => {
|
|
3045
3297
|
const [closed, setClosed] = useState(false);
|
|
3046
3298
|
if (closed) {
|
|
@@ -4250,6 +4502,6 @@ function initUI(config) {
|
|
|
4250
4502
|
r.style.setProperty("--ui-empty-compact-description", layout.empty.compactDescription);
|
|
4251
4503
|
}
|
|
4252
4504
|
|
|
4253
|
-
export { ActiveTag, Alert, Avatar, Badge, Button, CheckboxInput, ColorInput, DateInput, Drawer, DrawerContent, DrawerFooter, DrawerTitle, Dropdown, Empty, ErrorProvider, FilterCheckboxInput, FilterDateInput, FilterDateRangePopover, FilterNumberInput, FilterSelectGroupPopover, FilterSelectInput, FilterTextInput, FlagTag, Grid, GridFilters, HtmlInput, InputError, InputField, InputLabel, MultiSelectInput, NotificationProvider, NumberInput, Panel, Popconfirm, Pretty, SelectInput, ServerError, Skeleton, SortDirection, Spinner, SwitchInput, Table, Tabs, Tag, TextInput, Tooltip, UploadInput, UploadProvider, getIcon, initUI, notification, registerIcons, uiTheme, useDrawer, useGrid, useNotification, useUploadConfig };
|
|
4505
|
+
export { ActiveTag, Alert, Avatar, Badge, Button, CheckboxInput, ColorInput, DateInput, Drawer, DrawerContent, DrawerFooter, DrawerTitle, Dropdown, Empty, ErrorProvider, FilterCheckboxInput, FilterDateInput, FilterDateRangePopover, FilterNumberInput, FilterSelectGroupPopover, FilterSelectInput, FilterTextInput, FlagTag, Grid, GridFilters, HtmlInput, InputError, InputField, InputLabel, Modal, ModalContent, ModalFooter, ModalTitle, MultiSelectInput, NotificationProvider, NumberInput, Panel, Popconfirm, Pretty, SelectInput, ServerError, Skeleton, SortDirection, Spinner, SwitchInput, Table, Tabs, Tag, TextInput, Tooltip, UploadInput, UploadProvider, getIcon, initUI, notification, registerIcons, uiTheme, useDrawer, useGrid, useModal, useNotification, useUploadConfig };
|
|
4254
4506
|
//# sourceMappingURL=index.js.map
|
|
4255
4507
|
//# sourceMappingURL=index.js.map
|