@loword/loword-design-system 0.0.11 → 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 (169) 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/LDAvatar/LDAvatar.d.ts +1 -1
  8. package/dist/components/LDAvatar/LDAvatar.d.ts.map +1 -1
  9. package/dist/components/LDAvatar/LDAvatar.js +19 -10
  10. package/dist/components/LDCalendar/CalendarBase.d.ts +17 -0
  11. package/dist/components/LDCalendar/CalendarBase.d.ts.map +1 -0
  12. package/dist/components/LDCalendar/CalendarBase.js +49 -0
  13. package/dist/components/LDCalendar/LDCalendar.d.ts +4 -11
  14. package/dist/components/LDCalendar/LDCalendar.d.ts.map +1 -1
  15. package/dist/components/LDCalendar/LDCalendar.js +9 -40
  16. package/dist/components/LDCarousel/CarouselBase.d.ts +3 -3
  17. package/dist/components/LDCarousel/CarouselBase.d.ts.map +1 -1
  18. package/dist/components/LDCarousel/CarouselBase.js +9 -7
  19. package/dist/components/LDCarousel/LDCarousel.d.ts +7 -8
  20. package/dist/components/LDCarousel/LDCarousel.d.ts.map +1 -1
  21. package/dist/components/LDCarousel/LDCarousel.js +2 -2
  22. package/dist/components/LDCheckbox/CheckboxBase.js +1 -1
  23. package/dist/components/LDCheckbox/LDCheckbox.d.ts +2 -5
  24. package/dist/components/LDCheckbox/LDCheckbox.d.ts.map +1 -1
  25. package/dist/components/LDCheckbox/LDCheckbox.js +65 -7
  26. package/dist/components/LDCheckbox/LDCheckboxGroup.d.ts +3 -3
  27. package/dist/components/LDCheckbox/LDCheckboxGroup.d.ts.map +1 -1
  28. package/dist/components/LDCheckbox/LDCheckboxGroup.js +11 -2
  29. package/dist/components/LDCheckbox/LDFormCheckbox.d.ts +1 -3
  30. package/dist/components/LDCheckbox/LDFormCheckbox.d.ts.map +1 -1
  31. package/dist/components/LDCheckbox/LDFormCheckbox.js +3 -4
  32. package/dist/components/LDCheckbox/LDFormCheckboxGroup.d.ts +1 -3
  33. package/dist/components/LDCheckbox/LDFormCheckboxGroup.d.ts.map +1 -1
  34. package/dist/components/LDCheckbox/LDFormCheckboxGroup.js +3 -4
  35. package/dist/components/LDDataCalendar/DataCalendarBase.d.ts +17 -1
  36. package/dist/components/LDDataCalendar/DataCalendarBase.d.ts.map +1 -1
  37. package/dist/components/LDDataCalendar/DataCalendarBase.js +34 -4
  38. package/dist/components/LDDataCalendar/LDDataCalendar.d.ts +27 -10
  39. package/dist/components/LDDataCalendar/LDDataCalendar.d.ts.map +1 -1
  40. package/dist/components/LDDataCalendar/LDDataCalendar.js +8 -8
  41. package/dist/components/LDDatePicker/LDDatePicker.d.ts.map +1 -1
  42. package/dist/components/LDDatePicker/LDDatePicker.js +1 -1
  43. package/dist/components/LDDateRangePicker/LDDateRangePicker.d.ts.map +1 -1
  44. package/dist/components/LDDateRangePicker/LDDateRangePicker.js +1 -1
  45. package/dist/components/LDDrawer/LDDrawer.d.ts +2 -0
  46. package/dist/components/LDDrawer/LDDrawer.d.ts.map +1 -1
  47. package/dist/components/LDDrawer/LDDrawer.js +1 -1
  48. package/dist/components/LDEditor/LDEditor.d.ts.map +1 -1
  49. package/dist/components/LDEditor/LDEditor.js +94 -54
  50. package/dist/components/LDEmpty/EmptyBase.d.ts +19 -0
  51. package/dist/components/LDEmpty/EmptyBase.d.ts.map +1 -0
  52. package/dist/components/LDEmpty/EmptyBase.js +18 -0
  53. package/dist/components/LDEmpty/LDEmpty.d.ts +35 -0
  54. package/dist/components/LDEmpty/LDEmpty.d.ts.map +1 -0
  55. package/dist/components/LDEmpty/LDEmpty.js +30 -0
  56. package/dist/components/LDFileUpload/FileUploadBase.d.ts.map +1 -1
  57. package/dist/components/LDFileUpload/FileUploadBase.js +6 -6
  58. package/dist/components/LDFileUpload/LDFileUpload.d.ts +3 -0
  59. package/dist/components/LDFileUpload/LDFileUpload.d.ts.map +1 -1
  60. package/dist/components/LDFileUpload/LDFileUpload.js +2 -4
  61. package/dist/components/LDFileUpload/LDFileUploadList.d.ts +3 -0
  62. package/dist/components/LDFileUpload/LDFileUploadList.d.ts.map +1 -1
  63. package/dist/components/LDFileUpload/LDFileUploadList.js +1 -3
  64. package/dist/components/LDFileUpload/LDImageUpload.d.ts +3 -0
  65. package/dist/components/LDFileUpload/LDImageUpload.d.ts.map +1 -1
  66. package/dist/components/LDFileUpload/LDImageUpload.js +2 -4
  67. package/dist/components/LDFileUpload/LDImageUploadList.d.ts +3 -0
  68. package/dist/components/LDFileUpload/LDImageUploadList.d.ts.map +1 -1
  69. package/dist/components/LDFileUpload/LDImageUploadList.js +1 -3
  70. package/dist/components/LDInput/InputBase.d.ts +5 -3
  71. package/dist/components/LDInput/InputBase.d.ts.map +1 -1
  72. package/dist/components/LDInput/InputBase.js +4 -4
  73. package/dist/components/LDInput/LDFormInput.d.ts.map +1 -1
  74. package/dist/components/LDInput/LDFormInput.js +7 -27
  75. package/dist/components/LDInput/LDInput.d.ts +8 -2
  76. package/dist/components/LDInput/LDInput.d.ts.map +1 -1
  77. package/dist/components/LDInput/LDInput.js +91 -28
  78. package/dist/components/LDLNB/LDLNB.d.ts +42 -0
  79. package/dist/components/LDLNB/LDLNB.d.ts.map +1 -0
  80. package/dist/components/LDLNB/LDLNB.js +34 -0
  81. package/dist/components/LDLNB/LDLNBBase.d.ts +5 -13
  82. package/dist/components/LDLNB/LDLNBBase.d.ts.map +1 -1
  83. package/dist/components/LDLNB/LDLNBBase.js +52 -18
  84. package/dist/components/LDMenuBar/LDMenuBar.d.ts +33 -19
  85. package/dist/components/LDMenuBar/LDMenuBar.d.ts.map +1 -1
  86. package/dist/components/LDMenuBar/LDMenuBar.js +13 -27
  87. package/dist/components/LDMenuBar/MenuBarBase.d.ts +4 -5
  88. package/dist/components/LDMenuBar/MenuBarBase.d.ts.map +1 -1
  89. package/dist/components/LDMenuBar/MenuBarBase.js +12 -14
  90. package/dist/components/LDModal/LDModal.d.ts +2 -1
  91. package/dist/components/LDModal/LDModal.d.ts.map +1 -1
  92. package/dist/components/LDModal/LDModal.js +1 -1
  93. package/dist/components/LDModal/LDModalView.d.ts +11 -3
  94. package/dist/components/LDModal/LDModalView.d.ts.map +1 -1
  95. package/dist/components/LDModal/LDModalView.js +4 -4
  96. package/dist/components/LDNotification/LDNotification.d.ts +40 -0
  97. package/dist/components/LDNotification/LDNotification.d.ts.map +1 -0
  98. package/dist/components/LDNotification/LDNotification.js +76 -0
  99. package/dist/components/LDNotification/NotificationBase.d.ts +29 -0
  100. package/dist/components/LDNotification/NotificationBase.d.ts.map +1 -0
  101. package/dist/components/LDNotification/NotificationBase.js +27 -0
  102. package/dist/components/LDOTPInput/LDFormOTPInput.d.ts +15 -0
  103. package/dist/components/LDOTPInput/LDFormOTPInput.d.ts.map +1 -0
  104. package/dist/components/LDOTPInput/LDFormOTPInput.js +8 -0
  105. package/dist/components/LDOTPInput/LDOTPInput.d.ts +10 -22
  106. package/dist/components/LDOTPInput/LDOTPInput.d.ts.map +1 -1
  107. package/dist/components/LDOTPInput/LDOTPInput.js +44 -73
  108. package/dist/components/LDOTPInput/OTPInputBase.d.ts +46 -0
  109. package/dist/components/LDOTPInput/OTPInputBase.d.ts.map +1 -0
  110. package/dist/components/LDOTPInput/OTPInputBase.js +48 -0
  111. package/dist/components/LDPagination/LDPagination.d.ts +1 -1
  112. package/dist/components/LDPagination/LDPagination.d.ts.map +1 -1
  113. package/dist/components/LDPagination/LDPagination.js +1 -8
  114. package/dist/components/LDPopover/LDPopover.d.ts +1 -1
  115. package/dist/components/LDPopover/LDPopover.d.ts.map +1 -1
  116. package/dist/components/LDPopover/LDPopover.js +5 -4
  117. package/dist/components/LDProgressBar/LDProgressBar.d.ts +16 -0
  118. package/dist/components/LDProgressBar/LDProgressBar.d.ts.map +1 -0
  119. package/dist/components/LDProgressBar/LDProgressBar.js +9 -0
  120. package/dist/components/LDProgressBar/ProgressBarBase.d.ts +11 -0
  121. package/dist/components/LDProgressBar/ProgressBarBase.d.ts.map +1 -0
  122. package/dist/components/LDProgressBar/ProgressBarBase.js +10 -0
  123. package/dist/components/LDRadio/LDFormRadioGroup.d.ts +1 -3
  124. package/dist/components/LDRadio/LDFormRadioGroup.d.ts.map +1 -1
  125. package/dist/components/LDRadio/LDFormRadioGroup.js +3 -4
  126. package/dist/components/LDRadio/LDRadio.d.ts +1 -1
  127. package/dist/components/LDRadio/LDRadio.d.ts.map +1 -1
  128. package/dist/components/LDRadio/LDRadio.js +58 -12
  129. package/dist/components/LDRadio/LDRadioGroup.d.ts +5 -3
  130. package/dist/components/LDRadio/LDRadioGroup.d.ts.map +1 -1
  131. package/dist/components/LDRadio/LDRadioGroup.js +11 -2
  132. package/dist/components/LDSectionNav/LDSectionNav.d.ts +11 -0
  133. package/dist/components/LDSectionNav/LDSectionNav.d.ts.map +1 -0
  134. package/dist/components/LDSectionNav/LDSectionNav.js +11 -0
  135. package/dist/components/LDSectionNav/SectionNavBase.d.ts +20 -0
  136. package/dist/components/LDSectionNav/SectionNavBase.d.ts.map +1 -0
  137. package/dist/components/LDSectionNav/SectionNavBase.js +53 -0
  138. package/dist/components/LDSelect/LDMultiSelect.js +3 -3
  139. package/dist/components/LDSelect/LDSelect.d.ts.map +1 -1
  140. package/dist/components/LDSelect/LDSelect.js +2 -2
  141. package/dist/components/LDTable/LDCollapsibleTanstackTable.d.ts.map +1 -1
  142. package/dist/components/LDTable/LDCollapsibleTanstackTable.js +12 -9
  143. package/dist/components/LDTable/LDTable.d.ts.map +1 -1
  144. package/dist/components/LDTable/LDTable.js +1 -1
  145. package/dist/components/LDTable/LDTanstackTable.d.ts.map +1 -1
  146. package/dist/components/LDTable/LDTanstackTable.js +5 -6
  147. package/dist/components/LDTable/TableField.d.ts.map +1 -1
  148. package/dist/components/LDTextarea/LDTextarea.js +1 -1
  149. package/dist/components/LDTimePicker/LDTimePicker.js +1 -1
  150. package/dist/components/LDToast/LDToaster.d.ts +2 -1
  151. package/dist/components/LDToast/LDToaster.d.ts.map +1 -1
  152. package/dist/components/LDToast/LDToaster.js +2 -2
  153. package/dist/components/LDToggleButton/LDFormToggleButton.d.ts +1 -3
  154. package/dist/components/LDToggleButton/LDFormToggleButton.d.ts.map +1 -1
  155. package/dist/components/LDToggleButton/LDFormToggleButton.js +3 -4
  156. package/dist/components/LDTooltip/LDTooltip.js +1 -1
  157. package/dist/components/LDTooltip/TooltipBase.d.ts +6 -2
  158. package/dist/components/LDTooltip/TooltipBase.d.ts.map +1 -1
  159. package/dist/components/LDTooltip/TooltipBase.js +4 -4
  160. package/dist/index.css +633 -166
  161. package/dist/index.d.ts +21 -13
  162. package/dist/index.d.ts.map +1 -1
  163. package/dist/index.js +25 -13
  164. package/package.json +14 -2
  165. package/src/styles/carousel.css +15 -14
  166. package/src/styles/components/editor.css +6 -0
  167. package/src/styles/components/input.css +14 -0
  168. package/src/styles/components/shared.css +6 -6
  169. package/src/styles/motion.css +78 -0
