@loword/loword-design-system 0.0.10 → 0.0.13

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.
Files changed (266) hide show
  1. package/dist/components/LDAccordion/AccordionBase.d.ts +41 -0
  2. package/dist/components/LDAccordion/AccordionBase.d.ts.map +1 -0
  3. package/dist/components/LDAccordion/AccordionBase.js +24 -0
  4. package/dist/components/LDAccordion/LDAccordion.d.ts +31 -0
  5. package/dist/components/LDAccordion/LDAccordion.d.ts.map +1 -0
  6. package/dist/components/LDAccordion/LDAccordion.js +21 -0
  7. package/dist/components/LDAutoComplete/AutoCompleteBase.js +6 -6
  8. package/dist/components/LDAvatar/LDAvatar.d.ts +1 -1
  9. package/dist/components/LDAvatar/LDAvatar.d.ts.map +1 -1
  10. package/dist/components/LDAvatar/LDAvatar.js +19 -10
  11. package/dist/components/LDBadge/LDBadge.d.ts +5 -6
  12. package/dist/components/LDBadge/LDBadge.d.ts.map +1 -1
  13. package/dist/components/LDBadge/LDBadge.js +2 -2
  14. package/dist/components/LDBreadCrumb/LDBreadCrumb.d.ts +1 -2
  15. package/dist/components/LDBreadCrumb/LDBreadCrumb.d.ts.map +1 -1
  16. package/dist/components/LDButton/LDButton.d.ts +3 -3
  17. package/dist/components/LDButton/LDButton.d.ts.map +1 -1
  18. package/dist/components/LDButton/LDButton.js +5 -5
  19. package/dist/components/LDCalendar/CalendarBase.d.ts +17 -0
  20. package/dist/components/LDCalendar/CalendarBase.d.ts.map +1 -0
  21. package/dist/components/LDCalendar/CalendarBase.js +49 -0
  22. package/dist/components/LDCalendar/LDCalendar.d.ts +8 -14
  23. package/dist/components/LDCalendar/LDCalendar.d.ts.map +1 -1
  24. package/dist/components/LDCalendar/LDCalendar.js +51 -39
  25. package/dist/components/LDCarousel/CarouselBase.d.ts +3 -3
  26. package/dist/components/LDCarousel/CarouselBase.d.ts.map +1 -1
  27. package/dist/components/LDCarousel/CarouselBase.js +12 -6
  28. package/dist/components/LDCarousel/LDCarousel.d.ts +7 -8
  29. package/dist/components/LDCarousel/LDCarousel.d.ts.map +1 -1
  30. package/dist/components/LDCarousel/LDCarousel.js +2 -2
  31. package/dist/components/LDCheckbox/CheckboxBase.d.ts +1 -3
  32. package/dist/components/LDCheckbox/CheckboxBase.d.ts.map +1 -1
  33. package/dist/components/LDCheckbox/CheckboxBase.js +4 -4
  34. package/dist/components/LDCheckbox/LDCheckbox.d.ts +2 -5
  35. package/dist/components/LDCheckbox/LDCheckbox.d.ts.map +1 -1
  36. package/dist/components/LDCheckbox/LDCheckbox.js +66 -8
  37. package/dist/components/LDCheckbox/LDCheckboxGroup.d.ts +3 -3
  38. package/dist/components/LDCheckbox/LDCheckboxGroup.d.ts.map +1 -1
  39. package/dist/components/LDCheckbox/LDCheckboxGroup.js +11 -2
  40. package/dist/components/LDCheckbox/LDFormCheckbox.d.ts +12 -0
  41. package/dist/components/LDCheckbox/LDFormCheckbox.d.ts.map +1 -0
  42. package/dist/components/LDCheckbox/LDFormCheckbox.js +8 -0
  43. package/dist/components/LDCheckbox/LDFormCheckboxGroup.d.ts +11 -0
  44. package/dist/components/LDCheckbox/LDFormCheckboxGroup.d.ts.map +1 -0
  45. package/dist/components/LDCheckbox/LDFormCheckboxGroup.js +8 -0
  46. package/dist/components/LDDataCalendar/DataCalendarBase.d.ts +17 -1
  47. package/dist/components/LDDataCalendar/DataCalendarBase.d.ts.map +1 -1
  48. package/dist/components/LDDataCalendar/DataCalendarBase.js +34 -4
  49. package/dist/components/LDDataCalendar/LDDataCalendar.d.ts +27 -10
  50. package/dist/components/LDDataCalendar/LDDataCalendar.d.ts.map +1 -1
  51. package/dist/components/LDDataCalendar/LDDataCalendar.js +8 -8
  52. package/dist/components/LDDatePicker/LDDatePicker.d.ts +10 -4
  53. package/dist/components/LDDatePicker/LDDatePicker.d.ts.map +1 -1
  54. package/dist/components/LDDatePicker/LDDatePicker.js +95 -25
  55. package/dist/components/LDDatePicker/LDFormDatePicker.d.ts +13 -0
  56. package/dist/components/LDDatePicker/LDFormDatePicker.d.ts.map +1 -0
  57. package/dist/components/LDDatePicker/LDFormDatePicker.js +15 -0
  58. package/dist/components/LDDateRangePicker/LDDateRangePicker.d.ts +13 -6
  59. package/dist/components/LDDateRangePicker/LDDateRangePicker.d.ts.map +1 -1
  60. package/dist/components/LDDateRangePicker/LDDateRangePicker.js +143 -93
  61. package/dist/components/LDDateRangePicker/LDFormDateRangePicker.d.ts +13 -0
  62. package/dist/components/LDDateRangePicker/LDFormDateRangePicker.d.ts.map +1 -0
  63. package/dist/components/LDDateRangePicker/LDFormDateRangePicker.js +20 -0
  64. package/dist/components/LDDrawer/LDDrawer.d.ts +2 -0
  65. package/dist/components/LDDrawer/LDDrawer.d.ts.map +1 -1
  66. package/dist/components/LDDrawer/LDDrawer.js +2 -2
  67. package/dist/components/LDEditor/LDEditor.d.ts.map +1 -1
  68. package/dist/components/LDEditor/LDEditor.js +94 -54
  69. package/dist/components/LDEmpty/EmptyBase.d.ts +19 -0
  70. package/dist/components/LDEmpty/EmptyBase.d.ts.map +1 -0
  71. package/dist/components/LDEmpty/EmptyBase.js +18 -0
  72. package/dist/components/LDEmpty/LDEmpty.d.ts +35 -0
  73. package/dist/components/LDEmpty/LDEmpty.d.ts.map +1 -0
  74. package/dist/components/LDEmpty/LDEmpty.js +30 -0
  75. package/dist/components/LDFileUpload/FileUploadBase.d.ts +11 -3
  76. package/dist/components/LDFileUpload/FileUploadBase.d.ts.map +1 -1
  77. package/dist/components/LDFileUpload/FileUploadBase.js +21 -21
  78. package/dist/components/LDFileUpload/LDFileUpload.d.ts +3 -0
  79. package/dist/components/LDFileUpload/LDFileUpload.d.ts.map +1 -1
  80. package/dist/components/LDFileUpload/LDFileUpload.js +3 -3
  81. package/dist/components/LDFileUpload/LDFileUploadList.d.ts +3 -0
  82. package/dist/components/LDFileUpload/LDFileUploadList.d.ts.map +1 -1
  83. package/dist/components/LDFileUpload/LDFileUploadList.js +1 -3
  84. package/dist/components/LDFileUpload/LDImageUpload.d.ts +5 -0
  85. package/dist/components/LDFileUpload/LDImageUpload.d.ts.map +1 -1
  86. package/dist/components/LDFileUpload/LDImageUpload.js +5 -3
  87. package/dist/components/LDFileUpload/LDImageUploadList.d.ts +3 -0
  88. package/dist/components/LDFileUpload/LDImageUploadList.d.ts.map +1 -1
  89. package/dist/components/LDFileUpload/LDImageUploadList.js +1 -3
  90. package/dist/components/LDForm/LDFormErrorMessage.d.ts +3 -1
  91. package/dist/components/LDForm/LDFormErrorMessage.d.ts.map +1 -1
  92. package/dist/components/LDForm/LDFormErrorMessage.js +2 -2
  93. package/dist/components/LDInput/InputBase.d.ts +5 -3
  94. package/dist/components/LDInput/InputBase.d.ts.map +1 -1
  95. package/dist/components/LDInput/InputBase.js +4 -4
  96. package/dist/components/LDInput/LDFormInput.d.ts +1 -1
  97. package/dist/components/LDInput/LDFormInput.d.ts.map +1 -1
  98. package/dist/components/LDInput/LDFormInput.js +17 -14
  99. package/dist/components/LDInput/LDInput.d.ts +10 -3
  100. package/dist/components/LDInput/LDInput.d.ts.map +1 -1
  101. package/dist/components/LDInput/LDInput.js +114 -50
  102. package/dist/components/LDLNB/LDLNB.d.ts +42 -0
  103. package/dist/components/LDLNB/LDLNB.d.ts.map +1 -0
  104. package/dist/components/LDLNB/LDLNB.js +34 -0
  105. package/dist/components/LDLNB/LDLNBBase.d.ts +5 -13
  106. package/dist/components/LDLNB/LDLNBBase.d.ts.map +1 -1
  107. package/dist/components/LDLNB/LDLNBBase.js +52 -18
  108. package/dist/components/LDMenuBar/LDMenuBar.d.ts +33 -19
  109. package/dist/components/LDMenuBar/LDMenuBar.d.ts.map +1 -1
  110. package/dist/components/LDMenuBar/LDMenuBar.js +13 -27
  111. package/dist/components/LDMenuBar/MenuBarBase.d.ts +4 -5
  112. package/dist/components/LDMenuBar/MenuBarBase.d.ts.map +1 -1
  113. package/dist/components/LDMenuBar/MenuBarBase.js +12 -14
  114. package/dist/components/LDModal/LDModal.d.ts +20 -40
  115. package/dist/components/LDModal/LDModal.d.ts.map +1 -1
  116. package/dist/components/LDModal/LDModal.js +56 -70
  117. package/dist/components/LDModal/LDModalView.d.ts +59 -0
  118. package/dist/components/LDModal/LDModalView.d.ts.map +1 -0
  119. package/dist/components/LDModal/LDModalView.js +72 -0
  120. package/dist/components/LDNotification/LDNotification.d.ts +40 -0
  121. package/dist/components/LDNotification/LDNotification.d.ts.map +1 -0
  122. package/dist/components/LDNotification/LDNotification.js +76 -0
  123. package/dist/components/LDNotification/NotificationBase.d.ts +29 -0
  124. package/dist/components/LDNotification/NotificationBase.d.ts.map +1 -0
  125. package/dist/components/LDNotification/NotificationBase.js +27 -0
  126. package/dist/components/LDOTPInput/LDFormOTPInput.d.ts +15 -0
  127. package/dist/components/LDOTPInput/LDFormOTPInput.d.ts.map +1 -0
  128. package/dist/components/LDOTPInput/LDFormOTPInput.js +8 -0
  129. package/dist/components/LDOTPInput/LDOTPInput.d.ts +10 -22
  130. package/dist/components/LDOTPInput/LDOTPInput.d.ts.map +1 -1
  131. package/dist/components/LDOTPInput/LDOTPInput.js +44 -72
  132. package/dist/components/LDOTPInput/OTPInputBase.d.ts +46 -0
  133. package/dist/components/LDOTPInput/OTPInputBase.d.ts.map +1 -0
  134. package/dist/components/LDOTPInput/OTPInputBase.js +48 -0
  135. package/dist/components/LDPagination/LDPagination.d.ts +5 -1
  136. package/dist/components/LDPagination/LDPagination.d.ts.map +1 -1
  137. package/dist/components/LDPagination/LDPagination.js +3 -1
  138. package/dist/components/LDPagination/PaginationBase.d.ts +13 -4
  139. package/dist/components/LDPagination/PaginationBase.d.ts.map +1 -1
  140. package/dist/components/LDPagination/PaginationBase.js +8 -7
  141. package/dist/components/LDPopover/LDPopover.d.ts +1 -1
  142. package/dist/components/LDPopover/LDPopover.d.ts.map +1 -1
  143. package/dist/components/LDPopover/LDPopover.js +8 -7
  144. package/dist/components/LDProgressBar/LDProgressBar.d.ts +16 -0
  145. package/dist/components/LDProgressBar/LDProgressBar.d.ts.map +1 -0
  146. package/dist/components/LDProgressBar/LDProgressBar.js +9 -0
  147. package/dist/components/LDProgressBar/ProgressBarBase.d.ts +11 -0
  148. package/dist/components/LDProgressBar/ProgressBarBase.d.ts.map +1 -0
  149. package/dist/components/LDProgressBar/ProgressBarBase.js +10 -0
  150. package/dist/components/LDRadio/LDFormRadioGroup.d.ts +11 -0
  151. package/dist/components/LDRadio/LDFormRadioGroup.d.ts.map +1 -0
  152. package/dist/components/LDRadio/LDFormRadioGroup.js +8 -0
  153. package/dist/components/LDRadio/LDRadio.d.ts +2 -2
  154. package/dist/components/LDRadio/LDRadio.d.ts.map +1 -1
  155. package/dist/components/LDRadio/LDRadio.js +70 -15
  156. package/dist/components/LDRadio/LDRadioGroup.d.ts +5 -3
  157. package/dist/components/LDRadio/LDRadioGroup.d.ts.map +1 -1
  158. package/dist/components/LDRadio/LDRadioGroup.js +11 -2
  159. package/dist/components/LDRadio/RadioBase.d.ts +2 -3
  160. package/dist/components/LDRadio/RadioBase.d.ts.map +1 -1
  161. package/dist/components/LDRadio/RadioBase.js +7 -4
  162. package/dist/components/LDSectionNav/LDSectionNav.d.ts +11 -0
  163. package/dist/components/LDSectionNav/LDSectionNav.d.ts.map +1 -0
  164. package/dist/components/LDSectionNav/LDSectionNav.js +11 -0
  165. package/dist/components/LDSectionNav/SectionNavBase.d.ts +20 -0
  166. package/dist/components/LDSectionNav/SectionNavBase.d.ts.map +1 -0
  167. package/dist/components/LDSectionNav/SectionNavBase.js +53 -0
  168. package/dist/components/LDSelect/LDFormMultiSelect.d.ts +13 -0
  169. package/dist/components/LDSelect/LDFormMultiSelect.d.ts.map +1 -0
  170. package/dist/components/LDSelect/{FormMultiSelect.js → LDFormMultiSelect.js} +2 -2
  171. package/dist/components/LDSelect/LDFormSelect.d.ts +13 -0
  172. package/dist/components/LDSelect/LDFormSelect.d.ts.map +1 -0
  173. package/dist/components/LDSelect/LDFormSelect.js +10 -0
  174. package/dist/components/LDSelect/LDMultiSelect.d.ts +6 -3
  175. package/dist/components/LDSelect/LDMultiSelect.d.ts.map +1 -1
  176. package/dist/components/LDSelect/LDMultiSelect.js +35 -31
  177. package/dist/components/LDSelect/LDSelect.d.ts +6 -3
  178. package/dist/components/LDSelect/LDSelect.d.ts.map +1 -1
  179. package/dist/components/LDSelect/LDSelect.js +37 -30
  180. package/dist/components/LDSelect/SelectBase.d.ts.map +1 -1
  181. package/dist/components/LDSelect/SelectBase.js +21 -7
  182. package/dist/components/LDSpinner/LDSpinner.d.ts +1 -1
  183. package/dist/components/LDSpinner/LDSpinner.d.ts.map +1 -1
  184. package/dist/components/LDSpinner/LDSpinner.js +6 -6
  185. package/dist/components/LDTable/LDCollapsibleTanstackTable.d.ts.map +1 -1
  186. package/dist/components/LDTable/LDCollapsibleTanstackTable.js +12 -9
  187. package/dist/components/LDTable/LDTable.d.ts.map +1 -1
  188. package/dist/components/LDTable/LDTable.js +1 -1
  189. package/dist/components/LDTable/LDTanstackTable.d.ts.map +1 -1
  190. package/dist/components/LDTable/LDTanstackTable.js +6 -7
  191. package/dist/components/LDTable/TableField.d.ts +1 -1
  192. package/dist/components/LDTable/TableField.d.ts.map +1 -1
  193. package/dist/components/LDTextarea/LDFormTextarea.d.ts +14 -0
  194. package/dist/components/LDTextarea/LDFormTextarea.d.ts.map +1 -0
  195. package/dist/components/LDTextarea/{FormTextarea.js → LDFormTextarea.js} +2 -2
  196. package/dist/components/LDTextarea/LDTextarea.d.ts +1 -1
  197. package/dist/components/LDTextarea/LDTextarea.d.ts.map +1 -1
  198. package/dist/components/LDTextarea/LDTextarea.js +30 -30
  199. package/dist/components/LDTimePicker/LDFormTimePicker.d.ts +12 -0
  200. package/dist/components/LDTimePicker/LDFormTimePicker.d.ts.map +1 -0
  201. package/dist/components/LDTimePicker/{FormTimePicker.js → LDFormTimePicker.js} +3 -3
  202. package/dist/components/LDTimePicker/LDTimePicker.js +3 -3
  203. package/dist/components/LDToast/LDToast.js +1 -1
  204. package/dist/components/LDToast/LDToaster.d.ts +2 -1
  205. package/dist/components/LDToast/LDToaster.d.ts.map +1 -1
  206. package/dist/components/LDToast/LDToaster.js +2 -2
  207. package/dist/components/LDToggleButton/LDFormToggleButton.d.ts +10 -0
  208. package/dist/components/LDToggleButton/LDFormToggleButton.d.ts.map +1 -0
  209. package/dist/components/LDToggleButton/LDFormToggleButton.js +8 -0
  210. package/dist/components/LDTooltip/LDTooltip.js +1 -1
  211. package/dist/components/LDTooltip/TooltipBase.d.ts +6 -2
  212. package/dist/components/LDTooltip/TooltipBase.d.ts.map +1 -1
  213. package/dist/components/LDTooltip/TooltipBase.js +4 -4
  214. package/dist/index.css +913 -307
  215. package/dist/index.d.ts +28 -19
  216. package/dist/index.d.ts.map +1 -1
  217. package/dist/index.js +32 -20
  218. package/dist/utils/file.d.ts +2 -2
  219. package/dist/utils/file.d.ts.map +1 -1
  220. package/dist/utils/file.js +26 -23
  221. package/dist/utils/renderIcon.d.ts +1 -2
  222. package/dist/utils/renderIcon.d.ts.map +1 -1
  223. package/dist/utils/renderIcon.js +5 -4
  224. package/package.json +14 -2
  225. package/src/styles/carousel.css +15 -14
  226. package/src/styles/components/button.css +2 -2
  227. package/src/styles/components/editor.css +6 -0
  228. package/src/styles/components/index.css +1 -0
  229. package/src/styles/components/input.css +16 -2
  230. package/src/styles/components/select.css +61 -0
  231. package/src/styles/components/shared.css +6 -6
  232. package/src/styles/motion.css +115 -0
  233. package/src/theme.css +3 -0
  234. package/dist/components/Icon/LucideIcon.d.ts +0 -12
  235. package/dist/components/Icon/LucideIcon.d.ts.map +0 -1
  236. package/dist/components/Icon/LucideIcon.js +0 -49
  237. package/dist/components/LDCheckbox/FormCheckbox.d.ts +0 -14
  238. package/dist/components/LDCheckbox/FormCheckbox.d.ts.map +0 -1
  239. package/dist/components/LDCheckbox/FormCheckbox.js +0 -9
  240. package/dist/components/LDCheckbox/FormCheckboxGroup.d.ts +0 -13
  241. package/dist/components/LDCheckbox/FormCheckboxGroup.d.ts.map +0 -1
  242. package/dist/components/LDCheckbox/FormCheckboxGroup.js +0 -9
  243. package/dist/components/LDDatePicker/FormDatePicker.d.ts +0 -12
  244. package/dist/components/LDDatePicker/FormDatePicker.d.ts.map +0 -1
  245. package/dist/components/LDDatePicker/FormDatePicker.js +0 -12
  246. package/dist/components/LDDateRangePicker/FormDateRangePicker.d.ts +0 -12
  247. package/dist/components/LDDateRangePicker/FormDateRangePicker.d.ts.map +0 -1
  248. package/dist/components/LDDateRangePicker/FormDateRangePicker.js +0 -10
  249. package/dist/components/LDModal/openModal.d.ts +0 -24
  250. package/dist/components/LDModal/openModal.d.ts.map +0 -1
  251. package/dist/components/LDModal/openModal.js +0 -52
  252. package/dist/components/LDRadio/FormRadioGroup.d.ts +0 -13
  253. package/dist/components/LDRadio/FormRadioGroup.d.ts.map +0 -1
  254. package/dist/components/LDRadio/FormRadioGroup.js +0 -9
  255. package/dist/components/LDSelect/FormMultiSelect.d.ts +0 -13
  256. package/dist/components/LDSelect/FormMultiSelect.d.ts.map +0 -1
  257. package/dist/components/LDSelect/FormSelect.d.ts +0 -13
  258. package/dist/components/LDSelect/FormSelect.d.ts.map +0 -1
  259. package/dist/components/LDSelect/FormSelect.js +0 -10
  260. package/dist/components/LDTextarea/FormTextarea.d.ts +0 -14
  261. package/dist/components/LDTextarea/FormTextarea.d.ts.map +0 -1
  262. package/dist/components/LDTimePicker/FormTimePicker.d.ts +0 -12
  263. package/dist/components/LDTimePicker/FormTimePicker.d.ts.map +0 -1
  264. package/dist/components/LDToggleButton/FormToggleButton.d.ts +0 -12
  265. package/dist/components/LDToggleButton/FormToggleButton.d.ts.map +0 -1
  266. package/dist/components/LDToggleButton/FormToggleButton.js +0 -9
