@loword/loword-design-system 0.0.2 → 0.0.4

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 (263) hide show
  1. package/README.md +77 -3
  2. package/dist/components/BreadCrumb/BreadCrumb.d.ts +17 -0
  3. package/dist/components/BreadCrumb/BreadCrumb.d.ts.map +1 -0
  4. package/dist/components/BreadCrumb/BreadCrumb.js +37 -0
  5. package/dist/components/BreadCrumb/BreadCrumbBase.d.ts +9 -0
  6. package/dist/components/BreadCrumb/BreadCrumbBase.d.ts.map +1 -0
  7. package/dist/components/BreadCrumb/BreadCrumbBase.js +17 -0
  8. package/dist/components/Button/ButtonSpinner.d.ts +1 -2
  9. package/dist/components/Button/ButtonSpinner.d.ts.map +1 -1
  10. package/dist/components/Button/ButtonSpinner.js +3 -2
  11. package/dist/components/Callout/Callout.d.ts +10 -0
  12. package/dist/components/Callout/Callout.d.ts.map +1 -0
  13. package/dist/components/Callout/Callout.js +6 -0
  14. package/dist/components/Callout/CalloutBase.d.ts +18 -0
  15. package/dist/components/Callout/CalloutBase.d.ts.map +1 -0
  16. package/dist/components/Callout/CalloutBase.js +21 -0
  17. package/dist/components/Divider/Divider.d.ts +9 -0
  18. package/dist/components/Divider/Divider.d.ts.map +1 -0
  19. package/dist/components/Divider/Divider.js +11 -0
  20. package/dist/components/Divider/DividerBase.d.ts +9 -0
  21. package/dist/components/Divider/DividerBase.d.ts.map +1 -0
  22. package/dist/components/Divider/DividerBase.js +9 -0
  23. package/dist/components/FileUpload/FileUploadBase.d.ts +5 -5
  24. package/dist/components/FileUpload/FileUploadBase.d.ts.map +1 -1
  25. package/dist/components/FileUpload/FileUploadBase.js +4 -4
  26. package/dist/components/Form/FormField.d.ts +2 -2
  27. package/dist/components/LDAvatar/AvatarBase.d.ts +32 -0
  28. package/dist/components/LDAvatar/AvatarBase.d.ts.map +1 -0
  29. package/dist/components/LDAvatar/AvatarBase.js +49 -0
  30. package/dist/components/LDAvatar/LDAvatar.d.ts +11 -0
  31. package/dist/components/LDAvatar/LDAvatar.d.ts.map +1 -0
  32. package/dist/components/LDAvatar/LDAvatar.js +24 -0
  33. package/dist/components/LDBadge/BadgeBase.d.ts +10 -0
  34. package/dist/components/LDBadge/BadgeBase.d.ts.map +1 -0
  35. package/dist/components/LDBadge/BadgeBase.js +9 -0
  36. package/dist/components/LDBadge/LDBadge.d.ts +25 -0
  37. package/dist/components/LDBadge/LDBadge.d.ts.map +1 -0
  38. package/dist/components/LDBadge/LDBadge.js +36 -0
  39. package/dist/components/LDBreadCrumb/BreadCrumbBase.d.ts +9 -0
  40. package/dist/components/LDBreadCrumb/BreadCrumbBase.d.ts.map +1 -0
  41. package/dist/components/LDBreadCrumb/BreadCrumbBase.js +17 -0
  42. package/dist/components/LDBreadCrumb/LDBreadCrumb.d.ts +17 -0
  43. package/dist/components/LDBreadCrumb/LDBreadCrumb.d.ts.map +1 -0
  44. package/dist/components/LDBreadCrumb/LDBreadCrumb.js +37 -0
  45. package/dist/components/LDButton/ButtonBase.d.ts +5 -0
  46. package/dist/components/LDButton/ButtonBase.d.ts.map +1 -0
  47. package/dist/components/LDButton/ButtonBase.js +10 -0
  48. package/dist/components/LDButton/ButtonSpinner.d.ts +8 -0
  49. package/dist/components/LDButton/ButtonSpinner.d.ts.map +1 -0
  50. package/dist/components/LDButton/ButtonSpinner.js +15 -0
  51. package/dist/components/LDButton/LDButton.d.ts +26 -0
  52. package/dist/components/LDButton/LDButton.d.ts.map +1 -0
  53. package/dist/components/LDButton/LDButton.js +102 -0
  54. package/dist/components/LDCalendar/LDCalendar.d.ts +16 -0
  55. package/dist/components/LDCalendar/LDCalendar.d.ts.map +1 -0
  56. package/dist/components/LDCalendar/LDCalendar.js +75 -0
  57. package/dist/components/LDCallout/CalloutBase.d.ts +18 -0
  58. package/dist/components/LDCallout/CalloutBase.d.ts.map +1 -0
  59. package/dist/components/LDCallout/CalloutBase.js +21 -0
  60. package/dist/components/LDCallout/LDCallout.d.ts +10 -0
  61. package/dist/components/LDCallout/LDCallout.d.ts.map +1 -0
  62. package/dist/components/LDCallout/LDCallout.js +6 -0
  63. package/dist/components/LDCarousel/CarouselBase.d.ts +98 -0
  64. package/dist/components/LDCarousel/CarouselBase.d.ts.map +1 -0
  65. package/dist/components/LDCarousel/CarouselBase.js +144 -0
  66. package/dist/components/LDCarousel/LDCarousel.d.ts +50 -0
  67. package/dist/components/LDCarousel/LDCarousel.d.ts.map +1 -0
  68. package/dist/components/LDCarousel/LDCarousel.js +22 -0
  69. package/dist/components/LDCheckbox/CheckboxBase.d.ts +40 -0
  70. package/dist/components/LDCheckbox/CheckboxBase.d.ts.map +1 -0
  71. package/dist/components/LDCheckbox/CheckboxBase.js +57 -0
  72. package/dist/components/LDCheckbox/FormCheckbox.d.ts +14 -0
  73. package/dist/components/LDCheckbox/FormCheckbox.d.ts.map +1 -0
  74. package/dist/components/LDCheckbox/FormCheckbox.js +9 -0
  75. package/dist/components/LDCheckbox/FormCheckboxGroup.d.ts +13 -0
  76. package/dist/components/LDCheckbox/FormCheckboxGroup.d.ts.map +1 -0
  77. package/dist/components/LDCheckbox/FormCheckboxGroup.js +9 -0
  78. package/dist/components/LDCheckbox/LDCheckbox.d.ts +27 -0
  79. package/dist/components/LDCheckbox/LDCheckbox.d.ts.map +1 -0
  80. package/dist/components/LDCheckbox/LDCheckbox.js +30 -0
  81. package/dist/components/LDCheckbox/LDCheckboxGroup.d.ts +22 -0
  82. package/dist/components/LDCheckbox/LDCheckboxGroup.d.ts.map +1 -0
  83. package/dist/components/LDCheckbox/LDCheckboxGroup.js +13 -0
  84. package/dist/components/LDDataCalendar/DataCalendarBase.d.ts +45 -0
  85. package/dist/components/LDDataCalendar/DataCalendarBase.d.ts.map +1 -0
  86. package/dist/components/LDDataCalendar/DataCalendarBase.js +57 -0
  87. package/dist/components/LDDataCalendar/LDDataCalendar.d.ts +12 -0
  88. package/dist/components/LDDataCalendar/LDDataCalendar.d.ts.map +1 -0
  89. package/dist/components/LDDataCalendar/LDDataCalendar.js +13 -0
  90. package/dist/components/LDDatePicker/FormDatePicker.d.ts +12 -0
  91. package/dist/components/LDDatePicker/FormDatePicker.d.ts.map +1 -0
  92. package/dist/components/LDDatePicker/FormDatePicker.js +12 -0
  93. package/dist/components/LDDatePicker/LDDatePicker.d.ts +34 -0
  94. package/dist/components/LDDatePicker/LDDatePicker.d.ts.map +1 -0
  95. package/dist/components/LDDatePicker/LDDatePicker.js +44 -0
  96. package/dist/components/LDDateRangePicker/FormDateRangePicker.d.ts +12 -0
  97. package/dist/components/LDDateRangePicker/FormDateRangePicker.d.ts.map +1 -0
  98. package/dist/components/LDDateRangePicker/FormDateRangePicker.js +10 -0
  99. package/dist/components/LDDateRangePicker/LDDateRangePicker.d.ts +49 -0
  100. package/dist/components/LDDateRangePicker/LDDateRangePicker.d.ts.map +1 -0
  101. package/dist/components/LDDateRangePicker/LDDateRangePicker.js +197 -0
  102. package/dist/components/LDDivider/DividerBase.d.ts +9 -0
  103. package/dist/components/LDDivider/DividerBase.d.ts.map +1 -0
  104. package/dist/components/LDDivider/DividerBase.js +9 -0
  105. package/dist/components/LDDivider/LDDivider.d.ts +9 -0
  106. package/dist/components/LDDivider/LDDivider.d.ts.map +1 -0
  107. package/dist/components/LDDivider/LDDivider.js +11 -0
  108. package/dist/components/LDDrawer/DrawerBase.d.ts +52 -0
  109. package/dist/components/LDDrawer/DrawerBase.d.ts.map +1 -0
  110. package/dist/components/LDDrawer/DrawerBase.js +38 -0
  111. package/dist/components/LDDrawer/LDDrawer.d.ts +51 -0
  112. package/dist/components/LDDrawer/LDDrawer.d.ts.map +1 -0
  113. package/dist/components/LDDrawer/LDDrawer.js +30 -0
  114. package/dist/components/LDEditor/EditorBase.d.ts +52 -0
  115. package/dist/components/LDEditor/EditorBase.d.ts.map +1 -0
  116. package/dist/components/LDEditor/EditorBase.js +89 -0
  117. package/dist/components/LDEditor/LDEditor.d.ts +12 -0
  118. package/dist/components/LDEditor/LDEditor.d.ts.map +1 -0
  119. package/dist/components/LDEditor/LDEditor.js +162 -0
  120. package/dist/components/LDEditor/LDViewer.d.ts +7 -0
  121. package/dist/components/LDEditor/LDViewer.d.ts.map +1 -0
  122. package/dist/components/LDEditor/LDViewer.js +9 -0
  123. package/dist/components/LDEditor/extensions.d.ts +6 -0
  124. package/dist/components/LDEditor/extensions.d.ts.map +1 -0
  125. package/dist/components/LDEditor/extensions.js +38 -0
  126. package/dist/components/LDFileUpload/LDFileUploadBase.d.ts +50 -0
  127. package/dist/components/LDFileUpload/LDFileUploadBase.d.ts.map +1 -0
  128. package/dist/components/LDFileUpload/LDFileUploadBase.js +102 -0
  129. package/dist/components/LDInput/FormInput.d.ts +15 -0
  130. package/dist/components/LDInput/FormInput.d.ts.map +1 -0
  131. package/dist/components/LDInput/FormInput.js +19 -0
  132. package/dist/components/LDInput/InputBase.d.ts +22 -0
  133. package/dist/components/LDInput/InputBase.d.ts.map +1 -0
  134. package/dist/components/LDInput/InputBase.js +17 -0
  135. package/dist/components/LDInput/LDInput.d.ts +24 -0
  136. package/dist/components/LDInput/LDInput.d.ts.map +1 -0
  137. package/dist/components/LDInput/LDInput.js +71 -0
  138. package/dist/components/LDLNB/LDLNBBase.d.ts +82 -0
  139. package/dist/components/LDLNB/LDLNBBase.d.ts.map +1 -0
  140. package/dist/components/LDLNB/LDLNBBase.js +108 -0
  141. package/dist/components/LDLoadingDots/LDLoadingDots.d.ts +8 -0
  142. package/dist/components/LDLoadingDots/LDLoadingDots.d.ts.map +1 -0
  143. package/dist/components/LDLoadingDots/LDLoadingDots.js +29 -0
  144. package/dist/components/LDMenuBar/LDMenuBar.d.ts +21 -0
  145. package/dist/components/LDMenuBar/LDMenuBar.d.ts.map +1 -0
  146. package/dist/components/LDMenuBar/LDMenuBar.js +33 -0
  147. package/dist/components/LDMenuBar/MenuBarBase.d.ts +43 -0
  148. package/dist/components/LDMenuBar/MenuBarBase.d.ts.map +1 -0
  149. package/dist/components/LDMenuBar/MenuBarBase.js +69 -0
  150. package/dist/components/LDModal/LDModal.d.ts +51 -0
  151. package/dist/components/LDModal/LDModal.d.ts.map +1 -0
  152. package/dist/components/LDModal/LDModal.js +72 -0
  153. package/dist/components/LDModal/ModalBase.d.ts +42 -0
  154. package/dist/components/LDModal/ModalBase.d.ts.map +1 -0
  155. package/dist/components/LDModal/ModalBase.js +30 -0
  156. package/dist/components/LDModal/openModal.d.ts +24 -0
  157. package/dist/components/LDModal/openModal.d.ts.map +1 -0
  158. package/dist/components/LDModal/openModal.js +52 -0
  159. package/dist/components/LDOTPInput/LDOTPInput.d.ts +46 -0
  160. package/dist/components/LDOTPInput/LDOTPInput.d.ts.map +1 -0
  161. package/dist/components/LDOTPInput/LDOTPInput.js +87 -0
  162. package/dist/components/LDPagination/LDPagination.d.ts +12 -0
  163. package/dist/components/LDPagination/LDPagination.d.ts.map +1 -0
  164. package/dist/components/LDPagination/LDPagination.js +5 -0
  165. package/dist/components/LDPagination/PaginationBase.d.ts +36 -0
  166. package/dist/components/LDPagination/PaginationBase.d.ts.map +1 -0
  167. package/dist/components/LDPagination/PaginationBase.js +44 -0
  168. package/dist/components/LDPagination/paginationUtils.d.ts +2 -0
  169. package/dist/components/LDPagination/paginationUtils.d.ts.map +1 -0
  170. package/dist/components/LDPagination/paginationUtils.js +18 -0
  171. package/dist/components/LDPopover/LDPopover.d.ts +42 -0
  172. package/dist/components/LDPopover/LDPopover.d.ts.map +1 -0
  173. package/dist/components/LDPopover/LDPopover.js +31 -0
  174. package/dist/components/LDPopover/PopoverBase.d.ts +31 -0
  175. package/dist/components/LDPopover/PopoverBase.d.ts.map +1 -0
  176. package/dist/components/LDPopover/PopoverBase.js +18 -0
  177. package/dist/components/LDRadio/FormRadioGroup.d.ts +13 -0
  178. package/dist/components/LDRadio/FormRadioGroup.d.ts.map +1 -0
  179. package/dist/components/LDRadio/FormRadioGroup.js +9 -0
  180. package/dist/components/LDRadio/LDRadio.d.ts +24 -0
  181. package/dist/components/LDRadio/LDRadio.d.ts.map +1 -0
  182. package/dist/components/LDRadio/LDRadio.js +39 -0
  183. package/dist/components/LDRadio/LDRadioGroup.d.ts +22 -0
  184. package/dist/components/LDRadio/LDRadioGroup.d.ts.map +1 -0
  185. package/dist/components/LDRadio/LDRadioGroup.js +7 -0
  186. package/dist/components/LDRadio/RadioBase.d.ts +38 -0
  187. package/dist/components/LDRadio/RadioBase.d.ts.map +1 -0
  188. package/dist/components/LDRadio/RadioBase.js +46 -0
  189. package/dist/components/LDScrollArea/LDScrollArea.d.ts +15 -0
  190. package/dist/components/LDScrollArea/LDScrollArea.d.ts.map +1 -0
  191. package/dist/components/LDScrollArea/LDScrollArea.js +10 -0
  192. package/dist/components/LDSelect/FormMultiSelect.d.ts +13 -0
  193. package/dist/components/LDSelect/FormMultiSelect.d.ts.map +1 -0
  194. package/dist/components/LDSelect/FormMultiSelect.js +14 -0
  195. package/dist/components/LDSelect/FormSelect.d.ts +13 -0
  196. package/dist/components/LDSelect/FormSelect.d.ts.map +1 -0
  197. package/dist/components/LDSelect/FormSelect.js +10 -0
  198. package/dist/components/LDSelect/LDMultiSelect.d.ts +31 -0
  199. package/dist/components/LDSelect/LDMultiSelect.d.ts.map +1 -0
  200. package/dist/components/LDSelect/LDMultiSelect.js +59 -0
  201. package/dist/components/LDSelect/LDSelect.d.ts +41 -0
  202. package/dist/components/LDSelect/LDSelect.d.ts.map +1 -0
  203. package/dist/components/LDSelect/LDSelect.js +55 -0
  204. package/dist/components/LDSelect/SelectBase.d.ts +59 -0
  205. package/dist/components/LDSelect/SelectBase.d.ts.map +1 -0
  206. package/dist/components/LDSelect/SelectBase.js +211 -0
  207. package/dist/components/LDSkeleton/LDSkeleton.d.ts +10 -0
  208. package/dist/components/LDSkeleton/LDSkeleton.d.ts.map +1 -0
  209. package/dist/components/LDSkeleton/LDSkeleton.js +8 -0
  210. package/dist/components/LDSlider/LDSlider.d.ts +23 -0
  211. package/dist/components/LDSlider/LDSlider.d.ts.map +1 -0
  212. package/dist/components/LDSlider/LDSlider.js +195 -0
  213. package/dist/components/LDSpinner/LDSpinner.d.ts +25 -0
  214. package/dist/components/LDSpinner/LDSpinner.d.ts.map +1 -0
  215. package/dist/components/LDSpinner/LDSpinner.js +20 -0
  216. package/dist/components/LDTable/LDTable.d.ts +34 -0
  217. package/dist/components/LDTable/LDTable.d.ts.map +1 -0
  218. package/dist/components/LDTable/LDTable.js +29 -0
  219. package/dist/components/LDTable/LDTanstackTable.d.ts +23 -0
  220. package/dist/components/LDTable/LDTanstackTable.d.ts.map +1 -0
  221. package/dist/components/LDTable/LDTanstackTable.js +35 -0
  222. package/dist/components/LDTable/TableBase.d.ts +37 -0
  223. package/dist/components/LDTable/TableBase.d.ts.map +1 -0
  224. package/dist/components/LDTable/TableBase.js +39 -0
  225. package/dist/components/LDTable/TableField.d.ts +64 -0
  226. package/dist/components/LDTable/TableField.d.ts.map +1 -0
  227. package/dist/components/LDTable/TableField.js +87 -0
  228. package/dist/components/LDTimePicker/FormTimePicker.d.ts +12 -0
  229. package/dist/components/LDTimePicker/FormTimePicker.d.ts.map +1 -0
  230. package/dist/components/LDTimePicker/FormTimePicker.js +12 -0
  231. package/dist/components/LDTimePicker/LDTimePicker.d.ts +27 -0
  232. package/dist/components/LDTimePicker/LDTimePicker.d.ts.map +1 -0
  233. package/dist/components/LDTimePicker/LDTimePicker.js +120 -0
  234. package/dist/components/LDToast/LDToast.d.ts +18 -0
  235. package/dist/components/LDToast/LDToast.d.ts.map +1 -0
  236. package/dist/components/LDToast/LDToast.js +42 -0
  237. package/dist/components/LDToast/LDToaster.d.ts +7 -0
  238. package/dist/components/LDToast/LDToaster.d.ts.map +1 -0
  239. package/dist/components/LDToast/LDToaster.js +7 -0
  240. package/dist/components/LDToggleButton/FormToggleButton.d.ts +12 -0
  241. package/dist/components/LDToggleButton/FormToggleButton.d.ts.map +1 -0
  242. package/dist/components/LDToggleButton/FormToggleButton.js +9 -0
  243. package/dist/components/LDToggleButton/LDToggleButton.d.ts +31 -0
  244. package/dist/components/LDToggleButton/LDToggleButton.d.ts.map +1 -0
  245. package/dist/components/LDToggleButton/LDToggleButton.js +42 -0
  246. package/dist/components/LDToggleButton/ToggleButtonBase.d.ts +41 -0
  247. package/dist/components/LDToggleButton/ToggleButtonBase.d.ts.map +1 -0
  248. package/dist/components/LDToggleButton/ToggleButtonBase.js +59 -0
  249. package/dist/components/LDTooltip/LDTooltip.d.ts +18 -0
  250. package/dist/components/LDTooltip/LDTooltip.d.ts.map +1 -0
  251. package/dist/components/LDTooltip/LDTooltip.js +13 -0
  252. package/dist/components/LDTooltip/TooltipBase.d.ts +39 -0
  253. package/dist/components/LDTooltip/TooltipBase.d.ts.map +1 -0
  254. package/dist/components/LDTooltip/TooltipBase.js +46 -0
  255. package/dist/components/LNB/LNBBase.js +2 -2
  256. package/dist/components/Spinner/Spinner.d.ts +1 -1
  257. package/dist/components/Spinner/Spinner.d.ts.map +1 -1
  258. package/dist/components/Spinner/Spinner.js +1 -1
  259. package/dist/index.css +115 -13
  260. package/dist/index.d.ts +52 -49
  261. package/dist/index.d.ts.map +1 -1
  262. package/dist/index.js +88 -82
  263. package/package.json +1 -1