@@ -1,46 +1,26 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { Children, Fragment, isValidElement, useMemo, } from 'react';
4
- import LDInput, { iconSizes, } from './LDInput.js';
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
8
  import { Pencil, X } from 'lucide-react';
9
9
  import { renderIcon } from '../../utils/renderIcon.js';
10
10
  import { iconSizeClasses } from '../../components/LDButton/LDButton.js';
11
- // addon 아이콘 사이 gap과 동일한 값 (addonListGapClasses = control-padding-x / 2)
12
- const controlPaddingXVars = {
13
- '2xsmall': '--control-padding-x-input-2xs',
14
- xsmall: '--control-padding-x-input-xs',
15
- small: '--control-padding-x-input-sm',
16
- medium: '--control-padding-x-input-md',
17
- large: '--control-padding-x-input-lg',
18
- xlarge: '--control-padding-x-input-xl',
19
- };
20
11
  const LDFormInput = ({ name, options, variant = 'filled', size = 'small', block = false, disabled = false, ref, customErrorMessage = '', isHiddenErrorMessage = false, errorClassName, showEditIcon = false, rightAddon, ...props }) => {
21
12
  const iconSize = iconSizes[size ?? 'medium'];
22
- const count = useMemo(() => {
23
- const editIconCount = showEditIcon && !disabled ? 1 : 0;
24
- const innerCount = isValidElement(rightAddon) && rightAddon.type === Fragment
25
- ? Children.count(rightAddon.props.children)
26
- : Children.count(rightAddon);
27
- const visibleIcon = !props.hiddenPasswordToggle && props.type === 'password' ? 1 : 0;
28
- return editIconCount + visibleIcon + innerCount;
29
- }, [
30
- showEditIcon,
31
- disabled,
32
- rightAddon,
33
- props.hiddenPasswordToggle,
34
- props.type,
35
- ]);
13
+ const addonRef = useRef(null);
36
14
  return (_jsx(LDFormField, { name: name, options: options, customErrorMessage: customErrorMessage, disabled: disabled, ref: ref, children: ({ field, fieldState, resetField }) => {
37
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) => {
38
16
  e.preventDefault();
39
17
  resetField({ defaultValue: '' });
40
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;
41
19
  const combinedAddon = editIconAddon || rightAddon ? (_jsxs(_Fragment, { children: [editIconAddon, renderIcon(rightAddon, iconSizeClasses[size])] })) : undefined;
42
- 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, "aria-invalid": fieldState.hasError, "aria-describedby": fieldState.hasError ? fieldState.errorId : undefined }), !isHiddenErrorMessage && (_jsx(LDFormErrorMessage, { id: fieldState.errorId, error: fieldState.error, disabled: disabled, className: errorClassName, style: {
43
- marginRight: `calc(${count * iconSize}px + var(${controlPaddingXVars[size]}) / 2 * ${count})`,
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],
44
24
  } }))] }));