@@ -1,24 +1,27 @@
1
1
  'use client';
2
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
- import LDInput, { iconSizes } from './LDInput.js';
4
- import LucideIcon from '../Icon/LucideIcon.js';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useRef } from 'react';
4
+ import LDInput, { iconSizes, inputPaddingXVars, } from './LDInput.js';
5
5
  import LDFormField from '../LDForm/LDFormField.js';
6
6
  import LDFormErrorMessage from '../LDForm/LDFormErrorMessage.js';
7
7
  import cn from '../../utils/cn.js';
8
- const LDFormInput = ({ name, options, variant = 'filled', color = 'neutral', size = 'small', block = false, disabled = false, ref, customErrorMessage = '', isHiddenErrorMessage = false, errorClassName, showEditIcon = false, rightAddon, ...props }) => {
9
- const iconSize = iconSizes[size ?? 'sm'];
8
+ import { Pencil, X } from 'lucide-react';
9
+ import { renderIcon } from '../../utils/renderIcon.js';
10
+ import { iconSizeClasses } from '../../components/LDButton/LDButton.js';
11
+ const LDFormInput = ({ name, options, variant = 'filled', size = 'small', block = false, disabled = false, ref, customErrorMessage = '', isHiddenErrorMessage = false, errorClassName, showEditIcon = false, rightAddon, ...props }) => {
12
+ const iconSize = iconSizes[size ?? 'medium'];
13
+ const addonRef = useRef(null);
10
14
  return (_jsx(LDFormField, { name: name, options: options, customErrorMessage: customErrorMessage, disabled: disabled, ref: ref, children: ({ field, fieldState, resetField }) => {
11
- const editIconAddon = showEditIcon && !disabled ? (_jsxs(_Fragment, { children: [_jsx("span", { className: "group-focus-within:hidden", children: _jsx(LucideIcon, { name: "pencil", size: iconSize }) }), _jsx("button", { type: "button", "aria-label": "\uC785\uB825 \uB0B4\uC6A9 \uCD08\uAE30\uD654", onMouseDown: (e) => {
15
+ const editIconAddon = showEditIcon && !disabled ? (_jsxs("div", { className: "relative", style: { width: iconSize, height: iconSize }, children: [_jsx("span", { className: "absolute top-1/2 left-1/2 -translate-1/2 opacity-100 group-focus-within:opacity-0", children: _jsx(Pencil, { size: iconSize }) }), _jsx("button", { type: "button", "aria-label": "\uC785\uB825 \uB0B4\uC6A9 \uCD08\uAE30\uD654", onMouseDown: (e) => {
12
16
  e.preventDefault();
13
17
  resetField({ defaultValue: '' });
14
- }, className: cn('hidden group-focus-within:block text-neutral500 cursor-pointer ld-transition', {
15
- ['hover:text-neutral600']: color === 'neutral',
16
- ['hover:text-lb500']: color === 'point',
17
- ['hover:text-danger600']: color === 'danger',
18
- }), children: _jsx(LucideIcon, { name: "x", size: iconSize }) })] })) : null;
19
- const combinedAddon = editIconAddon || rightAddon ? (_jsxs(_Fragment, { children: [editIconAddon, rightAddon] })) : undefined;
20
- return (_jsxs("div", { className: cn('relative border-2 border-transparent', block ? 'w-full' : 'w-auto'), children: [_jsx(LDInput, { ...props, ...field, value: field.value ?? '', variant: variant, color: fieldState.hasError ? 'danger' : 'neutral', size: size, block: block, rightAddon: combinedAddon, "aria-invalid": fieldState.hasError, "aria-describedby": fieldState.hasError ? fieldState.errorId : undefined }), !isHiddenErrorMessage && (_jsx(LDFormErrorMessage, { id: fieldState.errorId, error: fieldState.error, disabled: disabled, className: cn((showEditIcon || rightAddon || props.showPasswordToggle) &&
21
- 'right-8', errorClassName) }))] }));
18
+ }, className: "absolute top-1/2 left-1/2 -translate-1/2 opacity-0 group-focus-within:opacity-100 text-neutral500 cursor-pointer ld-transition", children: _jsx(X, { size: iconSize }) })] })) : null;
19
+ const combinedAddon = editIconAddon || rightAddon ? (_jsxs(_Fragment, { children: [editIconAddon, renderIcon(rightAddon, iconSizeClasses[size])] })) : undefined;
20
+ return (_jsxs("div", { className: cn('relative', block ? 'w-full' : 'w-auto'), children: [_jsx(LDInput, { ...props, ...field, value: field.value ?? '', variant: variant, color: fieldState.hasError ? 'danger' : 'neutral', size: size, block: block, rightAddon: combinedAddon, addonRef: addonRef, "aria-invalid": fieldState.hasError, "aria-describedby": fieldState.hasError ? fieldState.errorId : undefined }), !isHiddenErrorMessage && (_jsx(LDFormErrorMessage, { id: fieldState.errorId, error: fieldState.error, disabled: disabled, className: errorClassName,
21
+ // base 우측 = size 패딩에 정렬, addon 있으면 그 폭만큼 더 왼쪽으로.
22
+ style: {
23
+ right: inputPaddingXVars[size],
24
+ } }))] }));
22
25
  } }));
23
26
  };
24
27
  export default LDFormInput;
@@ -1,8 +1,9 @@
1
1
  import { type InputHTMLAttributes, type ReactNode, type Ref } from 'react';
2
2
  type InputVariant = 'filled' | 'outline' | 'ghost';
3
3
  type InputColor = 'neutral' | 'point' | 'danger';
4
- export type InputSize = 'xSmall' | 'small' | 'medium' | 'large' | 'big' | 'xLarge';
4
+ export type InputSize = '2xsmall' | 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge';
5
5
  export declare const inputSizeClasses: Record<InputSize, string>;
6
+ export declare const inputPaddingXVars: Record<InputSize, string>;
6
7
  export declare const iconSizes: Record<InputSize, number>;
7
8
  export interface LDInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'color' | 'size'> {
8
9
  /** 입력 필드 스타일 유형 */
@@ -12,14 +13,20 @@ export interface LDInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>
12
13
  /** 입력 필드 높이 및 폰트 크기 프리셋 */
13
14
  size?: InputSize;
14
15
  /** 비밀번호 표시/숨김 토글 버튼 */
15
- showPasswordToggle?: boolean;
16
+ hiddenPasswordToggle?: boolean;
16
17
  /** true 시 너비 100% */
17
18
  block?: boolean;
19
+ /** 래퍼(Root div)에 적용할 className */
20
+ rootClassName?: string;
18
21
  /** 우측 부가 요소 (아이콘 등) */
19
22
  rightAddon?: ReactNode;
23
+ /** 우측 addon 컨테이너 ref (addon 폭·위치 측정용) */
24
+ addonRef?: Ref<HTMLSpanElement>;
25
+ /** 입력값 바로 뒤에 표시할 텍스트 */
26
+ suffix?: string;
20
27
  /** input 요소 ref */
21
28
  ref?: Ref<HTMLInputElement>;
22
29
  }
23
- declare const LDInput: ({ variant, color, size, showPasswordToggle, block, type, disabled, className, style, rightAddon, ref, ...props }: LDInputProps) => import("react/jsx-runtime").JSX.Element;
30
+ declare const LDInput: ({ variant, color, size, block, type, disabled, className, rootClassName, style, rightAddon, addonRef, suffix, hiddenPasswordToggle, ref, value, defaultValue, onChange, ...props }: LDInputProps) => import("react/jsx-runtime").JSX.Element;
24
31
  export default LDInput;
25
32
  //# sourceMappingURL=LDInput.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"LDInput.d.ts","sourceRoot":"","sources":["../../../src/components/LDInput/LDInput.tsx"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,SAAS,EACd,KAAK,GAAG,EACT,MAAM,OAAO,CAAC;AAMf,KAAK,YAAY,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;AACnD,KAAK,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;AACjD,MAAM,MAAM,SAAS,GACjB,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,OAAO,GACP,KAAK,GACL,QAAQ,CAAC;AA0Cb,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAOtD,CAAC;AAWF,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAO/C,CAAC;AAGF,MAAM,WAAW,YAAa,SAAQ,IAAI,CACxC,mBAAmB,CAAC,gBAAgB,CAAC,EACrC,OAAO,GAAG,MAAM,CACjB;IACC,mBAAmB;IACnB,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,YAAY;IACZ,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,2BAA2B;IAC3B,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,uBAAuB;IACvB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,qBAAqB;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,uBAAuB;IACvB,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,mBAAmB;IACnB,GAAG,CAAC,EAAE,GAAG,CAAC,gBAAgB,CAAC,CAAC;CAC7B;AAED,QAAA,MAAM,OAAO,GAAI,kHAad,YAAY,4CA0Ed,CAAC;AAEF,eAAe,OAAO,CAAC"}
1
+ {"version":3,"file":"LDInput.d.ts","sourceRoot":"","sources":["../../../src/components/LDInput/LDInput.tsx"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,mBAAmB,EACxB,KAAK,SAAS,EACd,KAAK,GAAG,EACT,MAAM,OAAO,CAAC;AAMf,KAAK,YAAY,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;AACnD,KAAK,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAC;AACjD,MAAM,MAAM,SAAS,GACjB,SAAS,GACT,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,OAAO,GACP,QAAQ,CAAC;AAqCb,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAOtD,CAAC;AAKF,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAOvD,CAAC;AAqBF,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAO/C,CAAC;AAcF,MAAM,WAAW,YAAa,SAAQ,IAAI,CACxC,mBAAmB,CAAC,gBAAgB,CAAC,EACrC,OAAO,GAAG,MAAM,CACjB;IACC,mBAAmB;IACnB,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,YAAY;IACZ,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,2BAA2B;IAC3B,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,uBAAuB;IACvB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,qBAAqB;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,kCAAkC;IAClC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uBAAuB;IACvB,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,GAAG,CAAC,eAAe,CAAC,CAAC;IAChC,wBAAwB;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,mBAAmB;IACnB,GAAG,CAAC,EAAE,GAAG,CAAC,gBAAgB,CAAC,CAAC;CAC7B;AAED,QAAA,MAAM,OAAO,GAAI,oLAmBd,YAAY,4CAoLd,CAAC;AAEF,eAAe,OAAO,CAAC"}
@@ -1,79 +1,143 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useState, } from 'react';
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useLayoutEffect, useRef, useState, } from 'react';
3
3
  import InputBase from './InputBase.js';
4
- import LucideIcon from '../Icon/LucideIcon.js';
5
4
  import cn from '../../utils/cn.js';
5
+ import { Eye, EyeOff } from 'lucide-react';
6
6
  // ── 스타일 매핑 ──
7
+ // 스타일 박스가 Root(wrapper)로 올라가고 focus는 내부 input에 가므로 focus → focus-within 사용.
7
8
  const variantColorClasses = {
8
9
  filled: {
9
- neutral: 'bg-neutral50 text-neutral900 border-none outline-2 outline-transparent [outline-style:solid] focus:bg-tintBlue focus:outline-lb500',
10
- point: 'bg-tintBlue text-neutral900 border-none outline-2 outline-transparent [outline-style:solid] focus:outline-lb500',
11
- danger: 'bg-tintRed text-neutral900 border-none outline-2 outline-danger600 [outline-style:solid] focus:outline-danger600',
10
+ neutral: 'bg-neutral50 text-neutral900 border-none outline-2 outline-transparent [outline-style:solid] [outline-offset:-2px] focus-within:bg-tintBlue focus-within:outline-lb500',
11
+ point: 'bg-tintBlue text-neutral900 border-none outline-2 outline-transparent [outline-style:solid] [outline-offset:-2px] focus-within:outline-lb500',
12
+ danger: 'bg-tintRed text-neutral900 border-none outline-2 outline-transparent [outline-style:solid] [outline-offset:-2px] outline-danger600',
12
13
  },
13
14
  outline: {
14
- neutral: 'bg-transparent text-neutral900 border-2 border-neutral100 outline-none',
15
- point: 'bg-transparent text-neutral900 border-2 border-lb500 outline-none',
16
- danger: 'bg-transparent text-neutral900 border-2 border-danger600 outline-none',
15
+ neutral: 'bg-transparent text-neutral900 border-none outline-2 outline-neutral100 [outline-style:solid] [outline-offset:-2px] focus-within:outline-lb500',
16
+ point: 'bg-transparent text-neutral900 border-none outline-2 outline-lb500 [outline-style:solid] [outline-offset:-2px]',
17
+ danger: 'bg-transparent text-neutral900 border-none outline-2 outline-danger600 [outline-style:solid] [outline-offset:-2px]',
17
18
  },
18
19
  ghost: {
19
- neutral: 'bg-transparent text-neutral900 border-none outline-2 outline-transparent [outline-style:solid] focus:bg-neutral50 focus:outline-lb500',
20
- point: 'bg-transparent text-neutral900 border-none outline-2 outline-transparent [outline-style:solid] focus:bg-tintBlue focus:outline-lb500',
21
- danger: 'bg-transparent text-danger600 border-none outline-2 outline-transparent [outline-style:solid] focus:bg-tintRed focus:outline-danger600',
20
+ neutral: 'bg-transparent border-none outline-2 outline-transparent [outline-style:solid] [outline-offset:-2px] focus-within:bg-neutral50',
21
+ point: 'bg-transparent border-none outline-2 outline-transparent [outline-style:solid] [outline-offset:-2px] focus-within:bg-tintBlue',
22
+ danger: 'bg-transparent border-none outline-2 outline-transparent [outline-style:solid] [outline-offset:-2px] outline-danger600 focus-within:bg-tintRed',
22
23
  },
23
24
  };
24
25
  const disabledVariantClasses = {
25
- filled: 'bg-mono100 text-mono400',
26
- outline: 'bg-transparent text-mono400 border-2 border-mono200',
27
- ghost: 'bg-transparent text-mono400',
28
- };
29
- // addon 아이콘 버튼 hover 색 — color 프리셋에 맞춰 강조(LDFormInput reset 아이콘과 동일 컨셉)
30
- const addonHoverColorClasses = {
31
- neutral: 'hover:text-neutral600',
32
- point: 'hover:text-lb500',
33
- danger: 'hover:text-danger600',
26
+ filled: 'bg-mono100 text-neutral300 border-none',
27
+ outline: 'bg-mono100 text-neutral300 border-none',
28
+ ghost: 'bg-mono100 text-neutral300 border-none',
34
29
  };
35
30
  export const inputSizeClasses = {
36
- xSmall: 'input-2xs',
37
- small: 'input-xs',
38
- medium: 'input-sm',
39
- large: 'input-md',
40
- big: 'input-lg',
41
- xLarge: 'input-xl',
31
+ '2xsmall': 'input-2xs',
32
+ xsmall: 'input-xs',
33
+ small: 'input-sm',
34
+ medium: 'input-md',
35
+ large: 'input-lg',
36
+ xlarge: 'input-xl',
37
+ };
38
+ // input size별 좌우 패딩 CSS 변수. 인라인 style에서 씀:
39
+ // - LDInput: addon gap = calc(이 값 / 2) (텍스트↔addon, 아이콘↔아이콘)
40
+ // - LDFormInput: 에러 메시지 base 우측 오프셋
41
+ export const inputPaddingXVars = {
42
+ '2xsmall': 'var(--control-padding-x-input-2xs)',
43
+ xsmall: 'var(--control-padding-x-input-xs)',
44
+ small: 'var(--control-padding-x-input-sm)',
45
+ medium: 'var(--control-padding-x-input-md)',
46
+ large: 'var(--control-padding-x-input-lg)',
47
+ xlarge: 'var(--control-padding-x-input-xl)',
42
48
  };
43
- const addonRightPaddingClasses = {
44
- xSmall: 'pr-8',
45
- small: 'pr-8',
46
- medium: 'pr-8',
47
- large: 'pr-10',
48
- big: 'pr-11',
49
- xLarge: 'pr-12',
49
+ // addon 안의 아이콘(svg)을 input size 토큰(--control-icon-*)에 맞춰 자동 사이징.
50
+ // 호출부가 lucide size를 안 줘도 input size만 맞으면 아이콘 크기가 일관됨.
51
+ const addonIconSizeClasses = {
52
+ '2xsmall': '[&_svg]:w-[var(--control-icon-2xs)] [&_svg]:h-[var(--control-icon-2xs)]',
53
+ xsmall: '[&_svg]:w-[var(--control-icon-xs)] [&_svg]:h-[var(--control-icon-xs)]',
54
+ small: '[&_svg]:w-[var(--control-icon-sm)] [&_svg]:h-[var(--control-icon-sm)]',
55
+ medium: '[&_svg]:w-[var(--control-icon-md)] [&_svg]:h-[var(--control-icon-md)]',
56
+ large: '[&_svg]:w-[var(--control-icon-lg)] [&_svg]:h-[var(--control-icon-lg)]',
57
+ xlarge: '[&_svg]:w-[var(--control-icon-xl)] [&_svg]:h-[var(--control-icon-xl)]',
50
58
  };
59
+ // --control-icon-* 토큰(shared.css)과 값을 일치시킨다. addon 아이콘은 CSS 토큰으로,
60
+ // password/edit 토글 박스는 이 JS 맵으로 사이징되므로 둘이 같아야 어긋나지 않음.
51
61
  export const iconSizes = {
52
- xSmall: 10,
53
- small: 12,
54
- medium: 14,
55
- large: 16,
56
- big: 18,
57
- xLarge: 20,
62
+ '2xsmall': 8,
63
+ xsmall: 12,
64
+ small: 16,
65
+ medium: 20,
66
+ large: 24,
67
+ xlarge: 28,
68
+ };
69
+ const SUFFIX_GAP = 4; // 값과 suffix 사이 간격(px)
70
+ const suffixTextClasses = {
71
+ '2xsmall': 'display10',
72
+ xsmall: 'display12',
73
+ small: 'display14',
74
+ medium: 'display16',
75
+ large: 'display18',
76
+ xlarge: 'display20',
58
77
  };
59
- const LDInput = ({ variant, color = 'neutral', size, showPasswordToggle = false, block = false, type = 'text', disabled = false, className, style, rightAddon, ref, ...props }) => {
78
+ const LDInput = ({ variant, color = 'neutral', size, block = false, type = 'text', disabled = false, className, rootClassName, style, rightAddon, addonRef, suffix, hiddenPasswordToggle = false, ref, value, defaultValue, onChange, ...props }) => {
60
79
  const [passwordVisible, setPasswordVisible] = useState(false);
61
- const resolvedType = showPasswordToggle
80
+ const [inputValue, setInputValue] = useState(() => String(value ?? defaultValue ?? ''));
81
+ const [suffixLeft, setSuffixLeft] = useState(0); // suffix의 최종 left 위치(px)
82
+ const valueRef = useRef(null); // 값 폭 측정용 숨은 span
83
+ const suffixRef = useRef(null); // suffix 자체 폭 측정용
84
+ const rootRef = useRef(null); // Root 래퍼(패딩·폭 측정용, suffix 위치 계산)
85
+ const isPasswordToggle = !hiddenPasswordToggle && type === 'password';
86
+ const resolvedType = isPasswordToggle
62
87
  ? passwordVisible
63
88
  ? 'text'
64
89
  : 'password'
65
90
  : type;
66
91
  const iconSize = iconSizes[size ?? 'medium'];
67
- const passwordToggleAddon = showPasswordToggle ? (_jsx("button", { type: "button", "aria-label": passwordVisible ? '비밀번호 숨기기' : '비밀번호 표시', "aria-pressed": passwordVisible, onClick: () => setPasswordVisible(!passwordVisible), disabled: disabled, className: cn('text-neutral500 ld-transition', disabled
68
- ? 'cursor-not-allowed'
69
- : cn('cursor-pointer', addonHoverColorClasses[color])), children: _jsx(LucideIcon, { name: passwordVisible ? 'eye' : 'eyeOff', size: iconSize }) })) : null;
70
- const resolvedRightAddon = rightAddon ?? passwordToggleAddon;
92
+ const displayedValue = String(value ?? inputValue);
93
+ const resolvedSize = size ?? 'small';
94
+ // 텍스트↔addon, 아이콘↔아이콘 간격 = 좌우 패딩의 절반. inline gap으로 적용.
95
+ const addonGap = `calc(${inputPaddingXVars[resolvedSize]} / 2)`;
96
+ useLayoutEffect(() => {
97
+ // 패딩이 이제 Root(wrapper)에 있으므로 suffix 기준 패딩도 Root에서 읽는다.
98
+ const root = rootRef.current;
99
+ // offsetWidth = 화면에서 실제로 차지하는 가로 px (content+padding+border)
100
+ const valueWidth = valueRef.current?.offsetWidth ?? 0;
101
+ const suffixWidth = suffixRef.current?.offsetWidth ?? 0;
102
+ if (!root) {
103
+ // suffix가 렌더 안 됐거나 미준비 시 fallback
104
+ setSuffixLeft(valueWidth);
105
+ return;
106
+ }
107
+ // getComputedStyle = 클래스·CSS변수까지 다 반영한 실제 적용 스타일(읽기 전용).
108
+ // 패딩이 Tailwind 클래스로 들어가서 root.style로는 못 읽음.
109
+ const cs = getComputedStyle(root);
110
+ const padLeft = parseFloat(cs.paddingLeft) || 0; // "12px" → 12
111
+ const padRight = parseFloat(cs.paddingRight) || 0;
112
+ // 값 뒤에 붙이되, suffix 오른끝이 Root 안쪽 오른 경계를 넘지 않게 clamp.
113
+ // clientWidth = content+padding (border 제외) → 안쪽 폭
114
+ const maxLeft = root.clientWidth - padRight - suffixWidth;
115
+ setSuffixLeft(Math.min(padLeft + valueWidth + SUFFIX_GAP, maxLeft));
116
+ }, [displayedValue, resolvedSize, suffix]);
117
+ const passwordToggleAddon = isPasswordToggle ? (_jsxs("button", { type: "button", "aria-label": passwordVisible ? '비밀번호 숨기기' : '비밀번호 표시', "aria-pressed": passwordVisible, onClick: () => setPasswordVisible(!passwordVisible), disabled: disabled, style: { width: iconSize, height: iconSize }, className: cn('relative text-neutral500 ld-transition flex items-center', disabled ? 'cursor-not-allowed' : 'cursor-pointer'), children: [_jsx(Eye, { size: iconSize, className: cn('ld-transition absolute top-1/2 left-1/2 -translate-1/2', passwordVisible ? 'opacity-100' : 'opacity-0') }), _jsx(EyeOff, { size: iconSize, className: cn('ld-transition absolute top-1/2 left-1/2 -translate-1/2', passwordVisible ? 'opacity-0' : 'opacity-100') })] })) : null;
71
118
  const { width, height, minWidth, maxWidth, minHeight, maxHeight, ...fieldStyle } = style ?? {};
72
- const rootStyle = { width, height, minWidth, maxWidth, minHeight, maxHeight };
73
- const fieldClassName = cn('w-full bold placeholder-mono400 ld-transition', variant &&
119
+ // 텍스트 - addon 간격(gap)은 inline으로 부여(패딩의 절반).
120
+ const rootStyle = {
121
+ width,
122
+ height,
123
+ minWidth,
124
+ maxWidth,
125
+ minHeight,
126
+ maxHeight,
127
+ gap: addonGap,
128
+ };
129
+ // 스타일 박스(배경·outline·높이·좌우 패딩·폰트)는 Root로. focus는 내부 input → Root가 focus-within으로 반응.
130
+ const rootClass = cn('ld-transition', variant &&
74
131
  (disabled
75
132
  ? disabledVariantClasses[variant]
76
- : variantColorClasses[variant][color]), size && !height && inputSizeClasses[size], (size === 'xSmall' || size === 'small') && 'rounded-[6px]', height && 'h-full', disabled && 'cursor-not-allowed', 'read-only:cursor-not-allowed', resolvedRightAddon && size && addonRightPaddingClasses[size], className);
77
- return (_jsxs(InputBase.Root, { block: block, style: rootStyle, children: [_jsx(InputBase.Field, { ref: ref, type: resolvedType, disabled: disabled, className: fieldClassName, style: fieldStyle, ...props }), resolvedRightAddon && (_jsx(InputBase.Addon, { position: "right", className: "right-2.5 text-neutral500", children: resolvedRightAddon }))] }));
133
+ : variantColorClasses[variant][color]), size && !height && inputSizeClasses[size], disabled && 'cursor-not-allowed');
134
+ // input은 알맹이만: w-full로 폭을 채우되 min-w-0으로 addon 자리만큼 줄어들게, 시각 스타일은 전부 투명 처리.
135
+ // (flex-1은 basis:0이라 input 고유 폭이 사라져 non-block에서 좁아짐 → w-full 사용)
136
+ const fieldClassName = cn('ld-input-field min-w-0 w-full h-full bg-transparent border-0 p-0 outline-none bold placeholder-neutral300', disabled && 'cursor-not-allowed', 'read-only:cursor-not-allowed', className);
137
+ const hasAddon = Boolean(rightAddon) || Boolean(passwordToggleAddon);
138
+ return (_jsxs(InputBase.Root, { ref: rootRef, block: block, style: rootStyle, className: cn(rootClass, rootClassName), children: [_jsx(InputBase.Field, { ref: ref, type: resolvedType, disabled: disabled, className: fieldClassName, style: fieldStyle, value: value, defaultValue: defaultValue, onChange: (event) => {
139
+ setInputValue(event.target.value);
140
+ onChange?.(event);
141
+ }, ...props }), suffix && displayedValue && (_jsxs(_Fragment, { children: [_jsx("span", { ref: valueRef, "aria-hidden": "true", className: cn('absolute invisible pointer-events-none whitespace-pre bold', suffixTextClasses[resolvedSize]), children: displayedValue }), _jsx("span", { ref: suffixRef, "aria-hidden": "true", className: cn('absolute inset-y-0 flex items-center pointer-events-none text-neutral900 bold translate-y-px', suffixTextClasses[resolvedSize]), style: { left: `${suffixLeft}px` }, children: suffix })] })), hasAddon && (_jsxs(InputBase.Addon, { ref: addonRef, style: { gap: addonGap }, className: cn('text-neutral500 flex items-center shrink-0', addonIconSizeClasses[resolvedSize]), children: [rightAddon, passwordToggleAddon] }))] }));
78
142
  };
79
143
  export default LDInput;
@@ -0,0 +1,42 @@
1
+ import type { ElementType, ReactNode } from 'react';
2
+ import { type INavItem } from './LDLNBBase.js';
3
+ export interface LDLNBProps {
4
+ /** 네비게이션 항목 목록 */
5
+ items: INavItem[];
6
+ /** 현재 경로 (active 판별용) */
7
+ pathname: string;
8
+ /** MenuItem 렌더 엘리먼트 (라우터 Link 주입용, 기본 'a') */
9
+ as?: ElementType;
10
+ /** 항목 이동 시 콜백 (라우터 push 등). 모바일에서는 이후 Drawer가 자동으로 닫힘 */
11
+ onNavigate?: (path: string) => void;
12
+ /** 헤더에 표시할 사용자 이름 */
13
+ name?: string;
14
+ /** 헤더에 표시할 이메일 */
15
+ email?: string;
16
+ /** 헤더 프로필 이미지 URL */
17
+ profileImage?: string | null;
18
+ /** 로그아웃 핸들러 (없으면 로그아웃 버튼 미표시) */
19
+ handleLogout?: () => void;
20
+ /** 데스크탑 사이드바 초기 접힘 상태 */
21
+ defaultCollapsed?: boolean;
22
+ /** 데스크탑 사이드바 기본이자 최대(펼침) 너비(px). 기본 300 */
23
+ size?: number;
24
+ /** 드래그로 줄일 수 있는 최소 너비(px). 기본 240 */
25
+ minWidth?: number;
26
+ /** 모바일 Drawer가 열리는 방향 (기본 'left') */
27
+ drawerDirection?: 'left' | 'right';
28
+ /** 모바일 햄버거 버튼에 적용할 className (위치·정렬 조정용, 예: 'fixed top-4 right-4 z-40') */
29
+ triggerClassName?: string;
30
+ /** Root에 적용할 추가 className */
31
+ className?: string;
32
+ /** 모바일 Drawer 안, 헤더와 메뉴(Content) 사이에만 렌더되는 커스텀 콘텐츠 (검색창·CTA 등) */
33
+ children?: ReactNode;
34
+ }
35
+ /**
36
+ * 반응형 LNB. 데스크탑에서는 인라인 사이드바, 모바일(<768px)에서는 햄버거 버튼 +
37
+ * Drawer 오버레이(기본 왼쪽, `drawerDirection`으로 조정)로 자동 전환된다.
38
+ * 뷰포트 감지는 내부에서 처리한다.
39
+ */
40
+ declare const LDLNB: ({ items, pathname, as, onNavigate, name, email, profileImage, handleLogout, defaultCollapsed, size, minWidth, drawerDirection, triggerClassName, className, children, }: LDLNBProps) => import("react/jsx-runtime").JSX.Element;
41
+ export default LDLNB;
42
+ //# sourceMappingURL=LDLNB.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LDLNB.d.ts","sourceRoot":"","sources":["../../../src/components/LDLNB/LDLNB.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEpD,OAAkB,EAAE,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAKvD,MAAM,WAAW,UAAU;IACzB,kBAAkB;IAClB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,yBAAyB;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,8CAA8C;IAC9C,EAAE,CAAC,EAAE,WAAW,CAAC;IACjB,yDAAyD;IACzD,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,qBAAqB;IACrB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kBAAkB;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qBAAqB;IACrB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,iCAAiC;IACjC,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,yBAAyB;IACzB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,2CAA2C;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,qCAAqC;IACrC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qCAAqC;IACrC,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACnC,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kEAAkE;IAClE,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAKD;;;;GAIG;AACH,QAAA,MAAM,KAAK,GAAI,yKAgBZ,UAAU,4CA0FZ,CAAC;AAEF,eAAe,KAAK,CAAC"}
@@ -0,0 +1,34 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useEffect, useState } from 'react';
4
+ import { Menu as MenuIcon } from 'lucide-react';
5
+ import LDLNBBase from './LDLNBBase.js';
6
+ import LDDrawer from '../LDDrawer/LDDrawer.js';
7
+ import { isActivePath } from '../../utils/utils.js';
8
+ import cn from '../../utils/cn.js';
9
+ // mobile: variant(max-width: calc(--size_md - 1px) = 767px)와 동일 기준
10
+ const MOBILE_QUERY = '(max-width: 767px)';
11
+ /**
12
+ * 반응형 LNB. 데스크탑에서는 인라인 사이드바, 모바일(<768px)에서는 햄버거 버튼 +
13
+ * Drawer 오버레이(기본 왼쪽, `drawerDirection`으로 조정)로 자동 전환된다.
14
+ * 뷰포트 감지는 내부에서 처리한다.
15
+ */
16
+ const LDLNB = ({ items, pathname, as, onNavigate, name, email, profileImage, handleLogout, defaultCollapsed = false, size = 400, minWidth = 200, drawerDirection = 'left', triggerClassName, className, children, }) => {
17
+ const [isMobile, setIsMobile] = useState(false);
18
+ const [open, setOpen] = useState(false);
19
+ useEffect(() => {
20
+ const mql = window.matchMedia(MOBILE_QUERY);
21
+ const sync = () => setIsMobile(mql.matches);
22
+ sync();
23
+ mql.addEventListener('change', sync);
24
+ return () => mql.removeEventListener('change', sync);
25
+ }, []);
26
+ const nav = (isMobile) => (_jsx(LDLNBBase.Provider, { isMobile: isMobile, items: items, pathname: pathname, defaultCollapsed: isMobile ? false : defaultCollapsed, size: size, minWidth: minWidth, children: _jsxs(LDLNBBase.Root, { className: className, children: [_jsx(LDLNBBase.Header, { name: name, email: email, profileImage: profileImage, handleLogout: handleLogout }), isMobile && children, _jsx(LDLNBBase.Content, { children: items.map((group) => (_jsx(LDLNBBase.Group, { label: group.label, noSlider: group.noSlider, children: _jsx(LDLNBBase.Menu, { label: group.label, noSlider: group.noSlider, tabCount: group.tabs?.length ?? 0, children: group.tabs?.map((tab) => (_jsx(LDLNBBase.MenuItem, { as: as, href: tab.path, icon: tab.icon, isActive: isActivePath(pathname, tab.path), onClick: () => {
27
+ onNavigate?.(tab.path);
28
+ setOpen(false);
29
+ }, children: tab.label }, tab.path))) }) }, group.label))) }), _jsx(LDLNBBase.ResizeWidthBar, { className: "absolute top-0 bottom-0 right-0" })] }) }));
30
+ if (!isMobile)
31
+ return nav(false);
32
+ return (_jsx(LDDrawer, { direction: drawerDirection, open: open, onOpenChange: setOpen, className: "w-full max-w-none p-0", trigger: _jsx("button", { type: "button", "aria-label": "\uBA54\uB274 \uC5F4\uAE30", className: cn('flex items-center justify-center w-10 h-10 text-neutral500 hover:text-mono900 ld-transition cursor-pointer', triggerClassName), children: _jsx(MenuIcon, { size: 20 }) }), children: _jsx("div", { className: "pt-6", children: nav(true) }) }));
33
+ };
34
+ export default LDLNB;
@@ -16,6 +16,8 @@ interface ProviderProps {
16
16
  items?: INavItem[];
17
17
  pathname?: string;
18
18
  defaultCollapsed?: boolean;
19
+ size?: number;
20
+ minWidth?: number;
19
21
  }
20
22
  interface RootProps {
21
23
  children: ReactNode;
@@ -54,20 +56,11 @@ interface MenuItemProps {
54
56
  className?: string;
55
57
  [key: string]: unknown;
56
58
  }
57
- interface MenuSubProps {
58
- children: ReactNode;
59
- className?: string;
60
- }
61
- interface MenuSubItemProps {
62
- as?: ElementType;
63
- href: string;
64
- isActive?: boolean;
65
- children: ReactNode;
59
+ interface IResizeWidthBar {
66
60
  className?: string;
67
- [key: string]: unknown;
68
61
  }
69
62
  declare const LDLNBBase: {
70
- Provider: ({ children, isMobile, items, pathname, defaultCollapsed, }: ProviderProps) => import("react/jsx-runtime").JSX.Element;
63
+ Provider: ({ children, isMobile, items, pathname, size, defaultCollapsed, minWidth, }: ProviderProps) => import("react/jsx-runtime").JSX.Element;
71
64
  Root: ({ children, className }: RootProps) => import("react/jsx-runtime").JSX.Element;
72
65
  Trigger: ({ className }: TriggerProps) => import("react/jsx-runtime").JSX.Element | null;
73
66
  Header: ({ name, email, profileImage, handleLogout }: HeaderProps) => import("react/jsx-runtime").JSX.Element;
@@ -75,8 +68,7 @@ declare const LDLNBBase: {
75
68
  Group: ({ children, label, noSlider }: GroupProps) => import("react/jsx-runtime").JSX.Element;
76
69
  Menu: ({ children, label, noSlider, tabCount }: MenuProps) => import("react/jsx-runtime").JSX.Element;
77
70
  MenuItem: ({ as: Comp, href, isActive, children, icon, className, ...rest }: MenuItemProps) => import("react/jsx-runtime").JSX.Element;
78
- MenuSub: ({ children, className }: MenuSubProps) => import("react/jsx-runtime").JSX.Element | null;
79
- MenuSubItem: ({ as: Comp, href, isActive, children, className, ...rest }: MenuSubItemProps) => import("react/jsx-runtime").JSX.Element;
71
+ ResizeWidthBar: ({ className }: IResizeWidthBar) => import("react/jsx-runtime").JSX.Element | null;
80
72
  };
81
73
  export default LDLNBBase;
82
74
  //# sourceMappingURL=LDLNBBase.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"LDLNBBase.d.ts","sourceRoot":"","sources":["../../../src/components/LDLNB/LDLNBBase.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAapD,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AA0BD,UAAU,aAAa;IACrB,QAAQ,EAAE,SAAS,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAyDD,UAAU,SAAS;IACjB,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA2BD,UAAU,YAAY;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA0BD,UAAU,WAAW;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B;AAqCD,UAAU,YAAY;IACpB,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAkBD,UAAU,UAAU;IAClB,QAAQ,EAAE,SAAS,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAqCD,UAAU,SAAS;IACjB,QAAQ,EAAE,SAAS,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AA6BD,UAAU,aAAa;IACrB,EAAE,CAAC,EAAE,WAAW,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;IACpB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAiCD,UAAU,YAAY;IACpB,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAYD,UAAU,gBAAgB;IACxB,EAAE,CAAC,EAAE,WAAW,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AA2BD,QAAA,MAAM,SAAS;2EA/UZ,aAAa;oCAsDuB,SAAS;6BA6BhB,YAAY;0DA+BiB,WAAW;uCAwC9B,YAAY;2CAsBR,UAAU;oDA0CG,SAAS;iFA6CjE,aAAa;uCA4B0B,YAAY;8EA0BnD,gBAAgB;CA6BlB,CAAC;AAEF,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"LDLNBBase.d.ts","sourceRoot":"","sources":["../../../src/components/LDLNB/LDLNBBase.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAEV,WAAW,EAEX,SAAS,EAEV,MAAM,OAAO,CAAC;AAgBf,MAAM,WAAW,OAAO;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAiCD,UAAU,aAAa;IACrB,QAAQ,EAAE,SAAS,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,QAAQ,EAAE,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAuED,UAAU,SAAS;IACjB,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA8BD,UAAU,YAAY;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA0BD,UAAU,WAAW;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B;AAqCD,UAAU,YAAY;IACpB,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAkBD,UAAU,UAAU;IAClB,QAAQ,EAAE,SAAS,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAuCD,UAAU,SAAS;IACjB,QAAQ,EAAE,SAAS,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AA6BD,UAAU,aAAa;IACrB,EAAE,CAAC,EAAE,WAAW,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;IACpB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAgCD,UAAU,eAAe;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAuDD,QAAA,MAAM,SAAS;2FAvWZ,aAAa;oCAkEuB,SAAS;6BAgChB,YAAY;0DA+BiB,WAAW;uCAwC9B,YAAY;2CAsBR,UAAU;oDA4CG,SAAS;iFA6CjE,aAAa;oCA0BuB,eAAe;CA+DrD,CAAC;AAEF,eAAe,SAAS,CAAC"}
@@ -5,6 +5,8 @@ import { ChevronDown, PanelLeftClose, PanelLeftOpen, LogOut, } from 'lucide-reac
5
5
  import cn from '../../utils/cn.js';
6
6
  import { isActivePath } from '../../utils/utils.js';
7
7
  import LDAvatar from '../LDAvatar/LDAvatar.js';
8
+ const DEFAULT_MIN_WIDTH = 144;
9
+ const DEFAULT_SIZE = 300;
8
10
  const LNBContext = createContext(null);
9
11
  const useLNBContext = () => {
10
12
  const ctx = useContext(LNBContext);
@@ -12,10 +14,16 @@ const useLNBContext = () => {
12
14
  throw new Error('LDLNBBase 서브컴포넌트는 LDLNBBase.Provider 내부에서 사용해야 합니다.');
13
15
  return ctx;
14
16
  };
15
- const Provider = ({ children, isMobile, items = [], pathname = '', defaultCollapsed = false, }) => {
17
+ const Provider = ({ children, isMobile, items = [], pathname = '', size = DEFAULT_SIZE, defaultCollapsed = false, minWidth = DEFAULT_MIN_WIDTH, }) => {
16
18
  const [collapsed, setCollapsed] = useState(defaultCollapsed);
17
19
  const [openGroups, setOpenGroups] = useState([]);
18
- const toggleCollapsed = () => setCollapsed((prev) => !prev);
20
+ const [width, setWidth] = useState(size);
21
+ const [isResizing, setIsResizing] = useState(false);
22
+ const toggleCollapsed = () => {
23
+ if (collapsed)
24
+ setWidth(size);
25
+ setCollapsed((prev) => !prev);
26
+ };
19
27
  const toggleGroup = (label) => {
20
28
  setOpenGroups((prev) => prev.includes(label) ? prev.filter((g) => g !== label) : [...prev, label]);
21
29
  };
@@ -41,11 +49,18 @@ const Provider = ({ children, isMobile, items = [], pathname = '', defaultCollap
41
49
  openGroups,
42
50
  toggleGroup,
43
51
  isGroupOpen,
52
+ width,
53
+ setWidth,
54
+ isResizing,
55
+ setIsResizing,
56
+ setCollapsed,
57
+ minWidth,
58
+ size,
44
59
  }, children: children }));
45
60
  };
46
61
  const Root = ({ children, className }) => {
47
- const { collapsed } = useLNBContext();
48
- return (_jsx("div", { className: cn('relative mobile:w-full ld-transition', collapsed ? 'w-[60px]' : 'w-[300px]', className), children: _jsx("div", { className: cn('w-full h-full bg-mono50 mobile:bg-white', 'h-[calc(100vh-64px)] mobile:h-auto mobile:overflow-hidden', 'overflow-y-auto p-sm flex flex-col gap-md mobile:py-0 scrollbar-hide scrollbar-hover'), children: children }) }));
62
+ const { isMobile, collapsed, width, isResizing } = useLNBContext();
63
+ return (_jsx("div", { className: cn('relative mobile:w-full', !isResizing && 'ld-transition', collapsed ? 'w-[60px]' : `w-[${width}px]`, className), style: collapsed || isMobile ? undefined : { width }, children: _jsx("div", { className: cn('w-full h-full bg-mono50 mobile:bg-white', 'h-[calc(100vh-64px)] mobile:h-auto mobile:overflow-hidden', 'overflow-y-auto p-sm flex flex-col gap-md mobile:py-0 scrollbar-hide scrollbar-hover'), children: children }) }));
49
64
  };
50
65
  const Trigger = ({ className }) => {
51
66
  const { isMobile, collapsed, toggleCollapsed } = useLNBContext();
@@ -56,16 +71,16 @@ const Trigger = ({ className }) => {
56
71
  };
57
72
  const Header = ({ name, email, profileImage, handleLogout }) => {
58
73
  const { collapsed } = useLNBContext();
59
- return (_jsxs("div", { className: cn('w-full flex gap-sm items-center rounded-[10px] ld-transition overflow-hidden', collapsed
74
+ return (_jsxs("div", { className: cn('w-full flex gap-sm items-center rounded-[10px] ld-transition overflow-hidden shrink-0', collapsed
60
75
  ? 'p-xs justify-center border-transparent'
61
- : 'p-md mobile:p-sm border border-neutral100'), children: [_jsx(LDAvatar, { size: "md", src: profileImage }), !collapsed && (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex flex-col gap-xs flex-1 min-w-0", children: [_jsx("span", { className: "display16 bold truncate", children: name ?? '' }), _jsx("span", { className: "display14 text-neutral500 truncate", children: email ?? '' })] }), handleLogout && (_jsx(LogOut, { size: 12, className: "cursor-pointer flex-shrink-0", onClick: handleLogout }))] }))] }));
76
+ : 'p-md mobile:p-sm border border-neutral100'), children: [_jsx(LDAvatar, { size: "large", src: profileImage }), !collapsed && (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex flex-col gap-xs flex-1 min-w-0", children: [_jsx("span", { className: "display16 bold truncate", children: name ?? '' }), _jsx("span", { className: "display14 text-neutral500 truncate", children: email ?? '' })] }), handleLogout && (_jsx(LogOut, { size: 20, className: "cursor-pointer shrink-0 text-neutral700 hover:text-neutral900 ld-transition", onClick: handleLogout }))] }))] }));
62
77
  };
63
78
  const Content = ({ children, className }) => (_jsxs(_Fragment, { children: [_jsx("div", { className: "w-full border-b border-neutral100" }), _jsx("div", { className: cn('flex flex-col gap-md mobile:overflow-y-auto mobile:h-[calc(62dvh-111px)]', className), children: children })] }));
64
79
  const Group = ({ children, label, noSlider }) => {
65
80
  const { isMobile, collapsed, toggleGroup, isGroupOpen } = useLNBContext();
66
81
  const open = label ? isGroupOpen(label) : true;
67
- return (_jsxs("div", { className: "flex flex-col gap-sm w-full items-start", children: [label && !collapsed && (_jsxs("div", { className: cn('w-full flex', isMobile && 'cursor-pointer justify-between'), onClick: () => !noSlider && isMobile && toggleGroup(label), children: [_jsx("span", { className: "display14 text-neutral500", children: label }), _jsx("div", { className: cn(isMobile &&
68
- 'transition-transform duration-300 ease-out flex items-center justify-center w-5 h-5 flex-shrink-0', isMobile && open ? 'rotate-180' : 'rotate-0', !isMobile && 'hidden', noSlider && 'hidden'), children: _jsx(ChevronDown, { size: 14, className: "text-neutral500" }) })] })), children] }));
82
+ return (_jsxs("div", { className: "flex flex-col gap-sm w-full items-start", children: [label && !collapsed && (_jsxs("div", { className: cn('w-full flex', isMobile && 'cursor-pointer justify-between'), onClick: () => !noSlider && isMobile && toggleGroup(label), children: [_jsx("span", { className: "display14 text-neutral500 whitespace-nowrap", children: label }), _jsx("div", { className: cn(isMobile &&
83
+ 'transition-transform duration-300 ease-out flex items-center justify-center w-5 h-5 shrink-0', isMobile && open ? 'rotate-180' : 'rotate-0', !isMobile && 'hidden', noSlider && 'hidden'), children: _jsx(ChevronDown, { size: 14, className: "text-neutral500" }) })] })), children] }));
69
84
  };
70
85
  const Menu = ({ children, label, noSlider, tabCount = 0 }) => {
71
86
  const { isMobile, isGroupOpen } = useLNBContext();
@@ -81,17 +96,37 @@ const Menu = ({ children, label, noSlider, tabCount = 0 }) => {
81
96
  };
82
97
  const MenuItem = ({ as: Comp = 'a', href, isActive, children, icon, className, ...rest }) => {
83
98
  const { collapsed } = useLNBContext();
84
- return (_jsxs(Comp, { href: href, className: cn('flex gap-sm w-full items-center p-sm display16 mobile:display14 bold mobile:medium', 'text-neutral500 cursor-pointer hover:bg-mono300 rounded-[5px] hover:text-mono900 ld-transition', collapsed && 'justify-center', isActive &&
85
- 'bg-tintBlue text-blue400 hover:bg-tintBlue hover:text-blue400', className), ...rest, children: [icon && _jsx("span", { className: "flex-shrink-0", children: icon }), !collapsed && children] }));
99
+ return (_jsxs(Comp, { href: href, className: cn('flex gap-sm w-full items-center p-sm display16 mobile:display14 bold mobile:medium', 'text-neutral500 cursor-pointer hover:bg-mono300 rounded-[5px] hover:text-mono900 ld-transition', 'whitespace-nowrap overflow-hidden', collapsed && 'justify-center', isActive &&
100
+ 'bg-tintBlue text-blue400 hover:bg-tintBlue hover:text-blue400', className), ...rest, children: [icon && _jsx("span", { className: "shrink-0", children: icon }), !collapsed && children] }));
86
101
  };
87
- const MenuSub = ({ children, className }) => {
88
- const { collapsed } = useLNBContext();
89
- if (collapsed)
102
+ const ResizeWidthBar = ({ className }) => {
103
+ const { isMobile, width, setWidth, setIsResizing, setCollapsed, minWidth, size, } = useLNBContext();
104
+ // 모바일에선 전체 너비라 리사이즈 비활성
105
+ if (isMobile)
90
106
  return null;
91
- return (_jsx("div", { className: cn('flex flex-col w-full gap-sm pl-sm', className), children: children }));
107
+ const handleResizeWidth = (e) => {
108
+ const startWidth = width; // 드래그 시작 시점의 패널 너비(고정)
109
+ const startX = e.pageX; // 드래그 시작 시점의 커서 X(고정)
110
+ setIsResizing(true);
111
+ const onMouseMove = (e) => {
112
+ const next = startWidth - startX + e.pageX;
113
+ if (next < minWidth) {
114
+ setCollapsed(true);
115
+ return;
116
+ }
117
+ setCollapsed(false);
118
+ setWidth(Math.min(size, next));
119
+ };
120
+ const onMouseUp = () => {
121
+ setIsResizing(false);
122
+ document.body.removeEventListener('mousemove', onMouseMove);
123
+ document.body.removeEventListener('mouseup', onMouseUp);
124
+ };
125
+ document.body.addEventListener('mousemove', onMouseMove);
126
+ document.body.addEventListener('mouseup', onMouseUp, { once: true });
127
+ };
128
+ return (_jsx("div", { className: cn('w-1 flex justify-start group ld-transition translate-x-1', className), onMouseDown: handleResizeWidth, children: _jsx("div", { className: "w-px h-full group-hover:bg-lb500 group-hover:cursor-col-resize ld-transition -translate-x-px" }) }));
92
129
  };
93
- const MenuSubItem = ({ as: Comp = 'a', href, isActive, children, className, ...rest }) => (_jsx(Comp, { href: href, className: cn('flex gap-sm w-full items-center p-sm display14 medium', 'text-neutral500 cursor-pointer hover:bg-mono300 rounded-[5px] hover:text-mono900 ld-transition', isActive &&
94
- 'bg-tintBlue text-blue400 hover:bg-tintBlue hover:text-blue400', className), ...rest, children: children }));
95
130
  // ── Export ──
96
131
  const LDLNBBase = {
97
132
  Provider,
@@ -102,7 +137,6 @@ const LDLNBBase = {
102
137
  Group,
103
138
  Menu,
104
139
  MenuItem,
105
- MenuSub,
106
- MenuSubItem,
140
+ ResizeWidthBar,
107
141
  };
108
142
  export default LDLNBBase;