@@ -0,0 +1,211 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { createContext, useContext, useState, useEffect, useRef, useId, useCallback, } from 'react';
4
+ import cn from '../../utils/cn.js';
5
+ const SelectContext = createContext(null);
6
+ const useSelectContext = () => {
7
+ const ctx = useContext(SelectContext);
8
+ if (!ctx)
9
+ throw new Error('SelectBase 하위 컴포넌트는 Root 내부에서 사용해야 합니다.');
10
+ return ctx;
11
+ };
12
+ // ── Item Context (Item → ItemIndicator 간 value 공유) ──
13
+ const ItemContext = createContext(null);
14
+ const useItemContext = () => {
15
+ return useContext(ItemContext);
16
+ };
17
+ const Root = ({ multiple = false, value, defaultValue, values, defaultValues = [], onChange, onMultiChange, disabled = false, name, items, maxDisplay = 2, children, }) => {
18
+ const [open, setOpen] = useState(false);
19
+ const [internalValue, setInternalValue] = useState(defaultValue);
20
+ const [internalValues, setInternalValues] = useState(defaultValues);
21
+ const rootRef = useRef(null);
22
+ const listboxId = useId();
23
+ const isControlled = value !== undefined;
24
+ const isMultiControlled = values !== undefined;
25
+ const resolvedValue = isControlled ? value : internalValue;
26
+ const resolvedValues = isMultiControlled ? values : internalValues;
27
+ const handleChange = useCallback((val) => {
28
+ if (!isControlled)
29
+ setInternalValue(val);
30
+ onChange?.(val);
31
+ }, [isControlled, onChange]);
32
+ const handleMultiChange = useCallback((vals) => {
33
+ if (!isMultiControlled)
34
+ setInternalValues(vals);
35
+ onMultiChange?.(vals);
36
+ }, [isMultiControlled, onMultiChange]);
37
+ const toggleValue = useCallback((val) => {
38
+ if (disabled)
39
+ return;
40
+ const newValues = resolvedValues.includes(val)
41
+ ? resolvedValues.filter((v) => v !== val)
42
+ : [...resolvedValues, val];
43
+ handleMultiChange(newValues);
44
+ }, [disabled, resolvedValues, handleMultiChange]);
45
+ // click-outside (LDDropdown 방식: capture phase)
46
+ useEffect(() => {
47
+ const handler = (e) => {
48
+ if (!rootRef.current?.contains(e.target)) {
49
+ setOpen(false);
50
+ }
51
+ };
52
+ document.addEventListener('mousedown', handler, { capture: true });
53
+ return () => document.removeEventListener('mousedown', handler, { capture: true });
54
+ }, []);
55
+ return (_jsx(SelectContext.Provider, { value: {
56
+ open,
57
+ setOpen,
58
+ multiple,
59
+ value: resolvedValue,
60
+ values: resolvedValues,
61
+ onChange: handleChange,
62
+ onMultiChange: handleMultiChange,
63
+ toggleValue,
64
+ disabled,
65
+ listboxId,
66
+ items,
67
+ maxDisplay,
68
+ }, children: _jsxs("div", { ref: rootRef, className: "relative w-full", children: [name && (_jsx("input", { type: "hidden", name: name, value: multiple ? JSON.stringify(resolvedValues) : (resolvedValue ?? '') })), children] }) }));
69
+ };
70
+ const Trigger = ({ className, style, children, 'aria-invalid': ariaInvalid, 'aria-describedby': ariaDescribedby, }) => {
71
+ const { open, setOpen, disabled, listboxId } = useSelectContext();
72
+ return (_jsx("button", { type: "button", "aria-haspopup": "listbox", "aria-expanded": open, "aria-controls": listboxId, "aria-invalid": ariaInvalid, "aria-describedby": ariaDescribedby, disabled: disabled, "data-state": open ? 'open' : 'closed', onClick: () => {
73
+ if (!disabled)
74
+ setOpen(!open);
75
+ }, onKeyDown: (e) => {
76
+ if (disabled)
77
+ return;
78
+ if (e.key === 'Enter' ||
79
+ e.key === ' ' ||
80
+ e.key === 'ArrowDown' ||
81
+ e.key === 'ArrowUp') {
82
+ e.preventDefault();
83
+ if (!open) {
84
+ setOpen(true);
85
+ }
86
+ else if (e.key === 'ArrowDown') {
87
+ const listbox = document.getElementById(listboxId);
88
+ const firstOption = listbox?.querySelector('[role="option"]');
89
+ firstOption?.focus();
90
+ }
91
+ }
92
+ else if (e.key === 'Escape') {
93
+ setOpen(false);
94
+ // 닫힐 때 트리거로 포커스 이동을 위해 버튼을 찾음
95
+ e.currentTarget.focus();
96
+ }
97
+ }, style: style, className: cn('w-full flex justify-center items-center', className), children: children }));
98
+ };
99
+ const Value = ({ placeholder, className, placeholderClassName, }) => {
100
+ const { multiple, value, values, items, maxDisplay } = useSelectContext();
101
+ // 단일 선택
102
+ if (!multiple) {
103
+ const selectedLabel = items?.find((item) => item.value === value)?.label;
104
+ return (_jsx("span", { className: cn(className, selectedLabel == null && placeholderClassName), children: selectedLabel ?? placeholder }));
105
+ }
106
+ // 다중 선택
107
+ if (values.length === 0) {
108
+ return (_jsx("span", { className: cn(className, placeholderClassName), children: placeholder }));
109
+ }
110
+ const selectedLabels = items
111
+ ?.filter((item) => values.includes(item.value))
112
+ .map((item) => item.label) ?? [];
113
+ if (selectedLabels.length <= maxDisplay) {
114
+ return _jsx("span", { className: className, children: selectedLabels.join(', ') });
115
+ }
116
+ return (_jsxs("span", { className: className, children: [selectedLabels.slice(0, maxDisplay).join(', '), " \uC678", ' ', selectedLabels.length - maxDisplay, "\uAC1C"] }));
117
+ };
118
+ const Content = ({ className, openClassName, closedClassName, children, }) => {
119
+ const { open, multiple, listboxId } = useSelectContext();
120
+ useEffect(() => {
121
+ if (open) {
122
+ const focusAndScroll = () => {
123
+ const listbox = document.getElementById(listboxId);
124
+ if (!listbox)
125
+ return;
126
+ let targetOption = listbox.querySelector('[role="option"][aria-selected="true"]');
127
+ if (!targetOption) {
128
+ targetOption = listbox.querySelector('[role="option"]');
129
+ }
130
+ if (targetOption) {
131
+ targetOption.focus();
132
+ targetOption.scrollIntoView({ block: 'nearest' });
133
+ }
134
+ };
135
+ // 즉시 포커스 (키보드 대응)
136
+ setTimeout(focusAndScroll, 0);
137
+ // 트랜지션(약 200ms) 후 스크롤 재조정 (max-height가 0일 때 scrollIntoView가 씹히는 문제 방지)
138
+ setTimeout(focusAndScroll, 200);
139
+ }
140
+ }, [open, listboxId]);
141
+ return (_jsx("ul", { id: listboxId, role: "listbox", tabIndex: -1, "aria-hidden": !open, "aria-multiselectable": multiple || undefined, "data-state": open ? 'open' : 'closed', className: cn('absolute z-50 w-full mt-1', className, open ? openClassName : closedClassName), children: children }));
142
+ };
143
+ const Item = ({ value: itemValue, className, children }) => {
144
+ const { multiple, value, values, onChange, toggleValue, setOpen, disabled, listboxId, } = useSelectContext();
145
+ const [highlighted, setHighlighted] = useState(false);
146
+ const isSelected = multiple
147
+ ? values.includes(itemValue)
148
+ : value === itemValue;
149
+ const handleClick = useCallback(() => {
150
+ if (disabled)
151
+ return;
152
+ if (multiple) {
153
+ toggleValue(itemValue);
154
+ }
155
+ else {
156
+ onChange?.(itemValue);
157
+ setOpen(false);
158
+ }
159
+ }, [disabled, multiple, onChange, toggleValue, itemValue, setOpen]);
160
+ return (_jsx(ItemContext.Provider, { value: itemValue, children: _jsx("li", { role: "option", tabIndex: 0, "aria-selected": isSelected, "data-state": isSelected ? 'checked' : 'unchecked', "data-highlighted": highlighted || undefined, onMouseDown: (e) => e.preventDefault(), onClick: handleClick, onMouseEnter: () => setHighlighted(true), onMouseLeave: () => setHighlighted(false), onFocus: () => setHighlighted(true), onBlur: () => setHighlighted(false), onKeyDown: (e) => {
161
+ switch (e.key) {
162
+ case 'Enter':
163
+ case ' ':
164
+ e.preventDefault();
165
+ handleClick();
166
+ // 단일 선택 시 닫히고 트리거로 포커스 복귀
167
+ if (!multiple) {
168
+ const trigger = document.querySelector(`[aria-controls="${listboxId}"]`);
169
+ trigger?.focus();
170
+ }
171
+ break;
172
+ case 'Escape':
173
+ e.preventDefault();
174
+ setOpen(false);
175
+ document.querySelector(`[aria-controls="${listboxId}"]`)?.focus();
176
+ break;
177
+ case 'ArrowDown':
178
+ e.preventDefault();
179
+ e.currentTarget.nextElementSibling?.focus();
180
+ break;
181
+ case 'ArrowUp':
182
+ e.preventDefault();
183
+ e.currentTarget.previousElementSibling?.focus();
184
+ break;
185
+ }
186
+ }, className: cn('relative flex items-center outline-none cursor-pointer', className), children: children }) }));
187
+ };
188
+ // ── ItemText ──
189
+ const ItemText = ({ children }) => {
190
+ return _jsx("span", { children: children });
191
+ };
192
+ const ItemIndicator = ({ className, children }) => {
193
+ const { multiple, value, values } = useSelectContext();
194
+ const itemValue = useItemContext();
195
+ const isSelected = multiple
196
+ ? itemValue != null && values.includes(itemValue)
197
+ : value === itemValue;
198
+ if (!isSelected)
199
+ return null;
200
+ return _jsx("span", { className: cn('ml-auto', className), children: children });
201
+ };
202
+ export const SelectBase = {
203
+ Root,
204
+ Trigger,
205
+ Value,
206
+ Content,
207
+ Item,
208
+ ItemText,
209
+ ItemIndicator,
210
+ };
211
+ export default SelectBase;
@@ -0,0 +1,10 @@
1
+ import type { ReactNode } from 'react';
2
+ export interface LDSkeletonProps {
3
+ /** false이면 children을 그대로 렌더링합니다 */
4
+ loading?: boolean;
5
+ className?: string;
6
+ children?: ReactNode;
7
+ }
8
+ declare const LDSkeleton: ({ loading, className, children, }: LDSkeletonProps) => import("react/jsx-runtime").JSX.Element;
9
+ export default LDSkeleton;
10
+ //# sourceMappingURL=LDSkeleton.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LDSkeleton.d.ts","sourceRoot":"","sources":["../../../src/components/LDSkeleton/LDSkeleton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,MAAM,WAAW,eAAe;IAC9B,mCAAmC;IACnC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED,QAAA,MAAM,UAAU,GAAI,mCAIjB,eAAe,4CAgBjB,CAAC;AAEF,eAAe,UAAU,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import cn from '../../utils/cn.js';
3
+ const LDSkeleton = ({ loading = true, className, children, }) => {
4
+ if (!loading)
5
+ return _jsx(_Fragment, { children: children });
6
+ return (_jsxs("span", { "aria-busy": "true", "aria-label": "\uB85C\uB529 \uC911", className: cn('relative inline-block overflow-hidden rounded-md', className), children: [_jsx("span", { className: "invisible", children: children }), _jsx("span", { className: "absolute inset-0 rounded-[inherit] bg-mono200 animate-pulse" })] }));
7
+ };
8
+ export default LDSkeleton;
@@ -0,0 +1,23 @@
1
+ type SliderSingleProps = {
2
+ value?: number;
3
+ defaultValue?: number;
4
+ onChange?: (value: number) => void;
5
+ };
6
+ type SliderRangeProps = {
7
+ value?: [number, number];
8
+ defaultValue?: [number, number];
9
+ onChange?: (value: [number, number]) => void;
10
+ };
11
+ export type LDSliderProps = (SliderSingleProps | SliderRangeProps) & {
12
+ min?: number;
13
+ max?: number;
14
+ step?: number;
15
+ disabled?: boolean;
16
+ orientation?: 'horizontal' | 'vertical';
17
+ showLabel?: boolean;
18
+ className?: string;
19
+ style?: React.CSSProperties;
20
+ };
21
+ declare const LDSlider: (props: LDSliderProps) => import("react/jsx-runtime").JSX.Element;
22
+ export default LDSlider;
23
+ //# sourceMappingURL=LDSlider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LDSlider.d.ts","sourceRoot":"","sources":["../../../src/components/LDSlider/LDSlider.tsx"],"names":[],"mappings":"AAKA,KAAK,iBAAiB,GAAG;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC,CAAC;AAEF,KAAK,gBAAgB,GAAG;IACtB,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzB,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,CAAC;CAC9C,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,CAAC,iBAAiB,GAAG,gBAAgB,CAAC,GAAG;IACnE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,YAAY,GAAG,UAAU,CAAC;IACxC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B,CAAC;AAiCF,QAAA,MAAM,QAAQ,GAAI,OAAO,aAAa,4CAgUrC,CAAC;AAEF,eAAe,QAAQ,CAAC"}
@@ -0,0 +1,195 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useRef, useState, useCallback, useMemo } from 'react';
3
+ import cn from '../../utils/cn.js';
4
+ // ── 헬퍼 함수 ────────────────────────────────────────────────────────────────
5
+ //퍼센테이지 계산
6
+ const toPercent = (value, min, max) => {
7
+ return ((value - min) / (max - min)) * 100;
8
+ };
9
+ //값 제한
10
+ const clamp = (value, min, max) => {
11
+ return Math.min(Math.max(value, min), max);
12
+ };
13
+ //값 범위
14
+ const getValueFromPointer = (clientPos, rect, isVertical, min, max, step) => {
15
+ const ratio = isVertical
16
+ ? 1 - (clientPos - rect.top) / rect.height
17
+ : (clientPos - rect.left) / rect.width;
18
+ const raw = min + clamp(ratio, 0, 1) * (max - min);
19
+ const stepped = Math.round((raw - min) / step) * step + min;
20
+ return clamp(stepped, min, max);
21
+ };
22
+ // ── 컴포넌트 ──────────────────────────────────────────────────────────────
23
+ const LDSlider = (props) => {
24
+ const { min = 0, max = 100, step = 1, disabled = false, orientation = 'horizontal', showLabel = false, className, style, } = props;
25
+ const isVertical = orientation === 'vertical';
26
+ const isRange = Array.isArray(props.value ??
27
+ props.defaultValue);
28
+ // ── 단일 상태일 경우 제어, 비제어 상태 확인 ──
29
+ const singleControlled = !isRange && props.value !== undefined;
30
+ const [singleInternal, setSingleInternal] = useState(!isRange ? (props.defaultValue ?? min) : min);
31
+ const singleValue = singleControlled
32
+ ? props.value
33
+ : singleInternal;
34
+ // ── 범위 상태일 경우 제어, 비제어 상태 확인 ──
35
+ const rangeControlled = isRange && props.value !== undefined;
36
+ const [rangeInternal, setRangeInternal] = useState(isRange
37
+ ? (props.defaultValue ?? [min, max])
38
+ : [min, max]);
39
+ const rangeValue = rangeControlled
40
+ ? props.value
41
+ : rangeInternal;
42
+ // stale closure 방지: 핸들러에서 항상 최신 rangeValue 참조
43
+ const rangeValueRef = useRef(rangeValue);
44
+ rangeValueRef.current = rangeValue;
45
+ // ── 범위 모드 시 활성화된 손잡이(Thumb) 관리 ──
46
+ const trackRef = useRef(null);
47
+ const activeThumbRef = useRef('a');
48
+ const resolveActiveThumb = useCallback((clientPos) => {
49
+ if (!trackRef.current)
50
+ return 'a';
51
+ const rect = trackRef.current.getBoundingClientRect();
52
+ const ratio = isVertical
53
+ ? 1 - (clientPos - rect.top) / rect.height
54
+ : (clientPos - rect.left) / rect.width;
55
+ const pointValue = min + ratio * (max - min);
56
+ const current = rangeValueRef.current;
57
+ const distA = Math.abs(pointValue - current[0]);
58
+ const distB = Math.abs(pointValue - current[1]);
59
+ return distA <= distB ? 'a' : 'b';
60
+ }, [isVertical, min, max]);
61
+ // ── 변경 핸들러 ──
62
+ const handleSingleChange = useCallback((raw) => {
63
+ if (!singleControlled)
64
+ setSingleInternal(raw);
65
+ props.onChange?.(raw);
66
+ },
67
+ // eslint-disable-next-line react-hooks/exhaustive-deps
68
+ [singleControlled]);
69
+ const handleRangeChangeA = useCallback((raw) => {
70
+ const next = [
71
+ Math.min(raw, rangeValueRef.current[1]),
72
+ rangeValueRef.current[1],
73
+ ];
74
+ if (!rangeControlled)
75
+ setRangeInternal(next);
76
+ props.onChange?.(next);
77
+ },
78
+ // eslint-disable-next-line react-hooks/exhaustive-deps
79
+ [rangeControlled]);
80
+ const handleRangeChangeB = useCallback((raw) => {
81
+ const next = [
82
+ rangeValueRef.current[0],
83
+ Math.max(raw, rangeValueRef.current[0]),
84
+ ];
85
+ if (!rangeControlled)
86
+ setRangeInternal(next);
87
+ props.onChange?.(next);
88
+ },
89
+ // eslint-disable-next-line react-hooks/exhaustive-deps
90
+ [rangeControlled]);
91
+ // ── 트랙 포인터 핸들러 (클릭 이동 + 드래그) ──
92
+ const handleTrackPointerDown = useCallback((e) => {
93
+ if (disabled || !trackRef.current)
94
+ return;
95
+ e.currentTarget.setPointerCapture(e.pointerId);
96
+ const rect = trackRef.current.getBoundingClientRect();
97
+ const v = getValueFromPointer(isVertical ? e.clientY : e.clientX, rect, isVertical, min, max, step);
98
+ if (isRange) {
99
+ const which = resolveActiveThumb(isVertical ? e.clientY : e.clientX);
100
+ activeThumbRef.current = which;
101
+ if (which === 'a')
102
+ handleRangeChangeA(v);
103
+ else
104
+ handleRangeChangeB(v);
105
+ }
106
+ else {
107
+ handleSingleChange(v);
108
+ }
109
+ }, [
110
+ disabled,
111
+ isVertical,
112
+ min,
113
+ max,
114
+ step,
115
+ isRange,
116
+ resolveActiveThumb,
117
+ handleRangeChangeA,
118
+ handleRangeChangeB,
119
+ handleSingleChange,
120
+ ]);
121
+ const handleTrackPointerMove = useCallback((e) => {
122
+ if (disabled ||
123
+ !e.currentTarget.hasPointerCapture(e.pointerId) ||
124
+ !trackRef.current)
125
+ return;
126
+ const rect = trackRef.current.getBoundingClientRect();
127
+ const v = getValueFromPointer(isVertical ? e.clientY : e.clientX, rect, isVertical, min, max, step);
128
+ if (isRange) {
129
+ if (activeThumbRef.current === 'a')
130
+ handleRangeChangeA(v);
131
+ else
132
+ handleRangeChangeB(v);
133
+ }
134
+ else {
135
+ handleSingleChange(v);
136
+ }
137
+ }, [
138
+ disabled,
139
+ isVertical,
140
+ min,
141
+ max,
142
+ step,
143
+ isRange,
144
+ handleRangeChangeA,
145
+ handleRangeChangeB,
146
+ handleSingleChange,
147
+ ]);
148
+ // ── 채워지는 영역 퍼센트 계산 ──
149
+ const fillStyle = useMemo(() => {
150
+ if (isRange) {
151
+ const lo = toPercent(rangeValue[0], min, max);
152
+ const hi = toPercent(rangeValue[1], min, max);
153
+ return isVertical
154
+ ? { bottom: `${lo}%`, height: `${hi - lo}%` }
155
+ : { left: `${lo}%`, width: `${hi - lo}%` };
156
+ }
157
+ const pct = toPercent(clamp(singleValue, min, max), min, max);
158
+ return isVertical
159
+ ? { bottom: 0, height: `${pct}%` }
160
+ : { left: 0, width: `${pct}%` };
161
+ }, [isRange, isVertical, min, max, singleValue, rangeValue]);
162
+ // ── 라벨 위치 계산 ──
163
+ const labelAPercent = isRange
164
+ ? toPercent(rangeValue[0], min, max)
165
+ : toPercent(clamp(singleValue, min, max), min, max);
166
+ const labelBPercent = isRange ? toPercent(rangeValue[1], min, max) : 0;
167
+ const shouldOffsetLabel = isRange && Math.abs(labelBPercent - labelAPercent) < 8;
168
+ const getLabelStyle = (percent, which) => {
169
+ const offset = shouldOffsetLabel ? (which === 'a' ? -16 : 16) : 0;
170
+ if (isVertical) {
171
+ return {
172
+ position: 'absolute',
173
+ left: 'calc(100% + 8px)',
174
+ bottom: `${percent}%`,
175
+ transform: `translateY(calc(50% + ${offset}px))`,
176
+ };
177
+ }
178
+ return {
179
+ position: 'absolute',
180
+ bottom: 'calc(100% + 8px)',
181
+ left: `${percent}%`,
182
+ transform: `translateX(calc(-50% + ${offset}px))`,
183
+ };
184
+ };
185
+ // ── 수직 모드용 입력창 공통 스타일 ──
186
+ const inputStyle = isVertical
187
+ ? { writingMode: 'vertical-lr', direction: 'rtl' }
188
+ : {};
189
+ // ── 렌더링 ──────────────────────────────────────────────────────────────
190
+ return (_jsxs("div", { className: cn('relative flex items-center', isVertical ? 'flex-col h-48 w-fit' : 'flex-row w-full', className), style: style, children: [_jsxs("div", { ref: trackRef, onPointerDown: handleTrackPointerDown, onPointerMove: handleTrackPointerMove, className: cn('relative rounded-full bg-mono200', isVertical ? 'w-1.5 h-full' : 'h-1.5 w-full', disabled ? 'opacity-40 cursor-not-allowed' : 'cursor-pointer'), children: [_jsx("div", { className: "absolute rounded-full bg-lb500 pointer-events-none", style: {
191
+ ...(isVertical ? { left: 0, right: 0 } : { top: 0, bottom: 0 }),
192
+ ...fillStyle,
193
+ } }), !isRange && (_jsx("input", { type: "range", min: min, max: max, step: step, value: singleValue, disabled: disabled, onChange: (e) => handleSingleChange(e.target.valueAsNumber), className: "ld-slider-thumb absolute inset-0 w-full h-full", style: inputStyle })), isRange && (_jsxs(_Fragment, { children: [_jsx("input", { type: "range", min: min, max: max, step: step, value: rangeValue[0], disabled: disabled, onChange: (e) => handleRangeChangeA(e.target.valueAsNumber), className: "ld-slider-thumb absolute inset-0 w-full h-full z-0", style: inputStyle }), _jsx("input", { type: "range", min: min, max: max, step: step, value: rangeValue[1], disabled: disabled, onChange: (e) => handleRangeChangeB(e.target.valueAsNumber), className: "ld-slider-thumb absolute inset-0 w-full h-full z-0", style: inputStyle })] }))] }), showLabel && (_jsxs(_Fragment, { children: [_jsx("span", { className: "text-xs font-medium text-lb500 whitespace-nowrap pointer-events-none select-none", style: getLabelStyle(labelAPercent, 'a'), children: isRange ? rangeValue[0] : singleValue }), isRange && (_jsx("span", { className: "text-xs font-medium text-lb500 whitespace-nowrap pointer-events-none select-none", style: getLabelStyle(labelBPercent, 'b'), children: rangeValue[1] }))] }))] }));
194
+ };
195
+ export default LDSlider;
@@ -0,0 +1,25 @@
1
+ export type SpinnerSize = 'xSmall' | 'small' | 'medium' | 'large' | 'big' | 'xLarge';
2
+ export interface LDSpinnerProps {
3
+ /**
4
+ * LDSpinner의 크기를 지정합니다. 프리셋 이름이나 숫자(px)를 사용할 수 있습니다. (기본값: 'large' / 24px)
5
+ */
6
+ size?: SpinnerSize | number;
7
+ /**
8
+ * 추가적인 스타일 클래스를 지정합니다. (색상 등을 변경할 때 사용)
9
+ */
10
+ className?: string;
11
+ /**
12
+ * 사용할 아이콘 타입을 지정합니다. (기본값: 'default')
13
+ */
14
+ variant?: 'default' | 'split';
15
+ /**
16
+ * 접근성을 위한 라벨입니다. (기본값: 'loading')
17
+ */
18
+ label?: string;
19
+ }
20
+ /**
21
+ * 디자인 시스템 표준을 따르는 LDSpinner 컴포넌트입니다.
22
+ */
23
+ declare const LDSpinner: ({ size, className, variant, label, }: LDSpinnerProps) => import("react/jsx-runtime").JSX.Element;
24
+ export default LDSpinner;
25
+ //# sourceMappingURL=LDSpinner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LDSpinner.d.ts","sourceRoot":"","sources":["../../../src/components/LDSpinner/LDSpinner.tsx"],"names":[],"mappings":"AAGA,MAAM,MAAM,WAAW,GACnB,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,OAAO,GACP,KAAK,GACL,QAAQ,CAAC;AAWb,MAAM,WAAW,cAAc;IAC7B;;OAEG;IACH,IAAI,CAAC,EAAE,WAAW,GAAG,MAAM,CAAC;IAC5B;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,OAAO,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;IAC9B;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,QAAA,MAAM,SAAS,GAAI,sCAKhB,cAAc,4CAYhB,CAAC;AAEF,eAAe,SAAS,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { LoaderIcon, LoaderCircleIcon } from 'lucide-react';
3
+ import cn from '../../utils/cn.js';
4
+ const sizeMap = {
5
+ xSmall: 12,
6
+ small: 16,
7
+ medium: 20,
8
+ large: 24,
9
+ big: 32,
10
+ xLarge: 48,
11
+ };
12
+ /**
13
+ * 디자인 시스템 표준을 따르는 LDSpinner 컴포넌트입니다.
14
+ */
15
+ const LDSpinner = ({ size = 'large', className, variant = 'default', label = 'loading', }) => {
16
+ const Icon = variant === 'default' ? LoaderCircleIcon : LoaderIcon;
17
+ const pixelSize = typeof size === 'number' ? size : sizeMap[size];
18
+ return (_jsx(Icon, { size: pixelSize, className: cn('animate-spin text-muted-foreground', className), role: "status", "aria-label": label }));
19
+ };
20
+ export default LDSpinner;
@@ -0,0 +1,34 @@
1
+ import { type ReactNode, type CSSProperties } from 'react';
2
+ export interface LDTableProps {
3
+ /** 테이블 콘텐츠 (LDTable.Header, LDTable.Body 등) */
4
+ children: ReactNode;
5
+ /** 상단 타이틀 텍스트 */
6
+ title?: string;
7
+ /** 전체 데이터 건수 (타이틀 옆에 표시) */
8
+ totalCount?: number;
9
+ /** 타이틀 우측에 배치할 요소 (버튼, 필터 등) */
10
+ /** 테이블 상단에 배치할 요소 */
11
+ /** 테이블 하단에 배치할 요소 (LDPagination 등) */
12
+ footer?: ReactNode;
13
+ /** 데이터 없음 상태 여부 */
14
+ isEmpty?: boolean;
15
+ /** 데이터 없을 때 표시할 메시지 */
16
+ emptyMessage?: string | ReactNode;
17
+ /** 빈 상태 행의 colSpan 값 */
18
+ columnCount?: number;
19
+ className?: string;
20
+ style?: CSSProperties;
21
+ }
22
+ declare const LDTable: {
23
+ ({ children, title, totalCount, footer, isEmpty, emptyMessage, columnCount, className, style, }: LDTableProps): import("react/jsx-runtime").JSX.Element;
24
+ Header: ({ className, children, ...props }: React.HTMLAttributes<HTMLTableSectionElement>) => import("react/jsx-runtime").JSX.Element;
25
+ HeaderRow: ({ className, children, ...props }: React.HTMLAttributes<HTMLTableRowElement>) => import("react/jsx-runtime").JSX.Element;
26
+ HeaderCell: ({ className, children, ...props }: React.ThHTMLAttributes<HTMLTableCellElement>) => import("react/jsx-runtime").JSX.Element;
27
+ Body: ({ className, children, ...props }: React.HTMLAttributes<HTMLTableSectionElement>) => import("react/jsx-runtime").JSX.Element;
28
+ Row: ({ className, children, ...props }: React.HTMLAttributes<HTMLTableRowElement> & {
29
+ selected?: boolean;
30
+ }) => import("react/jsx-runtime").JSX.Element;
31
+ Cell: ({ className, children, ...props }: React.TdHTMLAttributes<HTMLTableCellElement>) => import("react/jsx-runtime").JSX.Element;
32
+ };
33
+ export default LDTable;
34
+ //# sourceMappingURL=LDTable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LDTable.d.ts","sourceRoot":"","sources":["../../../src/components/LDTable/LDTable.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAI3D,MAAM,WAAW,YAAY;IAC3B,+CAA+C;IAC/C,QAAQ,EAAE,SAAS,CAAC;IACpB,iBAAiB;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,gCAAgC;IAGhC,qBAAqB;IAGrB,sCAAsC;IACtC,MAAM,CAAC,EAAE,SAAS,CAAC;IAQnB,mBAAmB;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,uBAAuB;IACvB,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAElC,wBAAwB;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CAOvB;AAED,QAAA,MAAM,OAAO;qGAgBV,YAAY;gDAmCZ,KAAK,CAAC,cAAc,CAAC,uBAAuB,CAAC;mDAgB7C,KAAK,CAAC,cAAc,CAAC,mBAAmB,CAAC;oDAUzC,KAAK,CAAC,gBAAgB,CAAC,oBAAoB,CAAC;8CAa5C,KAAK,CAAC,cAAc,CAAC,uBAAuB,CAAC;6CAU7C,KAAK,CAAC,cAAc,CAAC,mBAAmB,CAAC,GAAG;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE;8CAgBlE,KAAK,CAAC,gBAAgB,CAAC,oBAAoB,CAAC;CAxE9C,CAAC;AAqFF,eAAe,OAAO,CAAC"}
@@ -0,0 +1,29 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import TableBase from './TableBase.js';
3
+ import cn from '../../utils/cn.js';
4
+ const LDTable = ({ children, title, totalCount,
5
+ // rightSideContents,
6
+ // tableTop,
7
+ footer,
8
+ // scrollable = false,
9
+ // scrollMinWidth = '1440px',
10
+ isEmpty = false, emptyMessage = '조회하신 데이터가 없습니다.', columnCount, className, style,
11
+ // wrapperClassName,
12
+ // wrapperStyle,
13
+ }) => {
14
+ return (_jsxs("div", { className: cn('flex flex-col justify-between h-full gap-sm'), children: [title && (_jsxs("h3", { className: "whitespace-nowrap display16 bold", children: [title, totalCount !== undefined && ` (${totalCount.toLocaleString()})`] })), _jsxs(TableBase.Root, { className: cn('w-full', className), style: style, children: [children, isEmpty && columnCount && (_jsx(TableBase.Body, { children: _jsx(TableBase.Row, { children: _jsx(TableBase.Cell, { colSpan: columnCount, className: "text-center h-24 py-24", children: emptyMessage }) }) }))] }), footer] }));
15
+ };
16
+ // ── Styled Sub-components ──
17
+ const Header = ({ className, children, ...props }) => (_jsx(TableBase.Header, { className: cn('border-b border-neutral700 bg-mono100 hover:bg-mono200 ld-transition', className), ...props, children: children }));
18
+ const HeaderRow = ({ className, children, ...props }) => (_jsx(TableBase.HeaderRow, { className: cn('bg-neutral5', className), ...props, children: children }));
19
+ const HeaderCell = ({ className, children, ...props }) => (_jsx(TableBase.HeaderCell, { className: cn('px-4 py-3 text-left display12 regular', className), ...props, children: children }));
20
+ const Body = ({ className, children, ...props }) => (_jsx(TableBase.Body, { className: className, ...props, children: children }));
21
+ const Row = ({ className, children, ...props }) => (_jsx(TableBase.Row, { className: cn('border-b border-neutral100 hover:bg-black/3 ld-transition', className), ...props, children: children }));
22
+ const Cell = ({ className, children, ...props }) => (_jsx(TableBase.Cell, { className: cn('px-4 py-3 display14', className), ...props, children: children }));
23
+ LDTable.Header = Header;
24
+ LDTable.HeaderRow = HeaderRow;
25
+ LDTable.HeaderCell = HeaderCell;
26
+ LDTable.Body = Body;
27
+ LDTable.Row = Row;
28
+ LDTable.Cell = Cell;
29
+ export default LDTable;
@@ -0,0 +1,23 @@
1
+ import { type ReactNode, type CSSProperties } from 'react';
2
+ import { type TableFieldProps, type Pageable } from './TableField.js';
3
+ export type { Pageable };
4
+ export interface LDTanstackTableProps<TData, TColumn> extends Omit<TableFieldProps<TData, TColumn>, 'children'> {
5
+ title?: string;
6
+ rightSideContents?: ReactNode;
7
+ tableTop?: ReactNode;
8
+ showPagination?: boolean;
9
+ emptyMessage?: string | ReactNode;
10
+ scrollable?: boolean;
11
+ stickyHeader?: boolean;
12
+ className?: string;
13
+ wrapperClassName?: string;
14
+ wrapperStyle?: CSSProperties;
15
+ headerClassName?: string;
16
+ theadClassName?: string;
17
+ rowClassName?: string;
18
+ cellClassName?: string;
19
+ paginationClassName?: string;
20
+ }
21
+ declare const LDTanstackTable: <TData, TColumn>({ columns, data, pageable, paginationState, onPageChange, sortingState, enableRowSelection, enableMultiRowSelection, rowSelectionState, enableToggleAllRowsSelection, getRowId, title, showPagination, emptyMessage, stickyHeader, className, headerClassName, theadClassName, rowClassName, cellClassName, paginationClassName, }: LDTanstackTableProps<TData, TColumn>) => import("react/jsx-runtime").JSX.Element;
22
+ export default LDTanstackTable;
23
+ //# sourceMappingURL=LDTanstackTable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LDTanstackTable.d.ts","sourceRoot":"","sources":["../../../src/components/LDTable/LDTanstackTable.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAE3D,OAAmB,EAAE,KAAK,eAAe,EAAE,KAAK,QAAQ,EAAE,MAAM,cAAc,CAAC;AAM/E,YAAY,EAAE,QAAQ,EAAE,CAAC;AAEzB,MAAM,WAAW,oBAAoB,CAAC,KAAK,EAAE,OAAO,CAAE,SAAQ,IAAI,CAChE,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,EAC/B,UAAU,CACX;IAEC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,SAAS,CAAC;IAC9B,QAAQ,CAAC,EAAE,SAAS,CAAC;IAGrB,cAAc,CAAC,EAAE,OAAO,CAAC;IAGzB,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;IAGvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,aAAa,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED,QAAA,MAAM,eAAe,GAAI,KAAK,EAAE,OAAO,EAAE,oUAwBtC,oBAAoB,CAAC,KAAK,EAAE,OAAO,CAAC,4CA+HtC,CAAC;AAEF,eAAe,eAAe,CAAC"}
@@ -0,0 +1,35 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { ArrowUp, ArrowDown } from 'lucide-react';
4
+ import TableField from './TableField.js';
5
+ import LDTable from './LDTable.js';
6
+ import LDPagination from '../LDPagination/LDPagination.js';
7
+ import cn from '../../utils/cn.js';
8
+ const LDTanstackTable = ({
9
+ // TableField props
10
+ columns, data, pageable, paginationState, onPageChange, sortingState, enableRowSelection, enableMultiRowSelection, rowSelectionState, enableToggleAllRowsSelection, getRowId,
11
+ // 프레젠테이션 props
12
+ title, showPagination = true, emptyMessage, stickyHeader = false, className, headerClassName, theadClassName, rowClassName, cellClassName, paginationClassName, }) => {
13
+ return (_jsx(TableField, { columns: columns, data: data, pageable: pageable, paginationState: paginationState, onPageChange: onPageChange, sortingState: sortingState, enableRowSelection: enableRowSelection, enableMultiRowSelection: enableMultiRowSelection, rowSelectionState: rowSelectionState, enableToggleAllRowsSelection: enableToggleAllRowsSelection, getRowId: getRowId, children: ({ headerGroups, rows, isEmpty, currentPage, totalPages, toggleAllRowsSelected, onPageChange: handlePageChange, getHeader, getCell, }) => {
14
+ const paginationFooter = showPagination && !isEmpty && pageable && totalPages > 0 ? (_jsx(LDPagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: handlePageChange, className: paginationClassName })) : null;
15
+ return (_jsxs(LDTable, { title: title, totalCount: pageable?.totalCount,
16
+ // rightSideContents={rightSideContents}
17
+ // tableTop={tableTop}
18
+ // scrollable={scrollable}
19
+ isEmpty: isEmpty, emptyMessage: emptyMessage, columnCount: columns.length, footer: paginationFooter, className: className, children: [_jsx(LDTable.Header, { className: cn('hover:bg-mono11 ld-transition', theadClassName), children: headerGroups.map((hg) => (_jsx(LDTable.HeaderRow, { className: "w-full", onClick: toggleAllRowsSelected, children: hg.headers.map((header) => {
20
+ const h = getHeader(header);
21
+ return (_jsxs(LDTable.HeaderCell, { className: cn('relative h-9', headerClassName, stickyHeader &&
22
+ 'sticky top-0 bg-mono10 z-10 border-b border-neutral10', h.canSort && 'cursor-pointer', h.meta
23
+ ?.headerAlign === 'left'
24
+ ? 'text-left'
25
+ : h.meta
26
+ ?.headerAlign === 'right'
27
+ ? 'text-right'
28
+ : 'text-center'), style: { width: h.size }, onClick: h.toggleSortingHandler, children: [h.renderHeader(), h.isSorted === 'asc' && (_jsx(ArrowUp, { className: "inline-block w-3 h-3 ml-1 align-middle" })), h.isSorted === 'desc' && (_jsx(ArrowDown, { className: "inline-block w-3 h-3 ml-1 align-middle" }))] }, h.id));
29
+ }) }, hg.id))) }), !isEmpty && (_jsx(LDTable.Body, { children: rows.map((row) => (_jsx(LDTable.Row, { selected: row.getIsSelected(), className: cn('hover:bg-black/3 ld-transition h-13', rowClassName), onClick: () => row.toggleSelected(), children: row.getVisibleCells().map((cell) => {
30
+ const c = getCell(cell);
31
+ return (_jsx(LDTable.Cell, { className: cellClassName, children: c.renderCell() }, c.id));
32
+ }) }, row.id))) }))] }));
33
+ } }));
34
+ };
35
+ export default LDTanstackTable;