45
25
  } }));
46
26
  };
@@ -3,7 +3,7 @@ type InputVariant = 'filled' | 'outline' | 'ghost';
3
3
  type InputColor = 'neutral' | 'point' | 'danger';
4
4
  export type InputSize = '2xsmall' | 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge';
5
5
  export declare const inputSizeClasses: Record<InputSize, string>;
6
- export declare const addonListRightOffsetClasses: Record<InputSize, string>;
6
+ export declare const inputPaddingXVars: Record<InputSize, string>;
7
7
  export declare const iconSizes: Record<InputSize, number>;
8
8
  export interface LDInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'color' | 'size'> {
9
9
  /** 입력 필드 스타일 유형 */
@@ -16,11 +16,17 @@ export interface LDInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>
16
16
  hiddenPasswordToggle?: boolean;
17
17
  /** true 시 너비 100% */
18
18
  block?: boolean;
19
+ /** 래퍼(Root div)에 적용할 className */
20
+ rootClassName?: string;
19
21
  /** 우측 부가 요소 (아이콘 등) */
20
22
  rightAddon?: ReactNode;
23
+ /** 우측 addon 컨테이너 ref (addon 폭·위치 측정용) */
24
+ addonRef?: Ref<HTMLSpanElement>;
25
+ /** 입력값 바로 뒤에 표시할 텍스트 */
26
+ suffix?: string;
21
27
  /** input 요소 ref */
22
28
  ref?: Ref<HTMLInputElement>;
23
29
  }
