@neko-os/ui 0.5.0 → 0.5.2
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/NekoUI.js +4 -1
- package/dist/abstractions/index.js +1 -0
- package/dist/components/actions/Dropdown.js +5 -3
- package/dist/components/calendar/PeriodNavBar.js +176 -0
- package/dist/components/calendar/WeekDaysBar.js +8 -4
- package/dist/components/calendar/_helpers/calendarDays.js +5 -1
- package/dist/components/calendar/index.js +1 -0
- package/dist/components/carousel/CarouselSlider.native.js +12 -1
- package/dist/components/filter/DateFilter.js +1 -1
- package/dist/components/inputs/Select.js +56 -52
- package/dist/components/inputs/datePicker/DayPicker.js +15 -9
- package/dist/components/inputs/datePicker/MonthPicker.js +15 -10
- package/dist/components/inputs/datePicker/QuarterPicker.js +15 -10
- package/dist/components/inputs/datePicker/WeekPicker.js +15 -9
- package/dist/components/inputs/datePicker/YearPicker.js +15 -10
- package/dist/helpers/index.js +2 -0
- package/dist/helpers/weekStart.js +25 -0
- package/dist/helpers/weekStartSetup.js +11 -0
- package/dist/helpers/weekStartSetup.native.js +11 -0
- package/dist/index.js +1 -0
- package/package.json +1 -1
- package/src/NekoUI.js +3 -0
- package/src/abstractions/index.js +1 -0
- package/src/components/actions/Dropdown.js +2 -0
- package/src/components/calendar/PeriodNavBar.js +176 -0
- package/src/components/calendar/WeekDaysBar.js +6 -2
- package/src/components/calendar/_helpers/calendarDays.js +5 -1
- package/src/components/calendar/index.js +1 -1
- package/src/components/carousel/CarouselSlider.native.js +12 -1
- package/src/components/filter/DateFilter.js +1 -1
- package/src/components/inputs/Select.js +19 -15
- package/src/components/inputs/datePicker/DayPicker.js +14 -8
- package/src/components/inputs/datePicker/MonthPicker.js +14 -9
- package/src/components/inputs/datePicker/QuarterPicker.js +14 -9
- package/src/components/inputs/datePicker/WeekPicker.js +14 -8
- package/src/components/inputs/datePicker/YearPicker.js +14 -9
- package/src/helpers/index.js +2 -0
- package/src/helpers/weekStart.js +25 -0
- package/src/helpers/weekStartSetup.js +11 -0
- package/src/helpers/weekStartSetup.native.js +11 -0
- package/src/index.js +1 -0
|
@@ -25,7 +25,9 @@ function fromMonthValue(v) {
|
|
|
25
25
|
startOf('month');
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
function MonthWeeks(_ref) {var _this = this;var
|
|
28
|
+
var MonthWeeks = React.memo(function MonthWeeks(_ref) {var _this = this;var monthValue = _ref.monthValue,selectedKey = _ref.selectedKey,onSelect = _ref.onSelect,min = _ref.min,max = _ref.max,onCheckDisabled = _ref.onCheckDisabled;
|
|
29
|
+
var month = fromMonthValue(monthValue);
|
|
30
|
+
var selectedValue = selectedKey ? dayjs(selectedKey) : null;
|
|
29
31
|
var _useCalendarDays = useCalendarDays(month),cells = _useCalendarDays.cells;
|
|
30
32
|
var weeks = splitEvery(7, cells);
|
|
31
33
|
|
|
@@ -67,9 +69,9 @@ function MonthWeeks(_ref) {var _this = this;var month = _ref.month,selectedValue
|
|
|
67
69
|
)] }
|
|
68
70
|
));
|
|
69
71
|
|
|
70
|
-
}
|
|
72
|
+
});
|
|
71
73
|
|
|
72
|
-
export function WeekPicker(_ref2) {var _value2,_value3,_value4,_this2 = this;var value = _ref2.value,onChange = _ref2.onChange,min = _ref2.min,max = _ref2.max,onCheckDisabled = _ref2.onCheckDisabled,allowClear = _ref2.allowClear,props = _objectWithoutProperties(_ref2, _excluded);
|
|
74
|
+
export function WeekPicker(_ref2) {var _value2,_value3,_value4,_value5,_this2 = this;var value = _ref2.value,onChange = _ref2.onChange,min = _ref2.min,max = _ref2.max,onCheckDisabled = _ref2.onCheckDisabled,allowClear = _ref2.allowClear,props = _objectWithoutProperties(_ref2, _excluded);
|
|
73
75
|
var _React$useState = React.useState(value),_React$useState2 = _slicedToArray(_React$useState, 2),localValue = _React$useState2[0],setLocalValue = _React$useState2[1];
|
|
74
76
|
var _React$useState3 = React.useState(function () {return dayjs(value || undefined).startOf('month');}),_React$useState4 = _slicedToArray(_React$useState3, 2),currentMonth = _React$useState4[0],setCurrentMonth = _React$useState4[1];
|
|
75
77
|
value = value === undefined ? localValue : value;
|
|
@@ -79,18 +81,22 @@ export function WeekPicker(_ref2) {var _value2,_value3,_value4,_this2 = this;var
|
|
|
79
81
|
if ((_value = value) != null && _value.isValid != null && _value.isValid()) setCurrentMonth(value.startOf('month'));
|
|
80
82
|
}, [(_value2 = value) == null ? void 0 : _value2.day == null ? void 0 : _value2.day(), (_value3 = value) == null ? void 0 : _value3.month == null ? void 0 : _value3.month(), (_value4 = value) == null ? void 0 : _value4.year == null ? void 0 : _value4.year()]);
|
|
81
83
|
|
|
82
|
-
var handleChange =
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
84
|
+
var handleChange = React.useCallback(
|
|
85
|
+
function (v) {
|
|
86
|
+
var newValue = v.startOf('week');
|
|
87
|
+
setLocalValue(newValue);
|
|
88
|
+
onChange == null ? void 0 : onChange(newValue);
|
|
89
|
+
},
|
|
90
|
+
[onChange]
|
|
91
|
+
);
|
|
87
92
|
|
|
88
93
|
var monthValue = toMonthValue(currentMonth);
|
|
89
94
|
var minMonth = min ? toMonthValue(dayjs(min).startOf('month')) : undefined;
|
|
90
95
|
var maxMonth = max ? toMonthValue(dayjs(max).startOf('month')) : undefined;
|
|
96
|
+
var selectedKey = (_value5 = value) == null ? void 0 : _value5.valueOf == null ? void 0 : _value5.valueOf();
|
|
91
97
|
|
|
92
98
|
var renderSlide = function renderSlide(v) {return (
|
|
93
|
-
_jsx(MonthWeeks, {
|
|
99
|
+
_jsx(MonthWeeks, { monthValue: v, selectedKey: selectedKey, onSelect: handleChange, min: min, max: max, onCheckDisabled: onCheckDisabled }));};
|
|
94
100
|
|
|
95
101
|
|
|
96
102
|
return (
|
|
@@ -21,15 +21,16 @@ function decadeFromIndex(i) {
|
|
|
21
21
|
return dayjs().year(i * 10).startOf('year');
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
function DecadeGrid(_ref) {var _this = this;var decadeIndex = _ref.decadeIndex,
|
|
24
|
+
var DecadeGrid = React.memo(function DecadeGrid(_ref) {var _this = this;var decadeIndex = _ref.decadeIndex,selectedKey = _ref.selectedKey,onSelect = _ref.onSelect,min = _ref.min,max = _ref.max,onCheckDisabled = _ref.onCheckDisabled;
|
|
25
25
|
var decadeStart = decadeFromIndex(decadeIndex);
|
|
26
|
+
var selectedValue = selectedKey ? dayjs(selectedKey) : null;
|
|
26
27
|
var years = range(decadeStart.year(), decadeStart.year() + 10);
|
|
27
28
|
|
|
28
29
|
return (
|
|
29
30
|
_jsx(Grid, { colSpan: 12, gap: "xs", children:
|
|
30
31
|
years.map(function (year) {
|
|
31
32
|
var dateVal = decadeStart.year(year);
|
|
32
|
-
var isActive = !!selectedValue && dateVal.isSame(selectedValue, '
|
|
33
|
+
var isActive = !!selectedValue && dateVal.isSame(selectedValue, 'year');
|
|
33
34
|
var disabled = isDateDisabled(dateVal, { min: min, max: max, onCheckDisabled: onCheckDisabled });
|
|
34
35
|
|
|
35
36
|
return (
|
|
@@ -51,9 +52,9 @@ function DecadeGrid(_ref) {var _this = this;var decadeIndex = _ref.decadeIndex,s
|
|
|
51
52
|
}) }
|
|
52
53
|
));
|
|
53
54
|
|
|
54
|
-
}
|
|
55
|
+
});
|
|
55
56
|
|
|
56
|
-
export function YearPicker(_ref2) {var _value2,_this2 = this;var value = _ref2.value,onChange = _ref2.onChange,min = _ref2.min,max = _ref2.max,onCheckDisabled = _ref2.onCheckDisabled,allowClear = _ref2.allowClear,props = _objectWithoutProperties(_ref2, _excluded);
|
|
57
|
+
export function YearPicker(_ref2) {var _value2,_value3,_this2 = this;var value = _ref2.value,onChange = _ref2.onChange,min = _ref2.min,max = _ref2.max,onCheckDisabled = _ref2.onCheckDisabled,allowClear = _ref2.allowClear,props = _objectWithoutProperties(_ref2, _excluded);
|
|
57
58
|
var _React$useState = React.useState(value),_React$useState2 = _slicedToArray(_React$useState, 2),localValue = _React$useState2[0],setLocalValue = _React$useState2[1];
|
|
58
59
|
var _React$useState3 = React.useState(function () {return getDecadeIndex(value);}),_React$useState4 = _slicedToArray(_React$useState3, 2),currentDecade = _React$useState4[0],setCurrentDecade = _React$useState4[1];
|
|
59
60
|
|
|
@@ -64,17 +65,21 @@ export function YearPicker(_ref2) {var _value2,_this2 = this;var value = _ref2.v
|
|
|
64
65
|
if ((_value = value) != null && _value.isValid != null && _value.isValid()) setCurrentDecade(getDecadeIndex(value));
|
|
65
66
|
}, [(_value2 = value) == null ? void 0 : _value2.year == null ? void 0 : _value2.year()]);
|
|
66
67
|
|
|
67
|
-
var handleChange =
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
var handleChange = React.useCallback(
|
|
69
|
+
function (v) {
|
|
70
|
+
var newValue = v.startOf('year');
|
|
71
|
+
setLocalValue(newValue);
|
|
72
|
+
onChange == null ? void 0 : onChange(newValue);
|
|
73
|
+
},
|
|
74
|
+
[onChange]
|
|
75
|
+
);
|
|
72
76
|
|
|
73
77
|
var minDecade = min ? getDecadeIndex(min) : undefined;
|
|
74
78
|
var maxDecade = max ? getDecadeIndex(max) : undefined;
|
|
79
|
+
var selectedKey = (_value3 = value) == null ? void 0 : _value3.valueOf == null ? void 0 : _value3.valueOf();
|
|
75
80
|
|
|
76
81
|
var renderSlide = function renderSlide(v) {return (
|
|
77
|
-
_jsx(DecadeGrid, { decadeIndex: v,
|
|
82
|
+
_jsx(DecadeGrid, { decadeIndex: v, selectedKey: selectedKey, onSelect: handleChange, min: min, max: max, onCheckDisabled: onCheckDisabled }));};
|
|
78
83
|
|
|
79
84
|
|
|
80
85
|
return (
|
package/dist/helpers/index.js
CHANGED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import dayjs from 'dayjs';
|
|
2
|
+
import updateLocale from 'dayjs/esm/plugin/updateLocale';
|
|
3
|
+
|
|
4
|
+
dayjs.extend(updateLocale);
|
|
5
|
+
|
|
6
|
+
var _override = null;
|
|
7
|
+
|
|
8
|
+
export function getFirstDayOfWeek() {
|
|
9
|
+
if (_override !== null) return _override;
|
|
10
|
+
return dayjs().$locale().weekStart || 0;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function setFirstDayOfWeek(day) {
|
|
14
|
+
_override = day;
|
|
15
|
+
dayjs.updateLocale(dayjs().$locale().name || 'en', { weekStart: day });
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function getOrderedWeekdays() {
|
|
19
|
+
var first = getFirstDayOfWeek();
|
|
20
|
+
return Array.from({ length: 7 }, function (_, i) {return (first + i) % 7;});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function getWeekdayOffset(dayIndex) {
|
|
24
|
+
return (dayIndex - getFirstDayOfWeek() + 7) % 7;
|
|
25
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { setFirstDayOfWeek } from "./weekStart";
|
|
2
|
+
|
|
3
|
+
export function initFirstDayOfWeek() {
|
|
4
|
+
try {var _locale$weekInfo;
|
|
5
|
+
var locale = new Intl.Locale(navigator.language);
|
|
6
|
+
var weekInfo = (_locale$weekInfo = locale.weekInfo) != null ? _locale$weekInfo : locale.getWeekInfo == null ? void 0 : locale.getWeekInfo();
|
|
7
|
+
if ((weekInfo == null ? void 0 : weekInfo.firstDay) != null) {
|
|
8
|
+
setFirstDayOfWeek(weekInfo.firstDay === 7 ? 0 : weekInfo.firstDay);
|
|
9
|
+
}
|
|
10
|
+
} catch (_unused) {}
|
|
11
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { setFirstDayOfWeek } from "./weekStart";
|
|
2
|
+
|
|
3
|
+
export function initFirstDayOfWeek() {
|
|
4
|
+
try {
|
|
5
|
+
var Localization = require('expo-localization');
|
|
6
|
+
var cal = Localization.getCalendars()[0];
|
|
7
|
+
if ((cal == null ? void 0 : cal.firstWeekday) != null) {
|
|
8
|
+
setFirstDayOfWeek((cal.firstWeekday - 1) % 7);
|
|
9
|
+
}
|
|
10
|
+
} catch (_unused) {}
|
|
11
|
+
}
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
package/src/NekoUI.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { initFirstDayOfWeek } from './helpers/weekStartSetup'
|
|
1
2
|
import { DynamicStyleTag } from './DynamicStyleTag'
|
|
2
3
|
import { I18nProvider } from './i18n'
|
|
3
4
|
import { ModalsHandler } from './components/modals/modal/handler/ModalsHandler'
|
|
@@ -9,6 +10,8 @@ import { ThemeHandler } from './theme/ThemeHandler'
|
|
|
9
10
|
import { ThemePickerDrawer } from './components/theme'
|
|
10
11
|
import { useThemeHandler } from './theme'
|
|
11
12
|
|
|
13
|
+
initFirstDayOfWeek()
|
|
14
|
+
|
|
12
15
|
export function NekoUI({ children, i18n, ...props }) {
|
|
13
16
|
return (
|
|
14
17
|
<ThemeHandler {...props}>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Platform'
|
|
@@ -37,6 +37,7 @@ export function Dropdown({ items, ...rootProps }) {
|
|
|
37
37
|
placement,
|
|
38
38
|
gap,
|
|
39
39
|
useBottomDrawer,
|
|
40
|
+
snapPoints,
|
|
40
41
|
...props
|
|
41
42
|
} = formattedProps
|
|
42
43
|
|
|
@@ -52,6 +53,7 @@ export function Dropdown({ items, ...rootProps }) {
|
|
|
52
53
|
// In case its web use the Drawer component
|
|
53
54
|
contentProps={{ padding: 0 }}
|
|
54
55
|
useBottomDrawer={useBottomDrawer}
|
|
56
|
+
snapPoints={snapPoints}
|
|
55
57
|
{...popoverProps}
|
|
56
58
|
renderContent={({ onClose }) => {
|
|
57
59
|
const handleChange = (...params) => {
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import dayjs from 'dayjs'
|
|
3
|
+
import quarterOfYear from 'dayjs/esm/plugin/quarterOfYear'
|
|
4
|
+
|
|
5
|
+
import { InfiniteCarousel } from '../carousel/InfiniteCarousel'
|
|
6
|
+
import { Link } from '../actions/Link'
|
|
7
|
+
import { Text } from '../text/Text'
|
|
8
|
+
import { View } from '../structure/View'
|
|
9
|
+
import { isDateDisabled } from './_helpers/dateDisabled'
|
|
10
|
+
|
|
11
|
+
dayjs.extend(quarterOfYear)
|
|
12
|
+
|
|
13
|
+
function getWeekEpoch() {
|
|
14
|
+
return dayjs('2000-01-01').startOf('week')
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const TYPES = {
|
|
18
|
+
day: {
|
|
19
|
+
count: 7,
|
|
20
|
+
unit: 'day',
|
|
21
|
+
toPageValue(date) {
|
|
22
|
+
return date.startOf('week').diff(getWeekEpoch(), 'week')
|
|
23
|
+
},
|
|
24
|
+
getItems(pageValue) {
|
|
25
|
+
const weekStart = getWeekEpoch().add(pageValue, 'week')
|
|
26
|
+
return Array.from({ length: 7 }, (_, i) => {
|
|
27
|
+
const d = weekStart.add(i, 'day')
|
|
28
|
+
return { key: d.valueOf(), date: d, label: d.format('ddd'), sublabel: String(d.date()) }
|
|
29
|
+
})
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
week: {
|
|
33
|
+
count: 7,
|
|
34
|
+
unit: 'week',
|
|
35
|
+
toPageValue(date) {
|
|
36
|
+
const weekIndex = date.startOf('week').diff(getWeekEpoch(), 'week')
|
|
37
|
+
return Math.floor(weekIndex / 7)
|
|
38
|
+
},
|
|
39
|
+
getItems(pageValue) {
|
|
40
|
+
return Array.from({ length: 7 }, (_, i) => {
|
|
41
|
+
const weekIndex = pageValue * 7 + i
|
|
42
|
+
const d = getWeekEpoch().add(weekIndex, 'week')
|
|
43
|
+
const end = d.add(6, 'day')
|
|
44
|
+
return { key: d.valueOf(), date: d, label: `${d.date()}-${end.date()}`, sublabel: d.format('MMM') }
|
|
45
|
+
})
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
month: {
|
|
49
|
+
count: 7,
|
|
50
|
+
unit: 'month',
|
|
51
|
+
toPageValue(date) {
|
|
52
|
+
const absMonth = date.year() * 12 + date.month()
|
|
53
|
+
return Math.floor(absMonth / 7)
|
|
54
|
+
},
|
|
55
|
+
getItems(pageValue) {
|
|
56
|
+
return Array.from({ length: 7 }, (_, i) => {
|
|
57
|
+
const absMonth = pageValue * 7 + i
|
|
58
|
+
const year = Math.floor(absMonth / 12)
|
|
59
|
+
const month = absMonth % 12
|
|
60
|
+
const d = dayjs().year(year).month(month).startOf('month')
|
|
61
|
+
return { key: d.valueOf(), date: d, label: d.format('MMM'), sublabel: d.format("'YY") }
|
|
62
|
+
})
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
quarter: {
|
|
66
|
+
count: 4,
|
|
67
|
+
unit: 'quarter',
|
|
68
|
+
toPageValue(date) {
|
|
69
|
+
return date.year()
|
|
70
|
+
},
|
|
71
|
+
getItems(pageValue) {
|
|
72
|
+
return Array.from({ length: 4 }, (_, i) => {
|
|
73
|
+
const d = dayjs().year(pageValue).month(i * 3).startOf('month')
|
|
74
|
+
return { key: d.valueOf(), date: d, label: `Q${i + 1}`, sublabel: String(pageValue) }
|
|
75
|
+
})
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
year: {
|
|
79
|
+
count: 7,
|
|
80
|
+
unit: 'year',
|
|
81
|
+
toPageValue(date) {
|
|
82
|
+
return Math.floor(date.year() / 7)
|
|
83
|
+
},
|
|
84
|
+
getItems(pageValue) {
|
|
85
|
+
return Array.from({ length: 7 }, (_, i) => {
|
|
86
|
+
const year = pageValue * 7 + i
|
|
87
|
+
const d = dayjs().year(year).startOf('year')
|
|
88
|
+
return { key: d.valueOf(), date: d, label: String(year), sublabel: null }
|
|
89
|
+
})
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const PeriodSlide = React.memo(function PeriodSlide({ items, value, unit, onChange, min, max, onCheckDisabled }) {
|
|
95
|
+
return (
|
|
96
|
+
<View row center gap="xs">
|
|
97
|
+
{items.map((item) => {
|
|
98
|
+
const isActive = !!value && dayjs(value).isSame(item.date, unit)
|
|
99
|
+
const disabled = isDateDisabled(item.date, { min, max, onCheckDisabled })
|
|
100
|
+
|
|
101
|
+
return (
|
|
102
|
+
<Link
|
|
103
|
+
key={item.key}
|
|
104
|
+
flex
|
|
105
|
+
center
|
|
106
|
+
br="md"
|
|
107
|
+
paddingV="xs"
|
|
108
|
+
onPress={() => onChange(item.date)}
|
|
109
|
+
bg={isActive && 'primary'}
|
|
110
|
+
disabled={disabled}
|
|
111
|
+
>
|
|
112
|
+
<Text sm center strong={isActive} text2={!isActive}>
|
|
113
|
+
{item.label}
|
|
114
|
+
</Text>
|
|
115
|
+
{item.sublabel && (
|
|
116
|
+
<Text xxs center text4={!isActive} strong={isActive}>
|
|
117
|
+
{item.sublabel}
|
|
118
|
+
</Text>
|
|
119
|
+
)}
|
|
120
|
+
</Link>
|
|
121
|
+
)
|
|
122
|
+
})}
|
|
123
|
+
</View>
|
|
124
|
+
)
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
export function PeriodNavBar({ type = 'day', value, onChange, min, max, onCheckDisabled, ...props }) {
|
|
128
|
+
const config = TYPES[type]
|
|
129
|
+
const [localValue, setLocalValue] = React.useState(value)
|
|
130
|
+
const resolvedValue = value === undefined ? localValue : value
|
|
131
|
+
|
|
132
|
+
const [currentPage, setCurrentPage] = React.useState(() => {
|
|
133
|
+
const date = resolvedValue ? dayjs(resolvedValue) : dayjs()
|
|
134
|
+
return config.toPageValue(date)
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
React.useEffect(() => {
|
|
138
|
+
const date = resolvedValue ? dayjs(resolvedValue) : dayjs()
|
|
139
|
+
setCurrentPage(TYPES[type].toPageValue(date))
|
|
140
|
+
}, [resolvedValue, type])
|
|
141
|
+
|
|
142
|
+
const handleSelect = React.useCallback(
|
|
143
|
+
(date) => {
|
|
144
|
+
setLocalValue(date)
|
|
145
|
+
onChange?.(date)
|
|
146
|
+
},
|
|
147
|
+
[onChange]
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
const minPage = min ? config.toPageValue(dayjs(min)) : undefined
|
|
151
|
+
const maxPage = max ? config.toPageValue(dayjs(max)) : undefined
|
|
152
|
+
|
|
153
|
+
const renderSlide = (pageValue) => (
|
|
154
|
+
<PeriodSlide
|
|
155
|
+
items={config.getItems(pageValue)}
|
|
156
|
+
value={resolvedValue}
|
|
157
|
+
unit={config.unit}
|
|
158
|
+
onChange={handleSelect}
|
|
159
|
+
min={min}
|
|
160
|
+
max={max}
|
|
161
|
+
onCheckDisabled={onCheckDisabled}
|
|
162
|
+
/>
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
return (
|
|
166
|
+
<View className="neko-period-nav-bar" {...props}>
|
|
167
|
+
<InfiniteCarousel
|
|
168
|
+
value={currentPage}
|
|
169
|
+
onChange={setCurrentPage}
|
|
170
|
+
renderSlide={renderSlide}
|
|
171
|
+
min={minPage}
|
|
172
|
+
max={maxPage}
|
|
173
|
+
/>
|
|
174
|
+
</View>
|
|
175
|
+
)
|
|
176
|
+
}
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import { Text } from '../text/Text'
|
|
2
2
|
import { View } from '../structure/View'
|
|
3
|
+
import { getFirstDayOfWeek } from '../../helpers/weekStart'
|
|
3
4
|
|
|
4
|
-
const
|
|
5
|
+
const ALL_DAYS = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
|
|
5
6
|
|
|
6
7
|
export function WeekDaysBar() {
|
|
8
|
+
const firstDay = getFirstDayOfWeek()
|
|
9
|
+
const labels = [...ALL_DAYS.slice(firstDay), ...ALL_DAYS.slice(0, firstDay)]
|
|
10
|
+
|
|
7
11
|
return (
|
|
8
12
|
<View className="neko-week-days-bar" row center gap="sm">
|
|
9
|
-
{
|
|
13
|
+
{labels.map((w) => (
|
|
10
14
|
<View key={w} flex height={30} center>
|
|
11
15
|
<Text center sm text4>
|
|
12
16
|
{w}
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import dayjs from 'dayjs'
|
|
2
2
|
import React from 'react'
|
|
3
3
|
|
|
4
|
+
import { getFirstDayOfWeek } from '../../../helpers/weekStart'
|
|
5
|
+
|
|
4
6
|
export function useCalendarDays(currentMonth) {
|
|
5
7
|
return React.useMemo(() => {
|
|
6
8
|
if (!currentMonth?.isValid?.()) currentMonth = dayjs()
|
|
7
9
|
const startWeekday = currentMonth.startOf('month').day()
|
|
10
|
+
const firstDay = getFirstDayOfWeek()
|
|
11
|
+
const offset = (startWeekday - firstDay + 7) % 7
|
|
8
12
|
const daysInMonth = currentMonth.daysInMonth()
|
|
9
13
|
|
|
10
|
-
const blanks = Array.from({ length:
|
|
14
|
+
const blanks = Array.from({ length: offset }, () => null)
|
|
11
15
|
const days = Array.from({ length: daysInMonth }, (_, i) => i + 1)
|
|
12
16
|
const cells = [...blanks, ...days]
|
|
13
17
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
export * from './PeriodNavBar'
|
|
@@ -27,12 +27,20 @@ export function CarouselSlider() {
|
|
|
27
27
|
const translateX = useSharedValue(0)
|
|
28
28
|
const gestureStartX = useSharedValue(0)
|
|
29
29
|
const prevItemsRef = React.useRef(items)
|
|
30
|
+
const gestureAnimatingRef = React.useRef(false)
|
|
31
|
+
|
|
32
|
+
const setGestureAnimating = React.useCallback((v) => {
|
|
33
|
+
gestureAnimatingRef.current = v
|
|
34
|
+
}, [])
|
|
30
35
|
|
|
31
36
|
React.useEffect(() => {
|
|
32
37
|
if (slideWidth > 0) {
|
|
33
38
|
if (prevItemsRef.current !== items) {
|
|
34
39
|
prevItemsRef.current = items
|
|
35
40
|
translateX.value = -activeIndex * slideWidth
|
|
41
|
+
} else if (gestureAnimatingRef.current) {
|
|
42
|
+
// Gesture onEnd already animating — skip to avoid double animation
|
|
43
|
+
gestureAnimatingRef.current = false
|
|
36
44
|
} else {
|
|
37
45
|
translateX.value = withTiming(-activeIndex * slideWidth, { duration: 300 }, (finished) => {
|
|
38
46
|
if (finished && afterChange) runOnJS(afterChange)(items?.[activeIndex]?.key, activeIndex)
|
|
@@ -87,7 +95,10 @@ export function CarouselSlider() {
|
|
|
87
95
|
}
|
|
88
96
|
|
|
89
97
|
const clamped = clampIndex(targetIndex, itemsCount, loop)
|
|
90
|
-
translateX.value = withTiming(-clamped * slideWidth, { duration: 300 })
|
|
98
|
+
translateX.value = withTiming(-clamped * slideWidth, { duration: 300 }, (finished) => {
|
|
99
|
+
if (finished && afterChange) runOnJS(afterChange)(items?.[clamped]?.key, clamped)
|
|
100
|
+
})
|
|
101
|
+
runOnJS(setGestureAnimating)(true)
|
|
91
102
|
runOnJS(goTo)(targetIndex)
|
|
92
103
|
runOnJS(resumeAutoplay)()
|
|
93
104
|
})
|
|
@@ -33,7 +33,7 @@ function formatValue(value, type) {
|
|
|
33
33
|
case 'month':
|
|
34
34
|
return [date.startOf('month'), date.endOf('month')]
|
|
35
35
|
case 'week':
|
|
36
|
-
return [date.startOf('
|
|
36
|
+
return [date.startOf('week'), date.endOf('week')]
|
|
37
37
|
default:
|
|
38
38
|
return [date.startOf('day'), date.endOf('day')]
|
|
39
39
|
}
|
|
@@ -2,6 +2,7 @@ import { dissoc } from 'ramda'
|
|
|
2
2
|
import React from 'react'
|
|
3
3
|
|
|
4
4
|
import { Icon, IconLabel } from '../presentation'
|
|
5
|
+
import { KeyboardDismissButton } from '../keyboard'
|
|
5
6
|
import { Link } from '../actions'
|
|
6
7
|
import { LinkInput } from './LinkInput'
|
|
7
8
|
import { Picker, getOptionLabel, searchOptions } from './Picker'
|
|
@@ -134,6 +135,8 @@ export function Select({
|
|
|
134
135
|
maxHeight={popoverMaxHeight}
|
|
135
136
|
{...popoverProps}
|
|
136
137
|
renderContent={({ onClose }) => (
|
|
138
|
+
<>
|
|
139
|
+
{useBottomDrawer && useSearch && <KeyboardDismissButton />}
|
|
137
140
|
<Picker
|
|
138
141
|
row={false}
|
|
139
142
|
options={searchOptions(options, search, { labelKey })}
|
|
@@ -152,21 +155,21 @@ export function Select({
|
|
|
152
155
|
}}
|
|
153
156
|
{...pickerProps}
|
|
154
157
|
renderHeader={
|
|
155
|
-
useBottomDrawer && useSearch
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
158
|
+
useBottomDrawer && useSearch ? (
|
|
159
|
+
<>
|
|
160
|
+
<View padding="md" paddingB="xs">
|
|
161
|
+
<TextInput
|
|
162
|
+
prefixIcon="search-line"
|
|
163
|
+
prefixIconColor="text4"
|
|
164
|
+
value={search}
|
|
165
|
+
onChange={handleChangeSearch}
|
|
166
|
+
/>
|
|
167
|
+
</View>
|
|
168
|
+
{renderHeader?.()}
|
|
169
|
+
</>
|
|
170
|
+
) : (
|
|
171
|
+
renderHeader
|
|
172
|
+
)
|
|
170
173
|
}
|
|
171
174
|
renderOption={({ option, selected, onChange }) => (
|
|
172
175
|
<Link
|
|
@@ -187,6 +190,7 @@ export function Select({
|
|
|
187
190
|
</Link>
|
|
188
191
|
)}
|
|
189
192
|
/>
|
|
193
|
+
</>
|
|
190
194
|
)}
|
|
191
195
|
>
|
|
192
196
|
<Input
|
|
@@ -24,7 +24,9 @@ function fromMonthValue(v) {
|
|
|
24
24
|
.startOf('month')
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
function MonthDays({
|
|
27
|
+
const MonthDays = React.memo(function MonthDays({ monthValue, selectedKey, onSelect, min, max, onCheckDisabled }) {
|
|
28
|
+
const month = fromMonthValue(monthValue)
|
|
29
|
+
const selectedValue = selectedKey ? dayjs(selectedKey) : null
|
|
28
30
|
const { cells } = useCalendarDays(month)
|
|
29
31
|
|
|
30
32
|
return (
|
|
@@ -57,7 +59,7 @@ function MonthDays({ month, selectedValue, onSelect, min, max, onCheckDisabled }
|
|
|
57
59
|
</Grid>
|
|
58
60
|
</View>
|
|
59
61
|
)
|
|
60
|
-
}
|
|
62
|
+
})
|
|
61
63
|
|
|
62
64
|
export function DayPicker({ value, onChange, min, max, onCheckDisabled, allowClear, ...props }) {
|
|
63
65
|
if (!!value) value = dayjs(value)
|
|
@@ -70,19 +72,23 @@ export function DayPicker({ value, onChange, min, max, onCheckDisabled, allowCle
|
|
|
70
72
|
if (value?.isValid?.()) setCurrentMonth(value.startOf('month'))
|
|
71
73
|
}, [value?.day?.(), value?.month?.(), value?.year?.()])
|
|
72
74
|
|
|
73
|
-
const handleChange = (
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
const handleChange = React.useCallback(
|
|
76
|
+
(v) => {
|
|
77
|
+
setLocalValue(v)
|
|
78
|
+
onChange?.(v)
|
|
79
|
+
},
|
|
80
|
+
[onChange]
|
|
81
|
+
)
|
|
77
82
|
|
|
78
83
|
const monthValue = toMonthValue(currentMonth)
|
|
79
84
|
const minMonth = min ? toMonthValue(dayjs(min).startOf('month')) : undefined
|
|
80
85
|
const maxMonth = max ? toMonthValue(dayjs(max).startOf('month')) : undefined
|
|
86
|
+
const selectedKey = value?.valueOf?.()
|
|
81
87
|
|
|
82
88
|
const renderSlide = (v) => (
|
|
83
89
|
<MonthDays
|
|
84
|
-
|
|
85
|
-
|
|
90
|
+
monthValue={v}
|
|
91
|
+
selectedKey={selectedKey}
|
|
86
92
|
onSelect={handleChange}
|
|
87
93
|
min={min}
|
|
88
94
|
max={max}
|
|
@@ -14,14 +14,15 @@ import { isDateDisabled } from '../../calendar/_helpers/dateDisabled'
|
|
|
14
14
|
|
|
15
15
|
const months = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
|
|
16
16
|
|
|
17
|
-
function MonthGrid({ year,
|
|
17
|
+
const MonthGrid = React.memo(function MonthGrid({ year, selectedKey, onSelect, min, max, onCheckDisabled }) {
|
|
18
18
|
const yearDate = dayjs().year(year).startOf('year')
|
|
19
|
+
const selectedValue = selectedKey ? dayjs(selectedKey) : null
|
|
19
20
|
|
|
20
21
|
return (
|
|
21
22
|
<Grid colSpan={8} gap="xs">
|
|
22
23
|
{months.map((month) => {
|
|
23
24
|
const dateVal = yearDate.month(month)
|
|
24
|
-
const isActive = !!selectedValue && dateVal.isSame(selectedValue, '
|
|
25
|
+
const isActive = !!selectedValue && dateVal.isSame(selectedValue, 'month')
|
|
25
26
|
const disabled = isDateDisabled(dateVal, { min, max, onCheckDisabled })
|
|
26
27
|
|
|
27
28
|
return (
|
|
@@ -43,7 +44,7 @@ function MonthGrid({ year, selectedValue, onSelect, min, max, onCheckDisabled })
|
|
|
43
44
|
})}
|
|
44
45
|
</Grid>
|
|
45
46
|
)
|
|
46
|
-
}
|
|
47
|
+
})
|
|
47
48
|
|
|
48
49
|
export function MonthPicker({ value, onChange, min, max, onCheckDisabled, allowClear, ...props }) {
|
|
49
50
|
const [localValue, setLocalValue] = React.useState(value)
|
|
@@ -55,18 +56,22 @@ export function MonthPicker({ value, onChange, min, max, onCheckDisabled, allowC
|
|
|
55
56
|
if (value?.isValid?.()) setCurrentYear(value.startOf('year'))
|
|
56
57
|
}, [value?.month?.(), value?.year?.()])
|
|
57
58
|
|
|
58
|
-
const handleChange = (
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
59
|
+
const handleChange = React.useCallback(
|
|
60
|
+
(v) => {
|
|
61
|
+
const newValue = v.startOf('month')
|
|
62
|
+
setLocalValue(newValue)
|
|
63
|
+
onChange?.(newValue)
|
|
64
|
+
},
|
|
65
|
+
[onChange]
|
|
66
|
+
)
|
|
63
67
|
|
|
64
68
|
const yearValue = currentYear.year()
|
|
65
69
|
const minYear = min ? dayjs(min).year() : undefined
|
|
66
70
|
const maxYear = max ? dayjs(max).year() : undefined
|
|
71
|
+
const selectedKey = value?.valueOf?.()
|
|
67
72
|
|
|
68
73
|
const renderSlide = (v) => (
|
|
69
|
-
<MonthGrid year={v}
|
|
74
|
+
<MonthGrid year={v} selectedKey={selectedKey} onSelect={handleChange} min={min} max={max} onCheckDisabled={onCheckDisabled} />
|
|
70
75
|
)
|
|
71
76
|
|
|
72
77
|
return (
|