@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.cjs
CHANGED
|
@@ -417,12 +417,12 @@ var ErrorContext = react.createContext({
|
|
|
417
417
|
var ErrorProvider = ({ resolveInputError, resolveServerError, children }) => /* @__PURE__ */ jsxRuntime.jsx(ErrorContext.Provider, { value: { resolveInputError, resolveServerError }, children });
|
|
418
418
|
var useErrorResolver = () => react.useContext(ErrorContext).resolveInputError;
|
|
419
419
|
var useServerError = () => react.useContext(ErrorContext).resolveServerError;
|
|
420
|
-
var TextInput = ({
|
|
420
|
+
var TextInput = react.forwardRef(({
|
|
421
421
|
size = "middle",
|
|
422
422
|
password = false,
|
|
423
423
|
newPassword = false,
|
|
424
424
|
...props
|
|
425
|
-
}) => {
|
|
425
|
+
}, ref) => {
|
|
426
426
|
const [showPassword, setShowPassword] = react.useState(false);
|
|
427
427
|
const resolveError = useErrorResolver();
|
|
428
428
|
const resolvedErrors = props.errorName ? resolveError(props.errorName) : [];
|
|
@@ -443,6 +443,7 @@ var TextInput = ({
|
|
|
443
443
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
444
444
|
"input",
|
|
445
445
|
{
|
|
446
|
+
ref,
|
|
446
447
|
type: inputType,
|
|
447
448
|
autoComplete: newPassword ? "new-password" : void 0,
|
|
448
449
|
placeholder: props.placeholder,
|
|
@@ -476,7 +477,8 @@ var TextInput = ({
|
|
|
476
477
|
] }),
|
|
477
478
|
errorDisplay && /* @__PURE__ */ jsxRuntime.jsx(InputError, { error: String(errorDisplay), className: props.classNames?.error })
|
|
478
479
|
] });
|
|
479
|
-
};
|
|
480
|
+
});
|
|
481
|
+
TextInput.displayName = "TextInput";
|
|
480
482
|
var numberInputClass = inputBaseClass + " [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none";
|
|
481
483
|
var NumberInput = ({
|
|
482
484
|
size = "middle",
|
|
@@ -651,7 +653,7 @@ var SwitchInput = ({
|
|
|
651
653
|
|
|
652
654
|
// src/floating/layerStack.ts
|
|
653
655
|
var FLOATING_ROOT_SELECTOR = "[data-ui-floating-root]";
|
|
654
|
-
var
|
|
656
|
+
var LAYER_ROOT_SELECTOR = "[data-ui-layer-root]";
|
|
655
657
|
function getTopmostElement(selector) {
|
|
656
658
|
const elements = document.querySelectorAll(selector);
|
|
657
659
|
return elements.length > 0 ? elements[elements.length - 1] : null;
|
|
@@ -662,8 +664,8 @@ function hasFloatingRootOpen() {
|
|
|
662
664
|
function isTopmostFloatingRoot(element) {
|
|
663
665
|
return element !== null && getTopmostElement(FLOATING_ROOT_SELECTOR) === element;
|
|
664
666
|
}
|
|
665
|
-
function
|
|
666
|
-
return element !== null && getTopmostElement(
|
|
667
|
+
function isTopmostLayerRoot(element) {
|
|
668
|
+
return element !== null && getTopmostElement(LAYER_ROOT_SELECTOR) === element;
|
|
667
669
|
}
|
|
668
670
|
function isTargetInsideFloatingRoot(target) {
|
|
669
671
|
return target instanceof Element && target.closest(FLOATING_ROOT_SELECTOR) !== null;
|
|
@@ -2894,7 +2896,7 @@ var Drawer = ({ placement = "top", ...props }) => {
|
|
|
2894
2896
|
if (isTargetInsideFloatingRoot(e.target)) {
|
|
2895
2897
|
return;
|
|
2896
2898
|
}
|
|
2897
|
-
if (!
|
|
2899
|
+
if (!isTopmostLayerRoot(panelRef.current)) {
|
|
2898
2900
|
return;
|
|
2899
2901
|
}
|
|
2900
2902
|
props.onClose(false);
|
|
@@ -2935,7 +2937,7 @@ var Drawer = ({ placement = "top", ...props }) => {
|
|
|
2935
2937
|
"div",
|
|
2936
2938
|
{
|
|
2937
2939
|
ref: panelRef,
|
|
2938
|
-
"data-ui-
|
|
2940
|
+
"data-ui-layer-root": "",
|
|
2939
2941
|
className: tailwindMerge.twMerge(
|
|
2940
2942
|
panelBase[placement],
|
|
2941
2943
|
"bg-white shadow-xl transition-transform duration-220 ease-out",
|
|
@@ -3047,6 +3049,256 @@ var DrawerContent = ({ loading = false, children }) => {
|
|
|
3047
3049
|
}
|
|
3048
3050
|
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
|
|
3049
3051
|
};
|
|
3052
|
+
var ModalContext = react.createContext(null);
|
|
3053
|
+
function useModal() {
|
|
3054
|
+
const ctx = react.useContext(ModalContext);
|
|
3055
|
+
if (!ctx) {
|
|
3056
|
+
throw new Error("useModal must be used inside Modal");
|
|
3057
|
+
}
|
|
3058
|
+
return ctx;
|
|
3059
|
+
}
|
|
3060
|
+
var TRANSITION_MS2 = 220;
|
|
3061
|
+
var sizeClass = {
|
|
3062
|
+
small: "w-full max-w-lg",
|
|
3063
|
+
middle: "w-full max-w-3xl",
|
|
3064
|
+
large: "w-full max-w-5xl",
|
|
3065
|
+
auto: "w-auto"
|
|
3066
|
+
};
|
|
3067
|
+
var Modal = ({
|
|
3068
|
+
placement = "center",
|
|
3069
|
+
size = "middle",
|
|
3070
|
+
width,
|
|
3071
|
+
maxWidth,
|
|
3072
|
+
closeOnEscape = true,
|
|
3073
|
+
closeOnOverlayClick = true,
|
|
3074
|
+
showCloseButton = true,
|
|
3075
|
+
hideHeader = false,
|
|
3076
|
+
destroyOnClose = true,
|
|
3077
|
+
preventClose = false,
|
|
3078
|
+
beforeClose,
|
|
3079
|
+
initialFocusRef,
|
|
3080
|
+
...props
|
|
3081
|
+
}) => {
|
|
3082
|
+
const [rendered, setRendered] = react.useState(props.isOpen);
|
|
3083
|
+
const [visible, setVisible] = react.useState(false);
|
|
3084
|
+
const [title, setTitle] = react.useState("");
|
|
3085
|
+
const [footer, setFooter] = react.useState(null);
|
|
3086
|
+
const [loading, setLoading] = react.useState(false);
|
|
3087
|
+
const frameRef = react.useRef(0);
|
|
3088
|
+
const panelRef = react.useRef(null);
|
|
3089
|
+
react.useEffect(() => {
|
|
3090
|
+
if (props.isOpen) {
|
|
3091
|
+
setRendered(true);
|
|
3092
|
+
frameRef.current = requestAnimationFrame(() => {
|
|
3093
|
+
frameRef.current = requestAnimationFrame(() => setVisible(true));
|
|
3094
|
+
});
|
|
3095
|
+
} else {
|
|
3096
|
+
setVisible(false);
|
|
3097
|
+
if (!destroyOnClose) {
|
|
3098
|
+
return () => cancelAnimationFrame(frameRef.current);
|
|
3099
|
+
}
|
|
3100
|
+
const t = setTimeout(() => setRendered(false), TRANSITION_MS2);
|
|
3101
|
+
return () => clearTimeout(t);
|
|
3102
|
+
}
|
|
3103
|
+
return () => cancelAnimationFrame(frameRef.current);
|
|
3104
|
+
}, [destroyOnClose, props.isOpen]);
|
|
3105
|
+
react.useEffect(() => {
|
|
3106
|
+
if (!props.isOpen) {
|
|
3107
|
+
return;
|
|
3108
|
+
}
|
|
3109
|
+
const focusTarget = initialFocusRef?.current;
|
|
3110
|
+
if (!focusTarget) {
|
|
3111
|
+
return;
|
|
3112
|
+
}
|
|
3113
|
+
const timeout = window.setTimeout(() => focusTarget.focus(), TRANSITION_MS2 / 2);
|
|
3114
|
+
return () => window.clearTimeout(timeout);
|
|
3115
|
+
}, [initialFocusRef, props.isOpen]);
|
|
3116
|
+
react.useEffect(() => {
|
|
3117
|
+
if (!props.isOpen) {
|
|
3118
|
+
return;
|
|
3119
|
+
}
|
|
3120
|
+
const handleKeyDown = (e) => {
|
|
3121
|
+
if (!closeOnEscape || e.key !== "Escape" || e.defaultPrevented) {
|
|
3122
|
+
return;
|
|
3123
|
+
}
|
|
3124
|
+
if (hasFloatingRootOpen() || isTargetInsideFloatingRoot(e.target)) {
|
|
3125
|
+
return;
|
|
3126
|
+
}
|
|
3127
|
+
if (!isTopmostLayerRoot(panelRef.current)) {
|
|
3128
|
+
return;
|
|
3129
|
+
}
|
|
3130
|
+
void requestClose();
|
|
3131
|
+
};
|
|
3132
|
+
document.body.style.overflow = "hidden";
|
|
3133
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
3134
|
+
return () => {
|
|
3135
|
+
document.body.style.overflow = "";
|
|
3136
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
3137
|
+
};
|
|
3138
|
+
}, [closeOnEscape, props.isOpen]);
|
|
3139
|
+
if (!rendered) {
|
|
3140
|
+
return null;
|
|
3141
|
+
}
|
|
3142
|
+
const requestClose = async () => {
|
|
3143
|
+
if (preventClose) {
|
|
3144
|
+
return;
|
|
3145
|
+
}
|
|
3146
|
+
const canClose = await beforeClose?.();
|
|
3147
|
+
if (canClose === false) {
|
|
3148
|
+
return;
|
|
3149
|
+
}
|
|
3150
|
+
props.onClose(false);
|
|
3151
|
+
};
|
|
3152
|
+
const close = () => {
|
|
3153
|
+
void requestClose();
|
|
3154
|
+
};
|
|
3155
|
+
const saveAndClose = (message) => {
|
|
3156
|
+
if (message) {
|
|
3157
|
+
notification.success(message);
|
|
3158
|
+
}
|
|
3159
|
+
props.onClose(true);
|
|
3160
|
+
};
|
|
3161
|
+
const hasFooter = footer !== null;
|
|
3162
|
+
const isFullscreen = placement === "fullscreen";
|
|
3163
|
+
return reactDom.createPortal(
|
|
3164
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ModalContext.Provider, { value: { close, saveAndClose, setTitle, setFooter, setLoading }, children: [
|
|
3165
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3166
|
+
"div",
|
|
3167
|
+
{
|
|
3168
|
+
className: tailwindMerge.twMerge(
|
|
3169
|
+
"fixed inset-0 z-1000 bg-black/40 transition-opacity duration-220",
|
|
3170
|
+
visible ? "opacity-100" : "opacity-0",
|
|
3171
|
+
!props.isOpen && "pointer-events-none",
|
|
3172
|
+
props.classNames?.overlay
|
|
3173
|
+
),
|
|
3174
|
+
onClick: () => closeOnOverlayClick && close()
|
|
3175
|
+
}
|
|
3176
|
+
),
|
|
3177
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3178
|
+
"div",
|
|
3179
|
+
{
|
|
3180
|
+
className: tailwindMerge.twMerge(
|
|
3181
|
+
"fixed inset-0 z-1001 flex p-4 transition-all duration-220",
|
|
3182
|
+
isFullscreen ? "items-stretch justify-stretch p-0" : "items-center justify-center",
|
|
3183
|
+
!props.isOpen && "pointer-events-none"
|
|
3184
|
+
),
|
|
3185
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3186
|
+
"div",
|
|
3187
|
+
{
|
|
3188
|
+
ref: panelRef,
|
|
3189
|
+
"data-ui-layer-root": "",
|
|
3190
|
+
role: "dialog",
|
|
3191
|
+
"aria-modal": "true",
|
|
3192
|
+
"aria-hidden": !props.isOpen,
|
|
3193
|
+
style: !isFullscreen ? { width, maxWidth } : void 0,
|
|
3194
|
+
className: tailwindMerge.twMerge(
|
|
3195
|
+
"bg-white shadow-xl flex flex-col transition-all duration-220 ease-out",
|
|
3196
|
+
isFullscreen ? "h-full w-full rounded-none" : `${sizeClass[size]} max-h-[calc(100dvh-32px)] rounded-(--ui-radius-lg)`,
|
|
3197
|
+
visible ? "scale-100 opacity-100" : "scale-95 opacity-0",
|
|
3198
|
+
props.className,
|
|
3199
|
+
props.classNames?.panel
|
|
3200
|
+
),
|
|
3201
|
+
onClick: (e) => e.stopPropagation(),
|
|
3202
|
+
children: [
|
|
3203
|
+
!hideHeader && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3204
|
+
"div",
|
|
3205
|
+
{
|
|
3206
|
+
className: tailwindMerge.twMerge(
|
|
3207
|
+
"flex items-center justify-between gap-2 bg-(--ui-primary) shrink-0 rounded-t-(--ui-radius-lg)",
|
|
3208
|
+
isFullscreen && "rounded-none",
|
|
3209
|
+
drawerLayoutClasses.header,
|
|
3210
|
+
props.classNames?.header
|
|
3211
|
+
),
|
|
3212
|
+
children: [
|
|
3213
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: tailwindMerge.twMerge(componentTitleClasses.inverse, "truncate", props.classNames?.title), children: title }),
|
|
3214
|
+
showCloseButton && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3215
|
+
"button",
|
|
3216
|
+
{
|
|
3217
|
+
type: "button",
|
|
3218
|
+
onClick: close,
|
|
3219
|
+
className: tailwindMerge.twMerge(
|
|
3220
|
+
"shrink-0 text-(--ui-primary-text)/70 hover:text-(--ui-primary-text) cursor-pointer transition-colors",
|
|
3221
|
+
props.classNames?.closeButton
|
|
3222
|
+
),
|
|
3223
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(iconsReact.IconX, { size: 18, strokeWidth: 1.5 })
|
|
3224
|
+
}
|
|
3225
|
+
)
|
|
3226
|
+
]
|
|
3227
|
+
}
|
|
3228
|
+
),
|
|
3229
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3230
|
+
"div",
|
|
3231
|
+
{
|
|
3232
|
+
className: tailwindMerge.twMerge(
|
|
3233
|
+
"overflow-y-auto flex-1",
|
|
3234
|
+
isFullscreen ? "min-h-0" : "max-h-[calc(100dvh-120px)]",
|
|
3235
|
+
drawerLayoutClasses.body,
|
|
3236
|
+
props.classNames?.body
|
|
3237
|
+
),
|
|
3238
|
+
children: loading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: tailwindMerge.twMerge("flex items-center justify-center py-16", props.classNames?.loading), children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: "large", color: "primary" }) }) : props.children
|
|
3239
|
+
}
|
|
3240
|
+
),
|
|
3241
|
+
hasFooter && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3242
|
+
"div",
|
|
3243
|
+
{
|
|
3244
|
+
className: tailwindMerge.twMerge(
|
|
3245
|
+
"border-t border-(--ui-border) shrink-0 bg-white",
|
|
3246
|
+
isFullscreen ? "rounded-none" : "rounded-b-(--ui-radius-lg)",
|
|
3247
|
+
drawerLayoutClasses.footer,
|
|
3248
|
+
props.classNames?.footer
|
|
3249
|
+
),
|
|
3250
|
+
children: footer
|
|
3251
|
+
}
|
|
3252
|
+
)
|
|
3253
|
+
]
|
|
3254
|
+
}
|
|
3255
|
+
)
|
|
3256
|
+
}
|
|
3257
|
+
)
|
|
3258
|
+
] }),
|
|
3259
|
+
document.body
|
|
3260
|
+
);
|
|
3261
|
+
};
|
|
3262
|
+
var ModalTitle = ({ children }) => {
|
|
3263
|
+
const { setTitle } = useModal();
|
|
3264
|
+
react.useEffect(() => {
|
|
3265
|
+
setTitle(String(children));
|
|
3266
|
+
return () => setTitle("");
|
|
3267
|
+
}, [children]);
|
|
3268
|
+
return null;
|
|
3269
|
+
};
|
|
3270
|
+
var alignClass2 = {
|
|
3271
|
+
left: "justify-start",
|
|
3272
|
+
center: "justify-center",
|
|
3273
|
+
right: "justify-end"
|
|
3274
|
+
};
|
|
3275
|
+
var ModalFooter = ({ children, align = "right" }) => {
|
|
3276
|
+
const { setFooter } = useModal();
|
|
3277
|
+
react.useEffect(() => {
|
|
3278
|
+
setFooter(
|
|
3279
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: tailwindMerge.twMerge("flex items-center gap-2", alignClass2[align]), children })
|
|
3280
|
+
);
|
|
3281
|
+
return () => setFooter(null);
|
|
3282
|
+
}, [align, children]);
|
|
3283
|
+
return null;
|
|
3284
|
+
};
|
|
3285
|
+
var ModalSkeleton = () => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "animate-pulse space-y-3", children: [
|
|
3286
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-4 bg-(--ui-surface-muted) rounded w-1/3" }),
|
|
3287
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-8 bg-(--ui-surface-muted) rounded" }),
|
|
3288
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-4 bg-(--ui-surface-muted) rounded w-1/3 mt-5" }),
|
|
3289
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-8 bg-(--ui-surface-muted) rounded" }),
|
|
3290
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-4 bg-(--ui-surface-muted) rounded w-1/3 mt-5" }),
|
|
3291
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-8 bg-(--ui-surface-muted) rounded" })
|
|
3292
|
+
] });
|
|
3293
|
+
var ModalContent = ({ loading = false, children }) => {
|
|
3294
|
+
if (loading) {
|
|
3295
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-5", children: [
|
|
3296
|
+
/* @__PURE__ */ jsxRuntime.jsx(ModalSkeleton, {}),
|
|
3297
|
+
/* @__PURE__ */ jsxRuntime.jsx(Skeleton, { active: true, title: false, paragraph: { rows: 2 } })
|
|
3298
|
+
] });
|
|
3299
|
+
}
|
|
3300
|
+
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
|
|
3301
|
+
};
|
|
3050
3302
|
var Alert = ({ type = "info", message, description, closable = false, className, classNames }) => {
|
|
3051
3303
|
const [closed, setClosed] = react.useState(false);
|
|
3052
3304
|
if (closed) {
|
|
@@ -4285,6 +4537,10 @@ exports.HtmlInput = HtmlInput;
|
|
|
4285
4537
|
exports.InputError = InputError;
|
|
4286
4538
|
exports.InputField = InputField;
|
|
4287
4539
|
exports.InputLabel = InputLabel;
|
|
4540
|
+
exports.Modal = Modal;
|
|
4541
|
+
exports.ModalContent = ModalContent;
|
|
4542
|
+
exports.ModalFooter = ModalFooter;
|
|
4543
|
+
exports.ModalTitle = ModalTitle;
|
|
4288
4544
|
exports.MultiSelectInput = MultiSelectInput;
|
|
4289
4545
|
exports.NotificationProvider = NotificationProvider;
|
|
4290
4546
|
exports.NumberInput = NumberInput;
|
|
@@ -4311,6 +4567,7 @@ exports.registerIcons = registerIcons;
|
|
|
4311
4567
|
exports.uiTheme = uiTheme;
|
|
4312
4568
|
exports.useDrawer = useDrawer;
|
|
4313
4569
|
exports.useGrid = useGrid;
|
|
4570
|
+
exports.useModal = useModal;
|
|
4314
4571
|
exports.useNotification = useNotification;
|
|
4315
4572
|
exports.useUploadConfig = useUploadConfig;
|
|
4316
4573
|
//# sourceMappingURL=index.cjs.map
|