24
- declare const LDInput: ({ variant, color, size, block, type, disabled, className, style, rightAddon, hiddenPasswordToggle, 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;
25
31
  export default LDInput;
26
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,EAGL,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;AAoCb,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAOtD,CAAC;AAWF,eAAO,MAAM,2BAA2B,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAOjE,CAAC;AAEF,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,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,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,oHAad,YAAY,4CA2Fd,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,24 +1,25 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useState, isValidElement, } 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
4
  import cn from '../../utils/cn.js';
5
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] [outline-offset:-2px] focus:bg-tintBlue focus:outline-lb500',
10
- point: 'bg-tintBlue text-neutral900 border-none outline-2 outline-transparent [outline-style:solid] [outline-offset:-2px] focus:outline-lb500',
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',
11
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-none outline-2 outline-neutral100 [outline-style:solid] [outline-offset:-2px] focus:outline-lb500',
15
+ neutral: 'bg-transparent text-neutral900 border-none outline-2 outline-neutral100 [outline-style:solid] [outline-offset:-2px] focus-within:outline-lb500',
15
16
  point: 'bg-transparent text-neutral900 border-none outline-2 outline-lb500 [outline-style:solid] [outline-offset:-2px]',
16
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 border-none outline-2 outline-transparent [outline-style:solid] [outline-offset:-2px] focus:bg-neutral50',
20
- point: 'bg-transparent border-none outline-2 outline-transparent [outline-style:solid] [outline-offset:-2px] focus:bg-tintBlue',
21
- danger: 'bg-transparent border-none outline-2 outline-transparent [outline-style:solid] [outline-offset:-2px] outline-danger600 focus:bg-tintRed',
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 = {
@@ -34,22 +35,29 @@ export const inputSizeClasses = {
34
35
  large: 'input-lg',
35
36
  xlarge: 'input-xl',
36
37
  };
37
- const addonListGapClasses = {
38
- '2xsmall': 'gap-[calc(var(--control-padding-x-input-2xs)/2)]',
39
- xsmall: 'gap-[calc(var(--control-padding-x-input-xs)/2)]',
40
- small: 'gap-[calc(var(--control-padding-x-input-sm)/2)]',
41
- medium: 'gap-[calc(var(--control-padding-x-input-md)/2)]',
42
- large: 'gap-[calc(var(--control-padding-x-input-lg)/2)]',
43
- xlarge: 'gap-[calc(var(--control-padding-x-input-xl)/2)]',
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)',
44
48
  };
