@xanui/ui 1.1.20 → 1.1.21
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/Input/index.d.ts +33 -7
- package/Input/index.js +31 -22
- package/Input/index.js.map +1 -1
- package/Input/index.mjs +33 -24
- package/Input/index.mjs.map +1 -1
- package/Menu/index.js +5 -3
- package/Menu/index.js.map +1 -1
- package/Menu/index.mjs +5 -3
- package/Menu/index.mjs.map +1 -1
- package/Select/index.d.ts +5 -0
- package/Select/index.js +8 -7
- package/Select/index.js.map +1 -1
- package/Select/index.mjs +9 -8
- package/Select/index.mjs.map +1 -1
- package/package.json +2 -2
package/Input/index.d.ts
CHANGED
|
@@ -1,23 +1,49 @@
|
|
|
1
|
-
import React, { ReactElement
|
|
1
|
+
import React, { ReactElement } from 'react';
|
|
2
2
|
import { TagComponentType, TagProps, useBreakpointPropsType, UseColorTemplateColor } from '@xanui/core';
|
|
3
3
|
|
|
4
|
-
type InputProps<T extends TagComponentType = "
|
|
4
|
+
type InputProps<T extends TagComponentType = "div"> = Omit<TagProps<T>, "size" | "color"> & {
|
|
5
|
+
value?: string;
|
|
6
|
+
type?: TagProps<'input'>['type'];
|
|
7
|
+
name?: string;
|
|
8
|
+
placeholder?: string;
|
|
9
|
+
readOnly?: boolean;
|
|
10
|
+
autoFocus?: boolean;
|
|
11
|
+
autoComplete?: string;
|
|
12
|
+
onFocus?: (e: React.FocusEvent<any>) => void;
|
|
13
|
+
onBlur?: (e: React.FocusEvent<any>) => void;
|
|
14
|
+
onChange?: (e: React.ChangeEvent<any>) => void;
|
|
15
|
+
onInput?: (e: React.FormEvent<any>) => void;
|
|
16
|
+
onKeyDown?: (e: React.KeyboardEvent<any>) => void;
|
|
17
|
+
onKeyUp?: (e: React.KeyboardEvent<any>) => void;
|
|
18
|
+
rows?: useBreakpointPropsType<number>;
|
|
19
|
+
minRows?: useBreakpointPropsType<number>;
|
|
20
|
+
maxRows?: useBreakpointPropsType<number>;
|
|
21
|
+
fullWidth?: boolean;
|
|
5
22
|
startIcon?: useBreakpointPropsType<ReactElement>;
|
|
6
23
|
endIcon?: useBreakpointPropsType<ReactElement>;
|
|
7
24
|
iconPlacement?: useBreakpointPropsType<"start" | "center" | "end">;
|
|
8
25
|
focused?: boolean;
|
|
9
26
|
color?: useBreakpointPropsType<Omit<UseColorTemplateColor, "default">>;
|
|
10
|
-
containerRef?: MutableRefObject<HTMLDivElement | undefined>;
|
|
11
27
|
variant?: useBreakpointPropsType<"fill" | "outline" | "text">;
|
|
12
28
|
error?: boolean;
|
|
13
29
|
helperText?: useBreakpointPropsType<string>;
|
|
14
30
|
multiline?: boolean;
|
|
15
31
|
size?: useBreakpointPropsType<"small" | "medium" | "large">;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
32
|
+
refs?: {
|
|
33
|
+
rootContainer?: React.Ref<"div">;
|
|
34
|
+
startIcon?: React.Ref<ReactElement>;
|
|
35
|
+
endIcon?: React.Ref<ReactElement>;
|
|
36
|
+
inputContainer?: React.Ref<"div">;
|
|
37
|
+
input?: React.Ref<'input' | 'textarea'>;
|
|
38
|
+
helperText?: React.Ref<"div">;
|
|
39
|
+
};
|
|
19
40
|
slotProps?: {
|
|
20
|
-
|
|
41
|
+
rootContainer?: Omit<TagProps<"div">, "children">;
|
|
42
|
+
startIcon?: Omit<TagProps<'div'>, "children">;
|
|
43
|
+
endIcon?: Omit<TagProps<'div'>, "children">;
|
|
44
|
+
inputContainer?: Omit<TagProps<"div">, "children">;
|
|
45
|
+
helperText?: Omit<TagProps<"div">, "children">;
|
|
46
|
+
input?: Partial<TagProps<T>>;
|
|
21
47
|
};
|
|
22
48
|
};
|
|
23
49
|
declare const Input: React.ForwardRefExoticComponent<Omit<InputProps<TagComponentType>, "ref"> & React.RefAttributes<any>>;
|
package/Input/index.js
CHANGED
|
@@ -5,12 +5,11 @@ var tslib = require('tslib');
|
|
|
5
5
|
var jsxRuntime = require('react/jsx-runtime');
|
|
6
6
|
var React = require('react');
|
|
7
7
|
var core = require('@xanui/core');
|
|
8
|
-
var index = require('../Text/index.js');
|
|
9
8
|
|
|
10
9
|
const Input = React.forwardRef((_a, ref) => {
|
|
11
10
|
var _b, _c, _d;
|
|
12
|
-
var { value } = _a, props = tslib.__rest(_a, ["value"]);
|
|
13
|
-
let [_e, theme] = core.useInterface("Input", props, {}), { startIcon, endIcon, iconPlacement,
|
|
11
|
+
var { value, refs } = _a, props = tslib.__rest(_a, ["value", "refs"]);
|
|
12
|
+
let [_e, theme] = core.useInterface("Input", props, {}), { startIcon, endIcon, iconPlacement, color, name, placeholder, type, readOnly, autoFocus, autoComplete, onFocus, onBlur, onChange, onKeyDown, onKeyUp, focused, disabled, variant, error, helperText, multiline, size, rows, minRows, maxRows, fullWidth, slotProps } = _e, rest = tslib.__rest(_e, ["startIcon", "endIcon", "iconPlacement", "color", "name", "placeholder", "type", "readOnly", "autoFocus", "autoComplete", "onFocus", "onBlur", "onChange", "onKeyDown", "onKeyUp", "focused", "disabled", "variant", "error", "helperText", "multiline", "size", "rows", "minRows", "maxRows", "fullWidth", "slotProps"]);
|
|
14
13
|
const _p = {};
|
|
15
14
|
if (startIcon)
|
|
16
15
|
_p.startIcon = startIcon;
|
|
@@ -43,18 +42,21 @@ const Input = React.forwardRef((_a, ref) => {
|
|
|
43
42
|
rows = p.rows;
|
|
44
43
|
minRows = p.minRows;
|
|
45
44
|
maxRows = p.maxRows;
|
|
46
|
-
ref !== null && ref !== void 0 ? ref : (ref = React.useRef(null));
|
|
47
45
|
iconPlacement !== null && iconPlacement !== void 0 ? iconPlacement : (iconPlacement = multiline ? "end" : "center");
|
|
48
46
|
if (!value)
|
|
49
47
|
iconPlacement = 'center';
|
|
50
48
|
const [_focused, setFocused] = React.useState(false);
|
|
51
|
-
const conRef = React.useRef(null);
|
|
52
49
|
let _focus = focused || _focused;
|
|
50
|
+
const inputRef = React.useRef(null);
|
|
51
|
+
const inputMergeRef = core.useMergeRefs(inputRef, refs === null || refs === void 0 ? void 0 : refs.input);
|
|
53
52
|
React.useEffect(() => {
|
|
54
|
-
if (
|
|
55
|
-
|
|
53
|
+
if (autoFocus) {
|
|
54
|
+
setTimeout(() => {
|
|
55
|
+
var _a;
|
|
56
|
+
(_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
57
|
+
}, 100);
|
|
56
58
|
}
|
|
57
|
-
}, [
|
|
59
|
+
}, [autoFocus]);
|
|
58
60
|
let _rows = React.useMemo(() => {
|
|
59
61
|
if (rows)
|
|
60
62
|
return rows;
|
|
@@ -100,18 +102,18 @@ const Input = React.forwardRef((_a, ref) => {
|
|
|
100
102
|
}
|
|
101
103
|
};
|
|
102
104
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
105
|
+
return (jsxRuntime.jsxs(core.Tag, Object.assign({ width: fullWidth ? "100%" : undefined }, rest, { ref: ref, baseClass: 'input-root', classNames: {
|
|
106
|
+
'input-full-width': fullWidth || false,
|
|
107
|
+
'input-focused': _focus,
|
|
108
|
+
'input-error': error || false,
|
|
109
|
+
[`input-variant-${variant}`]: true,
|
|
110
|
+
[`input-size-${size}`]: true,
|
|
111
|
+
}, children: [jsxRuntime.jsxs(core.Tag, Object.assign({}, slotProps === null || slotProps === void 0 ? void 0 : slotProps.rootContainer, { ref: refs === null || refs === void 0 ? void 0 : refs.rootContainer, baseClass: 'root-container', sxr: {
|
|
112
|
+
width: "100%",
|
|
110
113
|
display: "flex",
|
|
111
114
|
flexDirection: "row",
|
|
112
115
|
alignItems: iconPlacement === 'center' ? iconPlacement : `flex-${iconPlacement}`,
|
|
113
116
|
flexWrap: "nowrap",
|
|
114
|
-
// minWidth: 100,
|
|
115
117
|
transitionProperty: "border, box-shadow, background",
|
|
116
118
|
bgcolor: error ? "danger.soft.primary" : variant === "fill" ? "background.secondary" : "background.primary",
|
|
117
119
|
border: variant === "text" ? 0 : "1px solid",
|
|
@@ -119,13 +121,14 @@ const Input = React.forwardRef((_a, ref) => {
|
|
|
119
121
|
borderRadius: 1,
|
|
120
122
|
px: 1,
|
|
121
123
|
py: .5,
|
|
122
|
-
},
|
|
124
|
+
}, disabled: disabled || false }, _size, { height: multiline ? "auto" : _size.height, minHeight: _size.height, children: [startIcon && jsxRuntime.jsx(core.Tag, Object.assign({}, slotProps === null || slotProps === void 0 ? void 0 : slotProps.startIcon, { ref: refs === null || refs === void 0 ? void 0 : refs.startIcon, flex: "0 0 auto", sxr: {
|
|
123
125
|
height: "100%",
|
|
124
126
|
alignItems: 'center',
|
|
125
127
|
justifyContent: "center",
|
|
126
128
|
display: "flex",
|
|
127
129
|
color: error ? "danger.primary" : "text.secondary",
|
|
128
|
-
}, baseClass: "input-start-icon", children: startIcon }), jsxRuntime.jsx(core.Tag, { flex: 1, sxr: {
|
|
130
|
+
}, baseClass: "input-start-icon", children: startIcon })), jsxRuntime.jsx(core.Tag, Object.assign({}, slotProps === null || slotProps === void 0 ? void 0 : slotProps.inputContainer, { ref: refs === null || refs === void 0 ? void 0 : refs.inputContainer, baseClass: 'input-container', flex: 1, sxr: {
|
|
131
|
+
width: "100%",
|
|
129
132
|
display: "flex",
|
|
130
133
|
alignItems: "center",
|
|
131
134
|
flex: 1,
|
|
@@ -138,7 +141,7 @@ const Input = React.forwardRef((_a, ref) => {
|
|
|
138
141
|
"box-shadow": `0 0 0px 1000px ${variant === "fill" ? theme.colors.background.secondary : theme.colors.background.primary} inset`,
|
|
139
142
|
transition: "background-color 5000s ease-in-out 0s"
|
|
140
143
|
}
|
|
141
|
-
}, children: jsxRuntime.jsx(core.Tag, Object.assign({ component: multiline ? 'textarea' : 'input' }, multiprops,
|
|
144
|
+
}, children: jsxRuntime.jsx(core.Tag, Object.assign({}, slotProps === null || slotProps === void 0 ? void 0 : slotProps.input, { ref: inputMergeRef, baseClass: 'input', component: multiline ? 'textarea' : 'input' }, multiprops, { sxr: {
|
|
142
145
|
border: 0,
|
|
143
146
|
outline: 0,
|
|
144
147
|
bgcolor: "transparent",
|
|
@@ -147,19 +150,25 @@ const Input = React.forwardRef((_a, ref) => {
|
|
|
147
150
|
height: multiline ? "auto" : _size.height + "px!important",
|
|
148
151
|
width: "100%",
|
|
149
152
|
maxHeight: 200,
|
|
150
|
-
}, value: value,
|
|
153
|
+
}, value: value, onChange: onChange, onFocus: (e) => {
|
|
151
154
|
focused !== null && focused !== void 0 ? focused : setFocused(true);
|
|
152
155
|
onFocus && onFocus(e);
|
|
153
156
|
}, onBlur: (e) => {
|
|
154
157
|
focused !== null && focused !== void 0 ? focused : setFocused(false);
|
|
155
158
|
onBlur && onBlur(e);
|
|
156
|
-
} })) }), endIcon && jsxRuntime.jsx(core.Tag, { flex: "0 0 auto", sxr: {
|
|
159
|
+
}, onKeyDown: onKeyDown, onKeyUp: onKeyUp, name: name, placeholder: placeholder, type: type, readOnly: readOnly, autoComplete: autoComplete })) })), endIcon && jsxRuntime.jsx(core.Tag, Object.assign({}, slotProps === null || slotProps === void 0 ? void 0 : slotProps.endIcon, { ref: refs === null || refs === void 0 ? void 0 : refs.endIcon, flex: "0 0 auto", sxr: {
|
|
157
160
|
height: "100%",
|
|
158
161
|
alignItems: 'center',
|
|
159
162
|
justifyContent: "center",
|
|
160
163
|
display: 'flex',
|
|
161
164
|
color: error ? "danger.primary" : "text.secondary",
|
|
162
|
-
}, baseClass: "input-end-icon", children: endIcon })] })), helperText && jsxRuntime.jsx(
|
|
165
|
+
}, baseClass: "input-end-icon", children: endIcon }))] })), helperText && jsxRuntime.jsx(core.Tag, Object.assign({}, slotProps === null || slotProps === void 0 ? void 0 : slotProps.helperText, { ref: refs === null || refs === void 0 ? void 0 : refs.helperText, baseClass: "input-helper-text", sxr: {
|
|
166
|
+
color: error ? "danger.primary" : "text.primary",
|
|
167
|
+
fontSize: "small",
|
|
168
|
+
lineHeight: "text",
|
|
169
|
+
fontWeight: 'text',
|
|
170
|
+
pl: .5,
|
|
171
|
+
}, children: helperText }))] })));
|
|
163
172
|
});
|
|
164
173
|
|
|
165
174
|
module.exports = Input;
|
package/Input/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/Input/index.tsx"],"sourcesContent":["\"use client\";\nimport React, { MutableRefObject, ReactElement, useEffect, useMemo, useRef, useState } from 'react';\nimport { Tag, TagProps, TagComponentType, UseColorTemplateColor, useBreakpointPropsType, useInterface, useBreakpointProps } from '@xanui/core';\nimport Text from '../Text';\n\nexport type InputProps<T extends TagComponentType = \"input\"> = Omit<TagProps<T>, \"size\" | \"color\"> & {\n startIcon?: useBreakpointPropsType<ReactElement>;\n endIcon?: useBreakpointPropsType<ReactElement>;\n iconPlacement?: useBreakpointPropsType<\"start\" | \"center\" | \"end\">;\n focused?: boolean;\n color?: useBreakpointPropsType<Omit<UseColorTemplateColor, \"default\">>;\n containerRef?: MutableRefObject<HTMLDivElement | undefined>;\n variant?: useBreakpointPropsType<\"fill\" | \"outline\" | \"text\">;\n error?: boolean;\n helperText?: useBreakpointPropsType<string>;\n multiline?: boolean;\n size?: useBreakpointPropsType<\"small\" | \"medium\" | \"large\">;\n rows?: useBreakpointPropsType<number>;\n minRows?: useBreakpointPropsType<number>;\n maxRows?: useBreakpointPropsType<number>;\n slotProps?: {\n container?: Omit<TagProps<\"div\">, \"children\">\n }\n}\n\nconst Input = React.forwardRef(<T extends TagComponentType = \"input\">({ value, ...props }: InputProps<T>, ref?: React.Ref<any>) => {\n let [{\n startIcon,\n endIcon,\n iconPlacement,\n onFocus,\n color,\n onBlur,\n focused,\n containerRef,\n disabled,\n variant,\n error,\n helperText,\n multiline,\n size,\n rows,\n minRows,\n maxRows,\n slotProps,\n ...rest\n }, theme] = useInterface<any>(\"Input\", props, {})\n\n const _p: any = {}\n if (startIcon) _p.startIcon = startIcon\n if (endIcon) _p.endIcon = endIcon\n if (iconPlacement) _p.iconPlacement = iconPlacement\n if (color) _p.color = color\n if (variant) _p.variant = variant\n if (helperText) _p.helperText = helperText\n if (size) _p.size = size\n if (rows) _p.rows = rows\n if (minRows) _p.minRows = minRows\n if (maxRows) _p.maxRows = maxRows\n const p: any = useBreakpointProps(_p)\n startIcon = p.startIcon\n endIcon = p.endIcon\n iconPlacement = p.iconPlacement\n color = p.color ?? \"brand\"\n variant = p.variant ?? \"fill\"\n helperText = p.helperText\n size = p.size ?? 'medium'\n rows = p.rows\n minRows = p.minRows\n maxRows = p.maxRows\n\n ref ??= useRef(null);\n iconPlacement ??= multiline ? \"end\" : \"center\"\n if (!value) iconPlacement = 'center'\n\n const [_focused, setFocused] = useState(false)\n const conRef: any = useRef(null)\n let _focus = focused || _focused\n\n useEffect(() => {\n if (containerRef) {\n (containerRef as any).current = conRef?.current\n }\n }, [containerRef])\n\n let _rows = useMemo(() => {\n if (rows) return rows\n if (value && multiline) {\n let lines = (value as string).split(`\\n`).length\n if (minRows && minRows > lines) {\n return minRows\n } else if (maxRows && maxRows < lines) {\n return maxRows\n } else {\n return lines\n }\n }\n }, [value]) || 1\n\n const sizes: any = {\n small: {\n height: 40,\n gap: .5,\n fontSize: 'button',\n },\n medium: {\n height: 48,\n gap: 1,\n fontSize: \"text\"\n },\n large: {\n height: 52,\n gap: 1,\n fontSize: 'big'\n }\n }\n\n const _size = sizes[size]\n let borderColor = _focus ? color : (variant === \"fill\" ? \"transparent\" : \"divider\")\n borderColor = error ? \"danger.primary\" : borderColor\n let multiprops: any = {}\n if (multiline) {\n multiprops = {\n rows: _rows,\n sx: {\n resize: \"none\"\n }\n }\n }\n\n useEffect(() => {\n if ((ref as any).current) {\n (ref as any).current.style.height = \"auto\";\n (ref as any).current.style.height = `${(ref as any).current.scrollHeight}px`;\n }\n }, [value]);\n\n return (\n <Tag\n baseClass={`input${_focus ? \" input-focused\" : \"\"}`}\n >\n <Tag\n {...slotProps?.container}\n sxr={{\n display: \"flex\",\n flexDirection: \"row\",\n alignItems: iconPlacement === 'center' ? iconPlacement : `flex-${iconPlacement}`,\n flexWrap: \"nowrap\",\n // minWidth: 100,\n transitionProperty: \"border, box-shadow, background\",\n bgcolor: error ? \"danger.soft.primary\" : variant === \"fill\" ? \"background.secondary\" : \"background.primary\",\n border: variant === \"text\" ? 0 : \"1px solid\",\n borderColor: borderColor,\n borderRadius: 1,\n px: 1,\n py: .5,\n }}\n baseClass='input-container'\n disabled={disabled || false}\n ref={conRef}\n {..._size}\n height={multiline ? \"auto\" : _size.height}\n minHeight={_size.height}\n >\n {startIcon && <Tag\n flex={\"0 0 auto\"}\n sxr={{\n height: \"100%\",\n alignItems: 'center',\n justifyContent: \"center\",\n display: \"flex\",\n color: error ? \"danger.primary\" : \"text.secondary\",\n }}\n baseClass=\"input-start-icon\"\n >{startIcon}</Tag>}\n <Tag\n flex={1}\n sxr={{\n display: \"flex\",\n alignItems: \"center\",\n flex: 1,\n minHeight: _size.height,\n \"& textarea\": {\n resize: \"none\"\n },\n \"& input:-webkit-autofill,& input:-webkit-autofill:hover, & input:-webkit-autofill:focus,& input:-webkit-autofill:active\": {\n \"-webkit-text-fill-color\": \"text.primary\",\n \"box-shadow\": `0 0 0px 1000px ${variant === \"fill\" ? theme.colors.background.secondary : theme.colors.background.primary} inset`,\n transition: \"background-color 5000s ease-in-out 0s\"\n } as any\n }}\n >\n <Tag\n component={multiline ? 'textarea' : 'input'}\n {...multiprops}\n {...rest}\n sxr={{\n border: 0,\n outline: 0,\n bgcolor: \"transparent\",\n color: error ? \"danger.primary\" : \"text.primary\",\n fontSize: _size.fontSize,\n height: multiline ? \"auto\" : _size.height + \"px!important\",\n width: \"100%\",\n maxHeight: 200,\n }}\n value={value}\n baseClass='input-box'\n ref={ref}\n onFocus={(e: any) => {\n focused ?? setFocused(true)\n onFocus && onFocus(e)\n }}\n onBlur={(e: any) => {\n focused ?? setFocused(false)\n onBlur && onBlur(e)\n }}\n />\n </Tag>\n {endIcon && <Tag\n flex={\"0 0 auto\"}\n sxr={{\n height: \"100%\",\n alignItems: 'center',\n justifyContent: \"center\",\n display: 'flex',\n color: error ? \"danger.primary\" : \"text.secondary\",\n }}\n baseClass=\"input-end-icon\"\n >{endIcon}</Tag>}\n </Tag>\n {helperText && <Text\n pl={.5}\n className=\"input-helper-text\"\n fontSize=\"small\"\n color={error ? \"danger.primary\" : \"text.primary\"}\n >{helperText}</Text>}\n </Tag>\n )\n})\n\nexport default Input\n"],"names":[],"mappings":";;;;;;;;;AAyBA;;AAAsE;;;AAwBlE;AAAe;AACf;AAAa;AACb;AAAmB;AACnB;AAAW;AACX;AAAa;AACb;AAAgB;AAChB;AAAU;AACV;AAAU;AACV;AAAa;AACb;AAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAGA;AACA;;;AAGA;AACA;;;;;AAMA;AAEA;AACI;AAAU;AACV;;AAEI;AACI;;AACG;AACH;;;AAEA;;;AAGZ;AAEA;AACI;AACI;AACA;AACA;AACH;AACD;AACI;AACA;AACA;AACH;AACD;AACI;AACA;AACA;AACH;;AAGL;;;;;AAKI;AACI;AACA;AACI;AACH;;;;AAKL;;AAEK;;AAET;AAEA;AAOgB;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAYI;AACA;AACA;AACA;;AAEH;AAMG;AACA;AACA;;AAEA;AACI;AACH;AACD;AACI;;AAEA;AACI;;AAQJ;AACA;AACA;;;AAGA;AACA;AACA;AACH;;AAMG;AACJ;;AAGI;AACJ;AAMA;AACA;AACA;AACA;;AAEH;AAYrB;;"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/Input/index.tsx"],"sourcesContent":["\"use client\";\nimport React, { ReactElement, useEffect, useMemo, useState } from 'react';\nimport { Tag, TagProps, TagComponentType, UseColorTemplateColor, useBreakpointPropsType, useInterface, useBreakpointProps, useMergeRefs } from '@xanui/core';\n\nexport type InputProps<T extends TagComponentType = \"div\"> = Omit<TagProps<T>, \"size\" | \"color\"> & {\n value?: string;\n type?: TagProps<'input'>['type'];\n name?: string;\n placeholder?: string;\n readOnly?: boolean;\n autoFocus?: boolean;\n autoComplete?: string;\n\n\n onFocus?: (e: React.FocusEvent<any>) => void;\n onBlur?: (e: React.FocusEvent<any>) => void;\n onChange?: (e: React.ChangeEvent<any>) => void;\n onInput?: (e: React.FormEvent<any>) => void;\n onKeyDown?: (e: React.KeyboardEvent<any>) => void;\n onKeyUp?: (e: React.KeyboardEvent<any>) => void;\n\n rows?: useBreakpointPropsType<number>;\n minRows?: useBreakpointPropsType<number>;\n maxRows?: useBreakpointPropsType<number>;\n fullWidth?: boolean;\n\n startIcon?: useBreakpointPropsType<ReactElement>;\n endIcon?: useBreakpointPropsType<ReactElement>;\n iconPlacement?: useBreakpointPropsType<\"start\" | \"center\" | \"end\">;\n focused?: boolean;\n color?: useBreakpointPropsType<Omit<UseColorTemplateColor, \"default\">>;\n variant?: useBreakpointPropsType<\"fill\" | \"outline\" | \"text\">;\n error?: boolean;\n helperText?: useBreakpointPropsType<string>;\n multiline?: boolean;\n size?: useBreakpointPropsType<\"small\" | \"medium\" | \"large\">;\n\n refs?: {\n rootContainer?: React.Ref<\"div\">;\n startIcon?: React.Ref<ReactElement>;\n endIcon?: React.Ref<ReactElement>;\n inputContainer?: React.Ref<\"div\">;\n input?: React.Ref<'input' | 'textarea'>;\n helperText?: React.Ref<\"div\">;\n };\n\n slotProps?: {\n rootContainer?: Omit<TagProps<\"div\">, \"children\">;\n startIcon?: Omit<TagProps<'div'>, \"children\">;\n endIcon?: Omit<TagProps<'div'>, \"children\">;\n inputContainer?: Omit<TagProps<\"div\">, \"children\">;\n helperText?: Omit<TagProps<\"div\">, \"children\">;\n input?: Partial<TagProps<T>>;\n }\n}\n\nconst Input = React.forwardRef(<T extends TagComponentType = \"div\">({ value, refs, ...props }: InputProps<T>, ref?: React.Ref<any>) => {\n let [{\n startIcon,\n endIcon,\n iconPlacement,\n color,\n\n name,\n placeholder,\n type,\n readOnly,\n autoFocus,\n autoComplete,\n onFocus,\n onBlur,\n onChange,\n onKeyDown,\n onKeyUp,\n\n focused,\n disabled,\n variant,\n error,\n helperText,\n multiline,\n size,\n rows,\n minRows,\n maxRows,\n fullWidth,\n slotProps,\n\n ...rest\n }, theme] = useInterface<any>(\"Input\", props, {})\n\n const _p: any = {}\n if (startIcon) _p.startIcon = startIcon\n if (endIcon) _p.endIcon = endIcon\n if (iconPlacement) _p.iconPlacement = iconPlacement\n if (color) _p.color = color\n if (variant) _p.variant = variant\n if (helperText) _p.helperText = helperText\n if (size) _p.size = size\n if (rows) _p.rows = rows\n if (minRows) _p.minRows = minRows\n if (maxRows) _p.maxRows = maxRows\n const p: any = useBreakpointProps(_p)\n startIcon = p.startIcon\n endIcon = p.endIcon\n iconPlacement = p.iconPlacement\n color = p.color ?? \"brand\"\n variant = p.variant ?? \"fill\"\n helperText = p.helperText\n size = p.size ?? 'medium'\n rows = p.rows\n minRows = p.minRows\n maxRows = p.maxRows\n\n iconPlacement ??= multiline ? \"end\" : \"center\"\n if (!value) iconPlacement = 'center'\n\n const [_focused, setFocused] = useState(false)\n let _focus = focused || _focused\n const inputRef = React.useRef<HTMLInputElement | HTMLTextAreaElement>(null);\n const inputMergeRef = useMergeRefs(inputRef, refs?.input as any);\n\n useEffect(() => {\n if (autoFocus) {\n setTimeout(() => {\n inputRef.current?.focus()\n }, 100);\n }\n }, [autoFocus])\n\n let _rows = useMemo(() => {\n if (rows) return rows\n if (value && multiline) {\n let lines = (value as string).split(`\\n`).length\n if (minRows && minRows > lines) {\n return minRows\n } else if (maxRows && maxRows < lines) {\n return maxRows\n } else {\n return lines\n }\n }\n }, [value]) || 1\n\n const sizes: any = {\n small: {\n height: 40,\n gap: .5,\n fontSize: 'button',\n },\n medium: {\n height: 48,\n gap: 1,\n fontSize: \"text\"\n },\n large: {\n height: 52,\n gap: 1,\n fontSize: 'big'\n }\n }\n\n const _size = sizes[size]\n let borderColor = _focus ? color : (variant === \"fill\" ? \"transparent\" : \"divider\")\n borderColor = error ? \"danger.primary\" : borderColor\n let multiprops: any = {}\n if (multiline) {\n multiprops = {\n rows: _rows,\n sx: {\n resize: \"none\"\n }\n }\n }\n\n return (\n <Tag\n width={fullWidth ? \"100%\" : undefined}\n {...rest}\n ref={ref}\n baseClass={'input-root'}\n classNames={{\n 'input-full-width': fullWidth || false,\n 'input-focused': _focus,\n 'input-error': error || false,\n [`input-variant-${variant}`]: true,\n [`input-size-${size}`]: true,\n }}\n >\n <Tag\n {...slotProps?.rootContainer}\n ref={refs?.rootContainer}\n baseClass='root-container'\n sxr={{\n width: \"100%\",\n display: \"flex\",\n flexDirection: \"row\",\n alignItems: iconPlacement === 'center' ? iconPlacement : `flex-${iconPlacement}`,\n flexWrap: \"nowrap\",\n transitionProperty: \"border, box-shadow, background\",\n bgcolor: error ? \"danger.soft.primary\" : variant === \"fill\" ? \"background.secondary\" : \"background.primary\",\n border: variant === \"text\" ? 0 : \"1px solid\",\n borderColor: borderColor,\n borderRadius: 1,\n px: 1,\n py: .5,\n }}\n disabled={disabled || false}\n {..._size}\n height={multiline ? \"auto\" : _size.height}\n minHeight={_size.height}\n >\n {startIcon && <Tag\n {...slotProps?.startIcon}\n ref={refs?.startIcon}\n flex={\"0 0 auto\"}\n sxr={{\n height: \"100%\",\n alignItems: 'center',\n justifyContent: \"center\",\n display: \"flex\",\n color: error ? \"danger.primary\" : \"text.secondary\",\n }}\n baseClass=\"input-start-icon\"\n >{startIcon}</Tag>}\n <Tag\n {...slotProps?.inputContainer}\n ref={refs?.inputContainer}\n baseClass='input-container'\n flex={1}\n sxr={{\n width: \"100%\",\n display: \"flex\",\n alignItems: \"center\",\n flex: 1,\n minHeight: _size.height,\n \"& textarea\": {\n resize: \"none\"\n },\n \"& input:-webkit-autofill,& input:-webkit-autofill:hover, & input:-webkit-autofill:focus,& input:-webkit-autofill:active\": {\n \"-webkit-text-fill-color\": \"text.primary\",\n \"box-shadow\": `0 0 0px 1000px ${variant === \"fill\" ? theme.colors.background.secondary : theme.colors.background.primary} inset`,\n transition: \"background-color 5000s ease-in-out 0s\"\n } as any\n }}\n >\n <Tag\n {...slotProps?.input}\n ref={inputMergeRef}\n baseClass='input'\n component={multiline ? 'textarea' : 'input'}\n {...multiprops}\n sxr={{\n border: 0,\n outline: 0,\n bgcolor: \"transparent\",\n color: error ? \"danger.primary\" : \"text.primary\",\n fontSize: _size.fontSize,\n height: multiline ? \"auto\" : _size.height + \"px!important\",\n width: \"100%\",\n maxHeight: 200,\n }}\n value={value}\n onChange={onChange}\n onFocus={(e: any) => {\n focused ?? setFocused(true)\n onFocus && onFocus(e)\n }}\n onBlur={(e: any) => {\n focused ?? setFocused(false)\n onBlur && onBlur(e)\n }}\n onKeyDown={onKeyDown}\n onKeyUp={onKeyUp}\n name={name}\n placeholder={placeholder}\n type={type}\n readOnly={readOnly}\n autoComplete={autoComplete}\n />\n </Tag>\n {endIcon && <Tag\n {...slotProps?.endIcon}\n ref={refs?.endIcon}\n flex={\"0 0 auto\"}\n sxr={{\n height: \"100%\",\n alignItems: 'center',\n justifyContent: \"center\",\n display: 'flex',\n color: error ? \"danger.primary\" : \"text.secondary\",\n }}\n baseClass=\"input-end-icon\"\n >{endIcon}</Tag>}\n </Tag>\n {helperText && <Tag\n {...slotProps?.helperText}\n ref={refs?.helperText}\n baseClass=\"input-helper-text\"\n sxr={{\n color: error ? \"danger.primary\" : \"text.primary\",\n fontSize: \"small\",\n lineHeight: \"text\",\n fontWeight: 'text',\n pl: .5,\n }}\n >{helperText}</Tag>}\n </Tag>\n )\n})\n\nexport default Input\n"],"names":[],"mappings":";;;;;;;;AAwDA;;;AACI;;AAmCA;AAAe;AACf;AAAa;AACb;AAAmB;AACnB;AAAW;AACX;AAAa;AACb;AAAgB;AAChB;AAAU;AACV;AAAU;AACV;AAAa;AACb;AAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;;;AAGA;;AAEA;;;;;AAKY;;;AAGZ;AAEA;AACI;AAAU;AACV;;AAEI;AACI;;AACG;AACH;;;AAEA;;;AAGZ;AAEA;AACI;AACI;AACA;AACA;AACH;AACD;AACI;AACA;AACA;AACH;AACD;AACI;AACA;AACA;AACH;;AAGL;;;;;AAKI;AACI;AACA;AACI;AACH;;;;;AAYG;;AAEA;AACA;;AAQI;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAYI;AACA;AACA;AACA;;AAEH;AASG;AACA;AACA;AACA;;AAEA;AACI;AACH;AACD;AACI;;AAEA;AACI;AACX;AASO;AACA;AACA;;;AAGA;AACA;AACA;AACH;;AAKG;AACJ;;AAGI;;AAgBJ;AACA;AACA;AACA;;AAEH;;AAUD;AACA;AACA;AACA;AACH;AAIjB;;"}
|
package/Input/index.mjs
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { __rest } from 'tslib';
|
|
3
3
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
|
-
import React, {
|
|
5
|
-
import { useInterface, useBreakpointProps, Tag } from '@xanui/core';
|
|
6
|
-
import Text from '../Text/index.mjs';
|
|
4
|
+
import React, { useState, useEffect, useMemo } from 'react';
|
|
5
|
+
import { useInterface, useBreakpointProps, useMergeRefs, Tag } from '@xanui/core';
|
|
7
6
|
|
|
8
7
|
const Input = React.forwardRef((_a, ref) => {
|
|
9
8
|
var _b, _c, _d;
|
|
10
|
-
var { value } = _a, props = __rest(_a, ["value"]);
|
|
11
|
-
let [_e, theme] = useInterface("Input", props, {}), { startIcon, endIcon, iconPlacement,
|
|
9
|
+
var { value, refs } = _a, props = __rest(_a, ["value", "refs"]);
|
|
10
|
+
let [_e, theme] = useInterface("Input", props, {}), { startIcon, endIcon, iconPlacement, color, name, placeholder, type, readOnly, autoFocus, autoComplete, onFocus, onBlur, onChange, onKeyDown, onKeyUp, focused, disabled, variant, error, helperText, multiline, size, rows, minRows, maxRows, fullWidth, slotProps } = _e, rest = __rest(_e, ["startIcon", "endIcon", "iconPlacement", "color", "name", "placeholder", "type", "readOnly", "autoFocus", "autoComplete", "onFocus", "onBlur", "onChange", "onKeyDown", "onKeyUp", "focused", "disabled", "variant", "error", "helperText", "multiline", "size", "rows", "minRows", "maxRows", "fullWidth", "slotProps"]);
|
|
12
11
|
const _p = {};
|
|
13
12
|
if (startIcon)
|
|
14
13
|
_p.startIcon = startIcon;
|
|
@@ -41,18 +40,21 @@ const Input = React.forwardRef((_a, ref) => {
|
|
|
41
40
|
rows = p.rows;
|
|
42
41
|
minRows = p.minRows;
|
|
43
42
|
maxRows = p.maxRows;
|
|
44
|
-
ref !== null && ref !== void 0 ? ref : (ref = useRef(null));
|
|
45
43
|
iconPlacement !== null && iconPlacement !== void 0 ? iconPlacement : (iconPlacement = multiline ? "end" : "center");
|
|
46
44
|
if (!value)
|
|
47
45
|
iconPlacement = 'center';
|
|
48
46
|
const [_focused, setFocused] = useState(false);
|
|
49
|
-
const conRef = useRef(null);
|
|
50
47
|
let _focus = focused || _focused;
|
|
48
|
+
const inputRef = React.useRef(null);
|
|
49
|
+
const inputMergeRef = useMergeRefs(inputRef, refs === null || refs === void 0 ? void 0 : refs.input);
|
|
51
50
|
useEffect(() => {
|
|
52
|
-
if (
|
|
53
|
-
|
|
51
|
+
if (autoFocus) {
|
|
52
|
+
setTimeout(() => {
|
|
53
|
+
var _a;
|
|
54
|
+
(_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
|
|
55
|
+
}, 100);
|
|
54
56
|
}
|
|
55
|
-
}, [
|
|
57
|
+
}, [autoFocus]);
|
|
56
58
|
let _rows = useMemo(() => {
|
|
57
59
|
if (rows)
|
|
58
60
|
return rows;
|
|
@@ -98,18 +100,18 @@ const Input = React.forwardRef((_a, ref) => {
|
|
|
98
100
|
}
|
|
99
101
|
};
|
|
100
102
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
103
|
+
return (jsxs(Tag, Object.assign({ width: fullWidth ? "100%" : undefined }, rest, { ref: ref, baseClass: 'input-root', classNames: {
|
|
104
|
+
'input-full-width': fullWidth || false,
|
|
105
|
+
'input-focused': _focus,
|
|
106
|
+
'input-error': error || false,
|
|
107
|
+
[`input-variant-${variant}`]: true,
|
|
108
|
+
[`input-size-${size}`]: true,
|
|
109
|
+
}, children: [jsxs(Tag, Object.assign({}, slotProps === null || slotProps === void 0 ? void 0 : slotProps.rootContainer, { ref: refs === null || refs === void 0 ? void 0 : refs.rootContainer, baseClass: 'root-container', sxr: {
|
|
110
|
+
width: "100%",
|
|
108
111
|
display: "flex",
|
|
109
112
|
flexDirection: "row",
|
|
110
113
|
alignItems: iconPlacement === 'center' ? iconPlacement : `flex-${iconPlacement}`,
|
|
111
114
|
flexWrap: "nowrap",
|
|
112
|
-
// minWidth: 100,
|
|
113
115
|
transitionProperty: "border, box-shadow, background",
|
|
114
116
|
bgcolor: error ? "danger.soft.primary" : variant === "fill" ? "background.secondary" : "background.primary",
|
|
115
117
|
border: variant === "text" ? 0 : "1px solid",
|
|
@@ -117,13 +119,14 @@ const Input = React.forwardRef((_a, ref) => {
|
|
|
117
119
|
borderRadius: 1,
|
|
118
120
|
px: 1,
|
|
119
121
|
py: .5,
|
|
120
|
-
},
|
|
122
|
+
}, disabled: disabled || false }, _size, { height: multiline ? "auto" : _size.height, minHeight: _size.height, children: [startIcon && jsx(Tag, Object.assign({}, slotProps === null || slotProps === void 0 ? void 0 : slotProps.startIcon, { ref: refs === null || refs === void 0 ? void 0 : refs.startIcon, flex: "0 0 auto", sxr: {
|
|
121
123
|
height: "100%",
|
|
122
124
|
alignItems: 'center',
|
|
123
125
|
justifyContent: "center",
|
|
124
126
|
display: "flex",
|
|
125
127
|
color: error ? "danger.primary" : "text.secondary",
|
|
126
|
-
}, baseClass: "input-start-icon", children: startIcon }), jsx(Tag, { flex: 1, sxr: {
|
|
128
|
+
}, baseClass: "input-start-icon", children: startIcon })), jsx(Tag, Object.assign({}, slotProps === null || slotProps === void 0 ? void 0 : slotProps.inputContainer, { ref: refs === null || refs === void 0 ? void 0 : refs.inputContainer, baseClass: 'input-container', flex: 1, sxr: {
|
|
129
|
+
width: "100%",
|
|
127
130
|
display: "flex",
|
|
128
131
|
alignItems: "center",
|
|
129
132
|
flex: 1,
|
|
@@ -136,7 +139,7 @@ const Input = React.forwardRef((_a, ref) => {
|
|
|
136
139
|
"box-shadow": `0 0 0px 1000px ${variant === "fill" ? theme.colors.background.secondary : theme.colors.background.primary} inset`,
|
|
137
140
|
transition: "background-color 5000s ease-in-out 0s"
|
|
138
141
|
}
|
|
139
|
-
}, children: jsx(Tag, Object.assign({ component: multiline ? 'textarea' : 'input' }, multiprops,
|
|
142
|
+
}, children: jsx(Tag, Object.assign({}, slotProps === null || slotProps === void 0 ? void 0 : slotProps.input, { ref: inputMergeRef, baseClass: 'input', component: multiline ? 'textarea' : 'input' }, multiprops, { sxr: {
|
|
140
143
|
border: 0,
|
|
141
144
|
outline: 0,
|
|
142
145
|
bgcolor: "transparent",
|
|
@@ -145,19 +148,25 @@ const Input = React.forwardRef((_a, ref) => {
|
|
|
145
148
|
height: multiline ? "auto" : _size.height + "px!important",
|
|
146
149
|
width: "100%",
|
|
147
150
|
maxHeight: 200,
|
|
148
|
-
}, value: value,
|
|
151
|
+
}, value: value, onChange: onChange, onFocus: (e) => {
|
|
149
152
|
focused !== null && focused !== void 0 ? focused : setFocused(true);
|
|
150
153
|
onFocus && onFocus(e);
|
|
151
154
|
}, onBlur: (e) => {
|
|
152
155
|
focused !== null && focused !== void 0 ? focused : setFocused(false);
|
|
153
156
|
onBlur && onBlur(e);
|
|
154
|
-
} })) }), endIcon && jsx(Tag, { flex: "0 0 auto", sxr: {
|
|
157
|
+
}, onKeyDown: onKeyDown, onKeyUp: onKeyUp, name: name, placeholder: placeholder, type: type, readOnly: readOnly, autoComplete: autoComplete })) })), endIcon && jsx(Tag, Object.assign({}, slotProps === null || slotProps === void 0 ? void 0 : slotProps.endIcon, { ref: refs === null || refs === void 0 ? void 0 : refs.endIcon, flex: "0 0 auto", sxr: {
|
|
155
158
|
height: "100%",
|
|
156
159
|
alignItems: 'center',
|
|
157
160
|
justifyContent: "center",
|
|
158
161
|
display: 'flex',
|
|
159
162
|
color: error ? "danger.primary" : "text.secondary",
|
|
160
|
-
}, baseClass: "input-end-icon", children: endIcon })] })), helperText && jsx(
|
|
163
|
+
}, baseClass: "input-end-icon", children: endIcon }))] })), helperText && jsx(Tag, Object.assign({}, slotProps === null || slotProps === void 0 ? void 0 : slotProps.helperText, { ref: refs === null || refs === void 0 ? void 0 : refs.helperText, baseClass: "input-helper-text", sxr: {
|
|
164
|
+
color: error ? "danger.primary" : "text.primary",
|
|
165
|
+
fontSize: "small",
|
|
166
|
+
lineHeight: "text",
|
|
167
|
+
fontWeight: 'text',
|
|
168
|
+
pl: .5,
|
|
169
|
+
}, children: helperText }))] })));
|
|
161
170
|
});
|
|
162
171
|
|
|
163
172
|
export { Input as default };
|
package/Input/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../../src/Input/index.tsx"],"sourcesContent":["\"use client\";\nimport React, { MutableRefObject, ReactElement, useEffect, useMemo, useRef, useState } from 'react';\nimport { Tag, TagProps, TagComponentType, UseColorTemplateColor, useBreakpointPropsType, useInterface, useBreakpointProps } from '@xanui/core';\nimport Text from '../Text';\n\nexport type InputProps<T extends TagComponentType = \"input\"> = Omit<TagProps<T>, \"size\" | \"color\"> & {\n startIcon?: useBreakpointPropsType<ReactElement>;\n endIcon?: useBreakpointPropsType<ReactElement>;\n iconPlacement?: useBreakpointPropsType<\"start\" | \"center\" | \"end\">;\n focused?: boolean;\n color?: useBreakpointPropsType<Omit<UseColorTemplateColor, \"default\">>;\n containerRef?: MutableRefObject<HTMLDivElement | undefined>;\n variant?: useBreakpointPropsType<\"fill\" | \"outline\" | \"text\">;\n error?: boolean;\n helperText?: useBreakpointPropsType<string>;\n multiline?: boolean;\n size?: useBreakpointPropsType<\"small\" | \"medium\" | \"large\">;\n rows?: useBreakpointPropsType<number>;\n minRows?: useBreakpointPropsType<number>;\n maxRows?: useBreakpointPropsType<number>;\n slotProps?: {\n container?: Omit<TagProps<\"div\">, \"children\">\n }\n}\n\nconst Input = React.forwardRef(<T extends TagComponentType = \"input\">({ value, ...props }: InputProps<T>, ref?: React.Ref<any>) => {\n let [{\n startIcon,\n endIcon,\n iconPlacement,\n onFocus,\n color,\n onBlur,\n focused,\n containerRef,\n disabled,\n variant,\n error,\n helperText,\n multiline,\n size,\n rows,\n minRows,\n maxRows,\n slotProps,\n ...rest\n }, theme] = useInterface<any>(\"Input\", props, {})\n\n const _p: any = {}\n if (startIcon) _p.startIcon = startIcon\n if (endIcon) _p.endIcon = endIcon\n if (iconPlacement) _p.iconPlacement = iconPlacement\n if (color) _p.color = color\n if (variant) _p.variant = variant\n if (helperText) _p.helperText = helperText\n if (size) _p.size = size\n if (rows) _p.rows = rows\n if (minRows) _p.minRows = minRows\n if (maxRows) _p.maxRows = maxRows\n const p: any = useBreakpointProps(_p)\n startIcon = p.startIcon\n endIcon = p.endIcon\n iconPlacement = p.iconPlacement\n color = p.color ?? \"brand\"\n variant = p.variant ?? \"fill\"\n helperText = p.helperText\n size = p.size ?? 'medium'\n rows = p.rows\n minRows = p.minRows\n maxRows = p.maxRows\n\n ref ??= useRef(null);\n iconPlacement ??= multiline ? \"end\" : \"center\"\n if (!value) iconPlacement = 'center'\n\n const [_focused, setFocused] = useState(false)\n const conRef: any = useRef(null)\n let _focus = focused || _focused\n\n useEffect(() => {\n if (containerRef) {\n (containerRef as any).current = conRef?.current\n }\n }, [containerRef])\n\n let _rows = useMemo(() => {\n if (rows) return rows\n if (value && multiline) {\n let lines = (value as string).split(`\\n`).length\n if (minRows && minRows > lines) {\n return minRows\n } else if (maxRows && maxRows < lines) {\n return maxRows\n } else {\n return lines\n }\n }\n }, [value]) || 1\n\n const sizes: any = {\n small: {\n height: 40,\n gap: .5,\n fontSize: 'button',\n },\n medium: {\n height: 48,\n gap: 1,\n fontSize: \"text\"\n },\n large: {\n height: 52,\n gap: 1,\n fontSize: 'big'\n }\n }\n\n const _size = sizes[size]\n let borderColor = _focus ? color : (variant === \"fill\" ? \"transparent\" : \"divider\")\n borderColor = error ? \"danger.primary\" : borderColor\n let multiprops: any = {}\n if (multiline) {\n multiprops = {\n rows: _rows,\n sx: {\n resize: \"none\"\n }\n }\n }\n\n useEffect(() => {\n if ((ref as any).current) {\n (ref as any).current.style.height = \"auto\";\n (ref as any).current.style.height = `${(ref as any).current.scrollHeight}px`;\n }\n }, [value]);\n\n return (\n <Tag\n baseClass={`input${_focus ? \" input-focused\" : \"\"}`}\n >\n <Tag\n {...slotProps?.container}\n sxr={{\n display: \"flex\",\n flexDirection: \"row\",\n alignItems: iconPlacement === 'center' ? iconPlacement : `flex-${iconPlacement}`,\n flexWrap: \"nowrap\",\n // minWidth: 100,\n transitionProperty: \"border, box-shadow, background\",\n bgcolor: error ? \"danger.soft.primary\" : variant === \"fill\" ? \"background.secondary\" : \"background.primary\",\n border: variant === \"text\" ? 0 : \"1px solid\",\n borderColor: borderColor,\n borderRadius: 1,\n px: 1,\n py: .5,\n }}\n baseClass='input-container'\n disabled={disabled || false}\n ref={conRef}\n {..._size}\n height={multiline ? \"auto\" : _size.height}\n minHeight={_size.height}\n >\n {startIcon && <Tag\n flex={\"0 0 auto\"}\n sxr={{\n height: \"100%\",\n alignItems: 'center',\n justifyContent: \"center\",\n display: \"flex\",\n color: error ? \"danger.primary\" : \"text.secondary\",\n }}\n baseClass=\"input-start-icon\"\n >{startIcon}</Tag>}\n <Tag\n flex={1}\n sxr={{\n display: \"flex\",\n alignItems: \"center\",\n flex: 1,\n minHeight: _size.height,\n \"& textarea\": {\n resize: \"none\"\n },\n \"& input:-webkit-autofill,& input:-webkit-autofill:hover, & input:-webkit-autofill:focus,& input:-webkit-autofill:active\": {\n \"-webkit-text-fill-color\": \"text.primary\",\n \"box-shadow\": `0 0 0px 1000px ${variant === \"fill\" ? theme.colors.background.secondary : theme.colors.background.primary} inset`,\n transition: \"background-color 5000s ease-in-out 0s\"\n } as any\n }}\n >\n <Tag\n component={multiline ? 'textarea' : 'input'}\n {...multiprops}\n {...rest}\n sxr={{\n border: 0,\n outline: 0,\n bgcolor: \"transparent\",\n color: error ? \"danger.primary\" : \"text.primary\",\n fontSize: _size.fontSize,\n height: multiline ? \"auto\" : _size.height + \"px!important\",\n width: \"100%\",\n maxHeight: 200,\n }}\n value={value}\n baseClass='input-box'\n ref={ref}\n onFocus={(e: any) => {\n focused ?? setFocused(true)\n onFocus && onFocus(e)\n }}\n onBlur={(e: any) => {\n focused ?? setFocused(false)\n onBlur && onBlur(e)\n }}\n />\n </Tag>\n {endIcon && <Tag\n flex={\"0 0 auto\"}\n sxr={{\n height: \"100%\",\n alignItems: 'center',\n justifyContent: \"center\",\n display: 'flex',\n color: error ? \"danger.primary\" : \"text.secondary\",\n }}\n baseClass=\"input-end-icon\"\n >{endIcon}</Tag>}\n </Tag>\n {helperText && <Text\n pl={.5}\n className=\"input-helper-text\"\n fontSize=\"small\"\n color={error ? \"danger.primary\" : \"text.primary\"}\n >{helperText}</Text>}\n </Tag>\n )\n})\n\nexport default Input\n"],"names":[],"mappings":";;;;;;;AAyBA;;AAAsE;;;AAwBlE;AAAe;AACf;AAAa;AACb;AAAmB;AACnB;AAAW;AACX;AAAa;AACb;AAAgB;AAChB;AAAU;AACV;AAAU;AACV;AAAa;AACb;AAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAGA;AACA;;;AAGA;AACA;;;;;AAMA;AAEA;AACI;AAAU;AACV;;AAEI;AACI;;AACG;AACH;;;AAEA;;;AAGZ;AAEA;AACI;AACI;AACA;AACA;AACH;AACD;AACI;AACA;AACA;AACH;AACD;AACI;AACA;AACA;AACH;;AAGL;;;;;AAKI;AACI;AACA;AACI;AACH;;;;AAKL;;AAEK;;AAET;AAEA;AAOgB;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;;AAYI;AACA;AACA;AACA;;AAEH;AAMG;AACA;AACA;;AAEA;AACI;AACH;AACD;AACI;;AAEA;AACI;;AAQJ;AACA;AACA;;;AAGA;AACA;AACA;AACH;;AAMG;AACJ;;AAGI;AACJ;AAMA;AACA;AACA;AACA;;AAEH;AAYrB;;"}
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../src/Input/index.tsx"],"sourcesContent":["\"use client\";\nimport React, { ReactElement, useEffect, useMemo, useState } from 'react';\nimport { Tag, TagProps, TagComponentType, UseColorTemplateColor, useBreakpointPropsType, useInterface, useBreakpointProps, useMergeRefs } from '@xanui/core';\n\nexport type InputProps<T extends TagComponentType = \"div\"> = Omit<TagProps<T>, \"size\" | \"color\"> & {\n value?: string;\n type?: TagProps<'input'>['type'];\n name?: string;\n placeholder?: string;\n readOnly?: boolean;\n autoFocus?: boolean;\n autoComplete?: string;\n\n\n onFocus?: (e: React.FocusEvent<any>) => void;\n onBlur?: (e: React.FocusEvent<any>) => void;\n onChange?: (e: React.ChangeEvent<any>) => void;\n onInput?: (e: React.FormEvent<any>) => void;\n onKeyDown?: (e: React.KeyboardEvent<any>) => void;\n onKeyUp?: (e: React.KeyboardEvent<any>) => void;\n\n rows?: useBreakpointPropsType<number>;\n minRows?: useBreakpointPropsType<number>;\n maxRows?: useBreakpointPropsType<number>;\n fullWidth?: boolean;\n\n startIcon?: useBreakpointPropsType<ReactElement>;\n endIcon?: useBreakpointPropsType<ReactElement>;\n iconPlacement?: useBreakpointPropsType<\"start\" | \"center\" | \"end\">;\n focused?: boolean;\n color?: useBreakpointPropsType<Omit<UseColorTemplateColor, \"default\">>;\n variant?: useBreakpointPropsType<\"fill\" | \"outline\" | \"text\">;\n error?: boolean;\n helperText?: useBreakpointPropsType<string>;\n multiline?: boolean;\n size?: useBreakpointPropsType<\"small\" | \"medium\" | \"large\">;\n\n refs?: {\n rootContainer?: React.Ref<\"div\">;\n startIcon?: React.Ref<ReactElement>;\n endIcon?: React.Ref<ReactElement>;\n inputContainer?: React.Ref<\"div\">;\n input?: React.Ref<'input' | 'textarea'>;\n helperText?: React.Ref<\"div\">;\n };\n\n slotProps?: {\n rootContainer?: Omit<TagProps<\"div\">, \"children\">;\n startIcon?: Omit<TagProps<'div'>, \"children\">;\n endIcon?: Omit<TagProps<'div'>, \"children\">;\n inputContainer?: Omit<TagProps<\"div\">, \"children\">;\n helperText?: Omit<TagProps<\"div\">, \"children\">;\n input?: Partial<TagProps<T>>;\n }\n}\n\nconst Input = React.forwardRef(<T extends TagComponentType = \"div\">({ value, refs, ...props }: InputProps<T>, ref?: React.Ref<any>) => {\n let [{\n startIcon,\n endIcon,\n iconPlacement,\n color,\n\n name,\n placeholder,\n type,\n readOnly,\n autoFocus,\n autoComplete,\n onFocus,\n onBlur,\n onChange,\n onKeyDown,\n onKeyUp,\n\n focused,\n disabled,\n variant,\n error,\n helperText,\n multiline,\n size,\n rows,\n minRows,\n maxRows,\n fullWidth,\n slotProps,\n\n ...rest\n }, theme] = useInterface<any>(\"Input\", props, {})\n\n const _p: any = {}\n if (startIcon) _p.startIcon = startIcon\n if (endIcon) _p.endIcon = endIcon\n if (iconPlacement) _p.iconPlacement = iconPlacement\n if (color) _p.color = color\n if (variant) _p.variant = variant\n if (helperText) _p.helperText = helperText\n if (size) _p.size = size\n if (rows) _p.rows = rows\n if (minRows) _p.minRows = minRows\n if (maxRows) _p.maxRows = maxRows\n const p: any = useBreakpointProps(_p)\n startIcon = p.startIcon\n endIcon = p.endIcon\n iconPlacement = p.iconPlacement\n color = p.color ?? \"brand\"\n variant = p.variant ?? \"fill\"\n helperText = p.helperText\n size = p.size ?? 'medium'\n rows = p.rows\n minRows = p.minRows\n maxRows = p.maxRows\n\n iconPlacement ??= multiline ? \"end\" : \"center\"\n if (!value) iconPlacement = 'center'\n\n const [_focused, setFocused] = useState(false)\n let _focus = focused || _focused\n const inputRef = React.useRef<HTMLInputElement | HTMLTextAreaElement>(null);\n const inputMergeRef = useMergeRefs(inputRef, refs?.input as any);\n\n useEffect(() => {\n if (autoFocus) {\n setTimeout(() => {\n inputRef.current?.focus()\n }, 100);\n }\n }, [autoFocus])\n\n let _rows = useMemo(() => {\n if (rows) return rows\n if (value && multiline) {\n let lines = (value as string).split(`\\n`).length\n if (minRows && minRows > lines) {\n return minRows\n } else if (maxRows && maxRows < lines) {\n return maxRows\n } else {\n return lines\n }\n }\n }, [value]) || 1\n\n const sizes: any = {\n small: {\n height: 40,\n gap: .5,\n fontSize: 'button',\n },\n medium: {\n height: 48,\n gap: 1,\n fontSize: \"text\"\n },\n large: {\n height: 52,\n gap: 1,\n fontSize: 'big'\n }\n }\n\n const _size = sizes[size]\n let borderColor = _focus ? color : (variant === \"fill\" ? \"transparent\" : \"divider\")\n borderColor = error ? \"danger.primary\" : borderColor\n let multiprops: any = {}\n if (multiline) {\n multiprops = {\n rows: _rows,\n sx: {\n resize: \"none\"\n }\n }\n }\n\n return (\n <Tag\n width={fullWidth ? \"100%\" : undefined}\n {...rest}\n ref={ref}\n baseClass={'input-root'}\n classNames={{\n 'input-full-width': fullWidth || false,\n 'input-focused': _focus,\n 'input-error': error || false,\n [`input-variant-${variant}`]: true,\n [`input-size-${size}`]: true,\n }}\n >\n <Tag\n {...slotProps?.rootContainer}\n ref={refs?.rootContainer}\n baseClass='root-container'\n sxr={{\n width: \"100%\",\n display: \"flex\",\n flexDirection: \"row\",\n alignItems: iconPlacement === 'center' ? iconPlacement : `flex-${iconPlacement}`,\n flexWrap: \"nowrap\",\n transitionProperty: \"border, box-shadow, background\",\n bgcolor: error ? \"danger.soft.primary\" : variant === \"fill\" ? \"background.secondary\" : \"background.primary\",\n border: variant === \"text\" ? 0 : \"1px solid\",\n borderColor: borderColor,\n borderRadius: 1,\n px: 1,\n py: .5,\n }}\n disabled={disabled || false}\n {..._size}\n height={multiline ? \"auto\" : _size.height}\n minHeight={_size.height}\n >\n {startIcon && <Tag\n {...slotProps?.startIcon}\n ref={refs?.startIcon}\n flex={\"0 0 auto\"}\n sxr={{\n height: \"100%\",\n alignItems: 'center',\n justifyContent: \"center\",\n display: \"flex\",\n color: error ? \"danger.primary\" : \"text.secondary\",\n }}\n baseClass=\"input-start-icon\"\n >{startIcon}</Tag>}\n <Tag\n {...slotProps?.inputContainer}\n ref={refs?.inputContainer}\n baseClass='input-container'\n flex={1}\n sxr={{\n width: \"100%\",\n display: \"flex\",\n alignItems: \"center\",\n flex: 1,\n minHeight: _size.height,\n \"& textarea\": {\n resize: \"none\"\n },\n \"& input:-webkit-autofill,& input:-webkit-autofill:hover, & input:-webkit-autofill:focus,& input:-webkit-autofill:active\": {\n \"-webkit-text-fill-color\": \"text.primary\",\n \"box-shadow\": `0 0 0px 1000px ${variant === \"fill\" ? theme.colors.background.secondary : theme.colors.background.primary} inset`,\n transition: \"background-color 5000s ease-in-out 0s\"\n } as any\n }}\n >\n <Tag\n {...slotProps?.input}\n ref={inputMergeRef}\n baseClass='input'\n component={multiline ? 'textarea' : 'input'}\n {...multiprops}\n sxr={{\n border: 0,\n outline: 0,\n bgcolor: \"transparent\",\n color: error ? \"danger.primary\" : \"text.primary\",\n fontSize: _size.fontSize,\n height: multiline ? \"auto\" : _size.height + \"px!important\",\n width: \"100%\",\n maxHeight: 200,\n }}\n value={value}\n onChange={onChange}\n onFocus={(e: any) => {\n focused ?? setFocused(true)\n onFocus && onFocus(e)\n }}\n onBlur={(e: any) => {\n focused ?? setFocused(false)\n onBlur && onBlur(e)\n }}\n onKeyDown={onKeyDown}\n onKeyUp={onKeyUp}\n name={name}\n placeholder={placeholder}\n type={type}\n readOnly={readOnly}\n autoComplete={autoComplete}\n />\n </Tag>\n {endIcon && <Tag\n {...slotProps?.endIcon}\n ref={refs?.endIcon}\n flex={\"0 0 auto\"}\n sxr={{\n height: \"100%\",\n alignItems: 'center',\n justifyContent: \"center\",\n display: 'flex',\n color: error ? \"danger.primary\" : \"text.secondary\",\n }}\n baseClass=\"input-end-icon\"\n >{endIcon}</Tag>}\n </Tag>\n {helperText && <Tag\n {...slotProps?.helperText}\n ref={refs?.helperText}\n baseClass=\"input-helper-text\"\n sxr={{\n color: error ? \"danger.primary\" : \"text.primary\",\n fontSize: \"small\",\n lineHeight: \"text\",\n fontWeight: 'text',\n pl: .5,\n }}\n >{helperText}</Tag>}\n </Tag>\n )\n})\n\nexport default Input\n"],"names":[],"mappings":";;;;;;AAwDA;;;AACI;;AAmCA;AAAe;AACf;AAAa;AACb;AAAmB;AACnB;AAAW;AACX;AAAa;AACb;AAAgB;AAChB;AAAU;AACV;AAAU;AACV;AAAa;AACb;AAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAEA;AACA;;;AAGA;;AAEA;;;;;AAKY;;;AAGZ;AAEA;AACI;AAAU;AACV;;AAEI;AACI;;AACG;AACH;;;AAEA;;;AAGZ;AAEA;AACI;AACI;AACA;AACA;AACH;AACD;AACI;AACA;AACA;AACH;AACD;AACI;AACA;AACA;AACH;;AAGL;;;;;AAKI;AACI;AACA;AACI;AACH;;;;;AAYG;;AAEA;AACA;;AAQI;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAYI;AACA;AACA;AACA;;AAEH;AASG;AACA;AACA;AACA;;AAEA;AACI;AACH;AACD;AACI;;AAEA;AACI;AACX;AASO;AACA;AACA;;;AAGA;AACA;AACA;AACH;;AAKG;AACJ;;AAGI;;AAgBJ;AACA;AACA;AACA;;AAEH;;AAUD;AACA;AACA;AACA;AACH;AAIjB;;"}
|
package/Menu/index.js
CHANGED
|
@@ -115,8 +115,10 @@ const Menu = (_a) => {
|
|
|
115
115
|
if (!closed && target && menuRef.current) {
|
|
116
116
|
const updatePosition = () => {
|
|
117
117
|
if (menuRef.current && target) {
|
|
118
|
-
|
|
119
|
-
|
|
118
|
+
requestAnimationFrame(() => {
|
|
119
|
+
const p = placeMenu(placement, menuRef.current, target);
|
|
120
|
+
setPlaced(p);
|
|
121
|
+
});
|
|
120
122
|
}
|
|
121
123
|
};
|
|
122
124
|
updatePosition();
|
|
@@ -127,7 +129,7 @@ const Menu = (_a) => {
|
|
|
127
129
|
window.removeEventListener("scroll", updatePosition, true);
|
|
128
130
|
};
|
|
129
131
|
}
|
|
130
|
-
return
|
|
132
|
+
return;
|
|
131
133
|
}, [closed, target, placement]);
|
|
132
134
|
if (closed)
|
|
133
135
|
return null;
|
package/Menu/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/Menu/index.tsx"],"sourcesContent":["\"use client\";\nimport { ReactNode, useEffect, useState, useRef } from \"react\";\nimport { Tag, TagProps, useBreakpointProps, useBreakpointPropsType, useInterface, TransitionProps, Transition } from \"@xanui/core\";\nimport Portal, { PortalProps } from \"../Portal\";\nimport ClickOutside from \"../ClickOutside\";\n\nexport type PlacementTypes =\n | \"top\"\n | \"top-left\"\n | \"top-right\"\n | \"bottom\"\n | \"bottom-left\"\n | \"bottom-right\"\n | \"right\"\n | \"right-top\"\n | \"right-bottom\"\n | \"left\"\n | \"left-top\"\n | \"left-bottom\";\n\nexport type MenuProps = {\n children?: ReactNode;\n target?: HTMLElement;\n placement?: useBreakpointPropsType<PlacementTypes>;\n zIndex?: number;\n onClickOutside?: (e: MouseEvent) => void;\n slotProps?: {\n transition?: Omit<TransitionProps, \"open\">;\n portal?: Omit<PortalProps, \"children\">;\n content?: Omit<TagProps<\"div\">, \"children\">;\n };\n};\n\nconst placements: PlacementTypes[] = [\n \"top\",\n \"top-left\",\n \"top-right\",\n \"bottom\",\n \"bottom-left\",\n \"bottom-right\",\n \"right\",\n \"right-top\",\n \"right-bottom\",\n \"left\",\n \"left-top\",\n \"left-bottom\",\n];\n\nconst getTransformOrigin = (placement: PlacementTypes) => {\n switch (placement) {\n case \"top\":\n return \"bottom\";\n case \"top-left\":\n return \"bottom left\";\n case \"top-right\":\n return \"bottom right\";\n case \"bottom\":\n return \"top\";\n case \"bottom-left\":\n return \"top left\";\n case \"bottom-right\":\n return \"top right\";\n case \"left\":\n return \"right\";\n case \"left-top\":\n return \"top right\";\n case \"left-bottom\":\n return \"bottom right\";\n case \"right\":\n return \"left\";\n case \"right-top\":\n return \"top left\";\n case \"right-bottom\":\n return \"bottom left\";\n default:\n return \"top\";\n }\n};\n\n// Compute coordinates for each placement\nconst computePosition = (\n placement: PlacementTypes,\n menu: HTMLElement,\n target: HTMLElement\n) => {\n const { width: mw, height: mh } = menu.getBoundingClientRect();\n const {\n top: tt,\n left: tl,\n bottom: tb,\n right: tr,\n width: tw,\n height: th,\n } = target.getBoundingClientRect();\n\n const positions: Record<PlacementTypes, { top: number; left: number }> = {\n \"bottom-left\": { top: tb, left: tl },\n \"bottom-right\": { top: tb, left: tr - mw },\n bottom: { top: tb, left: tl + (tw - mw) / 2 },\n\n \"top-left\": { top: tt - mh, left: tl },\n \"top-right\": { top: tt - mh, left: tr - mw },\n top: { top: tt - mh, left: tl + (tw - mw) / 2 },\n\n left: { top: tt + (th - mh) / 2, left: tl - mw },\n \"left-top\": { top: tt, left: tl - mw },\n \"left-bottom\": { top: tb - mh, left: tl - mw },\n\n right: { top: tt + (th - mh) / 2, left: tr },\n \"right-top\": { top: tt, left: tr },\n \"right-bottom\": { top: tb - mh, left: tr },\n };\n\n return positions[placement];\n};\n\n\n// Check if menu is off-screen\nconst isOffScreen = (menu: HTMLElement) => {\n const { x, y, width, height } = menu.getBoundingClientRect();\n return x < 0 || y < 0 || x + width > window.innerWidth || y + height > window.innerHeight;\n};\n\n// Try to place menu and fallback if off-screen\nconst placeMenu = (placement: PlacementTypes, menu: HTMLElement, target: HTMLElement) => {\n let pos = computePosition(placement, menu, target);\n menu.style.top = pos.top + \"px\";\n menu.style.left = pos.left + \"px\";\n\n if (isOffScreen(menu)) {\n for (const p of placements) {\n const fallbackPos = computePosition(p, menu, target);\n menu.style.top = fallbackPos.top + \"px\";\n menu.style.left = fallbackPos.left + \"px\";\n if (!isOffScreen(menu)) return p;\n }\n }\n return placement;\n};\n\nconst Menu = ({ children, target, ...props }: MenuProps) => {\n let [{ onClickOutside, placement, zIndex, slotProps }] = useInterface<any>(\"Menu\", props, {});\n const _p: any = {};\n if (placement) _p.placement = placement;\n const p: any = useBreakpointProps(_p);\n placement = p.placement || \"bottom-left\";\n\n const isOpen = Boolean(target);\n const [closed, setClosed] = useState(!isOpen);\n const [placed, setPlaced] = useState<PlacementTypes>(placement);\n const menuRef = useRef<HTMLDivElement>(null);\n\n // Open/close effect\n useEffect(() => {\n if (closed && isOpen) setClosed(false);\n }, [isOpen]);\n\n\n useEffect(() => {\n if (!closed && target && menuRef.current) {\n const updatePosition = () => {\n if (menuRef.current && target) {\n const p = placeMenu(placement!, menuRef.current, target);\n
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/Menu/index.tsx"],"sourcesContent":["\"use client\";\nimport { ReactNode, useEffect, useState, useRef } from \"react\";\nimport { Tag, TagProps, useBreakpointProps, useBreakpointPropsType, useInterface, TransitionProps, Transition } from \"@xanui/core\";\nimport Portal, { PortalProps } from \"../Portal\";\nimport ClickOutside from \"../ClickOutside\";\n\nexport type PlacementTypes =\n | \"top\"\n | \"top-left\"\n | \"top-right\"\n | \"bottom\"\n | \"bottom-left\"\n | \"bottom-right\"\n | \"right\"\n | \"right-top\"\n | \"right-bottom\"\n | \"left\"\n | \"left-top\"\n | \"left-bottom\";\n\nexport type MenuProps = {\n children?: ReactNode;\n target?: HTMLElement;\n placement?: useBreakpointPropsType<PlacementTypes>;\n zIndex?: number;\n onClickOutside?: (e: MouseEvent) => void;\n slotProps?: {\n transition?: Omit<TransitionProps, \"open\">;\n portal?: Omit<PortalProps, \"children\">;\n content?: Omit<TagProps<\"div\">, \"children\">;\n };\n};\n\nconst placements: PlacementTypes[] = [\n \"top\",\n \"top-left\",\n \"top-right\",\n \"bottom\",\n \"bottom-left\",\n \"bottom-right\",\n \"right\",\n \"right-top\",\n \"right-bottom\",\n \"left\",\n \"left-top\",\n \"left-bottom\",\n];\n\nconst getTransformOrigin = (placement: PlacementTypes) => {\n switch (placement) {\n case \"top\":\n return \"bottom\";\n case \"top-left\":\n return \"bottom left\";\n case \"top-right\":\n return \"bottom right\";\n case \"bottom\":\n return \"top\";\n case \"bottom-left\":\n return \"top left\";\n case \"bottom-right\":\n return \"top right\";\n case \"left\":\n return \"right\";\n case \"left-top\":\n return \"top right\";\n case \"left-bottom\":\n return \"bottom right\";\n case \"right\":\n return \"left\";\n case \"right-top\":\n return \"top left\";\n case \"right-bottom\":\n return \"bottom left\";\n default:\n return \"top\";\n }\n};\n\n// Compute coordinates for each placement\nconst computePosition = (\n placement: PlacementTypes,\n menu: HTMLElement,\n target: HTMLElement\n) => {\n const { width: mw, height: mh } = menu.getBoundingClientRect();\n const {\n top: tt,\n left: tl,\n bottom: tb,\n right: tr,\n width: tw,\n height: th,\n } = target.getBoundingClientRect();\n\n const positions: Record<PlacementTypes, { top: number; left: number }> = {\n \"bottom-left\": { top: tb, left: tl },\n \"bottom-right\": { top: tb, left: tr - mw },\n bottom: { top: tb, left: tl + (tw - mw) / 2 },\n\n \"top-left\": { top: tt - mh, left: tl },\n \"top-right\": { top: tt - mh, left: tr - mw },\n top: { top: tt - mh, left: tl + (tw - mw) / 2 },\n\n left: { top: tt + (th - mh) / 2, left: tl - mw },\n \"left-top\": { top: tt, left: tl - mw },\n \"left-bottom\": { top: tb - mh, left: tl - mw },\n\n right: { top: tt + (th - mh) / 2, left: tr },\n \"right-top\": { top: tt, left: tr },\n \"right-bottom\": { top: tb - mh, left: tr },\n };\n\n return positions[placement];\n};\n\n\n// Check if menu is off-screen\nconst isOffScreen = (menu: HTMLElement) => {\n const { x, y, width, height } = menu.getBoundingClientRect();\n return x < 0 || y < 0 || x + width > window.innerWidth || y + height > window.innerHeight;\n};\n\n// Try to place menu and fallback if off-screen\nconst placeMenu = (placement: PlacementTypes, menu: HTMLElement, target: HTMLElement) => {\n let pos = computePosition(placement, menu, target);\n menu.style.top = pos.top + \"px\";\n menu.style.left = pos.left + \"px\";\n\n if (isOffScreen(menu)) {\n for (const p of placements) {\n const fallbackPos = computePosition(p, menu, target);\n menu.style.top = fallbackPos.top + \"px\";\n menu.style.left = fallbackPos.left + \"px\";\n if (!isOffScreen(menu)) return p;\n }\n }\n return placement;\n};\n\nconst Menu = ({ children, target, ...props }: MenuProps) => {\n let [{ onClickOutside, placement, zIndex, slotProps }] = useInterface<any>(\"Menu\", props, {});\n const _p: any = {};\n if (placement) _p.placement = placement;\n const p: any = useBreakpointProps(_p);\n placement = p.placement || \"bottom-left\";\n\n const isOpen = Boolean(target);\n const [closed, setClosed] = useState(!isOpen);\n const [placed, setPlaced] = useState<PlacementTypes>(placement);\n const menuRef = useRef<HTMLDivElement>(null);\n\n // Open/close effect\n useEffect(() => {\n if (closed && isOpen) setClosed(false);\n }, [isOpen]);\n\n\n useEffect(() => {\n if (!closed && target && menuRef.current) {\n const updatePosition = () => {\n if (menuRef.current && target) {\n requestAnimationFrame(() => {\n const p = placeMenu(placement!, menuRef.current as any, target);\n setPlaced(p);\n });\n }\n };\n\n updatePosition();\n window.addEventListener(\"resize\", updatePosition);\n window.addEventListener(\"scroll\", updatePosition, true);\n\n return () => {\n window.removeEventListener(\"resize\", updatePosition);\n window.removeEventListener(\"scroll\", updatePosition, true);\n };\n }\n return\n }, [closed, target, placement]);\n\n\n if (closed) return null;\n\n return (\n <Portal {...slotProps?.portal}>\n <ClickOutside\n onClickOutside={(e: MouseEvent) => {\n if (e.target !== target) {\n onClickOutside && onClickOutside(e);\n }\n }}\n ref={menuRef}\n sx={{ position: \"fixed\", zIndex: 1500 + (zIndex || 0) }}\n >\n <Transition\n duration={200}\n easing=\"fast\"\n variant=\"grow\"\n {...slotProps?.transition}\n open={isOpen}\n onClosed={() => {\n setClosed(true);\n slotProps?.transition?.onClosed?.();\n }}\n >\n <Tag\n baseClass=\"menu-content\"\n {...slotProps?.content}\n sxr={{\n overflow: \"hidden\",\n bgcolor: \"background.primary\",\n shadow: 2,\n radius: 1,\n transformOrigin: getTransformOrigin(placed),\n ...slotProps?.content?.sx,\n }}\n >\n {children}\n </Tag>\n </Transition>\n </ClickOutside>\n </Portal>\n );\n};\n\nexport default Menu;\n"],"names":[],"mappings":";;;;;;;;;;AAiCA;;;;;;;;;;;;;;AAeA;;AAEQ;AACI;AACJ;AACI;AACJ;AACI;AACJ;AACI;AACJ;AACI;AACJ;AACI;AACJ;AACI;AACJ;AACI;AACJ;AACI;AACJ;AACI;AACJ;AACI;AACJ;AACI;AACJ;AACI;;AAEZ;AAEA;AACA;AAKI;AACA;AASA;;;AAGI;;AAGA;AACA;AAEA;;AAEA;AAEA;;;;AAKJ;AACJ;AAGA;AACA;AACI;;AAEJ;AAEA;AACA;;;;AAKI;AACI;;;;AAII;AAAwB;;;AAGhC;AACJ;AAEA;;;;;AAGI;AAAe;AACf;AACA;AAEA;;;AAGA;;;;;AAKA;;;;AAMY;;AAEQ;;AAEJ;;AAER;AAEA;AACA;;AAGA;AACI;;AAEJ;;;;AAMR;AAAY;;AAMI;AACI;;;;;;;AAmCxB;;"}
|
package/Menu/index.mjs
CHANGED
|
@@ -113,8 +113,10 @@ const Menu = (_a) => {
|
|
|
113
113
|
if (!closed && target && menuRef.current) {
|
|
114
114
|
const updatePosition = () => {
|
|
115
115
|
if (menuRef.current && target) {
|
|
116
|
-
|
|
117
|
-
|
|
116
|
+
requestAnimationFrame(() => {
|
|
117
|
+
const p = placeMenu(placement, menuRef.current, target);
|
|
118
|
+
setPlaced(p);
|
|
119
|
+
});
|
|
118
120
|
}
|
|
119
121
|
};
|
|
120
122
|
updatePosition();
|
|
@@ -125,7 +127,7 @@ const Menu = (_a) => {
|
|
|
125
127
|
window.removeEventListener("scroll", updatePosition, true);
|
|
126
128
|
};
|
|
127
129
|
}
|
|
128
|
-
return
|
|
130
|
+
return;
|
|
129
131
|
}, [closed, target, placement]);
|
|
130
132
|
if (closed)
|
|
131
133
|
return null;
|
package/Menu/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../../src/Menu/index.tsx"],"sourcesContent":["\"use client\";\nimport { ReactNode, useEffect, useState, useRef } from \"react\";\nimport { Tag, TagProps, useBreakpointProps, useBreakpointPropsType, useInterface, TransitionProps, Transition } from \"@xanui/core\";\nimport Portal, { PortalProps } from \"../Portal\";\nimport ClickOutside from \"../ClickOutside\";\n\nexport type PlacementTypes =\n | \"top\"\n | \"top-left\"\n | \"top-right\"\n | \"bottom\"\n | \"bottom-left\"\n | \"bottom-right\"\n | \"right\"\n | \"right-top\"\n | \"right-bottom\"\n | \"left\"\n | \"left-top\"\n | \"left-bottom\";\n\nexport type MenuProps = {\n children?: ReactNode;\n target?: HTMLElement;\n placement?: useBreakpointPropsType<PlacementTypes>;\n zIndex?: number;\n onClickOutside?: (e: MouseEvent) => void;\n slotProps?: {\n transition?: Omit<TransitionProps, \"open\">;\n portal?: Omit<PortalProps, \"children\">;\n content?: Omit<TagProps<\"div\">, \"children\">;\n };\n};\n\nconst placements: PlacementTypes[] = [\n \"top\",\n \"top-left\",\n \"top-right\",\n \"bottom\",\n \"bottom-left\",\n \"bottom-right\",\n \"right\",\n \"right-top\",\n \"right-bottom\",\n \"left\",\n \"left-top\",\n \"left-bottom\",\n];\n\nconst getTransformOrigin = (placement: PlacementTypes) => {\n switch (placement) {\n case \"top\":\n return \"bottom\";\n case \"top-left\":\n return \"bottom left\";\n case \"top-right\":\n return \"bottom right\";\n case \"bottom\":\n return \"top\";\n case \"bottom-left\":\n return \"top left\";\n case \"bottom-right\":\n return \"top right\";\n case \"left\":\n return \"right\";\n case \"left-top\":\n return \"top right\";\n case \"left-bottom\":\n return \"bottom right\";\n case \"right\":\n return \"left\";\n case \"right-top\":\n return \"top left\";\n case \"right-bottom\":\n return \"bottom left\";\n default:\n return \"top\";\n }\n};\n\n// Compute coordinates for each placement\nconst computePosition = (\n placement: PlacementTypes,\n menu: HTMLElement,\n target: HTMLElement\n) => {\n const { width: mw, height: mh } = menu.getBoundingClientRect();\n const {\n top: tt,\n left: tl,\n bottom: tb,\n right: tr,\n width: tw,\n height: th,\n } = target.getBoundingClientRect();\n\n const positions: Record<PlacementTypes, { top: number; left: number }> = {\n \"bottom-left\": { top: tb, left: tl },\n \"bottom-right\": { top: tb, left: tr - mw },\n bottom: { top: tb, left: tl + (tw - mw) / 2 },\n\n \"top-left\": { top: tt - mh, left: tl },\n \"top-right\": { top: tt - mh, left: tr - mw },\n top: { top: tt - mh, left: tl + (tw - mw) / 2 },\n\n left: { top: tt + (th - mh) / 2, left: tl - mw },\n \"left-top\": { top: tt, left: tl - mw },\n \"left-bottom\": { top: tb - mh, left: tl - mw },\n\n right: { top: tt + (th - mh) / 2, left: tr },\n \"right-top\": { top: tt, left: tr },\n \"right-bottom\": { top: tb - mh, left: tr },\n };\n\n return positions[placement];\n};\n\n\n// Check if menu is off-screen\nconst isOffScreen = (menu: HTMLElement) => {\n const { x, y, width, height } = menu.getBoundingClientRect();\n return x < 0 || y < 0 || x + width > window.innerWidth || y + height > window.innerHeight;\n};\n\n// Try to place menu and fallback if off-screen\nconst placeMenu = (placement: PlacementTypes, menu: HTMLElement, target: HTMLElement) => {\n let pos = computePosition(placement, menu, target);\n menu.style.top = pos.top + \"px\";\n menu.style.left = pos.left + \"px\";\n\n if (isOffScreen(menu)) {\n for (const p of placements) {\n const fallbackPos = computePosition(p, menu, target);\n menu.style.top = fallbackPos.top + \"px\";\n menu.style.left = fallbackPos.left + \"px\";\n if (!isOffScreen(menu)) return p;\n }\n }\n return placement;\n};\n\nconst Menu = ({ children, target, ...props }: MenuProps) => {\n let [{ onClickOutside, placement, zIndex, slotProps }] = useInterface<any>(\"Menu\", props, {});\n const _p: any = {};\n if (placement) _p.placement = placement;\n const p: any = useBreakpointProps(_p);\n placement = p.placement || \"bottom-left\";\n\n const isOpen = Boolean(target);\n const [closed, setClosed] = useState(!isOpen);\n const [placed, setPlaced] = useState<PlacementTypes>(placement);\n const menuRef = useRef<HTMLDivElement>(null);\n\n // Open/close effect\n useEffect(() => {\n if (closed && isOpen) setClosed(false);\n }, [isOpen]);\n\n\n useEffect(() => {\n if (!closed && target && menuRef.current) {\n const updatePosition = () => {\n if (menuRef.current && target) {\n const p = placeMenu(placement!, menuRef.current, target);\n
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../src/Menu/index.tsx"],"sourcesContent":["\"use client\";\nimport { ReactNode, useEffect, useState, useRef } from \"react\";\nimport { Tag, TagProps, useBreakpointProps, useBreakpointPropsType, useInterface, TransitionProps, Transition } from \"@xanui/core\";\nimport Portal, { PortalProps } from \"../Portal\";\nimport ClickOutside from \"../ClickOutside\";\n\nexport type PlacementTypes =\n | \"top\"\n | \"top-left\"\n | \"top-right\"\n | \"bottom\"\n | \"bottom-left\"\n | \"bottom-right\"\n | \"right\"\n | \"right-top\"\n | \"right-bottom\"\n | \"left\"\n | \"left-top\"\n | \"left-bottom\";\n\nexport type MenuProps = {\n children?: ReactNode;\n target?: HTMLElement;\n placement?: useBreakpointPropsType<PlacementTypes>;\n zIndex?: number;\n onClickOutside?: (e: MouseEvent) => void;\n slotProps?: {\n transition?: Omit<TransitionProps, \"open\">;\n portal?: Omit<PortalProps, \"children\">;\n content?: Omit<TagProps<\"div\">, \"children\">;\n };\n};\n\nconst placements: PlacementTypes[] = [\n \"top\",\n \"top-left\",\n \"top-right\",\n \"bottom\",\n \"bottom-left\",\n \"bottom-right\",\n \"right\",\n \"right-top\",\n \"right-bottom\",\n \"left\",\n \"left-top\",\n \"left-bottom\",\n];\n\nconst getTransformOrigin = (placement: PlacementTypes) => {\n switch (placement) {\n case \"top\":\n return \"bottom\";\n case \"top-left\":\n return \"bottom left\";\n case \"top-right\":\n return \"bottom right\";\n case \"bottom\":\n return \"top\";\n case \"bottom-left\":\n return \"top left\";\n case \"bottom-right\":\n return \"top right\";\n case \"left\":\n return \"right\";\n case \"left-top\":\n return \"top right\";\n case \"left-bottom\":\n return \"bottom right\";\n case \"right\":\n return \"left\";\n case \"right-top\":\n return \"top left\";\n case \"right-bottom\":\n return \"bottom left\";\n default:\n return \"top\";\n }\n};\n\n// Compute coordinates for each placement\nconst computePosition = (\n placement: PlacementTypes,\n menu: HTMLElement,\n target: HTMLElement\n) => {\n const { width: mw, height: mh } = menu.getBoundingClientRect();\n const {\n top: tt,\n left: tl,\n bottom: tb,\n right: tr,\n width: tw,\n height: th,\n } = target.getBoundingClientRect();\n\n const positions: Record<PlacementTypes, { top: number; left: number }> = {\n \"bottom-left\": { top: tb, left: tl },\n \"bottom-right\": { top: tb, left: tr - mw },\n bottom: { top: tb, left: tl + (tw - mw) / 2 },\n\n \"top-left\": { top: tt - mh, left: tl },\n \"top-right\": { top: tt - mh, left: tr - mw },\n top: { top: tt - mh, left: tl + (tw - mw) / 2 },\n\n left: { top: tt + (th - mh) / 2, left: tl - mw },\n \"left-top\": { top: tt, left: tl - mw },\n \"left-bottom\": { top: tb - mh, left: tl - mw },\n\n right: { top: tt + (th - mh) / 2, left: tr },\n \"right-top\": { top: tt, left: tr },\n \"right-bottom\": { top: tb - mh, left: tr },\n };\n\n return positions[placement];\n};\n\n\n// Check if menu is off-screen\nconst isOffScreen = (menu: HTMLElement) => {\n const { x, y, width, height } = menu.getBoundingClientRect();\n return x < 0 || y < 0 || x + width > window.innerWidth || y + height > window.innerHeight;\n};\n\n// Try to place menu and fallback if off-screen\nconst placeMenu = (placement: PlacementTypes, menu: HTMLElement, target: HTMLElement) => {\n let pos = computePosition(placement, menu, target);\n menu.style.top = pos.top + \"px\";\n menu.style.left = pos.left + \"px\";\n\n if (isOffScreen(menu)) {\n for (const p of placements) {\n const fallbackPos = computePosition(p, menu, target);\n menu.style.top = fallbackPos.top + \"px\";\n menu.style.left = fallbackPos.left + \"px\";\n if (!isOffScreen(menu)) return p;\n }\n }\n return placement;\n};\n\nconst Menu = ({ children, target, ...props }: MenuProps) => {\n let [{ onClickOutside, placement, zIndex, slotProps }] = useInterface<any>(\"Menu\", props, {});\n const _p: any = {};\n if (placement) _p.placement = placement;\n const p: any = useBreakpointProps(_p);\n placement = p.placement || \"bottom-left\";\n\n const isOpen = Boolean(target);\n const [closed, setClosed] = useState(!isOpen);\n const [placed, setPlaced] = useState<PlacementTypes>(placement);\n const menuRef = useRef<HTMLDivElement>(null);\n\n // Open/close effect\n useEffect(() => {\n if (closed && isOpen) setClosed(false);\n }, [isOpen]);\n\n\n useEffect(() => {\n if (!closed && target && menuRef.current) {\n const updatePosition = () => {\n if (menuRef.current && target) {\n requestAnimationFrame(() => {\n const p = placeMenu(placement!, menuRef.current as any, target);\n setPlaced(p);\n });\n }\n };\n\n updatePosition();\n window.addEventListener(\"resize\", updatePosition);\n window.addEventListener(\"scroll\", updatePosition, true);\n\n return () => {\n window.removeEventListener(\"resize\", updatePosition);\n window.removeEventListener(\"scroll\", updatePosition, true);\n };\n }\n return\n }, [closed, target, placement]);\n\n\n if (closed) return null;\n\n return (\n <Portal {...slotProps?.portal}>\n <ClickOutside\n onClickOutside={(e: MouseEvent) => {\n if (e.target !== target) {\n onClickOutside && onClickOutside(e);\n }\n }}\n ref={menuRef}\n sx={{ position: \"fixed\", zIndex: 1500 + (zIndex || 0) }}\n >\n <Transition\n duration={200}\n easing=\"fast\"\n variant=\"grow\"\n {...slotProps?.transition}\n open={isOpen}\n onClosed={() => {\n setClosed(true);\n slotProps?.transition?.onClosed?.();\n }}\n >\n <Tag\n baseClass=\"menu-content\"\n {...slotProps?.content}\n sxr={{\n overflow: \"hidden\",\n bgcolor: \"background.primary\",\n shadow: 2,\n radius: 1,\n transformOrigin: getTransformOrigin(placed),\n ...slotProps?.content?.sx,\n }}\n >\n {children}\n </Tag>\n </Transition>\n </ClickOutside>\n </Portal>\n );\n};\n\nexport default Menu;\n"],"names":[],"mappings":";;;;;;;;AAiCA;;;;;;;;;;;;;;AAeA;;AAEQ;AACI;AACJ;AACI;AACJ;AACI;AACJ;AACI;AACJ;AACI;AACJ;AACI;AACJ;AACI;AACJ;AACI;AACJ;AACI;AACJ;AACI;AACJ;AACI;AACJ;AACI;AACJ;AACI;;AAEZ;AAEA;AACA;AAKI;AACA;AASA;;;AAGI;;AAGA;AACA;AAEA;;AAEA;AAEA;;;;AAKJ;AACJ;AAGA;AACA;AACI;;AAEJ;AAEA;AACA;;;;AAKI;AACI;;;;AAII;AAAwB;;;AAGhC;AACJ;AAEA;;;;;AAGI;AAAe;AACf;AACA;AAEA;;;AAGA;;;;;AAKA;;;;AAMY;;AAEQ;;AAEJ;;AAER;AAEA;AACA;;AAGA;AACI;;AAEJ;;;;AAMR;AAAY;;AAMI;AACI;;;;;;;AAmCxB;;"}
|
package/Select/index.d.ts
CHANGED
|
@@ -12,6 +12,11 @@ type SelectProps = {
|
|
|
12
12
|
placeholder?: useBreakpointPropsType<string>;
|
|
13
13
|
color?: useBreakpointPropsType<UseColorTemplateColor>;
|
|
14
14
|
variant?: useBreakpointPropsType<UseColorTemplateType>;
|
|
15
|
+
refs?: {
|
|
16
|
+
input?: React.Ref<any>;
|
|
17
|
+
menu?: React.Ref<any>;
|
|
18
|
+
list?: React.Ref<any>;
|
|
19
|
+
};
|
|
15
20
|
slotProps?: {
|
|
16
21
|
menu?: Omit<MenuProps, 'children' | 'target'>;
|
|
17
22
|
input?: Omit<InputProps, "onChange" | "value">;
|
package/Select/index.js
CHANGED
|
@@ -13,8 +13,8 @@ var UpIcon = require('@xanui/icons/KeyboardArrowUp');
|
|
|
13
13
|
var core = require('@xanui/core');
|
|
14
14
|
|
|
15
15
|
const Select = React.forwardRef((_a, ref) => {
|
|
16
|
-
var _b, _c, _d, _e;
|
|
17
|
-
var { onChange, value, children } = _a, props = tslib.__rest(_a, ["onChange", "value", "children"]);
|
|
16
|
+
var _b, _c, _d, _e, _f;
|
|
17
|
+
var { onChange, value, children, refs } = _a, props = tslib.__rest(_a, ["onChange", "value", "children", "refs"]);
|
|
18
18
|
let [{ slotProps, color, variant, placeholder }] = core.useInterface("Select", props, {});
|
|
19
19
|
color !== null && color !== void 0 ? color : (color = "brand");
|
|
20
20
|
variant !== null && variant !== void 0 ? variant : (variant = "fill");
|
|
@@ -40,12 +40,13 @@ const Select = React.forwardRef((_a, ref) => {
|
|
|
40
40
|
selectedProps: sProps
|
|
41
41
|
};
|
|
42
42
|
}, [children, value]);
|
|
43
|
+
const mergeRefs = core.useMergeRefs(ref, conRef);
|
|
43
44
|
const toggleMenu = () => setTarget(target ? null : conRef.current);
|
|
44
|
-
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(index, Object.assign({ color: color, variant: variant === "soft" ? "fill" : variant, endIcon: jsxRuntime.jsxs(index$1, { flexDirection: "row", component: "span", children: [" ", (target ? jsxRuntime.jsx(UpIcon, {}) : jsxRuntime.jsx(DownIcon, {}))] }), readOnly: true, value: typeof selectedProps.children === 'string' ? selectedProps.children : value, cursor: "pointer", userSelect: "none", startIcon: selectedProps.startIcon, focused: !!target, placeholder: placeholder }, slotProps === null || slotProps === void 0 ? void 0 : slotProps.input, { slotProps: {
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
content: Object.assign({ mt: .5,
|
|
48
|
-
}, onClickOutside: toggleMenu, children: jsxRuntime.jsx(index$3, Object.assign({}, slotProps === null || slotProps === void 0 ? void 0 : slotProps.list, { color: color, variant: variant, children: childs })) }))] }));
|
|
45
|
+
return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(index, Object.assign({ ref: mergeRefs, color: color, variant: variant === "soft" ? "fill" : variant, endIcon: jsxRuntime.jsxs(index$1, { flexDirection: "row", component: "span", children: [" ", (target ? jsxRuntime.jsx(UpIcon, {}) : jsxRuntime.jsx(DownIcon, {}))] }), readOnly: true, value: typeof selectedProps.children === 'string' ? selectedProps.children : value, cursor: "pointer", userSelect: "none", startIcon: selectedProps.startIcon, focused: !!target, placeholder: placeholder }, slotProps === null || slotProps === void 0 ? void 0 : slotProps.input, { refs: Object.assign({ input: refs === null || refs === void 0 ? void 0 : refs.input }, (_b = slotProps === null || slotProps === void 0 ? void 0 : slotProps.input) === null || _b === void 0 ? void 0 : _b.refs), slotProps: {
|
|
46
|
+
rootContainer: Object.assign(Object.assign({ cursor: "pointer", userSelect: "none" }, (((_d = (_c = slotProps === null || slotProps === void 0 ? void 0 : slotProps.input) === null || _c === void 0 ? void 0 : _c.slotProps) === null || _d === void 0 ? void 0 : _d.container) || {})), { onClick: toggleMenu })
|
|
47
|
+
} })), jsxRuntime.jsx(index$2, Object.assign({ ref: refs === null || refs === void 0 ? void 0 : refs.menu, target: target, placement: "bottom-left" }, slotProps === null || slotProps === void 0 ? void 0 : slotProps.menu, { slotProps: {
|
|
48
|
+
content: Object.assign(Object.assign({ mt: .5 }, (_e = slotProps === null || slotProps === void 0 ? void 0 : slotProps.menu) === null || _e === void 0 ? void 0 : _e.content), { width: conRef && ((_f = conRef === null || conRef === void 0 ? void 0 : conRef.current) === null || _f === void 0 ? void 0 : _f.clientWidth) })
|
|
49
|
+
}, onClickOutside: toggleMenu, children: jsxRuntime.jsx(index$3, Object.assign({ ref: refs === null || refs === void 0 ? void 0 : refs.list }, slotProps === null || slotProps === void 0 ? void 0 : slotProps.list, { color: color, variant: variant, children: childs })) }))] }));
|
|
49
50
|
});
|
|
50
51
|
|
|
51
52
|
module.exports = Select;
|
package/Select/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/Select/index.tsx"],"sourcesContent":["\"use client\";\n\nimport React, { ReactElement, useMemo, cloneElement, useState, Children, useRef } from 'react'\nimport Input, { InputProps } from '../Input'\nimport List, { ListProps } from '../List'\nimport Menu, { MenuProps } from '../Menu'\nimport Stack from '../Stack'\nimport { OptionProps } from '../Option'\nimport DownIcon from '@xanui/icons/KeyboardArrowDown';\nimport UpIcon from '@xanui/icons/KeyboardArrowUp';\nimport { UseColorTemplateColor, UseColorTemplateType, useInterface, useBreakpointPropsType } from '@xanui/core'\n\n\nexport type SelectProps = {\n value?: string | number;\n onChange?: (value: string | number) => void;\n children: ReactElement<OptionProps> | ReactElement<OptionProps>[];\n placeholder?: useBreakpointPropsType<string>;\n color?: useBreakpointPropsType<UseColorTemplateColor>;\n variant?: useBreakpointPropsType<UseColorTemplateType>;\n slotProps?: {\n menu?: Omit<MenuProps, 'children' | 'target'>;\n input?: Omit<InputProps, \"onChange\" | \"value\">;\n list?: Omit<ListProps, \"children\">\n }\n}\n\nconst Select = React.forwardRef(({ onChange, value, children, ...props }: SelectProps, ref: React.Ref<any>) => {\n let [{ slotProps, color, variant, placeholder }] = useInterface<any>(\"Select\", props, {})\n color ??= \"brand\"\n variant ??= \"fill\"\n const [target, setTarget] = useState<any>()\n const conRef = useRef(null)\n const { childs, selectedProps } = useMemo(() => {\n let sProps: any = {}\n const c = Children.map(children, (child: any) => {\n let selected = child.props.value === value\n if (selected) sProps = child.props\n return cloneElement(child, {\n value: undefined,\n selected,\n onClick: () => {\n setTarget(null)\n onChange && onChange(child.props.value)\n }\n })\n })\n return {\n childs: c,\n selectedProps: sProps as OptionProps\n }\n }, [children, value])\n\n const toggleMenu = () => setTarget(target ? null : conRef.current)\n\n return (\n <>\n <Input\n color={color}\n variant={variant === \"soft\" ? \"fill\" : variant}\n endIcon={<Stack flexDirection=\"row\" component=\"span\" > {(target ? <UpIcon /> : <DownIcon />)}</Stack>}\n readOnly\n value={typeof selectedProps.children === 'string' ? selectedProps.children : value}\n cursor=\"pointer\"\n userSelect=\"none\"\n startIcon={selectedProps.startIcon}\n focused={!!target}\n placeholder={placeholder}\n {...slotProps?.input}\n slotProps={{\n
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/Select/index.tsx"],"sourcesContent":["\"use client\";\n\nimport React, { ReactElement, useMemo, cloneElement, useState, Children, useRef } from 'react'\nimport Input, { InputProps } from '../Input'\nimport List, { ListProps } from '../List'\nimport Menu, { MenuProps } from '../Menu'\nimport Stack from '../Stack'\nimport { OptionProps } from '../Option'\nimport DownIcon from '@xanui/icons/KeyboardArrowDown';\nimport UpIcon from '@xanui/icons/KeyboardArrowUp';\nimport { UseColorTemplateColor, UseColorTemplateType, useInterface, useBreakpointPropsType, useMergeRefs } from '@xanui/core'\n\n\nexport type SelectProps = {\n value?: string | number;\n onChange?: (value: string | number) => void;\n children: ReactElement<OptionProps> | ReactElement<OptionProps>[];\n placeholder?: useBreakpointPropsType<string>;\n color?: useBreakpointPropsType<UseColorTemplateColor>;\n variant?: useBreakpointPropsType<UseColorTemplateType>;\n refs?: {\n input?: React.Ref<any>;\n menu?: React.Ref<any>;\n list?: React.Ref<any>;\n };\n slotProps?: {\n menu?: Omit<MenuProps, 'children' | 'target'>;\n input?: Omit<InputProps, \"onChange\" | \"value\">;\n list?: Omit<ListProps, \"children\">\n }\n}\n\nconst Select = React.forwardRef(({ onChange, value, children, refs, ...props }: SelectProps, ref: React.Ref<any>) => {\n let [{ slotProps, color, variant, placeholder }] = useInterface<any>(\"Select\", props, {})\n color ??= \"brand\"\n variant ??= \"fill\"\n const [target, setTarget] = useState<any>()\n const conRef = useRef(null)\n const { childs, selectedProps } = useMemo(() => {\n let sProps: any = {}\n const c = Children.map(children, (child: any) => {\n let selected = child.props.value === value\n if (selected) sProps = child.props\n return cloneElement(child, {\n value: undefined,\n selected,\n onClick: () => {\n setTarget(null)\n onChange && onChange(child.props.value)\n }\n })\n })\n return {\n childs: c,\n selectedProps: sProps as OptionProps\n }\n }, [children, value])\n\n const mergeRefs = useMergeRefs(ref, conRef)\n const toggleMenu = () => setTarget(target ? null : conRef.current)\n\n return (\n <>\n <Input\n ref={mergeRefs}\n color={color}\n variant={variant === \"soft\" ? \"fill\" : variant}\n endIcon={<Stack flexDirection=\"row\" component=\"span\" > {(target ? <UpIcon /> : <DownIcon />)}</Stack>}\n readOnly\n value={typeof selectedProps.children === 'string' ? selectedProps.children : value}\n cursor=\"pointer\"\n userSelect=\"none\"\n startIcon={selectedProps.startIcon}\n focused={!!target}\n placeholder={placeholder}\n {...slotProps?.input}\n refs={{\n input: refs?.input,\n ...slotProps?.input?.refs\n }}\n slotProps={{\n rootContainer: {\n cursor: \"pointer\",\n userSelect: \"none\",\n ...(slotProps?.input?.slotProps?.container || {}),\n onClick: toggleMenu,\n }\n }}\n />\n <Menu\n ref={refs?.menu}\n target={target}\n placement=\"bottom-left\"\n {...slotProps?.menu}\n slotProps={{\n content: {\n mt: .5,\n ...slotProps?.menu?.content,\n width: conRef && (conRef?.current as any)?.clientWidth,\n }\n }}\n onClickOutside={toggleMenu}\n >\n <List\n ref={refs?.list}\n {...slotProps?.list}\n color={color}\n variant={variant}\n >\n {childs}\n </List>\n </Menu>\n </>\n )\n})\n\nexport default Select"],"names":[],"mappings":";;;;;;;;;;;;;;AAgCA;;AAAiC;;;;;AAK7B;;;;;AAKQ;AAAc;;AAEV;;;;;;AAMH;AACL;;AAEI;AACA;;AAER;;AAGA;AAEA;AAoBgB;AAMH;AAQG;AAKH;AAcjB;;"}
|
package/Select/index.mjs
CHANGED
|
@@ -8,11 +8,11 @@ import Menu from '../Menu/index.mjs';
|
|
|
8
8
|
import Stack from '../Stack/index.mjs';
|
|
9
9
|
import DownIcon from '@xanui/icons/KeyboardArrowDown';
|
|
10
10
|
import UpIcon from '@xanui/icons/KeyboardArrowUp';
|
|
11
|
-
import { useInterface } from '@xanui/core';
|
|
11
|
+
import { useInterface, useMergeRefs } from '@xanui/core';
|
|
12
12
|
|
|
13
13
|
const Select = React.forwardRef((_a, ref) => {
|
|
14
|
-
var _b, _c, _d, _e;
|
|
15
|
-
var { onChange, value, children } = _a, props = __rest(_a, ["onChange", "value", "children"]);
|
|
14
|
+
var _b, _c, _d, _e, _f;
|
|
15
|
+
var { onChange, value, children, refs } = _a, props = __rest(_a, ["onChange", "value", "children", "refs"]);
|
|
16
16
|
let [{ slotProps, color, variant, placeholder }] = useInterface("Select", props, {});
|
|
17
17
|
color !== null && color !== void 0 ? color : (color = "brand");
|
|
18
18
|
variant !== null && variant !== void 0 ? variant : (variant = "fill");
|
|
@@ -38,12 +38,13 @@ const Select = React.forwardRef((_a, ref) => {
|
|
|
38
38
|
selectedProps: sProps
|
|
39
39
|
};
|
|
40
40
|
}, [children, value]);
|
|
41
|
+
const mergeRefs = useMergeRefs(ref, conRef);
|
|
41
42
|
const toggleMenu = () => setTarget(target ? null : conRef.current);
|
|
42
|
-
return (jsxs(Fragment, { children: [jsx(Input, Object.assign({ color: color, variant: variant === "soft" ? "fill" : variant, endIcon: jsxs(Stack, { flexDirection: "row", component: "span", children: [" ", (target ? jsx(UpIcon, {}) : jsx(DownIcon, {}))] }), readOnly: true, value: typeof selectedProps.children === 'string' ? selectedProps.children : value, cursor: "pointer", userSelect: "none", startIcon: selectedProps.startIcon, focused: !!target, placeholder: placeholder }, slotProps === null || slotProps === void 0 ? void 0 : slotProps.input, { slotProps: {
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
content: Object.assign({ mt: .5,
|
|
46
|
-
}, onClickOutside: toggleMenu, children: jsx(List, Object.assign({}, slotProps === null || slotProps === void 0 ? void 0 : slotProps.list, { color: color, variant: variant, children: childs })) }))] }));
|
|
43
|
+
return (jsxs(Fragment, { children: [jsx(Input, Object.assign({ ref: mergeRefs, color: color, variant: variant === "soft" ? "fill" : variant, endIcon: jsxs(Stack, { flexDirection: "row", component: "span", children: [" ", (target ? jsx(UpIcon, {}) : jsx(DownIcon, {}))] }), readOnly: true, value: typeof selectedProps.children === 'string' ? selectedProps.children : value, cursor: "pointer", userSelect: "none", startIcon: selectedProps.startIcon, focused: !!target, placeholder: placeholder }, slotProps === null || slotProps === void 0 ? void 0 : slotProps.input, { refs: Object.assign({ input: refs === null || refs === void 0 ? void 0 : refs.input }, (_b = slotProps === null || slotProps === void 0 ? void 0 : slotProps.input) === null || _b === void 0 ? void 0 : _b.refs), slotProps: {
|
|
44
|
+
rootContainer: Object.assign(Object.assign({ cursor: "pointer", userSelect: "none" }, (((_d = (_c = slotProps === null || slotProps === void 0 ? void 0 : slotProps.input) === null || _c === void 0 ? void 0 : _c.slotProps) === null || _d === void 0 ? void 0 : _d.container) || {})), { onClick: toggleMenu })
|
|
45
|
+
} })), jsx(Menu, Object.assign({ ref: refs === null || refs === void 0 ? void 0 : refs.menu, target: target, placement: "bottom-left" }, slotProps === null || slotProps === void 0 ? void 0 : slotProps.menu, { slotProps: {
|
|
46
|
+
content: Object.assign(Object.assign({ mt: .5 }, (_e = slotProps === null || slotProps === void 0 ? void 0 : slotProps.menu) === null || _e === void 0 ? void 0 : _e.content), { width: conRef && ((_f = conRef === null || conRef === void 0 ? void 0 : conRef.current) === null || _f === void 0 ? void 0 : _f.clientWidth) })
|
|
47
|
+
}, onClickOutside: toggleMenu, children: jsx(List, Object.assign({ ref: refs === null || refs === void 0 ? void 0 : refs.list }, slotProps === null || slotProps === void 0 ? void 0 : slotProps.list, { color: color, variant: variant, children: childs })) }))] }));
|
|
47
48
|
});
|
|
48
49
|
|
|
49
50
|
export { Select as default };
|
package/Select/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../../src/Select/index.tsx"],"sourcesContent":["\"use client\";\n\nimport React, { ReactElement, useMemo, cloneElement, useState, Children, useRef } from 'react'\nimport Input, { InputProps } from '../Input'\nimport List, { ListProps } from '../List'\nimport Menu, { MenuProps } from '../Menu'\nimport Stack from '../Stack'\nimport { OptionProps } from '../Option'\nimport DownIcon from '@xanui/icons/KeyboardArrowDown';\nimport UpIcon from '@xanui/icons/KeyboardArrowUp';\nimport { UseColorTemplateColor, UseColorTemplateType, useInterface, useBreakpointPropsType } from '@xanui/core'\n\n\nexport type SelectProps = {\n value?: string | number;\n onChange?: (value: string | number) => void;\n children: ReactElement<OptionProps> | ReactElement<OptionProps>[];\n placeholder?: useBreakpointPropsType<string>;\n color?: useBreakpointPropsType<UseColorTemplateColor>;\n variant?: useBreakpointPropsType<UseColorTemplateType>;\n slotProps?: {\n menu?: Omit<MenuProps, 'children' | 'target'>;\n input?: Omit<InputProps, \"onChange\" | \"value\">;\n list?: Omit<ListProps, \"children\">\n }\n}\n\nconst Select = React.forwardRef(({ onChange, value, children, ...props }: SelectProps, ref: React.Ref<any>) => {\n let [{ slotProps, color, variant, placeholder }] = useInterface<any>(\"Select\", props, {})\n color ??= \"brand\"\n variant ??= \"fill\"\n const [target, setTarget] = useState<any>()\n const conRef = useRef(null)\n const { childs, selectedProps } = useMemo(() => {\n let sProps: any = {}\n const c = Children.map(children, (child: any) => {\n let selected = child.props.value === value\n if (selected) sProps = child.props\n return cloneElement(child, {\n value: undefined,\n selected,\n onClick: () => {\n setTarget(null)\n onChange && onChange(child.props.value)\n }\n })\n })\n return {\n childs: c,\n selectedProps: sProps as OptionProps\n }\n }, [children, value])\n\n const toggleMenu = () => setTarget(target ? null : conRef.current)\n\n return (\n <>\n <Input\n color={color}\n variant={variant === \"soft\" ? \"fill\" : variant}\n endIcon={<Stack flexDirection=\"row\" component=\"span\" > {(target ? <UpIcon /> : <DownIcon />)}</Stack>}\n readOnly\n value={typeof selectedProps.children === 'string' ? selectedProps.children : value}\n cursor=\"pointer\"\n userSelect=\"none\"\n startIcon={selectedProps.startIcon}\n focused={!!target}\n placeholder={placeholder}\n {...slotProps?.input}\n slotProps={{\n
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../src/Select/index.tsx"],"sourcesContent":["\"use client\";\n\nimport React, { ReactElement, useMemo, cloneElement, useState, Children, useRef } from 'react'\nimport Input, { InputProps } from '../Input'\nimport List, { ListProps } from '../List'\nimport Menu, { MenuProps } from '../Menu'\nimport Stack from '../Stack'\nimport { OptionProps } from '../Option'\nimport DownIcon from '@xanui/icons/KeyboardArrowDown';\nimport UpIcon from '@xanui/icons/KeyboardArrowUp';\nimport { UseColorTemplateColor, UseColorTemplateType, useInterface, useBreakpointPropsType, useMergeRefs } from '@xanui/core'\n\n\nexport type SelectProps = {\n value?: string | number;\n onChange?: (value: string | number) => void;\n children: ReactElement<OptionProps> | ReactElement<OptionProps>[];\n placeholder?: useBreakpointPropsType<string>;\n color?: useBreakpointPropsType<UseColorTemplateColor>;\n variant?: useBreakpointPropsType<UseColorTemplateType>;\n refs?: {\n input?: React.Ref<any>;\n menu?: React.Ref<any>;\n list?: React.Ref<any>;\n };\n slotProps?: {\n menu?: Omit<MenuProps, 'children' | 'target'>;\n input?: Omit<InputProps, \"onChange\" | \"value\">;\n list?: Omit<ListProps, \"children\">\n }\n}\n\nconst Select = React.forwardRef(({ onChange, value, children, refs, ...props }: SelectProps, ref: React.Ref<any>) => {\n let [{ slotProps, color, variant, placeholder }] = useInterface<any>(\"Select\", props, {})\n color ??= \"brand\"\n variant ??= \"fill\"\n const [target, setTarget] = useState<any>()\n const conRef = useRef(null)\n const { childs, selectedProps } = useMemo(() => {\n let sProps: any = {}\n const c = Children.map(children, (child: any) => {\n let selected = child.props.value === value\n if (selected) sProps = child.props\n return cloneElement(child, {\n value: undefined,\n selected,\n onClick: () => {\n setTarget(null)\n onChange && onChange(child.props.value)\n }\n })\n })\n return {\n childs: c,\n selectedProps: sProps as OptionProps\n }\n }, [children, value])\n\n const mergeRefs = useMergeRefs(ref, conRef)\n const toggleMenu = () => setTarget(target ? null : conRef.current)\n\n return (\n <>\n <Input\n ref={mergeRefs}\n color={color}\n variant={variant === \"soft\" ? \"fill\" : variant}\n endIcon={<Stack flexDirection=\"row\" component=\"span\" > {(target ? <UpIcon /> : <DownIcon />)}</Stack>}\n readOnly\n value={typeof selectedProps.children === 'string' ? selectedProps.children : value}\n cursor=\"pointer\"\n userSelect=\"none\"\n startIcon={selectedProps.startIcon}\n focused={!!target}\n placeholder={placeholder}\n {...slotProps?.input}\n refs={{\n input: refs?.input,\n ...slotProps?.input?.refs\n }}\n slotProps={{\n rootContainer: {\n cursor: \"pointer\",\n userSelect: \"none\",\n ...(slotProps?.input?.slotProps?.container || {}),\n onClick: toggleMenu,\n }\n }}\n />\n <Menu\n ref={refs?.menu}\n target={target}\n placement=\"bottom-left\"\n {...slotProps?.menu}\n slotProps={{\n content: {\n mt: .5,\n ...slotProps?.menu?.content,\n width: conRef && (conRef?.current as any)?.clientWidth,\n }\n }}\n onClickOutside={toggleMenu}\n >\n <List\n ref={refs?.list}\n {...slotProps?.list}\n color={color}\n variant={variant}\n >\n {childs}\n </List>\n </Menu>\n </>\n )\n})\n\nexport default Select"],"names":[],"mappings":";;;;;;;;;;;;AAgCA;;AAAiC;;;;;AAK7B;;;;;AAKQ;AAAc;;AAEV;;;;;;AAMH;AACL;;AAEI;AACA;;AAER;;AAGA;AAEA;AAoBgB;AAMH;AAQG;AAKH;AAcjB;;"}
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xanui/ui",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.21",
|
|
4
4
|
"description": "",
|
|
5
5
|
"private": false,
|
|
6
6
|
"main": "./index.js",
|
|
7
7
|
"module": "./index.mjs",
|
|
8
8
|
"types": "./index.d.ts",
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"@xanui/core": "^1.2.
|
|
10
|
+
"@xanui/core": "^1.2.38",
|
|
11
11
|
"@xanui/icons": "^1.1.10",
|
|
12
12
|
"pretty-class": "^1.0.8",
|
|
13
13
|
"react-state-bucket": "^1.2.6"
|