@daryasidorovich/modsen-datepicker 1.0.0
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/.babelrc.json +7 -0
- package/.github/workflows/chromatic.yml +25 -0
- package/.github/workflows/ci.yml +56 -0
- package/.husky/commit-msg +1 -0
- package/.husky/pre-commit +1 -0
- package/.prettierignore +16 -0
- package/.prettierrc +6 -0
- package/.storybook/main.js +93 -0
- package/.storybook/preview-head.html +6 -0
- package/.storybook/preview.js +26 -0
- package/.storybook/preview.tsx +18 -0
- package/README.md +302 -0
- package/commitlint.config.js +23 -0
- package/dist/components/BaseCalendar/index.d.ts +2 -0
- package/dist/components/CalendarGrid/CalendarGridWithTasks/Tooltip/index.d.ts +8 -0
- package/dist/components/CalendarGrid/CalendarGridWithTasks/index.d.ts +2 -0
- package/dist/components/CalendarGrid/CalendarGridWithoutTasks/CalendarGridWithoutTasks.test.d.ts +1 -0
- package/dist/components/CalendarGrid/CalendarGridWithoutTasks/index.d.ts +4 -0
- package/dist/components/CalendarGrid/index.d.ts +2 -0
- package/dist/components/CalendarGrid/types.d.ts +21 -0
- package/dist/components/Clear/index.d.ts +5 -0
- package/dist/components/DatePicker/index.d.ts +5 -0
- package/dist/components/Day/index.d.ts +16 -0
- package/dist/components/Input/index.d.ts +10 -0
- package/dist/components/Modal/CrudModal/index.d.ts +2 -0
- package/dist/components/Modal/index.d.ts +12 -0
- package/dist/components/Modal/types.d.ts +12 -0
- package/dist/components/Month/index.d.ts +7 -0
- package/dist/components/RangePicker/index.d.ts +6 -0
- package/dist/components/TasksManager/AddModal/index.d.ts +6 -0
- package/dist/components/TasksManager/DeleteModal/index.d.ts +6 -0
- package/dist/components/TasksManager/EditModal/index.d.ts +7 -0
- package/dist/components/TasksManager/index.d.ts +9 -0
- package/dist/components/Week/index.d.ts +17 -0
- package/dist/components/WeekDay/index.d.ts +7 -0
- package/dist/constants/dateMask.d.ts +21 -0
- package/dist/constants/firstDayOfWeek.d.ts +5 -0
- package/dist/constants/holidays.d.ts +1 -0
- package/dist/constants/modes.d.ts +5 -0
- package/dist/constants/monthsNames.d.ts +1 -0
- package/dist/constants/weekdaysNames.d.ts +1 -0
- package/dist/hooks/useCalendar.d.ts +7 -0
- package/dist/hooks/useLockBodyScroll.d.ts +2 -0
- package/dist/hooks/useModal.d.ts +13 -0
- package/dist/hooks/useTooltip.d.ts +9 -0
- package/dist/hooks/useValidate.d.ts +11 -0
- package/dist/index.cjs +17250 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +17233 -0
- package/dist/index.js.map +1 -0
- package/dist/services/calendarService.d.ts +19 -0
- package/dist/services/decorators/withHolidays.d.ts +2 -0
- package/dist/services/decorators/withHolidays.test.d.ts +1 -0
- package/dist/services/decorators/withMinMax.d.ts +2 -0
- package/dist/services/decorators/withMinMax.test.d.ts +1 -0
- package/dist/services/holidayService.d.ts +5 -0
- package/dist/setupTests.d.ts +1 -0
- package/dist/store/localStorage.d.ts +3 -0
- package/dist/store/tasksStore.d.ts +8 -0
- package/dist/store/tasksStore.test.d.ts +1 -0
- package/dist/store/types.d.ts +18 -0
- package/dist/utils/calendar.d.ts +7 -0
- package/dist/utils/calendar.test.d.ts +1 -0
- package/dist/utils/controlDate.d.ts +1 -0
- package/dist/utils/dateChecks.d.ts +10 -0
- package/dist/utils/dateChecks.test.d.ts +1 -0
- package/dist/utils/formatDate.d.ts +3 -0
- package/dist/utils/formatDate.test.d.ts +1 -0
- package/dist/utils/schema.d.ts +6 -0
- package/dist/utils/schema.test.d.ts +1 -0
- package/dist/utils/weekdayOrder.d.ts +1 -0
- package/dist/utils/weekdayOrder.test.d.ts +1 -0
- package/docs/base-calendar.png +0 -0
- package/docs/dark-theme.png +0 -0
- package/docs/datepicker.png +0 -0
- package/docs/rangepicker-with-error.png +0 -0
- package/docs/rangepicker.png +0 -0
- package/eslint.config.ts +80 -0
- package/jest.config.json +21 -0
- package/package.json +106 -0
- package/rollup.config.js +65 -0
- package/src/assets/actions/Delete.svg +4 -0
- package/src/assets/actions/Edit.svg +3 -0
- package/src/assets/arrows/Next.svg +4 -0
- package/src/assets/arrows/Prev.svg +4 -0
- package/src/assets/input/Calendar.svg +3 -0
- package/src/assets/input/Clear.svg +3 -0
- package/src/components/BaseCalendar/BaseCalendar.stories.tsx +77 -0
- package/src/components/BaseCalendar/index.tsx +63 -0
- package/src/components/BaseCalendar/styles.module.scss +15 -0
- package/src/components/CalendarGrid/CalendarGrid.stories.tsx +136 -0
- package/src/components/CalendarGrid/CalendarGridWithTasks/Tooltip/index.tsx +27 -0
- package/src/components/CalendarGrid/CalendarGridWithTasks/Tooltip/styles.module.scss +9 -0
- package/src/components/CalendarGrid/CalendarGridWithTasks/index.tsx +51 -0
- package/src/components/CalendarGrid/CalendarGridWithoutTasks/CalendarGridWithoutTasks.test.tsx +223 -0
- package/src/components/CalendarGrid/CalendarGridWithoutTasks/index.tsx +36 -0
- package/src/components/CalendarGrid/CalendarGridWithoutTasks/styles.module.scss +11 -0
- package/src/components/CalendarGrid/index.tsx +19 -0
- package/src/components/CalendarGrid/types.ts +26 -0
- package/src/components/Clear/Clear.stories.tsx +16 -0
- package/src/components/Clear/index.tsx +12 -0
- package/src/components/Clear/styles.module.scss +34 -0
- package/src/components/DatePicker/DatePicker.stories.tsx +127 -0
- package/src/components/DatePicker/index.tsx +72 -0
- package/src/components/DatePicker/styles.module.scss +10 -0
- package/src/components/Day/Day.stories.tsx +75 -0
- package/src/components/Day/index.tsx +95 -0
- package/src/components/Day/styles.module.scss +97 -0
- package/src/components/Input/Input.stories.tsx +37 -0
- package/src/components/Input/index.tsx +64 -0
- package/src/components/Input/styles.module.scss +79 -0
- package/src/components/Modal/CrudModal/index.tsx +43 -0
- package/src/components/Modal/CrudModal/styles.module.scss +44 -0
- package/src/components/Modal/index.tsx +66 -0
- package/src/components/Modal/styles.module.scss +40 -0
- package/src/components/Modal/types.ts +13 -0
- package/src/components/Month/Month.stories.tsx +19 -0
- package/src/components/Month/index.tsx +31 -0
- package/src/components/Month/styles.module.scss +30 -0
- package/src/components/RangePicker/RangePicker.stories.tsx +134 -0
- package/src/components/RangePicker/index.tsx +144 -0
- package/src/components/RangePicker/styles.module.scss +19 -0
- package/src/components/TasksManager/AddModal/index.tsx +62 -0
- package/src/components/TasksManager/DeleteModal/index.tsx +22 -0
- package/src/components/TasksManager/EditModal/index.tsx +96 -0
- package/src/components/TasksManager/index.tsx +112 -0
- package/src/components/TasksManager/styles.module.scss +62 -0
- package/src/components/Week/Week.stories.tsx +49 -0
- package/src/components/Week/index.tsx +68 -0
- package/src/components/Week/styles.module.scss +7 -0
- package/src/components/WeekDay/WeekDay.stories.tsx +38 -0
- package/src/components/WeekDay/index.tsx +35 -0
- package/src/components/WeekDay/styles.module.scss +19 -0
- package/src/constants/dateMask.ts +23 -0
- package/src/constants/firstDayOfWeek.ts +7 -0
- package/src/constants/holidays.ts +32 -0
- package/src/constants/modes.ts +6 -0
- package/src/constants/monthsNames.ts +14 -0
- package/src/constants/weekdaysNames.ts +1 -0
- package/src/hooks/useCalendar.ts +62 -0
- package/src/hooks/useLockBodyScroll.ts +19 -0
- package/src/hooks/useModal.ts +45 -0
- package/src/hooks/useTooltip.ts +41 -0
- package/src/hooks/useValidate.ts +80 -0
- package/src/index.ts +15 -0
- package/src/services/calendarService.ts +62 -0
- package/src/services/decorators/withHolidays.test.ts +64 -0
- package/src/services/decorators/withHolidays.ts +12 -0
- package/src/services/decorators/withMinMax.test.ts +77 -0
- package/src/services/decorators/withMinMax.ts +19 -0
- package/src/services/holidayService.ts +56 -0
- package/src/setupTests.ts +1 -0
- package/src/store/localStorage.ts +33 -0
- package/src/store/tasksStore.test.tsx +208 -0
- package/src/store/tasksStore.tsx +146 -0
- package/src/store/types.ts +22 -0
- package/src/styles/_border.scss +9 -0
- package/src/styles/_colors.scss +53 -0
- package/src/styles/_gap.scss +4 -0
- package/src/styles/_globals.scss +61 -0
- package/src/styles/_grid.scss +9 -0
- package/src/styles/_mixins.scss +6 -0
- package/src/styles/_reset.scss +98 -0
- package/src/styles/_theme-mixins.scss +51 -0
- package/src/styles/_typography.scss +10 -0
- package/src/styles/_variables.scss +8 -0
- package/src/styles/main.scss +3 -0
- package/src/types/types.d.ts +15 -0
- package/src/utils/calendar.test.ts +154 -0
- package/src/utils/calendar.ts +82 -0
- package/src/utils/controlDate.ts +3 -0
- package/src/utils/dateChecks.test.ts +216 -0
- package/src/utils/dateChecks.ts +75 -0
- package/src/utils/formatDate.test.ts +57 -0
- package/src/utils/formatDate.ts +27 -0
- package/src/utils/schema.test.ts +40 -0
- package/src/utils/schema.ts +8 -0
- package/src/utils/weekdayOrder.test.ts +11 -0
- package/src/utils/weekdayOrder.ts +7 -0
- package/tsconfig.json +31 -0
- package/vitest.config.ts +38 -0
- package/vitest.shims.d.ts +1 -0
package/.babelrc.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
name: 'Chromatic'
|
|
2
|
+
|
|
3
|
+
on: push
|
|
4
|
+
|
|
5
|
+
jobs:
|
|
6
|
+
chromatic:
|
|
7
|
+
name: Run Chromatic
|
|
8
|
+
runs-on: ubuntu-latest
|
|
9
|
+
steps:
|
|
10
|
+
- name: Checkout code
|
|
11
|
+
uses: actions/checkout@v7
|
|
12
|
+
with:
|
|
13
|
+
fetch-depth: 0
|
|
14
|
+
- uses: actions/setup-node@v7
|
|
15
|
+
with:
|
|
16
|
+
node-version: 24.19.0
|
|
17
|
+
- name: Install dependencies
|
|
18
|
+
run: npm ci
|
|
19
|
+
- name: Run Chromatic
|
|
20
|
+
uses: chromaui/action@latest
|
|
21
|
+
with:
|
|
22
|
+
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
|
|
23
|
+
env:
|
|
24
|
+
STORYBOOK_HOLIDAY_API_KEY: ${{ secrets.STORYBOOK_HOLIDAY_API_KEY }}
|
|
25
|
+
STORYBOOK_HOLIDAY_API_URL: ${{ secrets.STORYBOOK_HOLIDAY_API_URL }}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
name: CI for datepicker
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main, dev]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main, dev]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
lint:
|
|
11
|
+
name: Lint
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v7
|
|
15
|
+
- uses: actions/setup-node@v7
|
|
16
|
+
with:
|
|
17
|
+
node-version: 24.19.0
|
|
18
|
+
cache: 'npm'
|
|
19
|
+
- run: npm ci
|
|
20
|
+
- run: npm run lint
|
|
21
|
+
|
|
22
|
+
format:
|
|
23
|
+
name: Format
|
|
24
|
+
runs-on: ubuntu-latest
|
|
25
|
+
steps:
|
|
26
|
+
- uses: actions/checkout@v7
|
|
27
|
+
- uses: actions/setup-node@v7
|
|
28
|
+
with:
|
|
29
|
+
node-version: 24.19.0
|
|
30
|
+
cache: 'npm'
|
|
31
|
+
- run: npm ci
|
|
32
|
+
- run: npm run format:check
|
|
33
|
+
|
|
34
|
+
test:
|
|
35
|
+
name: Test
|
|
36
|
+
runs-on: ubuntu-latest
|
|
37
|
+
steps:
|
|
38
|
+
- uses: actions/checkout@v7
|
|
39
|
+
- uses: actions/setup-node@v7
|
|
40
|
+
with:
|
|
41
|
+
node-version: 24.19.0
|
|
42
|
+
cache: 'npm'
|
|
43
|
+
- run: npm ci
|
|
44
|
+
- run: npm test
|
|
45
|
+
|
|
46
|
+
build:
|
|
47
|
+
name: Build
|
|
48
|
+
runs-on: ubuntu-latest
|
|
49
|
+
steps:
|
|
50
|
+
- uses: actions/checkout@v7
|
|
51
|
+
- uses: actions/setup-node@v7
|
|
52
|
+
with:
|
|
53
|
+
node-version: 24.19.0
|
|
54
|
+
cache: 'npm'
|
|
55
|
+
- run: npm ci
|
|
56
|
+
- run: npm run build
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
npx commitlint --edit "$1"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
npx lint-staged
|
package/.prettierignore
ADDED
package/.prettierrc
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/** @type { import('@storybook/react-vite').StorybookConfig } */
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import svgr from 'vite-plugin-svgr';
|
|
5
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
6
|
+
const __dirname = path.dirname(__filename);
|
|
7
|
+
|
|
8
|
+
const config = {
|
|
9
|
+
stories: ['../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
|
|
10
|
+
addons: [
|
|
11
|
+
'@storybook/addon-themes',
|
|
12
|
+
'@storybook/addon-vitest',
|
|
13
|
+
'@storybook/addon-a11y',
|
|
14
|
+
'@storybook/addon-docs',
|
|
15
|
+
],
|
|
16
|
+
framework: {
|
|
17
|
+
name: '@storybook/react-vite',
|
|
18
|
+
options: {},
|
|
19
|
+
},
|
|
20
|
+
docs: {
|
|
21
|
+
autodocs: true,
|
|
22
|
+
},
|
|
23
|
+
typescript: {
|
|
24
|
+
check: false,
|
|
25
|
+
reactDocgen: 'react-docgen-typescript',
|
|
26
|
+
},
|
|
27
|
+
async viteFinal(config) {
|
|
28
|
+
config.optimizeDeps = {
|
|
29
|
+
include: ['react', 'react-dom'],
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
config.plugins = config.plugins || [];
|
|
33
|
+
config.plugins.push(
|
|
34
|
+
svgr({
|
|
35
|
+
include: '**/*.svg?react',
|
|
36
|
+
})
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
config.css = {
|
|
40
|
+
modules: {
|
|
41
|
+
localsConvention: 'camelCase',
|
|
42
|
+
},
|
|
43
|
+
preprocessorOptions: {
|
|
44
|
+
scss: {
|
|
45
|
+
additionalData: `
|
|
46
|
+
@use "@styles/variables" as *;
|
|
47
|
+
@use "@styles/border" as *;
|
|
48
|
+
@use "@styles/mixins" as *;
|
|
49
|
+
@use "@styles/theme-mixins" as *;
|
|
50
|
+
@use "@styles/colors" as *;
|
|
51
|
+
@use "@styles/typography" as *;
|
|
52
|
+
@use "@styles/gap" as *;
|
|
53
|
+
`,
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
config.define = {
|
|
59
|
+
...config.define,
|
|
60
|
+
'process.env.STORYBOOK_HOLIDAY_API_KEY': JSON.stringify(
|
|
61
|
+
process.env.STORYBOOK_HOLIDAY_API_KEY
|
|
62
|
+
),
|
|
63
|
+
'process.env.STORYBOOK_HOLIDAY_API_URL': JSON.stringify(
|
|
64
|
+
process.env.STORYBOOK_HOLIDAY_API_URL
|
|
65
|
+
),
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
config.resolve = {
|
|
69
|
+
alias: {
|
|
70
|
+
'@': path.resolve(__dirname, '../src'),
|
|
71
|
+
'@components': path.resolve(__dirname, '../src/components'),
|
|
72
|
+
'@styles': path.resolve(__dirname, '../src/styles'),
|
|
73
|
+
'@assets': path.resolve(__dirname, '../src/assets'),
|
|
74
|
+
'@utils': path.resolve(__dirname, '../src/utils'),
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
config.server = {
|
|
79
|
+
...config.server,
|
|
80
|
+
proxy: {
|
|
81
|
+
'/holidays': {
|
|
82
|
+
target: 'https://holidayapi.com/v1',
|
|
83
|
+
changeOrigin: true,
|
|
84
|
+
secure: true,
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
return config;
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export default config;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** @type { import('@storybook/react-vite').Preview } */
|
|
2
|
+
import '../src/styles/main.scss';
|
|
3
|
+
|
|
4
|
+
import { withThemeByClassName } from '@storybook/addon-themes';
|
|
5
|
+
|
|
6
|
+
const preview = {
|
|
7
|
+
parameters: {
|
|
8
|
+
controls: {
|
|
9
|
+
matchers: {
|
|
10
|
+
color: /(background|color)$/i,
|
|
11
|
+
date: /Date$/i,
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
decorators: [
|
|
16
|
+
withThemeByClassName({
|
|
17
|
+
themes: {
|
|
18
|
+
light: 'theme-light',
|
|
19
|
+
dark: 'theme-dark',
|
|
20
|
+
},
|
|
21
|
+
defaultTheme: 'light',
|
|
22
|
+
}),
|
|
23
|
+
],
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export default preview;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Preview } from '@storybook/react-vite';
|
|
2
|
+
|
|
3
|
+
const preview: Preview = {
|
|
4
|
+
parameters: {
|
|
5
|
+
controls: {
|
|
6
|
+
matchers: {
|
|
7
|
+
color: /(background|color)$/i,
|
|
8
|
+
date: /Date$/i,
|
|
9
|
+
},
|
|
10
|
+
},
|
|
11
|
+
|
|
12
|
+
a11y: {
|
|
13
|
+
test: 'todo',
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export default preview;
|
package/README.md
ADDED
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
# Modsen DatePicker Library
|
|
4
|
+
|
|
5
|
+
**Three calendar components for React: BaseCalendar, DatePicker and RangePicker**
|
|
6
|
+
|
|
7
|
+
[Installation](#installation) • [Usage](#usage) • [API](#api) • [Types](#types) • [Demo](https://6a88497b3bbc2742a15109b2-cxguycdfyi.chromatic.com/)
|
|
8
|
+
|
|
9
|
+
</div>
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- **BaseCalendar** — a simple calendar for viewing and selecting dates
|
|
16
|
+
- **DatePicker** — single date selection via `selectedDate`
|
|
17
|
+
- **RangePicker** — range selection via `rangeStart` / `rangeEnd`
|
|
18
|
+
- **Flexible configuration** — `minDate`, `maxDate`, first day of week, display modes
|
|
19
|
+
- **Hide weekends** — `hideWeekends`
|
|
20
|
+
- **Holidays** — `showHolidays`, highlights public holidays based on the region (browser language)
|
|
21
|
+
- **Tasks** — `enableTasks`, shows task indicators on dates and enables the built-in task manager- **Light and dark themes** — via CSS class on `<html>`
|
|
22
|
+
- **TypeScript** — fully typed props out of the box
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm install modsen-datepicker
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Or via yarn:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
yarn add modsen-datepicker
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Requires **React 19+**.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## API
|
|
43
|
+
|
|
44
|
+
### Shared props (all components)
|
|
45
|
+
|
|
46
|
+
| Prop | Type | Default | Description |
|
|
47
|
+
| ---------------- | ------------------------- | ------------ | -------------------------------------------------- |
|
|
48
|
+
| `monthDate` | `Date` | `new Date()` | **Required.** The month being displayed |
|
|
49
|
+
| `minDate` | `Date` | — | Minimum selectable date |
|
|
50
|
+
| `maxDate` | `Date` | — | Maximum selectable date |
|
|
51
|
+
| `firstDayOfWeek` | `FIRST_DAY_OF_WEEK_TYPES` | `0` | First day of the week (`0` — Sunday, `1` — Monday) |
|
|
52
|
+
| `mode` | `MODES_TYPES` | `'month'` | Display mode: `'week'` or `'month'` |
|
|
53
|
+
| `hideWeekends` | `boolean` | `false` | Hide Saturday and Sunday |
|
|
54
|
+
| `showHolidays` | `boolean` | `false` | Highlight holidays |
|
|
55
|
+
| `enableTasks` | `boolean` | `false` | Enable task indicators and tasks manager |
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Usage
|
|
60
|
+
|
|
61
|
+
### DatePicker
|
|
62
|
+
|
|
63
|
+
Single date selection. Extends the shared props with:
|
|
64
|
+
|
|
65
|
+
| Prop | Type | Description |
|
|
66
|
+
| -------------- | ----------------------------------- | ----------------------------------------- |
|
|
67
|
+
| `selectedDate` | `Date` | The selected date |
|
|
68
|
+
| `onChange` | `(date: Date \| undefined) => void` | Called when a date is selected or cleared |
|
|
69
|
+
|
|
70
|
+
```tsx
|
|
71
|
+
import { useState } from 'react';
|
|
72
|
+
import { DatePicker } from 'modsen-datepicker';
|
|
73
|
+
|
|
74
|
+
const Example = () => {
|
|
75
|
+
const [selectedDate, setSelectedDate] = useState<Date | undefined>();
|
|
76
|
+
|
|
77
|
+
return (
|
|
78
|
+
<DatePicker
|
|
79
|
+
monthDate={new Date()}
|
|
80
|
+
selectedDate={selectedDate}
|
|
81
|
+
onChange={(date) => setSelectedDate(date)}
|
|
82
|
+
/>
|
|
83
|
+
);
|
|
84
|
+
};
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
<div align="center">
|
|
88
|
+
|
|
89
|
+

|
|
90
|
+
</div>
|
|
91
|
+
|
|
92
|
+
### RangePicker
|
|
93
|
+
|
|
94
|
+
Range selection. Extends the shared props with:
|
|
95
|
+
|
|
96
|
+
| Prop | Type | Description |
|
|
97
|
+
| --------------- | ----------------------- | -------------------------------------------------- |
|
|
98
|
+
| `rangeStart` | `Date` | Start of the range |
|
|
99
|
+
| `rangeEnd` | `Date` | End of the range |
|
|
100
|
+
| `onChangeStart` | `(date?: Date) => void` | Called when the start of the range changes |
|
|
101
|
+
| `onChangeEnd` | `(date?: Date) => void` | Called when the end of the range changes or clears |
|
|
102
|
+
|
|
103
|
+
```tsx
|
|
104
|
+
import { useState } from 'react';
|
|
105
|
+
import { RangePicker } from 'modsen-datepicker';
|
|
106
|
+
|
|
107
|
+
const Example = () => {
|
|
108
|
+
const [rangeStart, setRangeStart] = useState<Date | undefined>();
|
|
109
|
+
const [rangeEnd, setRangeEnd] = useState<Date | undefined>();
|
|
110
|
+
|
|
111
|
+
return (
|
|
112
|
+
<RangePicker
|
|
113
|
+
monthDate={new Date()}
|
|
114
|
+
rangeStart={rangeStart}
|
|
115
|
+
rangeEnd={rangeEnd}
|
|
116
|
+
onChangeStart={setRangeStart}
|
|
117
|
+
onChangeEnd={setRangeEnd}
|
|
118
|
+
/>
|
|
119
|
+
);
|
|
120
|
+
};
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
<div align="center">
|
|
124
|
+
|
|
125
|
+

|
|
126
|
+
</div>
|
|
127
|
+
|
|
128
|
+
### BaseCalendar
|
|
129
|
+
|
|
130
|
+
A simple calendar for viewing and selecting dates. It has no built-in selection logic — you control everything through `onDateClick`. Accepts `selectedDate`, `rangeStart` and `rangeEnd` purely for display.
|
|
131
|
+
|
|
132
|
+
| Prop | Type | Description |
|
|
133
|
+
| -------------- | -------------------------------------- | ----------------------------------------------------------------- |
|
|
134
|
+
| `selectedDate` | `Date` | The date to highlight as selected |
|
|
135
|
+
| `rangeStart` | `Date` | Start of the range to highlight |
|
|
136
|
+
| `rangeEnd` | `Date` | End of the range to highlight |
|
|
137
|
+
| `onDateClick` | `(e: MouseEvent) => void, date: Date)` | Called on every date click — define your own selection logic here |
|
|
138
|
+
|
|
139
|
+
```tsx
|
|
140
|
+
import { BaseCalendar, FIRST_DAY_OF_WEEK } from 'modsen-datepicker';
|
|
141
|
+
|
|
142
|
+
const Example = () => {
|
|
143
|
+
return (
|
|
144
|
+
<BaseCalendar
|
|
145
|
+
monthDate={new Date()}
|
|
146
|
+
selectedDate={new Date()}
|
|
147
|
+
firstDayOfWeek={FIRST_DAY_OF_WEEK.MONDAY}
|
|
148
|
+
onDateClick={(date, e) => {
|
|
149
|
+
if (e.ctrlKey) {
|
|
150
|
+
console.log('Ctrl + click', date);
|
|
151
|
+
} else {
|
|
152
|
+
console.log('Click', date);
|
|
153
|
+
}
|
|
154
|
+
}}
|
|
155
|
+
/>
|
|
156
|
+
);
|
|
157
|
+
};
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
<div align="center">
|
|
161
|
+
|
|
162
|
+

|
|
163
|
+
</div>
|
|
164
|
+
|
|
165
|
+
## Callbacks
|
|
166
|
+
|
|
167
|
+
All callbacks receive the **final, validated** value — never an intermediate state.
|
|
168
|
+
|
|
169
|
+
| Component | Callback | Signature | When it fires |
|
|
170
|
+
| ------------- | --------------- | ----------------------- | ----------------------------------------------- |
|
|
171
|
+
| `DatePicker` | `onChange` | `(date: Date | undefined) => void` | On date select or clear |
|
|
172
|
+
| `RangePicker` | `onChangeStart` | `(date?: Date) => void` | When the start of the range changes |
|
|
173
|
+
| `RangePicker` | `onChangeEnd` | `(date?: Date) => void` | When the end of the range changes or is cleared |
|
|
174
|
+
|
|
175
|
+
## Input validation
|
|
176
|
+
|
|
177
|
+
The input is `masked` (dd/mm/yyyy) and validated:
|
|
178
|
+
|
|
179
|
+
- **Mask** — accepts only digits and inserts separators automatically.
|
|
180
|
+
|
|
181
|
+
- **Invalid date**- — if the value cannot be parsed, the input shows Invalid date and the selection is cleared.
|
|
182
|
+
|
|
183
|
+
- **Out of range** — if minDate or maxDate is set and the value falls outside, the input shows the corresponding error and the value is rejected.
|
|
184
|
+
|
|
185
|
+
<div align="center">
|
|
186
|
+

|
|
187
|
+
|
|
188
|
+
</div>
|
|
189
|
+
|
|
190
|
+
## Interaction
|
|
191
|
+
|
|
192
|
+
### Single date (DatePicker)
|
|
193
|
+
|
|
194
|
+
A regular click selects a date and calls `onChange` with the new value.
|
|
195
|
+
|
|
196
|
+
```tsx
|
|
197
|
+
<DatePicker
|
|
198
|
+
monthDate={new Date()}
|
|
199
|
+
selectedDate={selectedDate}
|
|
200
|
+
onChange={(date) => setSelectedDate(date)}
|
|
201
|
+
/>
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Clicking the same date again clears the selection and calls `onChange(undefined)`.
|
|
205
|
+
|
|
206
|
+
### Range (RangePicker)
|
|
207
|
+
|
|
208
|
+
Clicks build the range step by step:
|
|
209
|
+
|
|
210
|
+
1. First click sets `rangeStart` — `onChangeStart(date)` is called.
|
|
211
|
+
2. Second click sets `rangeEnd` — `onChangeEnd(date)` is called.
|
|
212
|
+
3. If the second click is earlier than `rangeStart`, the values are swapped and both callbacks receive the corrected pair.
|
|
213
|
+
4. If the range is already complete, the next click starts a new range — `onChangeStart(date)` and `onChangeEnd(undefined)`.
|
|
214
|
+
|
|
215
|
+
```tsx
|
|
216
|
+
<RangePicker
|
|
217
|
+
monthDate={new Date()}
|
|
218
|
+
rangeStart={rangeStart}
|
|
219
|
+
rangeEnd={rangeEnd}
|
|
220
|
+
onChangeStart={setRangeStart}
|
|
221
|
+
onChangeEnd={setRangeEnd}
|
|
222
|
+
/>
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Ctrl + click
|
|
226
|
+
|
|
227
|
+
If the range is already selected and the user holds **Ctrl** while clicking, the end of the range is reset to the clicked date. The start stays the same. Only `onChangeEnd(date)` is called.
|
|
228
|
+
|
|
229
|
+
## Tasks
|
|
230
|
+
|
|
231
|
+
Tasks are disabled by default. Enable them with the `enableTasks` prop:
|
|
232
|
+
|
|
233
|
+
```tsx
|
|
234
|
+
<DatePicker enableTasks />
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
When `enableTasks` is on, a **double click** on any date opens a dialog where you can add, edit and delete tasks for that day.
|
|
238
|
+
|
|
239
|
+
Tasks are stored in `localStorage`, so they persist between sessions without any backend.
|
|
240
|
+
|
|
241
|
+
## Types
|
|
242
|
+
|
|
243
|
+
All types are exported from the package:
|
|
244
|
+
|
|
245
|
+
```ts
|
|
246
|
+
import type { FIRST_DAY_OF_WEEK_TYPES, MODES_TYPES } from 'modsen-datepicker';
|
|
247
|
+
|
|
248
|
+
import { FIRST_DAY_OF_WEEK, MODES } from 'modsen-datepicker';
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### `FIRST_DAY_OF_WEEK`
|
|
252
|
+
|
|
253
|
+
Defines which day the week starts on.
|
|
254
|
+
|
|
255
|
+
| Constant | Value | Day |
|
|
256
|
+
| -------------------------- | ----- | ------ |
|
|
257
|
+
| `FIRST_DAY_OF_WEEK.SUNDAY` | `0` | Sunday |
|
|
258
|
+
| `FIRST_DAY_OF_WEEK.MONDAY` | `1` | Monday |
|
|
259
|
+
|
|
260
|
+
```ts
|
|
261
|
+
export type FIRST_DAY_OF_WEEK_TYPES = 0 | 1;
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
**Example:**
|
|
265
|
+
|
|
266
|
+
```tsx
|
|
267
|
+
<BaseCalendar
|
|
268
|
+
monthDate={new Date()}
|
|
269
|
+
firstDayOfWeek={FIRST_DAY_OF_WEEK.MONDAY}
|
|
270
|
+
/>
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### `MODES`
|
|
274
|
+
|
|
275
|
+
Defines the calendar display mode.
|
|
276
|
+
|
|
277
|
+
| Constant | Value | Description |
|
|
278
|
+
| ------------- | --------- | ----------- |
|
|
279
|
+
| `MODES.WEEK` | `'week'` | Week view |
|
|
280
|
+
| `MODES.MONTH` | `'month'` | Month view |
|
|
281
|
+
|
|
282
|
+
```ts
|
|
283
|
+
export type MODES_TYPES = 'week' | 'month';
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
**Example:**
|
|
287
|
+
|
|
288
|
+
```tsx
|
|
289
|
+
<BaseCalendar monthDate={new Date()} mode={MODES.WEEK} />
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
## Theming
|
|
293
|
+
|
|
294
|
+
The library ships with light and dark themes out of the box — no extra configuration is required. The theme is applied automatically via a class on the `<html>` element:
|
|
295
|
+
|
|
296
|
+
- `theme-light` — light theme
|
|
297
|
+
- `theme-dark` — dark theme
|
|
298
|
+
|
|
299
|
+
<div align="center">
|
|
300
|
+
|
|
301
|
+

|
|
302
|
+
</div>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
extends: ['@commitlint/config-conventional'],
|
|
3
|
+
rules: {
|
|
4
|
+
'type-enum': [
|
|
5
|
+
2,
|
|
6
|
+
'always',
|
|
7
|
+
[
|
|
8
|
+
'feat',
|
|
9
|
+
'fix',
|
|
10
|
+
'docs',
|
|
11
|
+
'style',
|
|
12
|
+
'refactor',
|
|
13
|
+
'test',
|
|
14
|
+
'chore',
|
|
15
|
+
'build',
|
|
16
|
+
'ci',
|
|
17
|
+
],
|
|
18
|
+
],
|
|
19
|
+
'subject-max-length': [2, 'always', 100],
|
|
20
|
+
'subject-empty': [2, 'never'],
|
|
21
|
+
'type-empty': [2, 'never'],
|
|
22
|
+
},
|
|
23
|
+
};
|
package/dist/components/CalendarGrid/CalendarGridWithoutTasks/CalendarGridWithoutTasks.test.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { FIRST_DAY_OF_WEEK_TYPES } from '@/constants/firstDayOfWeek';
|
|
2
|
+
import { MODES_TYPES } from '@/constants/modes';
|
|
3
|
+
export interface CalendarProps {
|
|
4
|
+
minDate?: Date;
|
|
5
|
+
maxDate?: Date;
|
|
6
|
+
monthDate: Date;
|
|
7
|
+
firstDayOfWeek?: FIRST_DAY_OF_WEEK_TYPES;
|
|
8
|
+
selectedDate?: Date;
|
|
9
|
+
mode?: MODES_TYPES;
|
|
10
|
+
rangeStart?: Date;
|
|
11
|
+
rangeEnd?: Date;
|
|
12
|
+
hideWeekends?: boolean;
|
|
13
|
+
showHolidays?: boolean;
|
|
14
|
+
enableTasks?: boolean;
|
|
15
|
+
hasTasks?: (date: Date) => boolean;
|
|
16
|
+
onDateClick?: (e: React.MouseEvent<HTMLButtonElement>, date: Date) => void;
|
|
17
|
+
onDateDoubleClick?: (date: Date) => void;
|
|
18
|
+
onMouseEnter?: (e: React.MouseEvent<HTMLButtonElement>) => void;
|
|
19
|
+
onMouseLeave?: () => void;
|
|
20
|
+
}
|
|
21
|
+
export type BaseCalendarProps = Omit<CalendarProps, 'hasTasks' | 'onDoubleDateClick' | 'onMouseEnter' | 'onMouseLeave'>;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { BaseCalendarProps, CalendarProps } from '../CalendarGrid/types';
|
|
2
|
+
export interface DatePickerProps extends BaseCalendarProps, Pick<CalendarProps, 'selectedDate'> {
|
|
3
|
+
onChange?: (date: Date | undefined) => void;
|
|
4
|
+
}
|
|
5
|
+
export declare const DatePicker: ({ selectedDate, monthDate, onChange, ...props }: DatePickerProps) => import("react").JSX.Element;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface DayProps {
|
|
2
|
+
date: Date;
|
|
3
|
+
isSelected?: boolean;
|
|
4
|
+
isDisabled?: boolean;
|
|
5
|
+
isHoliday?: boolean;
|
|
6
|
+
hasTasks?: boolean;
|
|
7
|
+
isRangeStart?: boolean;
|
|
8
|
+
isRangeEnd?: boolean;
|
|
9
|
+
isRangeMiddle?: boolean;
|
|
10
|
+
isCurrentMonth: boolean;
|
|
11
|
+
onClick?: (e: React.MouseEvent<HTMLButtonElement>, date: Date) => void;
|
|
12
|
+
onDoubleClick?: (date: Date) => void;
|
|
13
|
+
onMouseEnter?: (e: React.MouseEvent<HTMLButtonElement>) => void;
|
|
14
|
+
onMouseLeave?: () => void;
|
|
15
|
+
}
|
|
16
|
+
export declare const Day: ({ date, isSelected, isCurrentMonth, isDisabled, isHoliday, hasTasks, isRangeStart, isRangeEnd, isRangeMiddle, onClick, onDoubleClick, onMouseEnter, onMouseLeave, }: DayProps) => import("react").JSX.Element;
|