45
- export const addonListRightOffsetClasses = {
46
- '2xsmall': 'right-[var(--control-padding-x-input-2xs)]',
47
- xsmall: 'right-[var(--control-padding-x-input-xs)]',
48
- small: 'right-[var(--control-padding-x-input-sm)]',
49
- medium: 'right-[var(--control-padding-x-input-md)]',
50
- large: 'right-[var(--control-padding-x-input-lg)]',
51
- xlarge: 'right-[var(--control-padding-x-input-xl)]',
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)]',
52
58
  };
59
+ // --control-icon-* 토큰(shared.css)과 값을 일치시킨다. addon 아이콘은 CSS 토큰으로,
60
+ // password/edit 토글 박스는 이 JS 맵으로 사이징되므로 둘이 같아야 어긋나지 않음.
53
61
  export const iconSizes = {
54
62
  '2xsmall': 8,
55
63
  xsmall: 12,
@@ -58,9 +66,22 @@ export const iconSizes = {
58
66
  large: 24,
59
67
  xlarge: 28,
60
68
  };
61
- const LDInput = ({ variant, color = 'neutral', size, block = false, type = 'text', disabled = false, className, style, rightAddon, hiddenPasswordToggle = false, ref, ...props }) => {
62
- const isExistAddonIconList = isValidElement(rightAddon);
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',
77
+ };
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 }) => {
63
79
  const [passwordVisible, setPasswordVisible] = useState(false);
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 위치 계산)
64
85
  const isPasswordToggle = !hiddenPasswordToggle && type === 'password';
