@loword/loword-design-system 0.0.2 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/BreadCrumb/BreadCrumb.d.ts +17 -0
- package/dist/components/BreadCrumb/BreadCrumb.d.ts.map +1 -0
- package/dist/components/BreadCrumb/BreadCrumb.js +37 -0
- package/dist/components/BreadCrumb/BreadCrumbBase.d.ts +9 -0
- package/dist/components/BreadCrumb/BreadCrumbBase.d.ts.map +1 -0
- package/dist/components/BreadCrumb/BreadCrumbBase.js +17 -0
- package/dist/components/Button/ButtonSpinner.d.ts +1 -2
- package/dist/components/Button/ButtonSpinner.d.ts.map +1 -1
- package/dist/components/Button/ButtonSpinner.js +3 -2
- package/dist/components/Callout/Callout.d.ts +10 -0
- package/dist/components/Callout/Callout.d.ts.map +1 -0
- package/dist/components/Callout/Callout.js +6 -0
- package/dist/components/Callout/CalloutBase.d.ts +18 -0
- package/dist/components/Callout/CalloutBase.d.ts.map +1 -0
- package/dist/components/Callout/CalloutBase.js +21 -0
- package/dist/components/Divider/Divider.d.ts +9 -0
- package/dist/components/Divider/Divider.d.ts.map +1 -0
- package/dist/components/Divider/Divider.js +11 -0
- package/dist/components/Divider/DividerBase.d.ts +9 -0
- package/dist/components/Divider/DividerBase.d.ts.map +1 -0
- package/dist/components/Divider/DividerBase.js +9 -0
- package/dist/components/FileUpload/FileUploadBase.d.ts +5 -5
- package/dist/components/FileUpload/FileUploadBase.d.ts.map +1 -1
- package/dist/components/FileUpload/FileUploadBase.js +4 -4
- package/dist/components/Form/FormField.d.ts +2 -2
- package/dist/components/LDAvatar/AvatarBase.d.ts +32 -0
- package/dist/components/LDAvatar/AvatarBase.d.ts.map +1 -0
- package/dist/components/LDAvatar/AvatarBase.js +49 -0
- package/dist/components/LDAvatar/LDAvatar.d.ts +11 -0
- package/dist/components/LDAvatar/LDAvatar.d.ts.map +1 -0
- package/dist/components/LDAvatar/LDAvatar.js +24 -0
- package/dist/components/LDBadge/BadgeBase.d.ts +10 -0
- package/dist/components/LDBadge/BadgeBase.d.ts.map +1 -0
- package/dist/components/LDBadge/BadgeBase.js +9 -0
- package/dist/components/LDBadge/LDBadge.d.ts +25 -0
- package/dist/components/LDBadge/LDBadge.d.ts.map +1 -0
- package/dist/components/LDBadge/LDBadge.js +36 -0
- package/dist/components/LDBreadCrumb/BreadCrumbBase.d.ts +9 -0
- package/dist/components/LDBreadCrumb/BreadCrumbBase.d.ts.map +1 -0
- package/dist/components/LDBreadCrumb/BreadCrumbBase.js +17 -0
- package/dist/components/LDBreadCrumb/LDBreadCrumb.d.ts +17 -0
- package/dist/components/LDBreadCrumb/LDBreadCrumb.d.ts.map +1 -0
- package/dist/components/LDBreadCrumb/LDBreadCrumb.js +37 -0
- package/dist/components/LDButton/ButtonBase.d.ts +5 -0
- package/dist/components/LDButton/ButtonBase.d.ts.map +1 -0
- package/dist/components/LDButton/ButtonBase.js +10 -0
- package/dist/components/LDButton/ButtonSpinner.d.ts +8 -0
- package/dist/components/LDButton/ButtonSpinner.d.ts.map +1 -0
- package/dist/components/LDButton/ButtonSpinner.js +15 -0
- package/dist/components/LDButton/LDButton.d.ts +26 -0
- package/dist/components/LDButton/LDButton.d.ts.map +1 -0
- package/dist/components/LDButton/LDButton.js +102 -0
- package/dist/components/LDCalendar/LDCalendar.d.ts +16 -0
- package/dist/components/LDCalendar/LDCalendar.d.ts.map +1 -0
- package/dist/components/LDCalendar/LDCalendar.js +75 -0
- package/dist/components/LDCallout/CalloutBase.d.ts +18 -0
- package/dist/components/LDCallout/CalloutBase.d.ts.map +1 -0
- package/dist/components/LDCallout/CalloutBase.js +21 -0
- package/dist/components/LDCallout/LDCallout.d.ts +10 -0
- package/dist/components/LDCallout/LDCallout.d.ts.map +1 -0
- package/dist/components/LDCallout/LDCallout.js +6 -0
- package/dist/components/LDCarousel/CarouselBase.d.ts +98 -0
- package/dist/components/LDCarousel/CarouselBase.d.ts.map +1 -0
- package/dist/components/LDCarousel/CarouselBase.js +144 -0
- package/dist/components/LDCarousel/LDCarousel.d.ts +50 -0
- package/dist/components/LDCarousel/LDCarousel.d.ts.map +1 -0
- package/dist/components/LDCarousel/LDCarousel.js +22 -0
- package/dist/components/LDCheckbox/CheckboxBase.d.ts +40 -0
- package/dist/components/LDCheckbox/CheckboxBase.d.ts.map +1 -0
- package/dist/components/LDCheckbox/CheckboxBase.js +57 -0
- package/dist/components/LDCheckbox/FormCheckbox.d.ts +14 -0
- package/dist/components/LDCheckbox/FormCheckbox.d.ts.map +1 -0
- package/dist/components/LDCheckbox/FormCheckbox.js +9 -0
- package/dist/components/LDCheckbox/FormCheckboxGroup.d.ts +13 -0
- package/dist/components/LDCheckbox/FormCheckboxGroup.d.ts.map +1 -0
- package/dist/components/LDCheckbox/FormCheckboxGroup.js +9 -0
- package/dist/components/LDCheckbox/LDCheckbox.d.ts +27 -0
- package/dist/components/LDCheckbox/LDCheckbox.d.ts.map +1 -0
- package/dist/components/LDCheckbox/LDCheckbox.js +30 -0
- package/dist/components/LDCheckbox/LDCheckboxGroup.d.ts +22 -0
- package/dist/components/LDCheckbox/LDCheckboxGroup.d.ts.map +1 -0
- package/dist/components/LDCheckbox/LDCheckboxGroup.js +13 -0
- package/dist/components/LDDataCalendar/DataCalendarBase.d.ts +45 -0
- package/dist/components/LDDataCalendar/DataCalendarBase.d.ts.map +1 -0
- package/dist/components/LDDataCalendar/DataCalendarBase.js +57 -0
- package/dist/components/LDDataCalendar/LDDataCalendar.d.ts +12 -0
- package/dist/components/LDDataCalendar/LDDataCalendar.d.ts.map +1 -0
- package/dist/components/LDDataCalendar/LDDataCalendar.js +13 -0
- package/dist/components/LDDatePicker/FormDatePicker.d.ts +12 -0
- package/dist/components/LDDatePicker/FormDatePicker.d.ts.map +1 -0
- package/dist/components/LDDatePicker/FormDatePicker.js +12 -0
- package/dist/components/LDDatePicker/LDDatePicker.d.ts +34 -0
- package/dist/components/LDDatePicker/LDDatePicker.d.ts.map +1 -0
- package/dist/components/LDDatePicker/LDDatePicker.js +44 -0
- package/dist/components/LDDateRangePicker/FormDateRangePicker.d.ts +12 -0
- package/dist/components/LDDateRangePicker/FormDateRangePicker.d.ts.map +1 -0
- package/dist/components/LDDateRangePicker/FormDateRangePicker.js +10 -0
- package/dist/components/LDDateRangePicker/LDDateRangePicker.d.ts +49 -0
- package/dist/components/LDDateRangePicker/LDDateRangePicker.d.ts.map +1 -0
- package/dist/components/LDDateRangePicker/LDDateRangePicker.js +197 -0
- package/dist/components/LDDivider/DividerBase.d.ts +9 -0
- package/dist/components/LDDivider/DividerBase.d.ts.map +1 -0
- package/dist/components/LDDivider/DividerBase.js +9 -0
- package/dist/components/LDDivider/LDDivider.d.ts +9 -0
- package/dist/components/LDDivider/LDDivider.d.ts.map +1 -0
- package/dist/components/LDDivider/LDDivider.js +11 -0
- package/dist/components/LDDrawer/DrawerBase.d.ts +52 -0
- package/dist/components/LDDrawer/DrawerBase.d.ts.map +1 -0
- package/dist/components/LDDrawer/DrawerBase.js +38 -0
- package/dist/components/LDDrawer/LDDrawer.d.ts +51 -0
- package/dist/components/LDDrawer/LDDrawer.d.ts.map +1 -0
- package/dist/components/LDDrawer/LDDrawer.js +30 -0
- package/dist/components/LDEditor/EditorBase.d.ts +52 -0
- package/dist/components/LDEditor/EditorBase.d.ts.map +1 -0
- package/dist/components/LDEditor/EditorBase.js +89 -0
- package/dist/components/LDEditor/LDEditor.d.ts +12 -0
- package/dist/components/LDEditor/LDEditor.d.ts.map +1 -0
- package/dist/components/LDEditor/LDEditor.js +162 -0
- package/dist/components/LDEditor/LDViewer.d.ts +7 -0
- package/dist/components/LDEditor/LDViewer.d.ts.map +1 -0
- package/dist/components/LDEditor/LDViewer.js +9 -0
- package/dist/components/LDEditor/extensions.d.ts +6 -0
- package/dist/components/LDEditor/extensions.d.ts.map +1 -0
- package/dist/components/LDEditor/extensions.js +38 -0
- package/dist/components/LDInput/FormInput.d.ts +15 -0
- package/dist/components/LDInput/FormInput.d.ts.map +1 -0
- package/dist/components/LDInput/FormInput.js +19 -0
- package/dist/components/LDInput/InputBase.d.ts +22 -0
- package/dist/components/LDInput/InputBase.d.ts.map +1 -0
- package/dist/components/LDInput/InputBase.js +17 -0
- package/dist/components/LDInput/LDInput.d.ts +24 -0
- package/dist/components/LDInput/LDInput.d.ts.map +1 -0
- package/dist/components/LDInput/LDInput.js +71 -0
- package/dist/components/LDLoadingDots/LDLoadingDots.d.ts +8 -0
- package/dist/components/LDLoadingDots/LDLoadingDots.d.ts.map +1 -0
- package/dist/components/LDLoadingDots/LDLoadingDots.js +29 -0
- package/dist/components/LDMenuBar/LDMenuBar.d.ts +21 -0
- package/dist/components/LDMenuBar/LDMenuBar.d.ts.map +1 -0
- package/dist/components/LDMenuBar/LDMenuBar.js +33 -0
- package/dist/components/LDMenuBar/MenuBarBase.d.ts +43 -0
- package/dist/components/LDMenuBar/MenuBarBase.d.ts.map +1 -0
- package/dist/components/LDMenuBar/MenuBarBase.js +69 -0
- package/dist/components/LDModal/LDModal.d.ts +51 -0
- package/dist/components/LDModal/LDModal.d.ts.map +1 -0
- package/dist/components/LDModal/LDModal.js +72 -0
- package/dist/components/LDModal/ModalBase.d.ts +42 -0
- package/dist/components/LDModal/ModalBase.d.ts.map +1 -0
- package/dist/components/LDModal/ModalBase.js +30 -0
- package/dist/components/LDModal/openModal.d.ts +24 -0
- package/dist/components/LDModal/openModal.d.ts.map +1 -0
- package/dist/components/LDModal/openModal.js +52 -0
- package/dist/components/LDOTPInput/LDOTPInput.d.ts +46 -0
- package/dist/components/LDOTPInput/LDOTPInput.d.ts.map +1 -0
- package/dist/components/LDOTPInput/LDOTPInput.js +87 -0
- package/dist/components/LDPagination/LDPagination.d.ts +12 -0
- package/dist/components/LDPagination/LDPagination.d.ts.map +1 -0
- package/dist/components/LDPagination/LDPagination.js +5 -0
- package/dist/components/LDPagination/PaginationBase.d.ts +36 -0
- package/dist/components/LDPagination/PaginationBase.d.ts.map +1 -0
- package/dist/components/LDPagination/PaginationBase.js +44 -0
- package/dist/components/LDPagination/paginationUtils.d.ts +2 -0
- package/dist/components/LDPagination/paginationUtils.d.ts.map +1 -0
- package/dist/components/LDPagination/paginationUtils.js +18 -0
- package/dist/components/LDPopover/LDPopover.d.ts +42 -0
- package/dist/components/LDPopover/LDPopover.d.ts.map +1 -0
- package/dist/components/LDPopover/LDPopover.js +31 -0
- package/dist/components/LDPopover/PopoverBase.d.ts +31 -0
- package/dist/components/LDPopover/PopoverBase.d.ts.map +1 -0
- package/dist/components/LDPopover/PopoverBase.js +18 -0
- package/dist/components/LDRadio/FormRadioGroup.d.ts +13 -0
- package/dist/components/LDRadio/FormRadioGroup.d.ts.map +1 -0
- package/dist/components/LDRadio/FormRadioGroup.js +9 -0
- package/dist/components/LDRadio/LDRadio.d.ts +24 -0
- package/dist/components/LDRadio/LDRadio.d.ts.map +1 -0
- package/dist/components/LDRadio/LDRadio.js +39 -0
- package/dist/components/LDRadio/LDRadioGroup.d.ts +22 -0
- package/dist/components/LDRadio/LDRadioGroup.d.ts.map +1 -0
- package/dist/components/LDRadio/LDRadioGroup.js +7 -0
- package/dist/components/LDRadio/RadioBase.d.ts +38 -0
- package/dist/components/LDRadio/RadioBase.d.ts.map +1 -0
- package/dist/components/LDRadio/RadioBase.js +46 -0
- package/dist/components/LDScrollArea/LDScrollArea.d.ts +15 -0
- package/dist/components/LDScrollArea/LDScrollArea.d.ts.map +1 -0
- package/dist/components/LDScrollArea/LDScrollArea.js +10 -0
- package/dist/components/LDSelect/FormMultiSelect.d.ts +13 -0
- package/dist/components/LDSelect/FormMultiSelect.d.ts.map +1 -0
- package/dist/components/LDSelect/FormMultiSelect.js +14 -0
- package/dist/components/LDSelect/FormSelect.d.ts +13 -0
- package/dist/components/LDSelect/FormSelect.d.ts.map +1 -0
- package/dist/components/LDSelect/FormSelect.js +10 -0
- package/dist/components/LDSelect/LDMultiSelect.d.ts +31 -0
- package/dist/components/LDSelect/LDMultiSelect.d.ts.map +1 -0
- package/dist/components/LDSelect/LDMultiSelect.js +59 -0
- package/dist/components/LDSelect/LDSelect.d.ts +41 -0
- package/dist/components/LDSelect/LDSelect.d.ts.map +1 -0
- package/dist/components/LDSelect/LDSelect.js +55 -0
- package/dist/components/LDSelect/SelectBase.d.ts +59 -0
- package/dist/components/LDSelect/SelectBase.d.ts.map +1 -0
- package/dist/components/LDSelect/SelectBase.js +211 -0
- package/dist/components/LDSkeleton/LDSkeleton.d.ts +10 -0
- package/dist/components/LDSkeleton/LDSkeleton.d.ts.map +1 -0
- package/dist/components/LDSkeleton/LDSkeleton.js +8 -0
- package/dist/components/LDSlider/LDSlider.d.ts +23 -0
- package/dist/components/LDSlider/LDSlider.d.ts.map +1 -0
- package/dist/components/LDSlider/LDSlider.js +195 -0
- package/dist/components/LDSpinner/LDSpinner.d.ts +25 -0
- package/dist/components/LDSpinner/LDSpinner.d.ts.map +1 -0
- package/dist/components/LDSpinner/LDSpinner.js +20 -0
- package/dist/components/LDTable/LDTable.d.ts +34 -0
- package/dist/components/LDTable/LDTable.d.ts.map +1 -0
- package/dist/components/LDTable/LDTable.js +29 -0
- package/dist/components/LDTable/LDTanstackTable.d.ts +23 -0
- package/dist/components/LDTable/LDTanstackTable.d.ts.map +1 -0
- package/dist/components/LDTable/LDTanstackTable.js +35 -0
- package/dist/components/LDTable/TableBase.d.ts +37 -0
- package/dist/components/LDTable/TableBase.d.ts.map +1 -0
- package/dist/components/LDTable/TableBase.js +39 -0
- package/dist/components/LDTable/TableField.d.ts +64 -0
- package/dist/components/LDTable/TableField.d.ts.map +1 -0
- package/dist/components/LDTable/TableField.js +87 -0
- package/dist/components/LDTimePicker/FormTimePicker.d.ts +12 -0
- package/dist/components/LDTimePicker/FormTimePicker.d.ts.map +1 -0
- package/dist/components/LDTimePicker/FormTimePicker.js +12 -0
- package/dist/components/LDTimePicker/LDTimePicker.d.ts +27 -0
- package/dist/components/LDTimePicker/LDTimePicker.d.ts.map +1 -0
- package/dist/components/LDTimePicker/LDTimePicker.js +120 -0
- package/dist/components/LDToggleButton/FormToggleButton.d.ts +12 -0
- package/dist/components/LDToggleButton/FormToggleButton.d.ts.map +1 -0
- package/dist/components/LDToggleButton/FormToggleButton.js +9 -0
- package/dist/components/LDToggleButton/LDToggleButton.d.ts +31 -0
- package/dist/components/LDToggleButton/LDToggleButton.d.ts.map +1 -0
- package/dist/components/LDToggleButton/LDToggleButton.js +42 -0
- package/dist/components/LDToggleButton/ToggleButtonBase.d.ts +41 -0
- package/dist/components/LDToggleButton/ToggleButtonBase.d.ts.map +1 -0
- package/dist/components/LDToggleButton/ToggleButtonBase.js +59 -0
- package/dist/components/LDTooltip/LDTooltip.d.ts +18 -0
- package/dist/components/LDTooltip/LDTooltip.d.ts.map +1 -0
- package/dist/components/LDTooltip/LDTooltip.js +13 -0
- package/dist/components/LDTooltip/TooltipBase.d.ts +39 -0
- package/dist/components/LDTooltip/TooltipBase.d.ts.map +1 -0
- package/dist/components/LDTooltip/TooltipBase.js +46 -0
- package/dist/components/LNB/LNBBase.js +2 -2
- package/dist/components/Spinner/Spinner.d.ts +1 -1
- package/dist/components/Spinner/Spinner.d.ts.map +1 -1
- package/dist/components/Spinner/Spinner.js +1 -1
- package/dist/index.css +115 -13
- package/dist/index.d.ts +48 -45
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +81 -75
- package/package.json +1 -1
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import LDTimePicker from './LDTimePicker.js';
|
|
4
|
+
import FormField from '../Form/FormField.js';
|
|
5
|
+
import FormErrorMessage from '../Form/FormErrorMessage.js';
|
|
6
|
+
import cn from '../../utils/cn.js';
|
|
7
|
+
const FormTimePicker = ({ name, options, customErrorMessage = '', isHiddenErrorMessage = false, errorClassName, disabled = false, block = false, ...props }) => {
|
|
8
|
+
return (_jsx(FormField, { name: name, options: options, customErrorMessage: customErrorMessage, disabled: disabled, children: ({ field, fieldState }) => (_jsxs("div", { className: cn('relative border-2 border-transparent', block ? 'w-full' : 'w-auto'), children: [_jsx(LDTimePicker, { ...props, block: block, value: field.value ?? '', onChange: (time) => {
|
|
9
|
+
field.onChange(time);
|
|
10
|
+
}, disabled: disabled, color: fieldState.hasError ? 'danger' : 'neutral' }), !isHiddenErrorMessage && (_jsx(FormErrorMessage, { error: fieldState.error, disabled: disabled, className: errorClassName }))] })) }));
|
|
11
|
+
};
|
|
12
|
+
export default FormTimePicker;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface LDTimePickerProps {
|
|
2
|
+
/** 선택된 시간 (HH:MM 형식) */
|
|
3
|
+
value?: string;
|
|
4
|
+
/** 초기 선택 시간 (uncontrolled) */
|
|
5
|
+
defaultValue?: string;
|
|
6
|
+
/** 시간 변경 시 호출되는 콜백 */
|
|
7
|
+
onChange?: (value: string) => void;
|
|
8
|
+
/** 미선택 시 표시할 텍스트 */
|
|
9
|
+
placeholder?: string;
|
|
10
|
+
/** 비활성화 여부 */
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
/** true 시 너비 100% */
|
|
13
|
+
block?: boolean;
|
|
14
|
+
/** 색상 테마 (danger 시 에러 스타일) */
|
|
15
|
+
color?: 'neutral' | 'danger';
|
|
16
|
+
/** 최소 선택 가능 시간 (HH:MM 형식, 이전 시간 비활성화) */
|
|
17
|
+
minTime?: string;
|
|
18
|
+
/** 추가 CSS 클래스 */
|
|
19
|
+
className?: string;
|
|
20
|
+
/** 인라인 스타일 (트리거 버튼에 적용) */
|
|
21
|
+
style?: React.CSSProperties;
|
|
22
|
+
/** 트리거 버튼 className */
|
|
23
|
+
triggerClassName?: string;
|
|
24
|
+
}
|
|
25
|
+
declare const LDTimePicker: ({ value, defaultValue, onChange, placeholder, disabled, block, color, minTime, className, style, triggerClassName, }: LDTimePickerProps) => import("react/jsx-runtime").JSX.Element;
|
|
26
|
+
export default LDTimePicker;
|
|
27
|
+
//# sourceMappingURL=LDTimePicker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LDTimePicker.d.ts","sourceRoot":"","sources":["../../../src/components/LDTimePicker/LDTimePicker.tsx"],"names":[],"mappings":"AAsCA,MAAM,WAAW,iBAAiB;IAChC,wBAAwB;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8BAA8B;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sBAAsB;IACtB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,oBAAoB;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qBAAqB;IACrB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,8BAA8B;IAC9B,KAAK,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC7B,yCAAyC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iBAAiB;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2BAA2B;IAC3B,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,uBAAuB;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,QAAA,MAAM,YAAY,GAAI,sHAYnB,iBAAiB,4CA4KnB,CAAC;AAEF,eAAe,YAAY,CAAC"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useMemo, useState, useRef } from 'react';
|
|
4
|
+
import PopoverBase from '../LDPopover/PopoverBase.js';
|
|
5
|
+
import LucideIcon from '../Icon/LucideIcon.js';
|
|
6
|
+
import cn from '../../utils/cn.js';
|
|
7
|
+
/** 시간 입력 자동 포맷팅 (1212 -> 12:12) */
|
|
8
|
+
const formatTimeInput = (value) => {
|
|
9
|
+
const numbers = value.replace(/\D/g, '');
|
|
10
|
+
if (!numbers)
|
|
11
|
+
return '';
|
|
12
|
+
const limitedNumbers = numbers.slice(0, 4);
|
|
13
|
+
if (limitedNumbers.length <= 2)
|
|
14
|
+
return limitedNumbers;
|
|
15
|
+
const hours = limitedNumbers.slice(0, 2);
|
|
16
|
+
const minutes = limitedNumbers.slice(2);
|
|
17
|
+
const hoursNum = parseInt(hours, 10);
|
|
18
|
+
if (hoursNum > 23)
|
|
19
|
+
return hours.slice(0, 1);
|
|
20
|
+
if (minutes) {
|
|
21
|
+
const minutesNum = parseInt(minutes, 10);
|
|
22
|
+
if (minutesNum > 59)
|
|
23
|
+
return `${hours}:${minutes.slice(0, 1)}`;
|
|
24
|
+
}
|
|
25
|
+
return `${hours}:${minutes}`;
|
|
26
|
+
};
|
|
27
|
+
// ── 시간 옵션 생성 (00:00 ~ 23:30, 30분 간격) ──
|
|
28
|
+
const generateTimeOptions = (minTime) => {
|
|
29
|
+
const options = [];
|
|
30
|
+
for (let hour = 0; hour < 24; hour++) {
|
|
31
|
+
for (let minute = 0; minute < 60; minute += 30) {
|
|
32
|
+
const timeString = `${String(hour).padStart(2, '0')}:${String(minute).padStart(2, '0')}`;
|
|
33
|
+
if (minTime && timeString < minTime)
|
|
34
|
+
continue;
|
|
35
|
+
options.push(timeString);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return options;
|
|
39
|
+
};
|
|
40
|
+
const LDTimePicker = ({ value, defaultValue, onChange, placeholder = 'HH:MM', disabled = false, block = false, color = 'neutral', minTime, className, style, triggerClassName, }) => {
|
|
41
|
+
const [open, setOpen] = useState(false);
|
|
42
|
+
const [internal, setInternal] = useState(defaultValue);
|
|
43
|
+
const [isEditable, setIsEditable] = useState(false);
|
|
44
|
+
const inputRef = useRef(null);
|
|
45
|
+
const isControlled = value !== undefined;
|
|
46
|
+
const resolved = isControlled ? value : internal;
|
|
47
|
+
const timeOptions = useMemo(() => generateTimeOptions(minTime), [minTime]);
|
|
48
|
+
const handleTimeSelect = (time) => {
|
|
49
|
+
if (!isControlled)
|
|
50
|
+
setInternal(time);
|
|
51
|
+
onChange?.(time);
|
|
52
|
+
setOpen(false);
|
|
53
|
+
};
|
|
54
|
+
const handleInputChange = (e) => {
|
|
55
|
+
const formatted = formatTimeInput(e.target.value);
|
|
56
|
+
if (!isControlled)
|
|
57
|
+
setInternal(formatted);
|
|
58
|
+
onChange?.(formatted);
|
|
59
|
+
};
|
|
60
|
+
const handlePencilClick = (e) => {
|
|
61
|
+
e.stopPropagation();
|
|
62
|
+
e.preventDefault();
|
|
63
|
+
if (isEditable) {
|
|
64
|
+
setIsEditable(false);
|
|
65
|
+
inputRef.current?.blur();
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
setIsEditable(true);
|
|
69
|
+
setTimeout(() => {
|
|
70
|
+
inputRef.current?.focus();
|
|
71
|
+
}, 0);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
const handleInputBlur = (e) => {
|
|
75
|
+
const relatedTarget = e.relatedTarget;
|
|
76
|
+
if (relatedTarget?.closest('[data-pencil-button]'))
|
|
77
|
+
return;
|
|
78
|
+
setIsEditable(false);
|
|
79
|
+
};
|
|
80
|
+
return (_jsx("div", { className: cn(block ? 'w-full' : 'w-auto', className), children: _jsxs(PopoverBase.Root, { open: open, onOpenChange: setOpen, children: [_jsxs(PopoverBase.Trigger, { disabled: disabled, style: style, onClick: (e) => {
|
|
81
|
+
if (isEditable)
|
|
82
|
+
e.preventDefault();
|
|
83
|
+
}, className: cn('border border-neutral10 h-[38px] w-full display14 px-4 rounded-[5px]', 'flex flex-row items-center justify-between gap-4', 'outline-2 outline-transparent ld-transition', disabled && 'cursor-not-allowed opacity-50', color === 'danger'
|
|
84
|
+
? 'bg-tintRed outline-red500'
|
|
85
|
+
: 'focus:bg-tintBlue focus:outline-lb500', triggerClassName), children: [_jsx("input", { ref: inputRef, type: "text", value: resolved ?? '', onChange: handleInputChange, onBlur: handleInputBlur, onKeyDown: (e) => {
|
|
86
|
+
if (e.key === 'ArrowDown') {
|
|
87
|
+
e.preventDefault();
|
|
88
|
+
setOpen(true);
|
|
89
|
+
}
|
|
90
|
+
}, placeholder: placeholder, "aria-label": "\uC2DC\uAC04 \uC785\uB825", disabled: disabled, readOnly: !isEditable, className: cn('flex-1 bg-transparent outline-none min-w-0', !resolved && 'text-neutral40', !isEditable && 'cursor-pointer') }), _jsxs("div", { className: "flex items-center gap-2 shrink-0", children: [_jsx("span", { "data-pencil-button": true, role: "button", tabIndex: 0, "aria-label": "\uC9C1\uC811 \uC785\uB825 \uBAA8\uB4DC \uC804\uD658", onClick: handlePencilClick, onKeyDown: (e) => {
|
|
91
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
92
|
+
e.preventDefault();
|
|
93
|
+
handlePencilClick(e);
|
|
94
|
+
}
|
|
95
|
+
}, className: cn('p-0 transition-colors cursor-pointer', isEditable ? 'text-lb500' : 'text-neutral40'), children: _jsx(LucideIcon, { name: "pencil", size: 15 }) }), _jsx(LucideIcon, { name: "clock", size: 15, className: "text-neutral40" })] })] }), _jsx(PopoverBase.Content, { className: "rounded-md border border-neutral-200 bg-white shadow-md p-0", style: { width: 'var(--radix-popover-trigger-width)' }, onOpenAutoFocus: (e) => {
|
|
96
|
+
e.preventDefault();
|
|
97
|
+
const targetTime = timeOptions.find((t) => t >= (resolved || '00:00')) ||
|
|
98
|
+
timeOptions[0];
|
|
99
|
+
setTimeout(() => {
|
|
100
|
+
const targetButton = document.querySelector(`[data-time-picker-list] button[data-time="${targetTime}"]`);
|
|
101
|
+
if (targetButton) {
|
|
102
|
+
targetButton.focus();
|
|
103
|
+
targetButton.scrollIntoView({ block: 'nearest' });
|
|
104
|
+
}
|
|
105
|
+
}, 0);
|
|
106
|
+
}, children: _jsx("div", { "data-time-picker-list": true, role: "listbox", "aria-label": "\uC2DC\uAC04 \uC120\uD0DD \uBAA9\uB85D", className: "max-h-[240px] overflow-y-auto scrollbar-hide p-2", children: timeOptions.map((time) => (_jsx("button", { "data-time": time, type: "button", role: "option", "aria-selected": resolved === time, "aria-label": `${time.split(':')[0]}시 ${time.split(':')[1]}분`, onClick: () => handleTimeSelect(time), onKeyDown: (e) => {
|
|
107
|
+
const target = e.currentTarget;
|
|
108
|
+
if (e.key === 'ArrowDown') {
|
|
109
|
+
e.preventDefault();
|
|
110
|
+
target.nextElementSibling?.focus();
|
|
111
|
+
}
|
|
112
|
+
else if (e.key === 'ArrowUp') {
|
|
113
|
+
e.preventDefault();
|
|
114
|
+
target.previousElementSibling?.focus();
|
|
115
|
+
}
|
|
116
|
+
}, className: cn('w-full text-left px-3 py-2 rounded-[5px] display14 transition-all cursor-pointer outline-none', 'hover:bg-lb50 hover:text-lb500', 'focus:bg-lb50 focus:text-lb500 focus:ring-1 focus:ring-inset focus:ring-lb500', resolved === time
|
|
117
|
+
? 'bg-neutral10 font-bold'
|
|
118
|
+
: 'text-neutral800'), children: time }, time))) }) })] }) }));
|
|
119
|
+
};
|
|
120
|
+
export default LDTimePicker;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type RegisterOptions } from 'react-hook-form';
|
|
2
|
+
import { type LDToggleButtonProps } from './LDToggleButton.js';
|
|
3
|
+
interface FormToggleButtonProps extends Omit<LDToggleButtonProps, 'checked' | 'name' | 'onCheckedChange'> {
|
|
4
|
+
name: string;
|
|
5
|
+
options?: RegisterOptions;
|
|
6
|
+
customErrorMessage?: string;
|
|
7
|
+
isHiddenErrorMessage?: boolean;
|
|
8
|
+
errorClassName?: string;
|
|
9
|
+
}
|
|
10
|
+
declare const FormToggleButton: ({ name, options, customErrorMessage, isHiddenErrorMessage, errorClassName, disabled, ...props }: FormToggleButtonProps) => import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
export default FormToggleButton;
|
|
12
|
+
//# sourceMappingURL=FormToggleButton.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FormToggleButton.d.ts","sourceRoot":"","sources":["../../../src/components/LDToggleButton/FormToggleButton.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAuB,EAAE,KAAK,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAI5E,UAAU,qBAAsB,SAAQ,IAAI,CAC1C,mBAAmB,EACnB,SAAS,GAAG,MAAM,GAAG,iBAAiB,CACvC;IACC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,QAAA,MAAM,gBAAgB,GAAI,iGAQvB,qBAAqB,4CAgCvB,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import LDToggleButton from './LDToggleButton.js';
|
|
4
|
+
import FormField from '../Form/FormField.js';
|
|
5
|
+
import FormErrorMessage from '../Form/FormErrorMessage.js';
|
|
6
|
+
const FormToggleButton = ({ name, options, customErrorMessage = '', isHiddenErrorMessage = false, errorClassName, disabled = false, ...props }) => {
|
|
7
|
+
return (_jsx(FormField, { name: name, options: options, customErrorMessage: customErrorMessage, disabled: disabled, children: ({ field, fieldState }) => (_jsxs("div", { className: "relative", children: [_jsx(LDToggleButton, { ...props, checked: !!field.value, onCheckedChange: field.onChange, onBlur: field.onBlur, disabled: disabled, ref: field.ref, "aria-invalid": field['aria-invalid'], "aria-describedby": field['aria-describedby'] }), !isHiddenErrorMessage && (_jsx(FormErrorMessage, { id: fieldState.errorId, error: fieldState.error, disabled: disabled, className: errorClassName }))] })) }));
|
|
8
|
+
};
|
|
9
|
+
export default FormToggleButton;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { type Ref } from 'react';
|
|
2
|
+
type ButtonSize = 'small' | 'medium' | 'large' | 'xlarge';
|
|
3
|
+
export interface LDToggleButtonProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size'> {
|
|
4
|
+
/** controlled 체크 상태 */
|
|
5
|
+
checked?: boolean;
|
|
6
|
+
/** 초기 체크 상태 (uncontrolled) */
|
|
7
|
+
defaultChecked?: boolean;
|
|
8
|
+
/** 체크 상태 변경 콜백 */
|
|
9
|
+
onCheckedChange?: (checked: boolean) => void;
|
|
10
|
+
/** 비활성화 여부 */
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
/** 크기 */
|
|
13
|
+
size?: ButtonSize;
|
|
14
|
+
/** input name */
|
|
15
|
+
name?: string;
|
|
16
|
+
/** input value */
|
|
17
|
+
value?: string;
|
|
18
|
+
/** input id */
|
|
19
|
+
id?: string;
|
|
20
|
+
/** 토글 옆에 표시할 라벨 텍스트 */
|
|
21
|
+
label?: string;
|
|
22
|
+
/** 추가 CSS 클래스 */
|
|
23
|
+
className?: string;
|
|
24
|
+
/** 인라인 스타일 */
|
|
25
|
+
style?: React.CSSProperties;
|
|
26
|
+
/** input 요소 ref */
|
|
27
|
+
ref?: Ref<HTMLInputElement>;
|
|
28
|
+
}
|
|
29
|
+
declare const LDToggleButton: ({ checked, defaultChecked, onCheckedChange, disabled, size, label, className, style, ref, name, id, value, ...props }: LDToggleButtonProps) => import("react/jsx-runtime").JSX.Element;
|
|
30
|
+
export default LDToggleButton;
|
|
31
|
+
//# sourceMappingURL=LDToggleButton.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LDToggleButton.d.ts","sourceRoot":"","sources":["../../../src/components/LDToggleButton/LDToggleButton.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,OAAO,CAAC;AAKjC,KAAK,UAAU,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;AAsC1D,MAAM,WAAW,mBAAoB,SAAQ,IAAI,CAC/C,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,EAC3C,MAAM,CACP;IACC,uBAAuB;IACvB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,8BAA8B;IAC9B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,kBAAkB;IAClB,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7C,cAAc;IACd,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS;IACT,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,iBAAiB;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kBAAkB;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,eAAe;IACf,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,uBAAuB;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc;IACd,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,mBAAmB;IACnB,GAAG,CAAC,EAAE,GAAG,CAAC,gBAAgB,CAAC,CAAC;CAC7B;AAmDD,QAAA,MAAM,cAAc,GAAI,uHAcrB,mBAAmB,4CAqBrB,CAAC;AAEF,eAAe,cAAc,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import ToggleButtonBase, { useToggleButtonContext } from './ToggleButtonBase.js';
|
|
3
|
+
import cn from '../../utils/cn.js';
|
|
4
|
+
const trackClass = {
|
|
5
|
+
small: 'toggle-track-sm',
|
|
6
|
+
medium: 'toggle-track-md',
|
|
7
|
+
large: 'toggle-track-lg',
|
|
8
|
+
xlarge: 'toggle-track-xl',
|
|
9
|
+
};
|
|
10
|
+
const thumbClass = {
|
|
11
|
+
small: 'toggle-thumb-sm',
|
|
12
|
+
medium: 'toggle-thumb-md',
|
|
13
|
+
large: 'toggle-thumb-lg',
|
|
14
|
+
xlarge: 'toggle-thumb-xl',
|
|
15
|
+
};
|
|
16
|
+
const thumbOffClass = {
|
|
17
|
+
small: 'toggle-thumb-off-sm',
|
|
18
|
+
medium: 'toggle-thumb-off-md',
|
|
19
|
+
large: 'toggle-thumb-off-lg',
|
|
20
|
+
xlarge: 'toggle-thumb-off-xl',
|
|
21
|
+
};
|
|
22
|
+
const thumbOnClass = {
|
|
23
|
+
small: 'toggle-thumb-on-sm',
|
|
24
|
+
medium: 'toggle-thumb-on-md',
|
|
25
|
+
large: 'toggle-thumb-on-lg',
|
|
26
|
+
xlarge: 'toggle-thumb-on-xl',
|
|
27
|
+
};
|
|
28
|
+
const rootClass = {
|
|
29
|
+
small: 'toggle-sm',
|
|
30
|
+
medium: 'toggle-md',
|
|
31
|
+
large: 'toggle-lg',
|
|
32
|
+
xlarge: 'toggle-xl',
|
|
33
|
+
};
|
|
34
|
+
// ── Inner: Context에서 checked/disabled 읽어 스타일 적용 ──
|
|
35
|
+
const ToggleInner = ({ label, ref, name, id, value, size, ...props }) => {
|
|
36
|
+
const { checked, disabled } = useToggleButtonContext();
|
|
37
|
+
return (_jsxs(_Fragment, { children: [_jsx(ToggleButtonBase.HiddenInput, { ref: ref, name: name, id: id, value: value, ...props }), _jsx(ToggleButtonBase.Track, { className: cn(trackClass[size], checked ? 'bg-lb500' : 'bg-mono300', disabled ? 'opacity-50' : 'cursor-pointer', 'peer-focus-visible:ring-2 peer-focus-visible:ring-lb500 peer-focus-visible:ring-offset-2'), children: _jsx(ToggleButtonBase.Thumb, { className: cn(thumbClass[size], 'bg-white ld-transition', checked ? thumbOnClass[size] : thumbOffClass[size]) }) }), label && (_jsx(ToggleButtonBase.Label, { className: "select-none", children: label }))] }));
|
|
38
|
+
};
|
|
39
|
+
const LDToggleButton = ({ checked, defaultChecked, onCheckedChange, disabled = false, size = 'medium', label, className, style, ref, name, id, value, ...props }) => {
|
|
40
|
+
return (_jsx(ToggleButtonBase.Root, { checked: checked, defaultChecked: defaultChecked, onCheckedChange: onCheckedChange, disabled: disabled, style: style, className: cn(rootClass[size], className), children: _jsx(ToggleInner, { label: label, ref: ref, name: name, value: value, id: id, size: size, ...props }) }));
|
|
41
|
+
};
|
|
42
|
+
export default LDToggleButton;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type ReactNode, type Ref } from 'react';
|
|
2
|
+
interface ToggleButtonContextType {
|
|
3
|
+
checked: boolean;
|
|
4
|
+
onCheckedChange: (checked: boolean) => void;
|
|
5
|
+
disabled: boolean;
|
|
6
|
+
isFocused: boolean;
|
|
7
|
+
setIsFocused: (focused: boolean) => void;
|
|
8
|
+
}
|
|
9
|
+
export declare const useToggleButtonContext: () => ToggleButtonContextType;
|
|
10
|
+
interface RootProps {
|
|
11
|
+
checked?: boolean;
|
|
12
|
+
defaultChecked?: boolean;
|
|
13
|
+
onCheckedChange?: (checked: boolean) => void;
|
|
14
|
+
disabled?: boolean;
|
|
15
|
+
className?: string;
|
|
16
|
+
style?: React.CSSProperties;
|
|
17
|
+
children?: ReactNode;
|
|
18
|
+
}
|
|
19
|
+
interface HiddenInputProps extends React.InputHTMLAttributes<HTMLInputElement> {
|
|
20
|
+
ref?: Ref<HTMLInputElement>;
|
|
21
|
+
}
|
|
22
|
+
interface TrackProps {
|
|
23
|
+
className?: string;
|
|
24
|
+
children?: ReactNode;
|
|
25
|
+
}
|
|
26
|
+
interface ThumbProps {
|
|
27
|
+
className?: string;
|
|
28
|
+
}
|
|
29
|
+
interface LabelProps {
|
|
30
|
+
className?: string;
|
|
31
|
+
children?: ReactNode;
|
|
32
|
+
}
|
|
33
|
+
export declare const ToggleButtonBase: {
|
|
34
|
+
Root: ({ checked, defaultChecked, onCheckedChange, disabled, className, style, children, }: RootProps) => import("react/jsx-runtime").JSX.Element;
|
|
35
|
+
HiddenInput: ({ ref, onFocus, onBlur, onChange, ...props }: HiddenInputProps) => import("react/jsx-runtime").JSX.Element;
|
|
36
|
+
Track: ({ className, children }: TrackProps) => import("react/jsx-runtime").JSX.Element;
|
|
37
|
+
Thumb: ({ className }: ThumbProps) => import("react/jsx-runtime").JSX.Element;
|
|
38
|
+
Label: ({ className, children }: LabelProps) => import("react/jsx-runtime").JSX.Element;
|
|
39
|
+
};
|
|
40
|
+
export default ToggleButtonBase;
|
|
41
|
+
//# sourceMappingURL=ToggleButtonBase.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ToggleButtonBase.d.ts","sourceRoot":"","sources":["../../../src/components/LDToggleButton/ToggleButtonBase.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,SAAS,EACd,KAAK,GAAG,EAIT,MAAM,OAAO,CAAC;AAIf,UAAU,uBAAuB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,eAAe,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5C,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CAC1C;AAID,eAAO,MAAM,sBAAsB,+BAOlC,CAAC;AAGF,UAAU,SAAS;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAC5B,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AA+CD,UAAU,gBAAiB,SAAQ,KAAK,CAAC,mBAAmB,CAAC,gBAAgB,CAAC;IAC5E,GAAG,CAAC,EAAE,GAAG,CAAC,gBAAgB,CAAC,CAAC;CAC7B;AAuCD,UAAU,UAAU;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAgBD,UAAU,UAAU;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAcD,UAAU,UAAU;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAMD,eAAO,MAAM,gBAAgB;gGA1H1B,SAAS;gEA+CT,gBAAgB;qCAoCqB,UAAU;2BAkBpB,UAAU;qCAiBA,UAAU;CAUjD,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { createContext, useContext, useState, } from 'react';
|
|
3
|
+
import cn from '../../utils/cn.js';
|
|
4
|
+
const ToggleButtonContext = createContext(null);
|
|
5
|
+
export const useToggleButtonContext = () => {
|
|
6
|
+
const ctx = useContext(ToggleButtonContext);
|
|
7
|
+
if (!ctx)
|
|
8
|
+
throw new Error('ToggleButtonBase 하위 컴포넌트는 Root 내부에서 사용해야 합니다.');
|
|
9
|
+
return ctx;
|
|
10
|
+
};
|
|
11
|
+
const Root = ({ checked, defaultChecked = false, onCheckedChange, disabled = false, className, style, children, }) => {
|
|
12
|
+
const [internal, setInternal] = useState(defaultChecked);
|
|
13
|
+
const [isFocused, setIsFocused] = useState(false);
|
|
14
|
+
const isControlled = checked !== undefined;
|
|
15
|
+
const resolved = isControlled ? checked : internal;
|
|
16
|
+
const handleChange = (val) => {
|
|
17
|
+
if (!isControlled)
|
|
18
|
+
setInternal(val);
|
|
19
|
+
onCheckedChange?.(val);
|
|
20
|
+
};
|
|
21
|
+
return (_jsx(ToggleButtonContext, { value: {
|
|
22
|
+
checked: resolved,
|
|
23
|
+
onCheckedChange: handleChange,
|
|
24
|
+
disabled,
|
|
25
|
+
isFocused,
|
|
26
|
+
setIsFocused,
|
|
27
|
+
}, children: _jsx("label", { style: style, onClick: (e) => e.stopPropagation(), className: cn('flex items-center gap-sm', disabled ? 'cursor-not-allowed' : 'cursor-pointer', className), children: children }) }));
|
|
28
|
+
};
|
|
29
|
+
const HiddenInput = ({ ref, onFocus, onBlur, onChange, ...props }) => {
|
|
30
|
+
const { checked, onCheckedChange, disabled, setIsFocused } = useToggleButtonContext();
|
|
31
|
+
return (_jsx("input", { type: "checkbox", role: "switch", "aria-checked": checked, ref: ref, className: "sr-only peer", checked: checked, disabled: disabled, onChange: (e) => {
|
|
32
|
+
e.stopPropagation();
|
|
33
|
+
onCheckedChange(e.target.checked);
|
|
34
|
+
onChange?.(e);
|
|
35
|
+
}, onFocus: (e) => {
|
|
36
|
+
setIsFocused(true);
|
|
37
|
+
onFocus?.(e);
|
|
38
|
+
}, onBlur: (e) => {
|
|
39
|
+
setIsFocused(false);
|
|
40
|
+
onBlur?.(e);
|
|
41
|
+
}, ...props }));
|
|
42
|
+
};
|
|
43
|
+
const Track = ({ className, children }) => {
|
|
44
|
+
return (_jsx("span", { className: cn('relative flex items-center rounded-full shrink-0', className), children: children }));
|
|
45
|
+
};
|
|
46
|
+
const Thumb = ({ className }) => {
|
|
47
|
+
return (_jsx("span", { className: cn('absolute rounded-full top-1/2 -translate-y-1/2', className) }));
|
|
48
|
+
};
|
|
49
|
+
const Label = ({ className, children }) => {
|
|
50
|
+
return _jsx("span", { className: className, children: children });
|
|
51
|
+
};
|
|
52
|
+
export const ToggleButtonBase = {
|
|
53
|
+
Root,
|
|
54
|
+
HiddenInput,
|
|
55
|
+
Track,
|
|
56
|
+
Thumb,
|
|
57
|
+
Label,
|
|
58
|
+
};
|
|
59
|
+
export default ToggleButtonBase;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface LDTooltipProps {
|
|
3
|
+
/** 툴팁이 표시될 트리거 요소 */
|
|
4
|
+
children: React.ReactElement;
|
|
5
|
+
/** 툴팁 내용 (생략 시 children 텍스트가 잘릴 때만 자동 표시) */
|
|
6
|
+
content?: React.ReactNode;
|
|
7
|
+
/** 툴팁 표시 위치 */
|
|
8
|
+
side?: 'top' | 'right' | 'bottom' | 'left';
|
|
9
|
+
/** 툴팁 정렬 */
|
|
10
|
+
align?: 'start' | 'center' | 'end';
|
|
11
|
+
/** 추가 CSS 클래스 */
|
|
12
|
+
className?: string;
|
|
13
|
+
/** 인라인 스타일 */
|
|
14
|
+
style?: React.CSSProperties;
|
|
15
|
+
}
|
|
16
|
+
declare const LDTooltip: ({ children, content, side, align, className, style, }: LDTooltipProps) => import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
export default LDTooltip;
|
|
18
|
+
//# sourceMappingURL=LDTooltip.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LDTooltip.d.ts","sourceRoot":"","sources":["../../../src/components/LDTooltip/LDTooltip.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,MAAM,WAAW,cAAc;IAC7B,qBAAqB;IACrB,QAAQ,EAAE,KAAK,CAAC,YAAY,CAAC;IAC7B,6CAA6C;IAC7C,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,eAAe;IACf,IAAI,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC3C,YAAY;IACZ,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;IACnC,iBAAiB;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc;IACd,KAAK,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;CAC7B;AAED,QAAA,MAAM,SAAS,GAAI,uDAOhB,cAAc,4CA8BhB,CAAC;AAEF,eAAe,SAAS,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import TooltipBase from './TooltipBase.js';
|
|
4
|
+
import cn from '../../utils/cn.js';
|
|
5
|
+
const LDTooltip = ({ children, content, side = 'top', align = 'center', className, style, }) => {
|
|
6
|
+
const { ref: textRef, isTruncated } = TooltipBase.useTruncation([children]);
|
|
7
|
+
const tooltipContent = content ?? textRef.current?.textContent ?? '';
|
|
8
|
+
const shouldShow = content ? true : isTruncated;
|
|
9
|
+
return (_jsx(TooltipBase.Provider, { children: _jsxs(TooltipBase.Root, { children: [_jsx(TooltipBase.Trigger, { asChild: true, children: _jsx("div", { className: cn('relative w-full', className), style: style, children: React.cloneElement(children, {
|
|
10
|
+
ref: textRef,
|
|
11
|
+
}) }) }), shouldShow && (_jsxs(TooltipBase.Content, { side: side, align: align, className: "px-2 py-1 text-xs text-white whitespace-nowrap bg-gray-900 rounded", children: [tooltipContent, _jsx(TooltipBase.Arrow, { className: "fill-gray-900" })] }))] }) }));
|
|
12
|
+
};
|
|
13
|
+
export default LDTooltip;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
interface ProviderProps {
|
|
3
|
+
delayDuration?: number;
|
|
4
|
+
children?: ReactNode;
|
|
5
|
+
}
|
|
6
|
+
interface RootProps {
|
|
7
|
+
open?: boolean;
|
|
8
|
+
defaultOpen?: boolean;
|
|
9
|
+
onOpenChange?: (open: boolean) => void;
|
|
10
|
+
children?: ReactNode;
|
|
11
|
+
}
|
|
12
|
+
interface TriggerProps {
|
|
13
|
+
asChild?: boolean;
|
|
14
|
+
className?: string;
|
|
15
|
+
children?: ReactNode;
|
|
16
|
+
}
|
|
17
|
+
interface ContentProps {
|
|
18
|
+
side?: 'top' | 'right' | 'bottom' | 'left';
|
|
19
|
+
sideOffset?: number;
|
|
20
|
+
align?: 'start' | 'center' | 'end';
|
|
21
|
+
className?: string;
|
|
22
|
+
children?: ReactNode;
|
|
23
|
+
}
|
|
24
|
+
interface ArrowProps {
|
|
25
|
+
className?: string;
|
|
26
|
+
}
|
|
27
|
+
export declare const TooltipBase: {
|
|
28
|
+
Provider: ({ delayDuration, children }: ProviderProps) => import("react/jsx-runtime").JSX.Element;
|
|
29
|
+
Root: ({ open, defaultOpen, onOpenChange, children }: RootProps) => import("react/jsx-runtime").JSX.Element;
|
|
30
|
+
Trigger: ({ asChild, className, children }: TriggerProps) => import("react/jsx-runtime").JSX.Element;
|
|
31
|
+
Content: ({ side, sideOffset, align, className, children, }: ContentProps) => import("react/jsx-runtime").JSX.Element;
|
|
32
|
+
Arrow: ({ className }: ArrowProps) => import("react/jsx-runtime").JSX.Element;
|
|
33
|
+
useTruncation: (deps?: React.DependencyList) => {
|
|
34
|
+
ref: import("react").RefObject<HTMLElement | null>;
|
|
35
|
+
isTruncated: boolean;
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
export default TooltipBase;
|
|
39
|
+
//# sourceMappingURL=TooltipBase.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TooltipBase.d.ts","sourceRoot":"","sources":["../../../src/components/LDTooltip/TooltipBase.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAA+B,MAAM,OAAO,CAAC;AA2BpE,UAAU,aAAa;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAWD,UAAU,SAAS;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACvC,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAeD,UAAU,YAAY;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAWD,UAAU,YAAY;IACpB,IAAI,CAAC,EAAE,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AA4BD,UAAU,UAAU;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAMD,eAAO,MAAM,WAAW;4CAtF6B,aAAa;0DAgBL,SAAS;gDAmBnB,YAAY;iEAuB5D,YAAY;2BAwBe,UAAU;2BA7GX,KAAK,CAAC,cAAc;;;;CAwHhD,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useRef, useEffect, useState } from 'react';
|
|
3
|
+
import * as RadixTooltip from '@radix-ui/react-tooltip';
|
|
4
|
+
import cn from '../../utils/cn.js';
|
|
5
|
+
// ── 말줄임 감지 Hook ──
|
|
6
|
+
const useTruncation = (deps = []) => {
|
|
7
|
+
const ref = useRef(null);
|
|
8
|
+
const [isTruncated, setIsTruncated] = useState(false);
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
const element = ref.current;
|
|
11
|
+
if (!element)
|
|
12
|
+
return;
|
|
13
|
+
const checkTruncation = () => {
|
|
14
|
+
setIsTruncated(element.scrollWidth > element.clientWidth);
|
|
15
|
+
};
|
|
16
|
+
checkTruncation();
|
|
17
|
+
window.addEventListener('resize', checkTruncation);
|
|
18
|
+
return () => window.removeEventListener('resize', checkTruncation);
|
|
19
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
20
|
+
}, deps);
|
|
21
|
+
return { ref, isTruncated };
|
|
22
|
+
};
|
|
23
|
+
const Provider = ({ delayDuration = 200, children }) => {
|
|
24
|
+
return (_jsx(RadixTooltip.Provider, { delayDuration: delayDuration, children: children }));
|
|
25
|
+
};
|
|
26
|
+
const Root = ({ open, defaultOpen, onOpenChange, children }) => {
|
|
27
|
+
return (_jsx(RadixTooltip.Root, { open: open, defaultOpen: defaultOpen, onOpenChange: onOpenChange, children: children }));
|
|
28
|
+
};
|
|
29
|
+
const Trigger = ({ asChild, className, children }) => {
|
|
30
|
+
return (_jsx(RadixTooltip.Trigger, { asChild: asChild, className: className, children: children }));
|
|
31
|
+
};
|
|
32
|
+
const Content = ({ side = 'top', sideOffset = 8, align = 'center', className, children, }) => {
|
|
33
|
+
return (_jsx(RadixTooltip.Portal, { children: _jsx(RadixTooltip.Content, { side: side, sideOffset: sideOffset, align: align, className: cn('z-50 outline-hidden', 'animate-in fade-in-0 data-[state=closed]:animate-out data-[state=closed]:fade-out-0', className), children: children }) }));
|
|
34
|
+
};
|
|
35
|
+
const Arrow = ({ className }) => {
|
|
36
|
+
return _jsx(RadixTooltip.Arrow, { className: className });
|
|
37
|
+
};
|
|
38
|
+
export const TooltipBase = {
|
|
39
|
+
Provider,
|
|
40
|
+
Root,
|
|
41
|
+
Trigger,
|
|
42
|
+
Content,
|
|
43
|
+
Arrow,
|
|
44
|
+
useTruncation,
|
|
45
|
+
};
|
|
46
|
+
export default TooltipBase;
|
|
@@ -4,7 +4,7 @@ import { createContext, useContext, useEffect, useState } from 'react';
|
|
|
4
4
|
import { ChevronDown, PanelLeftClose, PanelLeftOpen, LogOut, } from 'lucide-react';
|
|
5
5
|
import cn from '../../utils/cn.js';
|
|
6
6
|
import { isActivePath } from '../../utils/utils.js';
|
|
7
|
-
import
|
|
7
|
+
import LDAvatar from '../LDAvatar/LDAvatar.js';
|
|
8
8
|
const LNBContext = createContext(null);
|
|
9
9
|
const useLNBContext = () => {
|
|
10
10
|
const ctx = useContext(LNBContext);
|
|
@@ -58,7 +58,7 @@ const Header = ({ name, email, profileImage, handleLogout }) => {
|
|
|
58
58
|
const { collapsed } = useLNBContext();
|
|
59
59
|
return (_jsxs("div", { className: cn('w-full flex gap-sm items-center rounded-[10px] ld-transition overflow-hidden', collapsed
|
|
60
60
|
? 'p-xs justify-center border-transparent'
|
|
61
|
-
: 'p-md mobile:p-sm border border-neutral100'), children: [_jsx(
|
|
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 }))] }))] }));
|
|
62
62
|
};
|
|
63
63
|
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
64
|
const Group = ({ children, label, noSlider }) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Spinner.d.ts","sourceRoot":"","sources":["../../../src/components/Spinner/Spinner.tsx"],"names":[],"mappings":"AAGA,MAAM,MAAM,WAAW,GACnB,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,OAAO,GACP,KAAK,GACL,QAAQ,CAAC;AAWb,MAAM,WAAW,YAAY;IAC3B;;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,
|
|
1
|
+
{"version":3,"file":"Spinner.d.ts","sourceRoot":"","sources":["../../../src/components/Spinner/Spinner.tsx"],"names":[],"mappings":"AAGA,MAAM,MAAM,WAAW,GACnB,QAAQ,GACR,OAAO,GACP,QAAQ,GACR,OAAO,GACP,KAAK,GACL,QAAQ,CAAC;AAWb,MAAM,WAAW,YAAY;IAC3B;;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,OAAO,GAAI,sCAKd,YAAY,4CAYd,CAAC;AAEF,eAAe,OAAO,CAAC"}
|
|
@@ -13,7 +13,7 @@ const sizeMap = {
|
|
|
13
13
|
* 디자인 시스템 표준을 따르는 Spinner 컴포넌트입니다.
|
|
14
14
|
*/
|
|
15
15
|
const Spinner = ({ size = 'large', className, variant = 'default', label = 'loading', }) => {
|
|
16
|
-
const Icon = variant === '
|
|
16
|
+
const Icon = variant === 'default' ? LoaderCircleIcon : LoaderIcon;
|
|
17
17
|
const pixelSize = typeof size === 'number' ? size : sizeMap[size];
|
|
18
18
|
return (_jsx(Icon, { size: pixelSize, className: cn('animate-spin text-muted-foreground', className), role: "status", "aria-label": label }));
|
|
19
19
|
};
|