@ryanhe919/lumen-ui 0.3.1 → 0.3.2
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/LICENSE +21 -0
- package/dist/ErrorMessage-CbE7emgD.cjs +26 -0
- package/dist/ErrorMessage-CbE7emgD.cjs.map +1 -0
- package/dist/ErrorMessage-Dt4cJ-sy.js +27 -0
- package/dist/ErrorMessage-Dt4cJ-sy.js.map +1 -0
- package/dist/{LMButton-B258yfky.cjs → LMButton-ByInEqMk.cjs} +15 -11
- package/dist/LMButton-ByInEqMk.cjs.map +1 -0
- package/dist/{LMButton-S4xQSohi.js → LMButton-DH7s4i80.js} +16 -12
- package/dist/LMButton-DH7s4i80.js.map +1 -0
- package/dist/{LMCard-D_K051f2.cjs → LMCard-lJGrsAzY.cjs} +9 -6
- package/dist/LMCard-lJGrsAzY.cjs.map +1 -0
- package/dist/{LMCard-D7ABNC95.js → LMCard-uuWNjVQL.js} +9 -6
- package/dist/LMCard-uuWNjVQL.js.map +1 -0
- package/dist/{LMCheckbox-C2YvEQ8f.cjs → LMCheckbox-C5gRhXJk.cjs} +11 -34
- package/dist/LMCheckbox-C5gRhXJk.cjs.map +1 -0
- package/dist/{LMCheckbox-DaaJRjKt.js → LMCheckbox-DPg4CldM.js} +11 -34
- package/dist/LMCheckbox-DPg4CldM.js.map +1 -0
- package/dist/{LMDatePicker-DSv28BFH.js → LMDatePicker-C7R0ByJ-.js} +5 -1
- package/dist/LMDatePicker-C7R0ByJ-.js.map +1 -0
- package/dist/{LMDatePicker-BlUwN4On.cjs → LMDatePicker-lH-8-HzG.cjs} +5 -1
- package/dist/LMDatePicker-lH-8-HzG.cjs.map +1 -0
- package/dist/{LMEmpty-BedQxpbi.cjs → LMEmpty-BCf4K8iH.cjs} +7 -6
- package/dist/LMEmpty-BCf4K8iH.cjs.map +1 -0
- package/dist/{LMEmpty-DzHM1fOb.js → LMEmpty-C499qRrR.js} +7 -6
- package/dist/LMEmpty-C499qRrR.js.map +1 -0
- package/dist/{LMField-DhDHj64z.cjs → LMField-BRaviP2p.cjs} +3 -2
- package/dist/LMField-BRaviP2p.cjs.map +1 -0
- package/dist/{LMField-BS-DSEya.js → LMField-DkRk9Q8-.js} +3 -2
- package/dist/LMField-DkRk9Q8-.js.map +1 -0
- package/dist/{LMInput-D9csGyhj.js → LMInput-Be2KkPOW.js} +21 -43
- package/dist/LMInput-Be2KkPOW.js.map +1 -0
- package/dist/{LMInput-CVjawj1F.cjs → LMInput-O55xkiRS.cjs} +20 -42
- package/dist/LMInput-O55xkiRS.cjs.map +1 -0
- package/dist/{LMModal-BCVVPLot.cjs → LMModal-BgxF1xOT.cjs} +2 -2
- package/dist/LMModal-BgxF1xOT.cjs.map +1 -0
- package/dist/{LMModal-DCJPlfA4.js → LMModal-CZF26Ask.js} +2 -2
- package/dist/LMModal-CZF26Ask.js.map +1 -0
- package/dist/{LMNumberInput-B1tU7T_W.cjs → LMNumberInput-DQaLVoud.cjs} +30 -39
- package/dist/LMNumberInput-DQaLVoud.cjs.map +1 -0
- package/dist/{LMNumberInput-BI5_OEx4.js → LMNumberInput-gnRvWRly.js} +31 -40
- package/dist/LMNumberInput-gnRvWRly.js.map +1 -0
- package/dist/{LMRadio-CHn6nFSy.cjs → LMRadio-BVBwm1rk.cjs} +11 -37
- package/dist/LMRadio-BVBwm1rk.cjs.map +1 -0
- package/dist/{LMRadio-UQLNgTMF.js → LMRadio-C0ZL0hVK.js} +11 -37
- package/dist/LMRadio-C0ZL0hVK.js.map +1 -0
- package/dist/{LMSearchInput-nBlAX734.cjs → LMSearchInput-BDJVh4Vs.cjs} +25 -31
- package/dist/LMSearchInput-BDJVh4Vs.cjs.map +1 -0
- package/dist/{LMSearchInput-CIvVkEf2.js → LMSearchInput-DQovqMTN.js} +26 -32
- package/dist/LMSearchInput-DQovqMTN.js.map +1 -0
- package/dist/{LMSelect-B-MWX2JI.js → LMSelect-BPfW-AHI.js} +37 -48
- package/dist/LMSelect-BPfW-AHI.js.map +1 -0
- package/dist/{LMSelect-ByQcUp2S.cjs → LMSelect-xIVolEhx.cjs} +37 -48
- package/dist/LMSelect-xIVolEhx.cjs.map +1 -0
- package/dist/{LMStatCard-D5HV9r6d.js → LMStatCard-CdyIDhrA.js} +11 -6
- package/dist/LMStatCard-CdyIDhrA.js.map +1 -0
- package/dist/{LMStatCard-MXs9Z0qH.cjs → LMStatCard-Do5f2Map.cjs} +11 -6
- package/dist/LMStatCard-Do5f2Map.cjs.map +1 -0
- package/dist/{LMSwitch-CP1_nrfU.js → LMSwitch-BqhucDO0.js} +3 -31
- package/dist/LMSwitch-BqhucDO0.js.map +1 -0
- package/dist/{LMSwitch-DYoSH6wE.cjs → LMSwitch-BxVqTSUH.cjs} +3 -31
- package/dist/LMSwitch-BxVqTSUH.cjs.map +1 -0
- package/dist/{LMTable-j1ZzAzXB.cjs → LMTable-Be9FK8bz.cjs} +7 -4
- package/dist/LMTable-Be9FK8bz.cjs.map +1 -0
- package/dist/{LMTable-Cp8HZqiV.js → LMTable-IGmHFhnV.js} +7 -4
- package/dist/LMTable-IGmHFhnV.js.map +1 -0
- package/dist/{LMTabs-D5n9lB8X.js → LMTabs-Cjp3oiNv.js} +2 -2
- package/dist/{LMTabs-D5n9lB8X.js.map → LMTabs-Cjp3oiNv.js.map} +1 -1
- package/dist/{LMTabs-NPmOzPat.cjs → LMTabs-DEYx2gOH.cjs} +2 -2
- package/dist/{LMTabs-NPmOzPat.cjs.map → LMTabs-DEYx2gOH.cjs.map} +1 -1
- package/dist/{LMTextarea-5dVVPeL2.js → LMTextarea-BNacTCNn.js} +20 -28
- package/dist/LMTextarea-BNacTCNn.js.map +1 -0
- package/dist/{LMTextarea-yG0OBZjA.cjs → LMTextarea-DRi6gaFW.cjs} +20 -28
- package/dist/LMTextarea-DRi6gaFW.cjs.map +1 -0
- package/dist/cn-I2jp-M-K.cjs +6 -0
- package/dist/cn-I2jp-M-K.cjs.map +1 -0
- package/dist/cn-wDEkOmcn.js +7 -0
- package/dist/cn-wDEkOmcn.js.map +1 -0
- package/dist/components/Chat/LMChatBubble/LMChatBubble.d.ts.map +1 -1
- package/dist/components/Chat/LMChatContainer/LMChatContainer.d.ts.map +1 -1
- package/dist/components/Chat/LMChatInput/LMChatInput.d.ts.map +1 -1
- package/dist/components/Chat/LMChatMessage/LMChatMessage.d.ts.map +1 -1
- package/dist/components/Chat/LMMarkdownRenderer/LMMarkdownRenderer.d.ts.map +1 -1
- package/dist/components/Chat/LMTypingIndicator/LMTypingIndicator.d.ts.map +1 -1
- package/dist/components/DataDisplay/LMCard/LMCard.d.ts.map +1 -1
- package/dist/components/DataDisplay/LMEmpty/LMEmpty.d.ts.map +1 -1
- package/dist/components/DataDisplay/LMStatCard/LMStatCard.d.ts.map +1 -1
- package/dist/components/DataDisplay/LMTable/LMTable.d.ts.map +1 -1
- package/dist/components/Feedback/LMModal/LMModal.d.ts +1 -1
- package/dist/components/Feedback/LMModal/LMModal.d.ts.map +1 -1
- package/dist/components/Form/LMCheckbox/LMCheckbox.d.ts.map +1 -1
- package/dist/components/Form/LMDatePicker/LMDatePicker.d.ts.map +1 -1
- package/dist/components/Form/LMField/LMField.d.ts.map +1 -1
- package/dist/components/Form/LMInput/LMInput.d.ts +1 -1
- package/dist/components/Form/LMInput/LMInput.d.ts.map +1 -1
- package/dist/components/Form/LMNumberInput/LMNumberInput.d.ts +1 -1
- package/dist/components/Form/LMNumberInput/LMNumberInput.d.ts.map +1 -1
- package/dist/components/Form/LMRadio/LMRadio.d.ts.map +1 -1
- package/dist/components/Form/LMSearchInput/LMSearchInput.d.ts +1 -1
- package/dist/components/Form/LMSearchInput/LMSearchInput.d.ts.map +1 -1
- package/dist/components/Form/LMSelect/LMSelect.d.ts.map +1 -1
- package/dist/components/Form/LMSwitch/LMSwitch.d.ts.map +1 -1
- package/dist/components/Form/LMTextarea/LMTextarea.d.ts +1 -1
- package/dist/components/Form/LMTextarea/LMTextarea.d.ts.map +1 -1
- package/dist/components/General/LMButton/LMButton.d.ts.map +1 -1
- package/dist/components/_internal/ErrorMessage.d.ts +9 -0
- package/dist/components/_internal/ErrorMessage.d.ts.map +1 -0
- package/dist/components/button/index.cjs +1 -1
- package/dist/components/button/index.js +1 -1
- package/dist/components/card/index.cjs +1 -1
- package/dist/components/card/index.js +1 -1
- package/dist/components/checkbox/index.cjs +1 -1
- package/dist/components/checkbox/index.js +1 -1
- package/dist/components/date-picker/index.cjs +1 -1
- package/dist/components/date-picker/index.js +1 -1
- package/dist/components/empty/index.cjs +1 -1
- package/dist/components/empty/index.js +1 -1
- package/dist/components/field/index.cjs +1 -1
- package/dist/components/field/index.js +1 -1
- package/dist/components/input/index.cjs +1 -1
- package/dist/components/input/index.js +1 -1
- package/dist/components/modal/index.cjs +1 -1
- package/dist/components/modal/index.js +1 -1
- package/dist/components/number-input/index.cjs +1 -1
- package/dist/components/number-input/index.js +1 -1
- package/dist/components/radio/index.cjs +1 -1
- package/dist/components/radio/index.js +1 -1
- package/dist/components/search-input/index.cjs +1 -1
- package/dist/components/search-input/index.js +1 -1
- package/dist/components/select/index.cjs +1 -1
- package/dist/components/select/index.js +1 -1
- package/dist/components/stat-card/index.cjs +1 -1
- package/dist/components/stat-card/index.js +1 -1
- package/dist/components/switch/index.cjs +1 -1
- package/dist/components/switch/index.js +1 -1
- package/dist/components/table/index.cjs +1 -1
- package/dist/components/table/index.js +1 -1
- package/dist/components/tabs/index.cjs +1 -1
- package/dist/components/tabs/index.js +1 -1
- package/dist/components/textarea/index.cjs +1 -1
- package/dist/components/textarea/index.js +1 -1
- package/dist/index.cjs +120 -121
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +119 -120
- package/dist/index.js.map +1 -1
- package/dist/style.css +6 -0
- package/package.json +8 -7
- package/dist/LMButton-B258yfky.cjs.map +0 -1
- package/dist/LMButton-S4xQSohi.js.map +0 -1
- package/dist/LMCard-D7ABNC95.js.map +0 -1
- package/dist/LMCard-D_K051f2.cjs.map +0 -1
- package/dist/LMCheckbox-C2YvEQ8f.cjs.map +0 -1
- package/dist/LMCheckbox-DaaJRjKt.js.map +0 -1
- package/dist/LMDatePicker-BlUwN4On.cjs.map +0 -1
- package/dist/LMDatePicker-DSv28BFH.js.map +0 -1
- package/dist/LMEmpty-BedQxpbi.cjs.map +0 -1
- package/dist/LMEmpty-DzHM1fOb.js.map +0 -1
- package/dist/LMField-BS-DSEya.js.map +0 -1
- package/dist/LMField-DhDHj64z.cjs.map +0 -1
- package/dist/LMInput-CVjawj1F.cjs.map +0 -1
- package/dist/LMInput-D9csGyhj.js.map +0 -1
- package/dist/LMModal-BCVVPLot.cjs.map +0 -1
- package/dist/LMModal-DCJPlfA4.js.map +0 -1
- package/dist/LMNumberInput-B1tU7T_W.cjs.map +0 -1
- package/dist/LMNumberInput-BI5_OEx4.js.map +0 -1
- package/dist/LMRadio-CHn6nFSy.cjs.map +0 -1
- package/dist/LMRadio-UQLNgTMF.js.map +0 -1
- package/dist/LMSearchInput-CIvVkEf2.js.map +0 -1
- package/dist/LMSearchInput-nBlAX734.cjs.map +0 -1
- package/dist/LMSelect-B-MWX2JI.js.map +0 -1
- package/dist/LMSelect-ByQcUp2S.cjs.map +0 -1
- package/dist/LMStatCard-D5HV9r6d.js.map +0 -1
- package/dist/LMStatCard-MXs9Z0qH.cjs.map +0 -1
- package/dist/LMSwitch-CP1_nrfU.js.map +0 -1
- package/dist/LMSwitch-DYoSH6wE.cjs.map +0 -1
- package/dist/LMTable-Cp8HZqiV.js.map +0 -1
- package/dist/LMTable-j1ZzAzXB.cjs.map +0 -1
- package/dist/LMTextarea-5dVVPeL2.js.map +0 -1
- package/dist/LMTextarea-yG0OBZjA.cjs.map +0 -1
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const jsxRuntime = require("react/jsx-runtime");
|
|
3
3
|
const React = require("react");
|
|
4
|
+
const cn = require("./cn-I2jp-M-K.cjs");
|
|
4
5
|
const componentSizes = require("./componentSizes-DUTZ7uEM.cjs");
|
|
5
|
-
const
|
|
6
|
+
const ErrorMessage = require("./ErrorMessage-CbE7emgD.cjs");
|
|
7
|
+
const LMSearchInput = React.forwardRef(({
|
|
6
8
|
value,
|
|
7
9
|
onChange,
|
|
8
10
|
onSearch,
|
|
@@ -17,11 +19,16 @@ const LMSearchInput = ({
|
|
|
17
19
|
showSearchButton = true,
|
|
18
20
|
searchButtonText = "Search",
|
|
19
21
|
debounceDelay = 300
|
|
20
|
-
}) => {
|
|
22
|
+
}, ref) => {
|
|
21
23
|
const [inputValue, setInputValue] = React.useState(value || "");
|
|
22
24
|
const [isFocused, setIsFocused] = React.useState(false);
|
|
23
25
|
const debounceRef = React.useRef(null);
|
|
24
26
|
const inputRef = React.useRef(null);
|
|
27
|
+
const setRefs = React.useCallback((node) => {
|
|
28
|
+
inputRef.current = node;
|
|
29
|
+
if (typeof ref === "function") ref(node);
|
|
30
|
+
else if (ref) ref.current = node;
|
|
31
|
+
}, [ref]);
|
|
25
32
|
const searchBtnRef = React.useRef(null);
|
|
26
33
|
const [searchBtnWidth, setSearchBtnWidth] = React.useState(0);
|
|
27
34
|
React.useEffect(() => {
|
|
@@ -34,14 +41,17 @@ const LMSearchInput = ({
|
|
|
34
41
|
setSearchBtnWidth(0);
|
|
35
42
|
}
|
|
36
43
|
}, [showSearchButton, searchButtonText]);
|
|
37
|
-
const baseClassName =
|
|
38
|
-
w-full
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
const baseClassName = cn.cn(
|
|
45
|
+
"w-full",
|
|
46
|
+
componentSizes.SIZE_INPUT_CONFIG[size].padding,
|
|
47
|
+
componentSizes.SIZE_INPUT_CONFIG[size].height,
|
|
48
|
+
"backdrop-blur-md border rounded-2xl",
|
|
49
|
+
"focus:ring-2 focus:outline-none transition-all duration-300",
|
|
50
|
+
"shadow-sm",
|
|
51
|
+
showSearchButton ? "pr-20" : showClear ? "pr-10" : "pr-4",
|
|
52
|
+
"pl-12",
|
|
53
|
+
className
|
|
54
|
+
);
|
|
45
55
|
const getSearchInputStyles = () => {
|
|
46
56
|
const baseStyles = {
|
|
47
57
|
backgroundColor: "var(--lm-bg-elevated)",
|
|
@@ -107,7 +117,7 @@ const LMSearchInput = ({
|
|
|
107
117
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
108
118
|
"input",
|
|
109
119
|
{
|
|
110
|
-
ref:
|
|
120
|
+
ref: setRefs,
|
|
111
121
|
type: "search",
|
|
112
122
|
name,
|
|
113
123
|
value: inputValue,
|
|
@@ -180,25 +190,9 @@ const LMSearchInput = ({
|
|
|
180
190
|
}
|
|
181
191
|
)
|
|
182
192
|
] }),
|
|
183
|
-
errorMessage && /* @__PURE__ */ jsxRuntime.
|
|
184
|
-
"p",
|
|
185
|
-
{
|
|
186
|
-
className: "text-xs flex items-center gap-1",
|
|
187
|
-
style: { color: "var(--lm-error-500)" },
|
|
188
|
-
children: [
|
|
189
|
-
/* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-3 h-3", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
190
|
-
"path",
|
|
191
|
-
{
|
|
192
|
-
fillRule: "evenodd",
|
|
193
|
-
d: "M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z",
|
|
194
|
-
clipRule: "evenodd"
|
|
195
|
-
}
|
|
196
|
-
) }),
|
|
197
|
-
errorMessage
|
|
198
|
-
]
|
|
199
|
-
}
|
|
200
|
-
)
|
|
193
|
+
errorMessage && /* @__PURE__ */ jsxRuntime.jsx(ErrorMessage.ErrorMessage, { message: errorMessage })
|
|
201
194
|
] });
|
|
202
|
-
};
|
|
195
|
+
});
|
|
196
|
+
LMSearchInput.displayName = "LMSearchInput";
|
|
203
197
|
exports.LMSearchInput = LMSearchInput;
|
|
204
|
-
//# sourceMappingURL=LMSearchInput-
|
|
198
|
+
//# sourceMappingURL=LMSearchInput-BDJVh4Vs.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LMSearchInput-BDJVh4Vs.cjs","sources":["../src/components/Form/LMSearchInput/LMSearchInput.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect, useCallback } from 'react'\nimport { cn } from '../../../utils/cn'\nimport { SIZE_INPUT_CONFIG } from '../../../utils/componentSizes'\nimport type { ComponentSize } from '../../../utils/componentSizes'\nimport { ErrorMessage } from '../../_internal/ErrorMessage'\n\nexport interface LMSearchInputProps {\n /** Current search value */\n value?: string\n /** Change callback */\n onChange?: (value: string) => void\n /** Search submit callback */\n onSearch?: (value: string) => void\n /** Error state */\n error?: boolean\n /** Error message */\n errorMessage?: string\n /** Placeholder */\n placeholder?: string\n /** Disabled state */\n disabled?: boolean\n /** Class name */\n className?: string\n /** Form field name */\n name?: string\n /** Size */\n size?: ComponentSize\n /** Show clear button */\n showClear?: boolean\n /** Show search button */\n showSearchButton?: boolean\n /** Search button text */\n searchButtonText?: string\n /** Debounce delay (ms) */\n debounceDelay?: number\n}\n\nconst LMSearchInput = React.forwardRef<HTMLInputElement, LMSearchInputProps>(({\n value,\n onChange,\n onSearch,\n error = false,\n errorMessage,\n placeholder = 'Search...',\n disabled = false,\n className = '',\n name,\n size = 'md',\n showClear = true,\n showSearchButton = true,\n searchButtonText = 'Search',\n debounceDelay = 300,\n}, ref) => {\n const [inputValue, setInputValue] = useState(value || '')\n const [isFocused, setIsFocused] = useState(false)\n const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n const inputRef = useRef<HTMLInputElement | null>(null)\n const setRefs = useCallback((node: HTMLInputElement | null) => {\n inputRef.current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) (ref as { current: HTMLInputElement | null }).current = node\n }, [ref])\n const searchBtnRef = useRef<HTMLButtonElement>(null)\n const [searchBtnWidth, setSearchBtnWidth] = useState(0)\n\n useEffect(() => {\n if (value !== undefined && value !== null) setInputValue(value)\n }, [value])\n\n useEffect(() => {\n if (showSearchButton && searchBtnRef.current) {\n setSearchBtnWidth(searchBtnRef.current.offsetWidth || 0)\n } else {\n setSearchBtnWidth(0)\n }\n }, [showSearchButton, searchButtonText])\n\n const baseClassName = cn(\n 'w-full',\n SIZE_INPUT_CONFIG[size].padding,\n SIZE_INPUT_CONFIG[size].height,\n 'backdrop-blur-md border rounded-2xl',\n 'focus:ring-2 focus:outline-none transition-all duration-300',\n 'shadow-sm',\n showSearchButton ? 'pr-20' : showClear ? 'pr-10' : 'pr-4',\n 'pl-12',\n className\n )\n\n const getSearchInputStyles = () => {\n const baseStyles = {\n backgroundColor: 'var(--lm-bg-elevated)',\n color: 'var(--lm-text-primary)',\n borderColor: error\n ? 'var(--lm-error-300)'\n : isFocused\n ? 'var(--lm-primary-400)'\n : 'var(--lm-border-default)',\n boxShadow: 'var(--lm-shadow-sm)',\n } as React.CSSProperties\n\n return {\n ...baseStyles,\n '--tw-ring-color': error\n ? 'var(--lm-error-400)'\n : 'var(--lm-primary-400)',\n '--tw-ring-opacity': '0.3',\n }\n }\n\n const getDisabledStyles = () =>\n disabled\n ? {\n backgroundColor: 'var(--lm-bg-paper)',\n color: 'var(--lm-text-disabled)',\n cursor: 'not-allowed',\n opacity: 0.6,\n }\n : {}\n\n const getIconStyles = () => {\n if (error) return { color: 'var(--lm-error-400)' }\n if (isFocused) return { color: 'var(--lm-primary-500)' }\n return { color: 'var(--lm-text-secondary)' }\n }\n\n const getButtonStyles = () => ({\n backgroundColor: 'var(--lm-primary-500)',\n color: 'white',\n })\n\n const getClearButtonStyles = () => ({\n backgroundColor: 'var(--lm-bg-paper)',\n color: 'var(--lm-text-secondary)',\n })\n\n const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = event.target.value\n setInputValue(newValue)\n onChange?.(newValue)\n\n if (debounceRef.current) clearTimeout(debounceRef.current)\n debounceRef.current = setTimeout(() => {\n onSearch?.(newValue)\n }, debounceDelay)\n }\n\n const handleSearch = () => onSearch?.(inputValue)\n\n const handleClear = () => {\n setInputValue('')\n onChange?.('')\n onSearch?.('')\n inputRef.current?.focus()\n }\n\n const handleKeyDown = (event: React.KeyboardEvent) => {\n if (event.key === 'Enter') {\n event.preventDefault()\n handleSearch()\n }\n }\n\n const clearBtnSizeClass =\n size === 'sm'\n ? 'w-7 h-7 text-xs'\n : size === 'lg'\n ? 'w-9 h-9 text-sm'\n : 'w-8 h-8 text-sm'\n\n const clearRightPx = showSearchButton ? searchBtnWidth + 8 : 8\n\n const SearchIcon = () => (\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\" />\n </svg>\n )\n\n const ClearIcon = () => (\n <svg className=\"w-3 h-3\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n )\n\n return (\n <div className=\"space-y-2\">\n <div className=\"relative group\">\n <div className=\"absolute inset-y-0 left-0 pl-4 flex items-center pointer-events-none z-10\">\n <span style={getIconStyles()}>\n <SearchIcon />\n </span>\n </div>\n\n <input\n ref={setRefs}\n type=\"search\"\n name={name}\n value={inputValue}\n placeholder={placeholder}\n disabled={disabled}\n className={baseClassName}\n style={{\n ...getSearchInputStyles(),\n ...getDisabledStyles(),\n } as React.CSSProperties}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n onMouseEnter={(e) => {\n if (!disabled && !error && !isFocused) {\n e.currentTarget.style.borderColor = 'var(--lm-border-strong)'\n }\n }}\n onMouseLeave={(e) => {\n if (!disabled && !error && !isFocused) {\n e.currentTarget.style.borderColor = 'var(--lm-border-default)'\n }\n }}\n />\n\n <style>{`\n input[type='search']::-webkit-search-cancel-button {\n -webkit-appearance: none;\n appearance: none;\n }\n `}</style>\n\n {showClear && inputValue && !disabled && (\n <button\n onClick={handleClear}\n className={`absolute top-1/2 -translate-y-1/2 z-10 rounded-full flex items-center justify-center ${clearBtnSizeClass}`}\n style={{\n ...getClearButtonStyles(),\n right: `${clearRightPx}px`,\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor = 'var(--lm-bg-elevated)'\n e.currentTarget.style.color = 'var(--lm-text-primary)'\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = 'var(--lm-bg-paper)'\n e.currentTarget.style.color = 'var(--lm-text-secondary)'\n }}\n aria-label=\"Clear\"\n type=\"button\"\n >\n <ClearIcon />\n </button>\n )}\n\n {showSearchButton && !disabled && (\n <button\n ref={searchBtnRef}\n onClick={handleSearch}\n className=\"absolute inset-y-0 right-0 px-4 rounded-r-2xl transition-colors duration-200 z-20\"\n style={getButtonStyles()}\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor = 'var(--lm-primary-600)'\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = 'var(--lm-primary-500)'\n }}\n type=\"button\"\n >\n <span className=\"text-sm font-medium\">{searchButtonText}</span>\n </button>\n )}\n </div>\n\n {errorMessage && <ErrorMessage message={errorMessage} />}\n </div>\n )\n})\n\nLMSearchInput.displayName = 'LMSearchInput'\n\nexport default LMSearchInput\n"],"names":["useState","useRef","useCallback","useEffect","cn","SIZE_INPUT_CONFIG","jsx","jsxs","ErrorMessage"],"mappings":";;;;;;AAqCA,MAAM,gBAAgB,MAAM,WAAiD,CAAC;AAAA,EAC5E;AAAA,EACA;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR;AAAA,EACA,cAAc;AAAA,EACd,WAAW;AAAA,EACX,YAAY;AAAA,EACZ;AAAA,EACA,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,mBAAmB;AAAA,EACnB,mBAAmB;AAAA,EACnB,gBAAgB;AAClB,GAAG,QAAQ;AACT,QAAM,CAAC,YAAY,aAAa,IAAIA,MAAAA,SAAS,SAAS,EAAE;AACxD,QAAM,CAAC,WAAW,YAAY,IAAIA,MAAAA,SAAS,KAAK;AAChD,QAAM,cAAcC,MAAAA,OAA6C,IAAI;AACrE,QAAM,WAAWA,MAAAA,OAAgC,IAAI;AACrD,QAAM,UAAUC,kBAAY,CAAC,SAAkC;AAC7D,aAAS,UAAU;AACnB,QAAI,OAAO,QAAQ,WAAY,KAAI,IAAI;AAAA,aAC9B,IAAM,KAA6C,UAAU;AAAA,EACxE,GAAG,CAAC,GAAG,CAAC;AACR,QAAM,eAAeD,MAAAA,OAA0B,IAAI;AACnD,QAAM,CAAC,gBAAgB,iBAAiB,IAAID,MAAAA,SAAS,CAAC;AAEtDG,QAAAA,UAAU,MAAM;AACd,QAAI,UAAU,UAAa,UAAU,oBAAoB,KAAK;AAAA,EAChE,GAAG,CAAC,KAAK,CAAC;AAEVA,QAAAA,UAAU,MAAM;AACd,QAAI,oBAAoB,aAAa,SAAS;AAC5C,wBAAkB,aAAa,QAAQ,eAAe,CAAC;AAAA,IACzD,OAAO;AACL,wBAAkB,CAAC;AAAA,IACrB;AAAA,EACF,GAAG,CAAC,kBAAkB,gBAAgB,CAAC;AAEvC,QAAM,gBAAgBC,GAAAA;AAAAA,IACpB;AAAA,IACAC,eAAAA,kBAAkB,IAAI,EAAE;AAAA,IACxBA,eAAAA,kBAAkB,IAAI,EAAE;AAAA,IACxB;AAAA,IACA;AAAA,IACA;AAAA,IACA,mBAAmB,UAAU,YAAY,UAAU;AAAA,IACnD;AAAA,IACA;AAAA,EAAA;AAGF,QAAM,uBAAuB,MAAM;AACjC,UAAM,aAAa;AAAA,MACjB,iBAAiB;AAAA,MACjB,OAAO;AAAA,MACP,aAAa,QACT,wBACA,YACE,0BACA;AAAA,MACN,WAAW;AAAA,IAAA;AAGb,WAAO;AAAA,MACL,GAAG;AAAA,MACH,mBAAmB,QACf,wBACA;AAAA,MACJ,qBAAqB;AAAA,IAAA;AAAA,EAEzB;AAEA,QAAM,oBAAoB,MACxB,WACI;AAAA,IACE,iBAAiB;AAAA,IACjB,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,SAAS;AAAA,EAAA,IAEX,CAAA;AAEN,QAAM,gBAAgB,MAAM;AAC1B,QAAI,MAAO,QAAO,EAAE,OAAO,sBAAA;AAC3B,QAAI,UAAW,QAAO,EAAE,OAAO,wBAAA;AAC/B,WAAO,EAAE,OAAO,2BAAA;AAAA,EAClB;AAEA,QAAM,kBAAkB,OAAO;AAAA,IAC7B,iBAAiB;AAAA,IACjB,OAAO;AAAA,EAAA;AAGT,QAAM,uBAAuB,OAAO;AAAA,IAClC,iBAAiB;AAAA,IACjB,OAAO;AAAA,EAAA;AAGT,QAAM,oBAAoB,CAAC,UAA+C;AACxE,UAAM,WAAW,MAAM,OAAO;AAC9B,kBAAc,QAAQ;AACtB,yCAAW;AAEX,QAAI,YAAY,QAAS,cAAa,YAAY,OAAO;AACzD,gBAAY,UAAU,WAAW,MAAM;AACrC,2CAAW;AAAA,IACb,GAAG,aAAa;AAAA,EAClB;AAEA,QAAM,eAAe,MAAM,qCAAW;AAEtC,QAAM,cAAc,MAAM;;AACxB,kBAAc,EAAE;AAChB,yCAAW;AACX,yCAAW;AACX,mBAAS,YAAT,mBAAkB;AAAA,EACpB;AAEA,QAAM,gBAAgB,CAAC,UAA+B;AACpD,QAAI,MAAM,QAAQ,SAAS;AACzB,YAAM,eAAA;AACN,mBAAA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,oBACJ,SAAS,OACL,oBACA,SAAS,OACP,oBACA;AAER,QAAM,eAAe,mBAAmB,iBAAiB,IAAI;AAE7D,QAAM,aAAa,MACjBC,+BAAC,OAAA,EAAI,WAAU,WAAU,MAAK,QAAO,QAAO,gBAAe,SAAQ,aACjE,UAAAA,2BAAAA,IAAC,QAAA,EAAK,eAAc,SAAQ,gBAAe,SAAQ,aAAa,GAAG,GAAE,8CAAA,CAA8C,EAAA,CACrH;AAGF,QAAM,YAAY,MAChBA,+BAAC,OAAA,EAAI,WAAU,WAAU,MAAK,QAAO,QAAO,gBAAe,SAAQ,aACjE,UAAAA,2BAAAA,IAAC,QAAA,EAAK,eAAc,SAAQ,gBAAe,SAAQ,aAAa,GAAG,GAAE,uBAAA,CAAuB,EAAA,CAC9F;AAGF,SACEC,2BAAAA,KAAC,OAAA,EAAI,WAAU,aACb,UAAA;AAAA,IAAAA,2BAAAA,KAAC,OAAA,EAAI,WAAU,kBACb,UAAA;AAAA,MAAAD,2BAAAA,IAAC,OAAA,EAAI,WAAU,6EACb,UAAAA,2BAAAA,IAAC,QAAA,EAAK,OAAO,cAAA,GACX,UAAAA,2BAAAA,IAAC,YAAA,CAAA,CAAW,EAAA,CACd,GACF;AAAA,MAEAA,2BAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UACC,KAAK;AAAA,UACL,MAAK;AAAA,UACL;AAAA,UACA,OAAO;AAAA,UACP;AAAA,UACA;AAAA,UACA,WAAW;AAAA,UACX,OAAO;AAAA,YACL,GAAG,qBAAA;AAAA,YACH,GAAG,kBAAA;AAAA,UAAkB;AAAA,UAEvB,UAAU;AAAA,UACV,WAAW;AAAA,UACX,SAAS,MAAM,aAAa,IAAI;AAAA,UAChC,QAAQ,MAAM,aAAa,KAAK;AAAA,UAChC,cAAc,CAAC,MAAM;AACnB,gBAAI,CAAC,YAAY,CAAC,SAAS,CAAC,WAAW;AACrC,gBAAE,cAAc,MAAM,cAAc;AAAA,YACtC;AAAA,UACF;AAAA,UACA,cAAc,CAAC,MAAM;AACnB,gBAAI,CAAC,YAAY,CAAC,SAAS,CAAC,WAAW;AACrC,gBAAE,cAAc,MAAM,cAAc;AAAA,YACtC;AAAA,UACF;AAAA,QAAA;AAAA,MAAA;AAAA,qCAGD,SAAA,EAAO,UAAA;AAAA;AAAA;AAAA;AAAA;AAAA,WAKN;AAAA,MAED,aAAa,cAAc,CAAC,YAC3BA,2BAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UACC,SAAS;AAAA,UACT,WAAW,wFAAwF,iBAAiB;AAAA,UACpH,OAAO;AAAA,YACL,GAAG,qBAAA;AAAA,YACH,OAAO,GAAG,YAAY;AAAA,UAAA;AAAA,UAExB,cAAc,CAAC,MAAM;AACnB,cAAE,cAAc,MAAM,kBAAkB;AACxC,cAAE,cAAc,MAAM,QAAQ;AAAA,UAChC;AAAA,UACA,cAAc,CAAC,MAAM;AACnB,cAAE,cAAc,MAAM,kBAAkB;AACxC,cAAE,cAAc,MAAM,QAAQ;AAAA,UAChC;AAAA,UACA,cAAW;AAAA,UACX,MAAK;AAAA,UAEL,yCAAC,WAAA,CAAA,CAAU;AAAA,QAAA;AAAA,MAAA;AAAA,MAId,oBAAoB,CAAC,YACpBA,2BAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UACC,KAAK;AAAA,UACL,SAAS;AAAA,UACT,WAAU;AAAA,UACV,OAAO,gBAAA;AAAA,UACP,cAAc,CAAC,MAAM;AACnB,cAAE,cAAc,MAAM,kBAAkB;AAAA,UAC1C;AAAA,UACA,cAAc,CAAC,MAAM;AACnB,cAAE,cAAc,MAAM,kBAAkB;AAAA,UAC1C;AAAA,UACA,MAAK;AAAA,UAEL,UAAAA,2BAAAA,IAAC,QAAA,EAAK,WAAU,uBAAuB,UAAA,iBAAA,CAAiB;AAAA,QAAA;AAAA,MAAA;AAAA,IAC1D,GAEJ;AAAA,IAEC,gBAAgBA,2BAAAA,IAACE,aAAAA,cAAA,EAAa,SAAS,aAAA,CAAc;AAAA,EAAA,GACxD;AAEJ,CAAC;AAED,cAAc,cAAc;;"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useState, useRef, useEffect } from "react";
|
|
2
|
+
import React, { useState, useRef, useCallback, useEffect } from "react";
|
|
3
|
+
import { c as cn } from "./cn-wDEkOmcn.js";
|
|
3
4
|
import { a as SIZE_INPUT_CONFIG } from "./componentSizes-CdWNL526.js";
|
|
4
|
-
|
|
5
|
+
import { E as ErrorMessage } from "./ErrorMessage-Dt4cJ-sy.js";
|
|
6
|
+
const LMSearchInput = React.forwardRef(({
|
|
5
7
|
value,
|
|
6
8
|
onChange,
|
|
7
9
|
onSearch,
|
|
@@ -16,11 +18,16 @@ const LMSearchInput = ({
|
|
|
16
18
|
showSearchButton = true,
|
|
17
19
|
searchButtonText = "Search",
|
|
18
20
|
debounceDelay = 300
|
|
19
|
-
}) => {
|
|
21
|
+
}, ref) => {
|
|
20
22
|
const [inputValue, setInputValue] = useState(value || "");
|
|
21
23
|
const [isFocused, setIsFocused] = useState(false);
|
|
22
24
|
const debounceRef = useRef(null);
|
|
23
25
|
const inputRef = useRef(null);
|
|
26
|
+
const setRefs = useCallback((node) => {
|
|
27
|
+
inputRef.current = node;
|
|
28
|
+
if (typeof ref === "function") ref(node);
|
|
29
|
+
else if (ref) ref.current = node;
|
|
30
|
+
}, [ref]);
|
|
24
31
|
const searchBtnRef = useRef(null);
|
|
25
32
|
const [searchBtnWidth, setSearchBtnWidth] = useState(0);
|
|
26
33
|
useEffect(() => {
|
|
@@ -33,14 +40,17 @@ const LMSearchInput = ({
|
|
|
33
40
|
setSearchBtnWidth(0);
|
|
34
41
|
}
|
|
35
42
|
}, [showSearchButton, searchButtonText]);
|
|
36
|
-
const baseClassName =
|
|
37
|
-
w-full
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
const baseClassName = cn(
|
|
44
|
+
"w-full",
|
|
45
|
+
SIZE_INPUT_CONFIG[size].padding,
|
|
46
|
+
SIZE_INPUT_CONFIG[size].height,
|
|
47
|
+
"backdrop-blur-md border rounded-2xl",
|
|
48
|
+
"focus:ring-2 focus:outline-none transition-all duration-300",
|
|
49
|
+
"shadow-sm",
|
|
50
|
+
showSearchButton ? "pr-20" : showClear ? "pr-10" : "pr-4",
|
|
51
|
+
"pl-12",
|
|
52
|
+
className
|
|
53
|
+
);
|
|
44
54
|
const getSearchInputStyles = () => {
|
|
45
55
|
const baseStyles = {
|
|
46
56
|
backgroundColor: "var(--lm-bg-elevated)",
|
|
@@ -106,7 +116,7 @@ const LMSearchInput = ({
|
|
|
106
116
|
/* @__PURE__ */ jsx(
|
|
107
117
|
"input",
|
|
108
118
|
{
|
|
109
|
-
ref:
|
|
119
|
+
ref: setRefs,
|
|
110
120
|
type: "search",
|
|
111
121
|
name,
|
|
112
122
|
value: inputValue,
|
|
@@ -179,27 +189,11 @@ const LMSearchInput = ({
|
|
|
179
189
|
}
|
|
180
190
|
)
|
|
181
191
|
] }),
|
|
182
|
-
errorMessage && /* @__PURE__ */
|
|
183
|
-
"p",
|
|
184
|
-
{
|
|
185
|
-
className: "text-xs flex items-center gap-1",
|
|
186
|
-
style: { color: "var(--lm-error-500)" },
|
|
187
|
-
children: [
|
|
188
|
-
/* @__PURE__ */ jsx("svg", { className: "w-3 h-3", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx(
|
|
189
|
-
"path",
|
|
190
|
-
{
|
|
191
|
-
fillRule: "evenodd",
|
|
192
|
-
d: "M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z",
|
|
193
|
-
clipRule: "evenodd"
|
|
194
|
-
}
|
|
195
|
-
) }),
|
|
196
|
-
errorMessage
|
|
197
|
-
]
|
|
198
|
-
}
|
|
199
|
-
)
|
|
192
|
+
errorMessage && /* @__PURE__ */ jsx(ErrorMessage, { message: errorMessage })
|
|
200
193
|
] });
|
|
201
|
-
};
|
|
194
|
+
});
|
|
195
|
+
LMSearchInput.displayName = "LMSearchInput";
|
|
202
196
|
export {
|
|
203
197
|
LMSearchInput as L
|
|
204
198
|
};
|
|
205
|
-
//# sourceMappingURL=LMSearchInput-
|
|
199
|
+
//# sourceMappingURL=LMSearchInput-DQovqMTN.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LMSearchInput-DQovqMTN.js","sources":["../src/components/Form/LMSearchInput/LMSearchInput.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect, useCallback } from 'react'\nimport { cn } from '../../../utils/cn'\nimport { SIZE_INPUT_CONFIG } from '../../../utils/componentSizes'\nimport type { ComponentSize } from '../../../utils/componentSizes'\nimport { ErrorMessage } from '../../_internal/ErrorMessage'\n\nexport interface LMSearchInputProps {\n /** Current search value */\n value?: string\n /** Change callback */\n onChange?: (value: string) => void\n /** Search submit callback */\n onSearch?: (value: string) => void\n /** Error state */\n error?: boolean\n /** Error message */\n errorMessage?: string\n /** Placeholder */\n placeholder?: string\n /** Disabled state */\n disabled?: boolean\n /** Class name */\n className?: string\n /** Form field name */\n name?: string\n /** Size */\n size?: ComponentSize\n /** Show clear button */\n showClear?: boolean\n /** Show search button */\n showSearchButton?: boolean\n /** Search button text */\n searchButtonText?: string\n /** Debounce delay (ms) */\n debounceDelay?: number\n}\n\nconst LMSearchInput = React.forwardRef<HTMLInputElement, LMSearchInputProps>(({\n value,\n onChange,\n onSearch,\n error = false,\n errorMessage,\n placeholder = 'Search...',\n disabled = false,\n className = '',\n name,\n size = 'md',\n showClear = true,\n showSearchButton = true,\n searchButtonText = 'Search',\n debounceDelay = 300,\n}, ref) => {\n const [inputValue, setInputValue] = useState(value || '')\n const [isFocused, setIsFocused] = useState(false)\n const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null)\n const inputRef = useRef<HTMLInputElement | null>(null)\n const setRefs = useCallback((node: HTMLInputElement | null) => {\n inputRef.current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) (ref as { current: HTMLInputElement | null }).current = node\n }, [ref])\n const searchBtnRef = useRef<HTMLButtonElement>(null)\n const [searchBtnWidth, setSearchBtnWidth] = useState(0)\n\n useEffect(() => {\n if (value !== undefined && value !== null) setInputValue(value)\n }, [value])\n\n useEffect(() => {\n if (showSearchButton && searchBtnRef.current) {\n setSearchBtnWidth(searchBtnRef.current.offsetWidth || 0)\n } else {\n setSearchBtnWidth(0)\n }\n }, [showSearchButton, searchButtonText])\n\n const baseClassName = cn(\n 'w-full',\n SIZE_INPUT_CONFIG[size].padding,\n SIZE_INPUT_CONFIG[size].height,\n 'backdrop-blur-md border rounded-2xl',\n 'focus:ring-2 focus:outline-none transition-all duration-300',\n 'shadow-sm',\n showSearchButton ? 'pr-20' : showClear ? 'pr-10' : 'pr-4',\n 'pl-12',\n className\n )\n\n const getSearchInputStyles = () => {\n const baseStyles = {\n backgroundColor: 'var(--lm-bg-elevated)',\n color: 'var(--lm-text-primary)',\n borderColor: error\n ? 'var(--lm-error-300)'\n : isFocused\n ? 'var(--lm-primary-400)'\n : 'var(--lm-border-default)',\n boxShadow: 'var(--lm-shadow-sm)',\n } as React.CSSProperties\n\n return {\n ...baseStyles,\n '--tw-ring-color': error\n ? 'var(--lm-error-400)'\n : 'var(--lm-primary-400)',\n '--tw-ring-opacity': '0.3',\n }\n }\n\n const getDisabledStyles = () =>\n disabled\n ? {\n backgroundColor: 'var(--lm-bg-paper)',\n color: 'var(--lm-text-disabled)',\n cursor: 'not-allowed',\n opacity: 0.6,\n }\n : {}\n\n const getIconStyles = () => {\n if (error) return { color: 'var(--lm-error-400)' }\n if (isFocused) return { color: 'var(--lm-primary-500)' }\n return { color: 'var(--lm-text-secondary)' }\n }\n\n const getButtonStyles = () => ({\n backgroundColor: 'var(--lm-primary-500)',\n color: 'white',\n })\n\n const getClearButtonStyles = () => ({\n backgroundColor: 'var(--lm-bg-paper)',\n color: 'var(--lm-text-secondary)',\n })\n\n const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = event.target.value\n setInputValue(newValue)\n onChange?.(newValue)\n\n if (debounceRef.current) clearTimeout(debounceRef.current)\n debounceRef.current = setTimeout(() => {\n onSearch?.(newValue)\n }, debounceDelay)\n }\n\n const handleSearch = () => onSearch?.(inputValue)\n\n const handleClear = () => {\n setInputValue('')\n onChange?.('')\n onSearch?.('')\n inputRef.current?.focus()\n }\n\n const handleKeyDown = (event: React.KeyboardEvent) => {\n if (event.key === 'Enter') {\n event.preventDefault()\n handleSearch()\n }\n }\n\n const clearBtnSizeClass =\n size === 'sm'\n ? 'w-7 h-7 text-xs'\n : size === 'lg'\n ? 'w-9 h-9 text-sm'\n : 'w-8 h-8 text-sm'\n\n const clearRightPx = showSearchButton ? searchBtnWidth + 8 : 8\n\n const SearchIcon = () => (\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z\" />\n </svg>\n )\n\n const ClearIcon = () => (\n <svg className=\"w-3 h-3\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n )\n\n return (\n <div className=\"space-y-2\">\n <div className=\"relative group\">\n <div className=\"absolute inset-y-0 left-0 pl-4 flex items-center pointer-events-none z-10\">\n <span style={getIconStyles()}>\n <SearchIcon />\n </span>\n </div>\n\n <input\n ref={setRefs}\n type=\"search\"\n name={name}\n value={inputValue}\n placeholder={placeholder}\n disabled={disabled}\n className={baseClassName}\n style={{\n ...getSearchInputStyles(),\n ...getDisabledStyles(),\n } as React.CSSProperties}\n onChange={handleInputChange}\n onKeyDown={handleKeyDown}\n onFocus={() => setIsFocused(true)}\n onBlur={() => setIsFocused(false)}\n onMouseEnter={(e) => {\n if (!disabled && !error && !isFocused) {\n e.currentTarget.style.borderColor = 'var(--lm-border-strong)'\n }\n }}\n onMouseLeave={(e) => {\n if (!disabled && !error && !isFocused) {\n e.currentTarget.style.borderColor = 'var(--lm-border-default)'\n }\n }}\n />\n\n <style>{`\n input[type='search']::-webkit-search-cancel-button {\n -webkit-appearance: none;\n appearance: none;\n }\n `}</style>\n\n {showClear && inputValue && !disabled && (\n <button\n onClick={handleClear}\n className={`absolute top-1/2 -translate-y-1/2 z-10 rounded-full flex items-center justify-center ${clearBtnSizeClass}`}\n style={{\n ...getClearButtonStyles(),\n right: `${clearRightPx}px`,\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor = 'var(--lm-bg-elevated)'\n e.currentTarget.style.color = 'var(--lm-text-primary)'\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = 'var(--lm-bg-paper)'\n e.currentTarget.style.color = 'var(--lm-text-secondary)'\n }}\n aria-label=\"Clear\"\n type=\"button\"\n >\n <ClearIcon />\n </button>\n )}\n\n {showSearchButton && !disabled && (\n <button\n ref={searchBtnRef}\n onClick={handleSearch}\n className=\"absolute inset-y-0 right-0 px-4 rounded-r-2xl transition-colors duration-200 z-20\"\n style={getButtonStyles()}\n onMouseEnter={(e) => {\n e.currentTarget.style.backgroundColor = 'var(--lm-primary-600)'\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = 'var(--lm-primary-500)'\n }}\n type=\"button\"\n >\n <span className=\"text-sm font-medium\">{searchButtonText}</span>\n </button>\n )}\n </div>\n\n {errorMessage && <ErrorMessage message={errorMessage} />}\n </div>\n )\n})\n\nLMSearchInput.displayName = 'LMSearchInput'\n\nexport default LMSearchInput\n"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useState, useRef, useEffect } from "react";
|
|
3
|
+
import { c as cn } from "./cn-wDEkOmcn.js";
|
|
3
4
|
import { d as SIZE_SELECTOR_CONFIG } from "./componentSizes-CdWNL526.js";
|
|
5
|
+
import { E as ErrorMessage } from "./ErrorMessage-Dt4cJ-sy.js";
|
|
4
6
|
const SIZE_DROPDOWN_CONFIG = {
|
|
5
7
|
xs: { maxHeight: "max-h-32", optionPadding: "px-3 py-1.5", optionTextSize: "text-xs" },
|
|
6
8
|
sm: { maxHeight: "max-h-40", optionPadding: "px-3 py-2", optionTextSize: "text-xs" },
|
|
@@ -9,6 +11,8 @@ const SIZE_DROPDOWN_CONFIG = {
|
|
|
9
11
|
xl: { maxHeight: "max-h-64", optionPadding: "px-5 py-3", optionTextSize: "text-base" },
|
|
10
12
|
"2xl": { maxHeight: "max-h-72", optionPadding: "px-6 py-4", optionTextSize: "text-lg" }
|
|
11
13
|
};
|
|
14
|
+
const ChevronDownIcon = () => /* @__PURE__ */ jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }) });
|
|
15
|
+
const CheckIcon = () => /* @__PURE__ */ jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) });
|
|
12
16
|
const LMSelect = ({
|
|
13
17
|
options,
|
|
14
18
|
value,
|
|
@@ -78,13 +82,16 @@ const LMSelect = ({
|
|
|
78
82
|
onDropdownVisibleChange == null ? void 0 : onDropdownVisibleChange(newIsOpen);
|
|
79
83
|
}
|
|
80
84
|
};
|
|
81
|
-
const baseClassName =
|
|
82
|
-
w-full
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
85
|
+
const baseClassName = cn(
|
|
86
|
+
"w-full",
|
|
87
|
+
SIZE_SELECTOR_CONFIG[size].padding,
|
|
88
|
+
SIZE_SELECTOR_CONFIG[size].height,
|
|
89
|
+
SIZE_SELECTOR_CONFIG[size].fontSize,
|
|
90
|
+
"border rounded-xl",
|
|
91
|
+
"cursor-pointer select-none",
|
|
92
|
+
"flex items-center justify-between",
|
|
93
|
+
className
|
|
94
|
+
);
|
|
88
95
|
const getSelectorStyles = () => {
|
|
89
96
|
const baseStyles = {
|
|
90
97
|
backgroundColor: "var(--lm-bg-elevated)",
|
|
@@ -148,18 +155,6 @@ const LMSelect = ({
|
|
|
148
155
|
}
|
|
149
156
|
return selectedOption ? selectedOption.label : placeholder;
|
|
150
157
|
};
|
|
151
|
-
const ChevronDown = () => /* @__PURE__ */ jsx(
|
|
152
|
-
"svg",
|
|
153
|
-
{
|
|
154
|
-
className: `w-4 h-4 transition-transform duration-200 ${isOpen ? "rotate-180" : ""}`,
|
|
155
|
-
fill: "none",
|
|
156
|
-
stroke: "currentColor",
|
|
157
|
-
viewBox: "0 0 24 24",
|
|
158
|
-
style: getIconStyles(),
|
|
159
|
-
children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" })
|
|
160
|
-
}
|
|
161
|
-
);
|
|
162
|
-
const CheckIcon = () => /* @__PURE__ */ jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) });
|
|
163
158
|
return /* @__PURE__ */ jsxs("div", { className: "relative", ref: dropdownRef, children: [
|
|
164
159
|
/* @__PURE__ */ jsx(
|
|
165
160
|
"select",
|
|
@@ -180,7 +175,9 @@ const LMSelect = ({
|
|
|
180
175
|
{
|
|
181
176
|
className: baseClassName,
|
|
182
177
|
onClick: toggleDropdown,
|
|
183
|
-
role: "
|
|
178
|
+
role: "combobox",
|
|
179
|
+
"aria-expanded": isOpen,
|
|
180
|
+
"aria-haspopup": "listbox",
|
|
184
181
|
tabIndex: disabled ? -1 : 0,
|
|
185
182
|
style: {
|
|
186
183
|
...getSelectorStyles(),
|
|
@@ -222,13 +219,21 @@ const LMSelect = ({
|
|
|
222
219
|
children: getDisplayText()
|
|
223
220
|
}
|
|
224
221
|
),
|
|
225
|
-
/* @__PURE__ */ jsx(
|
|
222
|
+
/* @__PURE__ */ jsx(
|
|
223
|
+
"span",
|
|
224
|
+
{
|
|
225
|
+
className: `transition-transform duration-200 ${isOpen ? "rotate-180" : ""}`,
|
|
226
|
+
style: getIconStyles(),
|
|
227
|
+
children: /* @__PURE__ */ jsx(ChevronDownIcon, {})
|
|
228
|
+
}
|
|
229
|
+
)
|
|
226
230
|
]
|
|
227
231
|
}
|
|
228
232
|
),
|
|
229
233
|
isOpen && /* @__PURE__ */ jsx(
|
|
230
234
|
"div",
|
|
231
235
|
{
|
|
236
|
+
role: "listbox",
|
|
232
237
|
className: `absolute left-0 right-0 z-50 border rounded-xl overflow-y-auto ${SIZE_DROPDOWN_CONFIG[size].maxHeight}`,
|
|
233
238
|
style: {
|
|
234
239
|
...getDropdownStyles(),
|
|
@@ -237,14 +242,15 @@ const LMSelect = ({
|
|
|
237
242
|
children: options.map((option, index) => /* @__PURE__ */ jsx(
|
|
238
243
|
"div",
|
|
239
244
|
{
|
|
240
|
-
className:
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
245
|
+
className: cn(
|
|
246
|
+
SIZE_DROPDOWN_CONFIG[size].optionPadding,
|
|
247
|
+
SIZE_DROPDOWN_CONFIG[size].optionTextSize,
|
|
248
|
+
"font-medium cursor-pointer transition-all duration-150",
|
|
249
|
+
option.disabled && "cursor-not-allowed",
|
|
250
|
+
index === 0 && "rounded-t-xl",
|
|
251
|
+
index === options.length - 1 && "rounded-b-xl",
|
|
252
|
+
index > 0 && "border-t"
|
|
253
|
+
),
|
|
248
254
|
style: {
|
|
249
255
|
...getOptionStyles(option),
|
|
250
256
|
borderTopColor: index > 0 ? "var(--lm-border-light)" : "transparent"
|
|
@@ -283,27 +289,10 @@ const LMSelect = ({
|
|
|
283
289
|
))
|
|
284
290
|
}
|
|
285
291
|
),
|
|
286
|
-
errorMessage && /* @__PURE__ */
|
|
287
|
-
"p",
|
|
288
|
-
{
|
|
289
|
-
className: "text-xs flex items-center gap-1 mt-2",
|
|
290
|
-
style: { color: "var(--lm-error-500)" },
|
|
291
|
-
children: [
|
|
292
|
-
/* @__PURE__ */ jsx("svg", { className: "w-3 h-3", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx(
|
|
293
|
-
"path",
|
|
294
|
-
{
|
|
295
|
-
fillRule: "evenodd",
|
|
296
|
-
d: "M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z",
|
|
297
|
-
clipRule: "evenodd"
|
|
298
|
-
}
|
|
299
|
-
) }),
|
|
300
|
-
errorMessage
|
|
301
|
-
]
|
|
302
|
-
}
|
|
303
|
-
)
|
|
292
|
+
errorMessage && /* @__PURE__ */ jsx(ErrorMessage, { message: errorMessage, className: "mt-2" })
|
|
304
293
|
] });
|
|
305
294
|
};
|
|
306
295
|
export {
|
|
307
296
|
LMSelect as L
|
|
308
297
|
};
|
|
309
|
-
//# sourceMappingURL=LMSelect-
|
|
298
|
+
//# sourceMappingURL=LMSelect-BPfW-AHI.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LMSelect-BPfW-AHI.js","sources":["../src/components/Form/LMSelect/LMSelect.tsx"],"sourcesContent":["import React, { useState, useRef, useEffect } from 'react'\nimport { cn } from '../../../utils/cn'\nimport { SIZE_SELECTOR_CONFIG } from '../../../utils/componentSizes'\nimport type { ComponentSize } from '../../../utils/componentSizes'\nimport { ErrorMessage } from '../../_internal/ErrorMessage'\n\nexport interface LMSelectOption {\n value: string | number\n label: string\n disabled?: boolean\n}\n\nexport interface LMSelectProps {\n /** Options */\n options: LMSelectOption[]\n /** Current value */\n value?: string | number | (string | number)[]\n /** Change callback */\n onChange?: (value: string | number | (string | number)[]) => void\n /** Dropdown visibility change callback */\n onDropdownVisibleChange?: (visible: boolean) => void\n /** Error state */\n error?: boolean\n /** Error message */\n errorMessage?: string\n /** Placeholder */\n placeholder?: string\n /** Disabled state */\n disabled?: boolean\n /** Class name */\n className?: string\n /** Form field name */\n name?: string\n /** Size */\n size?: ComponentSize\n /** Multiple selection */\n multiple?: boolean\n}\n\nconst SIZE_DROPDOWN_CONFIG: Record<\n ComponentSize,\n {\n maxHeight: string\n optionPadding: string\n optionTextSize: string\n }\n> = {\n xs: { maxHeight: 'max-h-32', optionPadding: 'px-3 py-1.5', optionTextSize: 'text-xs' },\n sm: { maxHeight: 'max-h-40', optionPadding: 'px-3 py-2', optionTextSize: 'text-xs' },\n md: { maxHeight: 'max-h-48', optionPadding: 'px-4 py-2.5', optionTextSize: 'text-sm' },\n lg: { maxHeight: 'max-h-56', optionPadding: 'px-4 py-3', optionTextSize: 'text-sm' },\n xl: { maxHeight: 'max-h-64', optionPadding: 'px-5 py-3', optionTextSize: 'text-base' },\n '2xl': { maxHeight: 'max-h-72', optionPadding: 'px-6 py-4', optionTextSize: 'text-lg' },\n}\n\nconst ChevronDownIcon: React.FC = () => (\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M19 9l-7 7-7-7\" />\n </svg>\n)\n\nconst CheckIcon: React.FC = () => (\n <svg className=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M5 13l4 4L19 7\" />\n </svg>\n)\n\nconst LMSelect: React.FC<LMSelectProps> = ({\n options,\n value,\n onChange,\n onDropdownVisibleChange,\n error = false,\n errorMessage,\n placeholder = 'Select...',\n disabled = false,\n className = '',\n name,\n size = 'md',\n multiple = false,\n}) => {\n const [isOpen, setIsOpen] = useState(false)\n const [selectedOption, setSelectedOption] = useState<LMSelectOption | null>(null)\n const [selectedOptions, setSelectedOptions] = useState<LMSelectOption[]>([])\n const dropdownRef = useRef<HTMLDivElement>(null)\n\n useEffect(() => {\n if (!multiple) {\n if (value !== undefined && value !== null && !Array.isArray(value)) {\n const option = options.find((opt) => opt.value === value)\n setSelectedOption(option || null)\n } else {\n setSelectedOption(null)\n }\n }\n }, [value, options, multiple])\n\n useEffect(() => {\n if (multiple && Array.isArray(value)) {\n const selectedOpts = options.filter((opt) => value.includes(opt.value))\n setSelectedOptions(selectedOpts)\n } else if (multiple) {\n setSelectedOptions([])\n }\n }, [value, options, multiple])\n\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {\n setIsOpen(false)\n onDropdownVisibleChange?.(false)\n }\n }\n\n if (isOpen) {\n document.addEventListener('mousedown', handleClickOutside)\n return () => document.removeEventListener('mousedown', handleClickOutside)\n }\n }, [isOpen, onDropdownVisibleChange])\n\n const handleSelect = (option: LMSelectOption) => {\n if (option.disabled) return\n\n if (multiple) {\n const currentValues = Array.isArray(value) ? value : []\n const isSelected = currentValues.includes(option.value)\n const newValues = isSelected\n ? currentValues.filter((v) => v !== option.value)\n : [...currentValues, option.value]\n onChange?.(newValues)\n } else {\n setSelectedOption(option)\n onChange?.(option.value)\n setIsOpen(false)\n onDropdownVisibleChange?.(false)\n }\n }\n\n const toggleDropdown = () => {\n if (!disabled) {\n const newIsOpen = !isOpen\n setIsOpen(newIsOpen)\n onDropdownVisibleChange?.(newIsOpen)\n }\n }\n\n // Apple-like refined select styling\n const baseClassName = cn(\n 'w-full',\n SIZE_SELECTOR_CONFIG[size].padding,\n SIZE_SELECTOR_CONFIG[size].height,\n SIZE_SELECTOR_CONFIG[size].fontSize,\n 'border rounded-xl',\n 'cursor-pointer select-none',\n 'flex items-center justify-between',\n className\n )\n\n const getSelectorStyles = () => {\n // Apple-like refined select styles\n const baseStyles = {\n backgroundColor: 'var(--lm-bg-elevated)',\n color: 'var(--lm-text-primary)',\n borderColor: error ? 'var(--lm-error-300)' : 'var(--lm-border-default)',\n boxShadow: 'var(--lm-shadow-sm)',\n transition: 'all var(--lm-transition-fast) var(--lm-ease-out)',\n }\n\n return {\n ...baseStyles,\n '--tw-ring-color': error ? 'var(--lm-error-400)' : 'var(--lm-primary-400)',\n '--tw-ring-opacity': '0.4',\n }\n }\n\n const getDisabledStyles = () =>\n disabled\n ? {\n backgroundColor: 'var(--lm-bg-paper)',\n color: 'var(--lm-text-disabled)',\n cursor: 'not-allowed',\n opacity: 0.6,\n }\n : {}\n\n const getIconStyles = () =>\n error ? { color: 'var(--lm-error-400)' } : { color: 'var(--lm-text-secondary)' }\n\n // Apple-like refined dropdown styles\n const getDropdownStyles = () => ({\n backgroundColor: 'var(--lm-bg-elevated)',\n borderColor: 'var(--lm-border-default)',\n boxShadow: 'var(--lm-shadow-lg)',\n backdropFilter: 'blur(20px) saturate(180%)',\n WebkitBackdropFilter: 'blur(20px) saturate(180%)',\n })\n\n const isOptionSelected = (optionValue: string | number): boolean => {\n if (multiple) {\n return Array.isArray(value) && value.includes(optionValue)\n }\n return selectedOption?.value === optionValue\n }\n\n const getOptionStyles = (option: LMSelectOption) => {\n const baseStyles = {\n color: option.disabled ? 'var(--lm-text-disabled)' : 'var(--lm-text-primary)',\n backgroundColor: option.disabled ? 'var(--lm-bg-paper)' : 'transparent',\n }\n\n if (isOptionSelected(option.value)) {\n return {\n ...baseStyles,\n backgroundColor: 'var(--lm-primary-50)',\n color: 'var(--lm-primary-700)',\n }\n }\n\n return baseStyles\n }\n\n const getHoverOptionStyles = (option: LMSelectOption) => {\n if (option.disabled) return {}\n\n if (isOptionSelected(option.value)) {\n return { backgroundColor: 'var(--lm-primary-100)' }\n }\n\n return { backgroundColor: 'var(--lm-bg-paper)' }\n }\n\n const getDisplayText = (): string => {\n if (multiple) {\n if (selectedOptions.length === 0) return placeholder\n if (selectedOptions.length === 1) return selectedOptions[0].label\n return `${selectedOptions.length} selected`\n }\n return selectedOption ? selectedOption.label : placeholder\n }\n\n return (\n <div className=\"relative\" ref={dropdownRef}>\n <select\n name={name}\n value={\n multiple\n ? Array.isArray(value)\n ? value.map(String)\n : []\n : value !== undefined && value !== null && !Array.isArray(value)\n ? String(value)\n : ''\n }\n // Empty handler to suppress React controlled component warning for hidden native select\n onChange={() => {}}\n className=\"sr-only\"\n disabled={disabled}\n tabIndex={-1}\n multiple={multiple}\n >\n {options.map((option) => (\n <option key={option.value} value={option.value} disabled={option.disabled}>\n {option.label}\n </option>\n ))}\n </select>\n\n <div\n className={baseClassName}\n onClick={toggleDropdown}\n role=\"combobox\"\n aria-expanded={isOpen}\n aria-haspopup=\"listbox\"\n tabIndex={disabled ? -1 : 0}\n style={{\n ...getSelectorStyles(),\n ...getDisabledStyles(),\n } as React.CSSProperties}\n onMouseEnter={(e) => {\n if (!disabled && !error) {\n e.currentTarget.style.borderColor = 'var(--lm-border-strong)'\n }\n }}\n onMouseLeave={(e) => {\n if (!disabled && !error) {\n e.currentTarget.style.borderColor = 'var(--lm-border-default)'\n }\n }}\n onFocus={(e) => {\n if (!disabled) {\n e.currentTarget.style.borderColor = error\n ? 'var(--lm-error-400)'\n : 'var(--lm-primary-400)'\n }\n }}\n onBlur={(e) => {\n if (!disabled) {\n e.currentTarget.style.borderColor = error\n ? 'var(--lm-error-300)'\n : 'var(--lm-border-default)'\n }\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n toggleDropdown()\n }\n }}\n >\n <span\n style={{\n color:\n (multiple && selectedOptions.length > 0) || selectedOption\n ? 'var(--lm-text-primary)'\n : 'var(--lm-text-secondary)',\n }}\n >\n {getDisplayText()}\n </span>\n <span\n className={`transition-transform duration-200 ${isOpen ? 'rotate-180' : ''}`}\n style={getIconStyles()}\n >\n <ChevronDownIcon />\n </span>\n </div>\n\n {isOpen && (\n <div\n role=\"listbox\"\n className={`absolute left-0 right-0 z-50 border rounded-xl overflow-y-auto ${SIZE_DROPDOWN_CONFIG[size].maxHeight}`}\n style={{\n ...getDropdownStyles(),\n top: 'calc(100% + 4px)',\n }}\n >\n {options.map((option, index) => (\n <div\n key={option.value}\n className={cn(\n SIZE_DROPDOWN_CONFIG[size].optionPadding,\n SIZE_DROPDOWN_CONFIG[size].optionTextSize,\n 'font-medium cursor-pointer transition-all duration-150',\n option.disabled && 'cursor-not-allowed',\n index === 0 && 'rounded-t-xl',\n index === options.length - 1 && 'rounded-b-xl',\n index > 0 && 'border-t'\n )}\n style={{\n ...getOptionStyles(option),\n borderTopColor: index > 0 ? 'var(--lm-border-light)' : 'transparent',\n }}\n onMouseEnter={(e) => {\n if (!option.disabled) {\n Object.assign(e.currentTarget.style, getHoverOptionStyles(option))\n }\n }}\n onMouseLeave={(e) => {\n if (!option.disabled) {\n Object.assign(e.currentTarget.style, getOptionStyles(option))\n }\n }}\n onClick={() => handleSelect(option)}\n role=\"option\"\n aria-selected={isOptionSelected(option.value)}\n >\n <div className=\"flex items-center justify-between\">\n {multiple && (\n <input\n type=\"checkbox\"\n checked={isOptionSelected(option.value)}\n // Empty handler: selection is handled by parent div onClick\n onChange={() => {}}\n className=\"mr-2 cursor-pointer\"\n style={{ accentColor: 'var(--lm-primary-500)' }}\n onClick={(e) => e.stopPropagation()}\n />\n )}\n <span className=\"truncate flex-1\">{option.label}</span>\n {!multiple && isOptionSelected(option.value) && (\n <span className=\"ml-2 shrink-0\" style={{ color: 'var(--lm-primary-600)' }}>\n <CheckIcon />\n </span>\n )}\n </div>\n </div>\n ))}\n </div>\n )}\n\n {errorMessage && <ErrorMessage message={errorMessage} className=\"mt-2\" />}\n </div>\n )\n}\n\nexport default LMSelect\n"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
const jsxRuntime = require("react/jsx-runtime");
|
|
3
3
|
const React = require("react");
|
|
4
|
+
const cn = require("./cn-I2jp-M-K.cjs");
|
|
4
5
|
const componentSizes = require("./componentSizes-DUTZ7uEM.cjs");
|
|
6
|
+
const ErrorMessage = require("./ErrorMessage-CbE7emgD.cjs");
|
|
5
7
|
const SIZE_DROPDOWN_CONFIG = {
|
|
6
8
|
xs: { maxHeight: "max-h-32", optionPadding: "px-3 py-1.5", optionTextSize: "text-xs" },
|
|
7
9
|
sm: { maxHeight: "max-h-40", optionPadding: "px-3 py-2", optionTextSize: "text-xs" },
|
|
@@ -10,6 +12,8 @@ const SIZE_DROPDOWN_CONFIG = {
|
|
|
10
12
|
xl: { maxHeight: "max-h-64", optionPadding: "px-5 py-3", optionTextSize: "text-base" },
|
|
11
13
|
"2xl": { maxHeight: "max-h-72", optionPadding: "px-6 py-4", optionTextSize: "text-lg" }
|
|
12
14
|
};
|
|
15
|
+
const ChevronDownIcon = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }) });
|
|
16
|
+
const CheckIcon = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) });
|
|
13
17
|
const LMSelect = ({
|
|
14
18
|
options,
|
|
15
19
|
value,
|
|
@@ -79,13 +83,16 @@ const LMSelect = ({
|
|
|
79
83
|
onDropdownVisibleChange == null ? void 0 : onDropdownVisibleChange(newIsOpen);
|
|
80
84
|
}
|
|
81
85
|
};
|
|
82
|
-
const baseClassName =
|
|
83
|
-
w-full
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
86
|
+
const baseClassName = cn.cn(
|
|
87
|
+
"w-full",
|
|
88
|
+
componentSizes.SIZE_SELECTOR_CONFIG[size].padding,
|
|
89
|
+
componentSizes.SIZE_SELECTOR_CONFIG[size].height,
|
|
90
|
+
componentSizes.SIZE_SELECTOR_CONFIG[size].fontSize,
|
|
91
|
+
"border rounded-xl",
|
|
92
|
+
"cursor-pointer select-none",
|
|
93
|
+
"flex items-center justify-between",
|
|
94
|
+
className
|
|
95
|
+
);
|
|
89
96
|
const getSelectorStyles = () => {
|
|
90
97
|
const baseStyles = {
|
|
91
98
|
backgroundColor: "var(--lm-bg-elevated)",
|
|
@@ -149,18 +156,6 @@ const LMSelect = ({
|
|
|
149
156
|
}
|
|
150
157
|
return selectedOption ? selectedOption.label : placeholder;
|
|
151
158
|
};
|
|
152
|
-
const ChevronDown = () => /* @__PURE__ */ jsxRuntime.jsx(
|
|
153
|
-
"svg",
|
|
154
|
-
{
|
|
155
|
-
className: `w-4 h-4 transition-transform duration-200 ${isOpen ? "rotate-180" : ""}`,
|
|
156
|
-
fill: "none",
|
|
157
|
-
stroke: "currentColor",
|
|
158
|
-
viewBox: "0 0 24 24",
|
|
159
|
-
style: getIconStyles(),
|
|
160
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" })
|
|
161
|
-
}
|
|
162
|
-
);
|
|
163
|
-
const CheckIcon = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-4 h-4", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) });
|
|
164
159
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", ref: dropdownRef, children: [
|
|
165
160
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
166
161
|
"select",
|
|
@@ -181,7 +176,9 @@ const LMSelect = ({
|
|
|
181
176
|
{
|
|
182
177
|
className: baseClassName,
|
|
183
178
|
onClick: toggleDropdown,
|
|
184
|
-
role: "
|
|
179
|
+
role: "combobox",
|
|
180
|
+
"aria-expanded": isOpen,
|
|
181
|
+
"aria-haspopup": "listbox",
|
|
185
182
|
tabIndex: disabled ? -1 : 0,
|
|
186
183
|
style: {
|
|
187
184
|
...getSelectorStyles(),
|
|
@@ -223,13 +220,21 @@ const LMSelect = ({
|
|
|
223
220
|
children: getDisplayText()
|
|
224
221
|
}
|
|
225
222
|
),
|
|
226
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
223
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
224
|
+
"span",
|
|
225
|
+
{
|
|
226
|
+
className: `transition-transform duration-200 ${isOpen ? "rotate-180" : ""}`,
|
|
227
|
+
style: getIconStyles(),
|
|
228
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(ChevronDownIcon, {})
|
|
229
|
+
}
|
|
230
|
+
)
|
|
227
231
|
]
|
|
228
232
|
}
|
|
229
233
|
),
|
|
230
234
|
isOpen && /* @__PURE__ */ jsxRuntime.jsx(
|
|
231
235
|
"div",
|
|
232
236
|
{
|
|
237
|
+
role: "listbox",
|
|
233
238
|
className: `absolute left-0 right-0 z-50 border rounded-xl overflow-y-auto ${SIZE_DROPDOWN_CONFIG[size].maxHeight}`,
|
|
234
239
|
style: {
|
|
235
240
|
...getDropdownStyles(),
|
|
@@ -238,14 +243,15 @@ const LMSelect = ({
|
|
|
238
243
|
children: options.map((option, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
239
244
|
"div",
|
|
240
245
|
{
|
|
241
|
-
className:
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
246
|
+
className: cn.cn(
|
|
247
|
+
SIZE_DROPDOWN_CONFIG[size].optionPadding,
|
|
248
|
+
SIZE_DROPDOWN_CONFIG[size].optionTextSize,
|
|
249
|
+
"font-medium cursor-pointer transition-all duration-150",
|
|
250
|
+
option.disabled && "cursor-not-allowed",
|
|
251
|
+
index === 0 && "rounded-t-xl",
|
|
252
|
+
index === options.length - 1 && "rounded-b-xl",
|
|
253
|
+
index > 0 && "border-t"
|
|
254
|
+
),
|
|
249
255
|
style: {
|
|
250
256
|
...getOptionStyles(option),
|
|
251
257
|
borderTopColor: index > 0 ? "var(--lm-border-light)" : "transparent"
|
|
@@ -284,25 +290,8 @@ const LMSelect = ({
|
|
|
284
290
|
))
|
|
285
291
|
}
|
|
286
292
|
),
|
|
287
|
-
errorMessage && /* @__PURE__ */ jsxRuntime.
|
|
288
|
-
"p",
|
|
289
|
-
{
|
|
290
|
-
className: "text-xs flex items-center gap-1 mt-2",
|
|
291
|
-
style: { color: "var(--lm-error-500)" },
|
|
292
|
-
children: [
|
|
293
|
-
/* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-3 h-3", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
294
|
-
"path",
|
|
295
|
-
{
|
|
296
|
-
fillRule: "evenodd",
|
|
297
|
-
d: "M8.257 3.099c.765-1.36 2.722-1.36 3.486 0l5.58 9.92c.75 1.334-.213 2.98-1.742 2.98H4.42c-1.53 0-2.493-1.646-1.743-2.98l5.58-9.92zM11 13a1 1 0 11-2 0 1 1 0 012 0zm-1-8a1 1 0 00-1 1v3a1 1 0 002 0V6a1 1 0 00-1-1z",
|
|
298
|
-
clipRule: "evenodd"
|
|
299
|
-
}
|
|
300
|
-
) }),
|
|
301
|
-
errorMessage
|
|
302
|
-
]
|
|
303
|
-
}
|
|
304
|
-
)
|
|
293
|
+
errorMessage && /* @__PURE__ */ jsxRuntime.jsx(ErrorMessage.ErrorMessage, { message: errorMessage, className: "mt-2" })
|
|
305
294
|
] });
|
|
306
295
|
};
|
|
307
296
|
exports.LMSelect = LMSelect;
|
|
308
|
-
//# sourceMappingURL=LMSelect-
|
|
297
|
+
//# sourceMappingURL=LMSelect-xIVolEhx.cjs.map
|