65
86
  const resolvedType = isPasswordToggle
66
87
  ? passwordVisible
@@ -68,13 +89,55 @@ const LDInput = ({ variant, color = 'neutral', size, block = false, type = 'text
68
89
  : 'password'
69
90
  : type;
70
91
  const iconSize = iconSizes[size ?? 'medium'];
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]);
71
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;
72
118
  const { width, height, minWidth, maxWidth, minHeight, maxHeight, ...fieldStyle } = style ?? {};
73
- const rootStyle = { width, height, minWidth, maxWidth, minHeight, maxHeight };
74
- const fieldClassName = cn('w-full bold placeholder-neutral300 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 &&
75
131
  (disabled
76
132
  ? disabledVariantClasses[variant]
77
- : variantColorClasses[variant][color]), size && !height && inputSizeClasses[size], height && 'h-full', disabled && 'cursor-not-allowed', 'read-only:cursor-not-allowed', className);
78
- return (_jsxs(InputBase.Root, { block: block, style: rootStyle, children: [_jsx(InputBase.Field, { ref: ref, type: resolvedType, disabled: disabled, className: fieldClassName, style: fieldStyle, ...props }), _jsxs(InputBase.Addon, { position: "right", className: cn('text-neutral500 flex flex-row items-center', size ? addonListRightOffsetClasses[size] : 'right-2.5', isExistAddonIconList && addonListGapClasses[size ?? 'small']), children: [rightAddon, passwordToggleAddon] })] }));
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] }))] }));
79
142
  };
