@musecat/uikit 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +9 -0
- package/README.md +51 -0
- package/index.ts +78 -0
- package/package.json +103 -0
- package/packages/Components/Box/Box.tsx +173 -0
- package/packages/Components/Box/Box.types.ts +48 -0
- package/packages/Components/Button/Button.tsx +275 -0
- package/packages/Components/Button/Button.types.ts +44 -0
- package/packages/Components/Card/Card.default.tsx +180 -0
- package/packages/Components/Card/Card.foldable.tsx +383 -0
- package/packages/Components/Card/Card.module.scss +23 -0
- package/packages/Components/Card/Card.tsx +8 -0
- package/packages/Components/Card/Card.types.ts +91 -0
- package/packages/Components/Card/Card.utils.ts +66 -0
- package/packages/Components/Checkbox/Checkbox.module.scss +11 -0
- package/packages/Components/Checkbox/Checkbox.tsx +104 -0
- package/packages/Components/Checkbox/Checkbox.types.ts +24 -0
- package/packages/Components/CodeBox/CodeBox.copy.tsx +43 -0
- package/packages/Components/CodeBox/CodeBox.module.scss +72 -0
- package/packages/Components/CodeBox/CodeBox.tsx +91 -0
- package/packages/Components/CodeBox/CodeBox.types.ts +17 -0
- package/packages/Components/ContextMenu/ContextMenu.module.scss +8 -0
- package/packages/Components/ContextMenu/ContextMenu.options.tsx +126 -0
- package/packages/Components/ContextMenu/ContextMenu.tsx +381 -0
- package/packages/Components/ContextMenu/ContextMenu.types.ts +46 -0
- package/packages/Components/ContributionGraph/ContributionGraph.module.scss +42 -0
- package/packages/Components/ContributionGraph/ContributionGraph.tsx +454 -0
- package/packages/Components/ContributionGraph/ContributionGraph.types.ts +27 -0
- package/packages/Components/DatePicker/DatePicker.calendar.tsx +161 -0
- package/packages/Components/DatePicker/DatePicker.core.tsx +582 -0
- package/packages/Components/DatePicker/DatePicker.module.scss +26 -0
- package/packages/Components/DatePicker/DatePicker.tsx +786 -0
- package/packages/Components/DatePicker/DatePicker.types.ts +36 -0
- package/packages/Components/DatePicker/DatePicker.utils.ts +80 -0
- package/packages/Components/DatePicker/hooks/useCalendar.ts +61 -0
- package/packages/Components/DatePicker/hooks/useSelection.ts +208 -0
- package/packages/Components/Divider/Divider.tsx +46 -0
- package/packages/Components/Divider/Divider.types.ts +12 -0
- package/packages/Components/Header/Header.module.scss +74 -0
- package/packages/Components/Header/Header.tsx +47 -0
- package/packages/Components/Header/Header.types.ts +8 -0
- package/packages/Components/Icon/Icon.group.tsx +122 -0
- package/packages/Components/Icon/Icon.group.types.ts +20 -0
- package/packages/Components/Icon/Icon.tsx +341 -0
- package/packages/Components/Icon/Icon.types.ts +59 -0
- package/packages/Components/Icon/SVG/data.tsx +232 -0
- package/packages/Components/Input/Input.module.scss +5 -0
- package/packages/Components/Input/Input.tsx +87 -0
- package/packages/Components/Input/Input.types.ts +14 -0
- package/packages/Components/Label/Label.module.scss +19 -0
- package/packages/Components/Label/Label.tsx +115 -0
- package/packages/Components/Label/Label.types.ts +28 -0
- package/packages/Components/Layout/Layout.docs.module.scss +42 -0
- package/packages/Components/Layout/Layout.docs.tsx +150 -0
- package/packages/Components/Layout/Layout.docs.types.ts +18 -0
- package/packages/Components/Layout/Layout.module.scss +91 -0
- package/packages/Components/Layout/Layout.tsx +306 -0
- package/packages/Components/Layout/Layout.types.ts +71 -0
- package/packages/Components/Maps/OSM/MapOSM.module.scss +11 -0
- package/packages/Components/Maps/OSM/MapOSM.shared.ts +121 -0
- package/packages/Components/Maps/OSM/MapOSM.tsx +279 -0
- package/packages/Components/Maps/OSM/MapOSM.types.ts +18 -0
- package/packages/Components/Nav/Nav.module.scss +137 -0
- package/packages/Components/Nav/Nav.tsx +304 -0
- package/packages/Components/Nav/Nav.types.ts +32 -0
- package/packages/Components/Nav/hooks/useNavDrag.ts +374 -0
- package/packages/Components/Nav/hooks/useNavIndicator.ts +137 -0
- package/packages/Components/Pagination/Pagination.tsx +254 -0
- package/packages/Components/Pagination/Pagination.types.ts +18 -0
- package/packages/Components/Pill/Pill.tsx +127 -0
- package/packages/Components/Pill/Pill.types.ts +33 -0
- package/packages/Components/Profile/Profile.shared.ts +74 -0
- package/packages/Components/Profile/Profile.tsx +382 -0
- package/packages/Components/Profile/Profile.types.ts +55 -0
- package/packages/Components/Progress/Progress.module.scss +15 -0
- package/packages/Components/Progress/Progress.tsx +88 -0
- package/packages/Components/Progress/Progress.types.ts +22 -0
- package/packages/Components/Radio/Radio.module.scss +11 -0
- package/packages/Components/Radio/Radio.tsx +121 -0
- package/packages/Components/Radio/Radio.types.ts +20 -0
- package/packages/Components/Select/Select.keyboard.tsx +76 -0
- package/packages/Components/Select/Select.trigger.tsx +88 -0
- package/packages/Components/Select/Select.tsx +11 -0
- package/packages/Components/Select/Select.types.ts +38 -0
- package/packages/Components/Select/Select.utils.ts +84 -0
- package/packages/Components/Select/hooks/useSelectNavigation.ts +461 -0
- package/packages/Components/Select/hooks/useSelectSelection.ts +142 -0
- package/packages/Components/Select/hooks/useSelectState.ts +314 -0
- package/packages/Components/Select/select.control.tsx +228 -0
- package/packages/Components/Select/select.inner.tsx +312 -0
- package/packages/Components/Skeleton/Skeleton.tsx +30 -0
- package/packages/Components/Skeleton/Skeleton.types.ts +12 -0
- package/packages/Components/Spinner/Spinner.module.scss +78 -0
- package/packages/Components/Spinner/Spinner.tsx +125 -0
- package/packages/Components/Spinner/Spinner.types.ts +19 -0
- package/packages/Components/Text/Text.module.scss +7 -0
- package/packages/Components/Text/Text.tsx +49 -0
- package/packages/Components/Text/Text.types.ts +33 -0
- package/packages/Components/TimePicker/TimePicker.core.tsx +448 -0
- package/packages/Components/TimePicker/TimePicker.module.scss +30 -0
- package/packages/Components/TimePicker/TimePicker.tsx +511 -0
- package/packages/Components/TimePicker/TimePicker.types.ts +22 -0
- package/packages/Components/Timeline/Timeline.tsx +111 -0
- package/packages/Components/Timeline/Timeline.types.ts +23 -0
- package/packages/Components/Title/Title.tsx +305 -0
- package/packages/Components/Title/Title.types.ts +64 -0
- package/packages/Components/Toggle/Toggle.module.scss +32 -0
- package/packages/Components/Toggle/Toggle.tsx +272 -0
- package/packages/Components/Toggle/Toggle.types.ts +17 -0
- package/packages/Components/Tooltip/Tooltip.module.scss +44 -0
- package/packages/Components/Tooltip/Tooltip.tsx +340 -0
- package/packages/Components/Tooltip/Tooltip.types.ts +38 -0
- package/packages/Frameworks/Dialog/Dialog.background.tsx +88 -0
- package/packages/Frameworks/Dialog/Dialog.boot.tsx +32 -0
- package/packages/Frameworks/Dialog/Dialog.store.ts +199 -0
- package/packages/Frameworks/Dialog/Dialog.tsx +185 -0
- package/packages/Frameworks/Dialog/Dialog.types.ts +264 -0
- package/packages/Frameworks/Dialog/Dialog.utils.ts +22 -0
- package/packages/Frameworks/Dialog/contents/Dialog.footer.tsx +79 -0
- package/packages/Frameworks/Dialog/contents/Dialog.funnel.tsx +260 -0
- package/packages/Frameworks/Dialog/contents/Dialog.header.tsx +137 -0
- package/packages/Frameworks/Dialog/hooks/useDialogPosition.ts +298 -0
- package/packages/Frameworks/Dialog/hooks/useSheetDrag.ts +325 -0
- package/packages/Frameworks/Dialog/hooks/useSheetGeometry.ts +201 -0
- package/packages/Frameworks/Dialog/hooks/useSheetProgressive.ts +98 -0
- package/packages/Frameworks/Dialog/renderers/renderModal.tsx +228 -0
- package/packages/Frameworks/Dialog/renderers/renderPopover.tsx +220 -0
- package/packages/Frameworks/Dialog/renderers/renderSheet.tsx +571 -0
- package/packages/Frameworks/EdgeEffect/EdgeEffect.tsx +52 -0
- package/packages/Frameworks/EdgeEffect/EdgeEffect.types.ts +5 -0
- package/packages/Frameworks/Motion/Motion.presets.ts +49 -0
- package/packages/Frameworks/Pressable/Pressable.module.scss +19 -0
- package/packages/Frameworks/Pressable/Pressable.tsx +651 -0
- package/packages/Frameworks/Pressable/Pressable.types.ts +73 -0
- package/packages/Frameworks/Squircle/Squircle.tsx +263 -0
- package/packages/Frameworks/Squircle/Squircle.types.ts +15 -0
- package/packages/Frameworks/Theme/Radius.types.ts +55 -0
- package/packages/Frameworks/Theme/Theme.types.ts +325 -0
- package/packages/Frameworks/Toaster/Toaster.boot.tsx +47 -0
- package/packages/Frameworks/Toaster/Toaster.module.scss +168 -0
- package/packages/Frameworks/Toaster/Toaster.types.ts +13 -0
- package/packages/Frameworks/View/DNDView/DNDView.module.scss +8 -0
- package/packages/Frameworks/View/DNDView/DNDView.tsx +470 -0
- package/packages/Frameworks/View/DNDView/DNDView.types.ts +61 -0
- package/packages/Frameworks/View/HScrollView/HScrollView.module.scss +59 -0
- package/packages/Frameworks/View/HScrollView/HScrollView.tsx +386 -0
- package/packages/Frameworks/View/HScrollView/HScrollView.types.ts +46 -0
- package/packages/Frameworks/View/ImageView/Dialog/ImageDialog.counter.tsx +27 -0
- package/packages/Frameworks/View/ImageView/Dialog/ImageDialog.footer.tsx +76 -0
- package/packages/Frameworks/View/ImageView/Dialog/ImageDialog.header.tsx +49 -0
- package/packages/Frameworks/View/ImageView/Dialog/ImageDialog.list.tsx +74 -0
- package/packages/Frameworks/View/ImageView/Dialog/ImageDialog.slide.tsx +71 -0
- package/packages/Frameworks/View/ImageView/Dialog/ImageDialog.tsx +175 -0
- package/packages/Frameworks/View/ImageView/Image.controls.tsx +39 -0
- package/packages/Frameworks/View/ImageView/Image.hooks.ts +82 -0
- package/packages/Frameworks/View/ImageView/Image.module.scss +7 -0
- package/packages/Frameworks/View/ImageView/Image.tsx +375 -0
- package/packages/Frameworks/View/ImageView/Image.types.ts +71 -0
- package/packages/Frameworks/View/ImageView/Image.utils.ts +79 -0
- package/packages/Frameworks/View/View.module.scss +34 -0
- package/packages/Frameworks/View/View.tsx +200 -0
- package/packages/Frameworks/View/View.types.ts +36 -0
- package/packages/Frameworks/_shared/Padding.types.ts +52 -0
- package/packages/Frameworks/_shared/StopParentInteraction.tsx +45 -0
- package/packages/Frameworks/_shared/Wind.types.ts +17 -0
- package/packages/Frameworks/_shared/bodyScrollLock.ts +127 -0
- package/packages/Frameworks/_shared/layer.constants.ts +8 -0
- package/packages/Frameworks/_shared/normalize.ts +39 -0
- package/packages/Frameworks/_shared/sizing.ts +55 -0
- package/packages/Frameworks/_shared/useControllableState.ts +29 -0
- package/packages/Styles/_animation.scss +42 -0
- package/packages/Styles/_color.scss +131 -0
- package/packages/Styles/_font.scss +30 -0
- package/packages/Styles/_icon.scss +782 -0
- package/packages/Styles/_importer.scss +9 -0
- package/packages/Styles/_system.scss +69 -0
- package/packages/Styles/_textstyle.scss +111 -0
- package/packages/Styles/_theme.scss +452 -0
- package/packages/Styles/_viewport-global.scss +99 -0
- package/packages/Styles/_viewport.scss +108 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { LabelProps } from "@/packages/Components/Label/Label.types";
|
|
2
|
+
|
|
3
|
+
export type DatePickerMode = "single" | "range";
|
|
4
|
+
|
|
5
|
+
export interface DatePickerProps {
|
|
6
|
+
"data-color-mode"?: string;
|
|
7
|
+
className?: string;
|
|
8
|
+
style?: React.CSSProperties;
|
|
9
|
+
title?: string;
|
|
10
|
+
required?: boolean;
|
|
11
|
+
readOnly?: boolean;
|
|
12
|
+
disabled?: boolean;
|
|
13
|
+
hint?: LabelProps["hint"];
|
|
14
|
+
|
|
15
|
+
mode?: DatePickerMode;
|
|
16
|
+
|
|
17
|
+
value?: string;
|
|
18
|
+
defaultValue?: string;
|
|
19
|
+
|
|
20
|
+
startDate?: string;
|
|
21
|
+
endDate?: string;
|
|
22
|
+
defaultStartDate?: string;
|
|
23
|
+
defaultEndDate?: string;
|
|
24
|
+
|
|
25
|
+
placeholder?: string;
|
|
26
|
+
|
|
27
|
+
minDate?: string;
|
|
28
|
+
maxDate?: string;
|
|
29
|
+
disabledDaysOfWeek?: number[];
|
|
30
|
+
|
|
31
|
+
showTime?: boolean;
|
|
32
|
+
use12h?: boolean;
|
|
33
|
+
|
|
34
|
+
onRangeChange?: (start: string | null, end: string | null) => void;
|
|
35
|
+
onChange?: (value: string | null) => void;
|
|
36
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
export function parseDate(str: string | undefined | null): Date | null {
|
|
2
|
+
if (!str) return null;
|
|
3
|
+
if (str.includes(" ")) {
|
|
4
|
+
const [datePart, timePart] = str.split(" ");
|
|
5
|
+
const d = new Date(`${datePart}T${timePart}:00`);
|
|
6
|
+
return Number.isNaN(d.getTime()) ? null : d;
|
|
7
|
+
}
|
|
8
|
+
const d = new Date(`${str}T00:00:00`);
|
|
9
|
+
return Number.isNaN(d.getTime()) ? null : d;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function toYMD(d: Date, showTime?: boolean): string {
|
|
13
|
+
const dateStr = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
|
|
14
|
+
if (!showTime) return dateStr;
|
|
15
|
+
return `${dateStr} ${String(d.getHours()).padStart(2, "0")}:${String(d.getMinutes()).padStart(2, "0")}`;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function isSameDay(a: Date | null, b: Date | null): boolean {
|
|
19
|
+
if (!a || !b) return false;
|
|
20
|
+
return (
|
|
21
|
+
a.getFullYear() === b.getFullYear() &&
|
|
22
|
+
a.getMonth() === b.getMonth() &&
|
|
23
|
+
a.getDate() === b.getDate()
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function isBefore(a: Date, b: Date): boolean {
|
|
28
|
+
return a.getTime() < b.getTime();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function formatDisplay(d: Date | null): string {
|
|
32
|
+
if (!d) return "";
|
|
33
|
+
return `${d.getFullYear()}. ${d.getMonth() + 1}. ${d.getDate()}.`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function formatRangeDisplay(
|
|
37
|
+
start: Date | null,
|
|
38
|
+
end: Date | null,
|
|
39
|
+
): string {
|
|
40
|
+
if (!start) return "";
|
|
41
|
+
if (!end) return formatDisplay(start);
|
|
42
|
+
return `${formatDisplay(start)} – ${formatDisplay(end)}`;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function getCalendarDays(year: number, month: number): Date[] {
|
|
46
|
+
const first = new Date(year, month, 1);
|
|
47
|
+
const startOffset = first.getDay();
|
|
48
|
+
const days: Date[] = [];
|
|
49
|
+
for (let i = 0; i < startOffset; i++) {
|
|
50
|
+
days.push(new Date(year, month, 1 - (startOffset - i)));
|
|
51
|
+
}
|
|
52
|
+
const daysInMonth = new Date(year, month + 1, 0).getDate();
|
|
53
|
+
for (let d = 1; d <= daysInMonth; d++) {
|
|
54
|
+
days.push(new Date(year, month, d));
|
|
55
|
+
}
|
|
56
|
+
while (days.length % 7 !== 0) {
|
|
57
|
+
days.push(
|
|
58
|
+
new Date(year, month + 1, days.length - startOffset - daysInMonth + 1),
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
return days;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function isDateDisabled(
|
|
65
|
+
date: Date,
|
|
66
|
+
minDate?: string | null,
|
|
67
|
+
maxDate?: string | null,
|
|
68
|
+
disabledDaysOfWeek?: number[],
|
|
69
|
+
): boolean {
|
|
70
|
+
if (minDate) {
|
|
71
|
+
const min = parseDate(minDate);
|
|
72
|
+
if (min && date.getTime() < min.getTime()) return true;
|
|
73
|
+
}
|
|
74
|
+
if (maxDate) {
|
|
75
|
+
const max = parseDate(maxDate);
|
|
76
|
+
if (max && date.getTime() > max.getTime()) return true;
|
|
77
|
+
}
|
|
78
|
+
if (disabledDaysOfWeek?.includes(date.getDay())) return true;
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useCallback, useMemo, useState } from "react";
|
|
3
|
+
import { getCalendarDays } from "@/packages/Components/DatePicker/DatePicker.utils";
|
|
4
|
+
|
|
5
|
+
interface UseCalendarOptions {
|
|
6
|
+
initialYear: number;
|
|
7
|
+
initialMonth: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface UseCalendarReturn {
|
|
11
|
+
viewYear: number;
|
|
12
|
+
viewMonth: number;
|
|
13
|
+
setViewYear: React.Dispatch<React.SetStateAction<number>>;
|
|
14
|
+
setViewMonth: React.Dispatch<React.SetStateAction<number>>;
|
|
15
|
+
prevMonth: () => void;
|
|
16
|
+
nextMonth: () => void;
|
|
17
|
+
days: Date[];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function useCalendar({
|
|
21
|
+
initialYear,
|
|
22
|
+
initialMonth,
|
|
23
|
+
}: UseCalendarOptions): UseCalendarReturn {
|
|
24
|
+
const [viewYear, setViewYear] = useState(initialYear);
|
|
25
|
+
const [viewMonth, setViewMonth] = useState(initialMonth);
|
|
26
|
+
|
|
27
|
+
const prevMonth = useCallback(() => {
|
|
28
|
+
setViewMonth((m) => {
|
|
29
|
+
if (m === 0) {
|
|
30
|
+
setViewYear((y) => y - 1);
|
|
31
|
+
return 11;
|
|
32
|
+
}
|
|
33
|
+
return m - 1;
|
|
34
|
+
});
|
|
35
|
+
}, []);
|
|
36
|
+
|
|
37
|
+
const nextMonth = useCallback(() => {
|
|
38
|
+
setViewMonth((m) => {
|
|
39
|
+
if (m === 11) {
|
|
40
|
+
setViewYear((y) => y + 1);
|
|
41
|
+
return 0;
|
|
42
|
+
}
|
|
43
|
+
return m + 1;
|
|
44
|
+
});
|
|
45
|
+
}, []);
|
|
46
|
+
|
|
47
|
+
const days = useMemo(
|
|
48
|
+
() => getCalendarDays(viewYear, viewMonth),
|
|
49
|
+
[viewYear, viewMonth],
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
viewYear,
|
|
54
|
+
viewMonth,
|
|
55
|
+
setViewYear,
|
|
56
|
+
setViewMonth,
|
|
57
|
+
prevMonth,
|
|
58
|
+
nextMonth,
|
|
59
|
+
days,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
3
|
+
import type { DatePickerMode } from "@/packages/Components/DatePicker/DatePicker.types";
|
|
4
|
+
import {
|
|
5
|
+
formatDisplay,
|
|
6
|
+
formatRangeDisplay,
|
|
7
|
+
isBefore,
|
|
8
|
+
isDateDisabled,
|
|
9
|
+
isSameDay,
|
|
10
|
+
parseDate,
|
|
11
|
+
toYMD,
|
|
12
|
+
} from "@/packages/Components/DatePicker/DatePicker.utils";
|
|
13
|
+
|
|
14
|
+
interface UseSelectionOptions {
|
|
15
|
+
mode: DatePickerMode;
|
|
16
|
+
isControlled: boolean;
|
|
17
|
+
value?: string | null;
|
|
18
|
+
defaultValue?: string | null;
|
|
19
|
+
startDate?: string | null;
|
|
20
|
+
endDate?: string | null;
|
|
21
|
+
defaultStartDate?: string | null;
|
|
22
|
+
defaultEndDate?: string | null;
|
|
23
|
+
onChange?: (value: string | null) => void;
|
|
24
|
+
onRangeChange?: (start: string | null, end: string | null) => void;
|
|
25
|
+
onClose?: () => void;
|
|
26
|
+
minDate?: string | null;
|
|
27
|
+
maxDate?: string | null;
|
|
28
|
+
disabledDaysOfWeek?: number[];
|
|
29
|
+
showTime?: boolean;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
interface UseSelectionReturn {
|
|
33
|
+
selected: Date | null;
|
|
34
|
+
rangeStart: Date | null;
|
|
35
|
+
rangeEnd: Date | null;
|
|
36
|
+
hoverDay: Date | null;
|
|
37
|
+
setHoverDay: React.Dispatch<React.SetStateAction<Date | null>>;
|
|
38
|
+
handleDayClick: (day: Date) => void;
|
|
39
|
+
isInRange: (day: Date) => boolean;
|
|
40
|
+
isRangeStart: (day: Date) => boolean;
|
|
41
|
+
isRangeEnd: (day: Date) => boolean;
|
|
42
|
+
setSelected: React.Dispatch<React.SetStateAction<Date | null>>;
|
|
43
|
+
setRangeStart: React.Dispatch<React.SetStateAction<Date | null>>;
|
|
44
|
+
setRangeEnd: React.Dispatch<React.SetStateAction<Date | null>>;
|
|
45
|
+
displayText: string | null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function useSelection({
|
|
49
|
+
mode,
|
|
50
|
+
isControlled,
|
|
51
|
+
value,
|
|
52
|
+
defaultValue,
|
|
53
|
+
startDate,
|
|
54
|
+
endDate,
|
|
55
|
+
defaultStartDate,
|
|
56
|
+
defaultEndDate,
|
|
57
|
+
onChange,
|
|
58
|
+
onRangeChange,
|
|
59
|
+
onClose,
|
|
60
|
+
minDate,
|
|
61
|
+
maxDate,
|
|
62
|
+
disabledDaysOfWeek,
|
|
63
|
+
showTime,
|
|
64
|
+
}: UseSelectionOptions): UseSelectionReturn {
|
|
65
|
+
const [selected, setSelected] = useState<Date | null>(() =>
|
|
66
|
+
parseDate(value ?? defaultValue),
|
|
67
|
+
);
|
|
68
|
+
const [rangeStart, setRangeStart] = useState<Date | null>(() =>
|
|
69
|
+
parseDate(startDate ?? defaultStartDate),
|
|
70
|
+
);
|
|
71
|
+
const [rangeEnd, setRangeEnd] = useState<Date | null>(() =>
|
|
72
|
+
parseDate(endDate ?? defaultEndDate),
|
|
73
|
+
);
|
|
74
|
+
const [hoverDay, setHoverDay] = useState<Date | null>(null);
|
|
75
|
+
|
|
76
|
+
useEffect(() => {
|
|
77
|
+
if (!isControlled) return;
|
|
78
|
+
if (mode === "single") setSelected(parseDate(value));
|
|
79
|
+
else {
|
|
80
|
+
setRangeStart(parseDate(startDate));
|
|
81
|
+
setRangeEnd(parseDate(endDate));
|
|
82
|
+
}
|
|
83
|
+
}, [value, startDate, endDate, mode, isControlled]);
|
|
84
|
+
|
|
85
|
+
const handleDayClick = useCallback(
|
|
86
|
+
(day: Date) => {
|
|
87
|
+
if (isDateDisabled(day, minDate, maxDate, disabledDaysOfWeek)) return;
|
|
88
|
+
if (mode === "single") {
|
|
89
|
+
const next = isSameDay(day, selected) ? null : new Date(day);
|
|
90
|
+
if (next && selected) {
|
|
91
|
+
next.setHours(
|
|
92
|
+
selected.getHours(),
|
|
93
|
+
selected.getMinutes(),
|
|
94
|
+
selected.getSeconds(),
|
|
95
|
+
selected.getMilliseconds(),
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
if (!isControlled) setSelected(next);
|
|
99
|
+
onChange?.(next ? toYMD(next, showTime) : null);
|
|
100
|
+
onClose?.();
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (!rangeStart || (rangeStart && rangeEnd)) {
|
|
104
|
+
const next = new Date(day);
|
|
105
|
+
if (rangeStart) {
|
|
106
|
+
next.setHours(
|
|
107
|
+
rangeStart.getHours(),
|
|
108
|
+
rangeStart.getMinutes(),
|
|
109
|
+
rangeStart.getSeconds(),
|
|
110
|
+
rangeStart.getMilliseconds(),
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
if (!isControlled) {
|
|
114
|
+
setRangeStart(next);
|
|
115
|
+
setRangeEnd(null);
|
|
116
|
+
}
|
|
117
|
+
onRangeChange?.(toYMD(next, showTime), null);
|
|
118
|
+
} else {
|
|
119
|
+
let start = new Date(rangeStart);
|
|
120
|
+
let end = new Date(day);
|
|
121
|
+
if (rangeEnd) {
|
|
122
|
+
end.setHours(
|
|
123
|
+
rangeEnd.getHours(),
|
|
124
|
+
rangeEnd.getMinutes(),
|
|
125
|
+
rangeEnd.getSeconds(),
|
|
126
|
+
rangeEnd.getMilliseconds(),
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
if (isBefore(end, start)) {
|
|
130
|
+
[start, end] = [end, start];
|
|
131
|
+
}
|
|
132
|
+
if (!isControlled) {
|
|
133
|
+
setRangeStart(start);
|
|
134
|
+
setRangeEnd(end);
|
|
135
|
+
}
|
|
136
|
+
onRangeChange?.(toYMD(start, showTime), toYMD(end, showTime));
|
|
137
|
+
onClose?.();
|
|
138
|
+
}
|
|
139
|
+
},
|
|
140
|
+
[
|
|
141
|
+
mode,
|
|
142
|
+
selected,
|
|
143
|
+
rangeStart,
|
|
144
|
+
rangeEnd,
|
|
145
|
+
isControlled,
|
|
146
|
+
onChange,
|
|
147
|
+
onRangeChange,
|
|
148
|
+
onClose,
|
|
149
|
+
minDate,
|
|
150
|
+
maxDate,
|
|
151
|
+
disabledDaysOfWeek,
|
|
152
|
+
showTime,
|
|
153
|
+
],
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
const isInRange = useCallback(
|
|
157
|
+
(day: Date): boolean => {
|
|
158
|
+
if (mode !== "range") return false;
|
|
159
|
+
const end = rangeEnd ?? hoverDay;
|
|
160
|
+
if (!rangeStart || !end) return false;
|
|
161
|
+
const lo = isBefore(rangeStart, end) ? rangeStart : end;
|
|
162
|
+
const hi = isBefore(rangeStart, end) ? end : rangeStart;
|
|
163
|
+
return day.getTime() > lo.getTime() && day.getTime() < hi.getTime();
|
|
164
|
+
},
|
|
165
|
+
[mode, rangeStart, rangeEnd, hoverDay],
|
|
166
|
+
);
|
|
167
|
+
|
|
168
|
+
const isRangeStart = useCallback(
|
|
169
|
+
(day: Date): boolean => {
|
|
170
|
+
const eff = rangeEnd ?? hoverDay;
|
|
171
|
+
if (!rangeStart || !eff) return isSameDay(day, rangeStart);
|
|
172
|
+
const lo = isBefore(rangeStart, eff) ? rangeStart : eff;
|
|
173
|
+
return isSameDay(day, lo);
|
|
174
|
+
},
|
|
175
|
+
[rangeStart, rangeEnd, hoverDay],
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
const isRangeEnd = useCallback(
|
|
179
|
+
(day: Date): boolean => {
|
|
180
|
+
const eff = rangeEnd ?? hoverDay;
|
|
181
|
+
if (!rangeStart || !eff) return false;
|
|
182
|
+
const hi = isBefore(rangeStart, eff) ? eff : rangeStart;
|
|
183
|
+
return isSameDay(day, hi);
|
|
184
|
+
},
|
|
185
|
+
[rangeStart, rangeEnd, hoverDay],
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
const displayText = useMemo(() => {
|
|
189
|
+
if (mode === "single") return selected ? formatDisplay(selected) : null;
|
|
190
|
+
return rangeStart ? formatRangeDisplay(rangeStart, rangeEnd) : null;
|
|
191
|
+
}, [mode, selected, rangeStart, rangeEnd]);
|
|
192
|
+
|
|
193
|
+
return {
|
|
194
|
+
selected,
|
|
195
|
+
rangeStart,
|
|
196
|
+
rangeEnd,
|
|
197
|
+
hoverDay,
|
|
198
|
+
setHoverDay,
|
|
199
|
+
handleDayClick,
|
|
200
|
+
isInRange,
|
|
201
|
+
isRangeStart,
|
|
202
|
+
isRangeEnd,
|
|
203
|
+
setSelected,
|
|
204
|
+
setRangeStart,
|
|
205
|
+
setRangeEnd,
|
|
206
|
+
displayText,
|
|
207
|
+
};
|
|
208
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { DividerProps } from "@/packages/Components/Divider/Divider.types";
|
|
2
|
+
import { Size } from "@/packages/Frameworks/_shared/sizing";
|
|
3
|
+
|
|
4
|
+
export default function Divider({
|
|
5
|
+
vertical = false,
|
|
6
|
+
margin,
|
|
7
|
+
marginHorizontal,
|
|
8
|
+
marginVertical,
|
|
9
|
+
gradient = false,
|
|
10
|
+
className,
|
|
11
|
+
style,
|
|
12
|
+
"data-color-mode": dataTheme,
|
|
13
|
+
}: DividerProps) {
|
|
14
|
+
const resolvedMargin = Size(margin);
|
|
15
|
+
const resolvedVertical = Size(marginVertical);
|
|
16
|
+
const resolvedHorizontal = Size(marginHorizontal);
|
|
17
|
+
|
|
18
|
+
const computedStyle = {
|
|
19
|
+
display: "block",
|
|
20
|
+
border: "none",
|
|
21
|
+
margin: 0,
|
|
22
|
+
borderRadius: "var(--radius-circle)",
|
|
23
|
+
width: vertical ? ".15rem" : "100%",
|
|
24
|
+
height: vertical ? undefined : ".1rem",
|
|
25
|
+
alignSelf: vertical ? "stretch" : undefined,
|
|
26
|
+
flex: vertical ? "0 0 auto" : undefined,
|
|
27
|
+
minHeight: vertical ? "1.8rem" : undefined,
|
|
28
|
+
background: gradient
|
|
29
|
+
? `linear-gradient(${vertical ? "180deg" : "90deg"}, transparent 0%, color-mix(in srgb, var(--color-base-reversed-6) 10%, transparent) 50%, transparent 100%)`
|
|
30
|
+
: "color-mix(in srgb, var(--color-base-reversed-6) 10%, transparent)",
|
|
31
|
+
marginTop: resolvedVertical ?? resolvedMargin,
|
|
32
|
+
marginBottom: resolvedVertical ?? resolvedMargin,
|
|
33
|
+
marginLeft: resolvedHorizontal ?? resolvedMargin,
|
|
34
|
+
marginRight: resolvedHorizontal ?? resolvedMargin,
|
|
35
|
+
...style,
|
|
36
|
+
} as React.CSSProperties;
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<hr
|
|
40
|
+
aria-orientation={vertical ? "vertical" : undefined}
|
|
41
|
+
data-color-mode={dataTheme}
|
|
42
|
+
className={className}
|
|
43
|
+
style={computedStyle}
|
|
44
|
+
/>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { UIKitSizeValue } from "@/packages/Frameworks/_shared/sizing";
|
|
2
|
+
|
|
3
|
+
export interface DividerProps {
|
|
4
|
+
"data-color-mode"?: string;
|
|
5
|
+
className?: string;
|
|
6
|
+
style?: React.CSSProperties;
|
|
7
|
+
vertical?: boolean;
|
|
8
|
+
margin?: UIKitSizeValue;
|
|
9
|
+
marginHorizontal?: UIKitSizeValue;
|
|
10
|
+
marginVertical?: UIKitSizeValue;
|
|
11
|
+
gradient?: boolean;
|
|
12
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
@use "../../Styles/viewport" as viewport;
|
|
2
|
+
|
|
3
|
+
.Wrapper {
|
|
4
|
+
max-width: 1280px;
|
|
5
|
+
width: 100%;
|
|
6
|
+
margin-top: 3.6rem;
|
|
7
|
+
padding-inline: 3.6rem;
|
|
8
|
+
height: 4rem;
|
|
9
|
+
position: relative;
|
|
10
|
+
|
|
11
|
+
@include viewport.down(w3) {
|
|
12
|
+
margin-top: 1.6rem;
|
|
13
|
+
padding-inline: 1.6rem;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.LeftGroup {
|
|
17
|
+
flex: 1 1 auto;
|
|
18
|
+
min-width: 0;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.LeftContent {
|
|
22
|
+
display: flex;
|
|
23
|
+
align-items: center;
|
|
24
|
+
gap: 0.8rem;
|
|
25
|
+
flex: 1 1 auto;
|
|
26
|
+
min-width: 0;
|
|
27
|
+
padding: 0.6rem 0.8rem;
|
|
28
|
+
margin: -0.8rem;
|
|
29
|
+
transition: var(--transition-surface);
|
|
30
|
+
|
|
31
|
+
@include viewport.down(w3) {
|
|
32
|
+
padding: 0.4rem 0.6rem;
|
|
33
|
+
margin: -0.4rem -0.6rem;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.LeftContentLink {
|
|
38
|
+
flex: 0 1 auto;
|
|
39
|
+
width: fit-content;
|
|
40
|
+
max-width: 100%;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.LogoLink {
|
|
44
|
+
display: flex;
|
|
45
|
+
align-items: center;
|
|
46
|
+
padding: 0.4rem;
|
|
47
|
+
margin: -0.4rem;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.RightContent {
|
|
51
|
+
display: flex;
|
|
52
|
+
align-items: center;
|
|
53
|
+
gap: 0;
|
|
54
|
+
padding: 0.2rem;
|
|
55
|
+
position: relative;
|
|
56
|
+
background: color-mix(in srgb, var(--color-base-light-1) 70%, transparent);
|
|
57
|
+
-webkit-backdrop-filter: blur(8px);
|
|
58
|
+
backdrop-filter: blur(8px);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.LinearBlur {
|
|
63
|
+
position: fixed;
|
|
64
|
+
top: 0;
|
|
65
|
+
left: 0;
|
|
66
|
+
right: 0;
|
|
67
|
+
height: 10.6rem;
|
|
68
|
+
width: 100%;
|
|
69
|
+
z-index: 1100;
|
|
70
|
+
|
|
71
|
+
@include viewport.down(w3) {
|
|
72
|
+
height: 7.2rem;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import clsx from "clsx";
|
|
2
|
+
import styles from "@/packages/Components/Header/Header.module.scss";
|
|
3
|
+
import type { HeaderProps } from "@/packages/Components/Header/Header.types";
|
|
4
|
+
import EdgeEffect from "@/packages/Frameworks/EdgeEffect/EdgeEffect";
|
|
5
|
+
import View from "@/packages/Frameworks/View/View";
|
|
6
|
+
|
|
7
|
+
export default function Header({
|
|
8
|
+
"data-color-mode": dataTheme,
|
|
9
|
+
left,
|
|
10
|
+
center,
|
|
11
|
+
right,
|
|
12
|
+
className,
|
|
13
|
+
wrapperClassName,
|
|
14
|
+
}: HeaderProps) {
|
|
15
|
+
return (
|
|
16
|
+
<>
|
|
17
|
+
<EdgeEffect side="top" className={styles.LinearBlur} />
|
|
18
|
+
<header
|
|
19
|
+
className={className}
|
|
20
|
+
data-color-mode={dataTheme}
|
|
21
|
+
style={{
|
|
22
|
+
display: "flex",
|
|
23
|
+
flexDirection: "column",
|
|
24
|
+
alignItems: "center",
|
|
25
|
+
justifyContent: "center",
|
|
26
|
+
position: "fixed",
|
|
27
|
+
top: 0,
|
|
28
|
+
left: 0,
|
|
29
|
+
right: 0,
|
|
30
|
+
width: "100%",
|
|
31
|
+
zIndex: 1200,
|
|
32
|
+
}}
|
|
33
|
+
>
|
|
34
|
+
<View
|
|
35
|
+
className={clsx(styles.Wrapper, wrapperClassName)}
|
|
36
|
+
alignItems="center"
|
|
37
|
+
justifyContent="space-between"
|
|
38
|
+
gap={4}
|
|
39
|
+
>
|
|
40
|
+
{left}
|
|
41
|
+
{center}
|
|
42
|
+
{right}
|
|
43
|
+
</View>
|
|
44
|
+
</header>
|
|
45
|
+
</>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { Children } from "react";
|
|
2
|
+
import type { IconGroupProps } from "@/packages/Components/Icon/Icon.group.types";
|
|
3
|
+
import Icon from "@/packages/Components/Icon/Icon";
|
|
4
|
+
import type { IconProps } from "@/packages/Components/Icon/Icon.types";
|
|
5
|
+
import {
|
|
6
|
+
Size,
|
|
7
|
+
type UIKitSizeValue,
|
|
8
|
+
} from "@/packages/Frameworks/_shared/sizing";
|
|
9
|
+
import View from "@/packages/Frameworks/View/View";
|
|
10
|
+
|
|
11
|
+
const GROUP_PADDING = 2;
|
|
12
|
+
const ICON_PADDING = 6;
|
|
13
|
+
|
|
14
|
+
function getIconKey(icon: IconProps, index: number) {
|
|
15
|
+
const title = typeof icon.title === "string" ? icon.title : undefined;
|
|
16
|
+
|
|
17
|
+
return [
|
|
18
|
+
title,
|
|
19
|
+
icon.icon,
|
|
20
|
+
icon.svg,
|
|
21
|
+
icon.image,
|
|
22
|
+
icon.width ?? 0,
|
|
23
|
+
icon.height ?? 0,
|
|
24
|
+
icon.color ?? "default",
|
|
25
|
+
index,
|
|
26
|
+
].join("-");
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function addSizeValues(a: UIKitSizeValue, b: UIKitSizeValue) {
|
|
30
|
+
if (typeof a === "number" && typeof b === "number") {
|
|
31
|
+
return a + b;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return `calc(${Size(a)} + ${Size(b)})`;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function resolveIcon(
|
|
38
|
+
icon: IconProps,
|
|
39
|
+
{
|
|
40
|
+
single,
|
|
41
|
+
groupPadding,
|
|
42
|
+
iconBoxOptions,
|
|
43
|
+
iconSize,
|
|
44
|
+
iconWidth,
|
|
45
|
+
iconHeight,
|
|
46
|
+
}: {
|
|
47
|
+
single: boolean;
|
|
48
|
+
groupPadding: UIKitSizeValue;
|
|
49
|
+
iconBoxOptions?: IconProps["boxOptions"];
|
|
50
|
+
iconSize?: IconProps["size"];
|
|
51
|
+
iconWidth?: IconProps["width"];
|
|
52
|
+
iconHeight?: IconProps["height"];
|
|
53
|
+
},
|
|
54
|
+
): IconProps {
|
|
55
|
+
const boxed = icon.box ?? true;
|
|
56
|
+
const resolvedPadding = boxed
|
|
57
|
+
? (icon.boxOptions?.padding ??
|
|
58
|
+
iconBoxOptions?.padding ??
|
|
59
|
+
(single ? addSizeValues(ICON_PADDING, groupPadding) : ICON_PADDING))
|
|
60
|
+
: (icon.boxOptions?.padding ?? iconBoxOptions?.padding);
|
|
61
|
+
|
|
62
|
+
return {
|
|
63
|
+
box: true,
|
|
64
|
+
border: icon.border,
|
|
65
|
+
size: icon.size ?? iconSize,
|
|
66
|
+
width: icon.width ?? iconWidth,
|
|
67
|
+
height: icon.height ?? iconHeight,
|
|
68
|
+
...icon,
|
|
69
|
+
boxOptions: {
|
|
70
|
+
...iconBoxOptions,
|
|
71
|
+
...icon.boxOptions,
|
|
72
|
+
padding: resolvedPadding,
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export default function IconGroup({
|
|
78
|
+
className,
|
|
79
|
+
style,
|
|
80
|
+
children,
|
|
81
|
+
icons,
|
|
82
|
+
padding = GROUP_PADDING,
|
|
83
|
+
iconBoxOptions,
|
|
84
|
+
iconSize,
|
|
85
|
+
iconWidth,
|
|
86
|
+
iconHeight,
|
|
87
|
+
background,
|
|
88
|
+
border,
|
|
89
|
+
radius,
|
|
90
|
+
}: IconGroupProps) {
|
|
91
|
+
const iconItems = icons ? (Array.isArray(icons) ? icons : [icons]) : [];
|
|
92
|
+
const itemCount = iconItems.length + Children.count(children);
|
|
93
|
+
const single = itemCount === 1;
|
|
94
|
+
|
|
95
|
+
return (
|
|
96
|
+
<View
|
|
97
|
+
alignItems="center"
|
|
98
|
+
background={background ?? "Base1TP2"}
|
|
99
|
+
radius={radius ?? "Circle"}
|
|
100
|
+
border={border}
|
|
101
|
+
className={className}
|
|
102
|
+
style={{ backdropFilter: "blur(2px)", width: "max-content", ...style }}
|
|
103
|
+
gap={2}
|
|
104
|
+
padding={single ? 0 : padding}
|
|
105
|
+
>
|
|
106
|
+
{iconItems.map((icon, index) => (
|
|
107
|
+
<Icon
|
|
108
|
+
key={getIconKey(icon, index)}
|
|
109
|
+
{...resolveIcon(icon, {
|
|
110
|
+
single,
|
|
111
|
+
groupPadding: padding,
|
|
112
|
+
iconBoxOptions,
|
|
113
|
+
iconSize,
|
|
114
|
+
iconWidth,
|
|
115
|
+
iconHeight,
|
|
116
|
+
})}
|
|
117
|
+
/>
|
|
118
|
+
))}
|
|
119
|
+
{children}
|
|
120
|
+
</View>
|
|
121
|
+
);
|
|
122
|
+
}
|