80
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;
@@ -1,21 +1,35 @@
1
- import type { ComponentProps } from 'react';
2
- import MenuBarBase from './MenuBarBase.js';
3
- declare const LDMenuBar: {
4
- Root: ({ className, ...props }: ComponentProps<typeof MenuBarBase.Root>) => import("react/jsx-runtime").JSX.Element;
5
- Logo: ({ className, ...props }: ComponentProps<typeof MenuBarBase.Logo>) => import("react/jsx-runtime").JSX.Element;
6
- Nav: ({ className, ...props }: ComponentProps<typeof MenuBarBase.Nav>) => import("react/jsx-runtime").JSX.Element;
7
- Item: ({ className, ...props }: ComponentProps<typeof MenuBarBase.Item>) => import("react/jsx-runtime").JSX.Element;
8
- Trigger: ({ className, ...props }: ComponentProps<typeof MenuBarBase.Trigger>) => import("react/jsx-runtime").JSX.Element;
9
- Content: {
10
- ({ className, ...props }: ComponentProps<typeof MenuBarBase.Content>): import("react/jsx-runtime").JSX.Element;
11
- displayName: string;
12
- };
13
- MegaContent: {
14
- ({ className, ...props }: ComponentProps<typeof MenuBarBase.Content>): import("react/jsx-runtime").JSX.Element;
15
- displayName: string;
16
- };
17
- Actions: ({ className, ...props }: ComponentProps<typeof MenuBarBase.Actions>) => import("react/jsx-runtime").JSX.Element;
18
- Separator: ({ className, }: ComponentProps<typeof MenuBarBase.Separator>) => import("react/jsx-runtime").JSX.Element;
19
- };
1
+ import type { ElementType, ReactNode } from 'react';
2
+ /** 메뉴바 항목 */
3
+ export interface LDMenuBarItem {
4
+ /** 항목 구분 값 (열림 상태 식별) */
5
+ value: string;
6
+ /** Trigger에 표시할 라벨/아이콘 */
7
+ label: ReactNode;
8
+ /** 드롭다운 내용. 있으면 드롭다운 항목, 없으면 단순 링크가 된다 */
9
+ content?: ReactNode;
10
+ /** content를 헤더 전체 폭(mega) 패널 + 딤으로 표시 */
11
+ mega?: boolean;
12
+ /** 단순 링크일 때 Trigger 렌더 엘리먼트 (라우터 Link 주입용, 기본 'button') */
13
+ as?: ElementType;
14
+ /** 단순 링크 href */
15
+ href?: string;
16
+ }
17
+ export interface LDMenuBarProps {
18
+ /** 메뉴바 항목 목록 */
19
+ items: LDMenuBarItem[];
20
+ /** 드롭다운 열림 트리거 방식. 기본 'hover' */
21
+ trigger?: 'hover' | 'click';
22
+ /** 좌측 로고 슬롯 */
23
+ logo?: ReactNode;
24
+ /** 우측 액션 슬롯 (알림·아바타 등) */
25
+ actions?: ReactNode;
26
+ /** Root에 적용할 추가 className */
27
+ className?: string;
28
+ }
29
+ /**
30
+ * 가로 헤더형 메뉴바. items로 네비게이션을 구성하고 logo/actions 슬롯에 임의 콘텐츠를 주입한다.
31
+ * item.content가 있으면 드롭다운, 없으면 단순 링크. item.mega면 헤더 전체 폭 패널로 열린다.
32
+ */
33
+ declare const LDMenuBar: ({ items, trigger, logo, actions, className, }: LDMenuBarProps) => import("react/jsx-runtime").JSX.Element;
20
34
  export default LDMenuBar;
21
35
  //# sourceMappingURL=LDMenuBar.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"LDMenuBar.d.ts","sourceRoot":"","sources":["../../../src/components/LDMenuBar/LDMenuBar.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AAE5C,OAAO,WAAW,MAAM,eAAe,CAAC;AAkHxC,QAAA,MAAM,SAAS;oCA1GZ,cAAc,CAAC,OAAO,WAAW,CAAC,IAAI,CAAC;oCAcvC,cAAc,CAAC,OAAO,WAAW,CAAC,IAAI,CAAC;mCAUvC,cAAc,CAAC,OAAO,WAAW,CAAC,GAAG,CAAC;oCAUtC,cAAc,CAAC,OAAO,WAAW,CAAC,IAAI,CAAC;uCAOvC,cAAc,CAAC,OAAO,WAAW,CAAC,OAAO,CAAC;;kCAgB1C,cAAc,CAAC,OAAO,WAAW,CAAC,OAAO,CAAC;;;;kCAgB1C,cAAc,CAAC,OAAO,WAAW,CAAC,OAAO,CAAC;;;uCAoB1C,cAAc,CAAC,OAAO,WAAW,CAAC,OAAO,CAAC;gCAS1C,cAAc,CAAC,OAAO,WAAW,CAAC,SAAS,CAAC;CAc9C,CAAC;AAEF,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"LDMenuBar.d.ts","sourceRoot":"","sources":["../../../src/components/LDMenuBar/LDMenuBar.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAOpD,aAAa;AACb,MAAM,WAAW,aAAa;IAC5B,yBAAyB;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,0BAA0B;IAC1B,KAAK,EAAE,SAAS,CAAC;IACjB,0CAA0C;IAC1C,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,yCAAyC;IACzC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,2DAA2D;IAC3D,EAAE,CAAC,EAAE,WAAW,CAAC;IACjB,iBAAiB;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,gBAAgB;IAChB,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,iCAAiC;IACjC,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC;IAC5B,eAAe;IACf,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,0BAA0B;IAC1B,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAsBD;;;GAGG;AACH,QAAA,MAAM,SAAS,GAAI,+CAMhB,cAAc,4CAuDhB,CAAC;AAEF,eAAe,SAAS,CAAC"}